diff --git a/dataobj/tabfile.cc b/dataobj/tabfile.cc index 828955297..028b24ea5 100644 --- a/dataobj/tabfile.cc +++ b/dataobj/tabfile.cc @@ -24,6 +24,7 @@ bool tabfile_t::open(const char *filename) { close(); + sublines.clear(); file = dr_fopen(filename, "r"); current_line_number = 0; return file != NULL; @@ -36,6 +37,7 @@ void tabfile_t::close() fclose(file); file = NULL; } + sublines.clear(); } @@ -291,181 +293,279 @@ void tabfileobj_t::unused( const char *exclude_start_chars ) } +// if-tree for directives +int tabfile_t::directive(char *dir) +{ + const char *STARTSUB = ""; + const char *ENDSUB = ""; + const char *MARKER = ""; + const char *DELSUB = ""; + if(!strcmp(dir, STARTSUB)){ + return 1; + } + if(!strcmp(dir, ENDSUB)){ + return 2; + } + if(!strcmp(dir, MARKER)){ + return 3; + } + if(!strcmp(dir, DELSUB)){ + return 4; + } + return -1; +} + bool tabfile_t::read(tabfileobj_t &objinfo, FILE *fp) { bool lines = false; char line[LINEBUFFER_SIZE]; - char line_expand[LINEBUFFER_SIZE]; char delim_expand[LINEBUFFER_SIZE]; char buffer[LINEBUFFER_SIZE]; char *param[10]; char *expansion[10]; - + + bool in_sub_block = false; + bool line_to_obj = false; + const char *DEFAULT = "#"; + char subname[LINEBUFFER_SIZE]; current_line_number = 0; - objinfo.clear(); - do { while(read_line(line, sizeof(line)) && *line != '-') { - char *delim = strchr(line, '='); - - if(delim) { - *delim++ = '\0'; - format_key(line); - if (line[0] == 0) { - return false; + // This part of the code handles substitution blocks. Lines get stored in the substitution_map, unless it's the end of the block. + if(in_sub_block) { + if(line[0] == '<') { // lines in substitution blocks cannot start with '<' except for ending the block. + if(directive(line)==2){ //End-Substitution + in_sub_block=false; + } + else { + dbg->warning( "tabfile_t::read", "Line %d in substitution block ignored. \"%s\"", current_line_number, line); + } } - - int parameters = 0; - int expansions = 0; - /* - @line, the whole parameter text (everything before =) - @delim, the whole value text (everything after =) - @parameters, number of fields enclosed by square brackets [] - @expansions, number of expansions included in the value (text inside angle brackets <>) - @param, array containing the text inside each [] field - @expansion, array containing the text inside each <> field - */ - if(find_parameter_expansion(line, delim, ¶meters, &expansions, param, expansion) > 0) { - int parameter_value[10][256]; - int parameter_length[10]; - int parameter_values[10]; // number of possible 'values' inside each [] field | e.g. [0-4]=5 / [n,s,w]=3 - char parameter_name[256][6]; // non-numeric ribis strings for all parameter fields consecutively - bool parameter_ribi[10]; // true if parameters are ribi strings - - int combinations=1; - int names = 0; // total number of ribi parameters - - // analyse and obtain all parameter expansions - for(int i=0; ipush_back(helper); + } + } + // this part handles directives starting with '<' + else if(line[0] == '<') { + // since directives can be key-value-pairs, they may need to be seperated + char *delim = strchr(line, '='); + if(delim) { + *delim++ = '\0'; + format_key(line); + } + // then, the code depends on the preprocessor command: + switch (directive(line)){ + case 1: //Beginning of a substitution block + if(delim) { + strcpy(subname, delim); + sublines.put(subname, std::vector(0)); + in_sub_block = true; + } + else{ + dbg->warning( "tabfile_t::read", "Line %d ignored. Start of substitution block without name.", current_line_number); + } + break; + case 2: //End of a substitution block -> Warning + dbg->warning( "tabfile_t::read", "End of substitution block outside of substitution block in line %d ignored.", current_line_number); + break; + case 3: //Insertion marker + if(delim) { + strcpy(subname, delim); + line_to_obj = true; + } + else{ + dbg->warning( "tabfile_t::read", "Line %d ignored. Insertion of substitution without name.", current_line_number); + } + break; + case 4: //forget substitution block + if(delim) { + sublines.remove(delim); + } + else{ + sublines.clear(); + } + break; + default: //Unknown command + dbg->warning( "tabfile_t::read", "Unknown command in line %d ignored. \"%s\"", current_line_number, line); + } + } + // if we deal with a regular line, just guide it through + else { + strcpy(subname, DEFAULT); + line_to_obj = true; + } + if(line_to_obj){ + for(size_t i=0; i < (strcmp(subname, DEFAULT) ? (sublines.access(subname) ? sublines.access(subname)->size() : 0) : 1); i++) { + // Replace line in case we need to. + if(strcmp(subname, DEFAULT)){ + strcpy(line, sublines.access(subname)->at(i)); + } + // from here, it's mostly the old code. Just the lines fed to this code are sometimes substituted. + char *delim = strchr(line, '='); + + if(delim) { + *delim++ = '\0'; + format_key(line); + if (line[0] == 0) { + return false; } - parameter_value[i][parameter_values[i]++] = value; - - token_ptr = strtok(buffer,"-,"); - while (token_ptr != NULL && parameter_values[i]<256) { - switch(param[i][token_ptr-buffer-1]) { - case ',': - value = atoi(token_ptr); - if (parameter_ribi[i]) { - value = parameter_values[i]; - sprintf(parameter_name[ names++ ], "%.*s", (int)strcspn(buffer+name_length+1,","), buffer+name_length+1); - name_length += strcspn(buffer+name_length+1,",") + 1; - } - parameter_value[i][parameter_values[i]++] = value; - break; - case '-': - if (parameter_ribi[i]) { - value = parameter_values[i]; - sprintf(parameter_name[value], "%.*s", (int)strcspn(buffer+name_length+1,","), buffer+name_length+1); - name_length += strcspn(buffer+name_length+1,",") + 1; - parameter_value[i][parameter_values[i]++] = value; + + int parameters = 0; + int expansions = 0; + /* + @line, the whole parameter text (everything before =) + @delim, the whole value text (everything after =) + @parameters, number of fields enclosed by square brackets [] + @expansions, number of expansions included in the value (text inside angle brackets <>) + @param, array containing the text inside each [] field + @expansion, array containing the text inside each <> field + */ + if(find_parameter_expansion(line, delim, ¶meters, &expansions, param, expansion) > 0) { + int parameter_value[10][256]; + int parameter_length[10]; + int parameter_values[10]; // number of possible 'values' inside each [] field | e.g. [0-4]=5 / [n,s,w]=3 + char parameter_name[256][6]; // non-numeric ribis strings for all parameter fields consecutively + bool parameter_ribi[10]; // true if parameters are ribi strings + + int combinations=1; + int names = 0; // total number of ribi parameters + + // analyse and obtain all parameter expansions + for(int i=0; i= 256) { + dbg->fatal("tabfile_t::read", "Invalid number range %d-%d (Max range %d values) in line %d", start_range, end_range, 256 - parameter_values[i], current_line_number); + } + + for(int range=start_range; range= 256) { - dbg->fatal("tabfile_t::read", "Invalid number range %d-%d (Max range %d values) in line %d", start_range, end_range, 256 - parameter_values[i], current_line_number); + // start expansion of the parameter + for(int c=0; c0) { + // warp values around the number of parameters the expansion has + for(int j=0; j0) { - // warp values around the number of parameters the expansion has - for(int j=0; j0) { - int expansion_length[10]; - int expansion_value[10]; + // expand the value + if(expansions>0) { + int expansion_length[10]; + int expansion_value[10]; - for(int i=0; i")-1; - sprintf(buffer, "%.*s", expansion_length[i]+1, expansion[i]); + for(int i=0; i")-1; + sprintf(buffer, "%.*s", expansion_length[i]+1, expansion[i]); - expansion_value[i] = calculate(buffer, parameter_value, parameters, combination); - } + expansion_value[i] = calculate(buffer, parameter_value, parameters, combination); + } + + sprintf(delim_expand, "%.*s%d", (int)(expansion[0]-delim), delim, expansion_value[0]); + for(int i=1; iwarning( "tabfile_t::read", "No data in \"%s\"", line ); } } - lines = true; - } - else if( *line ) { - dbg->warning( "tabfile_t::read", "No data in \"%s\"", line ); + line_to_obj=false; } } } while(!lines && !feof(file)); // skip empty objects diff --git a/dataobj/tabfile.h b/dataobj/tabfile.h index 83239a566..c1a81a26c 100644 --- a/dataobj/tabfile.h +++ b/dataobj/tabfile.h @@ -8,6 +8,7 @@ #include +#include #include "../simcolor.h" #include "../tpl/stringhashtable_tpl.h" @@ -47,7 +48,7 @@ class tabfile_t public: tabfile_t() : file(NULL) {} ~tabfile_t() { close(); } - + stringhashtable_tpl> sublines; public: bool open(const char *filename); @@ -98,6 +99,11 @@ private: * Format the key string (trimright and lowercase) */ void format_key(char *key); + + /** + * Turns directives into integer values. + */ + int directive(char *dir); private: FILE *file;