📄 symbol.c
字号:
cur = 1; for (i = 0; i < 10; i++) { if (bound[i]) cur *= bound[i]; ind[i] = 0; } for (i = 9; i >= 0; i--) { if (bound[i]) { cur /= bound[i]; ind[i] = off / cur; off -= ind[i] * cur; } else { ind[i] = 0; } }}voidquery_array (struct command *cmd) /* query array */{ int index; struct stackentry *s; struct array *ar; struct symbol *sym; if (cmd->type == cARSIZE) index = (int) pop (stNUMBER)->value; s = pop (stSTRING_OR_NUMBER_ARRAYREF); if (!cmd->symbol) { sym = get_sym (s->pointer, syARRAY, amSEARCH); if (!sym || !sym->pointer) { sprintf (string, "array '%s()' is not defined", strip (s->pointer)); error (ERROR, string); return; } cmd->symbol = sym; } ar = ((struct symbol *) cmd->symbol)->pointer; if (cmd->type == cARSIZE && (index < 1 || index > ar->dimension)) { sprintf (string, "only indices between 1 and %d allowed", ar->dimension); error (ERROR, string); return; } s = push (); s->type = stNUMBER; if (cmd->type == cARSIZE) s->value = ar->bounds[ar->dimension - index] - 1; else s->value = ar->dimension; return;}voidcreate_doarray (char *symbol, int command) /* creates array-commands */{ struct command *cmd; cmd = add_command (cDOARRAY, symbol); cmd->tag = command; /* operation to perform */ cmd->args = -1;}voiddoarray (struct command *cmd) /* call an array */{ struct array *ar; struct stackentry *stack; struct symbol *sym; void *p; char **str; double *dbl; int i, j, bnd, index, cur, rval; if (!cmd->symbol) { sym = get_sym (cmd->name, syARRAY, amSEARCH); if (!sym || !sym->pointer) { sprintf (string, "'%s()' is neither array nor subroutine", strip (cmd->name)); error (ERROR, string); return; } cmd->symbol = sym; } rval = (current->tag == CALLARRAY || current->tag == CALLSTRINGARRAY || current->tag == GETSTRINGPOINTER); if (cmd->args < 0) cmd->args = count_args (!rval); if (cmd->args < 0) { error (ERROR, "only numerical indices allowed for arrays"); return; } cmd->args = abs (cmd->args); if (!cmd->args) { /* no indizes supplied, create a reference to an array */ pop (stFREE); /* remove left over stFREE */ stack = push (); if (cmd->tag == CALLARRAY) stack->type = stNUMBERARRAYREF; else stack->type = stSTRINGARRAYREF; stack->pointer = my_strdup (cmd->name); return; } ar = ((struct symbol *) cmd->symbol)->pointer; if (!ar->dimension) { sprintf (string, "array parameter '%s()' has not been supplied", strip (cmd->name)); error (ERROR, string); return; } if (cmd->args != ar->dimension) { sprintf (string, "%d indices supplied, %d expected for '%s()'", cmd->args, ar->dimension, strip (cmd->name)); error (ERROR, string); return; } if (!rval) stack = pop (stSTRING_OR_NUMBER); index = 0; cur = 1; for (i = 0; i < ar->dimension; i++) { bnd = (ar->bounds[i]); j = (int) pop (stNUMBER)->value; if (j < 0 || j >= bnd) { sprintf (string, "index %d (=%d) out of range", ar->dimension - i, j); error (ERROR, string); return; } index += j * cur; cur *= bnd; } pop (stFREE); /* remove left over stFREE */ if (rval) stack = push (); p = ar->pointer; switch (current->tag) { case CALLARRAY: dbl = (double *) p + index; stack->value = *dbl; stack->type = stNUMBER; break; case ASSIGNARRAY: dbl = (double *) p + index; *dbl = stack->value; break; case CALLSTRINGARRAY: str = ((char **) p + index); stack->pointer = my_strdup (*str); stack->type = stSTRING; break; case ASSIGNSTRINGARRAY: str = ((char **) p + index); if (*str != NULL) my_free (*str); *str = my_strdup (stack->pointer); break; case GETSTRINGPOINTER: str = ((char **) p + index); stack->pointer = *str; stack->type = stSTRING; break; }}struct array *create_array (int type, int dimension) /* create an array */{ int i; struct array *ar; ar = my_malloc (sizeof (struct array)); ar->type = type; ar->dimension = dimension; ar->pointer = NULL; for (i = 0; i < 10; i++) ar->bounds[i] = 0; return ar;}static intcount_args (int skipfirst) /* count number of numeric arguments on stack */{ int i = 0; int sign = 1; struct stackentry *curr; curr = stackhead->prev; if (skipfirst) curr = curr->prev; while (curr) { if (curr->type == stFREE) return i * sign; if (curr->type != stNUMBER) sign = -1; curr = curr->prev; i++; } return -1;}voidskipper ()/* used for on_goto/gosub, skip specified number of commands */{ int i, len; struct command *ahead; /* command to follow */ len = (int) pop (stNUMBER)->value; i = 1; current = current->next; /* advance to first goto/gosub */ for (i = 1; i < len; i++) { ahead = current->next->next; /* skip interleaving findnop statement */ if (ahead->type == cNOP) break; else current = ahead; }}voidskiponce (struct command *cmd) /* skip next command exectly once */{ if (cmd->tag) current = current->next; cmd->tag = 0;}voidresetskiponce (struct command *cmd) /* find and reset next skip */{ struct command *c; c = cmd; while (c->type != cSKIPONCE) c = c->next; c->tag = 1;}voidcreate_break_mark (int minor, int major) /* create marks for break */{ struct command *cmd; in_loop += major; cmd = add_command (cBREAK_MARK, NULL); cmd->tag = (major + 2) * 16 + minor + 2;}voidnext_case (void) /* go to next case in switch statement */{ if (stackhead->prev->type == stSTRING || stackhead->prev->type == stSWITCH_STRING) stackhead->prev->type = stSWITCH_STRING; else stackhead->prev->type = stSWITCH_NUMBER;}voidpush_switch_id (void) /* generate a new switch id */{ static int max_switch_id = 0; static int switch_stack_depth = 1; struct switch_id *new_id; if (switch_id_stackhead == NULL || switch_id_stackhead->next == NULL) { if (switch_id_stackroot && switch_id_stackhead == NULL) { new_id = switch_id_stackroot; } else { new_id = my_malloc (sizeof (struct switch_id)); new_id->next = NULL; new_id->depth = switch_stack_depth++; } } else { new_id = switch_id_stackhead->next; } max_switch_id++; new_id->id = max_switch_id; if (switch_id_stackhead == NULL) { switch_id_stackhead = new_id; switch_id_stackhead->prev = NULL; } else { switch_id_stackhead->next = new_id; new_id->prev = switch_id_stackhead; switch_id_stackhead = new_id; }}voidpop_switch_id (void) /* get previous switch id */{ if (switch_id_stackhead) switch_id_stackhead = switch_id_stackhead->prev;}intget_switch_id (void) /* get current switch id */{ return switch_id_stackhead ? switch_id_stackhead->id : 0;}intget_switch_depth (void) /* get current depth of switch id stack */{ return switch_id_stackhead ? switch_id_stackhead->depth : 0;}voidpush_switch_mark (void) /* push a switch mark */{ push ()->type = stSWITCH_MARK;}voidcreate_clean_switch_mark (int keep, int ret) /* add command clean_switch_mark */{ struct command *cmd; cmd = add_command (cCLEAN_SWITCH_MARK, NULL); cmd->args = keep; cmd->tag = ret;}voidclean_switch_mark (struct command *cmd) /* pop everything up to (and including) first switch_mark from stack */{ struct stackentry *t, *tt, *b, *bb, *s; int keep, k, ret; k = keep = cmd->args; ret = cmd->tag; s = stackhead->prev; while (k && s != stackroot) { k--; s = s->prev; } t = s; tt = s->next; while (((ret && s->type != stRETADDCALL) || (!ret && s->type != stSWITCH_MARK)) && s != stackroot) { s = s->prev; } if (ret) { bb = s; b = s->next; } else { b = s; bb = s->prev; } /* cut part between (and including) b and t out of stack */ bb->next = tt; tt->prev = bb; /* insert cut-out part between stackhead and stackhead->prev */ stackhead->prev->next = b; b->prev = stackhead->prev; t->next = stackhead; stackhead->prev = t; if (keep) stackhead = tt->next; else stackhead = bb->next;}voidmybreak (struct command *cmd) /* find break_here statement */{ struct command *curr; int major, minor; int major_nesting = 0; int minor_nesting = 0; if (cmd->type == cBREAK) major_nesting = 1; else minor_nesting = 0; curr = cmd; while (curr->type != cBREAK_HERE || major_nesting || minor_nesting) { if (curr->type == cBREAK_MARK) { minor = (curr->tag & 15) - 2; major = ((curr->tag & 240) / 16) - 2; if (!major_nesting) minor_nesting += minor; major_nesting += major; if (infolevel >= DEBUG) { sprintf (string, "searching break-mark: diff(%d,%d), total(%d,%d)", minor, major, minor_nesting, major_nesting); error (DEBUG, string); } } curr = curr->next; if (!curr) error (FATAL, "break has left program"); } cmd->type = cQGOTO; if (infolevel >= DEBUG) error (DEBUG, "converting cBREAK to cQGOTO"); cmd->jump = current = curr;}voidmycontinue (struct command *cmd) /* find continue_here statement */{ struct command *curr; int major; int major_nesting = -1; curr = cmd; while (curr->type != cCONTINUE_HERE || major_nesting) { if (curr->type == cBREAK_MARK) { major = ((curr->tag & 240) >> 4) - 2; major_nesting += major; } if (curr->type == cCONTINUE_CORRECTION) major_nesting--; curr = curr->prev; if (!curr) error (FATAL, "continue has left program"); } cmd->type = cQGOTO; if (infolevel >= DEBUG) error (DEBUG, "converting cCONTINUE to cQGOTO"); cmd->jump = current = curr;}voidfindnop ()/* used for on_gosub, find trailing nop command */{ while (current->type != cNOP) { current = current->next; /* next label */ }}voidforcheck (void) /* check, if for-loop is done */{ double start, bound, step, val; val = pop (stNUMBER)->value; step = pop (stNUMBER)->value; bound = pop (stNUMBER)->value; start = stackhead->prev->value; if ((val <= bound && val >= start && step >= 0) || (val <= start && val >= bound && step <= 0)) stackhead->prev->value = 1.; else stackhead->prev->value = 0.;}voidforincrement (void) /* increment value on stack */{/* expecting on stack: BOUND,STEP,VAL,stackhead where for VAL=START to BOUND step STEP */ stackhead->prev->value += stackhead->prev->prev->value;}voidstartfor (void) /* compute initial value of for-variable */{ struct stackentry *p; p = push (); p->value = stackhead->prev->prev->prev->prev->value - stackhead->prev->prev->value; p->type = stNUMBER; return;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -