]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - usr.sbin/config/config.y
add -n option to suppress clearing the build tree and add -DNO_CLEAN
[FreeBSD/FreeBSD.git] / usr.sbin / config / config.y
1 %union {
2         char    *str;
3         int     val;
4         struct  file_list *file;
5 }
6
7 %token  ARCH
8 %token  COMMA
9 %token  CONFIG
10 %token  CPU
11 %token  NOCPU
12 %token  DEVICE
13 %token  NODEVICE
14 %token  ENV
15 %token  EQUALS
16 %token  HINTS
17 %token  IDENT
18 %token  MAXUSERS
19 %token  PROFILE
20 %token  OPTIONS
21 %token  NOOPTION
22 %token  MAKEOPTIONS
23 %token  NOMAKEOPTION 
24 %token  SEMICOLON
25 %token  INCLUDE
26 %token  FILES
27
28 %token  <str>   ID
29 %token  <val>   NUMBER
30
31 %type   <str>   Save_id
32 %type   <str>   Opt_value
33 %type   <str>   Dev
34 %token  <str>   PATH
35
36 %{
37
38 /*
39  * Copyright (c) 1988, 1993
40  *      The Regents of the University of California.  All rights reserved.
41  *
42  * Redistribution and use in source and binary forms, with or without
43  * modification, are permitted provided that the following conditions
44  * are met:
45  * 1. Redistributions of source code must retain the above copyright
46  *    notice, this list of conditions and the following disclaimer.
47  * 2. Redistributions in binary form must reproduce the above copyright
48  *    notice, this list of conditions and the following disclaimer in the
49  *    documentation and/or other materials provided with the distribution.
50  * 3. All advertising materials mentioning features or use of this software
51  *    must display the following acknowledgement:
52  *      This product includes software developed by the University of
53  *      California, Berkeley and its contributors.
54  * 4. Neither the name of the University nor the names of its contributors
55  *    may be used to endorse or promote products derived from this software
56  *    without specific prior written permission.
57  *
58  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
59  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
60  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
61  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
62  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
63  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
64  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
65  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
66  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
67  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
68  * SUCH DAMAGE.
69  *
70  *      @(#)config.y    8.1 (Berkeley) 6/6/93
71  * $FreeBSD$
72  */
73
74 #include <assert.h>
75 #include <ctype.h>
76 #include <err.h>
77 #include <stdio.h>
78 #include <string.h>
79
80 #include "config.h"
81
82 struct  device_head dtab;
83 char    *ident;
84 char    *env;
85 int     envmode;
86 int     hintmode;
87 int     yyline;
88 const   char *yyfile;
89 struct  file_list_head ftab;
90 struct  files_name_head fntab;
91 char    errbuf[80];
92 int     maxusers;
93
94 #define ns(s)   strdup(s)
95 int include(const char *, int);
96 void yyerror(const char *s);
97 int yywrap(void);
98
99 static void newdev(char *name);
100 static void newfile(char *name);
101 static void rmdev_schedule(struct device_head *dh, char *name);
102 static void newopt(struct opt_head *list, char *name, char *value);
103 static void rmopt_schedule(struct opt_head *list, char *name);
104
105 static char *
106 devopt(char *dev)
107 {
108         char *ret = malloc(strlen(dev) + 5);
109         
110         sprintf(ret, "DEV_%s", dev);
111         raisestr(ret);
112         return ret;
113 }
114
115 %}
116 %%
117 Configuration:
118         Many_specs
119                 ;
120
121 Many_specs:
122         Many_specs Spec
123                 |
124         /* lambda */
125                 ;
126
127 Spec:
128         Device_spec SEMICOLON
129                 |
130         Config_spec SEMICOLON
131                 |
132         INCLUDE PATH SEMICOLON {
133                 if (incignore == 0)
134                         include($2, 0);
135                 };
136                 |
137         INCLUDE ID SEMICOLON {
138                   if (incignore == 0)
139                         include($2, 0);
140                 };
141                 |
142         FILES ID SEMICOLON { newfile($2); };
143                 |
144         SEMICOLON
145                 |
146         error SEMICOLON
147                 ;
148
149 Config_spec:
150         ARCH Save_id {
151                 if (machinename != NULL && !eq($2, machinename))
152                     errx(1, "%s:%d: only one machine directive is allowed",
153                         yyfile, yyline);
154                 machinename = $2;
155                 machinearch = $2;
156               } |
157         ARCH Save_id Save_id {
158                 if (machinename != NULL &&
159                     !(eq($2, machinename) && eq($3, machinearch)))
160                     errx(1, "%s:%d: only one machine directive is allowed",
161                         yyfile, yyline);
162                 machinename = $2;
163                 machinearch = $3;
164               } |
165         CPU Save_id {
166                 struct cputype *cp =
167                     (struct cputype *)calloc(1, sizeof (struct cputype));
168                 cp->cpu_name = $2;
169                 SLIST_INSERT_HEAD(&cputype, cp, cpu_next);
170               } |
171         NOCPU Save_id {
172                 struct cputype *cp, *cp2;
173                 SLIST_FOREACH_SAFE(cp, &cputype, cpu_next, cp2) {
174                         if (eq(cp->cpu_name, $2)) {
175                                 SLIST_REMOVE(&cputype, cp, cputype, cpu_next);
176                                 free(cp);
177                         }
178                 }
179               } |
180         OPTIONS Opt_list
181                 |
182         NOOPTION Save_id { rmopt_schedule(&opt, $2); } |
183         MAKEOPTIONS Mkopt_list
184                 |
185         NOMAKEOPTION Save_id { rmopt_schedule(&mkopt, $2); } |
186         IDENT ID { ident = $2; } |
187         System_spec
188                 |
189         MAXUSERS NUMBER { maxusers = $2; } |
190         PROFILE NUMBER { profiling = $2; } |
191         ENV ID {
192                 env = $2;
193                 envmode = 1;
194                 } |
195         HINTS ID {
196                 struct hint *hint;
197
198                 hint = (struct hint *)calloc(1, sizeof (struct hint));
199                 hint->hint_name = $2;
200                 STAILQ_INSERT_TAIL(&hints, hint, hint_next);
201                 hintmode = 1;
202                 }
203
204 System_spec:
205         CONFIG System_id System_parameter_list {
206                 errx(1, "%s:%d: root/dump/swap specifications obsolete",
207                       yyfile, yyline);
208                 }
209           |
210         CONFIG System_id
211           ;
212
213 System_id:
214         Save_id { newopt(&mkopt, ns("KERNEL"), $1); };
215
216 System_parameter_list:
217           System_parameter_list ID
218         | ID
219         ;
220
221 Opt_list:
222         Opt_list COMMA Option
223                 |
224         Option
225                 ;
226
227 Option:
228         Save_id {
229                 newopt(&opt, $1, NULL);
230                 if (strchr($1, '=') != NULL)
231                         errx(1, "%s:%d: The `=' in options should not be "
232                             "quoted", yyfile, yyline);
233               } |
234         Save_id EQUALS Opt_value {
235                 newopt(&opt, $1, $3);
236               } ;
237
238 Opt_value:
239         ID { $$ = $1; } |
240         NUMBER {
241                         char buf[80];
242
243                         (void) snprintf(buf, sizeof(buf), "%d", $1);
244                         $$ = ns(buf);
245                 } ;
246
247 Save_id:
248         ID { $$ = $1; }
249         ;
250
251 Mkopt_list:
252         Mkopt_list COMMA Mkoption
253                 |
254         Mkoption
255                 ;
256
257 Mkoption:
258         Save_id { newopt(&mkopt, $1, ns("")); } |
259         Save_id EQUALS Opt_value { newopt(&mkopt, $1, $3); } ;
260
261 Dev:
262         ID { $$ = $1; }
263         ;
264
265 Device_spec:
266         DEVICE Dev_list
267                 |
268         NODEVICE NoDev_list
269                 ;
270
271 Dev_list:
272         Dev_list COMMA Device
273                 |
274         Device
275                 ;
276
277 NoDev_list:
278         NoDev_list COMMA NoDevice
279                 |
280         NoDevice
281                 ;
282
283 Device:
284         Dev {
285                 newopt(&opt, devopt($1), ns("1"));
286                 /* and the device part */
287                 newdev($1);
288                 }
289
290 NoDevice:
291         Dev {
292                 char *s = devopt($1);
293
294                 rmopt_schedule(&opt, s);
295                 free(s);
296                 /* and the device part */
297                 rmdev_schedule(&dtab, $1);
298                 } ;
299
300 %%
301
302 void
303 yyerror(const char *s)
304 {
305
306         errx(1, "%s:%d: %s", yyfile, yyline + 1, s);
307 }
308
309 int
310 yywrap(void)
311 {
312         if (found_defaults) {
313                 if (freopen(PREFIX, "r", stdin) == NULL)
314                         err(2, "%s", PREFIX);           
315                 yyfile = PREFIX;
316                 yyline = 0;
317                 found_defaults = 0;
318                 return 0;
319         }
320         return 1;
321 }
322
323 /*
324  * Add a new file to the list of files.
325  */
326 static void
327 newfile(char *name)
328 {
329         struct files_name *nl;
330         
331         nl = (struct files_name *) calloc(1, sizeof *nl);
332         nl->f_name = name;
333         STAILQ_INSERT_TAIL(&fntab, nl, f_next);
334 }
335         
336 /*
337  * Find a device in the list of devices.
338  */
339 static struct device *
340 finddev(struct device_head *dlist, char *name)
341 {
342         struct device *dp;
343
344         STAILQ_FOREACH(dp, dlist, d_next)
345                 if (eq(dp->d_name, name))
346                         return (dp);
347
348         return (NULL);
349 }
350         
351 /*
352  * Add a device to the list of devices.
353  */
354 static void
355 newdev(char *name)
356 {
357         struct device *np;
358
359         if (finddev(&dtab, name)) {
360                 printf("WARNING: duplicate device `%s' encountered.\n", name);
361                 return;
362         }
363
364         np = (struct device *) calloc(1, sizeof *np);
365         np->d_name = name;
366         STAILQ_INSERT_TAIL(&dtab, np, d_next);
367 }
368
369 /*
370  * Schedule a device to removal.
371  */
372 static void
373 rmdev_schedule(struct device_head *dh, char *name)
374 {
375         struct device *dp;
376
377         dp = finddev(dh, name);
378         if (dp != NULL) {
379                 STAILQ_REMOVE(dh, dp, device, d_next);
380                 free(dp->d_name);
381                 free(dp);
382         }
383 }
384
385 /*
386  * Find an option in the list of options.
387  */
388 static struct opt *
389 findopt(struct opt_head *list, char *name)
390 {
391         struct opt *op;
392
393         SLIST_FOREACH(op, list, op_next)
394                 if (eq(op->op_name, name))
395                         return (op);
396
397         return (NULL);
398 }
399
400 /*
401  * Add an option to the list of options.
402  */
403 static void
404 newopt(struct opt_head *list, char *name, char *value)
405 {
406         struct opt *op;
407
408         /*
409          * Ignore inclusions listed explicitly for configuration files.
410          */
411         if (eq(name, OPT_AUTOGEN)) {
412                 incignore = 1;
413                 return;
414         }
415
416         if (findopt(list, name)) {
417                 printf("WARNING: duplicate option `%s' encountered.\n", name);
418                 return;
419         }
420
421         op = (struct opt *)calloc(1, sizeof (struct opt));
422         op->op_name = name;
423         op->op_ownfile = 0;
424         op->op_value = value;
425         SLIST_INSERT_HEAD(list, op, op_next);
426 }
427
428 /*
429  * Remove an option from the list of options.
430  */
431 static void
432 rmopt_schedule(struct opt_head *list, char *name)
433 {
434         struct opt *op;
435
436         op = findopt(list, name);
437         if (op != NULL) {
438                 SLIST_REMOVE(list, op, opt, op_next);
439                 free(op->op_name);
440                 free(op);
441         }
442 }