diff --git a/Engine/source/console/torquescript/CMDgram.y b/Engine/source/console/torquescript/CMDgram.y index 5b439c590..59dc27778 100644 --- a/Engine/source/console/torquescript/CMDgram.y +++ b/Engine/source/console/torquescript/CMDgram.y @@ -23,7 +23,7 @@ int outtext(char *fmt, ...); extern int serrors; -extern char linebuf[512]; +extern Vector lines; #define nil 0 #undef YY_ARGS @@ -645,11 +645,15 @@ yyreport_syntax_error (const yypcontext_t *ctx) output += String::ToString("%s %s", i == 0 ? ": expected" : "or", yysymbol_name(expected[i])); } - if (dStrlen(linebuf) > 1) + if (lines.size() > 0) { - output += "\n"; - output += String::ToString("%5d | %s\n", loc->first_line, linebuf); - output += String::ToString("%5s | %*s", "", loc->first_column, "^"); + output += "\n"; + for (int i = 0; i < lines.size(); i++) + { + int line = 10 - i; + output += String::ToString("%5d | ", loc->first_line - (line-1)) + lines[i] + "\n"; + } + output += String::ToString("%5s | %*s", "", loc->first_column, "^"); } yyerror(output.c_str()); diff --git a/Engine/source/console/torquescript/CMDscan.cpp b/Engine/source/console/torquescript/CMDscan.cpp index 044246d12..ccf1aacb5 100644 --- a/Engine/source/console/torquescript/CMDscan.cpp +++ b/Engine/source/console/torquescript/CMDscan.cpp @@ -951,7 +951,7 @@ static int Sc_ScanIdent(); #define FLEX_DEBUG 0 #endif -char linebuf[512]; +Vector lines; // Install our own input code... #undef CMDgetc @@ -1301,166 +1301,172 @@ case 5: /* rule 5 can match eol */ YY_RULE_SETUP #line 120 "CMDscan.l" -{ yycolumn = 1; dStrcpy(linebuf, yytext + 1, sizeof(linebuf)); yyless(1); } +{ yycolumn = 1; + lines.push_back(String::ToString("%s", yytext+1)); + if (lines.size() > Con::getIntVariable("$scriptErrorLineCount", 10)) + lines.erase(lines.begin()); + + yyless(1); +} YY_BREAK case 6: YY_RULE_SETUP -#line 121 "CMDscan.l" +#line 127 "CMDscan.l" { return(Sc_ScanString(STRATOM)); } YY_BREAK case 7: YY_RULE_SETUP -#line 122 "CMDscan.l" +#line 128 "CMDscan.l" { return(Sc_ScanString(TAGATOM)); } YY_BREAK case 8: YY_RULE_SETUP -#line 123 "CMDscan.l" +#line 129 "CMDscan.l" { CMDlval.i = MakeToken< int >( opEQ, yylineno ); return opEQ; } YY_BREAK case 9: YY_RULE_SETUP -#line 124 "CMDscan.l" +#line 130 "CMDscan.l" { CMDlval.i = MakeToken< int >( opNE, yylineno ); return opNE; } YY_BREAK case 10: YY_RULE_SETUP -#line 125 "CMDscan.l" +#line 131 "CMDscan.l" { CMDlval.i = MakeToken< int >( opGE, yylineno ); return opGE; } YY_BREAK case 11: YY_RULE_SETUP -#line 126 "CMDscan.l" +#line 132 "CMDscan.l" { CMDlval.i = MakeToken< int >( opLE, yylineno ); return opLE; } YY_BREAK case 12: YY_RULE_SETUP -#line 127 "CMDscan.l" +#line 133 "CMDscan.l" { CMDlval.i = MakeToken< int >( opAND, yylineno ); return opAND; } YY_BREAK case 13: YY_RULE_SETUP -#line 128 "CMDscan.l" +#line 134 "CMDscan.l" { CMDlval.i = MakeToken< int >( opOR, yylineno ); return opOR; } YY_BREAK case 14: YY_RULE_SETUP -#line 129 "CMDscan.l" +#line 135 "CMDscan.l" { CMDlval.i = MakeToken< int >( opCOLONCOLON, yylineno ); return opCOLONCOLON; } YY_BREAK case 15: YY_RULE_SETUP -#line 130 "CMDscan.l" +#line 136 "CMDscan.l" { CMDlval.i = MakeToken< int >( opMINUSMINUS, yylineno ); return opMINUSMINUS; } YY_BREAK case 16: YY_RULE_SETUP -#line 131 "CMDscan.l" +#line 137 "CMDscan.l" { CMDlval.i = MakeToken< int >( opPLUSPLUS, yylineno ); return opPLUSPLUS; } YY_BREAK case 17: YY_RULE_SETUP -#line 132 "CMDscan.l" +#line 138 "CMDscan.l" { CMDlval.i = MakeToken< int >( opSTREQ, yylineno ); return opSTREQ; } YY_BREAK case 18: YY_RULE_SETUP -#line 133 "CMDscan.l" +#line 139 "CMDscan.l" { CMDlval.i = MakeToken< int >( opSTRNE, yylineno ); return opSTRNE; } YY_BREAK case 19: YY_RULE_SETUP -#line 134 "CMDscan.l" +#line 140 "CMDscan.l" { CMDlval.i = MakeToken< int >( opSHL, yylineno ); return opSHL; } YY_BREAK case 20: YY_RULE_SETUP -#line 135 "CMDscan.l" +#line 141 "CMDscan.l" { CMDlval.i = MakeToken< int >( opSHR, yylineno ); return opSHR; } YY_BREAK case 21: YY_RULE_SETUP -#line 136 "CMDscan.l" +#line 142 "CMDscan.l" { CMDlval.i = MakeToken< int >( opPLASN, yylineno ); return opPLASN; } YY_BREAK case 22: YY_RULE_SETUP -#line 137 "CMDscan.l" +#line 143 "CMDscan.l" { CMDlval.i = MakeToken< int >( opMIASN, yylineno ); return opMIASN; } YY_BREAK case 23: YY_RULE_SETUP -#line 138 "CMDscan.l" +#line 144 "CMDscan.l" { CMDlval.i = MakeToken< int >( opMLASN, yylineno ); return opMLASN; } YY_BREAK case 24: YY_RULE_SETUP -#line 139 "CMDscan.l" +#line 145 "CMDscan.l" { CMDlval.i = MakeToken< int >( opDVASN, yylineno ); return opDVASN; } YY_BREAK case 25: YY_RULE_SETUP -#line 140 "CMDscan.l" +#line 146 "CMDscan.l" { CMDlval.i = MakeToken< int >( opMODASN, yylineno ); return opMODASN; } YY_BREAK case 26: YY_RULE_SETUP -#line 141 "CMDscan.l" +#line 147 "CMDscan.l" { CMDlval.i = MakeToken< int >( opANDASN, yylineno ); return opANDASN; } YY_BREAK case 27: YY_RULE_SETUP -#line 142 "CMDscan.l" +#line 148 "CMDscan.l" { CMDlval.i = MakeToken< int >( opXORASN, yylineno ); return opXORASN; } YY_BREAK case 28: YY_RULE_SETUP -#line 143 "CMDscan.l" +#line 149 "CMDscan.l" { CMDlval.i = MakeToken< int >( opORASN, yylineno ); return opORASN; } YY_BREAK case 29: YY_RULE_SETUP -#line 144 "CMDscan.l" +#line 150 "CMDscan.l" { CMDlval.i = MakeToken< int >( opSLASN, yylineno ); return opSLASN; } YY_BREAK case 30: YY_RULE_SETUP -#line 145 "CMDscan.l" +#line 151 "CMDscan.l" { CMDlval.i = MakeToken< int >( opSRASN, yylineno ); return opSRASN; } YY_BREAK case 31: YY_RULE_SETUP -#line 146 "CMDscan.l" +#line 152 "CMDscan.l" { CMDlval.i = MakeToken< int >( opINTNAME, yylineno ); return opINTNAME; } YY_BREAK case 32: YY_RULE_SETUP -#line 147 "CMDscan.l" +#line 153 "CMDscan.l" { CMDlval.i = MakeToken< int >( opINTNAMER, yylineno ); return opINTNAMER; } YY_BREAK case 33: YY_RULE_SETUP -#line 148 "CMDscan.l" +#line 154 "CMDscan.l" { CMDlval.i = MakeToken< int >( '\n', yylineno ); return '@'; } YY_BREAK case 34: YY_RULE_SETUP -#line 149 "CMDscan.l" +#line 155 "CMDscan.l" { CMDlval.i = MakeToken< int >( '\t', yylineno ); return '@'; } YY_BREAK case 35: YY_RULE_SETUP -#line 150 "CMDscan.l" +#line 156 "CMDscan.l" { CMDlval.i = MakeToken< int >( ' ', yylineno ); return '@'; } YY_BREAK case 36: YY_RULE_SETUP -#line 151 "CMDscan.l" +#line 157 "CMDscan.l" { CMDlval.i = MakeToken< int >( 0, yylineno ); return '@'; } YY_BREAK case 37: YY_RULE_SETUP -#line 152 "CMDscan.l" +#line 158 "CMDscan.l" { /* this comment stops syntax highlighting from getting messed up when editing the lexer in TextPad */ int c = 0, l; for ( ; ; ) @@ -1482,222 +1488,222 @@ YY_RULE_SETUP } YY_BREAK case 38: -#line 172 "CMDscan.l" -case 39: -#line 173 "CMDscan.l" -case 40: -#line 174 "CMDscan.l" -case 41: -#line 175 "CMDscan.l" -case 42: -#line 176 "CMDscan.l" -case 43: -#line 177 "CMDscan.l" -case 44: #line 178 "CMDscan.l" -case 45: +case 39: #line 179 "CMDscan.l" -case 46: +case 40: #line 180 "CMDscan.l" -case 47: +case 41: #line 181 "CMDscan.l" -case 48: +case 42: #line 182 "CMDscan.l" -case 49: +case 43: #line 183 "CMDscan.l" -case 50: +case 44: #line 184 "CMDscan.l" -case 51: +case 45: #line 185 "CMDscan.l" -case 52: +case 46: #line 186 "CMDscan.l" -case 53: +case 47: #line 187 "CMDscan.l" -case 54: +case 48: #line 188 "CMDscan.l" -case 55: +case 49: #line 189 "CMDscan.l" -case 56: +case 50: #line 190 "CMDscan.l" -case 57: +case 51: #line 191 "CMDscan.l" -case 58: +case 52: #line 192 "CMDscan.l" -case 59: +case 53: #line 193 "CMDscan.l" -case 60: +case 54: #line 194 "CMDscan.l" +case 55: +#line 195 "CMDscan.l" +case 56: +#line 196 "CMDscan.l" +case 57: +#line 197 "CMDscan.l" +case 58: +#line 198 "CMDscan.l" +case 59: +#line 199 "CMDscan.l" +case 60: +#line 200 "CMDscan.l" case 61: YY_RULE_SETUP -#line 194 "CMDscan.l" +#line 200 "CMDscan.l" { CMDlval.i = MakeToken< int >( CMDtext[ 0 ], yylineno ); return CMDtext[ 0 ]; } YY_BREAK case 62: YY_RULE_SETUP -#line 195 "CMDscan.l" +#line 201 "CMDscan.l" { CMDlval.i = MakeToken< int >( rwIN, yylineno ); return(rwIN); } YY_BREAK case 63: YY_RULE_SETUP -#line 196 "CMDscan.l" +#line 202 "CMDscan.l" { CMDlval.i = MakeToken< int >( rwCASEOR, yylineno ); return(rwCASEOR); } YY_BREAK case 64: YY_RULE_SETUP -#line 197 "CMDscan.l" +#line 203 "CMDscan.l" { CMDlval.i = MakeToken< int >( rwBREAK, yylineno ); return(rwBREAK); } YY_BREAK case 65: YY_RULE_SETUP -#line 198 "CMDscan.l" +#line 204 "CMDscan.l" { CMDlval.i = MakeToken< int >( rwRETURN, yylineno ); return(rwRETURN); } YY_BREAK case 66: YY_RULE_SETUP -#line 199 "CMDscan.l" +#line 205 "CMDscan.l" { CMDlval.i = MakeToken< int >( rwELSE, yylineno ); return(rwELSE); } YY_BREAK case 67: YY_RULE_SETUP -#line 200 "CMDscan.l" +#line 206 "CMDscan.l" { CMDlval.i = MakeToken< int >( rwASSERT, yylineno ); return(rwASSERT); } YY_BREAK case 68: YY_RULE_SETUP -#line 201 "CMDscan.l" +#line 207 "CMDscan.l" { CMDlval.i = MakeToken< int >( rwWHILE, yylineno ); return(rwWHILE); } YY_BREAK case 69: YY_RULE_SETUP -#line 202 "CMDscan.l" +#line 208 "CMDscan.l" { CMDlval.i = MakeToken< int >( rwDO, yylineno ); return(rwDO); } YY_BREAK case 70: YY_RULE_SETUP -#line 203 "CMDscan.l" +#line 209 "CMDscan.l" { CMDlval.i = MakeToken< int >( rwIF, yylineno ); return(rwIF); } YY_BREAK case 71: YY_RULE_SETUP -#line 204 "CMDscan.l" +#line 210 "CMDscan.l" { CMDlval.i = MakeToken< int >( rwFOREACHSTR, yylineno ); return(rwFOREACHSTR); } YY_BREAK case 72: YY_RULE_SETUP -#line 205 "CMDscan.l" +#line 211 "CMDscan.l" { CMDlval.i = MakeToken< int >( rwFOREACH, yylineno ); return(rwFOREACH); } YY_BREAK case 73: YY_RULE_SETUP -#line 206 "CMDscan.l" +#line 212 "CMDscan.l" { CMDlval.i = MakeToken< int >( rwFOR, yylineno ); return(rwFOR); } YY_BREAK case 74: YY_RULE_SETUP -#line 207 "CMDscan.l" +#line 213 "CMDscan.l" { CMDlval.i = MakeToken< int >( rwCONTINUE, yylineno ); return(rwCONTINUE); } YY_BREAK case 75: YY_RULE_SETUP -#line 208 "CMDscan.l" +#line 214 "CMDscan.l" { CMDlval.i = MakeToken< int >( rwDEFINE, yylineno ); return(rwDEFINE); } YY_BREAK case 76: YY_RULE_SETUP -#line 209 "CMDscan.l" +#line 215 "CMDscan.l" { CMDlval.i = MakeToken< int >( rwDECLARE, yylineno ); return(rwDECLARE); } YY_BREAK case 77: YY_RULE_SETUP -#line 210 "CMDscan.l" +#line 216 "CMDscan.l" { CMDlval.i = MakeToken< int >( rwDECLARESINGLETON, yylineno ); return(rwDECLARESINGLETON); } YY_BREAK case 78: YY_RULE_SETUP -#line 211 "CMDscan.l" +#line 217 "CMDscan.l" { CMDlval.i = MakeToken< int >( rwDATABLOCK, yylineno ); return(rwDATABLOCK); } YY_BREAK case 79: YY_RULE_SETUP -#line 212 "CMDscan.l" +#line 218 "CMDscan.l" { CMDlval.i = MakeToken< int >( rwCASE, yylineno ); return(rwCASE); } YY_BREAK case 80: YY_RULE_SETUP -#line 213 "CMDscan.l" +#line 219 "CMDscan.l" { CMDlval.i = MakeToken< int >( rwSWITCHSTR, yylineno ); return(rwSWITCHSTR); } YY_BREAK case 81: YY_RULE_SETUP -#line 214 "CMDscan.l" +#line 220 "CMDscan.l" { CMDlval.i = MakeToken< int >( rwSWITCH, yylineno ); return(rwSWITCH); } YY_BREAK case 82: YY_RULE_SETUP -#line 215 "CMDscan.l" +#line 221 "CMDscan.l" { CMDlval.i = MakeToken< int >( rwDEFAULT, yylineno ); return(rwDEFAULT); } YY_BREAK case 83: YY_RULE_SETUP -#line 216 "CMDscan.l" +#line 222 "CMDscan.l" { CMDlval.i = MakeToken< int >( rwPACKAGE, yylineno ); return(rwPACKAGE); } YY_BREAK case 84: YY_RULE_SETUP -#line 217 "CMDscan.l" +#line 223 "CMDscan.l" { CMDlval.i = MakeToken< int >( rwNAMESPACE, yylineno ); return(rwNAMESPACE); } YY_BREAK case 85: YY_RULE_SETUP -#line 218 "CMDscan.l" +#line 224 "CMDscan.l" { CMDlval.i = MakeToken< int >( 1, yylineno ); return INTCONST; } YY_BREAK case 86: YY_RULE_SETUP -#line 219 "CMDscan.l" +#line 225 "CMDscan.l" { CMDlval.i = MakeToken< int >( 0, yylineno ); return INTCONST; } YY_BREAK case 87: YY_RULE_SETUP -#line 220 "CMDscan.l" +#line 226 "CMDscan.l" { return(Sc_ScanVar()); } YY_BREAK case 88: YY_RULE_SETUP -#line 222 "CMDscan.l" +#line 228 "CMDscan.l" { return Sc_ScanIdent(); } YY_BREAK case 89: YY_RULE_SETUP -#line 223 "CMDscan.l" +#line 229 "CMDscan.l" return(Sc_ScanHex()); YY_BREAK case 90: YY_RULE_SETUP -#line 224 "CMDscan.l" +#line 230 "CMDscan.l" { CMDtext[CMDleng] = 0; CMDlval.i = MakeToken< int >( dAtoi(CMDtext), yylineno ); return INTCONST; } YY_BREAK case 91: YY_RULE_SETUP -#line 225 "CMDscan.l" +#line 231 "CMDscan.l" return Sc_ScanNum(); YY_BREAK case 92: YY_RULE_SETUP -#line 226 "CMDscan.l" +#line 232 "CMDscan.l" return(ILLEGAL_TOKEN); YY_BREAK case 93: YY_RULE_SETUP -#line 227 "CMDscan.l" +#line 233 "CMDscan.l" return(ILLEGAL_TOKEN); YY_BREAK case 94: YY_RULE_SETUP -#line 228 "CMDscan.l" +#line 234 "CMDscan.l" ECHO; YY_BREAK -#line 1700 "CMDscan.cpp" +#line 1706 "CMDscan.cpp" case YY_STATE_EOF(INITIAL): yyterminate(); @@ -2673,7 +2679,7 @@ void yyfree (void * ptr ) #define YYTABLES_NAME "yytables" -#line 228 "CMDscan.l" +#line 234 "CMDscan.l" static const char *scanBuffer; diff --git a/Engine/source/console/torquescript/CMDscan.l b/Engine/source/console/torquescript/CMDscan.l index 1c9f23b44..57e8f0b3f 100644 --- a/Engine/source/console/torquescript/CMDscan.l +++ b/Engine/source/console/torquescript/CMDscan.l @@ -55,7 +55,7 @@ static int Sc_ScanIdent(); #define FLEX_DEBUG 0 #endif -char linebuf[512]; +Vector lines; // Install our own input code... #undef CMDgetc @@ -116,7 +116,13 @@ HEXDIGIT [a-fA-F0-9] ("///"([^/\n\r][^\n\r]*)?[\n\r]+)+ { return(Sc_ScanDocBlock()); } "//"[^\n\r]* ; [\r] ; -\n.* { yycolumn = 1; dStrcpy(linebuf, yytext + 1, sizeof(linebuf)); yyless(1); } +\n.* { yycolumn = 1; + lines.push_back(String::ToString("%s", yytext+1)); + if (lines.size() > Con::getIntVariable("$scriptErrorLineCount", 10)) + lines.erase(lines.begin()); + + yyless(1); +} \"(\\.|[^\\"\n\r])*\" { return(Sc_ScanString(STRATOM)); } \'(\\.|[^\\'\n\r])*\' { return(Sc_ScanString(TAGATOM)); } "==" { CMDlval.i = MakeToken< int >( opEQ, yylineno ); return opEQ; } diff --git a/Engine/source/console/torquescript/cmdgram.cpp b/Engine/source/console/torquescript/cmdgram.cpp index 0536bbbca..05ec8947e 100644 --- a/Engine/source/console/torquescript/cmdgram.cpp +++ b/Engine/source/console/torquescript/cmdgram.cpp @@ -98,7 +98,7 @@ int outtext(char *fmt, ...); extern int serrors; -extern char linebuf[512]; +extern Vector lines; #define nil 0 #undef YY_ARGS @@ -3352,11 +3352,15 @@ yyreport_syntax_error (const yypcontext_t *ctx) output += String::ToString("%s %s", i == 0 ? ": expected" : "or", yysymbol_name(expected[i])); } - if (dStrlen(linebuf) > 1) + if (lines.size() > 0) { - output += "\n"; - output += String::ToString("%5d | %s\n", loc->first_line, linebuf); - output += String::ToString("%5s | %*s", "", loc->first_column, "^"); + output += "\n"; + for (int i = 0; i < lines.size(); i++) + { + int line = 10 - i; + output += String::ToString("%5d | ", loc->first_line - (line-1)) + lines[i] + "\n"; + } + output += String::ToString("%5s | %*s", "", loc->first_column, "^"); } yyerror(output.c_str());