root/op/1.32/lex.l

Revision 247, 9.4 kB (checked in by athomas, 4 years ago)
  • Merged autoconf branch into trunk.
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 <syslog.h>
17 #include "defs.h"
18
19 static cmd_t    *newcmd();
20 char    *savestr();
21 void addvar(const char *str);
22 void preproc(const char *str);
23 void preprocerror(const char *str);
24 static void addquotedarg(int state, cmd_t *cmd, const char *instr);
25 static void addarg(int state, cmd_t *cmd, const char *instr);
26
27 int     yyline = 1;
28
29 %}
30
31 WS              [ \t]*
32 NWS             [^ \n\t;]+
33
34 %s ARGS
35 %a 2700
36 %o 3700
37
38 %%
39         int     state = 0;
40         cmd_t   *cmd = NULL;
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>([^ \n\t'"]*'(\\.|[^'])*')+       addquotedarg(state, cmd, yytext);
53 <ARGS>([^ \n\t'"]*\"(\\.|[^\"])*\")+    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, q;
178
179         if (strlen(instr) + 2 > MAXSTRLEN) {
180                 fatal(1, "Quoted argument too long\n");
181                 exit(1);
182         }
183         for (o = 0; !strchr("'\"", instr[o]); ++o)
184                 buffer[o] = instr[o];
185         q = o;
186
187         for (i = o + 1; instr[i] && instr[i] != instr[q]; ++i, ++o) {
188                 if (instr[i] == '\\') {
189                 int c = instr[++i];
190
191                         if (strchr("'\"", c)) {
192                                 buffer[o] = c;
193                         } else {
194                                 buffer[o++] = '\\';
195                                 buffer[o] = c;
196                         }
197                 } else
198                         buffer[o] = instr[i];
199         }
200         buffer[o] = 0;
201         addarg(state, cmd, buffer);
202 }
203
204 static void addarg(int state, cmd_t *cmd, const char *instr) {
205 char *str = expandvars(instr);
206
207         if (state == 0) {
208                 msg("cmd='%s' add arg '%s'",cmd->name,str);
209                 if (cmd->margs == cmd->nargs)  {
210                         cmd->margs += cmd->margs;
211                         cmd->args = (char **)realloc(cmd->args,
212                                         sizeof(char *) * cmd->margs);
213                         if (cmd->args == NULL)
214                                 fatal(1, "Unable to groupw args");
215                 }
216                 cmd->args[cmd->nargs++] = savestr(str);
217         } else if (state == 1) {
218                 msg("cmd='%s' add opt '%s'",cmd->name,str);
219                 if (cmd->mopts == cmd->nopts) {
220                         cmd->mopts += cmd->mopts;
221                         cmd->opts = (char **)realloc(cmd->opts,
222                                         sizeof(char *) * cmd->mopts);
223                         if (cmd->opts == NULL)
224                                 fatal(1, "Unable to groupw opts");
225                 }
226                 cmd->opts[cmd->nopts++] = savestr(str);
227         } else {
228                 fatal(1, "bad state (%d) received\n",state);
229         }
230         free(str);
231 }
232
233 char    *savestr(str)
234 char    *str;
235 {
236         char    *s = (char *)malloc(strlen(str)+1);
237
238         if (s == NULL)
239                 fatal(1, "No string space");
240
241         strcpy(s, str);
242         return s;
243 }
244
245 static cmd_t    *alloccmd(char *name)
246 {
247         cmd_t   *cmd = (cmd_t *)malloc(sizeof(cmd_t));
248
249         if (cmd == NULL)
250                 fatal(1, "Unable to alloc space for new command");
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 static cmd_t    *newcmd(char *name)
265 {
266         cmd_t   *cmd = alloccmd(name);
267
268         cmd->next = First;
269         First = cmd;
270
271         return cmd;
272
273 }
274
275 int ReadFile(file)
276 char    *file;
277 {
278         struct stat     statbuf;
279         FILE            *fd;
280        
281         if ((stat(file, &statbuf) < 0))
282                 return 0;
283         if ((statbuf.st_uid != 0) || /* Owned by root */
284                         ((statbuf.st_mode & 0077) != 0)) { /* SD - no perm */
285                 logger(LOG_ERR, "Permission problems on %s", file);
286                 return 0;
287         }
288         if ((fd = fopen(file,"r")) == NULL)
289                 return 0;
290
291         yyin = fd;
292         yylex();
293
294         return 1;
295 }
296
297 int CountArgs(cmd)
298 cmd_t   *cmd;
299 {
300         int     i, val;
301         int     wild = 0, max = 0;
302         char    *cp, *np, str[MAXSTRLEN];
303
304         for (i = 0; i < cmd->nargs; i++) {
305                 np = cmd->args[i];
306
307                 while ((cp = strchr(np, '$')) != NULL) {
308                         if ((cp != cmd->args[i]) && (*(cp-1) == '\\'))
309                                 np = cp + 1;
310                         else {
311                                 if (*(cp+1) == '*') {
312                                         wild = 1;
313                                         ++cp;
314                                         np = cp;
315                                         continue;
316                                 }
317                                 cp++;
318                                 np = cp;
319                                
320                                 while (isdigit(*cp))
321                                         cp++;
322                                 if ((cp - np) == 0)
323                                         continue;
324                                 strncpy(str, np, cp - np);
325                                 str[cp - np] = '\0';
326                                 val = atoi(str);
327                                 if (val > max)
328                                         max = val;
329                         }
330                 }
331         }
332
333         if (wild)
334                 return -max;
335         return max;
336 }
337
338 static int      cmpopts(a, b)
339 char    *a, *b;
340 {
341         char    *cp_a, *cp_b;
342         int     val_a, val_b;
343         char    str_a[MAXSTRLEN], str_b[MAXSTRLEN];
344
345         if (*a != '$' && *b != '$')
346                 return 0;
347         if (*a == '$' && *b != '$')
348                 return -1;
349         if (*a != '$' && *b == '$')
350                 return  1;
351
352         cp_a = ++a;
353         cp_b = ++b;
354         while ((*cp_a != '\0') && (*cp_a != '='))
355                 if (! isdigit(*cp_a))
356                         break;
357         while ((*cp_b != '\0') && (*cp_b != '='))
358                 if (! isdigit(*cp_b))
359                         break;
360        
361         if (*cp_a != '=' && *cp_b != '=')
362                 return 0;
363         if (*cp_a == '=' && *cp_b != '=')
364                 return -1;
365         if (*cp_a != '=' && *cp_b == '=')
366                 return  1;
367
368         strncpy(str_a, a, cp_a - a);
369         str_a[cp_a - a] = '\0';
370         val_a = atoi(str_a);
371         strncpy(str_b, b, cp_b - a);
372         str_a[cp_b - b] = '\0';
373         val_b = atoi(str_b);
374
375         if (val_a < val_b)
376                 return -1;
377         if (val_a > val_b)
378                 return  1;
379         return 0;
380 }
381
382 void sortopts(cmd)
383 cmd_t   *cmd;
384 {
385         qsort(cmd->opts, cmd->nopts, sizeof(char *), cmpopts);
386 }
387
388 /* Build a new command but don't merge it into the global list */
389 cmd_t   *BuildSingle(cmd_t *def, cmd_t *cmd)
390 {
391         cmd_t   *new = alloccmd(cmd->name ? cmd->name : "");
392         char    defname[MAXSTRLEN], optname[MAXSTRLEN], *cp;
393         int             i, j;
394         if (cmd == NULL)
395                 return def;
396         if (def == NULL)
397                 return cmd;
398
399         for (i = 0; i < cmd->nargs; i++)
400                 addarg(0, new, cmd->args[i]);
401
402         for (i = 0; i < def->nopts; i++) {
403         int skipped = 0;
404
405                 if ((cp = strchr(def->opts[i], '=')) == NULL)
406                         strcpy(defname, def->opts[i]);
407                 else {
408                         int     l = cp - def->opts[i];
409                         strncpy(defname, def->opts[i], l);
410                         defname[l] = '\0';
411                 }
412                 for (j = 0; j < cmd->nopts; j++) {
413                         if ((cp = strchr(cmd->opts[j], '=')) == NULL)
414                                 strcpy(optname, cmd->opts[j]);
415                         else {
416                                 int     l = cp - cmd->opts[j];
417                                 strncpy(optname, cmd->opts[j], l);
418                                 optname[l] = '\0';
419                         }
420                         if (strcmp(defname, optname) == 0) {
421                                 skipped = 1;
422                                 break;
423                         }
424                 }
425                 if (skipped) continue;
426                 if (def->opts[i][0] != '\0')
427                         addarg(1, new, def->opts[i]);
428         }
429         for (j = 0; j < cmd->nopts; j++)
430                 addarg(1, new, cmd->opts[j]);
431
432         /* sortopts(new); */
433
434         return new;
435 }
436
437
438 /* Build a new command *and* merge it with the global command list */
439 cmd_t   *Build(cmd_t *def, cmd_t *cmd)
440 {
441         cmd_t *new =    BuildSingle(def, cmd);
442
443         new->next = First;
444         First = new;
445
446         return new;
447 }
Note: See TracBrowser for help on using the browser.