4146375a69512ceff739a697739f58de690face3
[dragonfly.git] / usr.sbin / config / config.y
1 %union {
2         char    *str;
3         int     val;
4         struct  file_list *file;
5 }
6
7 %token  ANY
8 %token  AT
9 %token  BUS
10 %token  COMMA
11 %token  CONFIG
12 %token  CONFIG_MACHINE
13 %token  CONFIG_MACHINE_ARCH
14 %token  CONFIG_PLATFORM
15 %token  CPU
16 %token  DEVICE
17 %token  DISABLE
18 %token  DRIVE
19 %token  DRQ
20 %token  EQUALS
21 %token  FLAGS
22 %token  IDENT
23 %token  IOMEM
24 %token  IOSIZ
25 %token  IRQ
26 %token  MAXUSERS
27 %token  MINUS
28 %token  NEXUS
29 %token  OPTIONS
30 %token  MAKEOPTIONS
31 %token  PORT
32 %token  PSEUDO_DEVICE
33 %token  SEMICOLON
34 %token  TARGET
35 %token  TTY
36 %token  UNIT
37 %token  VECTOR
38
39 %token  <str>   ID
40 %token  <val>   NUMBER
41 %token  <val>   FPNUMBER
42
43 %type   <str>   Save_id
44 %type   <str>   Opt_value
45 %type   <str>   Dev
46 %type   <str>   device_name
47
48 %{
49
50 /*
51  * Copyright (c) 1988, 1993
52  *      The Regents of the University of California.  All rights reserved.
53  *
54  * Redistribution and use in source and binary forms, with or without
55  * modification, are permitted provided that the following conditions
56  * are met:
57  * 1. Redistributions of source code must retain the above copyright
58  *    notice, this list of conditions and the following disclaimer.
59  * 2. Redistributions in binary form must reproduce the above copyright
60  *    notice, this list of conditions and the following disclaimer in the
61  *    documentation and/or other materials provided with the distribution.
62  * 3. All advertising materials mentioning features or use of this software
63  *    must display the following acknowledgement:
64  *      This product includes software developed by the University of
65  *      California, Berkeley and its contributors.
66  * 4. Neither the name of the University nor the names of its contributors
67  *    may be used to endorse or promote products derived from this software
68  *    without specific prior written permission.
69  *
70  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
71  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
72  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
73  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
74  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
75  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
76  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
77  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
78  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
79  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
80  * SUCH DAMAGE.
81  *
82  *      @(#)config.y    8.1 (Berkeley) 6/6/93
83  * $FreeBSD: src/usr.sbin/config/config.y,v 1.42.2.1 2001/01/23 00:09:32 peter Exp $
84  * $DragonFly: src/usr.sbin/config/config.y,v 1.15 2008/05/01 09:24:42 swildner Exp $
85  */
86
87 #include <ctype.h>
88 #include <err.h>
89 #include <stdio.h>
90 #include <string.h>
91
92 #include "config.h"
93
94 static struct   device cur;
95 static struct   device *curp = 0;
96
97 struct  device *dtab;
98 char    *ident;
99 int     yyline;
100 struct  file_list *ftab;
101 char    errbuf[80];
102 int     maxusers;
103
104 static int connect(char *, int);
105 static void yyerror(const char *s);
106
107 int yylex(void);
108
109 %}
110 %%
111 Configuration:
112         Many_specs
113                 ;
114
115 Many_specs:
116         Many_specs Spec
117                 |
118         /* lambda */
119                 ;
120
121 Spec:
122         Device_spec SEMICOLON
123               = { newdev(&cur); } |
124         Config_spec SEMICOLON
125                 |
126         SEMICOLON
127                 |
128         error SEMICOLON
129                 ;
130
131 Config_spec:
132         CONFIG_PLATFORM Save_id
133             = {
134                 if (platformname != NULL) {
135                     errx(1, "%d: only one platform directive is allowed",
136                         yyline);
137                 }
138                 platformname = $2;
139               } |
140         CONFIG_MACHINE Save_id
141             = {
142                 if (machinename != NULL) {
143                     errx(1, "%d: only one machine directive is allowed",
144                         yyline);
145                 }
146                 machinename = $2;
147               } |
148         CONFIG_MACHINE_ARCH Save_id
149               = {
150                 if (machinearchname != NULL) {
151                     errx(1, "%d: only one machine_arch directive is allowed",
152                         yyline);
153                 }
154                 machinearchname = $2;
155               } |
156         CPU Save_id
157               = {
158                 struct cputype *cp;
159
160                 cp = malloc(sizeof(struct cputype));
161                 bzero(cp, sizeof(*cp));
162                 cp->cpu_name = $2;
163                 cp->cpu_next = cputype;
164                 cputype = cp;
165               } |
166         OPTIONS Opt_list
167                 |
168         MAKEOPTIONS Mkopt_list
169                 |
170         IDENT ID
171               = { ident = $2; } |
172         System_spec
173                 |
174         MAXUSERS NUMBER
175               = { maxusers = $2; };
176
177 System_spec:
178         CONFIG System_id System_parameter_list
179           = { errx(1,"line %d: root/dump/swap specifications obsolete", yyline);}
180           |
181         CONFIG System_id
182           ;
183
184 System_id:
185         Save_id
186               = {
187                 struct opt *op;
188
189                 op = malloc(sizeof(struct opt));
190                 bzero(op, sizeof(*op));
191                 op->op_name = strdup("KERNEL");
192                 op->op_ownfile = 0;
193                 op->op_next = mkopt;
194                 op->op_value = $1;
195                 op->op_line = yyline + 1;
196                 mkopt = op;
197               };
198
199 System_parameter_list:
200           System_parameter_list ID
201         | ID
202         ;
203
204 device_name:
205           Save_id
206                 = { $$ = $1; }
207         | Save_id NUMBER
208                 = {
209                         char buf[80];
210
211                         snprintf(buf, sizeof(buf), "%s%d", $1, $2);
212                         $$ = strdup(buf);
213                         free($1);
214                 }
215         | Save_id NUMBER ID
216                 = {
217                         char buf[80];
218
219                         snprintf(buf, sizeof(buf), "%s%d%s", $1, $2, $3);
220                         $$ = strdup(buf);
221                         free($1);
222                 }
223         | Save_id NUMBER ID NUMBER
224                 = {
225                         char buf[80];
226
227                         snprintf(buf, sizeof(buf), "%s%d%s%d",
228                              $1, $2, $3, $4);
229                         $$ = strdup(buf);
230                         free($1);
231                 }
232         | Save_id NUMBER ID NUMBER ID
233                 = {
234                         char buf[80];
235
236                         snprintf(buf, sizeof(buf), "%s%d%s%d%s",
237                              $1, $2, $3, $4, $5);
238                         $$ = strdup(buf);
239                         free($1);
240                 }
241         ;
242
243 Opt_list:
244         Opt_list COMMA Option
245                 |
246         Option
247                 ;
248
249 Option:
250         Save_id
251               = {
252                 struct opt *op;
253                 
254                 op = malloc(sizeof(struct opt));
255                 bzero(op, sizeof(*op));
256                 op->op_name = $1;
257                 op->op_next = opt;
258                 op->op_value = 0;
259                 /*
260                  * op->op_line is 1-based; yyline is 0-based but is now 1
261                  * larger than when `Save_id' was lexed.
262                  */
263                 op->op_line = yyline;
264                 opt = op;
265                 if (strchr(op->op_name, '=') != NULL)
266                         errx(1, "line %d: The `=' in options should not be quoted", yyline);
267               } |
268         Save_id EQUALS Opt_value
269               = {
270                 struct opt *op;
271
272                 op = malloc(sizeof(struct opt));
273                 bzero(op, sizeof(*op));
274                 op->op_name = $1;
275                 op->op_next = opt;
276                 op->op_value = $3;
277                 op->op_line = yyline + 1;
278                 opt = op;
279               } ;
280
281 Opt_value:
282         ID
283                 = { $$ = $1; } |
284         NUMBER
285                 = {
286                         char buf[80];
287
288                         snprintf(buf, sizeof(buf), "%d", $1);
289                         $$ = strdup(buf);
290                 } ;
291
292 Save_id:
293         ID
294               = { $$ = $1; }
295         ;
296
297 Mkopt_list:
298         Mkopt_list COMMA Mkoption
299                 |
300         Mkoption
301                 ;
302
303 Mkoption:
304         Save_id EQUALS Opt_value
305               = {
306                 struct opt *op;
307
308                 op = malloc(sizeof(struct opt));
309                 bzero(op, sizeof(*op));
310                 op->op_name = $1;
311                 op->op_ownfile = 0;     /* for now */
312                 op->op_next = mkopt;
313                 op->op_value = $3;
314                 op->op_line = yyline + 1;
315                 mkopt = op;
316               } ;
317
318 Dev:
319         ID
320               = { $$ = $1; }
321         ;
322
323 Device_spec:
324         DEVICE Dev_spec
325               = { cur.d_type = DEVICE; } |
326         PSEUDO_DEVICE Init_dev Dev
327               = {
328                 cur.d_name = $3;
329                 cur.d_type = PSEUDO_DEVICE;
330                 } |
331         PSEUDO_DEVICE Init_dev Dev NUMBER
332               = {
333                 cur.d_name = $3;
334                 cur.d_type = PSEUDO_DEVICE;
335                 cur.d_count = $4;
336                 } ;
337
338 Dev_spec:
339         Init_dev Dev
340               = {
341                 cur.d_name = $2;
342                 cur.d_unit = UNKNOWN;
343                 } |
344         Init_dev Dev NUMBER Dev_info
345               = {
346                 cur.d_name = $2;
347                 cur.d_unit = $3;
348                 };
349
350 Init_dev:
351         /* lambda */
352               = { init_dev(&cur); };
353
354 Dev_info:
355         Con_info Info_list
356                 |
357         /* lambda */
358                 ;
359
360 Con_info:
361         AT Dev NUMBER
362               = {
363                 connect($2, $3);
364                 cur.d_conn = $2;
365                 cur.d_connunit = $3;
366                 } |
367         AT NEXUS NUMBER
368               = {
369                 cur.d_conn = "nexus";
370                 cur.d_connunit = 0;
371                 };
372     
373 Info_list:
374         Info_list Info
375                 |
376         /* lambda */
377                 ;
378
379 Info:
380         BUS NUMBER      /* device scbus1 at ahc0 bus 1 - twin channel */
381               = { cur.d_bus = $2; } |
382         TARGET NUMBER
383               = { cur.d_target = $2; } |
384         UNIT NUMBER
385               = { cur.d_lun = $2; } |
386         DRIVE NUMBER
387               = { cur.d_drive = $2; } |
388         IRQ NUMBER
389               = { cur.d_irq = $2; } |
390         DRQ NUMBER
391               = { cur.d_drq = $2; } |
392         IOMEM NUMBER
393               = { cur.d_maddr = $2; } |
394         IOSIZ NUMBER
395               = { cur.d_msize = $2; } |
396         PORT device_name
397               = { cur.d_port = $2; } |
398         PORT NUMBER
399               = { cur.d_portn = $2; } |
400         FLAGS NUMBER
401               = { cur.d_flags = $2; } |
402         DISABLE 
403               = { cur.d_disabled = 1; }
404
405 %%
406
407 static void
408 yyerror(const char *s)
409 {
410
411         errx(1, "line %d: %s", yyline + 1, s);
412 }
413
414 /*
415  * add a device to the list of devices
416  */
417 static void
418 newdev(struct device *dp)
419 {
420         struct device *np, *xp;
421
422         if (dp->d_unit >= 0) {
423                 for (xp = dtab; xp != NULL; xp = xp->d_next) {
424                         if ((xp->d_unit == dp->d_unit) &&
425                             !strcmp(xp->d_name, dp->d_name)) {
426                                 errx(1, "line %d: already seen device %s%d",
427                                     yyline, xp->d_name, xp->d_unit);
428                         }
429                 }
430         }
431         np = malloc(sizeof(*np));
432         bzero(np, sizeof(*np));
433         *np = *dp;
434         np->d_next = NULL;
435         if (curp == NULL)
436                 dtab = np;
437         else
438                 curp->d_next = np;
439         curp = np;
440 }
441
442
443 /*
444  * find the pointer to connect to the given device and number.
445  * returns 0 if no such device and prints an error message
446  */
447 static int
448 connect(char *dev, int num)
449 {
450         struct device *dp;
451
452         if (num == QUES) {
453                 for (dp = dtab; dp != NULL; dp = dp->d_next)
454                         if (!strcmp(dp->d_name, dev))
455                                 break;
456                 if (dp == NULL) {
457                         snprintf(errbuf, sizeof(errbuf),
458                             "no %s's to wildcard", dev);
459                         yyerror(errbuf);
460                         return(0);
461                 }
462                 return(1);
463         }
464         for (dp = dtab; dp != NULL; dp = dp->d_next) {
465                 if ((num != dp->d_unit) || strcmp(dev, dp->d_name))
466                         continue;
467                 if (dp->d_type != DEVICE) {
468                         snprintf(errbuf, sizeof(errbuf), 
469                             "%s connected to non-device", dev);
470                         yyerror(errbuf);
471                         return(0);
472                 }
473                 return(1);
474         }
475         snprintf(errbuf, sizeof(errbuf), "%s %d not defined", dev, num);
476         yyerror(errbuf);
477         return(0);
478 }
479
480 void
481 init_dev(struct device *dp)
482 {
483
484         dp->d_name = "OHNO!!!";
485         dp->d_type = DEVICE;
486         dp->d_conn = 0;
487         dp->d_disabled = 0;
488         dp->d_flags = 0;
489         dp->d_bus = dp->d_lun = dp->d_target = dp->d_drive = dp->d_unit =
490             dp->d_count = UNKNOWN;
491         dp->d_port = NULL;
492         dp->d_portn = -1;
493         dp->d_irq = -1;
494         dp->d_drq = -1;
495         dp->d_maddr = 0;
496         dp->d_msize = 0;
497 }