+ ConsumeComma ();
+
+ /* Argument #3. Since memset is a fastcall function, we must load the
+ ** arg into the primary if it is not already there. This parameter is
+ ** also ignored for the calculation of the parameter size, since it is
+ ** not passed via the stack.
+ */
+ ParseArg (&Arg3, Arg3Type);
+ if (Arg3.Flags & CF_CONST) {
+ LoadExpr (CF_NONE, &Arg3.Expr);
+ }
+
+ /* Emit the actual function call. This will also cleanup the stack. */
+ g_call (CF_FIXARGC, MemSet? Func_memset : Func__bzero, ParamSize);
+
+ if (ED_IsConstAbsInt (&Arg3.Expr) && Arg3.Expr.IVal == 0) {
+
+ /* memset has been called with a count argument of zero */
+ Warning ("Call to memset has no effect");
+
+ /* Remove all of the generated code but the load of the first
+ ** argument, which is what memset returns.
+ */
+ RemoveCode (&Arg1.Push);
+
+ /* Set the function result to the first argument */
+ *Expr = Arg1.Expr;
+
+ /* Bail out, no need for further improvements */
+ goto ExitPoint;
+ }
+
+ if (IS_Get (&InlineStdFuncs)) {
+
+ /* We've generated the complete code for the function now and know the
+ ** types of all parameters. Check for situations where better code can
+ ** be generated. If such a situation is detected, throw away the
+ ** generated, and emit better code.
+ ** Note: Lots of improvements would be possible here, but I will
+ ** concentrate on the most common case: memset with arguments 2 and 3
+ ** being constant numerical values. Some checks have shown that this
+ ** covers nearly 90% of all memset calls.
+ */
+ if (ED_IsConstAbsInt (&Arg3.Expr) && Arg3.Expr.IVal <= 256 &&
+ ED_IsConstAbsInt (&Arg2.Expr) &&
+ ((ED_IsRVal (&Arg1.Expr) && ED_IsLocConst (&Arg1.Expr)) ||
+ (ED_IsLVal (&Arg1.Expr) && ED_IsLocRegister (&Arg1.Expr)))) {
+
+ int Reg = ED_IsLVal (&Arg1.Expr) && ED_IsLocRegister (&Arg1.Expr);
+
+ /* Drop the generated code */
+ RemoveCode (&Arg1.Expr.Start);
+
+ /* We need a label */
+ Label = GetLocalLabel ();
+
+ /* Generate memset code */
+ if (Arg3.Expr.IVal <= 129) {
+
+ AddCodeLine ("ldy #$%02X", (unsigned char) (Arg3.Expr.IVal-1));
+ AddCodeLine ("lda #$%02X", (unsigned char) Arg2.Expr.IVal);
+ g_defcodelabel (Label);
+ if (Reg) {
+ AddCodeLine ("sta (%s),y", ED_GetLabelName (&Arg1.Expr, 0));
+ } else {
+ AddCodeLine ("sta %s,y", ED_GetLabelName (&Arg1.Expr, 0));
+ }
+ AddCodeLine ("dey");
+ AddCodeLine ("bpl %s", LocalLabelName (Label));
+
+ } else {
+
+ AddCodeLine ("ldy #$00");
+ AddCodeLine ("lda #$%02X", (unsigned char) Arg2.Expr.IVal);
+ g_defcodelabel (Label);
+ if (Reg) {
+ AddCodeLine ("sta (%s),y", ED_GetLabelName (&Arg1.Expr, 0));
+ } else {
+ AddCodeLine ("sta %s,y", ED_GetLabelName (&Arg1.Expr, 0));
+ }
+ AddCodeLine ("iny");
+ AddCmpCodeIfSizeNot256 ("cpy #$%02X", Arg3.Expr.IVal);
+ AddCodeLine ("bne %s", LocalLabelName (Label));
+
+ }
+
+ /* memset returns the address, so the result is actually identical
+ ** to the first argument.
+ */
+ *Expr = Arg1.Expr;
+
+ /* Bail out, no need for further processing */
+ goto ExitPoint;
+ }
+
+ if (ED_IsConstAbsInt (&Arg3.Expr) && Arg3.Expr.IVal <= 256 &&
+ ED_IsConstAbsInt (&Arg2.Expr) &&
+ ED_IsRVal (&Arg1.Expr) && ED_IsLocStack (&Arg1.Expr) &&
+ (Arg1.Expr.IVal - StackPtr) + Arg3.Expr.IVal < 256) {
+
+ /* Calculate the real stack offset */
+ int Offs = ED_GetStackOffs (&Arg1.Expr, 0);
+
+ /* Drop the generated code */
+ RemoveCode (&Arg1.Expr.Start);
+
+ /* We need a label */
+ Label = GetLocalLabel ();
+
+ /* Generate memset code */
+ AddCodeLine ("ldy #$%02X", (unsigned char) Offs);
+ AddCodeLine ("lda #$%02X", (unsigned char) Arg2.Expr.IVal);
+ g_defcodelabel (Label);
+ AddCodeLine ("sta (sp),y");
+ AddCodeLine ("iny");
+ AddCmpCodeIfSizeNot256 ("cpy #$%02X", Offs + Arg3.Expr.IVal);
+ AddCodeLine ("bne %s", LocalLabelName (Label));
+
+ /* memset returns the address, so the result is actually identical
+ ** to the first argument.
+ */
+ *Expr = Arg1.Expr;
+
+ /* Bail out, no need for further processing */
+ goto ExitPoint;
+ }
+
+ if (ED_IsConstAbsInt (&Arg3.Expr) && Arg3.Expr.IVal <= 256 &&
+ ED_IsConstAbsInt (&Arg2.Expr) &&
+ (Arg2.Expr.IVal != 0 || IS_Get (&CodeSizeFactor) > 200)) {
+
+ /* Remove all of the generated code but the load of the first
+ ** argument.
+ */
+ RemoveCode (&Arg1.Push);
+
+ /* We need a label */
+ Label = GetLocalLabel ();
+
+ /* Generate code */
+ AddCodeLine ("sta ptr1");
+ AddCodeLine ("stx ptr1+1");
+ if (Arg3.Expr.IVal <= 129) {
+ AddCodeLine ("ldy #$%02X", (unsigned char) (Arg3.Expr.IVal-1));
+ AddCodeLine ("lda #$%02X", (unsigned char) Arg2.Expr.IVal);
+ g_defcodelabel (Label);
+ AddCodeLine ("sta (ptr1),y");
+ AddCodeLine ("dey");
+ AddCodeLine ("bpl %s", LocalLabelName (Label));
+ } else {
+ AddCodeLine ("ldy #$00");
+ AddCodeLine ("lda #$%02X", (unsigned char) Arg2.Expr.IVal);
+ g_defcodelabel (Label);
+ AddCodeLine ("sta (ptr1),y");
+ AddCodeLine ("iny");
+ AddCmpCodeIfSizeNot256 ("cpy #$%02X", Arg3.Expr.IVal);
+ AddCodeLine ("bne %s", LocalLabelName (Label));
+ }
+
+ /* Load the function result pointer into a/x (x is still valid). This
+ ** code will get removed by the optimizer if it is not used later.
+ */
+ AddCodeLine ("lda ptr1");
+
+ /* The function result is an rvalue in the primary register */
+ ED_MakeRValExpr (Expr);
+ Expr->Type = GetFuncReturn (Expr->Type);
+
+ /* Bail out, no need for further processing */
+ goto ExitPoint;
+ }
+ }
+
+ /* The function result is an rvalue in the primary register */
+ ED_MakeRValExpr (Expr);
+ Expr->Type = GetFuncReturn (Expr->Type);
+
+ExitPoint:
+ /* We expect the closing brace */
+ ConsumeRParen ();
+}
+
+
+
+/*****************************************************************************/
+/* strcmp */
+/*****************************************************************************/
+
+
+
+static void StdFunc_strcmp (FuncDesc* F attribute ((unused)), ExprDesc* Expr)
+/* Handle the strcmp function */
+{
+ /* Argument types: (const char*, const char*) */
+ static Type Arg1Type[] = { TYPE(T_PTR), TYPE(T_CHAR|T_QUAL_CONST), TYPE(T_END) };
+ static Type Arg2Type[] = { TYPE(T_PTR), TYPE(T_CHAR|T_QUAL_CONST), TYPE(T_END) };
+
+ ArgDesc Arg1, Arg2;
+ unsigned ParamSize = 0;
+ long ECount1;
+ long ECount2;
+ int IsArray;
+ int Offs;
+
+ /* Setup the argument type string */
+ Arg1Type[1].C = GetDefaultChar () | T_QUAL_CONST;
+ Arg2Type[1].C = GetDefaultChar () | T_QUAL_CONST;
+
+ /* Argument #1 */
+ ParseArg (&Arg1, Arg1Type);
+ g_push (Arg1.Flags, Arg1.Expr.IVal);
+ ParamSize += SizeOf (Arg1Type);
+ ConsumeComma ();
+
+ /* Argument #2. */
+ ParseArg (&Arg2, Arg2Type);
+
+ /* Since strcmp is a fastcall function, we must load the
+ ** arg into the primary if it is not already there. This parameter is
+ ** also ignored for the calculation of the parameter size, since it is
+ ** not passed via the stack.
+ */
+ if (Arg2.Flags & CF_CONST) {
+ LoadExpr (CF_NONE, &Arg2.Expr);
+ }
+
+ /* Emit the actual function call. This will also cleanup the stack. */
+ g_call (CF_FIXARGC, Func_strcmp, ParamSize);
+
+ /* Get the element counts of the arguments. Then get the larger of the
+ ** two into ECount1. This removes FLEXIBLE and UNSPECIFIED automatically
+ */
+ ECount1 = ArrayElementCount (&Arg1);
+ ECount2 = ArrayElementCount (&Arg2);
+ if (ECount2 > ECount1) {
+ ECount1 = ECount2;
+ }
+
+ if (IS_Get (&InlineStdFuncs)) {
+
+ /* If the second argument is the empty string literal, we can generate
+ ** more efficient code.
+ */
+ if (ED_IsLocLiteral (&Arg2.Expr) &&
+ IS_Get (&WritableStrings) == 0 &&
+ GetLiteralSize (Arg2.Expr.LVal) == 1 &&
+ GetLiteralStr (Arg2.Expr.LVal)[0] == '\0') {
+
+ /* Drop the generated code so we have the first argument in the
+ ** primary
+ */
+ RemoveCode (&Arg1.Push);
+
+ /* We don't need the literal any longer */
+ ReleaseLiteral (Arg2.Expr.LVal);
+
+ /* We do now have Arg1 in the primary. Load the first character from
+ ** this string and cast to int. This is the function result.
+ */
+ IsArray = IsTypeArray (Arg1.Type) && ED_IsRVal (&Arg1.Expr);
+ if (IsArray && ED_IsLocStack (&Arg1.Expr) &&
+ (Offs = ED_GetStackOffs (&Arg1.Expr, 0) < 256)) {
+ /* Drop the generated code */
+ RemoveCode (&Arg1.Load);
+
+ /* Generate code */
+ AddCodeLine ("ldy #$%02X", Offs);
+ AddCodeLine ("ldx #$00");
+ AddCodeLine ("lda (sp),y");
+ } else if (IsArray && ED_IsLocConst (&Arg1.Expr)) {
+ /* Drop the generated code */
+ RemoveCode (&Arg1.Load);
+
+ /* Generate code */
+ AddCodeLine ("ldx #$00");
+ AddCodeLine ("lda %s", ED_GetLabelName (&Arg1.Expr, 0));
+ } else {
+ /* Drop part of the generated code so we have the first argument
+ ** in the primary
+ */
+ RemoveCode (&Arg1.Push);
+
+ /* Fetch the first char */
+ g_getind (CF_CHAR | CF_UNSIGNED, 0);
+ }
+
+ } else if ((IS_Get (&CodeSizeFactor) >= 165) &&
+ ((ED_IsRVal (&Arg2.Expr) && ED_IsLocConst (&Arg2.Expr)) ||
+ (ED_IsLVal (&Arg2.Expr) && ED_IsLocRegister (&Arg2.Expr))) &&
+ ((ED_IsRVal (&Arg1.Expr) && ED_IsLocConst (&Arg1.Expr)) ||
+ (ED_IsLVal (&Arg1.Expr) && ED_IsLocRegister (&Arg1.Expr))) &&
+ (IS_Get (&EagerlyInlineFuncs) || (ECount1 > 0 && ECount1 < 256))) {
+
+ unsigned Entry, Loop, Fin; /* Labels */
+ const char* Load;
+ const char* Compare;
+
+ if (ED_IsLVal (&Arg1.Expr) && ED_IsLocRegister (&Arg1.Expr)) {
+ Load = "lda (%s),y";
+ } else {
+ Load = "lda %s,y";
+ }
+ if (ED_IsLVal (&Arg2.Expr) && ED_IsLocRegister (&Arg2.Expr)) {
+ Compare = "cmp (%s),y";
+ } else {
+ Compare = "cmp %s,y";
+ }
+
+ /* Drop the generated code */
+ RemoveCode (&Arg1.Expr.Start);
+
+ /* We need labels */
+ Entry = GetLocalLabel ();
+ Loop = GetLocalLabel ();
+ Fin = GetLocalLabel ();
+
+ /* Generate strcmp code */
+ AddCodeLine ("ldy #$00");
+ AddCodeLine ("beq %s", LocalLabelName (Entry));
+ g_defcodelabel (Loop);
+ AddCodeLine ("tax");
+ AddCodeLine ("beq %s", LocalLabelName (Fin));
+ AddCodeLine ("iny");
+ g_defcodelabel (Entry);
+ AddCodeLine (Load, ED_GetLabelName (&Arg1.Expr, 0));
+ AddCodeLine (Compare, ED_GetLabelName (&Arg2.Expr, 0));
+ AddCodeLine ("beq %s", LocalLabelName (Loop));
+ AddCodeLine ("ldx #$01");
+ AddCodeLine ("bcs %s", LocalLabelName (Fin));
+ AddCodeLine ("ldx #$FF");
+ g_defcodelabel (Fin);
+
+ } else if ((IS_Get (&CodeSizeFactor) > 190) &&
+ ((ED_IsRVal (&Arg2.Expr) && ED_IsLocConst (&Arg2.Expr)) ||
+ (ED_IsLVal (&Arg2.Expr) && ED_IsLocRegister (&Arg2.Expr))) &&
+ (IS_Get (&EagerlyInlineFuncs) || (ECount1 > 0 && ECount1 < 256))) {
+
+ unsigned Entry, Loop, Fin; /* Labels */
+ const char* Compare;
+
+ if (ED_IsLVal (&Arg2.Expr) && ED_IsLocRegister (&Arg2.Expr)) {
+ Compare = "cmp (%s),y";
+ } else {
+ Compare = "cmp %s,y";
+ }
+
+ /* Drop the generated code */
+ RemoveCode (&Arg1.Push);
+
+ /* We need labels */
+ Entry = GetLocalLabel ();
+ Loop = GetLocalLabel ();
+ Fin = GetLocalLabel ();
+
+ /* Store Arg1 into ptr1 */
+ AddCodeLine ("sta ptr1");
+ AddCodeLine ("stx ptr1+1");
+
+ /* Generate strcmp code */
+ AddCodeLine ("ldy #$00");
+ AddCodeLine ("beq %s", LocalLabelName (Entry));
+ g_defcodelabel (Loop);
+ AddCodeLine ("tax");
+ AddCodeLine ("beq %s", LocalLabelName (Fin));
+ AddCodeLine ("iny");
+ g_defcodelabel (Entry);
+ AddCodeLine ("lda (ptr1),y");
+ AddCodeLine (Compare, ED_GetLabelName (&Arg2.Expr, 0));
+ AddCodeLine ("beq %s", LocalLabelName (Loop));
+ AddCodeLine ("ldx #$01");
+ AddCodeLine ("bcs %s", LocalLabelName (Fin));
+ AddCodeLine ("ldx #$FF");
+ g_defcodelabel (Fin);
+ }
+ }
+
+ /* The function result is an rvalue in the primary register */
+ ED_MakeRValExpr (Expr);
+ Expr->Type = GetFuncReturn (Expr->Type);
+
+ /* We expect the closing brace */
+ ConsumeRParen ();
+}
+
+
+
+/*****************************************************************************/
+/* strcpy */
+/*****************************************************************************/
+
+
+
+static void StdFunc_strcpy (FuncDesc* F attribute ((unused)), ExprDesc* Expr)
+/* Handle the strcpy function */
+{
+ /* Argument types: (char*, const char*) */
+ static Type Arg1Type[] = { TYPE(T_PTR), TYPE(T_CHAR), TYPE(T_END) };
+ static Type Arg2Type[] = { TYPE(T_PTR), TYPE(T_CHAR|T_QUAL_CONST), TYPE(T_END) };
+
+ ArgDesc Arg1, Arg2;
+ unsigned ParamSize = 0;
+ long ECount;
+ unsigned L1;
+
+ /* Setup the argument type string */
+ Arg1Type[1].C = GetDefaultChar ();
+ Arg2Type[1].C = GetDefaultChar () | T_QUAL_CONST;
+
+ /* Argument #1 */
+ ParseArg (&Arg1, Arg1Type);
+ g_push (Arg1.Flags, Arg1.Expr.IVal);
+ GetCodePos (&Arg1.End);
+ ParamSize += SizeOf (Arg1Type);
+ ConsumeComma ();
+
+ /* Argument #2. Since strcpy is a fastcall function, we must load the
+ ** arg into the primary if it is not already there. This parameter is
+ ** also ignored for the calculation of the parameter size, since it is
+ ** not passed via the stack.
+ */
+ ParseArg (&Arg2, Arg2Type);
+ if (Arg2.Flags & CF_CONST) {
+ LoadExpr (CF_NONE, &Arg2.Expr);
+ }
+
+ /* Emit the actual function call. This will also cleanup the stack. */
+ g_call (CF_FIXARGC, Func_strcpy, ParamSize);
+
+ /* Get the element count of argument 1 if it is an array */
+ ECount = ArrayElementCount (&Arg1);
+
+ if (IS_Get (&InlineStdFuncs)) {
+
+ /* We've generated the complete code for the function now and know the
+ ** types of all parameters. Check for situations where better code can
+ ** be generated. If such a situation is detected, throw away the
+ ** generated, and emit better code.
+ */
+ if (((ED_IsRVal (&Arg2.Expr) && ED_IsLocConst (&Arg2.Expr)) ||
+ (ED_IsLVal (&Arg2.Expr) && ED_IsLocRegister (&Arg2.Expr))) &&
+ ((ED_IsRVal (&Arg1.Expr) && ED_IsLocConst (&Arg1.Expr)) ||
+ (ED_IsLVal (&Arg1.Expr) && ED_IsLocRegister (&Arg1.Expr))) &&
+ (IS_Get (&EagerlyInlineFuncs) ||
+ (ECount != UNSPECIFIED && ECount < 256))) {
+
+ const char* Load;
+ const char* Store;
+ if (ED_IsLVal (&Arg2.Expr) && ED_IsLocRegister (&Arg2.Expr)) {
+ Load = "lda (%s),y";
+ } else {
+ Load = "lda %s,y";
+ }
+ if (ED_IsLVal (&Arg1.Expr) && ED_IsLocRegister (&Arg1.Expr)) {
+ Store = "sta (%s),y";
+ } else {
+ Store = "sta %s,y";
+ }
+
+ /* Drop the generated code */
+ RemoveCode (&Arg1.Expr.Start);
+
+ /* We need labels */
+ L1 = GetLocalLabel ();
+
+ /* Generate strcpy code */
+ AddCodeLine ("ldy #$FF");
+ g_defcodelabel (L1);
+ AddCodeLine ("iny");
+ AddCodeLine (Load, ED_GetLabelName (&Arg2.Expr, 0));
+ AddCodeLine (Store, ED_GetLabelName (&Arg1.Expr, 0));
+ AddCodeLine ("bne %s", LocalLabelName (L1));
+
+ /* strcpy returns argument #1 */
+ *Expr = Arg1.Expr;
+
+ /* Bail out, no need for further processing */
+ goto ExitPoint;
+ }
+
+ if (ED_IsRVal (&Arg2.Expr) && ED_IsLocStack (&Arg2.Expr) &&
+ StackPtr >= -255 &&
+ ED_IsRVal (&Arg1.Expr) && ED_IsLocConst (&Arg1.Expr)) {
+
+ /* It is possible to just use one index register even if the stack
+ ** offset is not zero, by adjusting the offset to the constant
+ ** address accordingly. But we cannot do this if the data in
+ ** question is in the register space or at an absolute address less
+ ** than 256. Register space is zero page, which means that the
+ ** address calculation could overflow in the linker.
+ */
+ int AllowOneIndex = !ED_IsLocRegister (&Arg1.Expr) &&
+ !(ED_IsLocAbs (&Arg1.Expr) && Arg1.Expr.IVal < 256);
+
+ /* Calculate the real stack offset */
+ int Offs = ED_GetStackOffs (&Arg2.Expr, 0);
+
+ /* Drop the generated code */
+ RemoveCode (&Arg1.Expr.Start);
+
+ /* We need labels */
+ L1 = GetLocalLabel ();
+
+ /* Generate strcpy code */
+ AddCodeLine ("ldy #$%02X", (unsigned char) (Offs - 1));
+ if (Offs == 0 || AllowOneIndex) {
+ g_defcodelabel (L1);
+ AddCodeLine ("iny");
+ AddCodeLine ("lda (sp),y");
+ AddCodeLine ("sta %s,y", ED_GetLabelName (&Arg1.Expr, -Offs));
+ } else {
+ AddCodeLine ("ldx #$FF");
+ g_defcodelabel (L1);
+ AddCodeLine ("iny");
+ AddCodeLine ("inx");
+ AddCodeLine ("lda (sp),y");
+ AddCodeLine ("sta %s,x", ED_GetLabelName (&Arg1.Expr, 0));
+ }
+ AddCodeLine ("bne %s", LocalLabelName (L1));
+
+ /* strcpy returns argument #1 */
+ *Expr = Arg1.Expr;
+
+ /* Bail out, no need for further processing */
+ goto ExitPoint;
+ }
+
+ if (ED_IsRVal (&Arg2.Expr) && ED_IsLocConst (&Arg2.Expr) &&
+ ED_IsRVal (&Arg1.Expr) && ED_IsLocStack (&Arg1.Expr) &&
+ StackPtr >= -255) {
+
+ /* It is possible to just use one index register even if the stack
+ ** offset is not zero, by adjusting the offset to the constant
+ ** address accordingly. But we cannot do this if the data in
+ ** question is in the register space or at an absolute address less
+ ** than 256. Register space is zero page, which means that the
+ ** address calculation could overflow in the linker.
+ */
+ int AllowOneIndex = !ED_IsLocRegister (&Arg2.Expr) &&
+ !(ED_IsLocAbs (&Arg2.Expr) && Arg2.Expr.IVal < 256);
+
+ /* Calculate the real stack offset */
+ int Offs = ED_GetStackOffs (&Arg1.Expr, 0);
+
+ /* Drop the generated code */
+ RemoveCode (&Arg1.Expr.Start);
+
+ /* We need labels */
+ L1 = GetLocalLabel ();
+
+ /* Generate strcpy code */
+ AddCodeLine ("ldy #$%02X", (unsigned char) (Offs - 1));
+ if (Offs == 0 || AllowOneIndex) {
+ g_defcodelabel (L1);
+ AddCodeLine ("iny");
+ AddCodeLine ("lda %s,y", ED_GetLabelName (&Arg2.Expr, -Offs));
+ AddCodeLine ("sta (sp),y");
+ } else {
+ AddCodeLine ("ldx #$FF");
+ g_defcodelabel (L1);
+ AddCodeLine ("iny");
+ AddCodeLine ("inx");
+ AddCodeLine ("lda %s,x", ED_GetLabelName (&Arg2.Expr, 0));
+ AddCodeLine ("sta (sp),y");
+ }
+ AddCodeLine ("bne %s", LocalLabelName (L1));
+
+ /* strcpy returns argument #1 */
+ *Expr = Arg1.Expr;
+
+ /* Bail out, no need for further processing */
+ goto ExitPoint;
+ }
+ }
+
+ /* The function result is an rvalue in the primary register */
+ ED_MakeRValExpr (Expr);
+ Expr->Type = GetFuncReturn (Expr->Type);
+
+ExitPoint:
+ /* We expect the closing brace */
+ ConsumeRParen ();
+}
+
+
+
+/*****************************************************************************/
+/* strlen */
+/*****************************************************************************/
+
+
+
+static void StdFunc_strlen (FuncDesc* F attribute ((unused)), ExprDesc* Expr)
+/* Handle the strlen function */
+{
+ static Type ArgType[] = { TYPE(T_PTR), TYPE(T_CHAR|T_QUAL_CONST), TYPE(T_END) };
+ ExprDesc Arg;
+ int IsArray;
+ int IsPtr;
+ int IsByteIndex;
+ long ECount;
+ unsigned L;