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