/* Note that we only do io redirection when we get to here - we also * postpone some other things until now. */ static void docommand(wordlist *wlist) { char *r, *s, *t; int nargs; int i; struct comm *command; wordlist *wl, *nextc, *ee, *rwlist; if (cp_debug) { printf("docommand "); wl_print(wlist, stdout); putc('\n', stdout); } /* Do all the things that used to be done by cshpar when the line * was read... */ wlist = cp_variablesubst(wlist); pwlist(wlist, "After variable substitution"); wlist = cp_bquote(wlist); pwlist(wlist, "After backquote substitution"); wlist = cp_doglob(wlist); pwlist(wlist, "After globbing"); pwlist_echo(wlist, "Becomes >"); if (!wlist || !wlist->wl_word) /*CDHW need to free wlist in second case? CDHW*/ return; /* Now loop through all of the commands given. */ rwlist = wlist; do { for (nextc = wlist; nextc; nextc = nextc->wl_next) if (eq(nextc->wl_word, cp_csep)) break; /* Temporarily hide the rest of the command... */ if (nextc && nextc->wl_prev) nextc->wl_prev->wl_next = NULL; ee = wlist->wl_prev; if (ee) wlist->wl_prev = NULL; if (nextc == wlist) { /* There was no text... */ goto out; } /* And do the redirection. */ cp_ioreset(); for (i = 0; noredirect[i]; i++) if (eq(wlist->wl_word, noredirect[i])) break; if (!noredirect[i]) { if (!(wlist = cp_redirect(wlist))) { cp_ioreset(); return; } } /* Get rid of all the 8th bits now... */ cp_striplist(wlist); s = wlist->wl_word; /* Look for the command in the command list. */ for (i = 0; cp_coms[i].co_comname; i++) { /* strcmp(cp_coms[i].co_comname, s) ... */ for (t = cp_coms[i].co_comname, r = s; *t && *r; t++, r++) if (*t != *r) break; if (!*t && !*r) break; } /* Now give the user-supplied command routine a try... */ if (!cp_coms[i].co_func && cp_oddcomm(s, wlist->wl_next)) goto out; /* If it's not there, try it as a unix command. */ if (!cp_coms[i].co_comname) { if (cp_dounixcom && cp_unixcom(wlist)) goto out; fprintf(cp_err,"%s: no such command available in %s\n", s, cp_program); goto out; /* If it's there but spiceonly, and this is nutmeg, error. */ } else if (!cp_coms[i].co_func && ft_nutmeg && (cp_coms[i].co_spiceonly)) { fprintf(cp_err,"%s: command available only in spice\n", s); goto out; } /* The command was a valid spice/nutmeg command. */ command = &cp_coms[i]; nargs = 0; for (wl = wlist->wl_next; wl; wl = wl->wl_next) nargs++; { if (nargs < command->co_minargs) { if (command->co_argfn) { (*command->co_argfn) (wlist->wl_next, command); } else { fprintf(cp_err, "%s: too few args.\n", s); } } else if (nargs > command->co_maxargs) { fprintf(cp_err, "%s: too many args.\n", s); } else { (*command->co_func) (wlist->wl_next); } } /* Now fix the pointers and advance wlist. */ out: wlist->wl_prev = ee; if (nextc) { for(wl=wlist; wl->wl_next; wl=wl->wl_next) ; wl->wl_next = nextc; nextc->wl_prev = wl; wlist = nextc->wl_next; } } while (nextc && wlist); wl_free(rwlist); /* Do periodic sorts of things... */ cp_periodic(); cp_ioreset(); return; }
/* Note that we only do io redirection when we get to here - we also * postpone some other things until now. */ static void docommand(wordlist *wlist) { wordlist *rwlist; if (cp_debug) { printf("docommand "); wl_print(wlist, stdout); putc('\n', stdout); } /* Do all the things that used to be done by cshpar when the line * was read... */ wlist = cp_variablesubst(wlist); pwlist(wlist, "After variable substitution"); wlist = cp_bquote(wlist); pwlist(wlist, "After backquote substitution"); wlist = cp_doglob(wlist); pwlist(wlist, "After globbing"); pwlist_echo(wlist, "Becomes >"); if (!wlist || !wlist->wl_word) /*CDHW need to free wlist in second case? CDHW*/ return; /* Now loop through all of the commands given. */ rwlist = wlist; while (wlist) { char *s; int i; struct comm *command; wordlist *nextc, *ee; nextc = wl_find(cp_csep, wlist); if (nextc == wlist) { /* skip leading `;' */ wlist = wlist->wl_next; continue; } /* Temporarily hide the rest of the command... */ ee = wlist->wl_prev; wl_chop(nextc); wl_chop(wlist); /* And do the redirection. */ cp_ioreset(); for (i = 0; noredirect[i]; i++) if (eq(wlist->wl_word, noredirect[i])) break; if (!noredirect[i]) if ((wlist = cp_redirect(wlist)) == NULL) { cp_ioreset(); return; } /* Get rid of all the 8th bits now... */ cp_striplist(wlist); s = wlist->wl_word; /* Look for the command in the command list. */ for (i = 0; cp_coms[i].co_comname; i++) if (strcasecmp(cp_coms[i].co_comname, s) == 0) break; command = &cp_coms[i]; /* Now give the user-supplied command routine a try... */ if (!command->co_func && cp_oddcomm(s, wlist->wl_next)) goto out; /* If it's not there, try it as a unix command. */ if (!command->co_comname) { if (cp_dounixcom && cp_unixcom(wlist)) goto out; fprintf(cp_err, "%s: no such command available in %s\n", s, cp_program); goto out; /* If it hasn't been implemented */ } else if (!command->co_func) { fprintf(cp_err, "%s: command is not implemented\n", s); goto out; /* If it's there but spiceonly, and this is nutmeg, error. */ } else if (ft_nutmeg && command->co_spiceonly) { fprintf(cp_err, "%s: command available only in spice\n", s); goto out; } /* The command was a valid spice/nutmeg command. */ { int nargs = wl_length(wlist->wl_next); if (nargs < command->co_minargs) { if (command->co_argfn) { command->co_argfn (wlist->wl_next, command); } else { fprintf(cp_err, "%s: too few args.\n", s); } } else if (nargs > command->co_maxargs) { fprintf(cp_err, "%s: too many args.\n", s); } else { command->co_func (wlist->wl_next); } } out: wl_append(ee, wlist); wl_append(wlist, nextc); if (!ee) rwlist = wlist; wlist = nextc; } wl_free(rwlist); /* Do periodic sorts of things... */ cp_periodic(); cp_ioreset(); }
wordlist * cp_lexer(char *string) { int c, d; int i, j; wordlist *wlist = NULL, *cw = NULL; char buf[NEW_BSIZE_SP], linebuf[NEW_BSIZE_SP]; int paren; if (!cp_inp_cur || cp_inp_cur != cp_in) cp_inp_cur = cp_in; /* prompt for string if none is passed */ if (!string && cp_interactive) { cp_ccon(TRUE); prompt(); } nloop: wlist = cw = NULL; i = 0; j = 0; paren = 0; bzero(linebuf, NEW_BSIZE_SP); bzero(buf, NEW_BSIZE_SP); for (;;) { c = cp_readchar(&string, cp_inp_cur); gotchar: if (string && (c == ESCAPE)) continue; if ((c != EOF) && (c != ESCAPE)) linebuf[j++] = (char) c; if (c != EOF) numeofs = 0; if (i == NEW_BSIZE_SP - 1) { fprintf(cp_err, "Warning: word too long.\n"); c = ' '; } if (j == NEW_BSIZE_SP - 1) { fprintf(cp_err, "Warning: line too long.\n"); if (cp_bqflag) c = EOF; else c = '\n'; } if (c != EOF) /* Don't need to do this really. */ c = strip(c); if ((c == '\\' && DIR_TERM != '\\') || (c == '\026') /* ^V */ ) { c = quote(cp_readchar(&string, cp_inp_cur)); linebuf[j++] = (char) strip(c); } if ((c == '\n') && cp_bqflag) c = ' '; if ((c == EOF) && cp_bqflag) c = '\n'; if ((c == cp_hash) && !cp_interactive && (j == 1)) { wl_free(wlist); wlist = cw = NULL; if (string) return NULL; while (((c = cp_readchar(&string, cp_inp_cur)) != '\n') && (c != EOF)) ; goto nloop; } if ((c == '(') || (c == '[')) /* MW. Nedded by parse() */ paren++; else if ((c == ')') || (c == ']')) paren--; switch (c) { case ' ': case '\t': if (i > 0) newword; break; case '\n': if (i) { buf[i] = '\0'; newword; } if (!cw) append(NULL); goto done; case '\'': while (((c = cp_readchar(&string, cp_inp_cur)) != '\'') && (i < NEW_BSIZE_SP - 1)) { if ((c == '\n') || (c == EOF) || (c == ESCAPE)) goto gotchar; buf[i++] = (char) quote(c); linebuf[j++] = (char) c; } linebuf[j++] = '\''; break; case '"': case '`': d = c; buf[i++] = (char) d; while (((c = cp_readchar(&string, cp_inp_cur)) != d) && (i < NEW_BSIZE_SP - 2)) { if ((c == '\n') || (c == EOF) || (c == ESCAPE)) goto gotchar; if (c == '\\') { linebuf[j++] = (char) c; c = cp_readchar(&string, cp_inp_cur); buf[i++] = (char) quote(c); linebuf[j++] = (char) c; } else { buf[i++] = (char) c; linebuf[j++] = (char) c; } } buf[i++] = (char) d; linebuf[j++] = (char) d; break; case '\004': case EOF: if (cp_interactive && !cp_nocc && !string) { if (j == 0) { if (cp_ignoreeof && (numeofs++ < 23)) { fputs("Use \"quit\" to quit.\n", stdout); } else { fputs("quit\n", stdout); // return ; // cp_doquit(); } append(NULL); goto done; } // cp_ccom doesn't mess wlist, read only access to wlist->wl_word cp_ccom(wlist, buf, FALSE); wl_free(wlist); (void) fputc('\r', cp_out); prompt(); for (j = 0; linebuf[j]; j++) #ifdef TIOCSTI (void) ioctl(fileno(cp_out), TIOCSTI, linebuf + j); #else fputc(linebuf[j], cp_out); /* But you can't edit */ #endif wlist = cw = NULL; goto nloop; } /* EOF during a source */ if (cp_interactive) { fputs("quit\n", stdout); cp_doquit(); append(NULL); goto done; } wl_free(wlist); return NULL; case ESCAPE: if (cp_interactive && !cp_nocc) { fputs("\b\b \b\b\r", cp_out); prompt(); for (j = 0; linebuf[j]; j++) #ifdef TIOCSTI (void) ioctl(fileno(cp_out), TIOCSTI, linebuf + j); #else fputc(linebuf[j], cp_out); /* But you can't edit */ #endif // cp_ccom doesn't mess wlist, read only access to wlist->wl_word cp_ccom(wlist, buf, TRUE); wl_free(wlist); wlist = cw = NULL; goto nloop; } goto ldefault; case ',': if ((paren < 1) && (i > 0)) { newword; break; } goto ldefault; case ';': /* CDHW semicolon inside parentheses is part of expression */ if (paren > 0) { buf[i++] = (char) c; break; } goto ldefault; case '&': /* va: $&name is one word */ if ((i >= 1) && (buf[i-1] == '$') && (c == '&')) { buf[i++] = (char) c; break; } goto ldefault; case '<': case '>': /* va: <=, >= are unbreakable words */ if (string) if ((i == 0) && (*string == '=')) { buf[i++] = (char) c; break; } goto ldefault; default: /* We have to remember the special case $< * here */ ldefault: if ((cp_chars[c] & CPC_BRL) && (i > 0)) if ((c != '<') || (buf[i-1] != '$')) newword; buf[i++] = (char) c; if (cp_chars[c] & CPC_BRR) if ((c != '<') || (i < 2) || (buf[i-2] != '$')) newword; } } done: if (wlist->wl_word) pwlist_echo(wlist, "Command>"); return wlist; }