📄 symbol.c
字号:
p=push(); p->value= *(double *)cmd->pointer; p->type=stNUMBER;}void pushdblsym(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;}void popdblsym(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;}void create_makelocal(char *name,int type) /* create command 'cMAKELOCAL' */{ struct command *cmd; cmd=add_command(cMAKELOCAL,name); cmd->args=type;}void makelocal(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);}void create_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));}void numparam(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));}void create_makestatic(char *name,int type) /* create command 'cMAKESTATIC' */{ struct command *cmd; cmd=add_command(cMAKESTATIC,name); cmd->args=type;}void makestatic(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);}void create_arraylink(char *name,int type) /* create command 'cARRAYLINK' */{ struct command *cmd; cmd=add_command(cARRAYLINK,name); cmd->pointer=current_function; cmd->args=type;}void arraylink(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); }}void create_pusharrayref(char *name,int type) /* create command 'cPUSHARRAYREF' */{ struct command *cmd; cmd=add_command(cPUSHARRAYREF,name); cmd->args=type;}void pusharrayref(struct command *cmd) /* push an array reference onto stack */{ struct stackentry *s; s=push(); s->type=cmd->args; s->pointer=my_strdup(cmd->name);}void create_require(int type) /* create command 'cREQUIRE' */{ struct command *cmd; cmd=add_command(cREQUIRE,NULL); cmd->args=type;}void require(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);}void create_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 */}void dblbin(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;}void negate() /* negates top of stack */{ stackhead->prev->value=-stackhead->prev->value;}void pushstrptr(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;}void pushstrsym(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;}void popstrsym(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);}void create_pushstr(char *s) /* creates command pushstr */{ struct command *cmd; cmd=add_command(cPUSHSTR,NULL); cmd->pointer=my_strdup(s); /* store string */}void pushstr(struct command *cmd) { /* push string onto stack */ struct stackentry *p; p=push(); p->pointer=my_strdup((char *)cmd->pointer); p->type=stSTRING;}void duplicate(void) /* duplicate topmost element of stack */{ struct stackentry *s; double actual; actual=stackhead->prev->value; s=push(); s->type=stNUMBER; s->value=actual;}void create_goto(char *label) /* creates command goto */{ struct command *cmd; cmd=add_command(cGOTO,NULL); /* specific info */ cmd->pointer=my_strdup(label);}void create_gosub(char *label) /* creates command gosub */{ struct command *cmd; cmd=add_command(cGOSUB,NULL); /* specific info */ cmd->pointer=my_strdup(label);}void create_call(char *label) /* creates command function call */{ struct command *cmd; cmd=add_command(cCALL,NULL); /* specific info */ cmd->pointer=my_strdup(label);}static void link_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;}void jump(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"); }}void reshufflestack(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; }}void myreturn(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;}void create_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);}void create_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);}void decide() /* skips next command, if not 0 on stack */{ if (pop(stNUMBER)->value!=0) current=current->next; /* skip one command */}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -