📄 symbol.c
字号:
int ftype; struct stackentry *s; /* test if there is something on the stack */ if (stackhead == stackroot) { error (FATAL, "Popped too much."); return stackhead; } stackhead = stackhead->prev; /* move down in stack */ ftype = stackhead->type; if (etype == ftype || etype == stANY || (etype == stSTRING_OR_NUMBER && (ftype == stNUMBER || ftype == stSTRING)) || (etype == stSTRING_OR_NUMBER_ARRAYREF && (ftype == stSTRINGARRAYREF || ftype == stNUMBERARRAYREF))) return stackhead; /* this is your value; use it quickly ! */ /* expected and found don't match */ stackdesc (etype, expected); stackdesc (ftype, found); sprintf (string, "expected %s but found %s", expected, found); if (etype == stNUMBER || etype == stSTRING || etype == stSTRING_OR_NUMBER) { s = push (); if (etype == stNUMBER) { s->type = stNUMBER; s->value = 0.0; } else { s->type = stSTRING; s->pointer = my_strdup (""); } error (ERROR, string); return s; } else { error (FATAL, string); } return stackhead;}static voidstackdesc (int type, char *desc) /* give back string describing stackentry */{ switch (type) { case stGOTO: strcpy (desc, "a goto"); break; case stSTRING: strcpy (desc, "a string"); break; case stSTRINGARRAYREF: strcpy (desc, "a reference to a string array"); break; case stNUMBER: strcpy (desc, "a number"); break; case stNUMBERARRAYREF: strcpy (desc, "a reference to a numeric array"); break; case stLABEL: strcpy (desc, "a label"); break; case stRETADD: strcpy (desc, "a return address for gosub"); break; case stRETADDCALL: strcpy (desc, "a return address for a subroutine"); break; case stFREE: strcpy (desc, "nothing"); break; case stROOT: strcpy (desc, "the root of the stack"); break; case stANY: strcpy (desc, "anything"); break; case stSTRING_OR_NUMBER: strcpy (desc, "a string or a number"); break; case stSTRING_OR_NUMBER_ARRAYREF: strcpy (desc, "reference to a string or an array"); break; case stSWITCH_STRING: strcpy (desc, "number for switch"); break; case stSWITCH_NUMBER: strcpy (desc, "string for switch"); break; default: sprintf (desc, "type %d", type); break; }}voidpushname (char *name) /* bison: push a name on stack */{ struct stackentry *s; s = push (); s->pointer = my_strdup (name); s->type = stSTRING;}voidpushlabel () /* bison: generate goto and push label on stack */{ char *st; struct stackentry *en; st = (char *) my_malloc (sizeof (char) * 20); sprintf (st, "***%d", labelcount); labelcount++; create_goto (st); en = push (); en->type = stLABEL; en->pointer = st;}voidpoplabel () /* bison: pops a label and generates the matching command */{ create_label (pop (stLABEL)->pointer, cLABEL); /* and create it */}voidpushgoto () /* bison: generate label and push goto on stack */{ char *st; struct stackentry *en; st = (char *) my_malloc (sizeof (char) * 20); sprintf (st, "***%d", labelcount); labelcount++; create_label (st, cLABEL); en = push (); en->type = stGOTO; en->pointer = st;}voidpopgoto () /* bison: pops a goto and generates the matching command */{ create_goto (pop (stGOTO)->pointer); /* and create it */}voidstorelabel () /* bison: push label on stack */{ char *st; struct stackentry *en; st = (char *) my_malloc (sizeof (char) * 20); sprintf (st, "***%d", labelcount); labelcount++; en = push (); en->type = stLABEL; en->pointer = st;}voidmatchgoto () /* bison: generate goto matching label on stack */{ create_goto (stackhead->prev->pointer);}voidcreate_pushdbl (double value) /* create command 'cPUSHDBL' */{ struct command *cmd; cmd = add_command (cPUSHDBL, NULL); cmd->pointer = my_malloc (sizeof (double)); *(double *) (cmd->pointer) = value;}voidpushdbl (struct command *cmd){ /* push double onto stack */ struct stackentry *p; p = push (); p->value = *(double *) cmd->pointer; p->type = stNUMBER;}voidpushdblsym (struct command *cmd){ /* push double symbol onto stack */ struct stackentry *p; p = push (); if (!cmd->name) error (WARNING, "invalid pushdblsym"); if (!cmd->symbol) cmd->symbol = &(get_sym (cmd->name, syNUMBER, amADD_GLOBAL)->value); p->value = *(double *) cmd->symbol; p->type = stNUMBER;}voidpopdblsym (struct command *cmd) /* pop double from stack */{ double d; d = pop (stNUMBER)->value; if (!cmd->symbol) cmd->symbol = &(get_sym (cmd->name, syNUMBER, amADD_GLOBAL)->value); *(double *) (cmd->symbol) = d;}voidcreate_makelocal (char *name, int type) /* create command 'cMAKELOCAL' */{ struct command *cmd; cmd = add_command (cMAKELOCAL, name); cmd->args = type;}voidmakelocal (struct command *cmd) /* makes symbol local */{ if (get_sym (cmd->name, cmd->args, amSEARCH_VERY_LOCAL)) { sprintf (string, "local variable '%s' already defined within this subroutine", strip (cmd->name)); error (ERROR, string); return; } get_sym (cmd->name, cmd->args, amADD_LOCAL);}voidcreate_numparam (void) /* create command 'cNUMPARAM' */{ struct command *cmd; /* dotifying numparams at compiletime (as opposed to runtime) is essential, because the function name is not known at runtime */ cmd = add_command (cNUMPARAM, dotify ("numparams", FALSE));}voidnumparam (struct command *cmd) /* count number of function parameters */{ struct symbol *sym; sym = get_sym (cmd->name, syNUMBER, amADD_LOCAL); sym->value = abs (count_args (FALSE));}voidcreate_makestatic (char *name, int type) /* create command 'cMAKESTATIC' */{ struct command *cmd; cmd = add_command (cMAKESTATIC, name); cmd->args = type;}voidmakestatic (struct command *cmd) /* makes symbol static */{ struct symbol *l, *g; char *at = NULL; /* mask function name */ if ((at = strchr (cmd->name, '@')) != NULL) *at = '\0'; if (get_sym (cmd->name, cmd->args, amSEARCH_VERY_LOCAL)) { sprintf (string, "static variable '%s' already defined within this subroutine", strip (cmd->name)); error (ERROR, string); return; } /* create global variable with unique name */ if (at) *at = '@'; g = get_sym (cmd->name, cmd->args, amADD_GLOBAL); if (at) *at = '\0'; /* create local variable */ l = get_sym (cmd->name, cmd->args, amADD_LOCAL); if (at) *at = '@'; /* link those two together */ link_symbols (l, g);}voidcreate_arraylink (char *name, int type) /* create command 'cARRAYLINK' */{ struct command *cmd; cmd = add_command (cARRAYLINK, name); cmd->pointer = current_function; cmd->args = type;}voidarraylink (struct command *cmd) /* link a local symbol to a global array */{ struct symbol *l, *g; struct array *ar; if (get_sym (cmd->name, cmd->args, amSEARCH_VERY_LOCAL)) { sprintf (string, "'%s()' already defined within this subroutine", strip (cmd->name)); error (ERROR, string); return; } /* get globally defined array */ g = get_sym (pop (cmd->args)->pointer, syARRAY, amSEARCH_PRE); /* create local array */ l = get_sym (cmd->name, syARRAY, amADD_LOCAL); if (!l) return; if (!g || !g->pointer) { /* no global array supplied, create one */ error (DEBUG, "creating dummy array"); ar = create_array ((cmd->args == stNUMBERARRAYREF) ? 'd' : 's', 0); l->pointer = ar; if (infolevel >= DEBUG) { sprintf (string, "creating 0-dimensional dummy array '%s()'", cmd->name); error (DEBUG, string); } } else { /* link those two together */ link_symbols (l, g); }}voidcreate_pusharrayref (char *name, int type) /* create command 'cPUSHARRAYREF' */{ struct command *cmd; cmd = add_command (cPUSHARRAYREF, name); cmd->args = type;}voidpusharrayref (struct command *cmd) /* push an array reference onto stack */{ struct stackentry *s; s = push (); s->type = cmd->args; s->pointer = my_strdup (cmd->name);}voidcreate_require (int type) /* create command 'cREQUIRE' */{ struct command *cmd; cmd = add_command (cREQUIRE, NULL); cmd->args = type;}voidrequire (struct command *cmd) /* check, that item on stack has right type */{ char *expected, *supplied; struct stackentry *s; if (stackhead->prev->type == cmd->args) return; /* okay, they match */ if (stackhead->prev->type == stFREE) { /* no argument supplied, create it */ s = push (); if (cmd->args == stSTRING) { s->type = stSTRING; s->pointer = my_strdup (""); return; } else if (cmd->args == stNUMBER) { s->type = stNUMBER; s->value = 0.0; return; } else { /* create array */ s->type = cmd->args; s->pointer = NULL; return; } } s = stackhead->prev; if (s->type == stSTRING) supplied = "string"; else if (s->type == stNUMBER) supplied = "number"; else if (s->type == stSTRINGARRAYREF) supplied = "string array"; else if (s->type == stNUMBERARRAYREF) supplied = "numeric array"; else if (s->type == stFREE) supplied = "nothing"; else supplied = "something strange"; if (cmd->args == stSTRING) expected = "string"; else if (cmd->args == stNUMBER) expected = "number"; else if (cmd->args == stSTRINGARRAYREF) expected = "string array"; else if (cmd->args == stNUMBERARRAYREF) expected = "numeric array"; else if (cmd->args == stFREE) expected = "nothing"; else expected = "something strange"; sprintf (string, "invalid subroutine call: %s expected, %s supplied", expected, supplied); error (ERROR, string);}voidcreate_dblbin (char c) /* create command for binary double operation */{ switch (c) { case '+': add_command (cDBLADD, NULL); break; case '-': add_command (cDBLMIN, NULL); break; case '*': add_command (cDBLMUL, NULL); break; case '/': add_command (cDBLDIV, NULL); break; case '^': add_command (cDBLPOW, NULL); break; } /* no specific information needed */}voiddblbin (struct command *cmd) /* compute with two numbers from stack */{ struct stackentry *d; double a, b, c; b = pop (stNUMBER)->value; a = pop (stNUMBER)->value; d = push (); switch (cmd->type) { case (cDBLADD): c = a + b; break; case (cDBLMIN): c = a - b; break; case (cDBLMUL): c = a * b; break; case (cDBLDIV): if (fabs (b) < DBL_MIN) { sprintf (string, "Division by zero, set to %g", DBL_MAX); error (NOTE, string); c = DBL_MAX; } else c = a / b; break; case (cDBLPOW): if ((a == 0 && b <= 0) || (a < 0 && b != (int) b)) { error (ERROR, "result is not a real number"); return; } else { c = pow (a, b); } break; } d->value = c; d->type = stNUMBER;}voidnegate () /* negates top of stack */{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -