]> git.sur5r.net Git - cc65/blobdiff - src/cc65/stdfunc.c
- fixed an old #include guard typo
[cc65] / src / cc65 / stdfunc.c
index 74b9b8c2a2d91459ff041e786991bcbc2259e9c1..1730ee08ac08647502a14ae0dc0b31d71262db75 100644 (file)
@@ -1,13 +1,13 @@
 /*****************************************************************************/
 /*                                                                           */
-/*                                stdfunc.c                                 */
+/*                                 stdfunc.c                                 */
 /*                                                                           */
-/*        Handle inlining of known functions for the cc65 compiler          */
+/*         Handle inlining of known functions for the cc65 compiler          */
 /*                                                                           */
 /*                                                                           */
 /*                                                                           */
-/* (C) 1998-2004 Ullrich von Bassewitz                                       */
-/*               Römerstrasse 52                                             */
+/* (C) 1998-2010 Ullrich von Bassewitz                                       */
+/*               Roemerstrasse 52                                            */
 /*               D-70794 Filderstadt                                         */
 /* EMail:        uz@cc65.org                                                 */
 /*                                                                           */
 
 
 /*****************************************************************************/
-/*                            Function forwards                             */
+/*                             Function forwards                             */
 /*****************************************************************************/
 
 
 
 static void StdFunc_memcpy (FuncDesc*, ExprDesc*);
 static void StdFunc_memset (FuncDesc*, ExprDesc*);
+static void StdFunc_strcmp (FuncDesc*, ExprDesc*);
 static void StdFunc_strcpy (FuncDesc*, ExprDesc*);
 static void StdFunc_strlen (FuncDesc*, ExprDesc*);
 
 
 
 /*****************************************************************************/
-/*                                  Data                                    */
+/*                                   Data                                    */
 /*****************************************************************************/
 
 
@@ -80,23 +81,24 @@ static void StdFunc_strlen (FuncDesc*, ExprDesc*);
  * alphabetically!
  */
 static struct StdFuncDesc {
-    const char*                Name;
-    void               (*Handler) (FuncDesc*, ExprDesc*);
+    const char*         Name;
+    void                (*Handler) (FuncDesc*, ExprDesc*);
 } StdFuncs[] = {
-    {          "memcpy",       StdFunc_memcpy          },
-    {          "memset",       StdFunc_memset          },
-    {          "strcpy",       StdFunc_strcpy          },
-    {          "strlen",       StdFunc_strlen          },
+    {   "memcpy",       StdFunc_memcpy          },
+    {   "memset",       StdFunc_memset          },
+    {   "strcmp",       StdFunc_strcmp          },
+    {   "strcpy",       StdFunc_strcpy          },
+    {   "strlen",       StdFunc_strlen          },
 
 };
