📄 symbol.c
字号:
/* YABASIC --- a simple Basic Interpreter written by Marc-Oliver Ihm 1995-2005 homepage: www.yabasic.de symbol.c --- code for control structures, symbol and stack management This file is part of yabasic and may be copied only under the terms of either the Artistic License or the GNU General Public License (GPL), both of which can be found at www.yabasic.de*//* ------------- includes ---------------- */#ifndef YABASIC_INCLUDED#include "yabasic.h" /* all prototypes and structures */#endif/* ------------- external references ---------------- */extern int yylineno; /* current line number */extern int yyparse (); /* call bison parser *//* ------------- local defines ---------------- */struct switch_id{ int id; int depth; struct switch_id *next; struct switch_id *prev;};/* ------------- local functions ---------------- */static struct symbol *create_symbol (int, char *); /* create a new symbol */static void link_label (struct command *); /* link label into list of labels */static int count_args (int); /* count number of arguments on stack */static void stackdesc (int, char *); /* give back string describing stackentry */static void freesym (struct symbol *); /* free contents of symbol */static int ind_to_off (int *, int *); /* convert array of indices to single offset */static void off_to_ind (int, int *, int *); /* convert a single offset to an array of indices *//* ------------- global variables ---------------- */static struct symstack *symroot = NULL; /* first element in symbol list */static struct symstack *symhead = NULL; /* last element ind symbol list */struct stackentry *stackroot; /* lowest element in stack */struct stackentry *stackhead; /* topmost element in stack */static struct command *labelroot = NULL; /* first label among commands */static struct command *labelhead = NULL; /* last label seen so far */extern char *current_function; /* name of currently defined function */struct command *lastref; /* last command in UDS referencing a symbol */struct command *firstref; /* first command in UDS referencing a symbol */int labelcount = 0; /* count self-generated labels */int in_switch = 0; /* true, if in switch (at compile-time) */struct switch_id *switch_id_stackhead = NULL; /* topmost (and valid) element of switch_id stack */struct switch_id *switch_id_stackroot = NULL; /* bottommost element of switch_id stack *//* ------------- subroutines ---------------- */voidpushsymlist (void) /* push a new list of symbols on symbol stack */{ struct symstack *new; new = my_malloc (sizeof (struct symstack)); if (symhead) symhead->next_in_stack = new; else symroot = new; /* first time called */ new->prev_in_stack = symhead; new->next_in_stack = NULL; new->next_in_list = NULL; symhead = new;}voidpopsymlist (void) /* pop list of symbols and free symbol contents */{ struct symstack *prevstack; struct symbol *currsym, *nextsym; int count = 0; currsym = symhead->next_in_list; while (currsym) { /* loop through symbol list */ freesym (currsym); count++; nextsym = currsym->next_in_list; my_free (currsym); currsym = nextsym; } if (infolevel >= DEBUG) { sprintf (string, "removed symbol list with %d symbols", count); error (DEBUG, string); } prevstack = symhead->prev_in_stack; my_free (symhead); prevstack->next_in_stack = NULL; symhead = prevstack;}static voidfreesym (struct symbol *s) /* free contents of symbol */{ int i; int total; struct array *ar; if (s->link) { /* it's a link, don't remove memory */ sprintf (string, "removing linked symbol '%s'", s->name); error (DEBUG, string); my_free (s->name); return; } if (s->type == sySTRING) { if (infolevel >= DEBUG) { sprintf (string, "removing string symbol '%s'", s->name); error (DEBUG, string); } my_free (s->pointer); } else if (s->type == syARRAY) { if (infolevel >= DEBUG) { sprintf (string, "removing array symbol '%s()'", s->name); error (DEBUG, string); } ar = s->pointer; if (ar->dimension > 0) { /* count total amount of memory */ total = 1; for (i = 0; i < ar->dimension; i++) total *= (ar->bounds)[i]; if (ar->type == 's') { /* string array */ for (i = 0; i < total; i++) my_free (*((char **) ar->pointer + i)); } my_free (ar->pointer); } my_free (ar); } else if (s->type == syNUMBER) { if (infolevel >= DEBUG) { sprintf (string, "removing numeric symbol '%s'", s->name); error (DEBUG, string); } } my_free (s->name); return;}voidclearrefs (struct command *cmd) /* clear references for commands within function */{ struct command *curr; int n = 0; curr = cmd->nextref; while (curr) { n++; curr->symbol = NULL; curr = curr->nextref; } sprintf (string, "removed references from %d symbols", n); error (DEBUG, string);}struct symbol *get_sym (char *name, int type, int add)/* get the value of a symbol, or create it with given type */{ struct symstack *currstack; struct symbol **currsym; struct symbol *prelink; struct symbol *new; int stackcount = 0; int symbolcount = 0; int linked = FALSE; if (!name) return NULL; /* go through all lists */ currstack = symhead; /* start with symhead */ if (add == amSEARCH_PRE && symhead->prev_in_stack) currstack = symhead->prev_in_stack; while (TRUE) { stackcount++; currsym = &(currstack->next_in_list); while (*currsym) { prelink = *currsym; symbolcount++; if ((*currsym)->type == type && !strcmp (name, (*currsym)->name)) { /* do the types and names match ? */ if ((*currsym)->link) { currsym = &((*currsym)->link); linked = TRUE; } if (infolevel >= DEBUG) { if (linked) sprintf (string, "found symbol '%s%s', linked to %s after searching %d symbol(s) in %d stack(s)", name, (type == syARRAY) ? "()" : "", (*currsym)->name, symbolcount, stackcount); else sprintf (string, "found symbol '%s%s' after searching %d symbol(s) in %d stack(s)", name, (type == syARRAY) ? "()" : "", symbolcount, stackcount); error (DEBUG, string); } return *currsym; /* give back address */ } currsym = &((*currsym)->next_in_list); /* try next entry */ } /* not found in first list */ if (add == amSEARCH_VERY_LOCAL) return NULL; if (add == amADD_LOCAL) { new = create_symbol (type, name); (*currsym) = new; if (infolevel >= DEBUG) { sprintf (string, "created local symbol %s%s", name, (type == syARRAY) ? "()" : ""); error (DEBUG, string); } return new; } if (currstack != symroot) currstack = symroot; else break; } if (add == amADD_GLOBAL) { new = create_symbol (type, name); (*currsym) = new; if (infolevel >= DEBUG) { sprintf (string, "created global symbol %s%s", name, (type == syARRAY) ? "()" : ""); error (DEBUG, string); } return new; } return NULL;}voidlink_symbols (struct symbol *from, struct symbol *to){ /* link one symbol to the other */ from->link = to; if (infolevel >= DEBUG) { sprintf (string, "linking symbol '%s' to '%s'", from->name, to->name); error (DEBUG, string); }}voidcreate_retval (int is, int should) /* create command 'cRETVAL' */{ struct command *cmd; cmd = add_command (cRETVAL, NULL); cmd->args = is; cmd->tag = should;}voidretval (struct command *cmd) /* check return value of function */{ int is, should; struct stackentry *s; is = cmd->args; should = cmd->tag; if (is == should) { /* okay, function returns expected type */ } else if (is == ftNONE) { /* no element on stack, create one */ s = push (); if (should == ftNUMBER) { s->type = stNUMBER; s->value = 0.0; } else { s->type = stSTRING; s->pointer = my_strdup (""); } } else { sprintf (string, "subroutine returns %s but should return %s", (is == ftSTRING) ? "a string" : "a number", (should == ftSTRING) ? "a string" : "a number"); error (ERROR, string); } if (infolevel >= DEBUG) { s = stackhead->prev; if (s->type == stNUMBER) sprintf (string, "subroutine returns number %g", s->value); else if (s->type == stSTRING) sprintf (string, "subroutine returns string '%s'", (char *) s->pointer); else sprintf (string, "subroutine returns something strange (%d)", s->type); error (DEBUG, string); } swap ();}voidcreate_endfunction (void) /* create command cEND_FUNCTION */{ struct command *cmd; cmd = add_command (cEND_FUNCTION, NULL); link_label (cmd);}voiddump_sym (void) /* dump the stack of lists of symbols */{ struct symstack *currstack; struct symbol **currsym; /* go through all lists */ error (DUMP, "head of symbol stack"); currstack = symhead; while (currstack) { /* search 'til last element of stack */ currsym = &(currstack->next_in_list); string[0] = '\0'; while (*currsym) { switch ((*currsym)->type) { case sySTRING: strcat (string, " STRING:"); break; case syNUMBER: strcat (string, " NUMBER:"); break; case syFREE: strcat (string, " FREE:"); break; case syARRAY: strcat (string, " ARRAY:"); break; default: sprintf (string, " UNKNOWN:"); break; } strcat (string, (*currsym)->name); currsym = &((*currsym)->next_in_list); /* try next entry */ } error (DUMP, string); currstack = currstack->prev_in_stack; } error (DUMP, "root of symbol stack"); return;}voiddump_sub (int short_dump) /* dump the stack of subroutine calls */{ struct stackentry *st = stackhead; struct command *cmd; int first = TRUE; do { if (st->type == stRETADDCALL) { cmd = st->pointer; if (cmd->type == cCALL || cmd->type == cQCALL) { char *dot; dot = strchr (cmd->pointer, '.'); if (first && !short_dump) error (DUMP, "Executing in:"); sprintf (string, "sub %s() called in %s,%d", dot ? (dot + 1) : cmd->pointer, cmd->lib->l, cmd->line); error (DUMP, string); first = FALSE; } } st = st->prev; } while (st && st != stackroot); if (first && !short_dump) { if (!short_dump) error (DUMP, "Executing in:"); } if (!short_dump) error (DUMP, "main program"); return;}static struct symbol *create_symbol (int type, char *name) /* create a new symbol */{ struct symbol *new; new = my_malloc (sizeof (struct symbol)); new->type = type; new->next_in_list = NULL; new->name = my_strdup (name); new->pointer = NULL; new->args = NULL; new->value = 0.0; new->link = NULL; return new;}voidfunction_or_array (struct command *cmd) /* decide whether to perform function or array */{ struct command *fu; fu = search_label (cmd->name, smSUB | smLINK); if (fu) { cmd->type = cCALL; cmd->pointer = cmd->name; cmd->name = NULL; error (DEBUG, "converting FUNCTION_OR_ARRAY to FUNCTION"); } else { if (cmd->type == cFUNCTION_OR_ARRAY) cmd->tag = CALLARRAY; else cmd->tag = CALLSTRINGARRAY; cmd->type = cDOARRAY; cmd->args = -1; error (DEBUG, "converting FUNCTION_OR_ARRAY to ARRAY"); }}voidswap () /* swap topmost elements on stack */{ struct stackentry *a, *b; if ((a = stackhead->prev) == NULL || (b = a->prev) == NULL) { error (ERROR, "Nothing to swap on stack !"); return; } a->prev = b->prev; b->next = a->next; /* just swap the pointers */ a->next = b; b->prev = a; stackhead->prev = b; (a->prev)->next = a;}struct stackentry *push ()/* push element on stack and enlarge stack it */{ struct stackentry *new; if (!stackhead->next) { /* no next element */ /* create new element */ new = (struct stackentry *) my_malloc (sizeof (struct stackentry)); /* and initialize it */ new->next = NULL; new->value = 0.0; new->type = stFREE; new->prev = stackhead; new->pointer = NULL; stackhead->next = new; } else if (stackhead->pointer != NULL && (stackhead->type == stSTRING || stackhead->type == stSTRINGARRAYREF || stackhead->type == stNUMBERARRAYREF || stackhead->type == stLABEL)) { /* any content is set free */ my_free (stackhead->pointer); stackhead->pointer = NULL; } stackhead = stackhead->next; /* advance head */ return stackhead->prev;}struct stackentry *pop (int etype)/* pops element to memory and looks for pop-error */{ static char expected[50]; static char found[50];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -