📄 symbol.c
字号:
stackhead->prev->value = -stackhead->prev->value;}voidpushstrptr (struct command *cmd) /* push string-pointer onto stack */{ struct stackentry *p; p = push (); if (!cmd->symbol) cmd->symbol = &(get_sym (cmd->name, sySTRING, amADD_GLOBAL)->pointer); p->pointer = *(char **) cmd->symbol; if (!p->pointer) p->pointer = my_strdup (""); p->type = stSTRING;}voidpushstrsym (struct command *cmd) /* push string-symbol onto stack */{ struct stackentry *p; p = push (); if (!cmd->symbol) cmd->symbol = &(get_sym (cmd->name, sySTRING, amADD_GLOBAL)->pointer); p->pointer = my_strdup (*(char **) cmd->symbol); p->type = stSTRING;}voidpopstrsym (struct command *cmd) /* pop string from stack */{ if (!cmd->name) return; if (!cmd->symbol) cmd->symbol = &(get_sym (cmd->name, sySTRING, amADD_GLOBAL)->pointer); if (*(char **) cmd->symbol != NULL) my_free (*(char **) cmd->symbol); *(char **) cmd->symbol = my_strdup (pop (stSTRING)->pointer);}voidcreate_pushstr (char *s) /* creates command pushstr */{ struct command *cmd; cmd = add_command (cPUSHSTR, NULL); cmd->pointer = my_strdup (s); /* store string */}voidpushstr (struct command *cmd){ /* push string onto stack */ struct stackentry *p; p = push (); p->pointer = my_strdup ((char *) cmd->pointer); p->type = stSTRING;}voidduplicate (void) /* duplicate topmost element of stack */{ struct stackentry *s; double actual; actual = stackhead->prev->value; s = push (); s->type = stNUMBER; s->value = actual;}voidcreate_goto (char *label) /* creates command goto */{ struct command *cmd; cmd = add_command (cGOTO, NULL); /* specific info */ cmd->pointer = my_strdup (label);}voidcreate_gosub (char *label) /* creates command gosub */{ struct command *cmd; cmd = add_command (cGOSUB, NULL); /* specific info */ cmd->pointer = my_strdup (label);}voidcreate_call (char *label) /* creates command function call */{ struct command *cmd; cmd = add_command (cCALL, NULL); /* specific info */ cmd->pointer = my_strdup (label);}static voidlink_label (struct command *cmd) /* link label into list of labels */{ if (!labelroot) labelroot = cmd; else labelhead->nextassoc = cmd; labelhead = cmd;}struct command *search_label (char *name, int type) /* search label */{ struct command *curr; char *at = NULL; curr = labelroot; if (type & smGLOBAL) { at = strchr (name, '@'); if (at) *at = '\0'; } while (curr) { if ((type & smSUB) && curr->type == cUSER_FUNCTION && !strcmp (curr->pointer, name)) { if (at) *at = '@'; return curr; } if ((type & smLINK) && curr->type == cSUBLINK && !strcmp (curr->pointer, name)) { if (at) *at = '@'; return curr->next; } if ((type & smLABEL) && curr->type == cLABEL && !strcmp (curr->pointer, name)) { if (at) *at = '@'; return curr; } curr = curr->nextassoc; } return NULL;}voidjump (struct command *cmd)/* jump to specific Label; used as goto, gosub or function call */{ struct command *label; struct stackentry *ret; int type; char *dot; type = cmd->type; if (type == cGOSUB || type == cQGOSUB || type == cCALL || type == cQCALL) { /* leave return address for return */ ret = push (); ret->pointer = current; if (type == cGOSUB || type == cQGOSUB) { ret->type = stRETADD; } else { ret->type = stRETADDCALL; reshufflestack (ret); } } if (type == cQGOSUB || type == cQGOTO || type == cQCALL) { current = (struct command *) cmd->jump; /* use remembered address */ return; } label = search_label (cmd->pointer, smSUB | smLINK | smLABEL); if (!label && type == cCALL && (dot = strchr (cmd->pointer, '.'))) { strcpy (string, "main"); strcat (string, dot); label = search_label (string, smLINK); } if (label) { /* found right label */ current = label; /* jump to new location */ /* use the address instead of the name next time */ cmd->jump = label; switch (cmd->type) { case cGOTO: cmd->type = cQGOTO; break; case cGOSUB: cmd->type = cQGOSUB; break; case cCALL: cmd->type = cQCALL; break; } } else { /* label not found */ sprintf (string, "can't find %s '%s'", (type == cCALL) ? "subroutine" : "label", strip ((char *) cmd->pointer)); if (strchr (cmd->pointer, '@')) strcat (string, " (not in this sub)"); error (ERROR, string); } /* check, if goto enters or leaves a switch_statement */ if (cmd->type == cQGOTO) { if (label->switch_id && !cmd->switch_id) error (ERROR, "cannot jump into switch-statement"); else if (!label->switch_id && cmd->switch_id) error (ERROR, "cannot jump out of switch-statement"); else if (label->switch_id != cmd->switch_id) error (ERROR, "cannot jump between switch statements"); }}voidreshufflestack (struct stackentry *ret) /* reorganize stack for function call */{ struct stackentry *a, *b, *c; struct stackentry *top, *bot; struct stackentry *ttop, *bbot; int args; /* this is a function call; revert stack and shuffle return address to bottom */ /* push address below parameters */ args = 0; top = a = ret->prev; while (a->type != stFREE) { a = a->prev; args++; } bot = a->next; b = a->prev; /* remove ret */ ret->prev->next = ret->next; ret->next->prev = ret->prev; /* squeeze ret between a and b */ ret->next = a; a->prev = ret; b->next = ret; ret->prev = b; /* revert stack between top and bot */ if (args > 1) { a = bot; b = a->next; bbot = bot->prev; ttop = top->next; for (; args > 1; args--) { a->prev = b; c = b->next; b->next = a; a = b; b = c; } bot->next = ttop; bot->next->prev = bot; top->prev = bbot; top->prev->next = top; }}voidmyreturn (struct command *cmd) /* return from gosub of function call */{ struct stackentry *address; address = pop (stANY); if (cmd->type == cRET_FROM_FUN) { if (address->type != stRETADDCALL) { error (ERROR, "RETURN from a subroutine without CALL"); return; } } else { if (address->type != stRETADD) { error (ERROR, "RETURN without GOSUB"); return; } } current = (struct command *) address->pointer; return;}voidcreate_label (char *label, int type) /* creates command label */{ struct command *cmd; /* check, if label is duplicate */ if (search_label (label, smSUB | smLINK | smLABEL)) { sprintf (string, "duplicate %s '%s'", (type == cLABEL) ? "label" : "subroutine", strip (label)); error (ERROR, string); return; } cmd = add_command (type, NULL); /* store label */ cmd->pointer = my_strdup (label); link_label (cmd);}voidcreate_sublink (char *label) /* create link to subroutine */{ char global[200]; char *dot; struct command *cmd; if (!inlib) return; dot = strchr (label, '.'); strcpy (global, "main"); strcat (global, dot); /* check, if label is duplicate */ if (search_label (global, smSUB | smLINK | smLABEL)) { sprintf (string, "duplicate subroutine '%s'", strip (global)); error (ERROR, string); return; } cmd = add_command (cSUBLINK, NULL); /* store label */ cmd->pointer = my_strdup (global); link_label (cmd);}voiddecide () /* skips next command, if not 0 on stack */{ if (pop (stNUMBER)->value != 0) current = current->next; /* skip one command */}voidcreate_dim (char *name, char type) /* create command 'dim' *//* type can be 's'=string or 'd'=double Array */{ struct command *cmd; cmd = add_command (cDIM, name); cmd->tag = type; /* type: string or double */ cmd->args = -1;}voiddim (struct command *cmd) /* get room for array */{ struct array *nar, *oar; char *nul; int ntotal, ototal, esize, i, j; int ind[10], nbounds[10], larger; struct symbol *s; int local; local = ((cmd->tag == tolower (cmd->tag)) ? TRUE : FALSE); if (cmd->args < 0) cmd->args = count_args (FALSE); if (cmd->args < 0) { error (ERROR, "only numerical indices allowed for arrays"); return; } s = get_sym (cmd->name, syARRAY, local ? amADD_LOCAL : amADD_GLOBAL); if (search_label (cmd->name, smSUB | smLINK)) { sprintf (string, "array '%s()' conflicts with user subroutine", strip (cmd->name)); error (ERROR, string); return; } /* check for dimensions */ if (cmd->args > 10) { error (ERROR, "more than 10 indices"); return; } oar = s->pointer; if (oar) { /* check, if old and new array are compatible */ if (cmd->args != oar->dimension) { sprintf (string, "cannot change dimension of '%s()' from %d to %d", strip (cmd->name), oar->dimension, cmd->args); error (ERROR, string); } } /* check, if redim is actually needed */ for (i = 0; i < 10; i++) nbounds[i] = 0; larger = FALSE; for (i = 0; i < cmd->args; i++) { nbounds[i] = 1 + (int) pop (stNUMBER)->value; if (nbounds[i] <= 1) { sprintf (string, "array index %d is less or equal zero", cmd->args - i); error (ERROR, string); return; } if (oar) { if (nbounds[i] > oar->bounds[i]) larger = TRUE; else nbounds[i] = oar->bounds[i]; } } pop (stFREE); /* remove left over stFREE */ if (oar && !larger) return; /* new array won't be larger than old one */ /* create array */ nar = create_array (tolower (cmd->tag), cmd->args); /* count needed memory */ ntotal = 1; for (i = 0; i < nar->dimension; i++) { (nar->bounds)[i] = nbounds[i]; ntotal *= nbounds[i]; } esize = (nar->type == 's') ? sizeof (char *) : sizeof (double); /* size of one array element */ nar->pointer = my_malloc (ntotal * esize); if (oar) { /* array already exists, get its size */ ototal = 1; for (i = 0; i < oar->dimension; i++) ototal *= (oar->bounds)[i]; } /* initialize Array */ for (i = 0; i < ntotal; i++) { if (nar->type == 's') { nul = my_malloc (sizeof (char)); *nul = '\0'; ((char **) nar->pointer)[i] = nul; } else { ((double *) nar->pointer)[i] = 0.0; } } if (oar) { /* copy contents of old array onto new */ for (i = 0; i < ototal; i++) { off_to_ind (i, oar->bounds, ind); j = ind_to_off (ind, nar->bounds); if (nar->type == 's') { my_free (((char **) nar->pointer)[j]); ((char **) nar->pointer)[j] = ((char **) oar->pointer)[i]; } else { ((double *) nar->pointer)[j] = ((double *) oar->pointer)[i]; } } my_free (oar->pointer); my_free (oar); } s->pointer = nar; cmd->symbol = nar;}static intind_to_off (int *ind, int *bound) /* convert array of indices to single offset */{ int i; int cur, off; off = 0; cur = 1; for (i = 0; i < 10 && bound[i]; i++) { off += ind[i] * cur; cur *= bound[i]; } return off;}static voidoff_to_ind (int off, int *bound, int *ind) /* convert a single offset to an array of indices */{ int i; int cur;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -