Home | History | Annotate | Download | only in stabs
      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