Home | History | Annotate | Line # | Download | only in platid_gen
      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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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