/* ca65 */
 #include "error.h"
 #include "expr.h"
+#include "global.h"
 #include "scanner.h"
 #include "toklist.h"
 #include "nexttok.h"
 
 
 
+static void NoIdent (void)
+/* Print an error message and skip the remainder of the line */
+{
+    Error ("Argument of .IDENT is not a valid identifier");
+    SkipUntilSep ();
+}
+
+
+
+static void FuncIdent (void)
+/* Handle the .IDENT function */
+{
+    char       Buf[sizeof(SVal)];
+    enum Token Id;
+    unsigned   Len;
+    unsigned   I;
+
+    /* Skip it */
+    NextTok ();
+
+    /* Left paren expected */
+    ConsumeLParen ();
+
+    /* The function expects a string argument */
+    if (Tok != TOK_STRCON) {
+        Error ("String constant expected");
+        SkipUntilSep ();
+        return;
+    }
+
+    /* Check that the string contains a valid identifier. While doing so,
+     * determine if it is a cheap local, or global one.
+     */
+    Len = strlen (SVal);
+    if (Len == 0) {
+        NoIdent ();
+        return;
+    }
+    I = 0;
+    if (SVal[0] == LocalStart) {
+        if (Len < 2) {
+            NoIdent ();
+            return;
+        }
+        I = 1;
+        Id = TOK_LOCAL_IDENT;
+    } else {
+        Id = TOK_IDENT;
+    }
+    if (!IsIdStart (SVal[I])) {
+        NoIdent ();
+        return;
+    }
+    while (I < Len) {
+        if (!IsIdChar (SVal[I])) {
+            NoIdent ();
+            return;
+        }
+        ++I;
+    }
+    if (IgnoreCase) {
+        UpcaseSVal ();
+    }
+
+    /* If anything is ok, save and skip the string. Check that the next token
+     * is a right paren, in which case SVal is untouched. Replace the token by
+     * a identifier token.
+     */
+    memcpy (Buf, SVal, Len+1);
+    NextTok ();
+    if (Tok != TOK_RPAREN) {
+       Error ("`)' expected");
+    } else {
+        Tok = Id;
+        memcpy (SVal, Buf, Len+1);
+    }
+}
+
+
+
 static void FuncMid (void)
 /* Handle the .MID function */
 {
                FuncLeft ();
                break;
 
+            case TOK_MAKEIDENT:
+                FuncIdent ();
+                break;
+
            case TOK_MID:
                FuncMid ();
                break;
 
     { ccNone,          DoUnexpected    },      /* .HIWORD */
     { ccNone,          DoI16           },
     { ccNone,          DoI8            },
+    { ccNone,           DoUnexpected    },      /* .IDENT */
     { ccKeepToken,     DoConditionals  },      /* .IF */
     { ccKeepToken,     DoConditionals  },      /* .IFBLANK */
     { ccKeepToken,     DoConditionals  },      /* .IFCONST */
 
     { ".HIWORD",        TOK_HIWORD      },
     { ".I16",          TOK_I16         },
     { ".I8",           TOK_I8          },
+    { ".IDENT",         TOK_MAKEIDENT   },
     { ".IF",           TOK_IF          },
     { ".IFBLANK",      TOK_IFBLANK     },
     { ".IFCONST",      TOK_IFCONST     },
 
 
 
-static int IsIdChar (int C)
+int IsIdChar (int C)
 /* Return true if the character is a valid character for an identifier */
 {
     return IsAlNum (C)                         ||
 
 
 
-static int IsIdStart (int C)
+int IsIdStart (int C)
 /* Return true if the character may start an identifier */
 {
     return IsAlpha (C) || C == '_';
 
 /*                                                                           */
 /*                                                                           */
 /*                                                                           */
-/* (C) 1998-2004 Ullrich von Bassewitz                                       */
+/* (C) 1998-2005 Ullrich von Bassewitz                                       */
 /*               Römerstraße 52                                              */
 /*               D-70794 Filderstadt                                         */
 /* EMail:        uz@cc65.org                                                 */
     TOK_HIWORD,
     TOK_I16,
     TOK_I8,
+    TOK_MAKEIDENT,
     TOK_IF,
     TOK_IFBLANK,
     TOK_IFCONST,
 
 
 
+int IsIdChar (int C);
+/* Return true if the character is a valid character for an identifier */
+
+int IsIdStart (int C);
+/* Return true if the character may start an identifier */
+
 void NewInputFile (const char* Name);
 /* Open a new input file */