1 %option yylineno
2 %{ /*-*- Mode: C -*-*/
3 /**************************************************************************
4  ** File     :       lexical.l                                           **
5  ** Author   :       Edward Groenendaal                                  **
6  ** Modified :       29/3/92 - set MAXERR to 0, put filename in error    **
7  **                  messages, eddyg.					 **
8  **                  18-04-92, Edward Groenendaal                        **
9  **                  Added #if NeedFunctionPrototypes stuff              **
10  **************************************************************************/
11 
12 /* with A/UX on a macII the pre-processor tries to expand the lex input macro
13  * within the X11R4 Xutil.h header file, therefore to prevent this I have
14  * defined the _XUTIL_H_ symbol for macII's, it's not needed in this file
15  * anyway. Edward Groenendaal 19-04-92.. Easter day.. and I'm doing this!?!
16  *
17  * 20-04-92 Edward Groenendaal - I had the same problem on a Sun (SunOS4.1.1)
18  * with X11R4, I therefore am going to undef _XUTIL_H_ for ALL machines.
19  */
20 
21 #ifdef __STDC__
22 #include "xdtm.h"
23 #endif
24 
25 /* #ifdef macII */
26 #ifndef _XUTIL_H_
27 #define _XUTIL_H_
28 #endif
29 /* #endif */
30 
31 #ifndef __STDC__
32 #include "xdtm.h"
33 #endif
34 #include "parse.h"
35 
36 /*
37  * Check to see if we are using flex instead of lex.  If so, need to
38  * undefine yywrap.
39  */
40 
41 #ifdef FLEX_SCANNER
42 #undef yywrap
43 #endif
44 
45 /* I shall use the macro RETURN whenever returning a token. If DEBUG_LEX has
46  * been defined then the token will be printed out, otherwise it will
47  * be returned.
48  */
49 
50 #ifdef DEBUG_LEX
51 
52 /* define the RETURN macro to print the token to be returned */
53 # define RETURN(token)    fprintf(stdout,"Token: " #token "\tReturned.\n")
54 
55   /* define the tokens to be returned. ONLY in DEBUG mode, when in normal
56    * operation the tokens are defined by yacc.
57    */
58   enum tokens { IF_T,
59 	        SET_T,
60 	        ICON_T,
61 	        NAME_T,
62 	        PATH_T,
63 	        ASSIGN_T,
64 	        EQUAL_T,
65 		NEQUAL_T,
66 	        STRING_T,
67 	        SEMIC_T,
68 	        O_PAR_T,
69 	        C_PAR_T,
70 	        O_BRACE_T,
71 	        C_BRACE_T,
72 		DEFICON_T,
73 		CHECKPATH_T,
74 		TRUE_T,
75 		FALSE_T,
76 		TYPE_T,
77                 DIR_T,
78 		FILE_T,
79 		READ_T,
80 		WRITE_T,
81 		EXE_T,
82 		BLOCK_T,
83 		CHARACTER_T,
84 		SLINK_T,
85 		SOCKET_T,
86 		FIFO_T,
87 		PROG_T,
88 		OPTIONS_T,
89 		TERMOPT_T,
90 		COMMA_T,
91 		MSEL_T,
92 		OSEL_T,
93 		NSEL_T,
94 		ASEL_T,
95 		DEFINE_T,
96 		DEFAPPL_T,
97 		TERM_T,
98 		NOTERM_T,
99 		FIRST_T,
100 		COLON_T,
101 		IGNORE_T,
102 		ERRORTOKEN
103 	      };
104 
105 #else           /* No DEBUG */
106 
107 #include "parser.h"         /* get the tokens from yacc */
108 
109 /* define the RETURN token to set the return value to the token to be
110  * returned, then return that token.
111  */
112 # define RETURN(token)    yylval.number=token;return(token)
113 #endif
114 
115 #include <sys/types.h>
116 #include <stdio.h>
117 
118 #define MAXERR      0       /* Maximum number of errors before the parser */
119                             /* quits. */
120 
121 void yyerror(
122 #if NeedFunctionPrototypes
123 	     char*
124 #endif
125 	     );
126 
127 typedef struct {                    /* structure for keyword table */
128     String name;
129     int token;
130 } keyword;
131 
132 static keyword keywordtable[] = {   /* table of keywords, in alphabetical order */
133   {"ASEL",    ASEL_T},
134   {"False",   FALSE_T},
135   {"MSEL",    MSEL_T},
136   {"NOTERM",  NOTERM_T},
137   {"NSEL",    NSEL_T},
138   {"OSEL",    OSEL_T},
139   {"TERM",    TERM_T},
140   {"True",    TRUE_T},
141   {"block",   BLOCK_T},
142   {"character", CHARACTER_T},
143   {"checkpath", CHECKPATH_T},
144   {"cmd",     CMD_T},
145   {"defappl", DEFAPPL_T},
146   {"deficon", DEFICON_T},
147   {"define",  DEFINE_T},
148   {"dir",     DIR_T},
149   {"exe",     EXE_T},
150   {"false",   FALSE_T},
151   {"fifo",    FIFO_T},
152   {"file",    FILE_T},
153   {"first",   FIRST_T},
154   {"icon",    ICON_T},
155   {"if",      IF_T},
156   {"ignore",  IGNORE_T},
157   {"name",    NAME_T},
158   {"options", OPTIONS_T},
159   {"path",    PATH_T},
160   {"prog",    PROG_T},
161   {"read",    READ_T},
162   {"set",     SET_T},
163   {"slink",   SLINK_T},
164   {"socket",  SOCKET_T},
165   {"termopt", TERMOPT_T},
166   {"true",    TRUE_T},
167   {"type",    TYPE_T},
168   {"write",   WRITE_T}
169 };
170 /* number of entries in the keyword table */
171 static int numkeywords = (sizeof(keywordtable)/sizeof(keywordtable[0]));
172 
173 int parseerror=0;                   /* Number of parse errors */
174 char errormessage[255];             /* used for error messsages */
175 
176 %}
177 %%
178 [\t ]*"#".*     { /* Remove Comments from beginning of line */ }
179 "="             { RETURN(ASSIGN_T);     }
180 "=="            { RETURN(EQUAL_T);      }
181 "{"             { RETURN(O_BRACE_T);    }
182 "}"             { RETURN(C_BRACE_T);    }
183 "("             { RETURN(O_PAR_T);      }
184 ")"             { RETURN(C_PAR_T);      }
185 ";"             { RETURN(SEMIC_T);      }
186 ","             { RETURN(COMMA_T);      }
187 ":"		{ RETURN(COLON_T);	}
188 [A-Za-z]+       { int token = parse_keyword(yytext);
189 #ifndef DEBUG_LEX
190 		  yylval.number = token;
191                   return(token);
192 #endif
193 		}
194 
195 \n		{
196 #ifdef FLEX_SCANNER
197   		  yylineno++;
198 #endif
199 		}
200 [\t ]           { /* Ignore White space */ }
201 \"[^\"]*\"      {
202 #ifdef DEBUG_LEX
203                   fprintf(stdout, "Token STRING_T %s returned", yytext);
204 #else
205 		  yylval.string = yytext;
206                   return(STRING_T);
207 #endif
208                 }
209 .               {
210 		sprintf(errormessage, "illegal character \'%c\'.", yytext[0]);
211 		yyerror(errormessage);
212                 }
213 %%
214 
215 
216 /*****************************************************************************
217  *                                yywrap                                     *
218  *****************************************************************************/
219 int yywrap()
220 {
221     /* function called when EOF encounterd.
222      *
223      * - Takes nothing
224      * + returns EOF token, not actually used other than to indicate an error
225      *   to the parser. Useful in DEBUG mode to see that EOF has been detected.
226      */
227 
228     RETURN(EOFTOKEN);
229 }
230 
231 
232 /*****************************************************************************
233  *                            parse_keyword                                  *
234  *****************************************************************************/
235 int parse_keyword(str)
236 String str;
237 {
238   /* Function to determine whether a string is a reserved keyword or an
239    * identifier. A table of keywords is searched via a binary search to check
240    * to see if the string is a keyword,if it is found the associated
241    * token is returned, otherwise an error is printed and ERRORTOKEN
242    * is returned.
243    * The effect of debugging is to prevent the assignment
244    * to the yacc structure, and to print out the keyword if found.
245    *
246    * - Takes a string to check
247    * + Returns a token (int)
248    */
249 
250   register int lower = 0, upper = numkeywords-1;
251 
252   while (lower <= upper) {
253     int middle = (lower + upper) /2;
254     keyword *p = &keywordtable[middle];
255     int res = strcmp(p->name, str);
256 
257     if (res < 0) {
258       lower = middle +1;
259     } else if (res == 0) {
260 #ifdef DEBUG_LEX
261       fprintf(stdout, "Token: %s\tReturned.\n", p->name);
262 #endif
263       return(p->token);
264     } else {
265       upper = middle -1;
266     }
267   }
268   sprintf(errormessage, "unknown keyword \'%s\'.", yytext);
269   yyerror(errormessage);
270   RETURN(ERRORTOKEN);
271 }
272 
273 /****************************************************************************
274  *                                     yyerror                              *
275  ****************************************************************************/
276 void yyerror(message)
277 char *message;
278 {
279   /* For the moment (29/3/92) the program will be terminated on the first
280    * parse error, this is due to the complexities involved in continuing
281    * the parse after an error.
282    * Edward Groenendaal.
283    *
284    */
285 
286   extern int yylineno;
287 
288   if (preferences_filename == NULL)
289     preferences_filename = XtNewString("config file");
290 
291   if (parseerror < MAXERR) {
292     fprintf(stderr, "(E) %s:line :%2d: ", preferences_filename, yylineno);
293     fprintf(stderr, "%s\n", message);
294     parseerror++;
295   } else {
296     fprintf(stderr, "(E) %s:line :%2d: ", preferences_filename, yylineno);
297     fprintf(stderr, "%s\n", message);
298     parseerror++;
299     /* fprintf(stderr, "Fatal error: over %d errors, exiting\n", MAXERR); */
300     exit(2);
301   }
302 }
303