aboutsummaryrefslogtreecommitdiff
path: root/lib/AsmParser/Lexer.l
diff options
context:
space:
mode:
Diffstat (limited to 'lib/AsmParser/Lexer.l')
-rw-r--r--lib/AsmParser/Lexer.l52
1 files changed, 46 insertions, 6 deletions
diff --git a/lib/AsmParser/Lexer.l b/lib/AsmParser/Lexer.l
index 1f4ea1a6de..761c6b5e62 100644
--- a/lib/AsmParser/Lexer.l
+++ b/lib/AsmParser/Lexer.l
@@ -24,6 +24,8 @@
#include "llvm/Module.h"
#include <list>
#include "llvmAsmParser.h"
+#include <ctype.h>
+#include <stdlib.h>
#define RET_TOK(type, Enum, sym) \
llvmAsmlval.type = Instruction::Enum; return sym
@@ -51,6 +53,34 @@ uint64_t atoull(const char *Buffer) {
}
+// UnEscapeLexed - Run through the specified buffer and change \xx codes to the
+// appropriate character. If AllowNull is set to false, a \00 value will cause
+// an exception to be thrown.
+//
+// If AllowNull is set to true, the return value of the function points to the
+// last character of the string in memory.
+//
+char *UnEscapeLexed(char *Buffer, bool AllowNull = false) {
+ char *BOut = Buffer;
+ for (char *BIn = Buffer; *BIn; ) {
+ if (BIn[0] == '\\' && isxdigit(BIn[1]) && isxdigit(BIn[2])) {
+ char Tmp = BIn[3]; BIn[3] = 0; // Terminate string
+ *BOut = strtol(BIn+1, 0, 16); // Convert to number
+ if (!AllowNull && !*BOut)
+ ThrowException("String literal cannot accept \\00 escape!");
+
+ BIn[3] = Tmp; // Restore character
+ BIn += 3; // Skip over handled chars
+ ++BOut;
+ } else {
+ *BOut++ = *BIn++;
+ }
+ }
+
+ return BOut;
+}
+
+
#define YY_NEVER_INTERACTIVE 1
%}
@@ -95,6 +125,7 @@ false { return FALSE; }
declare { return DECLARE; }
implementation { return IMPLEMENTATION; }
\.\.\. { return DOTDOTDOT; }
+string { return STRING; }
void { llvmAsmlval.TypeVal = Type::VoidTy ; return VOID; }
bool { llvmAsmlval.TypeVal = Type::BoolTy ; return BOOL; }
@@ -148,18 +179,27 @@ store { RET_TOK(MemOpVal, Store, STORE); }
getelementptr { RET_TOK(MemOpVal, GetElementPtr, GETELEMENTPTR); }
-{VarID} { llvmAsmlval.StrVal = strdup(yytext+1); return VAR_ID; }
-{Label} {
+{VarID} {
+ UnEscapeLexed(yytext+1);
+ llvmAsmlval.StrVal = strdup(yytext+1); // Skip %
+ return VAR_ID;
+ }
+{Label} {
yytext[strlen(yytext)-1] = 0; // nuke colon
- llvmAsmlval.StrVal = strdup(yytext);
+ UnEscapeLexed(yytext);
+ llvmAsmlval.StrVal = strdup(yytext);
return LABELSTR;
}
-{StringConstant} {
+{StringConstant} { // Note that we cannot unescape a string constant here! The
+ // string constant might contain a \00 which would not be
+ // understood by the string stuff. It is valid to make a
+ // [sbyte] c"Hello World\00" constant, for example.
+ //
yytext[strlen(yytext)-1] = 0; // nuke end quote
- llvmAsmlval.StrVal = strdup(yytext+1); // Nuke start quote
+ llvmAsmlval.StrVal = strdup(yytext+1); // Nuke start quote
return STRINGCONSTANT;
- }
+ }
{PInteger} { llvmAsmlval.UInt64Val = atoull(yytext); return EUINT64VAL; }