Merge commit '80d5689f5d4588adc071138e25e9d0d5252d9b55'
[unleashed.git] / usr / src / tools / stabs / main.c
blobaccb2a32a0d1c4216ed6700983f3ee50b19f5461
1 /*
2 * CDDL HEADER START
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.
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.
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]
20 * CDDL HEADER END
23 * Copyright 1996-2002 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #pragma ident "%Z%%M% %I% %E% SMI"
29 #include <unistd.h>
30 #include <math.h>
31 #include <stdlib.h>
32 #include "stabs.h"
34 int debug_level = 0;
35 int line;
37 boolean_t error = B_FALSE;
38 char *program = NULL;
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 *);
50 struct model_info models[] = {
51 { "ilp32", 4, 1, 2, 4, 4 },
52 { "lp64", 8, 1, 2, 4, 8 },
53 { NULL, 0, 0, 0 }
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 }
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);
79 struct stab_ops *ops;
80 struct model_info *model;
82 int
83 main(int argc, char **argv)
85 char *output_type = NULL;
86 char *model_name = NULL;
87 int c;
89 program = strrchr(argv[0], '/');
90 if (program != NULL)
91 program++;
92 else
93 program = argv[0];
95 /* defaults */
96 output_type = "forth";
97 model_name = "ilp32";
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;
117 if (!error) {
119 * Find ops for the specified output type
121 for (ops = ops_table; ops->type != NULL; ops++) {
122 if (strcmp(ops->type, output_type) == 0)
123 break;
125 if (ops->type == NULL)
126 error = B_TRUE;
129 if (!error) {
131 * Find model characteristics
133 for (model = models; model->name != NULL; model++) {
134 if (strcmp(model->name, model_name) == 0)
135 break;
137 if (model->name == NULL)
138 error = B_TRUE;
141 /* skip over previously processed arguments */
142 argc -= optind;
143 argv += optind;
144 if (argc < 1)
145 error = B_TRUE;
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);
159 parse_input();
161 get_dbgs(argc, argv);
163 return (error ? 1 : 0);
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.
172 static void
173 get_dbgs(int argc, char **argv)
175 FILE *fp;
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;
183 /* add all types in this file to our table */
184 parse_dbg(fp);
188 static char *
189 namex(char *cp, char **w)
191 char *new, *orig, c;
192 int len;
194 if (*cp == '\0') {
195 *w = NULL;
196 return (cp);
199 for (c = *cp++; isspace(c); c = *cp++)
201 orig = --cp;
202 c = *cp++;
203 if (isalpha(c) || ispunct(c)) {
204 for (c = *cp++; isalnum(c) || ispunct(c); c = *cp++)
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;
217 return (cp);
221 * checks to see if this field in the struct was requested for by user
222 * in the .dbg file.
224 struct child *
225 find_child(struct node *np, char *w)
227 struct child *chp;
229 for (chp = np->child; chp != NULL; chp = chp->next) {
230 if (strcmp(chp->name, w) == 0)
231 return (chp);
233 return (NULL);
236 static struct tdesc *
237 find_member(struct tdesc *tdp, char *name)
239 struct mlist *mlp;
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);
252 * add this field to our table of structs/fields that the user has
253 * requested in the .dbg files
255 static void
256 addchild(char *cp, struct node *np)
258 struct child *chp;
259 char *w;
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);
270 /* XXX - always convert to upper-case? */
271 chp->format = uc(chp->name);
272 } else {
273 chp->format = w;
275 chp->next = np->child;
276 np->child = chp;
280 * add this struct to our table of structs/fields that the user has
281 * requested in the .dbg files
283 static struct node *
284 getnode(char *cp)
286 char *w;
287 struct node *np;
289 cp = namex(cp, &w);
290 np = malloc(sizeof (*np));
291 np->name = w;
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.
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;
307 np->child = NULL;
308 return (np);
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"
319 static void
320 parse_dbg(FILE *sp)
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;
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;
336 if (*cp == '\\') {
337 if (cp[1] == '#')
338 printf("%s", (cp + 1));
339 continue;
341 if (strcmp(cp, "model_end\n") == 0) {
342 if (ignore_flag)
343 ignore_flag = 0;
344 continue;
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;
357 if ((strcmp(cp, "verbatim_begin\n") == 0) ||
358 (strcmp(cp, "forth_start\n") == 0)) {
359 copy_flag = 1;
360 continue;
362 if ((strcmp(cp, "verbatim_end\n") == 0) ||
363 (strcmp(cp, "forth_end\n") == 0)) {
364 copy_flag = 0;
365 continue;
367 if (copy_flag) {
368 printf("%s", cp);
369 continue;
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);
378 printnode(np);
382 static void
383 printnode(struct node *np)
385 struct tdesc *tdp;
387 tdp = lookupname(np->name);
388 if (tdp == NULL) {
389 char *member;
390 struct tdesc *ptdp;
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 = '.';
399 if (tdp == NULL) {
400 fprintf(stderr, "Can't find %s\n", np->name);
401 error = B_TRUE;
402 return;
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;
428 char *
429 convert_format(char *format, char *dfault)
431 static char dot[3] = ".";
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);
442 char *
443 uc(const char *s)
445 char *buf;
446 int i;
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);