void ParseMorpheme(char* S, ParseStates* state, Tree** T){ static char* redirop=NULL; redirop=myrealloc(redirop,3*sizeof(char)); Tree* newT=NULL; switch (*state){ case CMD:{ switch (ParseGetTokenClass(S)){ case TEXT: StringPut(&((*T)->cmd),S); (*T)->type=LINK_COMMAND; *state=ARGS; break; case SUBSHELL_BEGIN: newT=TreeInit(); newT->type=LINK_SUBSHELL; newT->left=(*T); newT->parent=(*T)->parent; (*T)->parent=newT; if (newT->parent!=NULL){ if (newT->parent->left==(*T)) newT->parent->left=newT; if (newT->parent->right==(*T)) newT->parent->right=newT; } *state=CMD; break; case SUBSHELL_END: while((*T)!=NULL &&((*T)->type!=LINK_SUBSHELL)) *T=(*T)->parent; if (*T==NULL) *state=PARSEERROR; else *state=AFTERSUBSHELL; break; default: *state=PARSEERROR; break; } break; } case ARGS:{ switch (ParseGetTokenClass(S)){ case TEXT: ListAdd(&((*T)->args),S); *state=ARGS; break; case REDIRECT: strcpy(redirop,S); *state=REDIR; break; case OPER: newT=TreeInit(); newT->type=OperatorType(S); if (newT->type==LINK_AND || newT->type==LINK_OR){ while ((*T)->parent->type!=LINK_SUBSHELL) (*T)=(*T)->parent; } if (newT->type==LINK_BACKGROUND || newT->type==LINK_SEMICOLON){ while ((*T)->parent->type!=LINK_SUBSHELL && (*T)->parent->type!=LINK_AND && (*T)->parent->type!=LINK_OR) (*T)=(*T)->parent; } if (newT->type==LINK_BACKGROUND || newT->type==LINK_SEMICOLON){ while ((*T)->parent->type!=LINK_SUBSHELL && (*T)->parent->type!=LINK_AND && (*T)->parent->type!=LINK_OR) (*T)=(*T)->parent; } newT->parent=(*T)->parent; if (newT->parent!=NULL) { if (newT->parent->left==(*T)) newT->parent->left=newT; if (newT->parent->right==(*T)) newT->parent->right=newT; } (*T)->parent=newT; newT->left=(*T); newT->right=TreeInit(); newT->right->parent=newT; *T=newT->right; *state=CMD; break; case SUBSHELL_END: while((*T)!=NULL &&((*T)->type!=LINK_SUBSHELL)) *T=(*T)->parent; if (*T==NULL) *state=PARSEERROR; else *state=AFTERSUBSHELL; break; default: *state=PARSEERROR; } break; } case REDIR:{ switch (ParseGetTokenClass(S)){ case TEXT: if (!strcmp(redirop,">")) StringPut(&((*T)->out),S); if (!strcmp(redirop,">>")) StringPut(&((*T)->append),S); if (!strcmp(redirop,"<")) StringPut(&((*T)->in),S); *state=ARGS; break; default: *state=PARSEERROR; } break; } case AFTERSUBSHELL:{ switch (ParseGetTokenClass(S)){ case OPER: newT=TreeInit(); newT->type=OperatorType(S); if (newT->type==LINK_AND || newT->type==LINK_OR){ while ((*T)->parent->type!=LINK_SUBSHELL) (*T)=(*T)->parent; } if (newT->type==LINK_BACKGROUND || newT->type==LINK_SEMICOLON){ while ((*T)->parent->type!=LINK_SUBSHELL && (*T)->parent->type!=LINK_AND && (*T)->parent->type!=LINK_OR) (*T)=(*T)->parent; } if (newT->type==LINK_BACKGROUND || newT->type==LINK_SEMICOLON){ while ((*T)->parent->type!=LINK_SUBSHELL && (*T)->parent->type!=LINK_AND && (*T)->parent->type!=LINK_OR) (*T)=(*T)->parent; } newT->parent=(*T)->parent; if (newT->parent!=NULL) { if (newT->parent->left==(*T)) newT->parent->left=newT; if (newT->parent->right==(*T)) newT->parent->right=newT; } (*T)->parent=newT; newT->left=(*T); newT->right=TreeInit(); newT->right->parent=newT; *T=newT->right; *state=CMD; break; case REDIRECT: *state=REDIR; break; case SUBSHELL_END: *T=(*T)->parent; while((*T)!=NULL &&((*T)->type!=LINK_SUBSHELL)) *T=(*T)->parent; if (*T==NULL) *state=PARSEERROR; else *state=AFTERSUBSHELL; break; default: *state=PARSEERROR; } break; } default: *state=PARSEERROR; } }
static void DoReplace (FILE *f, ReplaceSet *s) { int c; String *tag; Replace *r; SkipStack *ss = 0; LoopStack *ls = 0; int skipping = 0; while ((c = getc (f)) != EOF) { if (c == '@') { tag = StringNew (); while ((c = getc (f)) != '@') { if (c == EOF) abort (); StringAdd (tag, c); } if (ls) StringAddString (tag, ls->extra->buf); switch (tag->buf[0]) { case '?': ss = SkipStackPush (ss, skipping); if (!ReplaceSetFind (s, tag->buf + 1)) skipping++; LineSkip (f); break; case ':': if (!ss) abort (); if (ss->skipping == skipping) ++skipping; else --skipping; LineSkip (f); break; case ';': skipping = ss->skipping; ss = SkipStackPop (ss); LineSkip (f); break; case '{': ls = LoopStackPush (ls, f, tag->buf + 1); LineSkip (f); break; case '}': ls = LoopStackLoop (s, ls, f); LineSkip (f); break; default: r = ReplaceSetFind (s, tag->buf); if (r && !skipping) StringPut (stdout, r->text); break; } StringDispose (tag); } else if (!skipping) putchar (c); } }