diff --git a/dataobj/tabfile.cc b/dataobj/tabfile.cc
index 828955297..12e0b444f 100644
--- a/dataobj/tabfile.cc
+++ b/dataobj/tabfile.cc
@@ -36,6 +36,7 @@ void tabfile_t::close()
fclose(file);
file = NULL;
}
+ sublines.clear();
}
@@ -291,181 +292,313 @@ void tabfileobj_t::unused( const char *exclude_start_chars )
}
+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; //copy lines to table
+ bool line_to_obj = false; //put line into object
+ char subname[LINEBUFFER_SIZE]; //holds name of substitution block; empty means no substitution
+ char replacement[LINEBUFFER_SIZE]; //holds string for inline replacement; empty means no replacement
+
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;
+ replacement[0]='\0';
+
+ // Handle substitution blocks. Lines get stored in the hashtable, unless it's the end of the block.
+ // directives are not allowed (except for ending the block), ignored + warning.
+ if(in_sub_block) {
+ if(line[0] == '<') {
+ if(directive(line)==2){ //End of a substitution block
+ 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);
+ }
+ }
+
+ // Handle directives. Since directives can be key-value-pairs, they may need to be seperated.
+ // Directive strings are turned into integers via directive() to be used in a switch.
+ else if(line[0] == '<') {
+ char *delim = strchr(line, '=');
+ if(delim) {
+ *delim++ = '\0';
+ format_key(line);
+ }
+ 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
+ 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) {
+ // check for replacement-string
+ char *repl = strchr(delim, ';');
+ if(repl){
+ *repl++ = '\0';
+ strcpy(replacement, repl);
}
- 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;
- }
- else {
- const int start_range = parameter_value[i][parameter_values[i]-1];
- const int end_range = atoi(token_ptr);
-
- if (parameter_values[i] + (end_range - start_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);
- }
-
- for(int range=start_range; rangewarning( "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);
+ }
+ }
+
+ // Handle regular lines.
+ else {
+ subname[0]='\0';
+ line_to_obj = true;
+ }
+
+ // Turn lines into key-value-pairs and store them in objinfo
+ if(line_to_obj) {
+
+ // For regular lines, go through the loop once.
+ // For a substitution block, loop through each stored line.
+ // For a substitution block without lines stored, skip the loop.
+ for(size_t i=0; i < (subname[0] ? (sublines.access(subname) ? sublines.access(subname)->size() : 0) : 1); i++) {
+
+ // Get lines from stored substitution block
+ if(subname[0]) {
+ strcpy(line, sublines.access(subname)->at(i));
+
+ // inline-replacement (replace > in lines within a substitution block)
+ if(replacement[0]) {
+ char *c = line;
+ do {
+ c = strchr(c, '<');
+ if(c && c[1] == '?' && c[2] == '>') {
+ *c++ = '\0';
+ *c+=2;
+ strcat(line, replacement);
+ strcat(line, c);
+ }
+ } while(c++);
}
- combinations*=parameter_values[i];
}
+
+ // Finally, the line can be seperated in key and value, expanded if shorthand is used, and put into objinfo
+ char *delim = strchr(line, '=');
+
+ if(delim) {
+ *delim++ = '\0';
+ format_key(line);
+ if (line[0] == 0) {
+ return false;
+ }
- // start expansion of the parameter
- for(int c=0; c0) {
- // warp values around the number of parameters the expansion has
- for(int j=0; j)
+ @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; range0) {
+ // 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;