root/op/1.25/lex.l

Revision 207, 8.9 kB (checked in by root, 5 years ago)

Initial import.

Line 
1 %{
2 /* +-------------------------------------------------------------------+ */
3 /* | Copyright 1991, David Koblas.                                     | */
4 /* |   Permission to use, copy, modify, and distribute this software   | */
5 /* |   and its documentation for any purpose and without fee is hereby | */
6 /* |   granted, provided that the above copyright notice appear in all | */
7 /* |   copies and that both that copyright notice and this permission  | */
8 /* |   notice appear in supporting documentation.  This software is    | */
9 /* |   provided "as is" without express or implied warranty.           | */
10 /* +-------------------------------------------------------------------+ */
11
12 #include <stdio.h>
13 #include <string.h>
14 #include <stdarg.h>
15 #include <ctype.h>
16 #include "defs.h"
17
18 static cmd_t    *newcmd();
19 char    *savestr();
20 void addvar(const char *str);
21 void preproc(const char *str);
22 void preprocerror(const char *str);
23 static void addquotedarg(int state, cmd_t *cmd, const char *instr);
24 static void addarg(int state, cmd_t *cmd, const char *instr);
25
26 #ifndef _AIX
27 extern char     *strchr();
28 #endif
29 int     yyline = 1;
30
31 %}
32
33 WS              [ \t]*
34 NWS             [^ \n\t;]+
35
36 %s ARGS
37
38 %%
39         int     state = 0;
40         cmd_t   *cmd;
41
42 #[^\n]*                 ;
43 ^%(((if|elsif)[ \t]+.*)|(else|endif))           { preproc(yytext); }
44 ^%.*                    { preprocerror(yytext); }
45 \n                      { yyline++; BEGIN 0; }
46 ^[A-Z_][A-Z_0-9]*=[^\n\r]*      { addvar(yytext); }
47 ^[^ \n\t]+              { cmd = newcmd(yytext);
48                                 state = (strcmp(yytext,"DEFAULT")==0) ? 1 : 0;
49                                 BEGIN ARGS; }
50 ^{WS}                   BEGIN ARGS;
51 <ARGS>";"               state++;
52 <ARGS>'(\\.|[^'])*'     addquotedarg(state, cmd, yytext);
53 <ARGS>\"(\\.|[^\"])*\"  addquotedarg(state, cmd, yytext);
54 <ARGS>{NWS}             addarg(state, cmd, yytext);
55 <ARGS>{WS}              ;
56 %%
57 #include <sys/types.h>
58 #include <sys/stat.h>
59 #include <string.h>
60
61 void msg(const char *format, ...)
62 {
63 #if 0
64         va_list ap;
65         char    *s;
66
67         va_start(ap);
68         s = va_arg(ap, char *);
69         fprintf(stderr,"line %d: ",yyline);
70         vfprintf(stderr, s, ap);
71         fputc('\n', stderr);
72         va_end(ap);
73 #endif
74 }
75
76 char *expandvars(const char *instr) {
77 char *str = (char*)malloc(VAR_EXPAND_LEN);
78 int i = 0;
79
80         if (str == NULL)
81                 fatal(1, "Unable to allocate variable expansion buffer");
82
83         while (*instr)
84                 if (isupper(*instr) || *instr == '_') {
85                 const char *mark = instr;
86                 var_t *var;
87
88                         while (*instr && (isupper(*instr) || isdigit(*instr) || *instr == '_'))
89                                 ++instr;
90                         for (var = Variables; var != 0; var = var->next) {
91                         int l = strlen(var->name);
92
93                                 if (instr - mark > l) l = instr - mark;
94                                 if (!strncmp(mark, var->name, l)) {
95                                         str[i] = 0;
96                                         strcat(str, var->value);
97                                         i += strlen(var->value);
98                                         break;
99                                 }
100                         }
101                         if (!var) {
102                                 instr = mark + 1;
103                                 str[i++] = *mark;
104                         }
105                 } else
106                         str[i++] = *instr++;
107         str[i] = 0;
108         return str;
109 }
110
111 void preprocerror(const char *str) {
112         fprintf(stderr, "Invalid preprocessor command '%s'\n", str);
113         exit(1);
114 }
115
116 void preproc(const char *str) {
117         if (!strncmp(str, "%if", 3)) {
118         } else
119         if (!strncmp(str, "%elseif", 7)) {
120         } else
121         if (!strcmp(str, "%else")) {
122         } else
123         if (!strcmp(str, "%endif")) {
124         } else
125                 preprocerror(str);
126 }
127
128 void addvar(const char *str) {
129 char name[VAR_NAME_LEN], value[VAR_EXPAND_LEN];
130 const char *eq = strchr(str, '=');
131
132         if (eq && str - eq < VAR_NAME_LEN) {
133         int i, o;
134         var_t *var;
135
136                 strncpy(name, str, eq - str);
137                 name[eq - str] = 0;
138
139                 for (o = 0, i = eq - str + 1; o < VAR_EXPAND_LEN - 1 && str[i]; ++i)
140                         if (str[i] == '\\') {
141                                 switch (str[++i]) {
142                                         case 'n' : value[o++] = '\n'; break;
143                                         case 'r' : value[o++] = '\r'; break;
144                                         case 't' : value[o++] = '\t'; break;
145                                         case 'a' : value[o++] = '\a'; break;
146                                         case 'b' : value[o++] = '\b'; break;
147                                         default : value[o++] = str[i]; break;
148                                 }
149                         } else
150                         if (str[i] == '"')
151                                 break;
152                         else
153                                 value[o++] = str[i];
154                 value[o++] = 0;
155
156                 if ((var = (var_t*)malloc(sizeof(var_t))) == NULL)
157                         fatal(1, "Unable to allocate var_t");
158                 if ((var->name = malloc(strlen(name) + 1)) == NULL)
159                         fatal(1, "Unable to allocate variable name");
160                 strcpy(var->name, name);
161                 var->value = expandvars(value);
162                 var->next = 0;
163
164                 if (Variables) {
165                 var_t *i;
166
167                         for (i = Variables; i->next; i = i->next) ;
168                         i->next = var;
169                 } else
170                         Variables = var;
171         } else
172                 fatal(1, "Invalid alias");
173 }
174
175 static void addquotedarg(int state, cmd_t *cmd, const char *instr) {
176 char buffer[MAXSTRLEN];
177 int i, o;
178
179         if (strlen(instr) + 2 > MAXSTRLEN) {
180                 fatal(1, "Quoted argument too long\n");
181                 exit(1);
182         }
183         for (o = 0, i = 1; instr[i] != instr[0]; ++i, ++o) {
184                 if (instr[i] == '\\') {
185                 int c = instr[++i];
186
187                         if (strchr("'\"", c)) {
188                                 buffer[o] = c;
189                         } else {
190                                 buffer[o++] = '\\';
191                                 buffer[o] = c;
192                         }
193                 } else
194                         buffer[o] = instr[i];
195         }
196         buffer[o] = 0;
197         addarg(state, cmd, buffer);
198 }
199
200 static void addarg(int state, cmd_t *cmd, const char *instr) {
201 char *str = expandvars(instr);
202
203         if (state == 0) {
204                 msg("cmd='%s' add arg '%s'",cmd->name,str);
205                 if (cmd->margs == cmd->nargs)  {
206                         cmd->margs += cmd->margs;
207                         cmd->args = (char **)realloc(cmd->args,
208                                         sizeof(char *) * cmd->margs);
209                         if (cmd->args == NULL)
210                                 fatal(1, "Unable to groupw args");
211                 }
212                 cmd->args[cmd->nargs++] = savestr(str);
213         } else if (state == 1) {
214                 msg("cmd='%s' add opt '%s'",cmd->name,str);
215                 if (cmd->mopts == cmd->nopts) {
216                         cmd->mopts += cmd->mopts;
217                         cmd->opts = (char **)realloc(cmd->opts,
218                                         sizeof(char *) * cmd->mopts);
219                         if (cmd->opts == NULL)
220                                 fatal(1, "Unable to groupw opts");
221                 }
222                 cmd->opts[cmd->nopts++] = savestr(str);
223         } else {
224                 fatal(1, "bad state (%d) received\n",state);
225         }
226         free(str);
227 }
228
229 char    *savestr(str)
230 char    *str;
231 {
232         char    *s = (char *)malloc(strlen(str)+1);
233
234         if (s == NULL)
235                 fatal(1, "No string space");
236
237         strcpy(s, str);
238         return s;
239 }
240
241 static cmd_t    *newcmd(name)
242 char    *name;
243 {
244         cmd_t   *cmd = (cmd_t *)malloc(sizeof(cmd_t));
245
246         if (cmd == NULL)
247                 fatal(1, "Unable to alloc space for new command");
248
249         cmd->next = First;
250         First = cmd;
251
252         cmd->name = savestr(name);
253         cmd->nargs = 0;         cmd->margs = 16;
254         cmd->nopts = 0;         cmd->mopts = 16;
255         cmd->args = (char **)malloc(sizeof(char *)*cmd->margs);
256         cmd->opts = (char **)malloc(sizeof(char *)*cmd->mopts);
257
258         if (cmd->args == NULL || cmd->opts == NULL)
259                 fatal(1, "Unable to alloc args/opts");
260
261         return cmd;
262 }
263
264 int ReadFile(file)
265 char    *file;
266 {
267         struct stat     statbuf;
268         FILE            *fd;
269        
270         if ((stat(file, &statbuf) < 0) ||
271                 (statbuf.st_uid != 0) || /* Owned by root */
272                 ((statbuf.st_mode & 0077) != 0)) { /* SD - no perm */
273                 fatal(1, "Permission problems on %s", file);
274         }
275         if ((fd = fopen(file,"r")) == NULL) {
276                 fatal(1, "Couldn't open %s", file);
277         }
278
279         yyin = fd;
280         yylex();
281
282         return 0;
283 }
284
285 int CountArgs(cmd)
286 cmd_t   *cmd;
287 {
288         int     i, val;
289         int     wild = 0, max = 0;
290         char    *cp, *np, str[MAXSTRLEN];
291
292         for (i = 0; i < cmd->nargs; i++) {
293                 np = cmd->args[i];
294
295                 while ((cp = strchr(np, '$')) != NULL) {
296                         if ((cp != cmd->args[i]) && (*(cp-1) == '\\'))
297                                 np = cp + 1;
298                         else {
299                                 if (*(cp+1) == '*') {
300                                         wild = 1;
301                                         ++cp;
302                                         np = cp;
303                                         continue;
304                                 }
305                                 cp++;
306                                 np = cp;
307                                
308                                 while (isdigit(*cp))
309                                         cp++;
310                                 if ((cp - np) == 0)
311                                         continue;
312                                 strncpy(str, np, cp - np);
313                                 str[cp - np] = '\0';
314                                 val = atoi(str);
315                                 if (val > max)
316                                         max = val;
317                         }
318                 }
319         }
320
321         if (wild)
322                 return -max;
323         return max;
324 }
325
326 static int      cmpopts(a, b)
327 char    *a, *b;
328 {
329         char    *cp_a, *cp_b;
330         int     val_a, val_b;
331         char    str_a[MAXSTRLEN], str_b[MAXSTRLEN];
332
333         if (*a != '$' && *b != '$')
334                 return 0;
335         if (*a == '$' && *b != '$')
336                 return -1;
337         if (*a != '$' && *b == '$')
338                 return  1;
339
340         cp_a = ++a;
341         cp_b = ++b;
342         while ((*cp_a != '\0') && (*cp_a != '='))
343                 if (! isdigit(*cp_a))
344                         break;
345         while ((*cp_b != '\0') && (*cp_b != '='))
346                 if (! isdigit(*cp_b))
347                         break;
348        
349         if (*cp_a != '=' && *cp_b != '=')
350                 return 0;
351         if (*cp_a == '=' && *cp_b != '=')
352                 return -1;
353         if (*cp_a != '=' && *cp_b == '=')
354                 return  1;
355
356         strncpy(str_a, a, cp_a - a);
357         str_a[cp_a - a] = '\0';
358         val_a = atoi(str_a);
359         strncpy(str_b, b, cp_b - a);
360         str_a[cp_b - b] = '\0';
361         val_b = atoi(str_b);
362
363         if (val_a < val_b)
364                 return -1;
365         if (val_a > val_b)
366                 return  1;
367         return 0;
368 }
369
370 void sortopts(cmd)
371 cmd_t   *cmd;
372 {
373         qsort(cmd->opts, cmd->nopts, sizeof(char *), cmpopts);
374 }
375
376 cmd_t   *Build(def, cmd)
377 cmd_t   *def, *cmd;
378 {
379         cmd_t           *new = newcmd("");
380         char            defname[MAXSTRLEN], optname[MAXSTRLEN], *cp;
381         int             i, j;
382 #ifndef _AIX
383         extern char     *strchr();
384 #endif
385         if (cmd == NULL)
386                 return def;
387         if (def == NULL)
388                 return cmd;
389
390         for (i = 0; i < cmd->nargs; i++)
391                 addarg(0, new, cmd->args[i]);
392
393         for (i = 0; i < def->nopts; i++) {
394                 if ((cp = strchr(def->opts[i], '=')) == NULL)
395                         strcpy(defname, def->opts[i]);
396                 else {
397                         int     l = cp - def->opts[i];
398                         strncpy(defname, def->opts[i], l);
399                         defname[l] = '\0';
400                 }
401                 for (j = 0; j < cmd->nopts; j++) {
402                         if ((cp = strchr(cmd->opts[j], '=')) == NULL)
403                                 strcpy(optname, cmd->opts[j]);
404                         else {
405                                 int     l = cp - cmd->opts[j];
406                                 strncpy(optname, cmd->opts[j], l);
407                                 optname[l] = '\0';
408                         }
409                         if (strcmp(defname, optname) == 0)
410                                 def->opts[i][0] = '\0';
411                 }
412                 if (def->opts[i][0] != '\0')
413                         addarg(1, new, def->opts[i]);
414         }
415         for (j = 0; j < cmd->nopts; j++)
416                 addarg(1, new, cmd->opts[j]);
417
418         /* sortopts(new); */
419
420         return new;
421 }
Note: See TracBrowser for help on using the browser.