/* * execute a stream of instructions, possibly returning a string */ char * exec_stream( pInstr s ) { while ( s != NULL) { char *r = exec_instr(s); if ( r != NULL ) return r; s = s->next; } return NULL; }
int exec_instr_not(s_instr *instr, s_list_dup *list_dup, int *error) { s_instr_not *instr_not = NULL; int res; if (instr == NULL || instr->instr == NULL) return (-1); instr_not = instr->instr; res = exec_instr(instr_not->instr, list_dup, error); if (*error != ERROR_NONE) return (1); if (res == 0) return (1); else return (0); }
int exec_instr_pipe(s_instr *instr, s_list_dup *list_dup, int *error) { s_instr_pipe *instr_pipe = NULL; int filedes[2]; int res = 0; s_list_dup *dp = NULL; s_list_dup *dp2 = NULL; s_list_instr_item *list_instr = NULL; int fd_in = STDIN_FILENO; if (instr == NULL || instr->instr == NULL) return (-1); instr_pipe = instr->instr; list_instr = instr_pipe->list_instr->first; for (; list_instr != NULL; list_instr = list_instr->next) { if (list_instr->next != NULL) mpipe(filedes); if (list_instr->next != NULL) dp = list_dup_insert(list_dup, filedes[1], STDOUT_FILENO); if (list_instr != instr_pipe->list_instr->first) dp2 = list_dup_insert(dp == NULL ? list_dup : dp, fd_in, STDIN_FILENO); res = exec_instr(list_instr->elmt, dp2 == NULL ? dp : dp2, error); close_fds(&fd_in, filedes, list_instr->next); free_and_null(&dp, &dp2); CHECK_ERROR() } return (res); }
static int run_metacommand(int cnum, int *redir_offset) /* cnum=command number to run. */ /* *redir_offset=offset of redirect header, if we exit with redirection. */ /* Return 0 to go on to next metacommand, 1 to stop running metacommands, and 2 to end the turn. 3 indicates that redirection has just occured 4 indicates a subcall has just occured. 5 Is used to go on to the next metacommand after a Return. -2 means we're doing disambiguation and just hit an action token. */ { int ip, oip; /* ip=Instruction pointer, oip=Old instruction pointer */ int r; /* Used to hold return value from token execution */ int fail_addr; /* What address to jump to on failure */ rbool fail; /* Last token was a conditional token that failed */ rbool ortrue, blocktrue, orflag; /* OR stuff orflag: Are we in an OR group? ortrue: Is current OR group true? blocktrue: Is current block w/in OR true? */ static rbool restart=0; /* Restarting after subroutine? */ op_rec currop; /* Information on the current token and its args */ fail_addr=32000; /* Fall off the end when we fail */ fail=0; ip=0; orflag=blocktrue=ortrue=0; *redir_offset=1; /* Default: This is what RedirectTo does. Only XRedirect can send a different value */ if (restart) /* finish up Return from subroutine */ pop_subcall(&cnum,&ip,&fail_addr); if (DEBUG_AGT_CMD && !supress_debug) { debug_head(cnum); if (restart) debugout(" (Resuming after subroutine)\n"); } restart=0; /* ========== Main Loop ================= */ while(ip<command[cnum].cmdsize) { oip=ip; ip+=decode_instr(&currop,command[cnum].data+ip,command[cnum].cmdsize-ip); /* ------- OR Logic --------------- */ if (currop.op==109) { /* OR */ if (!orflag) { /* First OR; set things up */ orflag=1; ortrue=0; blocktrue=1; } blocktrue=blocktrue && !fail; /* Was the previous token true? */ fail=0; ortrue=ortrue||blocktrue; /* OR in last block */ blocktrue=1; /* New block starts out true. */ } else if (orflag) { /* we're in the middle of a block */ blocktrue=blocktrue&&!fail; /* Add in previous token */ fail=0; if (currop.endor) { /* i.e. not a conditional token */ orflag=0; /* End of OR block */ ortrue=ortrue||blocktrue; /* OR in last block */ fail=!ortrue; /* Success of whole group */ } } /* ------------ FAILMESSAGE handling ------------- */ if (currop.failmsg) { /* Is the current token a Fail... token? */ if (!fail) continue; /* Skip it; look at next instruction */ /* ErrMessage and ErrStdMessage: set disambiguation score */ if (do_disambig) { if (currop.op==1130 || currop.op==1131) { if (!decode_args(oip,&currop)) return 2; disambig_score=currop.arg1; return 2; } else return -2; /* FailMessage counts as an action token */ } /* Then run the failmessage, skipping the following step... */ } /* -------- Failure routines -------------------- */ else if (fail) { /* ... and not failmessage */ /* consequences of failure */ fail=0; /* In case fail_addr doesn't point off the edge of the world */ ip=fail_addr; fail_addr=32000; /* Reset fail_addr */ continue; /* Usually fail_addr will fall off the end, causing this to return 0 */ } /* - Finish decoding arguments and print out debugging message - */ if (!decode_args(oip,&currop)) { if (currop.op<1000) fail=currop.negate ? 0 : 1; continue; /* return 2;*/ } /* -------- Commands that need to be handled specially -------------- */ if (currop.op==109) { /* OR */ if (DEBUG_AGT_CMD && !supress_debug) debug_newline(op,0); continue; /* OR: skip further processing */ } if (currop.op==1037) { /* DoSubroutine */ if (!push_subcall(cnum,ip,fail_addr)) { writeln("GAME ERROR: Subroutine stack overflow."); return 2; } subcall_arg=currop.arg1; if (DEBUG_AGT_CMD && !supress_debug) debugout("--> Call\n"); return 4; } if (currop.op==1038) { /* Return */ restart=1; if (DEBUG_AGT_CMD && !supress_debug) debugout("--> Return\n"); return 5; } if (currop.op==1149) { /* Goto */ ip=currop.arg1; if (DEBUG_AGT_CMD && !supress_debug) debugout("\n"); continue; } if (currop.op==1150) { /* OnFailGoto */ fail_addr=currop.arg1; if (DEBUG_AGT_CMD && !supress_debug) debugout("\n"); continue; } if (currop.op==1152) /* XRedirect */ *redir_offset=currop.arg1; /* ---------- Disambiguation Success -------------- */ if (do_disambig && currop.disambig) { if (DEBUG_AGT_CMD && !supress_debug) debugout("==> ACTION\n"); return -2; } /* ---------- Run normal metacommands -------------- */ switch(r=exec_instr(&currop)) { case 0: /* Normal action token or successful conditional token */ if (DEBUG_AGT_CMD && !supress_debug) debug_newline(op,0); continue; case 1: /* Conditional token: fail */ if (DEBUG_AGT_CMD && !supress_debug) { if (orflag) debugout(" (-->FAIL)\n"); else debugout("--->FAIL\n"); } fail=1; continue; default: /* Return explicit value */ if (DEBUG_AGT_CMD && !supress_debug) { if (r==103) debugout("-->Redirect\n"); else debugout("==> END\n"); } return r-100; } } return 0; }
/* Appel: * tp [-option]* programme.txt * Les options doivent apparaitre avant le nom du fichier du programme. * Options: -[eE] -[vV] -[hH?] */ int main(int argc, char **argv) { int fi; int i, res; if (argc == 1) { fprintf(stderr, "Syntax: zn [-v] program.txt\n"); exit(USAGE_ERROR); } for(i = 1; i < argc; i++) { if (argv[i][0] == '-') { switch (argv[i][1]) { case 'v': case 'V': verbose = TRUE; continue; case '?': case 'h': case 'H': fprintf(stderr, "Syntax: zn [-v] program.txt\n"); exit(USAGE_ERROR); default: fprintf(stderr, "Error: Unknown Option: %c\n", argv[i][1]); exit(USAGE_ERROR); } } else break; } if (i == argc) { fprintf(stderr, "Error: Program file is missing\n"); exit(USAGE_ERROR); } if ((fi = open(argv[i++], O_RDONLY)) == -1) { fprintf(stderr, "Error: Cannot open %s\n", argv[i-1]); exit(USAGE_ERROR); } /* Initialisations */ InitializationFinished = FALSE; CurrentMethodName = (char*) malloc(128 * sizeof(char)); initIntegerClass(); initStringClass(); initVoidClass(); initializeScope(); InitializationFinished = TRUE; CurrentClass = NULL; AllDefinedClasses = defaultClassDefsPlus(NULL); /* redirige l'entree standard sur le fichier. .. */ close(0); dup(fi); close(fi); /* Lance l'analyse syntaxique de tout le source, en appelant yylex au fur * et a mesure. Execute les actions semantiques en parallele avec les * reductions. * yyparse renvoie 0 si le source est syntaxiquement correct, une valeur * differente de 0 en cas d'erreur syntaxique (eventuellement dues a des * erreurs lexicales). * Comme l'interpretation globale est automatiquement lancee par les actions * associees aux reductions, une fois que yyparse a termine il n'y * a plus rien a faire (sauf fermer les fichiers) * Si le code du programme contient une erreur, on bloque l'evaluation. * S'il ny a que des erreurs contextuelles on essaye de ne pas s'arreter * a la premiere mais de continuer l'analyse pour en trovuer d'autres, quand * c'est possible. */ yydebug = 0; res = yyparse(); if (fd != NIL(FILE)) fclose(fd); if ( !(res == 0 && errorCode == NO_ERROR) ) { int res2 = res ? SYNTAX_ERROR : errorCode; printf("Error in file. Kind of error: %d\n", res2); return res2; } ProgramTypeAndRedirect(program); InstrTypeAndRedirect(program->instrs, MainScope); exec_instr(program->instrs, MainScope); }