/* * csh - a shell by PJAC * cond.c - loops and conditionals */ #include "csh.h" /* * for loop processing */ do_for(argc, argv) char **argv; { struct lvars *lp, *xlp; int ac; char **av, **xp; char *savstr; struct forblk *fp; if(argc < 5) syn_err(); ac = argc - 4; av = argv + 3; if(strcmp(argv[2], "(") || strcmp(argv[argc-1], ")")) syn_err(); if(Cur_ins >= &in_bufs[MAX_INS]){ puterr("No resources for for loop.\n"); return(ERR); } for(lp = Lvars ; lp ; lp = lp->L_next) if(strcmp(argv[1], lp->L_name) == 0) break; if(lp == 0){ lp = (struct lvars *)mmalloc(sizeof(struct lvars)); lp->L_name = strsave(argv[1]); lp->L_flags = 0; lp->L_next = 0; if(Lvars == 0) Lvars = lp; else { for(xlp = Lvars ; xlp->L_next ; xlp = xlp->L_next); xlp->L_next = lp; } } else if(xp = lp->L_aval){ while(*xp) free(*xp++); free( (char *)lp->L_aval); } lp->L_aval = 0; savstr = read_blk("end", (char *)0); if(savstr == NULL) return(ERR); /* * savstr now points to body of loop * build a control block and put it on the input stack */ fp = (struct forblk *)mmalloc(sizeof(struct forblk)); fp->F_name = strsave(argv[1]); fp->F_argv = (char **)mmalloc(sizeof(char *)*(ac+1)); for(xp = fp->F_argv ; ac && *av ; av++, xp++, ac--) *xp = strsave(*av); *xp = 0; Cur_ins++; Cur_ins->i_buf = savstr; Cur_ins->i_ptr = savstr; Cur_ins->i_nleft = strlen(savstr); Cur_ins->i_fblk = fp; in_savblk = 0; return(do_end(0, (char **)0)); /* cheat like mad !! */ } do_while(argc, argv) char **argv; { int ac; char **av, **xp; char *savstr; struct forblk *fp; if(argc < 4) syn_err(); if(strcmp(argv[1], "(") || strcmp(argv[argc-1], ")")) syn_err(); ac = argc - 3; av = argv + 2; if(Cur_ins >= &in_bufs[MAX_INS]){ puterr("No resources for while loop.\n"); return(ERR); } savstr = read_blk("end", (char *)0); if(savstr == NULL) return(ERR); fp = (struct forblk *)mmalloc(sizeof(struct forblk)); fp->F_name = 0; fp->F_argc = ac; fp->F_argv = (char **)mmalloc(sizeof(char *)*(ac+1)); for(xp = fp->F_argv ; ac && *av ; av++, xp++, ac--) *xp = strsave(*av); *xp = 0; Cur_ins++; Cur_ins->i_buf = savstr; Cur_ins->i_ptr = savstr; Cur_ins->i_nleft = strlen(savstr); Cur_ins->i_fblk = fp; in_savblk = 0; return(do_end(0, (char **)0)); /* cheat like mad !! */ } char * read_blk(endstr1, endstr2) char *endstr1, *endstr2; { char *p, *q; int len, olen; for(len = 0;;){ if(Prompt[1]) put_prompt(Prompt[1]); if(readin() == EOF){ if(in_savblk){ free(in_savblk); in_savblk = 0; } return(NULL); } p = skipsp(in_buf); if(p != 0) olen = strlen(p); else olen = 0; q = mmalloc(len + 1 + olen + 1 + 1); if(in_savblk){ strcpy(q, in_savblk); free(in_savblk); } q[len++] = '\n'; if(olen) strcpy(q + len, p); else q[len] = 0; len += olen; in_savblk = q; if(olen){ if(strncmp(p, endstr1, strlen(endstr1)) == 0 || (endstr2 && strncmp(p, endstr2, strlen(endstr2))==0)) if(p[olen] == '\0' || index(IFS, p[olen])){ strcat(q + olen, "\n"); break; } } } return(in_savblk); } do_brk(argc, argv) char **argv; { if(Cur_ins->i_fblk == 0){ puterr("Illegal Break.\n"); return(ERR); } return(pop_in(FALSE)); } do_cont(argc, argv) char **argv; { if(Cur_ins->i_fblk == 0){ puterr("Illegal Continue.\n"); return(ERR); } return(do_end(argc, argv)); } do_end(argc, argv) char **argv; { struct forblk *fp; struct lvars *lp; char **xp, **xlp; int res = 0; if((fp = Cur_ins->i_fblk) == 0){ puterr("Illegal end.\n"); return(ERR); } if(fp->F_name){ /* it's a for loop */ for(lp = Lvars ; lp ; lp = lp->L_next) if(strcmp(lp->L_name, fp->F_name) == 0) break; if(!lp){ puterr("For: loop variable deleted.\n"); return(ERR); } if(xp = lp->L_aval){ while(*xp) free(*xp++); free( (char *)lp->L_aval); } lp->L_aval =(char **)mmalloc(sizeof(char *)*2); lp->L_aval[0] = 0; lp->L_aval[1] = 0; /* * at this point got lp fit to get next val */ if((xp = fp->F_argv) == 0) return(pop_in(FALSE)); lp->L_aval[0] = *xp; while(*xp = xp[1]) xp++; if(fp->F_argv[0] == 0){ free( (char *)fp->F_argv); fp->F_argv = 0; } } else { if(arg_eval(fp->F_argc, fp->F_argv, &res) == ERR) expr_err(); if(res == 0) return(pop_in(FALSE)); } /* * finally got to the point when we have to restart */ Cur_ins->i_ptr = Cur_ins->i_buf; Cur_ins->i_nleft = strlen(Cur_ins->i_buf); return(OK); } /* * perform an if statement */ do_if(argc, argv) char **argv; { char **xp; int ac = 0; int res; struct cmd T; int level = 0; if(argc < 5) syn_err(); if(strcmp(argv[1], "(")) syn_err(); for(xp = argv + 2; *xp ; xp++, ac++) if(strcmp(*xp, ")") == 0){ if(--level < 0) break; } else if(strcmp(*xp, "(") == 0) level++; if(!*xp || !xp[1]) syn_err(); if(arg_eval(ac, argv + 2, &res) == ERR) expr_err(); if(strcmp(*++xp, "then") != 0){ if(!res) return(OK); /* a simple command - build a tree struct and call r_tree */ T.cm_parent = 0; T.cm_child = 0; T.cm_next = 0; T.cm_ofile = 0; T.cm_ifile = 0; T.cm_argv = xp; T.cm_argc = argc - ac - 3; return(r_tree(&T)); } if(xp[1]) syn_err(); /* * Groan - now have to scan to get end of else if construct */ return(OK); } expr_err() { longjmp(env_main, EXPRERR); }