-#define FUNC_COUNT     (sizeof (StdFuncs) / sizeof (StdFuncs[0]))
+#define FUNC_COUNT      (sizeof (StdFuncs) / sizeof (StdFuncs[0]))
 
 typedef struct ArgDesc ArgDesc;
 struct ArgDesc {
-    const type* ArgType;        /* Required argument type */
+    const Type* ArgType;        /* Required argument type */
     ExprDesc    Expr;           /* Argument expression */
-    const type* Type;           /* The original type before conversion */
-    CodeMark    Start;          /* Start of the code for calculation */
+    const Type* Type;           /* The original type before conversion */
+    CodeMark    Load;           /* Start of argument load code */
     CodeMark    Push;           /* Start of argument push code */
     CodeMark    End;            /* End of the code for calculation+push */
     unsigned    Flags;          /* Code generation flags */
@@ -105,7 +107,7 @@ struct ArgDesc {
 
 
 /*****************************************************************************/
-/*                            Helper functions                              */
+/*                             Helper functions                              */
 /*****************************************************************************/
 
 
@@ -139,7 +141,7 @@ static long ArrayElementCount (const ArgDesc* Arg)
 
 
 
-static void ParseArg (ArgDesc* Arg, type* Type)
+static void ParseArg (ArgDesc* Arg, Type* Type)
 /* Parse one argument but do not push it onto the stack. Make all fields in
  * Arg valid.
  */
@@ -150,11 +152,8 @@ static void ParseArg (ArgDesc* Arg, type* Type)
     /* Remember the required argument type */
     Arg->ArgType = Type;
 
-    /* Remember the current code position */
-    Arg->Start = GetCodePos ();
-
     /* Read the expression we're going to pass to the function */
-    ExprWithCheck (hie1, &Arg->Expr);
+    MarkedExprWithCheck (hie1, &Arg->Expr);
 
     /* Remember the actual argument type */
     Arg->Type = Arg->Expr.Type;
@@ -162,10 +161,13 @@ static void ParseArg (ArgDesc* Arg, type* Type)
     /* Convert this expression to the expected type */
     TypeConversion (&Arg->Expr, Type);
 
+    /* Remember the following code position */
+    GetCodePos (&Arg->Load);
+
     /* If the value is a constant, set the flag, otherwise load it into the
      * primary register.
      */
-    if (ED_IsConstAbsInt (&Arg->Expr)) {
+    if (ED_IsConstAbsInt (&Arg->Expr) && ED_CodeRangeIsEmpty (&Arg->Expr)) {
         /* Remember that we have a constant value */
         Arg->Flags |= CF_CONST;
     } else {
@@ -174,7 +176,8 @@ static void ParseArg (ArgDesc* Arg, type* Type)
     }
 
     /* Remember the following code position */
-    Arg->End = Arg->Push = GetCodePos ();
+    GetCodePos (&Arg->Push);
+    GetCodePos (&Arg->End);
 
     /* Use the type of the argument for the push */
     Arg->Flags |= TypeOf (Arg->Expr.Type);
@@ -191,30 +194,27 @@ static void ParseArg (ArgDesc* Arg, type* Type)
 static void StdFunc_memcpy (FuncDesc* F attribute ((unused)), ExprDesc* Expr)
 /* Handle the memcpy function */
 {
-    /* Argument types */
-    static type Arg1Type[] = { T_PTR, T_VOID, T_END };              /* void* */
-    static type Arg2Type[] = { T_PTR, T_VOID|T_QUAL_CONST, T_END }; /* const void* */
-    static type Arg3Type[] = { T_SIZE_T, T_END };                   /* size_t */
+    /* Argument types: (void*, const void*, size_t) */
+    static Type Arg1Type[] = { TYPE(T_PTR), TYPE(T_VOID), TYPE(T_END) };
+    static Type Arg2Type[] = { TYPE(T_PTR), TYPE(T_VOID|T_QUAL_CONST), TYPE(T_END) };
+    static Type Arg3Type[] = { TYPE(T_SIZE_T), TYPE(T_END) };
 
-    CodeMark Start;
     ArgDesc  Arg1, Arg2, Arg3;
     unsigned ParamSize = 0;
     unsigned Label;
-
-    /* Remember where we are now */
-    Start = GetCodePos ();
+    int      Offs;
 
     /* Argument #1 */
     ParseArg (&Arg1, Arg1Type);
     g_push (Arg1.Flags, Arg1.Expr.IVal);
-    Arg1.End = GetCodePos ();
+    GetCodePos (&Arg1.End);
     ParamSize += SizeOf (Arg1Type);
     ConsumeComma ();
 
     /* Argument #2 */
     ParseArg (&Arg2, Arg2Type);
     g_push (Arg2.Flags, Arg2.Expr.IVal);
-    Arg2.End = GetCodePos ();
+    GetCodePos (&Arg2.End);
     ParamSize += SizeOf (Arg2Type);
     ConsumeComma ();
 
@@ -239,7 +239,7 @@ static void StdFunc_memcpy (FuncDesc* F attribute ((unused)), ExprDesc* Expr)
         /* Remove all of the generated code but the load of the first
          * argument, which is what memcpy returns.
          */
-        RemoveCode (Arg1.Push);
+        RemoveCode (&Arg1.Push);
 
         /* Set the function result to the first argument */
         *Expr = Arg1.Expr;
@@ -263,7 +263,7 @@ static void StdFunc_memcpy (FuncDesc* F attribute ((unused)), ExprDesc* Expr)
         int Reg2 = ED_IsLVal (&Arg2.Expr) && ED_IsLocRegister (&Arg2.Expr);
 
         /* Drop the generated code */
-        RemoveCode (Start);
+        RemoveCode (&Arg1.Expr.Start);
 
         /* We need a label */
         Label = GetLocalLabel ();
@@ -329,18 +329,18 @@ static void StdFunc_memcpy (FuncDesc* F attribute ((unused)), ExprDesc* Expr)
                             !(ED_IsLocAbs (&Arg2.Expr) && Arg2.Expr.IVal < 256);
 
         /* Calculate the real stack offset */
-        int Offs = ED_GetStackOffs (&Arg1.Expr, 0);
+        Offs = ED_GetStackOffs (&Arg1.Expr, 0);
 
         /* Drop the generated code */
-        RemoveCode (Start);
+        RemoveCode (&Arg1.Expr.Start);
 
         /* We need a label */
         Label = GetLocalLabel ();
 
         /* Generate memcpy code */
-        if (Arg3.Expr.IVal <= 127) {
+        if (Arg3.Expr.IVal <= 127 && !AllowOneIndex) {
 
-            if (Offs == 0 || AllowOneIndex) {
+            if (Offs == 0) {
                 AddCodeLine ("ldy #$%02X", (unsigned char) (Offs + Arg3.Expr.IVal - 1));
                 g_defcodelabel (Label);
                 AddCodeLine ("lda %s,y", ED_GetLabelName (&Arg2.Expr, -Offs));
@@ -403,22 +403,22 @@ static void StdFunc_memcpy (FuncDesc* F attribute ((unused)), ExprDesc* Expr)
                             !(ED_IsLocAbs (&Arg1.Expr) && Arg1.Expr.IVal < 256);
 
         /* Calculate the real stack offset */
-        int Offs = ED_GetStackOffs (&Arg2.Expr, 0);
+        Offs = ED_GetStackOffs (&Arg2.Expr, 0);
 
         /* Drop the generated code */
-        RemoveCode (Start);
+        RemoveCode (&Arg1.Expr.Start);
 
         /* We need a label */
         Label = GetLocalLabel ();
 
         /* Generate memcpy code */
-        if (Arg3.Expr.IVal <= 127) {
+        if (Arg3.Expr.IVal <= 127 && !AllowOneIndex) {
 
-            if (Offs == 0 || AllowOneIndex) {
-                AddCodeLine ("ldy #$%02X", (unsigned char) (Offs + Arg3.Expr.IVal - 1));
+            if (Offs == 0) {
+                AddCodeLine ("ldy #$%02X", (unsigned char) (Arg3.Expr.IVal - 1));
                 g_defcodelabel (Label);
                 AddCodeLine ("lda (sp),y");
-                AddCodeLine ("sta %s,y", ED_GetLabelName (&Arg1.Expr, -Offs));
+                AddCodeLine ("sta %s,y", ED_GetLabelName (&Arg1.Expr, 0));
                 AddCodeLine ("dey");
                 AddCodeLine ("bpl %s", LocalLabelName (Label));
             } else {
@@ -461,6 +461,43 @@ static void StdFunc_memcpy (FuncDesc* F attribute ((unused)), ExprDesc* Expr)
          */
         *Expr = Arg1.Expr;
 
+    } else if (ED_IsConstAbsInt (&Arg3.Expr) && Arg3.Expr.IVal <= 256   &&
+               ED_IsRVal (&Arg2.Expr) && ED_IsLocStack (&Arg2.Expr)     &&
+               (Offs = ED_GetStackOffs (&Arg2.Expr, 0)) == 0) {
+
+        /* Drop the generated code but leave the load of the first argument*/
+        RemoveCode (&Arg1.Push);
+
+        /* We need a label */
+        Label = GetLocalLabel ();
+
+        /* Generate memcpy code */
+        AddCodeLine ("sta ptr1");
+        AddCodeLine ("stx ptr1+1");
+        if (Arg3.Expr.IVal <= 127) {
+            AddCodeLine ("ldy #$%02X", (unsigned char) (Arg3.Expr.IVal - 1));
+            g_defcodelabel (Label);
+            AddCodeLine ("lda (sp),y");
+            AddCodeLine ("sta (ptr1),y");
+            AddCodeLine ("dey");
+            AddCodeLine ("bpl %s", LocalLabelName (Label));
+        } else {
+            AddCodeLine ("ldy #$00");
+            g_defcodelabel (Label);
+            AddCodeLine ("lda (sp),y");
+            AddCodeLine ("sta (ptr1),y");
+            AddCodeLine ("iny");
+            AddCodeLine ("cpy #$%02X", (unsigned char) Arg3.Expr.IVal);
+            AddCodeLine ("bne %s", LocalLabelName (Label));
+        }
+
+        /* Reload result - X hasn't changed by the code above */
+        AddCodeLine ("lda ptr1");
+
+        /* The function result is an rvalue in the primary register */
+        ED_MakeRValExpr (Expr);
+        Expr->Type = GetFuncReturn (Expr->Type);
+
     } else {
 
         /* The function result is an rvalue in the primary register */
@@ -485,24 +522,20 @@ ExitPoint:
 static void StdFunc_memset (FuncDesc* F attribute ((unused)), ExprDesc* Expr)
 /* Handle the memset function */
 {
-    /* Argument types */
-    static type Arg1Type[] = { T_PTR, T_VOID, T_END };  /* void* */
-    static type Arg2Type[] = { T_INT, T_END };          /* int */
-    static type Arg3Type[] = { T_SIZE_T, T_END };       /* size_t */
+    /* Argument types: (void*, int, size_t) */
+    static Type Arg1Type[] = { TYPE(T_PTR), TYPE(T_VOID), TYPE(T_END) };
+    static Type Arg2Type[] = { TYPE(T_INT), TYPE(T_END) };
+    static Type Arg3Type[] = { TYPE(T_SIZE_T), TYPE(T_END) };
 
-    CodeMark Start;
     ArgDesc  Arg1, Arg2, Arg3;
     int      MemSet    = 1;             /* Use real memset if true */
     unsigned ParamSize = 0;
     unsigned Label;
 
-    /* Remember where we are now */
-    Start = GetCodePos ();
-
     /* Argument #1 */
     ParseArg (&Arg1, Arg1Type);
     g_push (Arg1.Flags, Arg1.Expr.IVal);
-    Arg1.End = GetCodePos ();
+    GetCodePos (&Arg1.End);
     ParamSize += SizeOf (Arg1Type);
     ConsumeComma ();
 
@@ -516,7 +549,7 @@ static void StdFunc_memset (FuncDesc* F attribute ((unused)), ExprDesc* Expr)
     } else {
         /* Push the argument */
         g_push (Arg2.Flags, Arg2.Expr.IVal);
-        Arg2.End = GetCodePos ();
+        GetCodePos (&Arg2.End);
         ParamSize += SizeOf (Arg2Type);
     }
     ConsumeComma ();
@@ -542,7 +575,7 @@ static void StdFunc_memset (FuncDesc* F attribute ((unused)), ExprDesc* Expr)
         /* Remove all of the generated code but the load of the first
          * argument, which is what memset returns.
          */
-        RemoveCode (Arg1.Push);
+        RemoveCode (&Arg1.Push);
 
         /* Set the function result to the first argument */
         *Expr = Arg1.Expr;
@@ -568,7 +601,7 @@ static void StdFunc_memset (FuncDesc* F attribute ((unused)), ExprDesc* Expr)
         int Reg = ED_IsLVal (&Arg1.Expr) && ED_IsLocRegister (&Arg1.Expr);
 
         /* Drop the generated code */
-        RemoveCode (Start);
+        RemoveCode (&Arg1.Expr.Start);
 
         /* We need a label */
         Label = GetLocalLabel ();
@@ -617,7 +650,7 @@ static void StdFunc_memset (FuncDesc* F attribute ((unused)), ExprDesc* Expr)
         int Offs = ED_GetStackOffs (&Arg1.Expr, 0);
 
         /* Drop the generated code */
-        RemoveCode (Start);
+        RemoveCode (&Arg1.Expr.Start);
 
         /* We need a label */
         Label = GetLocalLabel ();
@@ -643,7 +676,7 @@ static void StdFunc_memset (FuncDesc* F attribute ((unused)), ExprDesc* Expr)
         /* Remove all of the generated code but the load of the first
          * argument.
          */
-        RemoveCode (Arg1.Push);
+        RemoveCode (&Arg1.Push);
 
         /* We need a label */
         Label = GetLocalLabel ();
@@ -692,6 +725,208 @@ ExitPoint:
 
 
 
+/*****************************************************************************/
+/*                                  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 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 (&InlineStdFuncs) || (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 (&InlineStdFuncs) || (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                                   */
 /*****************************************************************************/
@@ -701,27 +936,23 @@ ExitPoint:
 static void StdFunc_strcpy (FuncDesc* F attribute ((unused)), ExprDesc* Expr)
 /* Handle the strcpy function */
 {
-    /* Argument types */
-    static type Arg1Type[] = { T_PTR, T_CHAR, T_END };              /* char* */
-    static type Arg2Type[] = { T_PTR, T_CHAR|T_QUAL_CONST, T_END }; /* const char* */
+    /* 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) };
 
-    CodeMark Start;
     ArgDesc  Arg1, Arg2;
     unsigned ParamSize = 0;
     long     ECount;
     unsigned L1;
 
     /* Setup the argument type string */
-    Arg1Type[1] = GetDefaultChar ();
-    Arg2Type[1] = GetDefaultChar () | T_QUAL_CONST;
-
-    /* Remember where we are now */
-    Start = GetCodePos ();
+    Arg1Type[1].C = GetDefaultChar ();
+    Arg2Type[1].C = GetDefaultChar () | T_QUAL_CONST;
 
     /* Argument #1 */
     ParseArg (&Arg1, Arg1Type);
     g_push (Arg1.Flags, Arg1.Expr.IVal);
-    Arg1.End = GetCodePos ();
+    GetCodePos (&Arg1.End);
     ParamSize += SizeOf (Arg1Type);
     ConsumeComma ();
 
@@ -738,7 +969,7 @@ static void StdFunc_strcpy (FuncDesc* F attribute ((unused)), ExprDesc* 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 2 if it is an array */
+    /* Get the element count of argument 1 if it is an array */
     ECount = ArrayElementCount (&Arg1);
 
     /* We've generated the complete code for the function now and know the
@@ -767,7 +998,7 @@ static void StdFunc_strcpy (FuncDesc* F attribute ((unused)), ExprDesc* Expr)
         }
 
         /* Drop the generated code */
-        RemoveCode (Start);
+        RemoveCode (&Arg1.Expr.Start);
 
         /* We need labels */
         L1 = GetLocalLabel ();
@@ -801,7 +1032,7 @@ static void StdFunc_strcpy (FuncDesc* F attribute ((unused)), ExprDesc* Expr)
         int Offs = ED_GetStackOffs (&Arg2.Expr, 0);
 
         /* Drop the generated code */
-        RemoveCode (Start);
+        RemoveCode (&Arg1.Expr.Start);
 
         /* We need labels */
         L1 = GetLocalLabel ();
@@ -844,7 +1075,7 @@ static void StdFunc_strcpy (FuncDesc* F attribute ((unused)), ExprDesc* Expr)
         int Offs = ED_GetStackOffs (&Arg1.Expr, 0);
 
         /* Drop the generated code */
-        RemoveCode (Start);
+        RemoveCode (&Arg1.Expr.Start);
 
         /* We need labels */
         L1 = GetLocalLabel ();
@@ -892,7 +1123,7 @@ static void StdFunc_strcpy (FuncDesc* F attribute ((unused)), ExprDesc* Expr)
 static void StdFunc_strlen (FuncDesc* F attribute ((unused)), ExprDesc* Expr)
 /* Handle the strlen function */
 {
-    static type ArgType[] = { T_PTR, T_SCHAR, T_END };
+    static Type ArgType[] = { TYPE(T_PTR), TYPE(T_CHAR|T_QUAL_CONST), TYPE(T_END) };
     ExprDesc    Arg;
     int         IsArray;
     int         IsPtr;
@@ -903,7 +1134,7 @@ static void StdFunc_strlen (FuncDesc* F attribute ((unused)), ExprDesc* Expr)
 
 
     /* Setup the argument type string */
-    ArgType[1] = GetDefaultChar () | T_QUAL_CONST;
+    ArgType[1].C = GetDefaultChar () | T_QUAL_CONST;
 
     /* Evaluate the parameter */
     hie1 (&Arg);
@@ -941,8 +1172,10 @@ static void StdFunc_strlen (FuncDesc* F attribute ((unused)), ExprDesc* Expr)
     if (ED_IsLocLiteral (&Arg) && IS_Get (&WritableStrings) == 0) {
 
         /* Constant string literal */
-        ED_MakeConstAbs (Expr, strlen (GetLiteral (Arg.IVal)), type_size_t);
-        ResetLiteralPoolOffs (Arg.IVal);
+        ED_MakeConstAbs (Expr, GetLiteralSize (Arg.LVal) - 1, type_size_t);
+
+        /* We don't need the literal any longer */
+        ReleaseLiteral (Arg.LVal);
 
     /* We will inline strlen for arrays with constant addresses, if either the
      * inlining was forced on the command line, or the array is smaller than
@@ -1057,7 +1290,7 @@ static void StdFunc_strlen (FuncDesc* F attribute ((unused)), ExprDesc* Expr)
 
 
 /*****************************************************************************/
-/*                                  Code                                    */
+/*                                   Code                                    */
 /*****************************************************************************/
 
 
@@ -1093,6 +1326,3 @@ void HandleStdFunc (int Index, FuncDesc* F, ExprDesc* lval)
     /* Call the handler function */
     D->Handler (F, lval);
 }
-
-
-