/* linked-list symbol table */ #include #include #include #include "ss.h" #include "parse.h" const char *symbol_format = "%g"; void install_symbol_format( const char *fmt) { symbol_format = fmt; } /*** head and tail of the symbol table ***/ static Symbol *chead = NULL, *head = NULL, *tail = NULL; /* chead -> constants -> ... (head) -> variables -> ... */ /*** internal functions: new_name, new_symbol ***/ /* create unique names for unnamed "" symbols */ static char *new_name( void) { static int n = 0; static char buf[32]; ++n; sprintf( buf, "$%d", n); return estrdup( buf); } /* allocate new symbol, exit if malloc fails */ static Symbol *new_symbol( const char *name, int constant, double val) { Symbol *e = malloc( sizeof( Symbol) ); if( e == NULL) { yyerror( "new_symbol: malloc failed"); exit(1); } e->name = *name ? name : new_name(); e->constant = constant; e->val = val; e->state = constant ? EVALUATED : UNEVALUATED; e->depend = NULL; e->n = NULL; e->next = NULL; return e; } /* install constant in symbol table */ void install_constant( const char *name, double val) { Symbol *e = new_symbol( name, 1, val); if( chead == NULL) { chead = tail = e; } else { tail->next = e; tail = e; } } /* try to find name in symbol table */ Symbol *find_symbol( const char *name) { Symbol *e; for( e = chead; e; e = e->next) if( strcmp( e->name, name) == 0) return e; return NULL; } /* lookup name in symbol table, install if not found */ Symbol *lookup_symbol( const char *name) { Symbol *e; if( *name && (e = find_symbol( name)) ) return e; e = new_symbol( name, 0, 0.0); /* chead and tail are not NULL since constants were installed at startup */ tail->next = e; tail = e; if( head == NULL) head = tail; return e; } /* install formula in symbol table */ void install_symbol( Symbol *e, Node *n) { if( e->constant) { fprintf( out, "warning: can not change constant %s = ", e->name); fprintf( out, symbol_format, e->val); fprintf( out, "\n"); return; } if( e->n) fprintf( out, "warning: overwriting symbol %s\n", e->name); if( n->type == NUMBER) { e->val = n->u.val; e->state = EVALUATED; e->n = NULL; } else { e->n = n; if( n->type == STRING) { e->state = EVALUATED; } else { install_tree( n, &cell_00, 1); e->state = UNEVALUATED; } } } /* evaluate the symbol table - called only from ss_eval() */ int eval_symbols( void) { Symbol *e; double oldval; int changed = 0; for( e = head; e; e = e->next) { if( debug) { fprintf( out, "eval_symbols: %s, state = %d", e->name, e->state); if( e->depend) fprintf( out, " - depends on %s", e->depend->name); else if( !e->n || e->n->type == STRING) fprintf( out, " - constant"); putc( '\n', out); } if( depend) { eval_symbol(e); // sets e->val if necessary } else if( e->n) { oldval = e->val; e->val = eval_tree( e->n, &cell_00); if( oldval != e->val) changed = 1; } } return changed; } /* set non-constant symbol states to UNEVALUATED */ void reset_symbols( void) { Symbol *e; for( e = head; e; e = e->next) if( e->depend || (e->n != NULL && e->n->type != STRING)) e->state = UNEVALUATED; } /* print one symbol */ static void print_symbol( const Symbol *e) { fprintf( out, " %s", e->name); if( e->n) { int t = func[e->n->type]->type; if( *e->name && (!t || !(t & SS_ASGN)) ) fprintf( out, " = "); print_tree( e->n, &cell_00, 0); } fprintf( out, " = "); fprintf( out, symbol_format, e->val); fprintf( out, "\n"); } /* print the symbol table list, except for constants */ void print_symbols( void) { Symbol *e; for( e = head; e; e = e->next) print_symbol( e); } /* print the symbol table list constants */ void print_constants( void) { Symbol *e; fprintf( out, "Constants:\n"); for( e = chead; e != head ; e = e->next) { fprintf( out, " %s = ", e->name); fprintf( out, symbol_format, e->val); fprintf( out, "\n"); } } /* print the symbol table list states */ void print_symbol_states( void) { Symbol *e; fprintf( out, "States:\n"); for( e = chead; e; e = e->next) { if( e->depend) fprintf( out, " %d (%s) %s\n", e->state, e->depend->name, e->name); else fprintf( out, " %d %s\n", e->state, e->name); } }