5590 improper use of NULL in tools/protocmp
[unleashed.git] / usr / src / tools / stabs / stabs.c
blob3bf7bab52d21684bf288ee47c9b6872c7d5bd88c
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 <limits.h>
30 #include <stdarg.h>
31 #include <stdio.h>
33 #include "stabs.h"
35 static struct tdesc *hash_table[BUCKETS];
36 static struct tdesc *name_table[BUCKETS];
38 static void reset(void);
39 static jmp_buf resetbuf;
41 static char *get_line(void);
42 static void parseline(char *cp);
43 static char *soudef(char *cp, enum type type, struct tdesc **rtdp);
44 static void enumdef(char *cp, struct tdesc **rtdp);
45 static int compute_sum(char *w);
46 static struct tdesc *lookup(int h);
48 static char *number(char *cp, int *n);
49 static char *name(char *cp, char **w);
50 static char *id(char *cp, int *h);
51 static char *offsize(char *cp, struct mlist *mlp);
52 static char *whitesp(char *cp);
53 static void addhash(struct tdesc *tdp, int num);
54 static void tagadd(char *w, int h, struct tdesc *tdp);
55 static void tagdecl(char *cp, struct tdesc **rtdp, int h, char *w);
56 static char *tdefdecl(char *cp, int h, struct tdesc **rtdp);
57 static char *intrinsic(char *cp, struct tdesc **rtdp);
58 static char *arraydef(char *cp, struct tdesc **rtdp);
60 static int line_number = 0;
61 static int debug_line = 0;
62 static char linebuf[MAXLINE];
64 extern int debug_level;
66 static void
67 debug(int level, char *cp, char *fmt, ...)
69 va_list ap;
70 char buf[1024];
71 char tmp[32];
72 int i;
74 if (level > debug_level)
75 return;
77 if (cp != NULL) {
78 for (i = 0; i < 30; i++) {
79 if (cp[i] == '\0')
80 break;
81 if (!iscntrl(cp[i]))
82 tmp[i] = cp[i];
84 tmp[i] = '\0';
85 (void) sprintf(buf, "%s [cp='%s']\n", fmt, tmp);
86 } else {
87 strcpy(buf, fmt);
88 strcat(buf, "\n");
91 va_start(ap, fmt);
92 (void) vfprintf(stderr, buf, ap);
93 va_end(ap);
97 /* Report unexpected syntax in stabs. */
98 static void
99 expected(
100 char *who, /* what function, or part thereof, is reporting */
101 char *what, /* what was expected */
102 char *where) /* where we were in the line of input */
104 fprintf(stderr, "%s, input line %d: expecting \"%s\" at \"%s\"\n",
105 who, line_number, what, where);
106 exit(1);
109 /* Read a line from stdin into linebuf and increment line_number. */
110 static char *
111 get_line(void)
113 char *cp = fgets(linebuf, MAXLINE, stdin);
114 line_number++;
116 /* For debugging, you can set debug_line to a line to stop on. */
117 if (line_number == debug_line) {
118 fprintf(stderr, "Hit debug line number %d\n", line_number);
119 for (;;)
120 sleep(1);
122 return (cp);
125 /* Get the continuation of the current input line. */
126 static char *
127 get_continuation(void)
129 char *cp = get_line();
130 if (!cp) {
131 fprintf(stderr, "expecting continuation line, "
132 "got end of input\n");
133 exit(1);
136 /* Skip to the quoted stuff. */
137 while (*cp++ != '"')
139 return (cp);
142 void
143 parse_input(void)
145 char *cp;
146 int i = 0;
148 for (i = 0; i < BUCKETS; i++) {
149 hash_table[i] = NULL;
150 name_table[i] = NULL;
154 * get a line at a time from the .s stabs file and parse.
156 while ((cp = get_line()) != NULL)
157 parseline(cp);
161 * Parse each line of the .s file (stabs entry) gather meaningful information
162 * like name of type, size, offsets of fields etc.
164 static void
165 parseline(char *cp)
167 struct tdesc *tdp;
168 char c, *w;
169 int h, tagdef;
172 * setup for reset()
174 if (setjmp(resetbuf))
175 return;
178 * Look for lines of the form
179 * .stabs "str",n,n,n,n
180 * The part in '"' is then parsed.
182 cp = whitesp(cp);
183 #define STLEN 6
184 debug(2, cp, "parseline");
185 if (strncmp(cp, ".stabs", STLEN) != 0)
186 reset();
187 cp += STLEN;
188 #undef STLEN
189 cp = whitesp(cp);
190 if (*cp++ != '"')
191 reset();
194 * name:type variable (ignored)
195 * name:ttype typedef
196 * name:Ttype struct tag define
198 cp = whitesp(cp);
199 cp = name(cp, &w);
201 tagdef = 0;
202 switch (c = *cp++) {
203 case 't': /* type */
204 break;
205 case 'T': /* struct, union, enum */
206 tagdef = 1;
207 break;
208 default:
209 reset();
213 * The type id and definition follow.
215 cp = id(cp, &h);
216 if (*cp == '"') {
217 struct tdesc *ntdp;
219 cp++;
220 ntdp = lookup(h);
221 if (ntdp == NULL) { /* if that type isn't defined yet */
222 if (*cp++ != '=') /* better be defining it now */
223 expected("parseline/'0-9'", "=", cp - 1);
224 cp = tdefdecl(cp, h, &tdp);
225 addhash(tdp, h); /* for *(x,y) types */
226 } else { /* that type is already defined */
227 tdp = malloc(sizeof (*tdp));
228 tdp->type = TYPEOF;
229 tdp->name = (w != NULL) ? strdup(w) : NULL;
230 tdp->data.tdesc = ntdp;
231 addhash(tdp, h); /* for *(x,y) types */
232 debug(3, NULL, " %s defined as %s(%d)", w,
233 (ntdp->name != NULL) ? ntdp->name : "anon", h);
235 return;
236 } else if (*cp++ != '=') {
237 expected("parseline", "=", cp - 1);
239 if (tagdef) {
240 tagdecl(cp, &tdp, h, w);
241 } else {
242 tdefdecl(cp, h, &tdp);
243 tagadd(w, h, tdp);
248 * Check if we have this node in the hash table already
250 static struct tdesc *
251 lookup(int h)
253 int hash = HASH(h);
254 struct tdesc *tdp = hash_table[hash];
256 while (tdp != NULL) {
257 if (tdp->id == h)
258 return (tdp);
259 tdp = tdp->hash;
261 return (NULL);
264 static char *
265 whitesp(char *cp)
267 char *orig, c;
269 orig = cp;
270 for (c = *cp++; isspace(c); c = *cp++)
272 --cp;
273 return (cp);
276 static char *
277 name(char *cp, char **w)
279 char *new, *orig, c;
280 int len;
282 orig = cp;
283 c = *cp++;
284 if (c == ':')
285 *w = NULL;
286 else if (isalpha(c) || c == '_') {
287 for (c = *cp++; isalnum(c) || c == ' ' || c == '_'; c = *cp++)
289 if (c != ':')
290 reset();
291 len = cp - orig;
292 new = malloc(len);
293 while (orig < cp - 1)
294 *new++ = *orig++;
295 *new = '\0';
296 *w = new - (len - 1);
297 } else
298 reset();
300 return (cp);
303 static char *
304 number(char *cp, int *n)
306 char *next;
308 *n = (int)strtol(cp, &next, 10);
309 if (next == cp)
310 expected("number", "<number>", cp);
311 return (next);
314 static char *
315 id(char *cp, int *h)
317 int n1, n2;
319 if (*cp == '(') { /* SunPro style */
320 cp++;
321 cp = number(cp, &n1);
322 if (*cp++ != ',')
323 expected("id", ",", cp - 1);
324 cp = number(cp, &n2);
325 if (*cp++ != ')')
326 expected("id", ")", cp - 1);
327 *h = n1 * 1000 + n2;
328 } else if (isdigit(*cp)) { /* gcc style */
329 cp = number(cp, &n1);
330 *h = n1;
331 } else {
332 expected("id", "(/0-9", cp);
334 return (cp);
337 static void
338 tagadd(char *w, int h, struct tdesc *tdp)
340 struct tdesc *otdp;
342 tdp->name = w;
343 if (!(otdp = lookup(h)))
344 addhash(tdp, h);
345 else if (otdp != tdp) {
346 fprintf(stderr, "duplicate entry\n");
347 fprintf(stderr, "old: %s %d %d %d\n",
348 otdp->name ? otdp->name : "NULL",
349 otdp->type, otdp->id / 1000, otdp->id % 1000);
350 fprintf(stderr, "new: %s %d %d %d\n",
351 tdp->name ? tdp->name : "NULL",
352 tdp->type, tdp->id / 1000, tdp->id % 1000);
356 static void
357 tagdecl(char *cp, struct tdesc **rtdp, int h, char *w)
359 debug(1, NULL, "tagdecl: declaring '%s'", w ? w : "(anon)");
360 if ((*rtdp = lookup(h)) != NULL) {
361 if (w != NULL) {
362 if ((*rtdp)->name != NULL &&
363 strcmp((*rtdp)->name, w) != 0) {
364 struct tdesc *tdp;
366 tdp = malloc(sizeof (*tdp));
367 tdp->name = strdup(w);
368 tdp->type = TYPEOF;
369 tdp->data.tdesc = *rtdp;
370 addhash(tdp, h); /* for *(x,y) types */
371 debug(3, NULL, " %s defined as %s(%d)", w,
372 ((*rtdp)->name != NULL) ?
373 (*rtdp)->name : "anon", h);
374 } else if ((*rtdp)->name == NULL) {
375 (*rtdp)->name = w;
376 addhash(*rtdp, h);
379 } else {
380 *rtdp = malloc(sizeof (**rtdp));
381 (*rtdp)->name = w;
382 addhash(*rtdp, h);
385 switch (*cp++) {
386 case 's':
387 soudef(cp, STRUCT, rtdp);
388 break;
389 case 'u':
390 soudef(cp, UNION, rtdp);
391 break;
392 case 'e':
393 enumdef(cp, rtdp);
394 break;
395 default:
396 expected("tagdecl", "<tag type s/u/e>", cp - 1);
397 break;
401 static char *
402 tdefdecl(char *cp, int h, struct tdesc **rtdp)
404 struct tdesc *ntdp;
405 char *w;
406 int c, h2;
407 char type;
409 debug(3, cp, "tdefdecl h=%d", h);
411 /* Type codes */
412 switch (type = *cp) {
413 case 'b': /* integer */
414 c = *++cp;
415 if (c != 's' && c != 'u')
416 expected("tdefdecl/b", "[su]", cp - 1);
417 c = *++cp;
418 if (c == 'c')
419 cp++;
420 cp = intrinsic(cp, rtdp);
421 break;
422 case 'R': /* fp */
423 /* skip up to and past ';' */
424 while (*cp++ != ';')
425 /* NULL */;
426 cp = intrinsic(cp, rtdp);
427 break;
428 case '(': /* equiv to another type */
429 cp = id(cp, &h2);
430 ntdp = lookup(h2);
431 if (ntdp == NULL) { /* if that type isn't defined yet */
432 if (*cp++ != '=') /* better be defining it now */
433 expected("tdefdecl/'('", "=", cp - 1);
434 cp = tdefdecl(cp, h2, rtdp);
435 ntdp = malloc(sizeof (*ntdp));
436 ntdp->type = TYPEOF;
437 ntdp->data.tdesc = *rtdp;
438 addhash(ntdp, h2);
439 } else { /* that type is already defined */
440 *rtdp = malloc(sizeof (**rtdp));
441 (*rtdp)->type = TYPEOF;
442 (*rtdp)->data.tdesc = ntdp;
444 break;
445 case '*':
446 ntdp = NULL;
447 cp = tdefdecl(cp + 1, h, &ntdp);
448 if (ntdp == NULL)
449 expected("tdefdecl/*", "id", cp);
451 *rtdp = malloc(sizeof (**rtdp));
452 (*rtdp)->type = POINTER;
453 (*rtdp)->size = model->pointersize;
454 (*rtdp)->name = "pointer";
455 (*rtdp)->data.tdesc = ntdp;
456 break;
457 case 'f':
458 cp = tdefdecl(cp + 1, h, &ntdp);
459 *rtdp = malloc(sizeof (**rtdp));
460 (*rtdp)->type = FUNCTION;
461 (*rtdp)->size = model->pointersize;
462 (*rtdp)->name = "function";
463 (*rtdp)->data.tdesc = ntdp;
464 break;
465 case 'a':
466 cp++;
467 if (*cp++ != 'r')
468 expected("tdefdecl/a", "r", cp - 1);
469 *rtdp = malloc(sizeof (**rtdp));
470 (*rtdp)->type = ARRAY;
471 (*rtdp)->name = "array";
472 cp = arraydef(cp, rtdp);
473 break;
474 case 'x':
475 c = *++cp;
476 if (c != 's' && c != 'u' && c != 'e')
477 expected("tdefdecl/x", "[sue]", cp - 1);
478 cp = name(cp + 1, &w);
479 *rtdp = malloc(sizeof (**rtdp));
480 (*rtdp)->type = FORWARD;
481 (*rtdp)->name = w;
482 break;
483 case 'B': /* volatile */
484 cp = tdefdecl(cp + 1, h, &ntdp);
485 *rtdp = malloc(sizeof (**rtdp));
486 (*rtdp)->type = VOLATILE;
487 (*rtdp)->size = 0;
488 (*rtdp)->name = "volatile";
489 (*rtdp)->data.tdesc = ntdp;
490 break;
491 case 'k': /* const */
492 cp = tdefdecl(cp + 1, h, &ntdp);
493 *rtdp = malloc(sizeof (**rtdp));
494 (*rtdp)->type = CONST;
495 (*rtdp)->size = 0;
496 (*rtdp)->name = "const";
497 (*rtdp)->data.tdesc = ntdp;
498 break;
499 case '0': case '1': case '2': case '3': case '4':
500 case '5': case '6': case '7': case '8': case '9':
501 /* gcc equiv to another type */
502 cp = id(cp, &h2);
503 ntdp = lookup(h2);
504 if (ntdp == NULL) { /* if that type isn't defined yet */
505 /* better be defining it now */
506 if (*cp++ != '=') {
507 if (h != h2)
508 expected("tdefdecl/'0-9'", "=", cp - 1);
509 /* defined in terms of itself */
510 *rtdp = malloc(sizeof (**rtdp));
511 (*rtdp)->type = INTRINSIC;
512 (*rtdp)->name = "void";
513 (*rtdp)->size = 0;
514 } else {
515 cp = tdefdecl(cp, h2, rtdp);
516 ntdp = malloc(sizeof (*ntdp));
517 ntdp->type = TYPEOF;
518 ntdp->data.tdesc = *rtdp;
519 addhash(ntdp, h2);
521 } else { /* that type is already defined */
522 *rtdp = malloc(sizeof (**rtdp));
523 (*rtdp)->type = TYPEOF;
524 (*rtdp)->data.tdesc = ntdp;
526 break;
527 case 'u':
528 case 's':
529 cp++;
531 *rtdp = malloc(sizeof (**rtdp));
532 (*rtdp)->name = NULL;
533 cp = soudef(cp, (type == 'u') ? UNION : STRUCT, rtdp);
534 break;
535 default:
536 expected("tdefdecl", "<type code>", cp);
538 return (cp);
541 static char *
542 intrinsic(char *cp, struct tdesc **rtdp)
544 struct tdesc *tdp;
545 int size;
547 cp = number(cp, &size);
548 tdp = malloc(sizeof (*tdp));
549 tdp->type = INTRINSIC;
550 tdp->size = size;
551 tdp->name = NULL;
552 debug(3, NULL, "intrinsic: size=%ld", size);
553 *rtdp = tdp;
554 return (cp);
557 static char *
558 soudef(char *cp, enum type type, struct tdesc **rtdp)
560 struct mlist **next_pp, *prev_p = NULL;
561 char *w;
562 int size;
563 struct tdesc *tdp;
565 cp = number(cp, &size);
566 (*rtdp)->size = size;
567 (*rtdp)->type = type; /* s or u */
570 * An '@' here indicates a bitmask follows. This is so the
571 * compiler can pass information to debuggers about how structures
572 * are passed in the v9 world. We don't need this information
573 * so we skip over it.
575 if (cp[0] == '@')
576 cp += 3;
578 debug(3, cp, "soudef: %s size=%d",
579 (*rtdp)->name ? (*rtdp)->name : "(anonsou)",
580 (*rtdp)->size);
582 next_pp = &((*rtdp)->data.members.forw); /* head for forward linklist */
583 /* fill up the fields */
584 while ((*cp != '"') && (*cp != ';')) { /* signifies end of fields */
585 int h;
586 struct mlist *mlp = malloc(sizeof (*mlp));
588 mlp->prev = prev_p; /* links for the backward list */
589 prev_p = mlp;
590 *next_pp = mlp; /* links for the forward list */
591 next_pp = &mlp->next;
593 cp = name(cp, &w);
594 mlp->name = w;
595 cp = id(cp, &h);
597 * find the tdesc struct in the hash table for this type
598 * and stick a ptr in here
600 tdp = lookup(h);
601 if (tdp == NULL) { /* not in hash list */
602 debug(3, NULL, " defines %s (%d)", w, h);
603 if (*cp++ != '=')
604 expected("soudef", "=", cp - 1);
605 cp = tdefdecl(cp, h, &tdp);
606 addhash(tdp, h);
607 debug(4, cp, " soudef now looking at ");
608 cp++;
610 } else {
611 debug(3, NULL, " refers to %s (%d, %s)",
612 w ? w : "anon", h, tdp->name ? tdp->name : "anon");
615 mlp->fdesc = tdp;
616 cp = offsize(cp, mlp); /* cp is now pointing to next field */
617 if (*cp == '\\') /* could be a continuation */
618 cp = get_continuation();
620 (*rtdp)->data.members.back = prev_p; /* head for backward linklist */
621 return (cp);
624 static char *
625 offsize(char *cp, struct mlist *mlp)
627 int offset, size;
629 if (*cp == ',')
630 cp++;
631 cp = number(cp, &offset);
632 if (*cp++ != ',')
633 expected("offsize/2", ",", cp - 1);
634 cp = number(cp, &size);
635 if (*cp++ != ';')
636 expected("offsize/3", ";", cp - 1);
637 mlp->offset = offset;
638 mlp->size = size;
639 return (cp);
642 static char *
643 arraydef(char *cp, struct tdesc **rtdp)
645 int h;
646 int start, end;
648 cp = id(cp, &h);
649 if (*cp++ != ';')
650 expected("arraydef/1", ";", cp - 1);
652 (*rtdp)->data.ardef = malloc(sizeof (struct ardef));
653 (*rtdp)->data.ardef->indices = malloc(sizeof (struct element));
654 (*rtdp)->data.ardef->indices->index_type = lookup(h);
656 cp = number(cp, &start); /* lower */
657 if (*cp++ != ';')
658 expected("arraydef/2", ";", cp - 1);
659 cp = number(cp, &end); /* upper */
660 if (*cp++ != ';')
661 expected("arraydef/3", ";", cp - 1);
662 (*rtdp)->data.ardef->indices->range_start = start;
663 (*rtdp)->data.ardef->indices->range_end = end;
664 #if 0
665 if (isdigit(*cp)) {
666 cp = number(cp, &contents_type); /* lower */
667 tdp = lookup(contents_type);
668 if (tdp != NULL) {
669 (*rtdp)->data.ardef->contents = tdp;
670 } else {
671 if (*cp != '=')
672 expected("arraydef/4", "=", cp);
673 cp = tdefdecl(cp + 1, h, &tdp);
674 addhash(tdp, h); /* for *(x,y) types */
675 (*rtdp)->data.ardef->contents = tdp;
677 } /* else */
678 #endif
679 cp = tdefdecl(cp, h, &((*rtdp)->data.ardef->contents));
680 return (cp);
683 static void
684 enumdef(char *cp, struct tdesc **rtdp)
686 struct elist *elp, **prev;
687 char *w;
689 (*rtdp)->type = ENUM;
690 (*rtdp)->data.emem = NULL;
692 prev = &((*rtdp)->data.emem);
693 while (*cp != ';') {
694 elp = malloc(sizeof (*elp));
695 elp->next = NULL;
696 *prev = elp;
697 cp = name(cp, &w);
698 elp->name = w;
699 cp = number(cp, &elp->number);
700 debug(3, NULL, "enum %s: %s=%ld",
701 (*rtdp)->name ? (*rtdp)->name : "(anon enum)",
702 elp->name, elp->number);
703 prev = &elp->next;
704 if (*cp++ != ',')
705 expected("enumdef", ",", cp - 1);
706 if (*cp == '\\')
707 cp = get_continuation();
712 * Add a node to the hash queues.
714 static void
715 addhash(struct tdesc *tdp, int num)
717 int hash = HASH(num);
718 struct tdesc *ttdp;
719 char added_num = 0, added_name = 0;
722 * If it already exists in the hash table don't add it again
723 * (but still check to see if the name should be hashed).
725 ttdp = lookup(num);
726 if (ttdp == NULL) {
727 tdp->id = num;
728 tdp->hash = hash_table[hash];
729 hash_table[hash] = tdp;
730 added_num = 1;
733 if (tdp->name != NULL) {
734 ttdp = lookupname(tdp->name);
735 if (ttdp == NULL) {
736 hash = compute_sum(tdp->name);
737 tdp->next = name_table[hash];
738 name_table[hash] = tdp;
739 added_name = 1;
742 if (!added_num && !added_name) {
743 fprintf(stderr, "stabs: broken hash\n");
744 exit(1);
748 struct tdesc *
749 lookupname(char *name)
751 int hash = compute_sum(name);
752 struct tdesc *tdp, *ttdp = NULL;
754 for (tdp = name_table[hash]; tdp != NULL; tdp = tdp->next) {
755 if (tdp->name != NULL && strcmp(tdp->name, name) == 0) {
756 if (tdp->type == STRUCT || tdp->type == UNION ||
757 tdp->type == ENUM || tdp->type == INTRINSIC)
758 return (tdp);
759 if (tdp->type == TYPEOF)
760 ttdp = tdp;
763 return (ttdp);
766 static int
767 compute_sum(char *w)
769 char c;
770 int sum;
772 for (sum = 0; (c = *w) != '\0'; sum += c, w++)
774 return (HASH(sum));
777 static void
778 reset(void)
780 longjmp(resetbuf, 1);
781 /* NOTREACHED */