1 /* $NetBSD: platid_gen.c,v 1.9 2009/03/18 10:22:28 cegger 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.9 2009/03/18 10:22:28 cegger 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 gen_name(char *buf, struct genctx_t ctx[], int nest, int name, char *punct, 263 int ignr) 264 { 265 int i; 266 buf[0] = '\0'; 267 for (i = 0; i <= nest; i++) { 268 if (!(ignr <= i && nest != i)) { 269 if (i != 0) { 270 strcat(buf, punct); 271 } 272 strcat(buf, ctx[i].node_name[name]); 273 } 274 } 275 } 276 277 void 278 gen_list(node_t* np) 279 { 280 int i, t; 281 282 for ( ; np; np = np->link) { 283 switch (np->type) { 284 case N_LABEL: 285 if ((mode = GET_MODE(np->ptr1)) == MODE_INVALID) { 286 fprintf(stderr, "invalid mode '%s'\n", 287 np->ptr1); 288 exit(1); 289 } 290 break; 291 case N_MODIFIER: 292 t = GET_ALT(np->ptr1); 293 if (t == MODE_INVALID) { 294 fprintf(stderr, "unknown alternater '%s'\n", 295 np->ptr1); 296 exit(1); 297 } 298 if (t == mode) { 299 fprintf(stderr, 300 "invalid alternater '%s' (ignored)\n", 301 np->ptr1); 302 exit(1); 303 } 304 genctx[mode][nest].alt = np->ptr2; 305 break; 306 case N_ENTRY: 307 if (np->ptr2 == NULL) { 308 char buf[MAXLEN]; 309 sprintf(buf, "%s%s", 310 nest == 0 ? "" : " ", 311 np->ptr1); 312 np->ptr2 = strdup(buf); 313 if (nest == 3) 314 np->val = 1; 315 } 316 touppers((char*)np->ptr1); 317 318 genctx[mode][nest].num++; 319 genctx[mode][nest].node_name[0] = np->ptr1; 320 genctx[mode][nest].node_name[1] = np->ptr2; 321 gen_name(genctx[mode][nest].sym, genctx[mode], 322 nest, 0, "_", nest == 3 ? 2 : nest); 323 gen_name(genctx[mode][nest].name, genctx[mode], 324 nest, 1, "", nest - np->val); 325 gen_output(); 326 break; 327 case N_LIST: 328 enter(); 329 gen_list((node_t*)np->ptr1); 330 leave(); 331 break; 332 case N_DIRECTIVE: 333 fprintf(fp_out, "%s", np->ptr1); 334 break; 335 default: 336 fprintf(stderr, "internal error (type=%d)\n", np->type); 337 exit(1); 338 break; 339 } 340 } 341 } 342 343 void 344 gen_output(void) 345 { 346 switch (form) { 347 case FORM_GENHDR: 348 gen_header(); 349 break; 350 case FORM_MASK_H: 351 gen_mask_h(); 352 break; 353 case FORM_MASK_C: 354 gen_mask_c(); 355 break; 356 case FORM_NAME_C: 357 gen_name_c(); 358 break; 359 } 360 } 361 362 /* 363 * platid_generated.h 364 * 365 * #define PLATID_CPU_XXX_NUM 1 366 * #define PLATID_CPU_XXX \ 367 * ((PLATID_CPU_XXX_NUM << PLATID_CPU_ARCH_SHIFT)) 368 * #define PLATID_CPU_XXX_YYY \ 369 * ((PLATID_CPU_XXX_YYY_NUM << PLATID_CPU_SERIES_SHIFT)| \ 370 * PLATID_CPU_XXX) 371 * 372 * #ifndef SPEC_PLATFORM 373 * #define SPEC_MACH_XXX 374 * #endif 375 * #define PLATID_MACH_XXX_NUM 1 376 * #define PLATID_MACH_XXX \ 377 * ((PLATID_MACH_XXX_NUM << PLATID_MACH_ARCH_SHIFT)) 378 * #define PLATID_MACH_XXX_YYY \ 379 * ((PLATID_MACH_XXX_YYY_NUM << PLATID_MACH_SERIES_SHIFT)| \ 380 * PLATID_MACH_XXX) 381 */ 382 void 383 gen_header(void) 384 { 385 char *prefix = prefix_names[mode]; 386 char *name = genctx[mode][nest].sym; 387 388 if (mode == MODE_MACHINE) { 389 fprintf(fp_out, "#ifndef SPEC_PLATFORM\n"); 390 fprintf(fp_out, "#define %s_%s_%s\n", "SPEC", prefix, name); 391 fprintf(fp_out, "#endif /* !SPEC_PLATFORM */\n"); 392 } 393 fprintf(fp_out, "#define %s_%s_%s_NUM\t%d\n", PREFIX, prefix, name, 394 genctx[mode][nest].num); 395 fprintf(fp_out, "#define %s_%s_%s\t\\\n", PREFIX, prefix, name); 396 fprintf(fp_out, " ((%s_%s_%s_NUM << %s)", PREFIX, prefix, name, 397 shift_names[mode][nest]); 398 if (0 < nest) { 399 fprintf(fp_out, "| \\\n %s_%s_%s", 400 PREFIX, prefix, genctx[mode][nest - 1].sym); 401 } 402 fprintf(fp_out, ")\n"); 403 } 404 405 /* 406 * platid_mask.h: 407 * 408 * extern platid_t platid_mask_CPU_MIPS; 409 * #ifdef PLATID_DEFINE_MASK_NICKNAME 410 * # define GENERIC_MIPS ((int)&platid_mask_CPU_MIPS) 411 * #endif 412 */ 413 void 414 gen_mask_h(void) 415 { 416 char *name = genctx[mode][nest].sym; 417 418 fprintf(fp_out, "extern platid_t platid_mask_%s_%s;\n", 419 prefix_names[mode], name); 420 fprintf(fp_out, "#ifdef PLATID_DEFINE_MASK_NICKNAME\n"); 421 fprintf(fp_out, "# define %s%s ((int)&platid_mask_%s_%s)\n", 422 (mode == MODE_CPU)?"GENERIC_":"", 423 name, prefix_names[mode], name); 424 fprintf(fp_out, "#endif\n"); 425 } 426 427 /* 428 * platid_mask.c: 429 * 430 * platid_t platid_mask_CPU_MIPS = {{ 431 * PLATID_CPU_MIPS, 432 * PLATID_WILD 433 * }}; 434 */ 435 void 436 gen_mask_c(void) 437 { 438 char *name = genctx[mode][nest].sym; 439 440 fprintf(fp_out, "platid_t platid_mask_%s_%s = {{\n", 441 prefix_names[mode], name); 442 switch (mode) { 443 case MODE_CPU: 444 fprintf(fp_out, "\t%s_CPU_%s,\n", PREFIX, name); 445 if (genctx[mode][nest].alt == NULL) 446 fprintf(fp_out, "\t%s_WILD\n", PREFIX); 447 else 448 fprintf(fp_out, "\t%s_MACH_%s,\n", PREFIX, 449 genctx[mode][nest].alt); 450 break; 451 case MODE_MACHINE: 452 if (genctx[mode][nest].alt == NULL) 453 fprintf(fp_out, "\t%s_WILD,\n", PREFIX); 454 else 455 fprintf(fp_out, "\t%s_CPU_%s,\n", PREFIX, 456 genctx[mode][nest].alt); 457 fprintf(fp_out, "\t%s_MACH_%s\n", PREFIX, name); 458 break; 459 } 460 fprintf(fp_out, "}};\n"); 461 } 462 463 /* 464 * platid_name.c: 465 */ 466 void 467 gen_name_c(void) 468 { 469 fprintf(fp_out, "\t{ &platid_mask_%s_%s,\n", 470 prefix_names[mode], genctx[mode][nest].sym); 471 fprintf(fp_out, "\t TEXT(\"%s\") },\n", genctx[mode][nest].name); 472 count++; 473 } 474