void ForFunc::execute() { static int body_symid = symbol_add("body"); ComValue initexpr(stack_arg_post_eval(0)); ComValue* bodyexpr = nil; while (1) { ComValue whileexpr(stack_arg_post_eval(1)); if (whileexpr.is_false()) break; delete bodyexpr; ComValue keybody(stack_key_post_eval(body_symid, false, ComValue::unkval(), true)); if (keybody.is_unknown() && nargsfixed()>= 4) bodyexpr = new ComValue(stack_arg_post_eval(3)); else bodyexpr = new ComValue(keybody); ComValue nextexpr(stack_arg_post_eval(2)); } reset_stack(); if (bodyexpr) { push_stack(*bodyexpr); delete bodyexpr; } else push_stack(ComValue::nullval()); }
int syntaxan (int token,symbol * sym) { static unsigned char num_channel; static unsigned char channels[12]={0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; static symbol ptr; switch (status) { case STATUS_INIT: /* Initial status */ recst = STATUS_INIT; /*Save actual state for error handling */ switch (token) { case VAR: /* Begin variable declaration */ status = STATUS_BEGIN_VAR_DECL; return 0; case CHANNEL: /* Begin channel declaration */ status = STATUS_BEGIN_CHN_DECL; return 0; case IDEN: /* Begin assign statement */ status = STATUS_BEGIN_GLOBAL_ASGN; /* TODO: Join to local assign */ if ((*sym = searchsym(lexcad)) == NULL) rerror(ESYNTAX, EIDEN_NAME, 0); return 0; case LN: /* Empty sentence */ return 1; default: rerror(ESYNTAX, E_INI, 0); } /* Variable declaration states */ case STATUS_BEGIN_VAR_DECL: /* VAR ; variable declaration */ switch (token) { case IDEN: /* Name of the variable */ status = STATUS_NAME_VAR_DECL; *sym = newsymbol(lexcad); return 0; default: rerror(ESYNTAX, E_VAR_DECL, 0); } case STATUS_NAME_VAR_DECL: /* VAR IDEN ; variable declaration */ switch (token) { case LN: /* end of declaration */ status = STATUS_INIT; insvar(*sym); return 1; case COMA: /* multiple declaration */ status = STATUS_BEGIN_VAR_DECL; insvar(*sym); return 0; default: rerror(ESYNTAX, E_VAR_DECL, 0); } /* Channel declaration states */ case STATUS_BEGIN_CHN_DECL: /* CHANNEL ; channel declaration */ switch (token) { case NUMBER: /* Number of the channel */ status = STATUS_END_OF_CHANNEL; num_channel = atoi(lexcad) - 1; if(num_channel >= 12) rerror(ESYNTAX, E_BAD_CH, 0); else { ssymval(syms1, num_channel); *sym = syms1; } if(channels[num_channel]) rerror(ESYNTAX, E_DECL_CH, 0); channels[num_channel]=1; return 0; case IDEN: /* Variable with the name of the channel */ status = STATUS_END_OF_CHANNEL; if ((*sym = searchsym(lexcad)) == NULL) rerror(ESYNTAX, EIDEN_NAME, 0); else if ((num_channel = gsymval(*sym)) >= 12) rerror(ESYNTAX, E_BAD_CH, 0); if (channels[num_channel]) rerror(ESYNTAX, E_DECL_CH, 0); channels[num_channel] = 1; return 0; default: rerror(ESYNTAX, E_CHANNEL, 0); } /* end of channel declaration */ case STATUS_END_OF_CHANNEL: /* CHANNEL IDEN | NUMBER ; end of channl dcl*/ switch (token) { case LN: /* finish channel dcl */ status = STATUS_BEGIN_CHN_BODY; inscode2(CHANNEL, gsymval(*sym)); return 1; default: rerror(ESYNTAX, E_CHANNEL, 0); } /* Begin channel body */ case STATUS_BEGIN_CHN_BODY: /* CHANNEL IDEN | NUMBER LN ; chl body*/ recst = STATUS_BEGIN_CHN_BODY; /*Save state for error handling*/ switch (token) { case LN: return 1; case ENDC: /* end of channel statement */ status = STATUS_BEGIN_ENDC; initsym(syms1, token, token); *sym = syms1; return 0; case PLAY: status = 11; /* play statement */ initexpr(); initsym(syms1, token, token); *sym = syms1; return 0; case SIL: /* silence statement */ case DECOC: /* dec octave statement */ case INCOC: /* inc octave statement */ case ENDL: /* end of loop statement */ case DECV: /* dec volume */ case INCV: /* inc volume */ status = STATUS_END_OF_1CMD; initsym(syms1, token, token); *sym = syms1; return 0; case OCT: /* octave statement */ case VOL: /* volume statement */ case BAT: /* battery statement */ case INST: /* instrument statement */ case LOOP: /* loop statement */ case AMPL: case VIB: /* vibrato statement */ case TIMES: /* time short format statement */ case TIMEL: /* time long format statement */ case DIVSUS: case BATL: /* battery long format statement */ case INSTL: /* instrument long format statement */ case FREC: /* set frequency statement */ status = STATUS_BEGIN_EXP_2CMD; initexpr(); initsym(syms1, token, token); *sym = syms1; return 0; case TIMEP: status = 39; initexpr(); initsym(syms1, token, token); initsym(syms2, NUMBER, 0); ssymsig(syms2, syms1); *sym = syms2; return 0; case REGFM: /* write to fm register statement */ status = 8; initexpr(); initsym(syms1, token, token); *sym = syms1; return 0; case PAR: /* parameter statement */ status = 9; initsym(syms1, token, token); *sym = syms1; return 0; case IDEN: /* Begin a assign statement */ status = 10; if ((*sym = searchsym(lexcad)) == NULL) rerror(ESYNTAX, EIDEN_NAME, 0); return 0; default: rerror(ESYNTAX, E_UNK_COMM, 0); } /* End of 1 word statement */ case STATUS_END_OF_1CMD: switch (token) { case LN: status = STATUS_BEGIN_CHN_BODY; inscodeI(*sym, NULL, num_channel); return 1; default: rerror(ESYNTAX, E_BAD_COMM, 0); } case 8: switch (token) { case NUMBER: status = 21; initsym(syms3, NUMBER, 0); ssymsig(syms3,*sym); *sym = syms3; pushexp(NUMBER, atoi(lexcad)); return 0; case IDEN: status = 21; if((ptr = searchsym(lexcad)) == NULL) rerror(ESYNTAX, EIDEN_NAME, 0); initsym(syms3, NUMBER, 0); ssymsig(syms3,*sym); *sym = syms3; pushexp(NUMBER, gsymval(ptr)); return 0; case PARI: status = 22; ssymsig(syms3,*sym); *sym = syms3; pushexp(token, 0); return 0; default: rerror(ESYNTAX, E_EXP, 0); } case 9: switch (token) { case ENVLOFF: case ENVLON: case SUSON: case HFNUM: case LFNUM: case NOISE: case TONE: status = STATUS_END_OF_1CMD; initsym(syms2, token, token); ssymsig(syms2,*sym); *sym = syms2; return 0; case DECO: status = STATUS_BEGIN_EXP_2CMD; initexpr(); initsym(syms3, token, token); ssymsig(syms3,*sym); *sym = syms3; return 0; case TAMP: status = STATUS_BEGIN_EXP_2CMD; initexpr(); initsym(syms3, token, token); ssymsig(syms3,*sym); *sym = syms3; return 0; case RITMON: status = STATUS_END_OF_1CMD; initsym(syms2, token, token); ssymsig(syms2,*sym); *sym = syms2; return 0; case MELON: status = STATUS_END_OF_1CMD; initsym(syms2, token, token); ssymsig(syms2,*sym); *sym = syms2; return 0; default: rerror(ESYNTAX, E_PAR, 0); } case 10: switch (token) { case EQ: status = STATUS_BEGIN_EXP_2CMD; initexpr(); initsym(syms3, EQ, EQ); ssymsig(syms3, *sym); *sym = syms3; return 0; default: rerror(ESYNTAX, E_ASIG, 0); } case 11: switch(token) { case NUMBER: status = STATUS_PLAY_EXPRESION; initsym(syms2, NUMBER, 0); ssymsig(syms2,*sym); *sym = syms2; pushexp(NUMBER, atoi(lexcad)); return 0; case IDEN: status = STATUS_PLAY_EXPRESION; if((ptr = searchsym(lexcad)) == NULL) rerror(ESYNTAX, EIDEN_NAME, 0); initsym(syms2, NUMBER, 0); ssymsig(syms2,*sym); *sym = syms2; pushexp(NUMBER, gsymval(ptr)); return 0; case PARI: status = STATUS_PLAY_EXPRESION; ssymsig(syms2,*sym); *sym = syms2; pushexp(token, 0); return 0; default: rerror(ESYNTAX, E_EXP, 0); } /* Begin end of channel statement */ case STATUS_BEGIN_ENDC: /* ENDC ; endc command */ switch(token) { case LN: status = 13; inscode(gsymval(*sym)); execute(); return 1; default: rerror(ESYNTAX, E_BAD_COMM, 0); } case 13: recst = 13; switch(token) { case WRITE: status = 38; return 0; case CHANNEL: status = STATUS_BEGIN_CHN_DECL; return 0; case LN: return 1; default: rerror(ESYNTAX, E_INI, 0); } case STATUS_BEGIN_GLOBAL_ASGN: switch(token) { case EQ: status = 15; initexpr(); return 0; default: rerror(ESYNTAX, E_ASIG, 0); } case 15: switch(token) { case NUMBER: status = 26; {pushexp(NUMBER, atoi(lexcad));}; return 0; case IDEN: status = 26; (ptr = searchsym(lexcad))?pushexp(NUMBER, gsymval(ptr)):rerror(ESYNTAX, EIDEN_NAME, 0); return 0; case PARI: status = 27; pushexp(token, 0); return 0; default: rerror(ESYNTAX, E_EXP, 0); } /*******************************************************************/ case STATUS_BEGIN_EXP_2CMD: switch (token) { case PARI: status = STATUS_EXP2_OPERAND; ssymsig(syms2,*sym); *sym = syms2; pushexp(token, 0); return 0; case NUMBER: status = STATUS_EXP2_OPERAND; initsym(syms2, NUMBER, 0); ssymsig(syms2,*sym); *sym = syms2; pushexp(NUMBER, atoi(lexcad)); return 0; case IDEN: status = STATUS_EXP2_OPERAND; if(!(ptr = searchsym(lexcad))) rerror(ESYNTAX, EIDEN_NAME, 0); initsym(syms2, NUMBER, 0); ssymsig(syms2,*sym); *sym = syms2; pushexp(NUMBER, gsymval(ptr)); return 0; default: rerror(ESYNTAX, E_EXP, 0); } case STATUS_EXP2_OPERAND: switch(token) { case NUMBER: status = STATUS_EXP2_OPERAND; pushexp(NUMBER, atoi(lexcad)); return 0; case IDEN: status = STATUS_EXP2_OPERAND; if ((ptr = searchsym(lexcad)) == NULL) rerror(ESYNTAX, EIDEN_NAME, 0); pushexp(NUMBER, gsymval(ptr)); return 0; case ADD: case SUB: case MUL: case DIV: case PARD: case PARI: /* left parenthesis */ status = STATUS_EXP2_OPERAND; pushexp(token, 0); return 0; case LN: status = recst; pushexp(token, 0); ssymval(*sym, evalexpr()); inscodeI(*sym, NULL, num_channel); return 1; default: rerror(ESYNTAX, E_EXP, 0); } /***********************************************/ /* initial assign expression*/ case 26: switch(token) { case ADD: status = 15; pushexp(token, 0); return 0; case SUB: status = 15; pushexp(token, 0); return 0; case MUL: status = 15; pushexp(token, 0); return 0; case DIV: status = 15; pushexp(token, 0); return 0; case LN: status = STATUS_INIT;{pushexp(token, 0);ssymval(*sym, evalexpr());} return 1; default: rerror(ESYNTAX, E_EXP, 0); } case 27: switch(token) { case NUMBER: status = 28;{pushexp(NUMBER, atoi(lexcad));}return 0; case IDEN: status = 28;{symbol ptr;(ptr = searchsym(lexcad))?pushexp(NUMBER, gsymval(ptr)):rerror(ESYNTAX, EIDEN_NAME, 0);}return 0; case PARI: status = 27; pushexp(token, 0); return 0; default: rerror(ESYNTAX, E_EXP, 0); } case 28: switch(token) { case PARD: status = 28; pushexp(token, 0); return 0; case ADD: status = 27; pushexp(token, 0); return 0; case SUB: status = 27; pushexp(token, 0); return 0; case MUL: status = 27; pushexp(token, 0); return 0; case DIV: status = 27; pushexp(token, 0); return 0; case LN: status = STATUS_INIT;{pushexp(token, 0);ssymval(*sym, evalexpr());}return 1; default: rerror(ESYNTAX, E_EXP, 0); } case 30: /*Expresion de play*/ case STATUS_PLAY_EXPRESION: switch(token) { case ADD: case SUB: case MUL: case DIV: status = 32; pushexp(token, 0); return 0; case SOS: status = STATUS_PLAY_SOST; return 0; case BEMOL: status = STATUS_PLAY_BEMOL; return 0; case COMA: case LN: pushexp(LN, 0); ssymval(*sym, evalexpr()); inscodeI(*sym, NULL, num_channel); if (token == COMA) { status = 32; initexpr(); return 0; } else { status = STATUS_BEGIN_CHN_BODY; return 1; } default: rerror(ESYNTAX, E_EXP, 0); } case 32: switch(token) { case NUMBER: status = 33;{pushexp(NUMBER, atoi(lexcad));}return 0; case IDEN: status = 33;{symbol ptr;(ptr = searchsym(lexcad))?pushexp(NUMBER, gsymval(ptr)):rerror(ESYNTAX, EIDEN_NAME, 0);}return 0; case PARI: status = 32; pushexp(token, 0); return 0; default: rerror(ESYNTAX, E_EXP, 0); } case 33: switch(token) { case PARD: status = 33; pushexp(token, 0); return 0; case ADD: status = 34; pushexp(token, 0); return 0; case SUB: status = 34; pushexp(token, 0); return 0; case MUL: status = 34; pushexp(token, 0); return 0; case DIV: status = 34; pushexp(token, 0); return 0; case SOS: status = STATUS_PLAY_SOST;{pushexp(token, 0);ssymval(*sym, evalexpr());}return 0; case BEMOL: status = STATUS_PLAY_BEMOL;{pushexp(token, 0);ssymval(*sym, evalexpr());}return 0; case COMA: status = 32;{pushexp(LN, 0);ssymval(*sym, evalexpr());inscodeI(*sym, NULL, num_channel);initexpr();} return 0; case LN: status = STATUS_BEGIN_CHN_BODY;{pushexp(token, 0);ssymval(*sym, evalexpr());inscodeI(*sym, NULL, num_channel);}return 1; default: rerror(ESYNTAX, E_EXP, 0); } case 34: switch(token) { case NUMBER: status = STATUS_PLAY_EXPRESION;{pushexp(NUMBER, atoi(lexcad));}return 0; case IDEN: status = STATUS_PLAY_EXPRESION;{symbol ptr;(ptr = searchsym(lexcad))?pushexp(NUMBER, gsymval(ptr)):rerror(ESYNTAX, EIDEN_NAME, 0);}return 0; case PARI: status = 32; pushexp(token, 0); return 0; default: rerror(ESYNTAX, E_EXP, 0); } case STATUS_PLAY_BEMOL: switch(token) { case BEMOL: pushexp(SUB, 0); pushexp(NUMBER, 3); return 0; case COMA: case LN: pushexp(LN, 0); ssymval(*sym, evalexpr() - 3); inscodeI(*sym, NULL, num_channel); if (token == LN) { status = STATUS_BEGIN_CHN_BODY; return 1; } else { status = 32; initexpr(); return 0; } default: rerror(ESYNTAX, E_BEMOL, 0); } case STATUS_PLAY_SOST: switch(token) { case SOS: pushexp(ADD, 0); pushexp(NUMBER, 3); return 0; case COMA: case LN: pushexp(LN, 0); ssymval(*sym, evalexpr() + 3); inscodeI(*sym, NULL, num_channel); if (token == LN) { status = STATUS_BEGIN_CHN_BODY; return 1; } else { status = 32; initexpr(); return 0; } default: rerror(ESYNTAX, E_SOS, 0); } case 38: switch(token) { case LN: status = 37;{errorg?rerror(EERROR, 0, 0):writesong();}return 2; /*Fin de entrada*/ default: rerror(ESYNTAX, E_BAD_COMM, 0); } case 39: switch (token) { case NUMBER: status = 40;{pushexp(NUMBER, atoi(lexcad));}return 0; case IDEN: status = 40;{symbol ptr;(ptr = searchsym(lexcad))?pushexp(NUMBER, gsymval(ptr)):rerror(ESYNTAX, EIDEN_NAME, 0);}return 0; case PARI: status = 41; pushexp(token, 0); return 0; default: rerror(ESYNTAX, E_EXP, 0); } case 40: switch(token) { case ADD: status = 39; pushexp(token, 0); return 0; case SUB: status = 39; pushexp(token, 0); return 0; case MUL: status = 39; pushexp(token, 0); return 0; case DIV: status = 39; pushexp(token, 0); return 0; case POINT: status = 43;{pointp = point=32;}; return 0; case LN: status = STATUS_BEGIN_CHN_BODY; { float time; pushexp(token, 0); time = evalexpr(); time/=64.0; time*=(240.0*((float)(gsymval(hz))))/((float)(gsymval(tempo))); if((time-((float)((unsigned char)time))) > 0.5) time=((float)((unsigned char)time))+1.0; else time=(float)((unsigned char)time); ssymval(*sym,(unsigned char)time); inscodeI(*sym, NULL, num_channel); }return 1; default: rerror(ESYNTAX, E_EXP, 0); } case 41: switch(token) { case NUMBER: status = 42;{pushexp(NUMBER, atoi(lexcad));}return 0; case IDEN: status = 42;{symbol ptr;(ptr = searchsym(lexcad))?pushexp(NUMBER, gsymval(ptr)):rerror(ESYNTAX, EIDEN_NAME, 0);}return 0; case PARI: status = 41; pushexp(token, 0); return 0; default: rerror(ESYNTAX, E_EXP, 0); } case 42: switch(token) { case PARD: status = 42; pushexp(token, 0); return 0; case ADD: case SUB: case MUL: case DIV: status = 41; pushexp(token, 0); return 0; case POINT: status = 43;{pointp = point=32;} return 0; case LN: status = STATUS_BEGIN_CHN_BODY; { float time, timei; pushexp(token, 0); time = evalexpr(); time/=64.0; time*=(240.0*((float)(gsymval(hz))))/((float)(gsymval(tempo))); time = fabs(time); timei = floor(time); if(time-timei) time = timei+1.0; else time = timei; ssymval(*sym,(unsigned char)time); inscodeI(*sym, NULL, num_channel); }return 1; default: rerror(ESYNTAX, E_EXP, 0); } case 43: switch(token) { case POINT: pointp >>= 1; point += pointp; return 0; case LN: status = STATUS_BEGIN_CHN_BODY; { float time, timei; pushexp(token, 0); time = evalexpr(); time/=64; time*=(240.0*((float)(gsymval(hz))))/((float)(gsymval(tempo))); time = fabs(time); time+=time*(((float)point)/64.0); timei = floor(time); if(time-timei) time = timei+1.0; else time = timei; ssymval(*sym,(unsigned char)time); inscodeI(*sym, NULL, num_channel); }return 1; } default: rerror(ESYNTAX, E_POINT, 0); } }