Commit | Line | Data |
---|---|---|
920dae64 AT |
1 | /* |
2 | * ========== Copyright Header Begin ========================================== | |
3 | * | |
4 | * Hypervisor Software File: stabs.c | |
5 | * | |
6 | * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. | |
7 | * | |
8 | * - Do no alter or remove copyright notices | |
9 | * | |
10 | * - Redistribution and use of this software in source and binary forms, with | |
11 | * or without modification, are permitted provided that the following | |
12 | * conditions are met: | |
13 | * | |
14 | * - Redistribution of source code must retain the above copyright notice, | |
15 | * this list of conditions and the following disclaimer. | |
16 | * | |
17 | * - Redistribution in binary form must reproduce the above copyright notice, | |
18 | * this list of conditions and the following disclaimer in the | |
19 | * documentation and/or other materials provided with the distribution. | |
20 | * | |
21 | * Neither the name of Sun Microsystems, Inc. or the names of contributors | |
22 | * may be used to endorse or promote products derived from this software | |
23 | * without specific prior written permission. | |
24 | * | |
25 | * This software is provided "AS IS," without a warranty of any kind. | |
26 | * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, | |
27 | * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A | |
28 | * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN | |
29 | * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR | |
30 | * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR | |
31 | * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN | |
32 | * OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR | |
33 | * FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE | |
34 | * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, | |
35 | * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF | |
36 | * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. | |
37 | * | |
38 | * You acknowledge that this software is not designed, licensed or | |
39 | * intended for use in the design, construction, operation or maintenance of | |
40 | * any nuclear facility. | |
41 | * | |
42 | * ========== Copyright Header End ============================================ | |
43 | */ | |
44 | /* | |
45 | * CDDL HEADER START | |
46 | * | |
47 | * The contents of this file are subject to the terms of the | |
48 | * Common Development and Distribution License (the "License"). | |
49 | * You may not use this file except in compliance with the License. | |
50 | * | |
51 | * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE | |
52 | * or http://www.opensolaris.org/os/licensing. | |
53 | * See the License for the specific language governing permissions | |
54 | * and limitations under the License. | |
55 | * | |
56 | * When distributing Covered Code, include this CDDL HEADER in each | |
57 | * file and include the License file at usr/src/OPENSOLARIS.LICENSE. | |
58 | * If applicable, add the following below this CDDL HEADER, with the | |
59 | * fields enclosed by brackets "[]" replaced with your own identifying | |
60 | * information: Portions Copyright [yyyy] [name of copyright owner] | |
61 | * | |
62 | * CDDL HEADER END | |
63 | */ | |
64 | ||
65 | /* | |
66 | * Copyright 2007 Sun Microsystems, Inc. All rights reserved. | |
67 | * Use is subject to license terms. | |
68 | */ | |
69 | ||
70 | #pragma ident "@(#)stabs.c 1.2 07/06/07 SMI" | |
71 | ||
72 | #include <limits.h> | |
73 | #include <stdarg.h> | |
74 | #include <stdio.h> | |
75 | ||
76 | #include "stabs.h" | |
77 | ||
78 | static struct tdesc *hash_table[BUCKETS]; | |
79 | static struct tdesc *name_table[BUCKETS]; | |
80 | ||
81 | static void reset(void); | |
82 | static jmp_buf resetbuf; | |
83 | ||
84 | static char *get_line(void); | |
85 | static void parseline(char *cp); | |
86 | static char *soudef(char *cp, enum type type, struct tdesc **rtdp); | |
87 | static void enumdef(char *cp, struct tdesc **rtdp); | |
88 | static int compute_sum(char *w); | |
89 | static struct tdesc *lookup(int h); | |
90 | ||
91 | static char *number(char *cp, int *n); | |
92 | static char *name(char *cp, char **w); | |
93 | static char *id(char *cp, int *h); | |
94 | static char *offsize(char *cp, struct mlist *mlp); | |
95 | static char *whitesp(char *cp); | |
96 | static void addhash(struct tdesc *tdp, int num); | |
97 | static void tagadd(char *w, int h, struct tdesc *tdp); | |
98 | static void tagdecl(char *cp, struct tdesc **rtdp, int h, char *w); | |
99 | static char *tdefdecl(char *cp, int h, struct tdesc **rtdp); | |
100 | static char *intrinsic(char *cp, struct tdesc **rtdp, intr_flags_t flags); | |
101 | static char *arraydef(char *cp, struct tdesc **rtdp); | |
102 | ||
103 | static int line_number = 0; | |
104 | static int debug_line = 0; | |
105 | static char linebuf[MAXLINE]; | |
106 | ||
107 | extern int debug_level; | |
108 | ||
109 | static void | |
110 | debug(int level, char *cp, char *fmt, ...) | |
111 | { | |
112 | va_list ap; | |
113 | char buf[1024]; | |
114 | char tmp[32]; | |
115 | int i; | |
116 | ||
117 | if (level > debug_level) | |
118 | return; | |
119 | ||
120 | if (cp != NULL) { | |
121 | for (i = 0; i < 30; i++) { | |
122 | if (cp[i] == '\0') | |
123 | break; | |
124 | if (!iscntrl(cp[i])) | |
125 | tmp[i] = cp[i]; | |
126 | } | |
127 | tmp[i] = '\0'; | |
128 | (void) sprintf(buf, "%s [cp='%s']\n", fmt, tmp); | |
129 | } else { | |
130 | strcpy(buf, fmt); | |
131 | strcat(buf, "\n"); | |
132 | } | |
133 | ||
134 | va_start(ap, fmt); | |
135 | (void) vfprintf(stderr, buf, ap); | |
136 | va_end(ap); | |
137 | } | |
138 | ||
139 | ||
140 | /* Report unexpected syntax in stabs. */ | |
141 | static void | |
142 | expected( | |
143 | char *who, /* what function, or part thereof, is reporting */ | |
144 | char *what, /* what was expected */ | |
145 | char *where) /* where we were in the line of input */ | |
146 | { | |
147 | fprintf(stderr, "%s, input line %d: expecting \"%s\" at \"%s\"\n", | |
148 | who, line_number, what, where); | |
149 | exit(1); | |
150 | } | |
151 | ||
152 | /* Read a line from stdin into linebuf and increment line_number. */ | |
153 | static char * | |
154 | get_line(void) | |
155 | { | |
156 | char *cp = fgets(linebuf, MAXLINE, stdin); | |
157 | line_number++; | |
158 | ||
159 | /* For debugging, you can set debug_line to a line to stop on. */ | |
160 | if (line_number == debug_line) { | |
161 | fprintf(stderr, "Hit debug line number %d\n", line_number); | |
162 | for (;;) | |
163 | sleep(1); | |
164 | } | |
165 | return (cp); | |
166 | } | |
167 | ||
168 | /* Get the continuation of the current input line. */ | |
169 | static char * | |
170 | get_continuation(void) | |
171 | { | |
172 | char *cp = get_line(); | |
173 | if (!cp) { | |
174 | fprintf(stderr, "expecting continuation line, " | |
175 | "got end of input\n"); | |
176 | exit(1); | |
177 | } | |
178 | ||
179 | /* Skip to the quoted stuff. */ | |
180 | while (*cp++ != '"') | |
181 | /* LINTED */ | |
182 | ; | |
183 | return (cp); | |
184 | } | |
185 | ||
186 | void | |
187 | parse_input(void) | |
188 | { | |
189 | char *cp; | |
190 | int i = 0; | |
191 | ||
192 | for (i = 0; i < BUCKETS; i++) { | |
193 | hash_table[i] = NULL; | |
194 | name_table[i] = NULL; | |
195 | } | |
196 | ||
197 | /* | |
198 | * get a line at a time from the .s stabs file and parse. | |
199 | */ | |
200 | while ((cp = get_line()) != NULL) | |
201 | parseline(cp); | |
202 | } | |
203 | ||
204 | /* | |
205 | * Parse each line of the .s file (stabs entry) gather meaningful information | |
206 | * like name of type, size, offsets of fields etc. | |
207 | */ | |
208 | static void | |
209 | parseline(char *cp) | |
210 | { | |
211 | struct tdesc *tdp; | |
212 | char c, *w; | |
213 | int h, tagdef; | |
214 | ||
215 | /* | |
216 | * setup for reset() | |
217 | */ | |
218 | if (setjmp(resetbuf)) | |
219 | return; | |
220 | ||
221 | /* | |
222 | * Look for lines of the form | |
223 | * .stabs "str",n,n,n,n | |
224 | * The part in '"' is then parsed. | |
225 | */ | |
226 | cp = whitesp(cp); | |
227 | #define STLEN 6 | |
228 | debug(2, cp, "parseline"); | |
229 | if (strncmp(cp, ".stabs", STLEN) != 0) | |
230 | reset(); | |
231 | cp += STLEN; | |
232 | #undef STLEN | |
233 | cp = whitesp(cp); | |
234 | if (*cp++ != '"') | |
235 | reset(); | |
236 | ||
237 | /* | |
238 | * name:type variable (ignored) | |
239 | * name:ttype typedef | |
240 | * name:Ttype struct tag define | |
241 | */ | |
242 | cp = whitesp(cp); | |
243 | cp = name(cp, &w); | |
244 | ||
245 | tagdef = 0; | |
246 | c = *cp++; | |
247 | switch (c) { | |
248 | case 't': /* type */ | |
249 | break; | |
250 | case 'T': /* struct, union, enum */ | |
251 | tagdef = 1; | |
252 | break; | |
253 | default: | |
254 | reset(); | |
255 | } | |
256 | ||
257 | /* | |
258 | * The type id and definition follow. | |
259 | */ | |
260 | cp = id(cp, &h); | |
261 | if (*cp == '"') { | |
262 | struct tdesc *ntdp; | |
263 | ||
264 | cp++; | |
265 | ntdp = lookup(h); | |
266 | if (ntdp == NULL) { /* if that type isn't defined yet */ | |
267 | if (*cp++ != '=') /* better be defining it now */ | |
268 | expected("parseline/'0-9'", "=", cp - 1); | |
269 | cp = tdefdecl(cp, h, &tdp); | |
270 | addhash(tdp, h); /* for *(x,y) types */ | |
271 | } else { /* that type is already defined */ | |
272 | tdp = malloc(sizeof (*tdp)); | |
273 | tdp->type = TYPEOF; | |
274 | tdp->name = (w != NULL) ? strdup(w) : NULL; | |
275 | tdp->data.tdesc = ntdp; | |
276 | addhash(tdp, h); /* for *(x,y) types */ | |
277 | debug(3, NULL, " %s defined as %s(%d)", w, | |
278 | (ntdp->name != NULL) ? ntdp->name : "anon", h); | |
279 | } | |
280 | return; | |
281 | } else if (*cp++ != '=') { | |
282 | expected("parseline", "=", cp - 1); | |
283 | } | |
284 | if (tagdef) { | |
285 | tagdecl(cp, &tdp, h, w); | |
286 | } else { | |
287 | tdefdecl(cp, h, &tdp); | |
288 | tagadd(w, h, tdp); | |
289 | } | |
290 | } | |
291 | ||
292 | /* | |
293 | * Check if we have this node in the hash table already | |
294 | */ | |
295 | static struct tdesc * | |
296 | lookup(int h) | |
297 | { | |
298 | int hash = HASH(h); | |
299 | struct tdesc *tdp = hash_table[hash]; | |
300 | ||
301 | while (tdp != NULL) { | |
302 | if (tdp->id == h) | |
303 | return (tdp); | |
304 | tdp = tdp->hash; | |
305 | } | |
306 | return (NULL); | |
307 | } | |
308 | ||
309 | static char * | |
310 | whitesp(char *cp) | |
311 | { | |
312 | char c; | |
313 | ||
314 | for (c = *cp++; isspace(c); c = *cp++) | |
315 | /* LINTED */ | |
316 | ; | |
317 | --cp; | |
318 | return (cp); | |
319 | } | |
320 | ||
321 | static char * | |
322 | name(char *cp, char **w) | |
323 | { | |
324 | char *new, *orig, c; | |
325 | int len; | |
326 | ||
327 | orig = cp; | |
328 | c = *cp++; | |
329 | if (c == ':') | |
330 | *w = NULL; | |
331 | else if (isalpha(c) || c == '_') { | |
332 | for (c = *cp++; isalnum(c) || c == ' ' || c == '_'; c = *cp++) | |
333 | /* LINTED */ | |
334 | ; | |
335 | if (c != ':') | |
336 | reset(); | |
337 | len = cp - orig; | |
338 | new = malloc(len); | |
339 | while (orig < cp - 1) | |
340 | *new++ = *orig++; | |
341 | *new = '\0'; | |
342 | *w = new - (len - 1); | |
343 | } else | |
344 | reset(); | |
345 | ||
346 | return (cp); | |
347 | } | |
348 | ||
349 | static char * | |
350 | number(char *cp, int *n) | |
351 | { | |
352 | char *next; | |
353 | ||
354 | *n = (int)strtol(cp, &next, 10); | |
355 | if (next == cp) | |
356 | expected("number", "<number>", cp); | |
357 | return (next); | |
358 | } | |
359 | ||
360 | static char * | |
361 | id(char *cp, int *h) | |
362 | { | |
363 | int n1, n2; | |
364 | ||
365 | if (*cp == '(') { /* SunPro style */ | |
366 | cp++; | |
367 | cp = number(cp, &n1); | |
368 | if (*cp++ != ',') | |
369 | expected("id", ",", cp - 1); | |
370 | cp = number(cp, &n2); | |
371 | if (*cp++ != ')') | |
372 | expected("id", ")", cp - 1); | |
373 | *h = n1 * 1000 + n2; | |
374 | } else if (isdigit(*cp)) { /* gcc style */ | |
375 | cp = number(cp, &n1); | |
376 | *h = n1; | |
377 | } else { | |
378 | expected("id", "(/0-9", cp); | |
379 | } | |
380 | return (cp); | |
381 | } | |
382 | ||
383 | static void | |
384 | tagadd(char *w, int h, struct tdesc *tdp) | |
385 | { | |
386 | struct tdesc *otdp; | |
387 | ||
388 | tdp->name = w; | |
389 | if (!(otdp = lookup(h))) | |
390 | addhash(tdp, h); | |
391 | else if (otdp != tdp) { | |
392 | fprintf(stderr, "duplicate entry\n"); | |
393 | fprintf(stderr, "old: %s %d %d %d\n", | |
394 | otdp->name ? otdp->name : "NULL", | |
395 | otdp->type, otdp->id / 1000, otdp->id % 1000); | |
396 | fprintf(stderr, "new: %s %d %d %d\n", | |
397 | tdp->name ? tdp->name : "NULL", | |
398 | tdp->type, tdp->id / 1000, tdp->id % 1000); | |
399 | } | |
400 | } | |
401 | ||
402 | static void | |
403 | tagdecl(char *cp, struct tdesc **rtdp, int h, char *w) | |
404 | { | |
405 | debug(1, NULL, "tagdecl: declaring '%s'", w ? w : "(anon)"); | |
406 | if ((*rtdp = lookup(h)) != NULL) { | |
407 | if (w != NULL) { | |
408 | if ((*rtdp)->name != NULL && | |
409 | strcmp((*rtdp)->name, w) != 0) { | |
410 | struct tdesc *tdp; | |
411 | ||
412 | tdp = malloc(sizeof (*tdp)); | |
413 | tdp->name = strdup(w); | |
414 | tdp->type = TYPEOF; | |
415 | tdp->data.tdesc = *rtdp; | |
416 | addhash(tdp, h); /* for *(x,y) types */ | |
417 | debug(3, NULL, " %s defined as %s(%d)", w, | |
418 | ((*rtdp)->name != NULL) ? | |
419 | (*rtdp)->name : "anon", h); | |
420 | } else if ((*rtdp)->name == NULL) { | |
421 | (*rtdp)->name = w; | |
422 | addhash(*rtdp, h); | |
423 | } | |
424 | } | |
425 | } else { | |
426 | *rtdp = malloc(sizeof (**rtdp)); | |
427 | (*rtdp)->name = w; | |
428 | addhash(*rtdp, h); | |
429 | } | |
430 | ||
431 | switch (*cp++) { | |
432 | case 's': | |
433 | soudef(cp, STRUCT, rtdp); | |
434 | break; | |
435 | case 'u': | |
436 | soudef(cp, UNION, rtdp); | |
437 | break; | |
438 | case 'e': | |
439 | enumdef(cp, rtdp); | |
440 | break; | |
441 | default: | |
442 | expected("tagdecl", "<tag type s/u/e>", cp - 1); | |
443 | break; | |
444 | } | |
445 | } | |
446 | ||
447 | static char * | |
448 | tdefdecl(char *cp, int h, struct tdesc **rtdp) | |
449 | { | |
450 | struct tdesc *ntdp; | |
451 | char *w; | |
452 | int c, h2; | |
453 | char type; | |
454 | intr_flags_t flags; | |
455 | ||
456 | flags = Intr_unknown; | |
457 | ||
458 | debug(3, cp, "tdefdecl h=%d", h); | |
459 | ||
460 | /* Type codes */ | |
461 | switch (type = *cp) { | |
462 | case 'b': /* integer */ | |
463 | c = *++cp; | |
464 | if (c != 's' && c != 'u') | |
465 | expected("tdefdecl/b", "[su]", cp - 1); | |
466 | flags = (c == 'u') ? Intr_unsigned : Intr_signed; | |
467 | c = *++cp; | |
468 | if (c == 'c') { | |
469 | flags |= Intr_char; | |
470 | cp++; | |
471 | } | |
472 | cp = intrinsic(cp, rtdp, flags); | |
473 | break; | |
474 | case 'R': /* fp */ | |
475 | /* skip up to and past ';' */ | |
476 | while (*cp++ != ';') | |
477 | /* LINTED */ | |
478 | ; | |
479 | cp = intrinsic(cp, rtdp, Intr_unknown); | |
480 | break; | |
481 | case '(': /* equiv to another type */ | |
482 | cp = id(cp, &h2); | |
483 | ntdp = lookup(h2); | |
484 | if (ntdp == NULL) { /* if that type isn't defined yet */ | |
485 | if (*cp++ != '=') /* better be defining it now */ | |
486 | expected("tdefdecl/'('", "=", cp - 1); | |
487 | cp = tdefdecl(cp, h2, rtdp); | |
488 | ntdp = malloc(sizeof (*ntdp)); | |
489 | ntdp->type = TYPEOF; | |
490 | ntdp->data.tdesc = *rtdp; | |
491 | addhash(ntdp, h2); | |
492 | } else { /* that type is already defined */ | |
493 | *rtdp = malloc(sizeof (**rtdp)); | |
494 | (*rtdp)->type = TYPEOF; | |
495 | (*rtdp)->data.tdesc = ntdp; | |
496 | } | |
497 | break; | |
498 | case '*': | |
499 | ntdp = NULL; | |
500 | cp = tdefdecl(cp + 1, h, &ntdp); | |
501 | if (ntdp == NULL) | |
502 | expected("tdefdecl/*", "id", cp); | |
503 | ||
504 | *rtdp = malloc(sizeof (**rtdp)); | |
505 | (*rtdp)->type = POINTER; | |
506 | (*rtdp)->size = model->pointersize; | |
507 | (*rtdp)->name = "pointer"; | |
508 | (*rtdp)->data.tdesc = ntdp; | |
509 | break; | |
510 | case 'f': | |
511 | cp = tdefdecl(cp + 1, h, &ntdp); | |
512 | *rtdp = malloc(sizeof (**rtdp)); | |
513 | (*rtdp)->type = FUNCTION; | |
514 | (*rtdp)->size = model->pointersize; | |
515 | (*rtdp)->name = "function"; | |
516 | (*rtdp)->data.tdesc = ntdp; | |
517 | break; | |
518 | case 'a': | |
519 | cp++; | |
520 | if (*cp++ != 'r') | |
521 | expected("tdefdecl/a", "r", cp - 1); | |
522 | *rtdp = malloc(sizeof (**rtdp)); | |
523 | (*rtdp)->type = ARRAY; | |
524 | (*rtdp)->name = "array"; | |
525 | cp = arraydef(cp, rtdp); | |
526 | break; | |
527 | case 'x': | |
528 | c = *++cp; | |
529 | if (c != 's' && c != 'u' && c != 'e') | |
530 | expected("tdefdecl/x", "[sue]", cp - 1); | |
531 | cp = name(cp + 1, &w); | |
532 | *rtdp = malloc(sizeof (**rtdp)); | |
533 | (*rtdp)->type = FORWARD; | |
534 | (*rtdp)->name = w; | |
535 | break; | |
536 | case 'B': /* volatile */ | |
537 | cp = tdefdecl(cp + 1, h, &ntdp); | |
538 | *rtdp = malloc(sizeof (**rtdp)); | |
539 | (*rtdp)->type = VOLATILE; | |
540 | (*rtdp)->size = 0; | |
541 | (*rtdp)->name = "volatile"; | |
542 | (*rtdp)->data.tdesc = ntdp; | |
543 | break; | |
544 | case 'k': /* const */ | |
545 | cp = tdefdecl(cp + 1, h, &ntdp); | |
546 | *rtdp = malloc(sizeof (**rtdp)); | |
547 | (*rtdp)->type = CONST; | |
548 | (*rtdp)->size = 0; | |
549 | (*rtdp)->name = "const"; | |
550 | (*rtdp)->data.tdesc = ntdp; | |
551 | break; | |
552 | case '0': case '1': case '2': case '3': case '4': | |
553 | case '5': case '6': case '7': case '8': case '9': | |
554 | /* gcc equiv to another type */ | |
555 | cp = id(cp, &h2); | |
556 | ntdp = lookup(h2); | |
557 | if (ntdp == NULL) { /* if that type isn't defined yet */ | |
558 | /* better be defining it now */ | |
559 | if (*cp++ != '=') { | |
560 | if (h != h2) | |
561 | expected("tdefdecl/'0-9'", "=", cp - 1); | |
562 | /* defined in terms of itself */ | |
563 | *rtdp = malloc(sizeof (**rtdp)); | |
564 | (*rtdp)->type = INTRINSIC; | |
565 | (*rtdp)->name = "void"; | |
566 | (*rtdp)->size = 0; | |
567 | } else { | |
568 | cp = tdefdecl(cp, h2, rtdp); | |
569 | ntdp = malloc(sizeof (*ntdp)); | |
570 | ntdp->type = TYPEOF; | |
571 | ntdp->data.tdesc = *rtdp; | |
572 | addhash(ntdp, h2); | |
573 | } | |
574 | } else { /* that type is already defined */ | |
575 | *rtdp = malloc(sizeof (**rtdp)); | |
576 | (*rtdp)->type = TYPEOF; | |
577 | (*rtdp)->data.tdesc = ntdp; | |
578 | } | |
579 | break; | |
580 | case 'u': | |
581 | case 's': | |
582 | cp++; | |
583 | ||
584 | *rtdp = malloc(sizeof (**rtdp)); | |
585 | (*rtdp)->name = NULL; | |
586 | cp = soudef(cp, (type == 'u') ? UNION : STRUCT, rtdp); | |
587 | break; | |
588 | default: | |
589 | expected("tdefdecl", "<type code>", cp); | |
590 | } | |
591 | return (cp); | |
592 | } | |
593 | ||
594 | static char * | |
595 | intrinsic(char *cp, struct tdesc **rtdp, intr_flags_t flags) | |
596 | { | |
597 | struct tdesc *tdp; | |
598 | int size; | |
599 | ||
600 | cp = number(cp, &size); | |
601 | tdp = malloc(sizeof (*tdp)); | |
602 | tdp->type = INTRINSIC; | |
603 | tdp->size = size; | |
604 | tdp->name = NULL; | |
605 | tdp->data.flags = flags; | |
606 | debug(3, NULL, "intrinsic: size=%ld", size); | |
607 | *rtdp = tdp; | |
608 | return (cp); | |
609 | } | |
610 | ||
611 | static char * | |
612 | soudef(char *cp, enum type type, struct tdesc **rtdp) | |
613 | { | |
614 | struct mlist **next_pp, *prev_p = NULL; | |
615 | char *w; | |
616 | int size; | |
617 | struct tdesc *tdp; | |
618 | ||
619 | cp = number(cp, &size); | |
620 | (*rtdp)->size = size; | |
621 | (*rtdp)->type = type; /* s or u */ | |
622 | ||
623 | /* | |
624 | * An '@' here indicates a bitmask follows. This is so the | |
625 | * compiler can pass information to debuggers about how structures | |
626 | * are passed in the v9 world. We don't need this information | |
627 | * so we skip over it. | |
628 | */ | |
629 | if (cp[0] == '@') | |
630 | cp += 3; | |
631 | ||
632 | debug(3, cp, "soudef: %s size=%d", | |
633 | (*rtdp)->name ? (*rtdp)->name : "(anonsou)", | |
634 | (*rtdp)->size); | |
635 | ||
636 | next_pp = &((*rtdp)->data.members.forw); /* head for forward linklist */ | |
637 | /* fill up the fields */ | |
638 | while ((*cp != '"') && (*cp != ';')) { /* signifies end of fields */ | |
639 | int h; | |
640 | struct mlist *mlp = malloc(sizeof (*mlp)); | |
641 | ||
642 | mlp->prev = prev_p; /* links for the backward list */ | |
643 | prev_p = mlp; | |
644 | *next_pp = mlp; /* links for the forward list */ | |
645 | next_pp = &mlp->next; | |
646 | ||
647 | cp = name(cp, &w); | |
648 | mlp->name = w; | |
649 | cp = id(cp, &h); | |
650 | /* | |
651 | * find the tdesc struct in the hash table for this type | |
652 | * and stick a ptr in here | |
653 | */ | |
654 | tdp = lookup(h); | |
655 | if (tdp == NULL) { /* not in hash list */ | |
656 | debug(3, NULL, " defines %s (%d)", w, h); | |
657 | if (*cp++ != '=') | |
658 | expected("soudef", "=", cp - 1); | |
659 | cp = tdefdecl(cp, h, &tdp); | |
660 | addhash(tdp, h); | |
661 | debug(4, cp, " soudef now looking at "); | |
662 | cp++; | |
663 | ||
664 | } else { | |
665 | debug(3, NULL, " refers to %s (%d, %s)", | |
666 | w ? w : "anon", h, tdp->name ? tdp->name : "anon"); | |
667 | } | |
668 | ||
669 | mlp->fdesc = tdp; | |
670 | cp = offsize(cp, mlp); /* cp is now pointing to next field */ | |
671 | if (*cp == '\\') /* could be a continuation */ | |
672 | cp = get_continuation(); | |
673 | } | |
674 | (*rtdp)->data.members.back = prev_p; /* head for backward linklist */ | |
675 | return (cp); | |
676 | } | |
677 | ||
678 | static char * | |
679 | offsize(char *cp, struct mlist *mlp) | |
680 | { | |
681 | int offset, size; | |
682 | ||
683 | if (*cp == ',') | |
684 | cp++; | |
685 | cp = number(cp, &offset); | |
686 | if (*cp++ != ',') | |
687 | expected("offsize/2", ",", cp - 1); | |
688 | cp = number(cp, &size); | |
689 | if (*cp++ != ';') | |
690 | expected("offsize/3", ";", cp - 1); | |
691 | mlp->offset = offset; | |
692 | mlp->size = size; | |
693 | return (cp); | |
694 | } | |
695 | ||
696 | static char * | |
697 | arraydef(char *cp, struct tdesc **rtdp) | |
698 | { | |
699 | int h; | |
700 | int start, end; | |
701 | ||
702 | cp = id(cp, &h); | |
703 | if (*cp++ != ';') | |
704 | expected("arraydef/1", ";", cp - 1); | |
705 | ||
706 | (*rtdp)->data.ardef = malloc(sizeof (struct ardef)); | |
707 | (*rtdp)->data.ardef->indices = malloc(sizeof (struct element)); | |
708 | (*rtdp)->data.ardef->indices->index_type = lookup(h); | |
709 | ||
710 | cp = number(cp, &start); /* lower */ | |
711 | if (*cp++ != ';') | |
712 | expected("arraydef/2", ";", cp - 1); | |
713 | cp = number(cp, &end); /* upper */ | |
714 | if (*cp++ != ';') | |
715 | expected("arraydef/3", ";", cp - 1); | |
716 | (*rtdp)->data.ardef->indices->range_start = start; | |
717 | (*rtdp)->data.ardef->indices->range_end = end; | |
718 | #if 0 | |
719 | if (isdigit(*cp)) { | |
720 | cp = number(cp, &contents_type); /* lower */ | |
721 | tdp = lookup(contents_type); | |
722 | if (tdp != NULL) { | |
723 | (*rtdp)->data.ardef->contents = tdp; | |
724 | } else { | |
725 | if (*cp != '=') | |
726 | expected("arraydef/4", "=", cp); | |
727 | cp = tdefdecl(cp + 1, h, &tdp); | |
728 | addhash(tdp, h); /* for *(x,y) types */ | |
729 | (*rtdp)->data.ardef->contents = tdp; | |
730 | } | |
731 | } /* else */ | |
732 | #endif | |
733 | cp = tdefdecl(cp, h, &((*rtdp)->data.ardef->contents)); | |
734 | return (cp); | |
735 | } | |
736 | ||
737 | static void | |
738 | enumdef(char *cp, struct tdesc **rtdp) | |
739 | { | |
740 | struct elist *elp, **prev; | |
741 | char *w; | |
742 | ||
743 | (*rtdp)->type = ENUM; | |
744 | (*rtdp)->data.emem = NULL; | |
745 | ||
746 | prev = &((*rtdp)->data.emem); | |
747 | while (*cp != ';') { | |
748 | elp = malloc(sizeof (*elp)); | |
749 | elp->next = NULL; | |
750 | *prev = elp; | |
751 | cp = name(cp, &w); | |
752 | elp->name = w; | |
753 | cp = number(cp, &elp->number); | |
754 | debug(3, NULL, "enum %s: %s=%ld", | |
755 | (*rtdp)->name ? (*rtdp)->name : "(anon enum)", | |
756 | elp->name, elp->number); | |
757 | prev = &elp->next; | |
758 | if (*cp++ != ',') | |
759 | expected("enumdef", ",", cp - 1); | |
760 | if (*cp == '\\') | |
761 | cp = get_continuation(); | |
762 | } | |
763 | } | |
764 | ||
765 | /* | |
766 | * Add a node to the hash queues. | |
767 | */ | |
768 | static void | |
769 | addhash(struct tdesc *tdp, int num) | |
770 | { | |
771 | int hash = HASH(num); | |
772 | struct tdesc *ttdp; | |
773 | char added_num = 0, added_name = 0; | |
774 | ||
775 | /* | |
776 | * If it already exists in the hash table don't add it again | |
777 | * (but still check to see if the name should be hashed). | |
778 | */ | |
779 | ttdp = lookup(num); | |
780 | if (ttdp == NULL) { | |
781 | tdp->id = num; | |
782 | tdp->hash = hash_table[hash]; | |
783 | hash_table[hash] = tdp; | |
784 | added_num = 1; | |
785 | } | |
786 | ||
787 | if (tdp->name != NULL) { | |
788 | ttdp = lookupname(tdp->name); | |
789 | if (ttdp == NULL) { | |
790 | hash = compute_sum(tdp->name); | |
791 | tdp->next = name_table[hash]; | |
792 | name_table[hash] = tdp; | |
793 | added_name = 1; | |
794 | } | |
795 | } | |
796 | if (!added_num && !added_name) { | |
797 | fprintf(stderr, "stabs: broken hash\n"); | |
798 | exit(1); | |
799 | } | |
800 | } | |
801 | ||
802 | struct tdesc * | |
803 | lookupname(char *name) | |
804 | { | |
805 | int hash = compute_sum(name); | |
806 | struct tdesc *tdp, *ttdp = NULL; | |
807 | ||
808 | for (tdp = name_table[hash]; tdp != NULL; tdp = tdp->next) { | |
809 | if (tdp->name != NULL && strcmp(tdp->name, name) == 0) { | |
810 | if (tdp->type == STRUCT || tdp->type == UNION || | |
811 | tdp->type == ENUM || tdp->type == INTRINSIC) | |
812 | return (tdp); | |
813 | if (tdp->type == TYPEOF) | |
814 | ttdp = tdp; | |
815 | } | |
816 | } | |
817 | return (ttdp); | |
818 | } | |
819 | ||
820 | static int | |
821 | compute_sum(char *w) | |
822 | { | |
823 | char c; | |
824 | int sum; | |
825 | ||
826 | for (sum = 0; (c = *w) != '\0'; sum += c, w++) | |
827 | /* LINTED */ | |
828 | ; | |
829 | return (HASH(sum)); | |
830 | } | |
831 | ||
832 | static void | |
833 | reset(void) | |
834 | { | |
835 | longjmp(resetbuf, 1); | |
836 | /* NOTREACHED */ | |
837 | } |