| 
					
				 | 
			
			
				@@ -1,3 +1,4 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#include <stdarg.h> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #include <stdio.h> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #include <string.h> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -5,15 +6,21 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #include "Utils.h" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #define TOKEN_BUFFER_LENGTH (1024 * 1024) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#define ERROR_LENGTH 256 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 static char tokenBuffer[TOKEN_BUFFER_LENGTH]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 static int writeIndex = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 static int readIndex = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-static const char* TOO_LONG_LITERAL = "literal is too long"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-static const char* UNKNOWN_CHARACTER = "unknown character"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static int line = 1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 static FILE* file = NULL; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-static const char* error = NULL; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static char error[ERROR_LENGTH] = {'\0'}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static void tError(const char* format, ...) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    va_list args; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    va_start(args, format); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    vsnprintf(error, ERROR_LENGTH, format, args); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    va_end(args); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 static bool tAdd(const void* data, int length) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     if(writeIndex + length > TOKEN_BUFFER_LENGTH) { 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -54,7 +61,7 @@ static bool tParseLiteral(int c) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     buffer[0] = c; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     while(isLetter(tPeek())) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         if(index >= 63) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            error = TOO_LONG_LITERAL; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            tError("literal is too long"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             return false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         buffer[index++] = tRead(); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -84,19 +91,21 @@ static bool tParseToken() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         return tParseNumber(c); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     switch(c) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        case ' ': 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        case '\n': return true; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        case ' ': return true; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        case '\n': line++; return true; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         case '+': return tAddToken(T_ADD); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        case '*': return tAddToken(T_MUL); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         case ';': return tAddToken(T_SEMICOLON); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    error = UNKNOWN_CHARACTER; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    tError("unknown character on line %d: %c", line, c); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     return false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 static void tParseFile() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     readIndex = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     writeIndex = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    error = NULL; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    line = 1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    error[0] = '\0'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     while(tParseToken()) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -104,12 +113,12 @@ static void tParseFile() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 bool tTokenize(const char* path) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     file = fopen(path, "r"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     if(file == NULL) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        error = "cannot read file"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        tError("cannot read file '%s'", path); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         return true; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     tParseFile(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     fclose(file); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    return error != NULL; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    return error[0] != '\0'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 const char* tGetError() { 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -145,6 +154,7 @@ const char* tGetTokenName(Token token) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     switch(token) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         case T_INT: return "int"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         case T_ADD: return "+"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        case T_MUL: return "*"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         case T_PRINT: return "print"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         case T_SEMICOLON: return ";"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         case T_END: return "end"; 
			 |