1: /*************************************************************
2: * Program: CMENU Menu Compiler
3: * Module: cmenu3.c
4: * Menu Compiler:
5: * Token Processing Functions
6: * Written by: Leor Zolman, 7/91
7: *************************************************************/
8:
9: #include "cmenu.h"
10: #include "cmenu.h"
11:
12: #include <ctype.h>
13:
14: static int unget_flag = FALSE;
15: static int unget_token;
16: static char unget_tparam[MAX_CMD];
17: static int unget_vparam;
18:
19: static int quoted_text;
20:
21: #if_STDC__
22: char *getword(void);
23: int matchkey(char *);
24: #else
25: char *getword();
26: int matchkey();
27: #endif
28:
29: /************************************************************
30: * ungettok():
31: * Push a token back into the input stream, to
32: * be returned by the following call to gettok().
33: * Only one level of push-back is supported; any attempt to
34: * push back a token when there is already one pushed back
35: * draws an "internal error" diagnostic.
36: ************************************************************/
37:
38: Void ungettok(tok)
39: int tok;
40: {
41: if (unget_flag) /* can't "unget" more than 1 item! */
42: fatalerr("internal error: ungettok() overflow");
43:
44: unget_flag = TRUE;
45: unget_token = tok;
46: unget_vparam = vparam;
47: strcpy(unget_tparam, tparam);
48: return;
49: }
50:
51:
52: /************************************************************
53: * gettok():
54: * Read a token from the source input stream.
55: * If the token is a reserved word, the appropriate token
56: * value is returned.
57: * If the token is a string, the global "tparam" is set
58: * to the text of the string. White space within the
59: * string is only recognized if double quote ("...")
60: * characters are used to delimit the string.
61: * T_STRING is returned.
62: * If the token is a numeric value, the global "vparam"
63: * is set to the integer value specified, and
64 * T_VALUE is returned.
65 * Returns T_EOF on end-of-file.
66: ************************************************************/
67:
68: int gettok()
69: {
70: register c;
71: char nexttok[MAX_CMD];
72: char *wordp;
73:
74: if (unget_flag) /* was a token "pushed back"? */
75: { /* yes. set the pushed-back values and */
76: vparam = unget_vparam; /* attributes */
77: strcpy(tparam, unget_tparam); /* clear the */
78: unget_flag = FALSE; /* flag */
79: return unget_token; /* return pushed token */
80: }
81:
82: *tparam = '\0'; /* clear parameter */
83: vparam = 0; /* value registers */
84:
85: if (!*(wordp = getword())) /* get a token. */
86: return token = T_EOF; /* End of file */
87:
88: if (quoted_text) /* string enclosed */
89: { /* in quotes? */
90: strcpy(tparam, wordp);
91: return T_STRING;
92: }
93:
94: if (!strcmp(wordp, ":")) /* colon is special */
95: return T_COLON; /* (non-alphabetic)*/
96:
97: if (c = matchkey(wordp)) /* reserved word? */
98: return c; /* yes, just return */
99:
100: if (isdigit(*wordp)) /* handle numeric value */
101: {
102: vparam = atoi(wordp);
103: return T_VALUE;
104: }
105: else
106: {
107: strcpy(tparam, wordp);
108: return T_STRING;
109: }
110: }
111:
112:
113: /***********************************************************
114: * getword():
115: * Read the next syntactic object from the input stream,
116: * and return a pointer to it.
117: * Return pointer to a null string on EOF.
118: * If object is a quoted string, drop the quotes and
119: * set the quoted_text flag (preserve whitespace).
120: * Otherwise strip all whitespace, commas and comments,
121: * return pointer to next word/number.
122: * Track current line number by incrementing lineno
123: * on each newline encountered.
124: ***********************************************************/
125:
126: char *getword()
127: {
128: static char tok[MAX_CMD];
129: char quote_char;
130: register c,i;
131:
132: quoted_text = FALSE;
133: *tok = '\0';
134:
135: while ((c = getc(fp)) != EOF)
136: {
137: if (c == '\n') /* bump line number if */
138: lineno++; /* newline encountered */
139:
140: if (isspace(c)) /* skip all whitespace */
141: continue;
142:
143: if (c == ',' || c == ';') /*legal separators: ,; */
144: continue;
145:
146: if (c == ':') /* special case: colon */
147: return ":";
148:
149: if (c == '#') /* process comment */
150: { /* wait for newline or EOF */
151: while(c = getc(fp))
152: {
153: if (c == EOF)
154: break;
155: if (c == '\n')
156: {
157: lineno++;
158: break;
159: }
160: }
161: continue; /* then get next token */
162: }
163:
164: if (c == '"' || c == '\" ) /* quoted string? */
165: {
166: quoted_text = TRUE;
167: quote_char = c;
168: for (i = 0; ;i++)
169: {
170: switch (c = getc(fp))
171: {
172: case '\n':
173: fatalerr("Unterminated string");
174: return NULL;
175:
176: case EOF:
177: fatalerr("Unterminated string (line %d)",
178: lineno);
179: return NULL;
180:
181: case ' " ':
182: case '\":
183: if (c == quote_char)
184: {
185: tok[i] = '\0';
186: return tok;
187: }
188:
189: default:
190: if (i == MAX_CMD)
191: {
192: tok[i - 1] = '\0';
193: fatalerr("String too long (max %d chars)",
194: MAX_CMD);
195: return NULL;
196: }
197: tok[i] = c;
198: }
199: }
200: }
201:
202: tok[0] = c;
203: for (i = 1; (c = getc(fp)) != EOF; i++)
204: if (isspace(c) || c == ';' || c == ','
205: || c == ':')
206: break;
207: else
208: tok[i] = tolower(c);
209: tok[i] = '\0';
210: ungetc(c, fp);
211: break;
212: }
213: return tok;
214: }
215:
/* End of File */