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