📄 lexical.c
字号:
/**********Copyright 1990 Regents of the University of California. All rights reserved.Author: 1985 Wayne A. Christopher, U. C. Berkeley CAD Group**********//* * Initial lexer. */#include "spice.h"#include "cpdefs.h"#include <errno.h>#ifdef HAS_GETPW#include <pwd.h>#endif#ifdef HAS_BSDTTY#include <sys/types.h>#include <sgtty.h>#else#ifdef HAS_SYSVTTY#include <sys/types.h>#include <termio.h>#else#ifdef HAS_POSIXTTY#include <sys/types.h>#include <termios.h>#endif#endif#endif#include "fteinput.h"#include "suffix.h"static void prompt();FILE *cp_inp_cur = NULL;int cp_event = 1;bool cp_interactive = true;bool cp_bqflag = false;char *cp_promptstring = NULL;char *cp_altprompt = NULL;char cp_hash = '#';static int numeofs = 0;static int input();extern void Input();#define ESCAPE '\033'/* Return a list of words, with backslash quoting and '' quoting done. * Strings en(void) closed in "" or `` are made single words and returned, * but with the "" or `` still present. For the \ and '' cases, the * 8th bit is turned on (as in csh) to prevent them from being recogized, * and stripped off once all processing is done. We also have to deal with * command, filename, and keyword completion here. * If string is non-NULL, then use it instead of the fp. Escape and EOF * have no business being in the string. */#define newword cw->wl_word = copy(buf); \ cw->wl_next = alloc(struct wordlist); \ cw->wl_next->wl_prev = cw; \ cw = cw->wl_next; \ cw->wl_next = NULL; \ bzero(buf, BSIZE_SP); \ i = 0;wordlist *cp_lexer(string) char *string;{ int c; int i, j; wordlist *wlist = NULL, *cw = NULL; char buf[BSIZE_SP], linebuf[BSIZE_SP], d; int paren; if (cp_inp_cur == NULL) cp_inp_cur = cp_in; if (!string && cp_interactive) { cp_ccon(true); prompt(); }nloop: i = 0; j = 0; paren = 0; bzero(linebuf, BSIZE_SP); bzero(buf, BSIZE_SP); wlist = cw = alloc(struct wordlist); cw->wl_next = cw->wl_prev = NULL; for (;;) { if (string) { c = *string++; if (c == '\0') c = '\n'; if (c == ESCAPE) c = '['; } else c = input(cp_inp_cur);gotchar: if ((c != EOF) && (c != ESCAPE)) linebuf[j++] = c; if (c != EOF) numeofs = 0; if (i == BSIZE_SP - 1) { fprintf(cp_err, "Warning: word too long.\n"); c = ' '; } if (j == BSIZE_SP - 1) { fprintf(cp_err, "Warning: line too long.\n"); if (cp_bqflag) c = EOF; else c = '\n'; } if (c != EOF) c = strip(c); /* Don't need to do this really. */ if (c == '\\' && DIR_TERM != '\\' || c == '\026' /* ^V */ ) { c = quote(string ? *string++ : input(cp_inp_cur)); linebuf[j++] = strip(c); } if ((c == '\n') && cp_bqflag) c = ' '; if ((c == EOF) && cp_bqflag) c = '\n'; if ((c == cp_hash) && !cp_interactive && (j == 1)) { if (string) return (NULL); while (((c = input(cp_inp_cur)) != '\n') && (c != EOF)); goto nloop; } if (c == '('/*)*/) paren++; else if (c == /*(*/')') paren--; switch (c) { case ' ': case '\t': if (i > 0) { newword; } break; case '\n': if (i) { buf[i] = '\0'; cw->wl_word = copy(buf); } else if (cw->wl_prev) { cw->wl_prev->wl_next = NULL; tfree(cw); } else { cw->wl_word = NULL; } goto done; case '\'': while (((c = (string ? *string++ : input(cp_inp_cur))) != '\'') && (i < BSIZE_SP - 1)) { if ((c == '\n') || (c == EOF) || (c == ESCAPE)) goto gotchar; else { buf[i++] = quote(c); linebuf[j++] = c; } } linebuf[j++] = '\''; break; case '"': case '`': d = c; buf[i++] = d; while (((c = (string ? *string++ : input(cp_inp_cur))) != d) && (i < BSIZE_SP - 2)) { if ((c == '\n') || (c == EOF) || (c == ESCAPE)) goto gotchar; else if (c == '\\') { linebuf[j++] = c; c = (string ? *string++ : input(cp_inp_cur)); buf[i++] = quote(c); linebuf[j++] = c; } else { buf[i++] = c; linebuf[j++] = c; } } buf[i++] = d; linebuf[j++] = d; break; case '\004': case EOF: if (cp_interactive && !cp_nocc && (string == NULL)) { if (j == 0) { if (cp_ignoreeof && (numeofs++ < 23)) { fputs( "Use \"quit\" to quit.\n", stdout); } else { fputs("quit\n", stdout); cp_doquit(); } goto done; } 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 goto nloop; } else /* EOF during a source */ { if (cp_interactive) { fputs("quit\n", stdout); cp_doquit(); goto done; } else 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(wlist, buf, true); wl_free(wlist); goto nloop; } /* Else fall through */ case ',': if (paren < 1 && i > 0) { newword; break; } default: /* We have to remember the special case $< * here */ if ((cp_chars[c] & CPC_BRL) && (i > 0)) { if ((c != '<') || (buf[i - 1] != '$')) { newword; } } buf[i++] = c; if (cp_chars[c] & CPC_BRR) { if ((c != '<') || (i < 2) || (buf[i - 2] != '$')) { newword; } } } }done: return (wlist);}static voidprompt(){ char *s; if (cp_interactive == false) return; if (cp_promptstring == NULL) s = "-> "; else s = cp_promptstring; if (cp_altprompt) s = cp_altprompt;#ifdef notdef /* XXXX VMS */ /* this is for VMS/RMS which otherwise won't output the LF * part of the newline on the previous line if this line * doesn't also end in newline, and most prompts don't, so... * we force an extra line here. */ fprintf(cp_out,"\n");#endif while (*s) { switch (strip(*s)) { case '!': fprintf(cp_out, "%d", cp_event); break; case '\\': if (*(s + 1)) (void) putc(strip(*++s), cp_out); default: (void) putc(strip(*s), cp_out); } s++; } (void) fflush(cp_out); return;}/* A special 'getc' so that we can deal with ^D properly. There is no way for * stdio to know if we have typed a ^D after some other characters, so * don't use buffering at all */intinchar(fp)FILE *fp;{ char c; int i;#ifdef TIOCSTI#endif if (cp_interactive && !cp_nocc) { do { i = read((int) fileno(fp), &c, 1); } while (i == -1 && errno == EINTR); if (i == 0 || c == '\004') return (EOF); else if (i == -1) { perror("read"); return (EOF); } else return ((int) c); } else c = getc(fp); return ((int) c);}static int input(fp)FILE *fp;{ REQUEST request; RESPONSE response; request.option = char_option; request.fp = fp; Input(&request, &response); return(response.reply.ch);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -