1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 1996-2002 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 #include <unistd.h> 30 #include <math.h> 31 #include <stdlib.h> 32 #include "stabs.h" 33 34 int debug_level = 0; 35 int line; 36 37 boolean_t error = B_FALSE; 38 char *program = NULL; 39 40 extern void forth_do_sou(struct tdesc *, struct node *); 41 extern void forth_do_enum(struct tdesc *, struct node *); 42 extern void forth_do_intrinsic(struct tdesc *, struct node *); 43 extern void genassym_do_sou(struct tdesc *, struct node *); 44 extern void genassym_do_enum(struct tdesc *, struct node *); 45 extern void genassym_do_intrinsic(struct tdesc *, struct node *); 46 extern void squander_do_sou(struct tdesc *, struct node *); 47 extern void squander_do_enum(struct tdesc *, struct node *); 48 extern void squander_do_intrinsic(struct tdesc *, struct node *); 49 50 struct model_info models[] = { 51 { "ilp32", 4, 1, 2, 4, 4 }, 52 { "lp64", 8, 1, 2, 4, 8 }, 53 { NULL, 0, 0, 0 } 54 }; 55 56 struct stab_ops { 57 char *type; 58 void (*do_sou)(struct tdesc *, struct node *); 59 void (*do_enum)(struct tdesc *, struct node *); 60 void (*do_intrinsic)(struct tdesc *, struct node *); 61 } ops_table[] = { 62 { "forth", 63 forth_do_sou, forth_do_enum, forth_do_intrinsic }, 64 { "genassym", 65 genassym_do_sou, genassym_do_enum, genassym_do_intrinsic }, 66 { "squander", 67 squander_do_sou, squander_do_enum, squander_do_intrinsic }, 68 { NULL, NULL, NULL } 69 }; 70 71 static void get_dbgs(int argc, char **argv); 72 static void parse_dbg(FILE *sp); 73 static void printnode(struct node *np); 74 static struct tdesc *find_member(struct tdesc *tdp, char *name); 75 static char *namex(char *cp, char **w); 76 static void addchild(char *cp, struct node *np); 77 static struct node *getnode(char *cp); 78 79 struct stab_ops *ops; 80 struct model_info *model; 81 82 int 83 main(int argc, char **argv) 84 { 85 char *output_type = NULL; 86 char *model_name = NULL; 87 int c; 88 89 program = strrchr(argv[0], '/'); 90 if (program != NULL) 91 program++; 92 else 93 program = argv[0]; 94 95 /* defaults */ 96 output_type = "forth"; 97 model_name = "ilp32"; 98 99 while (!error && ((c = getopt(argc, argv, "dt:m:")) != EOF)) { 100 switch (c) { 101 case 't': 102 output_type = optarg; 103 break; 104 case 'm': 105 model_name = optarg; 106 break; 107 case 'd': 108 debug_level++; 109 break; 110 case '?': 111 default: 112 error = B_TRUE; 113 break; 114 } 115 } 116 117 if (!error) { 118 /* 119 * Find ops for the specified output type 120 */ 121 for (ops = ops_table; ops->type != NULL; ops++) { 122 if (strcmp(ops->type, output_type) == 0) 123 break; 124 } 125 if (ops->type == NULL) 126 error = B_TRUE; 127 } 128 129 if (!error) { 130 /* 131 * Find model characteristics 132 */ 133 for (model = models; model->name != NULL; model++) { 134 if (strcmp(model->name, model_name) == 0) 135 break; 136 } 137 if (model->name == NULL) 138 error = B_TRUE; 139 } 140 141 /* skip over previously processed arguments */ 142 argc -= optind; 143 argv += optind; 144 if (argc < 1) 145 error = B_TRUE; 146 147 if (error) { 148 fprintf(stderr, "Usage: %s [-d] {-m datamodel} " 149 "{-t output_type} files\n", program); 150 fprintf(stderr, "\tSupported data models:\n"); 151 for (model = models; model->name != NULL; model++) 152 fprintf(stderr, "\t\t%s\n", model->name); 153 fprintf(stderr, "\tSupported output types:\n"); 154 for (ops = ops_table; ops->type != NULL; ops++) 155 fprintf(stderr, "\t\t%s\n", ops->type); 156 return (1); 157 } 158 159 parse_input(); 160 161 get_dbgs(argc, argv); 162 163 return (error ? 1 : 0); 164 } 165 166 /* 167 * This routine will read the .dbg files and build a list of the structures 168 * and fields that user is interested in. Any struct specified will get all 169 * its fields included. If nested struct needs to be printed - then the 170 * field name and name of struct type needs to be included in the next line. 171 */ 172 static void 173 get_dbgs(int argc, char **argv) 174 { 175 FILE *fp; 176 177 for (; argc != 0; argc--, argv++) { 178 if ((fp = fopen(*argv, "r")) == NULL) { 179 fprintf(stderr, "Cannot open %s\n", *argv); 180 error = B_TRUE; 181 return; 182 } 183 /* add all types in this file to our table */ 184 parse_dbg(fp); 185 } 186 } 187 188 static char * 189 namex(char *cp, char **w) 190 { 191 char *new, *orig, c; 192 int len; 193 194 if (*cp == '\0') { 195 *w = NULL; 196 return (cp); 197 } 198 199 for (c = *cp++; isspace(c); c = *cp++) 200 ; 201 orig = --cp; 202 c = *cp++; 203 if (isalpha(c) || ispunct(c)) { 204 for (c = *cp++; isalnum(c) || ispunct(c); c = *cp++) 205 ; 206 len = cp - orig; 207 new = (char *)malloc(len); 208 while (orig < cp - 1) 209 *new++ = *orig++; 210 *new = '\0'; 211 *w = new - (len - 1); 212 } else if (c != '\0') { 213 fprintf(stderr, "line %d has bad character %c\n", line, c); 214 error = B_TRUE; 215 } 216 217 return (cp); 218 } 219 220 /* 221 * checks to see if this field in the struct was requested for by user 222 * in the .dbg file. 223 */ 224 struct child * 225 find_child(struct node *np, char *w) 226 { 227 struct child *chp; 228 229 for (chp = np->child; chp != NULL; chp = chp->next) { 230 if (strcmp(chp->name, w) == 0) 231 return (chp); 232 } 233 return (NULL); 234 } 235 236 static struct tdesc * 237 find_member(struct tdesc *tdp, char *name) 238 { 239 struct mlist *mlp; 240 241 while (tdp->type == TYPEOF) 242 tdp = tdp->data.tdesc; 243 if (tdp->type != STRUCT && tdp->type != UNION) 244 return (NULL); 245 for (mlp = tdp->data.members.forw; mlp != NULL; mlp = mlp->next) 246 if (strcmp(mlp->name, name) == 0) 247 return (mlp->fdesc); 248 return (NULL); 249 } 250 251 /* 252 * add this field to our table of structs/fields that the user has 253 * requested in the .dbg files 254 */ 255 static void 256 addchild(char *cp, struct node *np) 257 { 258 struct child *chp; 259 char *w; 260 261 chp = malloc(sizeof (*chp)); 262 cp = namex(cp, &w); 263 chp->name = w; 264 cp = namex(cp, &w); 265 if (w == NULL) { 266 if (chp->name == NULL) { 267 fprintf(stderr, "NULL child name\n"); 268 exit(1); 269 } 270 /* XXX - always convert to upper-case? */ 271 chp->format = uc(chp->name); 272 } else { 273 chp->format = w; 274 } 275 chp->next = np->child; 276 np->child = chp; 277 } 278 279 /* 280 * add this struct to our table of structs/fields that the user has 281 * requested in the .dbg files 282 */ 283 static struct node * 284 getnode(char *cp) 285 { 286 char *w; 287 struct node *np; 288 289 cp = namex(cp, &w); 290 np = malloc(sizeof (*np)); 291 np->name = w; 292 293 /* 294 * XXX - These positional parameters are a hack 295 * We have two right now for genassym. The back-ends 296 * can use format and format2 any way they'd like. 297 */ 298 cp = namex(cp, &w); 299 np->format = w; 300 if (w != NULL) { 301 w = NULL; 302 cp = namex(cp, &w); 303 np->format2 = w; 304 } else { 305 np->format2 = NULL; 306 } 307 np->child = NULL; 308 return (np); 309 } 310 311 /* 312 * Format for .dbg files should be 313 * Ex: 314 * seg 315 * as s_as 316 * if you wanted the contents of "s_as" (a pointer) to be printed in 317 * the format of a "as" 318 */ 319 static void 320 parse_dbg(FILE *sp) 321 { 322 char *cp; 323 struct node *np; 324 static char linebuf[MAXLINE]; 325 int copy_flag = 0; 326 int ignore_flag = 0; 327 size_t c; 328 329 /* grab each line and add them to our table */ 330 for (line = 1; (cp = fgets(linebuf, MAXLINE, sp)) != NULL; line++) { 331 if (*cp == '\n') { 332 if (copy_flag) 333 printf("\n"); 334 continue; 335 } 336 if (*cp == '\\') { 337 if (cp[1] == '#') 338 printf("%s", (cp + 1)); 339 continue; 340 } 341 if (strcmp(cp, "model_end\n") == 0) { 342 if (ignore_flag) 343 ignore_flag = 0; 344 continue; 345 } 346 if (ignore_flag) 347 continue; 348 c = strlen("model_start "); 349 if (strncmp(cp, "model_start ", c) == 0) { 350 if (strncmp(cp + c, model->name, strlen(model->name)) 351 == 0 && *(cp + c + strlen(model->name)) == '\n') 352 /* model matches */; 353 else 354 ignore_flag = 1; 355 continue; 356 } 357 if ((strcmp(cp, "verbatim_begin\n") == 0) || 358 (strcmp(cp, "forth_start\n") == 0)) { 359 copy_flag = 1; 360 continue; 361 } 362 if ((strcmp(cp, "verbatim_end\n") == 0) || 363 (strcmp(cp, "forth_end\n") == 0)) { 364 copy_flag = 0; 365 continue; 366 } 367 if (copy_flag) { 368 printf("%s", cp); 369 continue; 370 } 371 np = getnode(cp); 372 for (line++; 373 ((cp = fgets(linebuf, MAXLINE, sp)) != NULL) && 374 *cp != '\n'; line++) { 375 /* members of struct, union or enum */ 376 addchild(cp, np); 377 } 378 printnode(np); 379 } 380 } 381 382 static void 383 printnode(struct node *np) 384 { 385 struct tdesc *tdp; 386 387 tdp = lookupname(np->name); 388 if (tdp == NULL) { 389 char *member; 390 struct tdesc *ptdp; 391 392 if ((member = strchr(np->name, '.')) != NULL) { 393 *member = '\0'; 394 ptdp = lookupname(np->name); 395 if (ptdp != NULL) 396 tdp = find_member(ptdp, member + 1); 397 *member = '.'; 398 } 399 if (tdp == NULL) { 400 fprintf(stderr, "Can't find %s\n", np->name); 401 error = B_TRUE; 402 return; 403 } 404 } 405 again: 406 switch (tdp->type) { 407 case STRUCT: 408 case UNION: 409 ops->do_sou(tdp, np); 410 break; 411 case ENUM: 412 ops->do_enum(tdp, np); 413 break; 414 case TYPEOF: 415 tdp = tdp->data.tdesc; 416 goto again; 417 case INTRINSIC: 418 ops->do_intrinsic(tdp, np); 419 break; 420 default: 421 fprintf(stderr, "%s isn't aggregate\n", np->name); 422 error = B_TRUE; 423 break; 424 } 425 } 426 427 428 char * 429 convert_format(char *format, char *dfault) 430 { 431 static char dot[3] = "."; 432 433 if (format == NULL) 434 return (dfault); 435 else if (strlen(format) == 1) { 436 dot[1] = *format; 437 return (dot); 438 } else 439 return (format); 440 } 441 442 char * 443 uc(const char *s) 444 { 445 char *buf; 446 int i; 447 448 buf = strdup(s); 449 for (i = 0; i < strlen(buf); i++) 450 buf[i] = toupper(buf[i]); 451 buf[i] = '\0'; 452 return (buf); 453 } 454