%{ /* repex_y.y Yacc syntactical description of template expressions sym_list is indexed by the stack value for the value of symbols erad in lex. same for string_list. */ #include #include #include extern double atof __P ((__const char *__nptr)); extern int tmp_count; extern int tmp_to_template[100000]; extern unsigned char tmp_hif[1000000]; extern int eval_error; extern int temp_lineno; extern unsigned char err_str[20][100]; extern FILE *fd_hif; unsigned char *card_blocks[50]; unsigned char *field_blocks[50]; unsigned char *switch_blocks[50]; unsigned char *rep_ex_string; int rep_ex_index; #if 0 #define REP_EX_DEBUG #endif #define MAX_STRINGS 50 #define MAX_STRING_LENGTH 100 #define REP_EX 7 unsigned char string_list[MAX_STRINGS][MAX_STRING_LENGTH]; int str_l_index; #define MAX_SYMS 1000 /* Signs of growth I'd say */ /* #define MAX_SYMS 100 */ /* #define MAX_SYMS 50 */ #define MAX_SYM_NAME_LENGTH 64 unsigned char sym_list[MAX_SYMS][MAX_SYM_NAME_LENGTH]; int sym_l_index; #include "repsym.h" extern symAssocType symbol_table[5000]; extern symAssocIdxType symbol_indices; int rep_ex_t_len; int return_value; int get_value_return; int list_search_return; extern struct { unsigned char symbol[100]; unsigned char value[512]; } entry_matrix[150][50]; unsigned char *get_value(unsigned char* s); unsigned char *my_malloc(int size); unsigned char *set_value(unsigned char *sym,unsigned char *string); unsigned char *itoa(double n,unsigned char *s); #define YYSTYPE double %} %start clause %token SYM EXIST NOT_EXIST STRING NUMBER STRNCMP STRCMP STRLEN FROM_LIST %token TOUPPER TOLOWER FLOOR CEIL SUBSTR QUOTE SQRT SPLIT %token LIST_SEARCH RICH_TEXT RICH_CARD RICH_BUTTON RICH_FIELD %token GT GTE LT LTE EQ NEQ STRCPY SYM_SIZE %token OR AND NOT %left OR %left AND %left GT GTE LT LTE EQ NEQ %left '-' '+' %left '*' '/' %left UNARYMINUS NOT %right TO_THE %% clause: expr {return_value = $1;} | TOLOWER '(' SYM ',' SYM ')' { unsigned char *value; unsigned int i; value = get_value(sym_list[(int)$5]); for(i=0;i $3) $$ = 1; else $$ = 0;} | expr GTE expr { if ($1 >= $3) $$ = 1; else $$ = 0;} | expr LT expr { if ($1 < $3) $$ = 1; else $$ = 0;} | expr LTE expr { if ($1 <= $3) $$ = 1; else $$ = 0;} | expr EQ expr { if ($1 == $3) $$ = 1; else $$ = 0;} | expr NEQ expr { if ($1 != $3) $$ = 1; else $$ = 0;} | expr '-' expr { $$ = $1 - $3; } | expr '+' expr { $$ = $1 + $3; } | expr '*' expr { $$ = $1 * $3; } | expr '/' expr { $$ = $1 / $3; } | expr TO_THE expr { $$ = pow($1,$3); } | '-' expr %prec UNARYMINUS { $$ = $2 * -1; } | SYM { unsigned char *value; value = get_value(sym_list[(int)$1]); if (get_value_return) return 1; $$ = atof(value); } | NUMBER { $$ = $1; } | EXIST '(' SYM ')' { if (does_exist(sym_list[(int)$3])) $$ = 1; else $$ = 0; } | NOT_EXIST '(' SYM ')' { if (does_exist(sym_list[(int)$3])) $$ = 0; else $$ = 1; } | SPLIT '(' STRING ',' SYM ',' STRING ')' { /* This function is modeled after the AWK command split. It takes three arguments. The first is a one character string (at least that's all I'm going to use from it) containing the delimiting character. The next argument is a variable that contains the string you want to split. The final argument is a variable name pre-fix to use for the elements that are found during the split. Don't worry I'll show an example further down. Finally the split function returns the number of items found. example: say you have a variable called photo that contains three integers separated by spaces and you want access to each integer in turn. This is what split is designed for. #photo = "111 222 333"; #num_photos = split(" ",photo,PHOTO_NUM); After this call the variable num_photos is 3 and 3 new variables are created PHOTO_NUM1, PHOTO_NUM2, PHOTO_NUM3 with the values 111, 222 and 333 respectively. Too bad we don't have arrays in this language. */ int num_elements = 0; unsigned char prefix[1024]; unsigned char delimit[2]; unsigned char buf[1024]; unsigned char *split_text, *sub_field; /* grab the delimiting character */ delimit[0] = (unsigned char) string_list[(int)$3][0]; /* I'm only allowing a split based upon the first character in the delimiter string */ delimit[1] = '\0'; #ifdef REP_EX_DEBUG printf("delimiter is %s\n",delimit); #endif /* grab the string containing the sub-fields */ split_text = get_value(sym_list[(int)$5]); if (get_value_return) return 1; #ifdef REP_EX_DEBUG printf("the source string is %s.\n",split_text); #endif /* grab the target prefix string */ strcpy(prefix,string_list[(int)$7]); #ifdef REP_EX_DEBUG printf("the prefix string is %s.\n",prefix); #endif /* initialize the token search */ sub_field = (unsigned char *) strtok(split_text,delimit); num_elements++; /* Create new variable using prefix and num_elements */ sprintf(buf,"%s%d",prefix,num_elements); #ifdef REP_EX_DEBUG printf("creating var %s contain %s.\n",buf,sub_field); #endif set_value(buf,sub_field); while (sub_field = (unsigned char *) strtok(NULL,delimit)) { num_elements++; /* Create new variable using prefix and num_elements */ sprintf(buf,"%s%d",prefix,num_elements); #ifdef REP_EX_DEBUG printf("creating var %s contain %s.\n",buf,sub_field); #endif set_value(buf,sub_field); } /* Return the number of sub_fields (possibly 1) */ $$ = num_elements; } | LIST_SEARCH '(' SYM ',' SYM ')' { $$ = list_search(sym_list[(int)$3],sym_list[(int)$5]); if (list_search_return) return 1; } | LIST_SEARCH '(' SYM ',' STRING ')' { $$ = list_search(sym_list[(int)$3],string_list[(int)$5]); if (list_search_return) return 1; } | STRCMP '(' strcmp_args ')' { $$ = $3; } | STRNCMP '(' strncmp_args ')' { $$ = $3; } | STRLEN '(' SYM ')' { unsigned char *value; value = get_value(sym_list[(int)$3]); if (get_value_return) return 1; $$ = strlen(value); } | FLOOR '(' expr ')' { $$ = floor($3); } | CEIL '(' expr ')' { $$ = ceil($3); } | SQRT '(' expr ')' { $$ = sqrt($3); } ; substr_args: SYM ',' SYM ',' NUMBER ',' NUMBER { unsigned char buf[1024]; unsigned char buf2[1024]; unsigned char *value1; int index, num_chars; num_chars = (int)$7; index = (int)$5; strcpy(buf2,get_value(sym_list[(int)$3])); /* get a copy of the text */ strncpy(buf,&buf2[index-1],num_chars); buf[num_chars] = '\0'; if (get_value_return) return 1; set_value(sym_list[(int)$1],buf); } | SYM ',' SYM ',' SYM ',' NUMBER { unsigned char buf[1024]; unsigned char buf2[1024]; unsigned char *value1; int index, num_chars; num_chars = (int)$7; value1 = get_value(sym_list[(int)$5]); /* get string value of 3rd argument */ index = atoi(value1); /* convert it to an int */ strcpy(buf2,get_value(sym_list[(int)$3])); /* get a copy of the text */ strncpy(buf,&buf2[index-1],num_chars); buf[num_chars] = '\0'; if (get_value_return) return 1; set_value(sym_list[(int)$1],buf); } | SYM ',' SYM ',' NUMBER ',' SYM { unsigned char buf[1024]; unsigned char buf2[1024]; unsigned char *value1; int index, num_chars; value1 = get_value(sym_list[(int)$7]); /* get string value of 4th argument */ num_chars = atoi(value1); /* convert it to an int */ index = (int)$5; /* convert 3rd argument to an int */ strcpy(buf2,get_value(sym_list[(int)$3])); /* get a copy of the text */ strncpy(buf,&buf2[index-1],num_chars); buf[num_chars] = '\0'; if (get_value_return) return 1; set_value(sym_list[(int)$1],buf); } | SYM ',' SYM ',' SYM ',' SYM { unsigned char buf[1024]; unsigned char buf2[1024]; unsigned char *value1; int index, num_chars; value1 = get_value(sym_list[(int)$5]); /* get string value of 3rd arg */ index = atoi(value1); /* convert it to an int */ value1 = get_value(sym_list[(int)$7]); /* get string value of 4th arg */ num_chars = atoi(value1); /* convert it to an int */ strcpy(buf2,get_value(sym_list[(int)$3])); /* get a copy of the text */ strncpy(buf,&buf2[index-1],num_chars); buf[num_chars] = '\0'; if (get_value_return) return 1; set_value(sym_list[(int)$1],buf); } strcpy_args: SYM ',' SYM { unsigned char *value; value = get_value(sym_list[(int)$3]); set_value(sym_list[(int)$1],value); if (get_value_return) return 1; } | SYM ',' STRING { set_value(sym_list[(int)$1],string_list[(int)$3]); if (get_value_return) return 1; } ; strcmp_args: SYM ',' SYM { unsigned char *value1,*value2; value1 = get_value(sym_list[(int)$1]); if (get_value_return) return 1; value2 = get_value(sym_list[(int)$3]); if (get_value_return) return 1; if (strcmp(value1,value2)) $$ = 1; else $$ = 0; } | SYM ',' STRING { unsigned char *value; value = get_value(sym_list[(int)$1]); if (get_value_return) return 1; if (strcmp(value,string_list[(int)$3])) $$ = 1; else $$ = 0; } | STRING ',' SYM { unsigned char *value; value = get_value(sym_list[(int)$3]); if (get_value_return) return 1; if (strcmp(string_list[(int)$1],value)) $$ = 1; else $$ = 0; } ; strncmp_args: SYM ',' SYM ',' NUMBER { unsigned char *value1,*value2; value1 = get_value(sym_list[(int)$1]); if (get_value_return) return 1; value2 = get_value(sym_list[(int)$3]); if (get_value_return) return 1; if (strncmp(value1,value2,(int)$5)) $$ = 1; else $$ = 0; } | SYM ',' STRING ',' NUMBER { unsigned char *value; value = get_value(sym_list[(int)$1]); if (get_value_return) return 1; if (strncmp(value,string_list[(int)$3],$5)) $$ = 1; else $$ = 0; } | STRING ',' SYM ',' NUMBER { unsigned char *value; value = get_value(sym_list[(int)$3]); if (get_value_return) return 1; if (strncmp(string_list[(int)$1],value,(int)$5)) $$ = 1; else $$ = 0; } ; %% #include "rep_ex_l.c" #define MEM_ALLOCS 5000 struct { unsigned char *ptr; int used; } mems[MEM_ALLOCS]; rep_error (int error) { printf("error %d\n", error); exit(1); } unsigned char *my_malloc(int size) { unsigned char *temp; int i; if ((temp = (unsigned char *) malloc(size)) == NULL) { printf("rep_ex_y: Out of memory. Exiting.\n"); exit(1); } for (i=0;i=0;i--) { if (!strcmp(symbol_table[i].symbol,s)) { return (unsigned char*) symbol_table[i].value; } } sprintf(err_str[0],"ERROR in user expression evaluation."); sprintf(err_str[1],"Symbol %s not found in symbol table.",s); sprintf(err_str[2],"In template line %d.",temp_lineno); sprintf(err_str[3],""); rep_error(REP_EX); get_value_return = 1; } unsigned char *set_value(sym,string) unsigned char *sym; unsigned char *string; { int i; for (i=symbol_indices.last;i>=symbol_indices.user;i--) { if (!strcmp(symbol_table[i].symbol,sym)) { strcpy(symbol_table[i].value,string); return; } } strcpy(symbol_table[symbol_indices.last+1].symbol,sym); strcpy(symbol_table[symbol_indices.last+1].value,string); symbol_indices.last++; if (symbol_indices.last > 5000) printf("ERROR too many symbols %d .",symbol_indices.last); } int does_exist(s) unsigned char *s; { int i; for (i=symbol_indices.last;i>=0;i--) { /* if (!strcmp(symbol_table[i].symbol,"Rating11")) printf("found Rating11 %s\n",symbol_table[i].value);*/ if (!strcmp(symbol_table[i].symbol,s)) { break; } } /*printf("looked for %s found %s %s\n", s ,symbol_table[i].symbol,symbol_table[i].value);*/ if (i<0) return 0; if (i>= symbol_indices.global && i < symbol_indices.user) { if (!strlen(symbol_table[i].value)) return 0; } return 1; } int list_search(field_name,value) unsigned char *field_name; unsigned char *value; { int i,index; for (i=0;entry_matrix[0][i].symbol[0];i++) { if (!strcmp(entry_matrix[0][i].symbol,field_name)) { break; } } if (!entry_matrix[0][i].symbol[0]) { sprintf(err_str[0],"ERROR in user expression evaluation."); sprintf(err_str[1],"No such field %s in entry.",field_name); sprintf(err_str[2],"In template line %d.",temp_lineno); sprintf(err_str[3],""); rep_error(REP_EX); list_search_return = 1; return 1; } for (index = 0;entry_matrix[index][0].symbol[0];index++){ if (!strcmp(entry_matrix[index][i].value,value)) { return index; } } return -1; } yyerror() { sprintf(err_str[0],"ERROR in user expression evaluation."); sprintf(err_str[1],"Syntax error: %s.",yytext); sprintf(err_str[2],"In template line %d.",temp_lineno); sprintf(err_str[3],""); rep_error(REP_EX); } unsigned char *itoa(n,s) double n; unsigned char *s; { if (floor(n) == n) { sprintf(s,"%d",(int)n); } else { sprintf(s,"%f",n); } return s; #if 0 int i, sign; if ((sign = n) < 0) n = -n; i=0; do { s[i++] = n % 10 + '0'; } while ((n/= 10) > 0); if (sign < 0) s[i++] = '-'; s[i] = '\0'; reverse(s); return s; #endif } reverse(s) unsigned char *s; { int c,i,j; for (i=0, j = strlen(s)-1; i