2 //**************************************************************************
\r
6 //**************************************************************************
\r
8 // HEADER FILES ------------------------------------------------------------
\r
19 // MACROS ------------------------------------------------------------------
\r
21 #define ERROR_FILE_NAME "acs.err"
\r
23 // TYPES -------------------------------------------------------------------
\r
31 // EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
\r
33 // PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
\r
35 // PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
\r
37 static char *ErrorText(error_t error);
\r
38 static char *ErrorFileName(void);
\r
39 static void eprintf(const char *fmt, ...);
\r
40 static void veprintf(const char *fmt, va_list args);
\r
42 // EXTERNAL DATA DECLARATIONS ----------------------------------------------
\r
44 extern char acs_SourceFileName[MAX_FILE_NAME_LENGTH];
\r
46 // PUBLIC DATA DEFINITIONS -------------------------------------------------
\r
48 // PRIVATE DATA DEFINITIONS ------------------------------------------------
\r
56 { ERR_MISSING_SEMICOLON, "Missing semicolon." },
\r
57 { ERR_MISSING_LPAREN, "Missing '('." },
\r
58 { ERR_MISSING_RPAREN, "Missing ')'." },
\r
59 { ERR_MISSING_LBRACE, "Missing '{'." },
\r
60 { ERR_MISSING_SCRIPT_NUMBER, "Missing script number." },
\r
61 { ERR_IDENTIFIER_TOO_LONG, "Identifier too long." },
\r
62 { ERR_STRING_TOO_LONG, "String too long." },
\r
63 { ERR_FILE_NAME_TOO_LONG, "File name too long.\nFile: \"%s\"" },
\r
64 { ERR_BAD_CHARACTER, "Bad character in script text." },
\r
65 { ERR_BAD_CHARACTER_CONSTANT, "Bad character constant in script text." },
\r
66 { ERR_ALLOC_PCODE_BUFFER, "Failed to allocate PCODE buffer." },
\r
67 { ERR_PCODE_BUFFER_OVERFLOW, "PCODE buffer overflow." },
\r
68 { ERR_TOO_MANY_SCRIPTS, "Too many scripts." },
\r
69 { ERR_TOO_MANY_FUNCTIONS, "Too many functions." },
\r
70 { ERR_SAVE_OBJECT_FAILED, "Couldn't save object file." },
\r
71 { ERR_MISSING_LPAREN_SCR, "Missing '(' in script definition." },
\r
72 { ERR_INVALID_IDENTIFIER, "Invalid identifier." },
\r
73 { ERR_REDEFINED_IDENTIFIER, "%s : Redefined identifier." },
\r
74 { ERR_MISSING_COMMA, "Missing comma." },
\r
75 { ERR_BAD_VAR_TYPE, "Invalid variable type." },
\r
76 { ERR_BAD_RETURN_TYPE, "Invalid return type." },
\r
77 { ERR_TOO_MANY_SCRIPT_ARGS, "Too many script arguments." },
\r
78 { ERR_MISSING_LBRACE_SCR, "Missing opening '{' in script definition." },
\r
79 { ERR_MISSING_RBRACE_SCR, "Missing closing '}' in script definition." },
\r
80 { ERR_TOO_MANY_MAP_VARS, "Too many map variables." },
\r
81 { ERR_TOO_MANY_SCRIPT_VARS, "Too many script variables." },
\r
82 { ERR_TOO_MANY_FUNCTION_VARS, "Too many function variables." },
\r
83 { ERR_MISSING_WVAR_INDEX, "Missing index in world variable declaration." },
\r
84 { ERR_MISSING_GVAR_INDEX, "Missing index in global variable declaration." },
\r
85 { ERR_BAD_WVAR_INDEX, "World variable index out of range." },
\r
86 { ERR_MISSING_WVAR_COLON, "Missing colon in world variable declaration." },
\r
87 { ERR_MISSING_GVAR_COLON, "Missing colon in global variable declaration." },
\r
88 { ERR_MISSING_SPEC_VAL, "Missing value in special declaration." },
\r
89 { ERR_MISSING_SPEC_COLON, "Missing colon in special declaration." },
\r
90 { ERR_MISSING_SPEC_ARGC, "Missing argument count in special declaration." },
\r
91 { ERR_CANT_READ_FILE, "Couldn't read file.\nFile: \"%s\"" },
\r
92 { ERR_CANT_OPEN_FILE, "Couldn't open file.\nFile: \"%s\"" },
\r
93 { ERR_CANT_OPEN_DBGFILE, "Couldn't open debug file." },
\r
94 { ERR_INVALID_DIRECTIVE, "Invalid directive." },
\r
95 { ERR_BAD_DEFINE, "Non-numeric constant found in #define." },
\r
96 { ERR_INCL_NESTING_TOO_DEEP, "Include nesting too deep.\nUnable to include file \"%s\"." },
\r
97 { ERR_STRING_LIT_NOT_FOUND, "String literal not found." },
\r
98 { ERR_INVALID_DECLARATOR, "Invalid declarator." },
\r
99 { ERR_BAD_LSPEC_ARG_COUNT, "Incorrect number of special arguments." },
\r
100 { ERR_BAD_ARG_COUNT, "Incorrect number of arguments." },
\r
101 { ERR_UNKNOWN_IDENTIFIER, "%s : Identifier has not been declared." },
\r
102 { ERR_MISSING_COLON, "Missing colon." },
\r
103 { ERR_BAD_EXPR, "Syntax error in expression." },
\r
104 { ERR_BAD_CONST_EXPR, "Syntax error in constant expression." },
\r
105 { ERR_NO_DIRECT_VER, "Internal function has no direct version." },
\r
106 { ERR_ILLEGAL_EXPR_IDENT, "%s : Illegal identifier in expression." },
\r
107 { ERR_EXPR_FUNC_NO_RET_VAL, "Function call in expression has no return value." },
\r
108 { ERR_MISSING_ASSIGN_OP, "Missing assignment operator." },
\r
109 { ERR_INCDEC_OP_ON_NON_VAR, "'++' or '--' used on a non-variable." },
\r
110 { ERR_MISSING_RBRACE, "Missing '}' at end of compound statement." },
\r
111 { ERR_INVALID_STATEMENT, "Invalid statement." },
\r
112 { ERR_BAD_DO_STATEMENT, "Do statement not followed by 'while' or 'until'." },
\r
113 { ERR_BAD_SCRIPT_DECL, "Bad script declaration." },
\r
114 { ERR_CASE_OVERFLOW, "Internal Error: Case stack overflow." },
\r
115 { ERR_BREAK_OVERFLOW, "Internal Error: Break stack overflow." },
\r
116 { ERR_CONTINUE_OVERFLOW, "Internal Error: Continue stack overflow." },
\r
117 { ERR_STATEMENT_OVERFLOW, "Internal Error: Statement overflow." },
\r
118 { ERR_MISPLACED_BREAK, "Misplaced BREAK statement." },
\r
119 { ERR_MISPLACED_CONTINUE, "Misplaced CONTINUE statement." },
\r
120 { ERR_CASE_NOT_IN_SWITCH, "CASE must appear in switch statement." },
\r
121 { ERR_DEFAULT_NOT_IN_SWITCH, "DEFAULT must appear in switch statement." },
\r
122 { ERR_MULTIPLE_DEFAULT, "Only 1 DEFAULT per switch allowed." },
\r
123 { ERR_EXPR_STACK_OVERFLOW, "Expression stack overflow." },
\r
124 { ERR_EXPR_STACK_EMPTY, "Tried to POP empty expression stack." },
\r
125 { ERR_UNKNOWN_CONST_EXPR_PCD, "Unknown PCD in constant expression." },
\r
126 { ERR_BAD_RADIX_CONSTANT, "Radix out of range in integer constant." },
\r
127 { ERR_BAD_ASSIGNMENT, "Syntax error in multiple assignment statement." },
\r
128 { ERR_OUT_OF_MEMORY, "Out of memory." },
\r
129 { ERR_TOO_MANY_STRINGS, "Too many strings. Current max is %d" },
\r
130 { ERR_UNKNOWN_PRTYPE, "Unknown cast type in print statement." },
\r
131 { ERR_SCRIPT_OUT_OF_RANGE, "Script number must be between 1 and 999." },
\r
132 { ERR_MISSING_PARAM, "Missing required argument." },
\r
133 { ERR_SCRIPT_ALREADY_DEFINED, "Script already has a body." },
\r
134 { ERR_FUNCTION_ALREADY_DEFINED, "Function already has a body." },
\r
135 { ERR_PARM_MUST_BE_VAR, "Parameter must be a variable." },
\r
136 { ERR_LANGCODE_SIZE, "Language code must be 2 or 3 characters long." },
\r
137 { ERR_MISSING_LBRACE_LOC, "Missing opening '{' in localization definition." },
\r
138 { ERR_MISSING_RBRACE_LOC, "Missing closing '}' in localization definition." },
\r
139 { ERR_MISSING_LOCALIZED, "Missing localized string." },
\r
140 { ERR_BAD_LANGCODE, "Language code must be all letters." },
\r
141 { ERR_MISSING_LANGCODE, "Missing language code in localization definiton." },
\r
142 { ERR_MISSING_FONT_NAME, "Missing font name." },
\r
143 { ERR_MISSING_LBRACE_FONTS, "Missing opening '{' in font list." },
\r
144 { ERR_MISSING_RBRACE_FONTS, "Missing closing '}' in font list." },
\r
145 { ERR_NOCOMPACT_NOT_HERE, "#nocompact must appear before any scripts." },
\r
146 { ERR_MISSING_ASSIGN, "Missing '='." },
\r
147 { ERR_PREVIOUS_NOT_VOID, "Previous use of function expected a return value." },
\r
148 { ERR_MUST_RETURN_A_VALUE, "Function must return a value." },
\r
149 { ERR_MUST_NOT_RETURN_A_VALUE, "Void functions cannot return a value." },
\r
150 { ERR_SUSPEND_IN_FUNCTION, "Suspend cannot be used inside a function." },
\r
151 { ERR_TERMINATE_IN_FUNCTION, "Terminate cannot be used inside a function." },
\r
152 { ERR_RESTART_IN_FUNCTION, "Restart cannot be used inside a function." },
\r
153 { ERR_RETURN_OUTSIDE_FUNCTION, "Return can only be used inside a function." },
\r
154 { ERR_FUNC_ARGUMENT_COUNT, "Function %s should have %d argument%s." },
\r
155 { ERR_EOF, "Unexpected end of file." },
\r
156 { ERR_UNDEFINED_FUNC, "Function %s is used but not defined." },
\r
157 { ERR_TOO_MANY_ARRAY_DIMS, "Too many array dimensions." },
\r
158 { ERR_MISSING_LBRACKET, "Missing '['." },
\r
159 { ERR_MISSING_RBRACKET, "Missing ']'." },
\r
160 { ERR_ZERO_DIMENSION, "Arrays cannot have a dimension of zero." },
\r
161 { ERR_TOO_MANY_DIM_USED, "%s only has %d dimensions." },
\r
162 { ERR_ARRAY_MAPVAR_ONLY, "Only map variables can be arrays." },
\r
163 { ERR_NOT_AN_ARRAY, "%s is not an array." },
\r
164 { ERR_MISSING_LBRACE_ARR, "Missing opening '{' in array initializer." },
\r
165 { ERR_MISSING_RBRACE_ARR, "Missing closing '}' in array initializer." },
\r
166 { ERR_LATENT_IN_FUNC, "Latent functions cannot be used inside functions." },
\r
167 { ERR_LOCAL_VAR_SHADOWED, "A global identifier already has this name." },
\r
168 { ERR_MULTIPLE_IMPORTS, "You can only #import one file." },
\r
169 { ERR_IMPORT_IN_EXPORT, "You cannot #import from inside an imported file." },
\r
170 { ERR_EXPORTER_NOT_FLAGGED, "A file that you #import must have an #imported line." },
\r
171 { ERR_TOO_MANY_IMPORTS, "Too many files imported." },
\r
172 { ERR_NO_NEED_ARRAY_SIZE, "Only map arrays need a size." },
\r
173 { ERR_NO_MULTIDIMENSIONS, "Only map arrays can have more than one dimension." },
\r
174 { ERR_NEED_ARRAY_SIZE, "Missing array size." },
\r
175 { ERR_DISCONNECT_NEEDS_1_ARG, "Disconnect scripts must have 1 argument." },
\r
176 { ERR_UNCLOSED_WITH_ARGS, "Most special scripts must not have arguments." },
\r
177 { ERR_NOT_A_CHAR_ARRAY, "%s has %d dimensions. Use %d subscripts to get a char array." },
\r
181 static FILE *ErrorFile;
\r
182 static int ErrorCount;
\r
183 static errorInfo_e ErrorFormat;
\r
184 static char *ErrorSourceName;
\r
185 static int ErrorSourceLine;
\r
187 // CODE --------------------------------------------------------------------
\r
189 //==========================================================================
\r
193 //==========================================================================
\r
195 void ERR_ErrorAt(char *source, int line)
\r
197 ErrorSourceName = source;
\r
198 ErrorSourceLine = line;
\r
201 //==========================================================================
\r
205 //==========================================================================
\r
207 void ERR_Error(error_t error, boolean info, ...)
\r
210 va_start(args, info);
\r
211 ERR_ErrorV(error, info, args);
\r
215 //==========================================================================
\r
219 //==========================================================================
\r
221 void ERR_Exit(error_t error, boolean info, ...)
\r
224 va_start(args, info);
\r
225 ERR_ErrorV(error, info, args);
\r
230 //==========================================================================
\r
234 //==========================================================================
\r
236 void ERR_Finish(void)
\r
249 //==========================================================================
\r
253 //==========================================================================
\r
255 void ERR_ErrorV(error_t error, boolean info, va_list args)
\r
258 boolean showLine = NO;
\r
259 static boolean showedInfo = NO;
\r
263 ErrorFile = fopen(ErrorFileName(), "w");
\r
265 if(ErrorCount == 0)
\r
267 fprintf(stderr, "\n**** ERROR ****\n");
\r
269 else if(ErrorCount == 100)
\r
271 eprintf("More than 100 errors. Can't continue.\n");
\r
280 if(ErrorSourceName)
\r
282 source = ErrorSourceName;
\r
283 line = ErrorSourceLine;
\r
284 ErrorSourceName = NULL;
\r
288 source = tk_SourceName;
\r
292 if(showedInfo == NO)
\r
293 { // Output info compatible with older ACCs
\r
294 // for editors that expect it.
\r
296 eprintf("Line %d in file \"%s\" ...\n", line, source);
\r
298 if(ErrorFormat == ERRINFO_GCC)
\r
300 eprintf("%s:%d: ", source, line);
\r
304 eprintf("%s(%d) : ", source, line);
\r
305 if(error != ERR_NONE)
\r
307 eprintf("error %04d: ", error);
\r
311 if(error != ERR_NONE)
\r
313 text = ErrorText(error);
\r
316 veprintf(text, args);
\r
321 // deal with master source line and position indicator - Ty 07jan2000
\r
322 MasterSourceLine[MasterSourcePos] = '\0'; // pre-incremented already
\r
323 eprintf("> %s\n", MasterSourceLine); // the string
\r
324 eprintf(">%*s\n", MasterSourcePos, "^"); // pointer to error
\r
331 va_start(va_arg(args,char*), args2);
\r
332 veprintf(va_arg(args,char*), args2);
\r
338 //==========================================================================
\r
340 // ERR_RemoveErrorFile
\r
342 //==========================================================================
\r
344 void ERR_RemoveErrorFile(void)
\r
346 remove(ErrorFileName());
\r
349 //==========================================================================
\r
351 // ERR_ErrorFileName
\r
353 //==========================================================================
\r
355 static char *ErrorFileName(void)
\r
357 static char errFileName[MAX_FILE_NAME_LENGTH];
\r
359 strcpy(errFileName, acs_SourceFileName);
\r
360 if(MS_StripFilename(errFileName) == NO)
\r
362 strcpy(errFileName, ERROR_FILE_NAME);
\r
366 strcat(errFileName, DIRECTORY_DELIMITER ERROR_FILE_NAME);
\r
368 return errFileName;
\r
371 //==========================================================================
\r
375 //==========================================================================
\r
377 static char *ErrorText(error_t error)
\r
381 for(i = 0; ErrorNames[i].number != ERR_NONE; i++)
\r
383 if(error == ErrorNames[i].number)
\r
385 return ErrorNames[i].name;
\r
391 //==========================================================================
\r
395 //==========================================================================
\r
397 static void eprintf(const char *fmt, ...)
\r
400 va_start(args, fmt);
\r
401 veprintf(fmt, args);
\r
405 //==========================================================================
\r
409 //==========================================================================
\r
411 static void veprintf(const char *fmt, va_list args)
\r
413 vfprintf(stderr, fmt, args);
\r
416 vfprintf(ErrorFile, fmt, args);
\r