6 #pragma warning (disable : 4786)
\r
7 #endif // NL_OS_WINDOWS
\r
8 #include "nel/misc/config_file.h"
\r
9 #include "nel/misc/common.h"
\r
10 #include "nel/misc/debug.h"
\r
16 using namespace std;
\r
17 using namespace NLMISC;
\r
21 #define YYPARSE_PARAM pvararray
\r
23 // WARNING!!!! DEBUG_PRINTF are commented using // so IT MUST HAVE NO INSTRUCTION AFTER A DEBUG_PRINTF OR THEY LL BE COMMENTED
\r
25 #define DEBUG_PRINTF InfoLog->displayRaw
\r
26 #define DEBUG_PRINT(a) InfoLog->displayRaw(a)
\r
29 #define DEBUG_PRINT(a)
\r
31 #define DEBUG_PRINTF(format, args...)
\r
33 #define DEBUG_PRINTF // InfoLog->displayRaw
\r
39 enum cf_operation { OP_PLUS, OP_MINUS, OP_MULT, OP_DIVIDE, OP_NEG };
\r
43 NLMISC::CConfigFile::CVar::TVarType Type;
\r
51 extern bool cf_Ignore;
\r
53 extern bool LoadRoot;
\r
59 NLMISC::CConfigFile::CVar cf_CurrentVar;
\r
62 char *cf_CurrentFile;
\r
64 bool cf_OverwriteExistingVariable; // setup in the config_file.cpp reparse()
\r
72 cf_value cf_op (cf_value a, cf_value b, cf_operation op);
\r
74 void cf_print (cf_value Val);
\r
76 void cf_setVar (NLMISC::CConfigFile::CVar &Var, cf_value Val);
\r
78 int yyerror (const char *);
\r
88 %token <Val> ADD_ASSIGN ASSIGN VARIABLE STRING SEMICOLON
\r
89 %token <Val> PLUS MINUS MULT DIVIDE
\r
90 %token <Val> RPAREN LPAREN RBRACE LBRACE
\r
91 %token <Val> COMMA INTEGER REAL FILELINE
\r
94 %type <Val> expression
\r
98 %type <Val> exprbrace
\r
99 %type <Val> variable
\r
103 ROOT: instlist | { }
\r
106 instlist: instlist inst { }
\r
110 inst : FILELINE STRING INTEGER
\r
112 DEBUG_PRINTF("Forcing current file %s and line %u\n", $2.String, $3.Int-1);
\r
114 if (cf_CurrentFile != NULL)
\r
115 free(cf_CurrentFile);
\r
116 // store the filename
\r
117 cf_CurrentFile = strdup($2.String);
\r
118 // store the current line minus 1 because the #fileline count for a line
\r
119 cf_CurrentLine = $3.Int-1;
\r
122 inst: VARIABLE ASSIGN expression SEMICOLON
\r
124 DEBUG_PRINTF(" (TYPE %d VARIABLE=", $1.Type);
\r
126 DEBUG_PRINTF("), (TYPE %d VALUE=", $3.Type);
\r
128 DEBUG_PRINT(")\n");
\r
130 // on recherche l'existence de la variable
\r
131 for(i = 0; i < (int)((*((vector<NLMISC::CConfigFile::CVar>*)(YYPARSE_PARAM))).size()); i++)
\r
133 if ((*((vector<NLMISC::CConfigFile::CVar>*)(YYPARSE_PARAM)))[i].Name == $1.String)
\r
135 if (cf_OverwriteExistingVariable || (*((vector<NLMISC::CConfigFile::CVar>*)(YYPARSE_PARAM)))[i].Root || !strcmp($1.String,"RootConfigFilename"))
\r
137 DEBUG_PRINTF("Variable '%s' existe deja, ecrasement\n", $1.String);
\r
142 NLMISC::CConfigFile::CVar Var;
\r
144 Var.Callback = NULL;
\r
145 if (cf_CurrentVar.Comp)
\r
147 DEBUG_PRINTF ("yacc: new assign complex variable '%s'\n", $1.String);
\r
148 Var = cf_CurrentVar;
\r
152 DEBUG_PRINTF ("yacc: new assign normal variable '%s'\n", $1.String);
\r
153 cf_setVar (Var, $3);
\r
155 Var.Name = $1.String;
\r
156 if (i == (int)((*((vector<NLMISC::CConfigFile::CVar>*)(YYPARSE_PARAM))).size ()))
\r
158 // nouvelle variable
\r
159 DEBUG_PRINTF ("yacc: new assign var '%s'\n", $1.String);
\r
160 (*((vector<NLMISC::CConfigFile::CVar>*)(YYPARSE_PARAM))).push_back (Var);
\r
162 else if (cf_OverwriteExistingVariable || (*((vector<NLMISC::CConfigFile::CVar>*)(YYPARSE_PARAM)))[i].Root || !strcmp($1.String,"RootConfigFilename"))
\r
164 // reaffectation d'une variable
\r
165 Var.Callback = (*((vector<NLMISC::CConfigFile::CVar>*)(YYPARSE_PARAM)))[i].Callback;
\r
166 DEBUG_PRINTF ("yacc: reassign var name '%s' type %d\n", Var.Name.c_str(), Var.Type);
\r
167 if (Var != (*((vector<NLMISC::CConfigFile::CVar>*)(YYPARSE_PARAM)))[i] && Var.Callback != NULL)
\r
168 (Var.Callback)(Var);
\r
169 (*((vector<NLMISC::CConfigFile::CVar>*)(YYPARSE_PARAM)))[i] = Var;
\r
173 DEBUG_PRINTF ("yacc: don't reassign var '%s' because the variable already exists\n", $1.String);
\r
176 cf_CurrentVar.IntValues.clear ();
\r
177 cf_CurrentVar.RealValues.clear ();
\r
178 cf_CurrentVar.StrValues.clear ();
\r
179 cf_CurrentVar.Comp = false;
\r
180 cf_CurrentVar.Type = NLMISC::CConfigFile::CVar::T_UNKNOWN;
\r
184 inst: VARIABLE ADD_ASSIGN expression SEMICOLON
\r
186 DEBUG_PRINT(" (VARIABLE+=");
\r
188 DEBUG_PRINT("), (VALUE=");
\r
190 DEBUG_PRINT(")\n");
\r
192 // on recherche l'existence de la variable
\r
193 for(i = 0; i < (int)((*((vector<NLMISC::CConfigFile::CVar>*)(YYPARSE_PARAM))).size()); i++)
\r
195 if ((*((vector<NLMISC::CConfigFile::CVar>*)(YYPARSE_PARAM)))[i].Name == $1.String)
\r
197 DEBUG_PRINTF("Variable '%s' existe deja, ajout\n", $1.String);
\r
201 NLMISC::CConfigFile::CVar Var;
\r
203 Var.Callback = NULL;
\r
204 if (cf_CurrentVar.Comp) Var = cf_CurrentVar;
\r
205 else cf_setVar (Var, $3);
\r
206 Var.Name = $1.String;
\r
207 if (i == (int)((*((vector<NLMISC::CConfigFile::CVar>*)(YYPARSE_PARAM))).size ()))
\r
209 // nouvelle variable
\r
210 DEBUG_PRINTF ("yacc: new add assign var '%s'\n", $1.String);
\r
211 (*((vector<NLMISC::CConfigFile::CVar>*)(YYPARSE_PARAM))).push_back (Var);
\r
215 // reaffectation d'une variable
\r
216 Var.Callback = (*((vector<NLMISC::CConfigFile::CVar>*)(YYPARSE_PARAM)))[i].Callback;
\r
217 DEBUG_PRINTF ("yacc: add assign var '%s'\n", $1.String);
\r
218 if ((*((vector<NLMISC::CConfigFile::CVar>*)(YYPARSE_PARAM)))[i].FromLocalFile)
\r
220 // this var was created in the current cfg, append the new value at the end
\r
221 (*((vector<NLMISC::CConfigFile::CVar>*)(YYPARSE_PARAM)))[i].add(Var);
\r
223 if (Var.size() > 0 && Var.Callback != NULL)
\r
224 (Var.Callback)((*((vector<NLMISC::CConfigFile::CVar>*)(YYPARSE_PARAM)))[i]);
\r
228 // this var has been created in a parent Cfg, append at the beginning of the array
\r
229 Var.add ((*((vector<NLMISC::CConfigFile::CVar>*)(YYPARSE_PARAM)))[i]);
\r
230 if (Var != (*((vector<NLMISC::CConfigFile::CVar>*)(YYPARSE_PARAM)))[i] && Var.Callback != NULL)
\r
231 (Var.Callback)(Var);
\r
232 (*((vector<NLMISC::CConfigFile::CVar>*)(YYPARSE_PARAM)))[i] = Var;
\r
236 cf_CurrentVar.IntValues.clear ();
\r
237 cf_CurrentVar.RealValues.clear ();
\r
238 cf_CurrentVar.StrValues.clear ();
\r
239 cf_CurrentVar.Comp = false;
\r
240 cf_CurrentVar.Type = NLMISC::CConfigFile::CVar::T_UNKNOWN;
\r
244 expression: expr2 { $$ = $1; cf_CurrentVar.Comp = false; DEBUG_PRINT("false\n"); }
\r
245 | LBRACE exprbrace RBRACE { $$ = $2; cf_CurrentVar.Comp = true; DEBUG_PRINT("true\n"); }
\r
246 | LBRACE exprbrace COMMA RBRACE { $$ = $2; cf_CurrentVar.Comp = true; DEBUG_PRINT("true\n"); }
\r
247 | LBRACE RBRACE { $$ = $2; cf_CurrentVar.Comp = true; DEBUG_PRINT("true\n"); }
\r
250 exprbrace: expr2 { $$ = $1; /*cf_CurrentVar.Type = $1.Type;*/ cf_setVar (cf_CurrentVar, $1); }
\r
251 | exprbrace COMMA expr2 { $$ = $3; /*cf_CurrentVar.Type = $3.Type;*/ cf_setVar (cf_CurrentVar, $3); }
\r
254 expr2: expr3 { $$ = $1; }
\r
255 | expr2 PLUS expr3 { $$ = cf_op($1, $3, OP_PLUS); }
\r
256 | expr2 MINUS expr3 { $$ = cf_op($1, $3, OP_MINUS); }
\r
259 expr3: expr4 { $$ = $1; }
\r
260 | expr3 MULT expr4 { $$ = cf_op($1, $3, OP_MULT); }
\r
261 | expr3 DIVIDE expr4 { $$ = cf_op ($1, $3, OP_DIVIDE); }
\r
264 expr4: PLUS expr4 { $$ = $2; }
\r
265 | MINUS expr4 { cf_value v; v.Type=NLMISC::CConfigFile::CVar::T_INT; /* just to avoid a warning, I affect 'v' with a dummy value */ $$ = cf_op($2,v,OP_NEG); }
\r
266 | LPAREN expression RPAREN { $$ = $2; }
\r
267 | INTEGER { $$ = yylval.Val; }
\r
268 | REAL { $$ = yylval.Val; }
\r
269 | STRING { $$ = yylval.Val; }
\r
270 | variable { $$ = $1; }
\r
275 DEBUG_PRINT("yacc: cont\n");
\r
278 for(i = 0; i < (int)((*((vector<NLMISC::CConfigFile::CVar>*)(YYPARSE_PARAM))).size()); i++)
\r
280 if ((*((vector<NLMISC::CConfigFile::CVar>*)(YYPARSE_PARAM)))[i].Name == $1.String)
\r
289 Var.Type = (*((vector<NLMISC::CConfigFile::CVar>*)(YYPARSE_PARAM)))[i].Type;
\r
290 DEBUG_PRINTF("vart %d\n", Var.Type);
\r
293 case NLMISC::CConfigFile::CVar::T_INT: Var.Int = (*((vector<NLMISC::CConfigFile::CVar>*)(YYPARSE_PARAM)))[i].IntValues[0]; break;
\r
294 case NLMISC::CConfigFile::CVar::T_REAL: Var.Real = (*((vector<NLMISC::CConfigFile::CVar>*)(YYPARSE_PARAM)))[i].RealValues[0]; break;
\r
295 case NLMISC::CConfigFile::CVar::T_STRING: strcpy (Var.String, (*((vector<NLMISC::CConfigFile::CVar>*)(YYPARSE_PARAM)))[i].StrValues[0].c_str()); break;
\r
296 default: DEBUG_PRINT("*** CAN T DO THAT!!!\n"); break;
\r
302 DEBUG_PRINT("var existe pas\n");
\r
308 /* compute the good operation with a, b and op */
\r
309 cf_value cf_op (cf_value a, cf_value b, cf_operation op)
\r
311 DEBUG_PRINTF("[OP:%d; ", op);
\r
319 case OP_MULT: // *********************
\r
322 case NLMISC::CConfigFile::CVar::T_INT:
\r
325 case NLMISC::CConfigFile::CVar::T_INT: a.Int *= b.Int; break;
\r
326 case NLMISC::CConfigFile::CVar::T_REAL: a.Int *= (int)b.Real; break;
\r
327 case NLMISC::CConfigFile::CVar::T_STRING: DEBUG_PRINT("ERROR: int*str\n"); break;
\r
331 case NLMISC::CConfigFile::CVar::T_REAL:
\r
334 case NLMISC::CConfigFile::CVar::T_INT: a.Real *= (double)b.Int; break;
\r
335 case NLMISC::CConfigFile::CVar::T_REAL: a.Real *= b.Real; break;
\r
336 case NLMISC::CConfigFile::CVar::T_STRING: DEBUG_PRINT("ERROR: real*str\n"); break;
\r
340 case NLMISC::CConfigFile::CVar::T_STRING:
\r
343 case NLMISC::CConfigFile::CVar::T_INT: DEBUG_PRINT("ERROR: str*int\n"); break;
\r
344 case NLMISC::CConfigFile::CVar::T_REAL: DEBUG_PRINT("ERROR: str*real\n"); break;
\r
345 case NLMISC::CConfigFile::CVar::T_STRING: DEBUG_PRINT("ERROR: str*str\n"); break;
\r
352 case OP_DIVIDE: // //////////////////////
\r
355 case NLMISC::CConfigFile::CVar::T_INT:
\r
358 case NLMISC::CConfigFile::CVar::T_INT: a.Int /= b.Int; break;
\r
359 case NLMISC::CConfigFile::CVar::T_REAL: a.Int /= (int)b.Real; break;
\r
360 case NLMISC::CConfigFile::CVar::T_STRING: DEBUG_PRINT("ERROR: int/str\n"); break;
\r
364 case NLMISC::CConfigFile::CVar::T_REAL:
\r
367 case NLMISC::CConfigFile::CVar::T_INT: a.Real /= (double)b.Int; break;
\r
368 case NLMISC::CConfigFile::CVar::T_REAL: a.Real /= b.Real; break;
\r
369 case NLMISC::CConfigFile::CVar::T_STRING: DEBUG_PRINT("ERROR: real/str\n"); break;
\r
373 case NLMISC::CConfigFile::CVar::T_STRING:
\r
376 case NLMISC::CConfigFile::CVar::T_INT: DEBUG_PRINT("ERROR: str/int\n"); break;
\r
377 case NLMISC::CConfigFile::CVar::T_REAL: DEBUG_PRINT("ERROR: str/real\n"); break;
\r
378 case NLMISC::CConfigFile::CVar::T_STRING: DEBUG_PRINT("ERROR: str/str\n"); break;
\r
385 case OP_PLUS: // ++++++++++++++++++++++++
\r
388 case NLMISC::CConfigFile::CVar::T_INT:
\r
391 case NLMISC::CConfigFile::CVar::T_INT: a.Int += b.Int; break;
\r
392 case NLMISC::CConfigFile::CVar::T_REAL: a.Int += (int)b.Real; break;
\r
393 case NLMISC::CConfigFile::CVar::T_STRING: a.Int += atoi(b.String); break;
\r
397 case NLMISC::CConfigFile::CVar::T_REAL:
\r
400 case NLMISC::CConfigFile::CVar::T_INT: a.Real += (double)b.Int; break;
\r
401 case NLMISC::CConfigFile::CVar::T_REAL: a.Real += b.Real; break;
\r
402 case NLMISC::CConfigFile::CVar::T_STRING: a.Real += atof (b.String); break;
\r
406 case NLMISC::CConfigFile::CVar::T_STRING:
\r
409 case NLMISC::CConfigFile::CVar::T_INT: { char str2[60]; NLMISC::smprintf(str2, 60, "%d", b.Int); strcat(a.String, str2); break; }
\r
410 case NLMISC::CConfigFile::CVar::T_REAL: { char str2[60]; NLMISC::smprintf(str2, 60, "%f", b.Real); strcat(a.String, str2); break; }
\r
411 case NLMISC::CConfigFile::CVar::T_STRING: strcat (a.String, b.String); break;
\r
418 case OP_MINUS: // -------------------------
\r
421 case NLMISC::CConfigFile::CVar::T_INT:
\r
424 case NLMISC::CConfigFile::CVar::T_INT: a.Int -= b.Int; break;
\r
425 case NLMISC::CConfigFile::CVar::T_REAL: a.Int -= (int)b.Real; break;
\r
426 case NLMISC::CConfigFile::CVar::T_STRING: DEBUG_PRINT("ERROR: int-str\n"); break;
\r
430 case NLMISC::CConfigFile::CVar::T_REAL:
\r
433 case NLMISC::CConfigFile::CVar::T_INT: a.Real -= (double)b.Int; break;
\r
434 case NLMISC::CConfigFile::CVar::T_REAL: a.Real -= b.Real; break;
\r
435 case NLMISC::CConfigFile::CVar::T_STRING: DEBUG_PRINT("ERROR: real-str\n"); break;
\r
439 case NLMISC::CConfigFile::CVar::T_STRING:
\r
442 case NLMISC::CConfigFile::CVar::T_INT: DEBUG_PRINT("ERROR: str-int\n"); break;
\r
443 case NLMISC::CConfigFile::CVar::T_REAL: DEBUG_PRINT("ERROR: str-real\n"); break;
\r
444 case NLMISC::CConfigFile::CVar::T_STRING: DEBUG_PRINT("ERROR: str-str\n"); break;
\r
451 case OP_NEG: // neg
\r
454 case NLMISC::CConfigFile::CVar::T_INT: a.Int = -a.Int; break;
\r
455 case NLMISC::CConfigFile::CVar::T_REAL: a.Real = -a.Real; break;
\r
456 case NLMISC::CConfigFile::CVar::T_STRING: DEBUG_PRINT("ERROR: -str\n"); break;
\r
462 DEBUG_PRINT("]\n");
\r
466 /* print a value, it's only for debug purpose */
\r
467 void cf_print (cf_value Val)
\r
471 case NLMISC::CConfigFile::CVar::T_INT:
\r
472 DEBUG_PRINTF("'%d'", Val.Int);
\r
474 case NLMISC::CConfigFile::CVar::T_REAL:
\r
475 DEBUG_PRINTF("`%f`", Val.Real);
\r
477 case NLMISC::CConfigFile::CVar::T_STRING:
\r
478 DEBUG_PRINTF("\"%s\"", Val.String);
\r
484 /* put a value into a var */
\r
485 void cf_setVar (NLMISC::CConfigFile::CVar &Var, cf_value Val)
\r
487 DEBUG_PRINTF("Set var (type %d var name '%s') with new var type %d with value : ", Var.Type, Var.Name.c_str(), Val.Type);
\r
489 DEBUG_PRINTF("\n");
\r
490 Var.Root = LoadRoot;
\r
491 if (Var.Type == NLMISC::CConfigFile::CVar::T_UNKNOWN || Var.Type == Val.Type)
\r
493 if (Var.Type == NLMISC::CConfigFile::CVar::T_UNKNOWN)
\r
495 DEBUG_PRINTF("var type is unknown, set to the val type\n");
\r
499 DEBUG_PRINTF("val type is same var type, just add\n");
\r
502 Var.Type = Val.Type;
\r
505 case NLMISC::CConfigFile::CVar::T_INT: Var.IntValues.push_back (Val.Int); break;
\r
506 case NLMISC::CConfigFile::CVar::T_REAL: Var.RealValues.push_back (Val.Real); break;
\r
507 case NLMISC::CConfigFile::CVar::T_STRING: Var.StrValues.push_back(Val.String); break;
\r
513 // need to convert the type
\r
516 case NLMISC::CConfigFile::CVar::T_INT:
\r
519 case NLMISC::CConfigFile::CVar::T_REAL: Var.IntValues.push_back ((int)Val.Real); break;
\r
520 case NLMISC::CConfigFile::CVar::T_STRING: { int val = 0; NLMISC::fromString(Val.String, val); Var.RealValues.push_back(val); break; }
\r
524 case NLMISC::CConfigFile::CVar::T_REAL:
\r
527 case NLMISC::CConfigFile::CVar::T_INT: Var.RealValues.push_back ((double)Val.Int); break;
\r
528 case NLMISC::CConfigFile::CVar::T_STRING: { double val = 0.0; NLMISC::fromString(Val.String, val); Var.RealValues.push_back(val); break; }
\r
532 case NLMISC::CConfigFile::CVar::T_STRING:
\r
535 case NLMISC::CConfigFile::CVar::T_INT: Var.StrValues.push_back(toString(Val.Int)); break;
\r
536 case NLMISC::CConfigFile::CVar::T_REAL: Var.StrValues.push_back(toString(Val.Real)); break;
\r
545 int yyerror (const char *s)
\r
547 DEBUG_PRINTF("%s\n",s);
\r