Initial import of binutils 2.22 on the new vendor branch
[dragonfly.git] / lib / libsys / genhooks / parse.c
1 /*
2  * Copyright (c) 2005 The DragonFly Project.  All rights reserved.
3  * 
4  * This code is derived from software contributed to The DragonFly Project
5  * by Matthew Dillon <dillon@backplane.com>
6  * 
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in
15  *    the documentation and/or other materials provided with the
16  *    distribution.
17  * 3. Neither the name of The DragonFly Project nor the names of its
18  *    contributors may be used to endorse or promote products derived
19  *    from this software without specific, prior written permission.
20  * 
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
25  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26  * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
27  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
31  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32  * SUCH DAMAGE.
33  * 
34  * $DragonFly: src/lib/libsys/genhooks/parse.c,v 1.1 2005/05/08 18:14:56 dillon Exp $
35  */
36 /*
37  * PARSE.C
38  *
39  * Parse the system call configuration file.
40  */
41
42 #include "defs.h"
43
44 struct sys_info **sys_array;
45 int sys_count;
46 char *sys_sectname;
47
48 static int parse_base(lex_token *tok);
49 static int parse_add(lex_token *tok);
50 static int parse_int(lex_token *tok, int *ret_p);
51 static int parse_type(lex_token *tok, sys_type **type_pp);
52
53 void
54 parse_file(const char *path)
55 {
56     lex_token tok;
57     int t;
58
59     lex_open(path, &tok);
60     t = lex_gettoken(&tok);
61     while (t != TOK_EOF) {
62         switch(t) {
63         case TOK_BASE:
64             t = parse_base(&tok);
65             break;
66         case TOK_ADD:
67             t = parse_add(&tok);
68             break;
69         default:
70             lex_error(&tok, "Expected command directive");
71             exit(1);
72         }
73     }
74     lex_close(&tok);
75 }
76
77 int
78 parse_base(lex_token *tok)
79 {
80     int t;
81
82     t = lex_gettoken(tok);
83     if (t & TOK_SYMBOL) {
84         sys_sectname = lex_string(tok);
85         t = lex_gettoken(tok);
86     } else {
87         lex_error(tok, "Expected section extension symbol");
88         exit(1);
89     }
90     t = lex_skip_token(tok, TOK_SEMI);
91     return(t);
92 }
93
94 static int
95 parse_add(lex_token *tok)
96 {
97     sys_info *info;
98     sys_type *type;
99     int sysno;
100     int t;
101
102     lex_gettoken(tok);
103     info = zalloc(sizeof(sys_info));
104
105     parse_int(tok, &info->sysno);
106
107     t = lex_skip_token(tok, TOK_OBRACE);
108
109     while (t != TOK_CBRACE) {
110         switch(t) {
111         case TOK_FUNCTION:
112             t = lex_gettoken(tok);
113             parse_type(tok, &info->func_ret);
114             t = lex_skip_token(tok, TOK_OPAREN);
115             while (t != TOK_CPAREN) {
116                 t = parse_type(tok, &type);
117                 if (t != TOK_COMMA)
118                     break;
119                 t = lex_gettoken(tok);
120                 info->func_args = realloc(info->func_args, 
121                                     sizeof(sys_type) * (info->nargs + 1));
122                 info->func_args[info->nargs++] = type;
123             }
124
125             /*
126              * cleanup void
127              */
128             if (info->nargs == 1 && 
129                 strcmp(info->func_args[0]->type_name, "void") == 0
130             ) {
131                 info->nargs = 0;
132                 /* XXX free/cleanup */
133             }
134
135             t = lex_skip_token(tok, TOK_CPAREN);
136             t = lex_skip_token(tok, TOK_SEMI);
137             break;
138         case TOK_IMPLEMENTATION:
139             t = lex_gettoken(tok);
140             switch(t) {
141             case TOK_DIRECT:
142                 t = lex_gettoken(tok);
143                 break;
144             default:
145                 lex_error(tok, "Expected 'direct'");
146                 exit(1);
147             }
148             t = lex_skip_token(tok, TOK_SEMI);
149             break;
150         default:
151             lex_error(tok, "Expected command directive");
152             exit(1);
153         }
154     }
155     t = lex_skip_token(tok, TOK_CBRACE);
156     if (sys_count <= info->sysno) {
157         sys_array = realloc(sys_array, 
158                                 sizeof(sys_info *) * (info->sysno + 1));
159         while (sys_count <= info->sysno)
160             sys_array[sys_count++] = NULL;
161     }
162     sys_array[info->sysno] = info;
163     return(t);
164 }
165
166 static
167 int
168 parse_int(lex_token *tok, int *ret_p)
169 {
170     int t = tok->type;
171
172     if (t != TOK_INTEGER) {
173         lex_error(tok, "Expected integer");
174         exit(1);
175     }
176     *ret_p = tok->value;
177     return(lex_gettoken(tok));
178 }
179
180 static
181 int
182 parse_type(lex_token *tok, sys_type **type_pp)
183 {
184     int t = tok->type;
185     sys_type *type;
186
187     type = zalloc(sizeof(sys_type));
188
189     if ((t & TOK_SYMBOL) == 0) {
190         lex_error(tok, "Expected type identifier");
191         exit(1);
192     }
193     type->type_name = lex_string(tok);
194     t = lex_gettoken(tok);
195     if (t != TOK_COMMA && t != TOK_CPAREN) {
196         if ((t & TOK_SYMBOL) == 0) {
197             lex_error(tok, "Expected name identifier");
198             exit(1);
199         }
200         type->var_name = lex_string(tok);
201         t = lex_gettoken(tok);
202     } else {
203         type->var_name = NULL;
204     }
205     *type_pp = type;
206     return(t);
207 }
208