1/* $NetBSD: platid_gen.c,v 1.10 2011/09/23 14:14:38 nonaka 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.10 2011/09/23 14:14:38 nonaka 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 56enum { FORM_GENHDR, FORM_MASK_H, FORM_MASK_C, FORM_NAME_C, FORM_PARSE_ONLY }; 57 58/* 59 * data type definitions 60 */ 61struct 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 */ 72void gen_list(node_t *); 73void gen_output(void); 74void gen_header(void); 75void gen_mask_h(void); 76void gen_mask_c(void); 77void gen_name_c(void); 78void gen_comment(FILE *); 79void enter(void); 80void leave(void); 81 82/* 83 * global data 84 */ 85node_t* def_tree; 86int nest; 87int mode; 88FILE *fp_out; 89int form; 90int count; 91 92#define MODE_INVALID -1 93#define MODE_CPU 0 94#define MODE_MACHINE 1 95char* mode_names[] = { 96 "CPU", "MACHINE", NULL 97}; 98#define PREFIX "PLATID" 99char* prefix_names[] = { 100 "CPU", "MACH", 101}; 102char* 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 */ 120int 121main(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 200int 201table_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 226void 227enter(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 243void 244leave(void) 245{ 246 nest--; 247 if (nest < 0) { 248 fprintf(stderr, "internal error (nest=%d)\n", nest); 249 exit(1); 250 } 251} 252 253void 254gen_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 262int 263gen_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 278void 279gen_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 344void 345gen_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 */ 383void 384gen_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 */ 414void 415gen_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 */ 436void 437gen_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 */ 467void 468gen_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