1: #include "hd.h" 2: #include "strings.h" 3: 4: /* Table for scanner machine. The machine can handle any regular 5: expression. Table elements come in pairs. The first is 6: the match character and the second is the next state assoc with 7: that character. The character '*' matches all character. 8: */ 9: static char st00[] = {' ', 0, '\t', 0, '\n', 3, '\\', 1, 10: '\'', 8, '"', 10, '*', 4}; 11: static char st01[] = {'\n', 0, '*', 4}; 12: static char st02[] = {'\n', 3, '*', 0}; 13: static char st03[] = {'*', 0}; 14: static char st04[] = {'*', 5}; 15: static char st05[] = {' ', 2, '\n', 2, '\t', 2, '\\', 6, '\'', 8, 16: '"', 10, '*', 4}; 17: static char st06[] = {'\n', 5, '*', 4}; 18: static char st07[] = {'*', 0}; 19: static char st08[] = {'\'', 5, '*', 9}; 20: static char st09[] = {'*', 8}; 21: static char st10[] = {'"', 5, '\\',12, '*',11}; 22: static char st11[] = {'*', 10}; 23: static char st12[] = {'\n',10, '*', 11}; 24: 25: static char *lextab[] = {st00, st01, st02, st03, st04, st05, st06, 26: st07, st08, st09, st10, st11, st12}; 27: 28: /* Readarg reads a line from pstream and converts it into 29: argv-argc format. One may use a format similar to the shell. 30: */ 31: readarg (pstream, pline, pargc, pargv, pbuf) 32: FILE *pstream; /* Stream being read */ 33: int *pline; /* Current line number */ 34: int *pargc; /* Count of words */ 35: char *pargv [ARGVMAX]; /* Array of pointers to the words */ 36: char pbuf [STRMAX]; /* Buf to hold the words themselves */ 37: { 38: /* Space is allocated from pargv and pbuf as words are read. 39: These vars keep track of the allocations. 40: */ 41: char **cargv = pargv; /* Current allocations */ 42: char * cbuf = pbuf; 43: /* Limit of allocation */ 44: char **largv = pargv + ARGVMAX - 1; 45: char * lbuf = pbuf + STRMAX - 1; 46: 47: /* Scanner vars */ 48: int state = 0; /* Scanner machine state */ 49: int ch; /* Current char */ 50: char *ltp; /* Lexical table pointer */ 51: 52: int prompt; /* Flag indicates when to prompt */ 53: #define NOPR 0 /* Don't */ 54: #define FPR 1 /* First prompt */ 55: #define CPR 2 /* Continuation prompt */ 56: 57: /* Initialization */ 58: *pargc = 0; 59: cargv[0] = pbuf; 60: prompt = FPR; 61: 62: for (;;) { 63: switch (state) { 64: 65: /* Get a char */ 66: case 0: case 1: case 5: case 6: case 8: 67: case 10: case 12: 68: if (prompt && pstream == stdin) 69: printf ((prompt == FPR) ? 70: "Parm: " : ": "); 71: ch = fgetc (pstream); 72: prompt = (ch == LF) ? CPR : NOPR; 73: if (ascii [ch] == EF) { 74: if (*pargc != 0) lderror 75: ("Incomplete line", *pline); 76: return FAILURE; 77: } 78: else if (ENDLINE (ch)) ++*pline; 79: else if (ascii [ch] == UD) { 80: lderror ("Non-Ascii character", *pline); 81: continue; 82: } 83: break; 84: 85: /* Store a char */ 86: case 4: case 9: case 11: 87: if (cbuf >= lbuf || cargv >= largv) { 88: lderror ("Too long", *pline); 89: return FAILURE; 90: } 91: *cbuf++ = ch; 92: break; 93: 94: /* Store a word */ 95: case 2: case 7: 96: *cbuf++ = 0; 97: *++cargv = cbuf; 98: ++*pargc; 99: break; 100: 101: /* Return from readarg */ 102: case 3: 103: *cargv = CNULL; return SUCCESS; 104: } 105: for (ltp = lextab [state]; 106: *ltp != ch && *ltp != '*'; ltp += 2); 107: state = *++ltp; 108: } 109: } 110: 111: /* Load error */ 112: lderror (cp, line) char *cp; int line; { 113: printf ("Line %d: %s\n", line, cp); 114: getrtn (); 115: }