1 /* $NetBSD: platid_gen.c,v 1.4 2001/09/27 16:31:24 uch 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 #include <stdio.h> 37 #include <strings.h> 38 #include <unistd.h> 39 40 #include "platid_gen.h" 41 42 /* 43 * constants 44 */ 45 #define SEARCH_IGNORECASE (1<<0) 46 47 #define NMODES 2 48 #define MAXNEST 4 49 #define MAXLEN 1024 50 51 enum { FORM_GENHDR, FORM_MASK_H, FORM_MASK_C, FORM_NAME_C, FORM_PARSE_ONLY }; 52 53 /* 54 * data type definitions 55 */ 56 struct genctx_t { 57 int num; 58 const char *alt; 59 const char *node_name[2]; 60 char sym[MAXLEN]; 61 char name[MAXLEN]; 62 } genctx[NMODES][MAXNEST]; 63 64 /* 65 * function prototypes 66 */ 67 void gen_list(node_t *); 68 void gen_output(void); 69 void gen_header(void); 70 void gen_mask_h(void); 71 void gen_mask_c(void); 72 void gen_name_c(void); 73 void gen_comment(FILE *); 74 void enter(void); 75 void leave(void); 76 77 /* 78 * global data 79 */ 80 node_t* def_tree; 81 int nest; 82 int mode; 83 FILE *fp_out; 84 int form; 85 int count; 86 87 #define MODE_INVALID -1 88 #define MODE_CPU 0 89 #define MODE_MACHINE 1 90 char* mode_names[] = { 91 "CPU", "MACHINE", NULL 92 }; 93 #define PREFIX "PLATID" 94 char* prefix_names[] = { 95 "CPU", "MACH", 96 }; 97 char* shift_names[NMODES][MAXNEST] = { 98 { 99 "PLATID_CPU_ARCH_SHIFT", 100 "PLATID_CPU_SERIES_SHIFT", 101 "PLATID_CPU_MODEL_SHIFT", 102 "PLATID_CPU_SUBMODEL_SHIFT", 103 }, 104 { 105 "PLATID_VENDOR_SHIFT", 106 "PLATID_SERIES_SHIFT", 107 "PLATID_MODEL_SHIFT", 108 "PLATID_SUBMODEL_SHIFT", 109 }, 110 }; 111 112 /* 113 * program entry 114 */ 115 int 116 main(int argc, char *argv[]) 117 { 118 int i; 119 120 form = FORM_GENHDR; 121 fp_out = stdout; 122 count = 0; 123 124 for (i = 1; i < argc; i++) { 125 if (strcmp(argv[i], "-header") == 0) { 126 form = FORM_GENHDR; 127 } else if (strcmp(argv[i], "-mask_h") == 0) { 128 form = FORM_MASK_H; 129 } else if (strcmp(argv[i], "-mask_c") == 0) { 130 form = FORM_MASK_C; 131 } else if (strcmp(argv[i], "-name_c") == 0) { 132 form = FORM_NAME_C; 133 } else if (strcmp(argv[i], "-parse_only") == 0) { 134 form = FORM_PARSE_ONLY; 135 } else { 136 usage: 137 fprintf(stderr, "usage platid_gen <option>\n"); 138 fprintf(stderr, " option: -header\n"); 139 fprintf(stderr, " -mask_h\n"); 140 fprintf(stderr, " -mask_c\n"); 141 fprintf(stderr, " -name_c\n"); 142 fprintf(stderr, " -parse_only\n"); 143 exit(1); 144 } 145 } 146 147 if (read_def()) { 148 exit(1); 149 } 150 151 if (form == FORM_PARSE_ONLY) { 152 dump_node("", def_tree); 153 exit (0); 154 } 155 156 gen_comment(fp_out); 157 switch (form) { 158 case FORM_GENHDR: 159 break; 160 case FORM_MASK_H: 161 break; 162 case FORM_MASK_C: 163 fprintf(fp_out, "#include <machine/platid.h>\n"); 164 fprintf(fp_out, "#include <machine/platid_mask.h>\n"); 165 break; 166 case FORM_NAME_C: 167 fprintf(fp_out, "#include <machine/platid.h>\n"); 168 fprintf(fp_out, "#include <machine/platid_mask.h>\n"); 169 fprintf(fp_out,"struct platid_name platid_name_table[] = {\n"); 170 break; 171 } 172 173 nest = -1; 174 enter(); /* XXX */ 175 mode = MODE_INVALID; 176 genctx[MODE_CPU][nest].alt = NULL; 177 genctx[MODE_MACHINE][nest].alt = NULL; 178 gen_list((node_t*)def_tree->ptr1); 179 180 switch (form) { 181 case FORM_GENHDR: 182 case FORM_MASK_H: 183 case FORM_MASK_C: 184 break; 185 case FORM_NAME_C: 186 fprintf(fp_out, "};\n"); 187 fprintf(fp_out, "int platid_name_table_size = sizeof(platid_name_table)/sizeof(*platid_name_table);\n"); 188 break; 189 } 190 fclose(fp_out); 191 192 exit(0); 193 } 194 195 int 196 table_getnum(char **table, char *s, int def, int opt) 197 { 198 int num; 199 200 num = 0; 201 while (table[num]) { 202 int diff; 203 if (opt & SEARCH_IGNORECASE) { 204 diff = strcmp(table[num], s); 205 } else { 206 diff = strcasecmp(table[num], s); 207 } 208 if (diff == 0) { 209 return (num); 210 } 211 num++; 212 } 213 return def; 214 } 215 216 #define GET_MODE(s) \ 217 table_getnum(mode_names, (s), MODE_INVALID, SEARCH_IGNORECASE) 218 #define GET_ALT(s) \ 219 table_getnum(mode_names, (s), MODE_INVALID, SEARCH_IGNORECASE) 220 221 void 222 enter() 223 { 224 nest++; 225 if (MAXNEST <= nest) { 226 fprintf(stderr, "too much nest\n"); 227 exit(1); 228 } 229 genctx[mode][nest].num = 0; 230 genctx[mode][nest].alt = NULL; 231 genctx[mode][nest].node_name[0] = NULL; 232 genctx[mode][nest].node_name[1] = NULL; 233 if (0 < nest) { 234 genctx[mode][nest].alt = genctx[mode][nest - 1].alt; 235 } 236 } 237 238 void 239 leave() 240 { 241 nest--; 242 if (nest < 0) { 243 fprintf(stderr, "internal error (nest=%d)\n", nest); 244 exit(1); 245 } 246 } 247 248 void 249 gen_comment(FILE *fp) 250 { 251 fprintf(fp, "/*\n"); 252 fprintf(fp, " * Do not edit.\n"); 253 fprintf(fp, " * This file is automatically generated by platid.awk.\n"); 254 fprintf(fp, " */\n"); 255 } 256 257 gen_name(char *buf, struct genctx_t ctx[], int nest, int name, char *punct, 258 int ignr) 259 { 260 int i; 261 buf[0] = '\0'; 262 for (i = 0; i <= nest; i++) { 263 if (!(ignr <= i && nest != i)) { 264 if (i != 0) { 265 strcat(buf, punct); 266 } 267 strcat(buf, ctx[i].node_name[name]); 268 } 269 } 270 } 271 272 void 273 gen_list(node_t* np) 274 { 275 int i, t; 276 277 for ( ; np; np = np->link) { 278 switch (np->type) { 279 case N_LABEL: 280 if ((mode = GET_MODE(np->ptr1)) == MODE_INVALID) { 281 fprintf(stderr, "invalid mode '%s'\n", 282 np->ptr1); 283 exit(1); 284 } 285 break; 286 case N_MODIFIER: 287 t = GET_ALT(np->ptr1); 288 if (t == MODE_INVALID) { 289 fprintf(stderr, "unknown alternater '%s'\n", 290 np->ptr1); 291 exit(1); 292 } 293 if (t == mode) { 294 fprintf(stderr, 295 "invalid alternater '%s' (ignored)\n", 296 np->ptr1); 297 exit(1); 298 } 299 genctx[mode][nest].alt = np->ptr2; 300 break; 301 case N_ENTRY: 302 if (np->ptr2 == NULL) { 303 char buf[MAXLEN]; 304 sprintf(buf, "%s%s", 305 nest == 0 ? "" : " ", 306 np->ptr1); 307 np->ptr2 = strdup(buf); 308 if (nest == 3) 309 np->val = 1; 310 } 311 touppers((char*)np->ptr1); 312 313 genctx[mode][nest].num++; 314 genctx[mode][nest].node_name[0] = np->ptr1; 315 genctx[mode][nest].node_name[1] = np->ptr2; 316 gen_name(genctx[mode][nest].sym, genctx[mode], 317 nest, 0, "_", nest == 3 ? 2 : nest); 318 gen_name(genctx[mode][nest].name, genctx[mode], 319 nest, 1, "", nest - np->val); 320 gen_output(); 321 break; 322 case N_LIST: 323 enter(); 324 gen_list((node_t*)np->ptr1); 325 leave(); 326 break; 327 case N_DIRECTIVE: 328 fprintf(fp_out, "%s", np->ptr1); 329 break; 330 default: 331 fprintf(stderr, "internal error (type=%d)\n", np->type); 332 exit(1); 333 break; 334 } 335 } 336 } 337 338 void 339 gen_output() 340 { 341 switch (form) { 342 case FORM_GENHDR: 343 gen_header(); 344 break; 345 case FORM_MASK_H: 346 gen_mask_h(); 347 break; 348 case FORM_MASK_C: 349 gen_mask_c(); 350 break; 351 case FORM_NAME_C: 352 gen_name_c(); 353 break; 354 } 355 } 356 357 /* 358 * platid_generated.h 359 * 360 * #define PLATID_CPU_XXX_NUM 1 361 * #define PLATID_CPU_XXX \ 362 * ((PLATID_CPU_XXX_NUM << PLATID_CPU_ARCH_SHIFT)) 363 * #define PLATID_CPU_XXX_YYY \ 364 * ((PLATID_CPU_XXX_YYY_NUM << PLATID_CPU_SERIES_SHIFT)| \ 365 * PLATID_CPU_XXX) 366 * 367 * #ifndef SPEC_PLATFORM 368 * #define SPEC_MACH_XXX 369 * #endif 370 * #define PLATID_MACH_XXX_NUM 1 371 * #define PLATID_MACH_XXX \ 372 * ((PLATID_MACH_XXX_NUM << PLATID_MACH_ARCH_SHIFT)) 373 * #define PLATID_MACH_XXX_YYY \ 374 * ((PLATID_MACH_XXX_YYY_NUM << PLATID_MACH_SERIES_SHIFT)| \ 375 * PLATID_MACH_XXX) 376 */ 377 void 378 gen_header() 379 { 380 char *prefix = prefix_names[mode]; 381 char *name = genctx[mode][nest].sym; 382 383 if (mode == MODE_MACHINE) { 384 fprintf(fp_out, "#ifndef SPEC_PLATFORM\n"); 385 fprintf(fp_out, "#define %s_%s_%s\n", "SPEC", prefix, name); 386 fprintf(fp_out, "#endif /* !SPEC_PLATFORM */\n"); 387 } 388 fprintf(fp_out, "#define %s_%s_%s_NUM\t%d\n", PREFIX, prefix, name, 389 genctx[mode][nest].num); 390 fprintf(fp_out, "#define %s_%s_%s\t\\\n", PREFIX, prefix, name); 391 fprintf(fp_out, " ((%s_%s_%s_NUM << %s)", PREFIX, prefix, name, 392 shift_names[mode][nest]); 393 if (0 < nest) { 394 fprintf(fp_out, "| \\\n %s_%s_%s", 395 PREFIX, prefix, genctx[mode][nest - 1].sym); 396 } 397 fprintf(fp_out, ")\n"); 398 } 399 400 /* 401 * platid_mask.h: 402 * 403 * extern platid_t platid_mask_CPU_MIPS; 404 * #ifdef PLATID_DEFINE_MASK_NICKNAME 405 * # define GENERIC_MIPS ((int)&platid_mask_CPU_MIPS) 406 * #endif 407 */ 408 void 409 gen_mask_h() 410 { 411 char *name = genctx[mode][nest].sym; 412 413 fprintf(fp_out, "extern platid_t platid_mask_%s_%s;\n", 414 prefix_names[mode], name); 415 fprintf(fp_out, "#ifdef PLATID_DEFINE_MASK_NICKNAME\n"); 416 fprintf(fp_out, "# define %s%s ((int)&platid_mask_%s_%s)\n", 417 (mode == MODE_CPU)?"GENERIC_":"", 418 name, prefix_names[mode], name); 419 fprintf(fp_out, "#endif\n"); 420 } 421 422 /* 423 * platid_mask.c: 424 * 425 * platid_t platid_mask_CPU_MIPS = {{ 426 * PLATID_CPU_MIPS, 427 * PLATID_WILD 428 * }}; 429 */ 430 void 431 gen_mask_c() 432 { 433 char *name = genctx[mode][nest].sym; 434 435 fprintf(fp_out, "platid_t platid_mask_%s_%s = {{\n", 436 prefix_names[mode], name); 437 switch (mode) { 438 case MODE_CPU: 439 fprintf(fp_out, "\t%s_CPU_%s,\n", PREFIX, name); 440 if (genctx[mode][nest].alt == NULL) 441 fprintf(fp_out, "\t%s_WILD\n", PREFIX); 442 else 443 fprintf(fp_out, "\t%s_MACH_%s,\n", PREFIX, 444 genctx[mode][nest].alt); 445 break; 446 case MODE_MACHINE: 447 if (genctx[mode][nest].alt == NULL) 448 fprintf(fp_out, "\t%s_WILD,\n", PREFIX); 449 else 450 fprintf(fp_out, "\t%s_CPU_%s,\n", PREFIX, 451 genctx[mode][nest].alt); 452 fprintf(fp_out, "\t%s_MACH_%s\n", PREFIX, name); 453 break; 454 } 455 fprintf(fp_out, "}};\n"); 456 } 457 458 /* 459 * platid_name.c: 460 */ 461 void 462 gen_name_c() 463 { 464 fprintf(fp_out, "\t{ &platid_mask_%s_%s,\n", 465 prefix_names[mode], genctx[mode][nest].sym); 466 fprintf(fp_out, "\t TEXT(\"%s\") },\n", genctx[mode][nest].name); 467 count++; 468 } 469