1 /* $NetBSD: platid_gen.c,v 1.11 2014/03/26 17:54:46 christos Exp $ */
2
3 /*-
4 * Copyright (c) 1999
5 * Shin Takemura and PocketBSD Project. All rights reserved.
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 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by the PocketBSD project
18 * and its contributors.
19 * 4. Neither the name of the project nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 *
35 */
36
37 #include <sys/cdefs.h>
38 __KERNEL_RCSID(0, "$NetBSD: platid_gen.c,v 1.11 2014/03/26 17:54:46 christos Exp $");
39
40 #include <stdio.h>
41 #include <stdlib.h>
42 #include <strings.h>
43 #include <unistd.h>
44
45 #include "platid_gen.h"
46
47 /*
48 * constants
49 */
50 #define SEARCH_IGNORECASE (1<<0)
51
52 #define NMODES 2
53 #define MAXNEST 4
54 #define MAXLEN 1024
55
56 enum { FORM_GENHDR, FORM_MASK_H, FORM_MASK_C, FORM_NAME_C, FORM_PARSE_ONLY };
57
58 /*
59 * data type definitions
60 */
61 struct genctx_t {
62 int num;
63 const char *alt;
64 const char *node_name[2];
65 char sym[MAXLEN];
66 char name[MAXLEN];
67 } genctx[NMODES][MAXNEST];
68
69 /*
70 * function prototypes
71 */
72 void gen_list(node_t *);
73 void gen_output(void);
74 void gen_header(void);
75 void gen_mask_h(void);
76 void gen_mask_c(void);
77 void gen_name_c(void);
78 void gen_comment(FILE *);
79 void enter(void);
80 void leave(void);
81
82 /*
83 * global data
84 */
85 node_t* def_tree;
86 int nest;
87 int mode;
88 FILE *fp_out;
89 int form;
90 int count;
91
92 #define MODE_INVALID -1
93 #define MODE_CPU 0
94 #define MODE_MACHINE 1
95 char* mode_names[] = {
96 "CPU", "MACHINE", NULL
97 };
98 #define PREFIX "PLATID"
99 char* prefix_names[] = {
100 "CPU", "MACH",
101 };
102 char* shift_names[NMODES][MAXNEST] = {
103 {
104 "PLATID_CPU_ARCH_SHIFT",
105 "PLATID_CPU_SERIES_SHIFT",
106 "PLATID_CPU_MODEL_SHIFT",
107 "PLATID_CPU_SUBMODEL_SHIFT",
108 },
109 {
110 "PLATID_VENDOR_SHIFT",
111 "PLATID_SERIES_SHIFT",
112 "PLATID_MODEL_SHIFT",
113 "PLATID_SUBMODEL_SHIFT",
114 },
115 };
116
117 /*
118 * program entry
119 */
120 int
main(int argc,char * argv[])121 main(int argc, char *argv[])
122 {
123 int i;
124
125 form = FORM_GENHDR;
126 fp_out = stdout;
127 count = 0;
128
129 for (i = 1; i < argc; i++) {
130 if (strcmp(argv[i], "-header") == 0) {
131 form = FORM_GENHDR;
132 } else if (strcmp(argv[i], "-mask_h") == 0) {
133 form = FORM_MASK_H;
134 } else if (strcmp(argv[i], "-mask_c") == 0) {
135 form = FORM_MASK_C;
136 } else if (strcmp(argv[i], "-name_c") == 0) {
137 form = FORM_NAME_C;
138 } else if (strcmp(argv[i], "-parse_only") == 0) {
139 form = FORM_PARSE_ONLY;
140 } else {
141 usage:
142 fprintf(stderr, "usage platid_gen <option>\n");
143 fprintf(stderr, " option: -header\n");
144 fprintf(stderr, " -mask_h\n");
145 fprintf(stderr, " -mask_c\n");
146 fprintf(stderr, " -name_c\n");
147 fprintf(stderr, " -parse_only\n");
148 exit(1);
149 }
150 }
151
152 if (read_def()) {
153 exit(1);
154 }
155
156 if (form == FORM_PARSE_ONLY) {
157 dump_node("", def_tree);
158 exit (0);
159 }
160
161 gen_comment(fp_out);
162 switch (form) {
163 case FORM_GENHDR:
164 break;
165 case FORM_MASK_H:
166 break;
167 case FORM_MASK_C:
168 fprintf(fp_out, "#include <machine/platid.h>\n");
169 fprintf(fp_out, "#include <machine/platid_mask.h>\n");
170 break;
171 case FORM_NAME_C:
172 fprintf(fp_out, "#include <machine/platid.h>\n");
173 fprintf(fp_out, "#include <machine/platid_mask.h>\n");
174 fprintf(fp_out,"struct platid_name platid_name_table[] = {\n");
175 break;
176 }
177
178 nest = -1;
179 enter(); /* XXX */
180 mode = MODE_INVALID;
181 genctx[MODE_CPU][nest].alt = NULL;
182 genctx[MODE_MACHINE][nest].alt = NULL;
183 gen_list((node_t*)def_tree->ptr1);
184
185 switch (form) {
186 case FORM_GENHDR:
187 case FORM_MASK_H:
188 case FORM_MASK_C:
189 break;
190 case FORM_NAME_C:
191 fprintf(fp_out, "};\n");
192 fprintf(fp_out, "int platid_name_table_size = sizeof(platid_name_table)/sizeof(*platid_name_table);\n");
193 break;
194 }
195 fclose(fp_out);
196
197 exit(0);
198 }
199
200 int
table_getnum(char ** table,const char * s,int def,int opt)201 table_getnum(char **table, const char *s, int def, int opt)
202 {
203 int num;
204
205 num = 0;
206 while (table[num]) {
207 int diff;
208 if (opt & SEARCH_IGNORECASE) {
209 diff = strcmp(table[num], s);
210 } else {
211 diff = strcasecmp(table[num], s);
212 }
213 if (diff == 0) {
214 return (num);
215 }
216 num++;
217 }
218 return def;
219 }
220
221 #define GET_MODE(s) \
222 table_getnum(mode_names, (s), MODE_INVALID, SEARCH_IGNORECASE)
223 #define GET_ALT(s) \
224 table_getnum(mode_names, (s), MODE_INVALID, SEARCH_IGNORECASE)
225
226 void
enter(void)227 enter(void)
228 {
229 nest++;
230 if (MAXNEST <= nest) {
231 fprintf(stderr, "too much nest\n");
232 exit(1);
233 }
234 genctx[mode][nest].num = 0;
235 genctx[mode][nest].alt = NULL;
236 genctx[mode][nest].node_name[0] = NULL;
237 genctx[mode][nest].node_name[1] = NULL;
238 if (0 < nest) {
239 genctx[mode][nest].alt = genctx[mode][nest - 1].alt;
240 }
241 }
242
243 void
leave(void)244 leave(void)
245 {
246 nest--;
247 if (nest < 0) {
248 fprintf(stderr, "internal error (nest=%d)\n", nest);
249 exit(1);
250 }
251 }
252
253 void
gen_comment(FILE * fp)254 gen_comment(FILE *fp)
255 {
256 fprintf(fp, "/*\n");
257 fprintf(fp, " * Do not edit.\n");
258 fprintf(fp, " * This file is automatically generated by platid.awk.\n");
259 fprintf(fp, " */\n");
260 }
261
262 int
gen_name(char * buf,struct genctx_t ctx[],int nest,int name,char * punct,int ignr)263 gen_name(char *buf, struct genctx_t ctx[], int nest, int name, char *punct,
264 int ignr)
265 {
266 int i;
267 buf[0] = '\0';
268 for (i = 0; i <= nest; i++) {
269 if (!(ignr <= i && nest != i)) {
270 if (i != 0) {
271 strcat(buf, punct);
272 }
273 strcat(buf, ctx[i].node_name[name]);
274 }
275 }
276 }
277
278 void
gen_list(node_t * np)279 gen_list(node_t* np)
280 {
281 int i, t;
282
283 for ( ; np; np = np->link) {
284 switch (np->type) {
285 case N_LABEL:
286 if ((mode = GET_MODE(np->ptr1)) == MODE_INVALID) {
287 fprintf(stderr, "invalid mode '%s'\n",
288 np->ptr1);
289 exit(1);
290 }
291 break;
292 case N_MODIFIER:
293 t = GET_ALT(np->ptr1);
294 if (t == MODE_INVALID) {
295 fprintf(stderr, "unknown alternater '%s'\n",
296 np->ptr1);
297 exit(1);
298 }
299 if (t == mode) {
300 fprintf(stderr,
301 "invalid alternater '%s' (ignored)\n",
302 np->ptr1);
303 exit(1);
304 }
305 genctx[mode][nest].alt = np->ptr2;
306 break;
307 case N_ENTRY:
308 if (np->ptr2 == NULL) {
309 char buf[MAXLEN];
310 snprintf(buf, sizeof(buf), "%s%s",
311 nest == 0 ? "" : " ",
312 np->ptr1);
313 np->ptr2 = strdup(buf);
314 if (nest == 3)
315 np->val = 1;
316 }
317 touppers((char*)np->ptr1);
318
319 genctx[mode][nest].num++;
320 genctx[mode][nest].node_name[0] = np->ptr1;
321 genctx[mode][nest].node_name[1] = np->ptr2;
322 gen_name(genctx[mode][nest].sym, genctx[mode],
323 nest, 0, "_", nest == 3 ? 2 : nest);
324 gen_name(genctx[mode][nest].name, genctx[mode],
325 nest, 1, "", nest - np->val);
326 gen_output();
327 break;
328 case N_LIST:
329 enter();
330 gen_list((node_t*)np->ptr1);
331 leave();
332 break;
333 case N_DIRECTIVE:
334 fprintf(fp_out, "%s", np->ptr1);
335 break;
336 default:
337 fprintf(stderr, "internal error (type=%d)\n", np->type);
338 exit(1);
339 break;
340 }
341 }
342 }
343
344 void
gen_output(void)345 gen_output(void)
346 {
347 switch (form) {
348 case FORM_GENHDR:
349 gen_header();
350 break;
351 case FORM_MASK_H:
352 gen_mask_h();
353 break;
354 case FORM_MASK_C:
355 gen_mask_c();
356 break;
357 case FORM_NAME_C:
358 gen_name_c();
359 break;
360 }
361 }
362
363 /*
364 * platid_generated.h
365 *
366 * #define PLATID_CPU_XXX_NUM 1
367 * #define PLATID_CPU_XXX \
368 * ((PLATID_CPU_XXX_NUM << PLATID_CPU_ARCH_SHIFT))
369 * #define PLATID_CPU_XXX_YYY \
370 * ((PLATID_CPU_XXX_YYY_NUM << PLATID_CPU_SERIES_SHIFT)| \
371 * PLATID_CPU_XXX)
372 *
373 * #ifndef SPEC_PLATFORM
374 * #define SPEC_MACH_XXX
375 * #endif
376 * #define PLATID_MACH_XXX_NUM 1
377 * #define PLATID_MACH_XXX \
378 * ((PLATID_MACH_XXX_NUM << PLATID_MACH_ARCH_SHIFT))
379 * #define PLATID_MACH_XXX_YYY \
380 * ((PLATID_MACH_XXX_YYY_NUM << PLATID_MACH_SERIES_SHIFT)| \
381 * PLATID_MACH_XXX)
382 */
383 void
gen_header(void)384 gen_header(void)
385 {
386 char *prefix = prefix_names[mode];
387 char *name = genctx[mode][nest].sym;
388
389 if (mode == MODE_MACHINE) {
390 fprintf(fp_out, "#ifndef SPEC_PLATFORM\n");
391 fprintf(fp_out, "#define %s_%s_%s\n", "SPEC", prefix, name);
392 fprintf(fp_out, "#endif /* !SPEC_PLATFORM */\n");
393 }
394 fprintf(fp_out, "#define %s_%s_%s_NUM\t%d\n", PREFIX, prefix, name,
395 genctx[mode][nest].num);
396 fprintf(fp_out, "#define %s_%s_%s\t\\\n", PREFIX, prefix, name);
397 fprintf(fp_out, " ((%s_%s_%s_NUM << %s)", PREFIX, prefix, name,
398 shift_names[mode][nest]);
399 if (0 < nest) {
400 fprintf(fp_out, "| \\\n %s_%s_%s",
401 PREFIX, prefix, genctx[mode][nest - 1].sym);
402 }
403 fprintf(fp_out, ")\n");
404 }
405
406 /*
407 * platid_mask.h:
408 *
409 * extern platid_t platid_mask_CPU_MIPS;
410 * #ifdef PLATID_DEFINE_MASK_NICKNAME
411 * # define GENERIC_MIPS ((int)&platid_mask_CPU_MIPS)
412 * #endif
413 */
414 void
gen_mask_h(void)415 gen_mask_h(void)
416 {
417 char *name = genctx[mode][nest].sym;
418
419 fprintf(fp_out, "extern platid_t platid_mask_%s_%s;\n",
420 prefix_names[mode], name);
421 fprintf(fp_out, "#ifdef PLATID_DEFINE_MASK_NICKNAME\n");
422 fprintf(fp_out, "# define %s%s ((int)&platid_mask_%s_%s)\n",
423 (mode == MODE_CPU)?"GENERIC_":"",
424 name, prefix_names[mode], name);
425 fprintf(fp_out, "#endif\n");
426 }
427
428 /*
429 * platid_mask.c:
430 *
431 * platid_t platid_mask_CPU_MIPS = {{
432 * PLATID_CPU_MIPS,
433 * PLATID_WILD
434 * }};
435 */
436 void
gen_mask_c(void)437 gen_mask_c(void)
438 {
439 char *name = genctx[mode][nest].sym;
440
441 fprintf(fp_out, "platid_t platid_mask_%s_%s = {{\n",
442 prefix_names[mode], name);
443 switch (mode) {
444 case MODE_CPU:
445 fprintf(fp_out, "\t%s_CPU_%s,\n", PREFIX, name);
446 if (genctx[mode][nest].alt == NULL)
447 fprintf(fp_out, "\t%s_WILD\n", PREFIX);
448 else
449 fprintf(fp_out, "\t%s_MACH_%s,\n", PREFIX,
450 genctx[mode][nest].alt);
451 break;
452 case MODE_MACHINE:
453 if (genctx[mode][nest].alt == NULL)
454 fprintf(fp_out, "\t%s_WILD,\n", PREFIX);
455 else
456 fprintf(fp_out, "\t%s_CPU_%s,\n", PREFIX,
457 genctx[mode][nest].alt);
458 fprintf(fp_out, "\t%s_MACH_%s\n", PREFIX, name);
459 break;
460 }
461 fprintf(fp_out, "}};\n");
462 }
463
464 /*
465 * platid_name.c:
466 */
467 void
gen_name_c(void)468 gen_name_c(void)
469 {
470 fprintf(fp_out, "\t{ &platid_mask_%s_%s,\n",
471 prefix_names[mode], genctx[mode][nest].sym);
472 fprintf(fp_out, "\t TEXT(\"%s\") },\n", genctx[mode][nest].name);
473 count++;
474 }
475