17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 54d232658Sjohnlev * Common Development and Distribution License (the "License"). 64d232658Sjohnlev * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 217c478bd9Sstevel@tonic-gate /* 22*53fb31f0SSurya Prakki * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. 237c478bd9Sstevel@tonic-gate */ 247c478bd9Sstevel@tonic-gate 257c478bd9Sstevel@tonic-gate /* 267c478bd9Sstevel@tonic-gate * This file is a sewer. 277c478bd9Sstevel@tonic-gate */ 287c478bd9Sstevel@tonic-gate 297c478bd9Sstevel@tonic-gate #include <limits.h> 307c478bd9Sstevel@tonic-gate #include <stdarg.h> 317c478bd9Sstevel@tonic-gate #include <stdio.h> 327c478bd9Sstevel@tonic-gate #include <assert.h> 337c478bd9Sstevel@tonic-gate #include <strings.h> 347c478bd9Sstevel@tonic-gate #include <setjmp.h> 357c478bd9Sstevel@tonic-gate #include <ctype.h> 367c478bd9Sstevel@tonic-gate #include <uts/common/sys/ctf.h> 377c478bd9Sstevel@tonic-gate 387c478bd9Sstevel@tonic-gate #include "ctftools.h" 397c478bd9Sstevel@tonic-gate #include "memory.h" 407c478bd9Sstevel@tonic-gate #include "list.h" 417c478bd9Sstevel@tonic-gate 427c478bd9Sstevel@tonic-gate #define HASH(NUM) ((int)(NUM & (BUCKETS - 1))) 437c478bd9Sstevel@tonic-gate #define BUCKETS 128 447c478bd9Sstevel@tonic-gate 457c478bd9Sstevel@tonic-gate #define TYPEPAIRMULT 10000 467c478bd9Sstevel@tonic-gate #define MAKETYPEID(file, num) ((file) * TYPEPAIRMULT + num) 477c478bd9Sstevel@tonic-gate #define TYPEFILE(tid) ((tid) / TYPEPAIRMULT) 487c478bd9Sstevel@tonic-gate #define TYPENUM(tid) ((tid) % TYPEPAIRMULT) 497c478bd9Sstevel@tonic-gate 507c478bd9Sstevel@tonic-gate #define expected(a, b, c) _expected(a, b, c, __LINE__) 517c478bd9Sstevel@tonic-gate 527c478bd9Sstevel@tonic-gate static int faketypenumber = 100000000; 537c478bd9Sstevel@tonic-gate 547c478bd9Sstevel@tonic-gate static tdesc_t *hash_table[BUCKETS]; 557c478bd9Sstevel@tonic-gate static tdesc_t *name_table[BUCKETS]; 567c478bd9Sstevel@tonic-gate 577c478bd9Sstevel@tonic-gate list_t *typedbitfldmems; 587c478bd9Sstevel@tonic-gate 597c478bd9Sstevel@tonic-gate static void reset(void); 607c478bd9Sstevel@tonic-gate static jmp_buf resetbuf; 617c478bd9Sstevel@tonic-gate 627c478bd9Sstevel@tonic-gate static char *soudef(char *cp, stabtype_t type, tdesc_t **rtdp); 637c478bd9Sstevel@tonic-gate static void enumdef(char *cp, tdesc_t **rtdp); 64e824d57fSjohnlev static int compute_sum(const char *w); 657c478bd9Sstevel@tonic-gate 667c478bd9Sstevel@tonic-gate static char *number(char *cp, int *n); 677c478bd9Sstevel@tonic-gate static char *name(char *cp, char **w); 687c478bd9Sstevel@tonic-gate static char *id(char *cp, int *h); 697c478bd9Sstevel@tonic-gate static char *whitesp(char *cp); 707c478bd9Sstevel@tonic-gate static void addhash(tdesc_t *tdp, int num); 717c478bd9Sstevel@tonic-gate static int tagadd(char *w, int h, tdesc_t *tdp); 727c478bd9Sstevel@tonic-gate static char *tdefdecl(char *cp, int h, tdesc_t **rtdp); 737c478bd9Sstevel@tonic-gate static char *intrinsic(char *cp, tdesc_t **rtdp); 747c478bd9Sstevel@tonic-gate static char *arraydef(char *cp, tdesc_t **rtdp); 757c478bd9Sstevel@tonic-gate 767c478bd9Sstevel@tonic-gate extern int debug_level; 777c478bd9Sstevel@tonic-gate int debug_parse = DEBUG_PARSE; 787c478bd9Sstevel@tonic-gate 797c478bd9Sstevel@tonic-gate /*PRINTFLIKE3*/ 807c478bd9Sstevel@tonic-gate static void 817c478bd9Sstevel@tonic-gate parse_debug(int level, char *cp, char *fmt, ...) 827c478bd9Sstevel@tonic-gate { 837c478bd9Sstevel@tonic-gate va_list ap; 847c478bd9Sstevel@tonic-gate char buf[1024]; 857c478bd9Sstevel@tonic-gate char tmp[32]; 867c478bd9Sstevel@tonic-gate int i; 877c478bd9Sstevel@tonic-gate 887c478bd9Sstevel@tonic-gate if (level > debug_level || !debug_parse) 897c478bd9Sstevel@tonic-gate return; 907c478bd9Sstevel@tonic-gate 917c478bd9Sstevel@tonic-gate if (cp != NULL) { 927c478bd9Sstevel@tonic-gate for (i = 0; i < 30; i++) { 937c478bd9Sstevel@tonic-gate if (cp[i] == '\0') 947c478bd9Sstevel@tonic-gate break; 957c478bd9Sstevel@tonic-gate if (!iscntrl(cp[i])) 967c478bd9Sstevel@tonic-gate tmp[i] = cp[i]; 977c478bd9Sstevel@tonic-gate } 987c478bd9Sstevel@tonic-gate tmp[i] = '\0'; 997c478bd9Sstevel@tonic-gate (void) snprintf(buf, sizeof (buf), "%s [cp='%s']\n", fmt, tmp); 1007c478bd9Sstevel@tonic-gate } else { 1017c478bd9Sstevel@tonic-gate strcpy(buf, fmt); 1027c478bd9Sstevel@tonic-gate strcat(buf, "\n"); 1037c478bd9Sstevel@tonic-gate } 1047c478bd9Sstevel@tonic-gate 1057c478bd9Sstevel@tonic-gate va_start(ap, fmt); 1067c478bd9Sstevel@tonic-gate vadebug(level, buf, ap); 1077c478bd9Sstevel@tonic-gate va_end(ap); 1087c478bd9Sstevel@tonic-gate } 1097c478bd9Sstevel@tonic-gate 1107c478bd9Sstevel@tonic-gate /* Report unexpected syntax in stabs. */ 1117c478bd9Sstevel@tonic-gate static void 1127c478bd9Sstevel@tonic-gate _expected( 1137c478bd9Sstevel@tonic-gate char *who, /* what function, or part thereof, is reporting */ 1147c478bd9Sstevel@tonic-gate char *what, /* what was expected */ 1157c478bd9Sstevel@tonic-gate char *where, /* where we were in the line of input */ 1167c478bd9Sstevel@tonic-gate int line) 1177c478bd9Sstevel@tonic-gate { 1187c478bd9Sstevel@tonic-gate fprintf(stderr, "%s, expecting \"%s\" at \"%s\"\n", who, what, where); 1197c478bd9Sstevel@tonic-gate fprintf(stderr, "code line: %d, file %s\n", line, 1207c478bd9Sstevel@tonic-gate (curhdr ? curhdr : "NO FILE")); 1217c478bd9Sstevel@tonic-gate reset(); 1227c478bd9Sstevel@tonic-gate } 1237c478bd9Sstevel@tonic-gate 1247c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 1257c478bd9Sstevel@tonic-gate void 1267c478bd9Sstevel@tonic-gate parse_init(tdata_t *td) 1277c478bd9Sstevel@tonic-gate { 1287c478bd9Sstevel@tonic-gate int i; 1297c478bd9Sstevel@tonic-gate 1307c478bd9Sstevel@tonic-gate for (i = 0; i < BUCKETS; i++) { 1317c478bd9Sstevel@tonic-gate hash_table[i] = NULL; 1327c478bd9Sstevel@tonic-gate name_table[i] = NULL; 1337c478bd9Sstevel@tonic-gate } 1347c478bd9Sstevel@tonic-gate 1357c478bd9Sstevel@tonic-gate if (typedbitfldmems != NULL) { 1367c478bd9Sstevel@tonic-gate list_free(typedbitfldmems, NULL, NULL); 1377c478bd9Sstevel@tonic-gate typedbitfldmems = NULL; 1387c478bd9Sstevel@tonic-gate } 1397c478bd9Sstevel@tonic-gate } 1407c478bd9Sstevel@tonic-gate 1417c478bd9Sstevel@tonic-gate void 1427c478bd9Sstevel@tonic-gate parse_finish(tdata_t *td) 1437c478bd9Sstevel@tonic-gate { 1447c478bd9Sstevel@tonic-gate td->td_nextid = ++faketypenumber; 1457c478bd9Sstevel@tonic-gate } 1467c478bd9Sstevel@tonic-gate 1477c478bd9Sstevel@tonic-gate static tdesc_t * 1487c478bd9Sstevel@tonic-gate unres_new(int tid) 1497c478bd9Sstevel@tonic-gate { 1507c478bd9Sstevel@tonic-gate tdesc_t *tdp; 1517c478bd9Sstevel@tonic-gate 1527c478bd9Sstevel@tonic-gate tdp = xcalloc(sizeof (*tdp)); 1537c478bd9Sstevel@tonic-gate tdp->t_type = TYPEDEF_UNRES; 1547c478bd9Sstevel@tonic-gate tdp->t_id = tid; 1557c478bd9Sstevel@tonic-gate 1567c478bd9Sstevel@tonic-gate return (tdp); 1577c478bd9Sstevel@tonic-gate } 1587c478bd9Sstevel@tonic-gate 1597c478bd9Sstevel@tonic-gate char * 1607c478bd9Sstevel@tonic-gate read_tid(char *cp, tdesc_t **tdpp) 1617c478bd9Sstevel@tonic-gate { 1627c478bd9Sstevel@tonic-gate tdesc_t *tdp; 1637c478bd9Sstevel@tonic-gate int tid; 1647c478bd9Sstevel@tonic-gate 1657c478bd9Sstevel@tonic-gate cp = id(cp, &tid); 1667c478bd9Sstevel@tonic-gate 1677c478bd9Sstevel@tonic-gate assert(tid != 0); 1687c478bd9Sstevel@tonic-gate 1697c478bd9Sstevel@tonic-gate if (*cp == '=') { 1707c478bd9Sstevel@tonic-gate if (!(cp = tdefdecl(cp + 1, tid, &tdp))) 1717c478bd9Sstevel@tonic-gate return (NULL); 1727c478bd9Sstevel@tonic-gate if (tdp->t_id && tdp->t_id != tid) { 1737c478bd9Sstevel@tonic-gate tdesc_t *ntdp = xcalloc(sizeof (*ntdp)); 1747c478bd9Sstevel@tonic-gate 1757c478bd9Sstevel@tonic-gate ntdp->t_type = TYPEDEF; 1767c478bd9Sstevel@tonic-gate ntdp->t_tdesc = tdp; 1777c478bd9Sstevel@tonic-gate tdp = ntdp; 1787c478bd9Sstevel@tonic-gate } 1797c478bd9Sstevel@tonic-gate addhash(tdp, tid); 1807c478bd9Sstevel@tonic-gate } else if ((tdp = lookup(tid)) == NULL) 1817c478bd9Sstevel@tonic-gate tdp = unres_new(tid); 1827c478bd9Sstevel@tonic-gate 1837c478bd9Sstevel@tonic-gate *tdpp = tdp; 1847c478bd9Sstevel@tonic-gate return (cp); 1857c478bd9Sstevel@tonic-gate } 1867c478bd9Sstevel@tonic-gate 1877c478bd9Sstevel@tonic-gate static iitype_t 1887c478bd9Sstevel@tonic-gate parse_fun(char *cp, iidesc_t *ii) 1897c478bd9Sstevel@tonic-gate { 1907c478bd9Sstevel@tonic-gate iitype_t iitype; 1917c478bd9Sstevel@tonic-gate tdesc_t *tdp; 1927c478bd9Sstevel@tonic-gate tdesc_t **args = NULL; 1937c478bd9Sstevel@tonic-gate int nargs = 0; 1947c478bd9Sstevel@tonic-gate int va = 0; 1957c478bd9Sstevel@tonic-gate 1967c478bd9Sstevel@tonic-gate /* 1977c478bd9Sstevel@tonic-gate * name:P prototype 1987c478bd9Sstevel@tonic-gate * name:F global function 1997c478bd9Sstevel@tonic-gate * name:f static function 2007c478bd9Sstevel@tonic-gate */ 2017c478bd9Sstevel@tonic-gate switch (*cp++) { 2027c478bd9Sstevel@tonic-gate case 'P': 2037c478bd9Sstevel@tonic-gate iitype = II_NOT; /* not interesting */ 2047c478bd9Sstevel@tonic-gate break; 2057c478bd9Sstevel@tonic-gate 2067c478bd9Sstevel@tonic-gate case 'F': 2077c478bd9Sstevel@tonic-gate iitype = II_GFUN; 2087c478bd9Sstevel@tonic-gate break; 2097c478bd9Sstevel@tonic-gate 2107c478bd9Sstevel@tonic-gate case 'f': 2117c478bd9Sstevel@tonic-gate iitype = II_SFUN; 2127c478bd9Sstevel@tonic-gate break; 2137c478bd9Sstevel@tonic-gate 2147c478bd9Sstevel@tonic-gate default: 2157c478bd9Sstevel@tonic-gate expected("parse_nfun", "[PfF]", cp - 1); 2167c478bd9Sstevel@tonic-gate } 2177c478bd9Sstevel@tonic-gate 2187c478bd9Sstevel@tonic-gate if (!(cp = read_tid(cp, &tdp))) 2197c478bd9Sstevel@tonic-gate return (-1); 2207c478bd9Sstevel@tonic-gate 2217c478bd9Sstevel@tonic-gate if (*cp) 2227c478bd9Sstevel@tonic-gate args = xmalloc(sizeof (tdesc_t *) * FUNCARG_DEF); 2237c478bd9Sstevel@tonic-gate 2247c478bd9Sstevel@tonic-gate while (*cp && *++cp) { 2257c478bd9Sstevel@tonic-gate if (*cp == '0') { 2267c478bd9Sstevel@tonic-gate va = 1; 2277c478bd9Sstevel@tonic-gate continue; 2287c478bd9Sstevel@tonic-gate } 2297c478bd9Sstevel@tonic-gate 2307c478bd9Sstevel@tonic-gate nargs++; 2317c478bd9Sstevel@tonic-gate if (nargs > FUNCARG_DEF) 2327c478bd9Sstevel@tonic-gate args = xrealloc(args, sizeof (tdesc_t *) * nargs); 2337c478bd9Sstevel@tonic-gate if (!(cp = read_tid(cp, &args[nargs - 1]))) 2347c478bd9Sstevel@tonic-gate return (-1); 2357c478bd9Sstevel@tonic-gate } 2367c478bd9Sstevel@tonic-gate 2377c478bd9Sstevel@tonic-gate ii->ii_type = iitype; 2387c478bd9Sstevel@tonic-gate ii->ii_dtype = tdp; 2397c478bd9Sstevel@tonic-gate ii->ii_nargs = nargs; 2407c478bd9Sstevel@tonic-gate ii->ii_args = args; 2417c478bd9Sstevel@tonic-gate ii->ii_vargs = va; 2427c478bd9Sstevel@tonic-gate 2437c478bd9Sstevel@tonic-gate return (iitype); 2447c478bd9Sstevel@tonic-gate } 2457c478bd9Sstevel@tonic-gate 2467c478bd9Sstevel@tonic-gate static iitype_t 2477c478bd9Sstevel@tonic-gate parse_sym(char *cp, iidesc_t *ii) 2487c478bd9Sstevel@tonic-gate { 2497c478bd9Sstevel@tonic-gate tdesc_t *tdp; 2507c478bd9Sstevel@tonic-gate iitype_t iitype; 2517c478bd9Sstevel@tonic-gate 2527c478bd9Sstevel@tonic-gate /* 2537c478bd9Sstevel@tonic-gate * name:G global variable 2547c478bd9Sstevel@tonic-gate * name:S static variable 2557c478bd9Sstevel@tonic-gate */ 2567c478bd9Sstevel@tonic-gate switch (*cp++) { 2577c478bd9Sstevel@tonic-gate case 'G': 2587c478bd9Sstevel@tonic-gate iitype = II_GVAR; 2597c478bd9Sstevel@tonic-gate break; 2607c478bd9Sstevel@tonic-gate case 'S': 2617c478bd9Sstevel@tonic-gate iitype = II_SVAR; 2627c478bd9Sstevel@tonic-gate break; 2637c478bd9Sstevel@tonic-gate case 'p': 2647c478bd9Sstevel@tonic-gate iitype = II_PSYM; 2657c478bd9Sstevel@tonic-gate break; 2667c478bd9Sstevel@tonic-gate case '(': 2677c478bd9Sstevel@tonic-gate cp--; 2687c478bd9Sstevel@tonic-gate /*FALLTHROUGH*/ 2697c478bd9Sstevel@tonic-gate case 'r': 2707c478bd9Sstevel@tonic-gate case 'V': 2717c478bd9Sstevel@tonic-gate iitype = II_NOT; /* not interesting */ 2727c478bd9Sstevel@tonic-gate break; 2737c478bd9Sstevel@tonic-gate default: 2747c478bd9Sstevel@tonic-gate expected("parse_sym", "[GprSV(]", cp - 1); 2757c478bd9Sstevel@tonic-gate } 2767c478bd9Sstevel@tonic-gate 2777c478bd9Sstevel@tonic-gate if (!(cp = read_tid(cp, &tdp))) 2787c478bd9Sstevel@tonic-gate return (-1); 2797c478bd9Sstevel@tonic-gate 2807c478bd9Sstevel@tonic-gate ii->ii_type = iitype; 2817c478bd9Sstevel@tonic-gate ii->ii_dtype = tdp; 2827c478bd9Sstevel@tonic-gate 2837c478bd9Sstevel@tonic-gate return (iitype); 2847c478bd9Sstevel@tonic-gate } 2857c478bd9Sstevel@tonic-gate 2867c478bd9Sstevel@tonic-gate static iitype_t 2877c478bd9Sstevel@tonic-gate parse_type(char *cp, iidesc_t *ii) 2887c478bd9Sstevel@tonic-gate { 2897c478bd9Sstevel@tonic-gate tdesc_t *tdp, *ntdp; 2907c478bd9Sstevel@tonic-gate int tid; 2917c478bd9Sstevel@tonic-gate 2927c478bd9Sstevel@tonic-gate if (*cp++ != 't') 2937c478bd9Sstevel@tonic-gate expected("parse_type", "t (type)", cp - 1); 2947c478bd9Sstevel@tonic-gate 2957c478bd9Sstevel@tonic-gate cp = id(cp, &tid); 2967c478bd9Sstevel@tonic-gate if ((tdp = lookup(tid)) == NULL) { 2977c478bd9Sstevel@tonic-gate if (*cp++ != '=') 2987c478bd9Sstevel@tonic-gate expected("parse_type", "= (definition)", cp - 1); 2997c478bd9Sstevel@tonic-gate 3007c478bd9Sstevel@tonic-gate (void) tdefdecl(cp, tid, &tdp); 3017c478bd9Sstevel@tonic-gate 3027c478bd9Sstevel@tonic-gate if (tdp->t_id == tid) { 3037c478bd9Sstevel@tonic-gate assert(tdp->t_type != TYPEDEF); 3047c478bd9Sstevel@tonic-gate assert(!lookup(tdp->t_id)); 3057c478bd9Sstevel@tonic-gate 3067c478bd9Sstevel@tonic-gate if (!streq(tdp->t_name, ii->ii_name)) { 3077c478bd9Sstevel@tonic-gate ntdp = xcalloc(sizeof (*ntdp)); 3087c478bd9Sstevel@tonic-gate ntdp->t_name = xstrdup(ii->ii_name); 3097c478bd9Sstevel@tonic-gate ntdp->t_type = TYPEDEF; 3107c478bd9Sstevel@tonic-gate ntdp->t_tdesc = tdp; 3117c478bd9Sstevel@tonic-gate tdp->t_id = faketypenumber++; 3127c478bd9Sstevel@tonic-gate tdp = ntdp; 3137c478bd9Sstevel@tonic-gate } 3147c478bd9Sstevel@tonic-gate } else if (tdp->t_id == 0) { 3157c478bd9Sstevel@tonic-gate assert(tdp->t_type == FORWARD || 3167c478bd9Sstevel@tonic-gate tdp->t_type == INTRINSIC); 3177c478bd9Sstevel@tonic-gate 3187c478bd9Sstevel@tonic-gate if (tdp->t_name && !streq(tdp->t_name, ii->ii_name)) { 3197c478bd9Sstevel@tonic-gate ntdp = xcalloc(sizeof (*ntdp)); 3207c478bd9Sstevel@tonic-gate ntdp->t_name = xstrdup(ii->ii_name); 3217c478bd9Sstevel@tonic-gate ntdp->t_type = TYPEDEF; 3227c478bd9Sstevel@tonic-gate ntdp->t_tdesc = tdp; 3237c478bd9Sstevel@tonic-gate tdp->t_id = faketypenumber++; 3247c478bd9Sstevel@tonic-gate tdp = ntdp; 3257c478bd9Sstevel@tonic-gate } 3267c478bd9Sstevel@tonic-gate } else if (tdp->t_id != tid) { 3277c478bd9Sstevel@tonic-gate ntdp = xcalloc(sizeof (*ntdp)); 3287c478bd9Sstevel@tonic-gate ntdp->t_name = xstrdup(ii->ii_name); 3297c478bd9Sstevel@tonic-gate ntdp->t_type = TYPEDEF; 3307c478bd9Sstevel@tonic-gate ntdp->t_tdesc = tdp; 3317c478bd9Sstevel@tonic-gate tdp = ntdp; 3327c478bd9Sstevel@tonic-gate } 3337c478bd9Sstevel@tonic-gate 3347c478bd9Sstevel@tonic-gate if (tagadd(ii->ii_name, tid, tdp) < 0) 3357c478bd9Sstevel@tonic-gate return (-1); 3367c478bd9Sstevel@tonic-gate } 3377c478bd9Sstevel@tonic-gate 3387c478bd9Sstevel@tonic-gate ii->ii_type = II_TYPE; 3397c478bd9Sstevel@tonic-gate ii->ii_dtype = tdp; 3407c478bd9Sstevel@tonic-gate return (II_TYPE); 3417c478bd9Sstevel@tonic-gate } 3427c478bd9Sstevel@tonic-gate 3437c478bd9Sstevel@tonic-gate static iitype_t 3447c478bd9Sstevel@tonic-gate parse_sou(char *cp, iidesc_t *idp) 3457c478bd9Sstevel@tonic-gate { 3467c478bd9Sstevel@tonic-gate tdesc_t *rtdp; 3477c478bd9Sstevel@tonic-gate int tid; 3487c478bd9Sstevel@tonic-gate 3497c478bd9Sstevel@tonic-gate if (*cp++ != 'T') 3507c478bd9Sstevel@tonic-gate expected("parse_sou", "T (sou)", cp - 1); 3517c478bd9Sstevel@tonic-gate 3527c478bd9Sstevel@tonic-gate cp = id(cp, &tid); 3537c478bd9Sstevel@tonic-gate if (*cp++ != '=') 3547c478bd9Sstevel@tonic-gate expected("parse_sou", "= (definition)", cp - 1); 3557c478bd9Sstevel@tonic-gate 3567c478bd9Sstevel@tonic-gate parse_debug(1, NULL, "parse_sou: declaring '%s'", idp->ii_name ? 3577c478bd9Sstevel@tonic-gate idp->ii_name : "(anon)"); 3587c478bd9Sstevel@tonic-gate if ((rtdp = lookup(tid)) != NULL) { 3597c478bd9Sstevel@tonic-gate if (idp->ii_name != NULL) { 3607c478bd9Sstevel@tonic-gate if (rtdp->t_name != NULL && 3617c478bd9Sstevel@tonic-gate strcmp(rtdp->t_name, idp->ii_name) != 0) { 3627c478bd9Sstevel@tonic-gate tdesc_t *tdp; 3637c478bd9Sstevel@tonic-gate 3647c478bd9Sstevel@tonic-gate tdp = xcalloc(sizeof (*tdp)); 3657c478bd9Sstevel@tonic-gate tdp->t_name = xstrdup(idp->ii_name); 3667c478bd9Sstevel@tonic-gate tdp->t_type = TYPEDEF; 3677c478bd9Sstevel@tonic-gate tdp->t_tdesc = rtdp; 3687c478bd9Sstevel@tonic-gate addhash(tdp, tid); /* for *(x,y) types */ 3697c478bd9Sstevel@tonic-gate parse_debug(3, NULL, " %s defined as %s(%d)", 3704d232658Sjohnlev idp->ii_name, tdesc_name(rtdp), tid); 3717c478bd9Sstevel@tonic-gate } else if (rtdp->t_name == NULL) { 3727c478bd9Sstevel@tonic-gate rtdp->t_name = xstrdup(idp->ii_name); 3737c478bd9Sstevel@tonic-gate addhash(rtdp, tid); 3747c478bd9Sstevel@tonic-gate } 3757c478bd9Sstevel@tonic-gate } 3767c478bd9Sstevel@tonic-gate } else { 3777c478bd9Sstevel@tonic-gate rtdp = xcalloc(sizeof (*rtdp)); 3787c478bd9Sstevel@tonic-gate rtdp->t_name = idp->ii_name ? xstrdup(idp->ii_name) : NULL; 3797c478bd9Sstevel@tonic-gate addhash(rtdp, tid); 3807c478bd9Sstevel@tonic-gate } 3817c478bd9Sstevel@tonic-gate 3827c478bd9Sstevel@tonic-gate switch (*cp++) { 3837c478bd9Sstevel@tonic-gate case 's': 3847c478bd9Sstevel@tonic-gate (void) soudef(cp, STRUCT, &rtdp); 3857c478bd9Sstevel@tonic-gate break; 3867c478bd9Sstevel@tonic-gate case 'u': 3877c478bd9Sstevel@tonic-gate (void) soudef(cp, UNION, &rtdp); 3887c478bd9Sstevel@tonic-gate break; 3897c478bd9Sstevel@tonic-gate case 'e': 3907c478bd9Sstevel@tonic-gate enumdef(cp, &rtdp); 3917c478bd9Sstevel@tonic-gate break; 3927c478bd9Sstevel@tonic-gate default: 3937c478bd9Sstevel@tonic-gate expected("parse_sou", "<tag type s/u/e>", cp - 1); 3947c478bd9Sstevel@tonic-gate break; 3957c478bd9Sstevel@tonic-gate } 3967c478bd9Sstevel@tonic-gate 3977c478bd9Sstevel@tonic-gate idp->ii_type = II_SOU; 3987c478bd9Sstevel@tonic-gate idp->ii_dtype = rtdp; 3997c478bd9Sstevel@tonic-gate return (II_SOU); 4007c478bd9Sstevel@tonic-gate } 4017c478bd9Sstevel@tonic-gate 4027c478bd9Sstevel@tonic-gate int 4037c478bd9Sstevel@tonic-gate parse_stab(stab_t *stab, char *cp, iidesc_t **iidescp) 4047c478bd9Sstevel@tonic-gate { 4057c478bd9Sstevel@tonic-gate iidesc_t *ii = NULL; 4067c478bd9Sstevel@tonic-gate iitype_t (*parse)(char *, iidesc_t *); 4077c478bd9Sstevel@tonic-gate int rc; 4087c478bd9Sstevel@tonic-gate 4097c478bd9Sstevel@tonic-gate /* 4107c478bd9Sstevel@tonic-gate * set up for reset() 4117c478bd9Sstevel@tonic-gate */ 4127c478bd9Sstevel@tonic-gate if (setjmp(resetbuf)) 4137c478bd9Sstevel@tonic-gate return (-1); 4147c478bd9Sstevel@tonic-gate 4157c478bd9Sstevel@tonic-gate cp = whitesp(cp); 4167c478bd9Sstevel@tonic-gate ii = iidesc_new(NULL); 4177c478bd9Sstevel@tonic-gate cp = name(cp, &ii->ii_name); 4187c478bd9Sstevel@tonic-gate 4197c478bd9Sstevel@tonic-gate switch (stab->n_type) { 4207c478bd9Sstevel@tonic-gate case N_FUN: 4217c478bd9Sstevel@tonic-gate parse = parse_fun; 4227c478bd9Sstevel@tonic-gate break; 4237c478bd9Sstevel@tonic-gate 4247c478bd9Sstevel@tonic-gate case N_LSYM: 4257c478bd9Sstevel@tonic-gate if (*cp == 't') 4267c478bd9Sstevel@tonic-gate parse = parse_type; 4277c478bd9Sstevel@tonic-gate else if (*cp == 'T') 4287c478bd9Sstevel@tonic-gate parse = parse_sou; 4297c478bd9Sstevel@tonic-gate else 4307c478bd9Sstevel@tonic-gate parse = parse_sym; 4317c478bd9Sstevel@tonic-gate break; 4327c478bd9Sstevel@tonic-gate 4337c478bd9Sstevel@tonic-gate case N_GSYM: 4347c478bd9Sstevel@tonic-gate case N_LCSYM: 4357c478bd9Sstevel@tonic-gate case N_PSYM: 4367c478bd9Sstevel@tonic-gate case N_ROSYM: 4377c478bd9Sstevel@tonic-gate case N_RSYM: 4387c478bd9Sstevel@tonic-gate case N_STSYM: 4397c478bd9Sstevel@tonic-gate parse = parse_sym; 4407c478bd9Sstevel@tonic-gate break; 4417c478bd9Sstevel@tonic-gate default: 4427c478bd9Sstevel@tonic-gate parse_debug(1, cp, "Unknown stab type %#x", stab->n_type); 4437c478bd9Sstevel@tonic-gate bzero(&resetbuf, sizeof (resetbuf)); 4447c478bd9Sstevel@tonic-gate return (-1); 4457c478bd9Sstevel@tonic-gate } 4467c478bd9Sstevel@tonic-gate 4477c478bd9Sstevel@tonic-gate rc = parse(cp, ii); 4487c478bd9Sstevel@tonic-gate bzero(&resetbuf, sizeof (resetbuf)); 4497c478bd9Sstevel@tonic-gate 4507c478bd9Sstevel@tonic-gate if (rc < 0 || ii->ii_type == II_NOT) { 4517c478bd9Sstevel@tonic-gate iidesc_free(ii, NULL); 4527c478bd9Sstevel@tonic-gate return (rc); 4537c478bd9Sstevel@tonic-gate } 4547c478bd9Sstevel@tonic-gate 4557c478bd9Sstevel@tonic-gate *iidescp = ii; 4567c478bd9Sstevel@tonic-gate 4577c478bd9Sstevel@tonic-gate return (1); 4587c478bd9Sstevel@tonic-gate } 4597c478bd9Sstevel@tonic-gate 4607c478bd9Sstevel@tonic-gate /* 4617c478bd9Sstevel@tonic-gate * Check if we have this node in the hash table already 4627c478bd9Sstevel@tonic-gate */ 4637c478bd9Sstevel@tonic-gate tdesc_t * 4647c478bd9Sstevel@tonic-gate lookup(int h) 4657c478bd9Sstevel@tonic-gate { 4667c478bd9Sstevel@tonic-gate int bucket = HASH(h); 4677c478bd9Sstevel@tonic-gate tdesc_t *tdp = hash_table[bucket]; 4687c478bd9Sstevel@tonic-gate 4697c478bd9Sstevel@tonic-gate while (tdp != NULL) { 4707c478bd9Sstevel@tonic-gate if (tdp->t_id == h) 4717c478bd9Sstevel@tonic-gate return (tdp); 4727c478bd9Sstevel@tonic-gate tdp = tdp->t_hash; 4737c478bd9Sstevel@tonic-gate } 4747c478bd9Sstevel@tonic-gate return (NULL); 4757c478bd9Sstevel@tonic-gate } 4767c478bd9Sstevel@tonic-gate 4777c478bd9Sstevel@tonic-gate static char * 4787c478bd9Sstevel@tonic-gate whitesp(char *cp) 4797c478bd9Sstevel@tonic-gate { 4807c478bd9Sstevel@tonic-gate char c; 4817c478bd9Sstevel@tonic-gate 482970495fcSsn199410 for (c = *cp++; isspace(c); c = *cp++) 483970495fcSsn199410 ; 4847c478bd9Sstevel@tonic-gate --cp; 4857c478bd9Sstevel@tonic-gate return (cp); 4867c478bd9Sstevel@tonic-gate } 4877c478bd9Sstevel@tonic-gate 4887c478bd9Sstevel@tonic-gate static char * 4897c478bd9Sstevel@tonic-gate name(char *cp, char **w) 4907c478bd9Sstevel@tonic-gate { 4917c478bd9Sstevel@tonic-gate char *new, *orig, c; 4927c478bd9Sstevel@tonic-gate int len; 4937c478bd9Sstevel@tonic-gate 4947c478bd9Sstevel@tonic-gate orig = cp; 4957c478bd9Sstevel@tonic-gate c = *cp++; 4967c478bd9Sstevel@tonic-gate if (c == ':') 4977c478bd9Sstevel@tonic-gate *w = NULL; 498970495fcSsn199410 else if (isalpha(c) || strchr("_.$#", c)) { 499970495fcSsn199410 for (c = *cp++; isalnum(c) || strchr(" _.$#", c); c = *cp++) 5007c478bd9Sstevel@tonic-gate ; 5017c478bd9Sstevel@tonic-gate if (c != ':') 5027c478bd9Sstevel@tonic-gate reset(); 5037c478bd9Sstevel@tonic-gate len = cp - orig; 5047c478bd9Sstevel@tonic-gate new = xmalloc(len); 5057c478bd9Sstevel@tonic-gate while (orig < cp - 1) 5067c478bd9Sstevel@tonic-gate *new++ = *orig++; 5077c478bd9Sstevel@tonic-gate *new = '\0'; 5087c478bd9Sstevel@tonic-gate *w = new - (len - 1); 5097c478bd9Sstevel@tonic-gate } else 5107c478bd9Sstevel@tonic-gate reset(); 5117c478bd9Sstevel@tonic-gate 5127c478bd9Sstevel@tonic-gate return (cp); 5137c478bd9Sstevel@tonic-gate } 5147c478bd9Sstevel@tonic-gate 5157c478bd9Sstevel@tonic-gate static char * 5167c478bd9Sstevel@tonic-gate number(char *cp, int *n) 5177c478bd9Sstevel@tonic-gate { 5187c478bd9Sstevel@tonic-gate char *next; 5197c478bd9Sstevel@tonic-gate 5207c478bd9Sstevel@tonic-gate *n = (int)strtol(cp, &next, 10); 5217c478bd9Sstevel@tonic-gate if (next == cp) 5227c478bd9Sstevel@tonic-gate expected("number", "<number>", cp); 5237c478bd9Sstevel@tonic-gate return (next); 5247c478bd9Sstevel@tonic-gate } 5257c478bd9Sstevel@tonic-gate 5267c478bd9Sstevel@tonic-gate static char * 5277c478bd9Sstevel@tonic-gate id(char *cp, int *h) 5287c478bd9Sstevel@tonic-gate { 5297c478bd9Sstevel@tonic-gate int n1, n2; 5307c478bd9Sstevel@tonic-gate 5317c478bd9Sstevel@tonic-gate if (*cp == '(') { /* SunPro style */ 5327c478bd9Sstevel@tonic-gate cp++; 5337c478bd9Sstevel@tonic-gate cp = number(cp, &n1); 5347c478bd9Sstevel@tonic-gate if (*cp++ != ',') 5357c478bd9Sstevel@tonic-gate expected("id", ",", cp - 1); 5367c478bd9Sstevel@tonic-gate cp = number(cp, &n2); 5377c478bd9Sstevel@tonic-gate if (*cp++ != ')') 5387c478bd9Sstevel@tonic-gate expected("id", ")", cp - 1); 5397c478bd9Sstevel@tonic-gate *h = MAKETYPEID(n1, n2); 5407c478bd9Sstevel@tonic-gate } else if (isdigit(*cp)) { /* gcc style */ 5417c478bd9Sstevel@tonic-gate cp = number(cp, &n1); 5427c478bd9Sstevel@tonic-gate *h = n1; 5437c478bd9Sstevel@tonic-gate } else { 5447c478bd9Sstevel@tonic-gate expected("id", "(/0-9", cp); 5457c478bd9Sstevel@tonic-gate } 5467c478bd9Sstevel@tonic-gate return (cp); 5477c478bd9Sstevel@tonic-gate } 5487c478bd9Sstevel@tonic-gate 5497c478bd9Sstevel@tonic-gate static int 5507c478bd9Sstevel@tonic-gate tagadd(char *w, int h, tdesc_t *tdp) 5517c478bd9Sstevel@tonic-gate { 5527c478bd9Sstevel@tonic-gate tdesc_t *otdp; 5537c478bd9Sstevel@tonic-gate 5547c478bd9Sstevel@tonic-gate tdp->t_name = w; 5557c478bd9Sstevel@tonic-gate if (!(otdp = lookup(h))) 5567c478bd9Sstevel@tonic-gate addhash(tdp, h); 5577c478bd9Sstevel@tonic-gate else if (otdp != tdp) { 5587c478bd9Sstevel@tonic-gate warning("duplicate entry\n"); 5594d232658Sjohnlev warning(" old: %s %d (%d,%d)\n", tdesc_name(otdp), 5607c478bd9Sstevel@tonic-gate otdp->t_type, TYPEFILE(otdp->t_id), TYPENUM(otdp->t_id)); 5614d232658Sjohnlev warning(" new: %s %d (%d,%d)\n", tdesc_name(tdp), 5627c478bd9Sstevel@tonic-gate tdp->t_type, TYPEFILE(tdp->t_id), TYPENUM(tdp->t_id)); 5637c478bd9Sstevel@tonic-gate return (-1); 5647c478bd9Sstevel@tonic-gate } 5657c478bd9Sstevel@tonic-gate 5667c478bd9Sstevel@tonic-gate return (0); 5677c478bd9Sstevel@tonic-gate } 5687c478bd9Sstevel@tonic-gate 5697c478bd9Sstevel@tonic-gate static char * 5707c478bd9Sstevel@tonic-gate tdefdecl(char *cp, int h, tdesc_t **rtdp) 5717c478bd9Sstevel@tonic-gate { 5727c478bd9Sstevel@tonic-gate tdesc_t *ntdp; 5737c478bd9Sstevel@tonic-gate char *w; 5747c478bd9Sstevel@tonic-gate int c, h2; 5757c478bd9Sstevel@tonic-gate char type; 5767c478bd9Sstevel@tonic-gate 5777c478bd9Sstevel@tonic-gate parse_debug(3, cp, "tdefdecl h=%d", h); 5787c478bd9Sstevel@tonic-gate 5797c478bd9Sstevel@tonic-gate /* Type codes */ 5807c478bd9Sstevel@tonic-gate switch (type = *cp) { 5817c478bd9Sstevel@tonic-gate case 'b': /* integer */ 5827c478bd9Sstevel@tonic-gate case 'R': /* fp */ 5837c478bd9Sstevel@tonic-gate cp = intrinsic(cp, rtdp); 5847c478bd9Sstevel@tonic-gate break; 5857c478bd9Sstevel@tonic-gate case '(': /* equiv to another type */ 5867c478bd9Sstevel@tonic-gate cp = id(cp, &h2); 5877c478bd9Sstevel@tonic-gate ntdp = lookup(h2); 5887c478bd9Sstevel@tonic-gate 5897c478bd9Sstevel@tonic-gate if (ntdp != NULL && *cp == '=') { 5907c478bd9Sstevel@tonic-gate if (ntdp->t_type == FORWARD && *(cp + 1) == 'x') { 5917c478bd9Sstevel@tonic-gate /* 5927c478bd9Sstevel@tonic-gate * The 6.2 compiler, and possibly others, will 5937c478bd9Sstevel@tonic-gate * sometimes emit the same stab for a forward 5947c478bd9Sstevel@tonic-gate * declaration twice. That is, "(1,2)=xsfoo:" 5957c478bd9Sstevel@tonic-gate * will sometimes show up in two different 5967c478bd9Sstevel@tonic-gate * places. This is, of course, quite fun. We 5977c478bd9Sstevel@tonic-gate * want CTF to work in spite of the compiler, 5987c478bd9Sstevel@tonic-gate * so we'll let this one through. 5997c478bd9Sstevel@tonic-gate */ 6007c478bd9Sstevel@tonic-gate char *c2 = cp + 2; 6017c478bd9Sstevel@tonic-gate char *nm; 6027c478bd9Sstevel@tonic-gate 6037c478bd9Sstevel@tonic-gate if (!strchr("sue", *c2++)) { 6047c478bd9Sstevel@tonic-gate expected("tdefdecl/x-redefine", "[sue]", 6057c478bd9Sstevel@tonic-gate c2 - 1); 6067c478bd9Sstevel@tonic-gate } 6077c478bd9Sstevel@tonic-gate 6087c478bd9Sstevel@tonic-gate c2 = name(c2, &nm); 6097c478bd9Sstevel@tonic-gate if (strcmp(nm, ntdp->t_name) != 0) { 6107c478bd9Sstevel@tonic-gate terminate("Stabs error: Attempt to " 6117c478bd9Sstevel@tonic-gate "redefine type (%d,%d) as " 6127c478bd9Sstevel@tonic-gate "something else: %s\n", 6137c478bd9Sstevel@tonic-gate TYPEFILE(h2), TYPENUM(h2), 6147c478bd9Sstevel@tonic-gate c2 - 1); 6157c478bd9Sstevel@tonic-gate } 6167c478bd9Sstevel@tonic-gate free(nm); 6177c478bd9Sstevel@tonic-gate 6187c478bd9Sstevel@tonic-gate h2 = faketypenumber++; 6197c478bd9Sstevel@tonic-gate ntdp = NULL; 6207c478bd9Sstevel@tonic-gate } else { 6217c478bd9Sstevel@tonic-gate terminate("Stabs error: Attempting to " 6227c478bd9Sstevel@tonic-gate "redefine type (%d,%d)\n", TYPEFILE(h2), 6237c478bd9Sstevel@tonic-gate TYPENUM(h2)); 6247c478bd9Sstevel@tonic-gate } 6257c478bd9Sstevel@tonic-gate } 6267c478bd9Sstevel@tonic-gate 6277c478bd9Sstevel@tonic-gate if (ntdp == NULL) { /* if that type isn't defined yet */ 6287c478bd9Sstevel@tonic-gate if (*cp != '=') { 6297c478bd9Sstevel@tonic-gate /* record it as unresolved */ 6307c478bd9Sstevel@tonic-gate parse_debug(3, NULL, "tdefdecl unres type %d", 6317c478bd9Sstevel@tonic-gate h2); 6327c478bd9Sstevel@tonic-gate *rtdp = calloc(sizeof (**rtdp), 1); 6337c478bd9Sstevel@tonic-gate (*rtdp)->t_type = TYPEDEF_UNRES; 6347c478bd9Sstevel@tonic-gate (*rtdp)->t_id = h2; 6357c478bd9Sstevel@tonic-gate break; 6367c478bd9Sstevel@tonic-gate } else 6377c478bd9Sstevel@tonic-gate cp++; 6387c478bd9Sstevel@tonic-gate 6397c478bd9Sstevel@tonic-gate /* define a new type */ 6407c478bd9Sstevel@tonic-gate cp = tdefdecl(cp, h2, rtdp); 6417c478bd9Sstevel@tonic-gate if ((*rtdp)->t_id && (*rtdp)->t_id != h2) { 6427c478bd9Sstevel@tonic-gate ntdp = calloc(sizeof (*ntdp), 1); 6437c478bd9Sstevel@tonic-gate ntdp->t_type = TYPEDEF; 6447c478bd9Sstevel@tonic-gate ntdp->t_tdesc = *rtdp; 6457c478bd9Sstevel@tonic-gate *rtdp = ntdp; 6467c478bd9Sstevel@tonic-gate } 6477c478bd9Sstevel@tonic-gate 6487c478bd9Sstevel@tonic-gate addhash(*rtdp, h2); 6497c478bd9Sstevel@tonic-gate 6507c478bd9Sstevel@tonic-gate } else { /* that type is already defined */ 6517c478bd9Sstevel@tonic-gate if (ntdp->t_type != TYPEDEF || ntdp->t_name != NULL) { 6527c478bd9Sstevel@tonic-gate *rtdp = ntdp; 6537c478bd9Sstevel@tonic-gate } else { 6547c478bd9Sstevel@tonic-gate parse_debug(3, NULL, 6557c478bd9Sstevel@tonic-gate "No duplicate typedef anon for ref"); 6567c478bd9Sstevel@tonic-gate *rtdp = ntdp; 6577c478bd9Sstevel@tonic-gate } 6587c478bd9Sstevel@tonic-gate } 6597c478bd9Sstevel@tonic-gate break; 6607c478bd9Sstevel@tonic-gate case '*': 6617c478bd9Sstevel@tonic-gate ntdp = NULL; 6627c478bd9Sstevel@tonic-gate cp = tdefdecl(cp + 1, h, &ntdp); 6637c478bd9Sstevel@tonic-gate if (ntdp == NULL) 6647c478bd9Sstevel@tonic-gate expected("tdefdecl/*", "id", cp); 6657c478bd9Sstevel@tonic-gate 6667c478bd9Sstevel@tonic-gate if (!ntdp->t_id) 6677c478bd9Sstevel@tonic-gate ntdp->t_id = faketypenumber++; 6687c478bd9Sstevel@tonic-gate 6697c478bd9Sstevel@tonic-gate *rtdp = xcalloc(sizeof (**rtdp)); 6707c478bd9Sstevel@tonic-gate (*rtdp)->t_type = POINTER; 6717c478bd9Sstevel@tonic-gate (*rtdp)->t_size = 0; 6727c478bd9Sstevel@tonic-gate (*rtdp)->t_id = h; 6737c478bd9Sstevel@tonic-gate (*rtdp)->t_tdesc = ntdp; 6747c478bd9Sstevel@tonic-gate break; 6757c478bd9Sstevel@tonic-gate case 'f': 6767c478bd9Sstevel@tonic-gate cp = tdefdecl(cp + 1, h, &ntdp); 6777c478bd9Sstevel@tonic-gate *rtdp = xcalloc(sizeof (**rtdp)); 6787c478bd9Sstevel@tonic-gate (*rtdp)->t_type = FUNCTION; 6797c478bd9Sstevel@tonic-gate (*rtdp)->t_size = 0; 6807c478bd9Sstevel@tonic-gate (*rtdp)->t_id = h; 6817c478bd9Sstevel@tonic-gate (*rtdp)->t_fndef = xcalloc(sizeof (fndef_t)); 6827c478bd9Sstevel@tonic-gate /* 6837c478bd9Sstevel@tonic-gate * The 6.1 compiler will sometimes generate incorrect stabs for 6847c478bd9Sstevel@tonic-gate * function pointers (it'll get the return type wrong). This 6857c478bd9Sstevel@tonic-gate * causes merges to fail. We therefore treat function pointers 6867c478bd9Sstevel@tonic-gate * as if they all point to functions that return int. When 6877c478bd9Sstevel@tonic-gate * 4432549 is fixed, the lookupname() call below should be 6887c478bd9Sstevel@tonic-gate * replaced with `ntdp'. 6897c478bd9Sstevel@tonic-gate */ 6907c478bd9Sstevel@tonic-gate (*rtdp)->t_fndef->fn_ret = lookupname("int"); 6917c478bd9Sstevel@tonic-gate break; 6927c478bd9Sstevel@tonic-gate case 'a': 6937c478bd9Sstevel@tonic-gate case 'z': 6947c478bd9Sstevel@tonic-gate cp++; 6957c478bd9Sstevel@tonic-gate if (*cp++ != 'r') 6967c478bd9Sstevel@tonic-gate expected("tdefdecl/[az]", "r", cp - 1); 6977c478bd9Sstevel@tonic-gate *rtdp = xcalloc(sizeof (**rtdp)); 6987c478bd9Sstevel@tonic-gate (*rtdp)->t_type = ARRAY; 6997c478bd9Sstevel@tonic-gate (*rtdp)->t_id = h; 7007c478bd9Sstevel@tonic-gate cp = arraydef(cp, rtdp); 7017c478bd9Sstevel@tonic-gate break; 7027c478bd9Sstevel@tonic-gate case 'x': 7037c478bd9Sstevel@tonic-gate c = *++cp; 7047c478bd9Sstevel@tonic-gate if (c != 's' && c != 'u' && c != 'e') 7057c478bd9Sstevel@tonic-gate expected("tdefdecl/x", "[sue]", cp - 1); 7067c478bd9Sstevel@tonic-gate cp = name(cp + 1, &w); 7077c478bd9Sstevel@tonic-gate 7087c478bd9Sstevel@tonic-gate ntdp = xcalloc(sizeof (*ntdp)); 7097c478bd9Sstevel@tonic-gate ntdp->t_type = FORWARD; 7107c478bd9Sstevel@tonic-gate ntdp->t_name = w; 7117c478bd9Sstevel@tonic-gate /* 7127c478bd9Sstevel@tonic-gate * We explicitly don't set t_id here - the caller will do it. 7137c478bd9Sstevel@tonic-gate * The caller may want to use a real type ID, or they may 7147c478bd9Sstevel@tonic-gate * choose to make one up. 7157c478bd9Sstevel@tonic-gate */ 7167c478bd9Sstevel@tonic-gate 7177c478bd9Sstevel@tonic-gate *rtdp = ntdp; 7187c478bd9Sstevel@tonic-gate break; 7197c478bd9Sstevel@tonic-gate 7207c478bd9Sstevel@tonic-gate case 'B': /* volatile */ 7217c478bd9Sstevel@tonic-gate cp = tdefdecl(cp + 1, h, &ntdp); 7227c478bd9Sstevel@tonic-gate 7237c478bd9Sstevel@tonic-gate if (!ntdp->t_id) 7247c478bd9Sstevel@tonic-gate ntdp->t_id = faketypenumber++; 7257c478bd9Sstevel@tonic-gate 7267c478bd9Sstevel@tonic-gate *rtdp = xcalloc(sizeof (**rtdp)); 7277c478bd9Sstevel@tonic-gate (*rtdp)->t_type = VOLATILE; 7287c478bd9Sstevel@tonic-gate (*rtdp)->t_size = 0; 7297c478bd9Sstevel@tonic-gate (*rtdp)->t_tdesc = ntdp; 7307c478bd9Sstevel@tonic-gate (*rtdp)->t_id = h; 7317c478bd9Sstevel@tonic-gate break; 7327c478bd9Sstevel@tonic-gate 7337c478bd9Sstevel@tonic-gate case 'k': /* const */ 7347c478bd9Sstevel@tonic-gate cp = tdefdecl(cp + 1, h, &ntdp); 7357c478bd9Sstevel@tonic-gate 7367c478bd9Sstevel@tonic-gate if (!ntdp->t_id) 7377c478bd9Sstevel@tonic-gate ntdp->t_id = faketypenumber++; 7387c478bd9Sstevel@tonic-gate 7397c478bd9Sstevel@tonic-gate *rtdp = xcalloc(sizeof (**rtdp)); 7407c478bd9Sstevel@tonic-gate (*rtdp)->t_type = CONST; 7417c478bd9Sstevel@tonic-gate (*rtdp)->t_size = 0; 7427c478bd9Sstevel@tonic-gate (*rtdp)->t_tdesc = ntdp; 7437c478bd9Sstevel@tonic-gate (*rtdp)->t_id = h; 7447c478bd9Sstevel@tonic-gate break; 7457c478bd9Sstevel@tonic-gate 7467c478bd9Sstevel@tonic-gate case 'K': /* restricted */ 7477c478bd9Sstevel@tonic-gate cp = tdefdecl(cp + 1, h, &ntdp); 7487c478bd9Sstevel@tonic-gate 7497c478bd9Sstevel@tonic-gate if (!ntdp->t_id) 7507c478bd9Sstevel@tonic-gate ntdp->t_id = faketypenumber++; 7517c478bd9Sstevel@tonic-gate 7527c478bd9Sstevel@tonic-gate *rtdp = xcalloc(sizeof (**rtdp)); 7537c478bd9Sstevel@tonic-gate (*rtdp)->t_type = RESTRICT; 7547c478bd9Sstevel@tonic-gate (*rtdp)->t_size = 0; 7557c478bd9Sstevel@tonic-gate (*rtdp)->t_tdesc = ntdp; 7567c478bd9Sstevel@tonic-gate (*rtdp)->t_id = h; 7577c478bd9Sstevel@tonic-gate break; 7587c478bd9Sstevel@tonic-gate 7597c478bd9Sstevel@tonic-gate case 'u': 7607c478bd9Sstevel@tonic-gate case 's': 7617c478bd9Sstevel@tonic-gate cp++; 7627c478bd9Sstevel@tonic-gate 7637c478bd9Sstevel@tonic-gate *rtdp = xcalloc(sizeof (**rtdp)); 7647c478bd9Sstevel@tonic-gate (*rtdp)->t_name = NULL; 7657c478bd9Sstevel@tonic-gate cp = soudef(cp, (type == 'u') ? UNION : STRUCT, rtdp); 7667c478bd9Sstevel@tonic-gate break; 7677c478bd9Sstevel@tonic-gate default: 7687c478bd9Sstevel@tonic-gate expected("tdefdecl", "<type code>", cp); 7697c478bd9Sstevel@tonic-gate } 7707c478bd9Sstevel@tonic-gate return (cp); 7717c478bd9Sstevel@tonic-gate } 7727c478bd9Sstevel@tonic-gate 7737c478bd9Sstevel@tonic-gate static char * 7747c478bd9Sstevel@tonic-gate intrinsic(char *cp, tdesc_t **rtdp) 7757c478bd9Sstevel@tonic-gate { 7767c478bd9Sstevel@tonic-gate intr_t *intr = xcalloc(sizeof (intr_t)); 7777c478bd9Sstevel@tonic-gate tdesc_t *tdp; 7787c478bd9Sstevel@tonic-gate int width, fmt, i; 7797c478bd9Sstevel@tonic-gate 7807c478bd9Sstevel@tonic-gate switch (*cp++) { 7817c478bd9Sstevel@tonic-gate case 'b': 7827c478bd9Sstevel@tonic-gate intr->intr_type = INTR_INT; 7837c478bd9Sstevel@tonic-gate if (*cp == 's') 7847c478bd9Sstevel@tonic-gate intr->intr_signed = 1; 7857c478bd9Sstevel@tonic-gate else if (*cp != 'u') 7867c478bd9Sstevel@tonic-gate expected("intrinsic/b", "[su]", cp); 7877c478bd9Sstevel@tonic-gate cp++; 7887c478bd9Sstevel@tonic-gate 7897c478bd9Sstevel@tonic-gate if (strchr("cbv", *cp)) 7907c478bd9Sstevel@tonic-gate intr->intr_iformat = *cp++; 7917c478bd9Sstevel@tonic-gate 7927c478bd9Sstevel@tonic-gate cp = number(cp, &width); 7937c478bd9Sstevel@tonic-gate if (*cp++ != ';') 7947c478bd9Sstevel@tonic-gate expected("intrinsic/b", "; (post-width)", cp - 1); 7957c478bd9Sstevel@tonic-gate 7967c478bd9Sstevel@tonic-gate cp = number(cp, &intr->intr_offset); 7977c478bd9Sstevel@tonic-gate if (*cp++ != ';') 7987c478bd9Sstevel@tonic-gate expected("intrinsic/b", "; (post-offset)", cp - 1); 7997c478bd9Sstevel@tonic-gate 8007c478bd9Sstevel@tonic-gate cp = number(cp, &intr->intr_nbits); 8017c478bd9Sstevel@tonic-gate break; 8027c478bd9Sstevel@tonic-gate 8037c478bd9Sstevel@tonic-gate case 'R': 8047c478bd9Sstevel@tonic-gate intr->intr_type = INTR_REAL; 8057c478bd9Sstevel@tonic-gate for (fmt = 0, i = 0; isdigit(*(cp + i)); i++) 8067c478bd9Sstevel@tonic-gate fmt = fmt * 10 + (*(cp + i) - '0'); 8077c478bd9Sstevel@tonic-gate 8087c478bd9Sstevel@tonic-gate if (fmt < 1 || fmt > CTF_FP_MAX) 8097c478bd9Sstevel@tonic-gate expected("intrinsic/R", "number <= CTF_FP_MAX", cp); 8107c478bd9Sstevel@tonic-gate 8117c478bd9Sstevel@tonic-gate intr->intr_fformat = fmt; 8127c478bd9Sstevel@tonic-gate cp += i; 8137c478bd9Sstevel@tonic-gate 8147c478bd9Sstevel@tonic-gate if (*cp++ != ';') 8157c478bd9Sstevel@tonic-gate expected("intrinsic/R", ";", cp - 1); 8167c478bd9Sstevel@tonic-gate cp = number(cp, &width); 8177c478bd9Sstevel@tonic-gate 8187c478bd9Sstevel@tonic-gate intr->intr_nbits = width * 8; 8197c478bd9Sstevel@tonic-gate break; 8207c478bd9Sstevel@tonic-gate } 8217c478bd9Sstevel@tonic-gate 8227c478bd9Sstevel@tonic-gate tdp = xcalloc(sizeof (*tdp)); 8237c478bd9Sstevel@tonic-gate tdp->t_type = INTRINSIC; 8247c478bd9Sstevel@tonic-gate tdp->t_size = width; 8257c478bd9Sstevel@tonic-gate tdp->t_name = NULL; 8267c478bd9Sstevel@tonic-gate tdp->t_intr = intr; 8277c478bd9Sstevel@tonic-gate parse_debug(3, NULL, "intrinsic: size=%d", width); 8287c478bd9Sstevel@tonic-gate *rtdp = tdp; 8297c478bd9Sstevel@tonic-gate 8307c478bd9Sstevel@tonic-gate return (cp); 8317c478bd9Sstevel@tonic-gate } 8327c478bd9Sstevel@tonic-gate 8337c478bd9Sstevel@tonic-gate static tdesc_t * 8347c478bd9Sstevel@tonic-gate bitintrinsic(tdesc_t *template, int nbits) 8357c478bd9Sstevel@tonic-gate { 8367c478bd9Sstevel@tonic-gate tdesc_t *newtdp = xcalloc(sizeof (tdesc_t)); 8377c478bd9Sstevel@tonic-gate 8387c478bd9Sstevel@tonic-gate newtdp->t_name = xstrdup(template->t_name); 8397c478bd9Sstevel@tonic-gate newtdp->t_id = faketypenumber++; 8407c478bd9Sstevel@tonic-gate newtdp->t_type = INTRINSIC; 8417c478bd9Sstevel@tonic-gate newtdp->t_size = template->t_size; 8427c478bd9Sstevel@tonic-gate newtdp->t_intr = xmalloc(sizeof (intr_t)); 8437c478bd9Sstevel@tonic-gate bcopy(template->t_intr, newtdp->t_intr, sizeof (intr_t)); 8447c478bd9Sstevel@tonic-gate newtdp->t_intr->intr_nbits = nbits; 8457c478bd9Sstevel@tonic-gate 8467c478bd9Sstevel@tonic-gate return (newtdp); 8477c478bd9Sstevel@tonic-gate } 8487c478bd9Sstevel@tonic-gate 8497c478bd9Sstevel@tonic-gate static char * 8507c478bd9Sstevel@tonic-gate offsize(char *cp, mlist_t *mlp) 8517c478bd9Sstevel@tonic-gate { 8527c478bd9Sstevel@tonic-gate int offset, size; 8537c478bd9Sstevel@tonic-gate 8547c478bd9Sstevel@tonic-gate if (*cp == ',') 8557c478bd9Sstevel@tonic-gate cp++; 8567c478bd9Sstevel@tonic-gate cp = number(cp, &offset); 8577c478bd9Sstevel@tonic-gate if (*cp++ != ',') 8587c478bd9Sstevel@tonic-gate expected("offsize/2", ",", cp - 1); 8597c478bd9Sstevel@tonic-gate cp = number(cp, &size); 8607c478bd9Sstevel@tonic-gate if (*cp++ != ';') 8617c478bd9Sstevel@tonic-gate expected("offsize/3", ";", cp - 1); 8627c478bd9Sstevel@tonic-gate mlp->ml_offset = offset; 8637c478bd9Sstevel@tonic-gate mlp->ml_size = size; 8647c478bd9Sstevel@tonic-gate return (cp); 8657c478bd9Sstevel@tonic-gate } 8667c478bd9Sstevel@tonic-gate 8677c478bd9Sstevel@tonic-gate static tdesc_t * 8687c478bd9Sstevel@tonic-gate find_intrinsic(tdesc_t *tdp) 8697c478bd9Sstevel@tonic-gate { 8707c478bd9Sstevel@tonic-gate for (;;) { 8717c478bd9Sstevel@tonic-gate switch (tdp->t_type) { 8727c478bd9Sstevel@tonic-gate case TYPEDEF: 8737c478bd9Sstevel@tonic-gate case VOLATILE: 8747c478bd9Sstevel@tonic-gate case CONST: 8757c478bd9Sstevel@tonic-gate case RESTRICT: 8767c478bd9Sstevel@tonic-gate tdp = tdp->t_tdesc; 8777c478bd9Sstevel@tonic-gate break; 8787c478bd9Sstevel@tonic-gate 8797c478bd9Sstevel@tonic-gate default: 8807c478bd9Sstevel@tonic-gate return (tdp); 8817c478bd9Sstevel@tonic-gate } 8827c478bd9Sstevel@tonic-gate } 8837c478bd9Sstevel@tonic-gate } 8847c478bd9Sstevel@tonic-gate 8857c478bd9Sstevel@tonic-gate static char * 8867c478bd9Sstevel@tonic-gate soudef(char *cp, stabtype_t type, tdesc_t **rtdp) 8877c478bd9Sstevel@tonic-gate { 8887c478bd9Sstevel@tonic-gate mlist_t *mlp, **prev; 8897c478bd9Sstevel@tonic-gate char *w; 8907c478bd9Sstevel@tonic-gate int h; 8917c478bd9Sstevel@tonic-gate int size; 8927c478bd9Sstevel@tonic-gate tdesc_t *tdp, *itdp; 8937c478bd9Sstevel@tonic-gate 8947c478bd9Sstevel@tonic-gate cp = number(cp, &size); 8957c478bd9Sstevel@tonic-gate (*rtdp)->t_size = size; 8967c478bd9Sstevel@tonic-gate (*rtdp)->t_type = type; /* s or u */ 8977c478bd9Sstevel@tonic-gate 8987c478bd9Sstevel@tonic-gate /* 8997c478bd9Sstevel@tonic-gate * An '@' here indicates a bitmask follows. This is so the 9007c478bd9Sstevel@tonic-gate * compiler can pass information to debuggers about how structures 9017c478bd9Sstevel@tonic-gate * are passed in the v9 world. We don't need this information 9027c478bd9Sstevel@tonic-gate * so we skip over it. 9037c478bd9Sstevel@tonic-gate */ 9047c478bd9Sstevel@tonic-gate if (cp[0] == '@') { 9057c478bd9Sstevel@tonic-gate cp += 3; 9067c478bd9Sstevel@tonic-gate } 9077c478bd9Sstevel@tonic-gate 9084d232658Sjohnlev parse_debug(3, cp, "soudef: %s size=%d", tdesc_name(*rtdp), 9097c478bd9Sstevel@tonic-gate (*rtdp)->t_size); 9107c478bd9Sstevel@tonic-gate 9117c478bd9Sstevel@tonic-gate prev = &((*rtdp)->t_members); 9127c478bd9Sstevel@tonic-gate /* now fill up the fields */ 9137c478bd9Sstevel@tonic-gate while ((*cp != '\0') && (*cp != ';')) { /* signifies end of fields */ 9147c478bd9Sstevel@tonic-gate mlp = xcalloc(sizeof (*mlp)); 9157c478bd9Sstevel@tonic-gate *prev = mlp; 9167c478bd9Sstevel@tonic-gate cp = name(cp, &w); 9177c478bd9Sstevel@tonic-gate mlp->ml_name = w; 9187c478bd9Sstevel@tonic-gate cp = id(cp, &h); 9197c478bd9Sstevel@tonic-gate /* 9207c478bd9Sstevel@tonic-gate * find the tdesc struct in the hash table for this type 9217c478bd9Sstevel@tonic-gate * and stick a ptr in here 9227c478bd9Sstevel@tonic-gate */ 9237c478bd9Sstevel@tonic-gate tdp = lookup(h); 9247c478bd9Sstevel@tonic-gate if (tdp == NULL) { /* not in hash list */ 9257c478bd9Sstevel@tonic-gate parse_debug(3, NULL, " defines %s (%d)", w, h); 9267c478bd9Sstevel@tonic-gate if (*cp++ != '=') { 9277c478bd9Sstevel@tonic-gate tdp = unres_new(h); 9287c478bd9Sstevel@tonic-gate parse_debug(3, NULL, 9297c478bd9Sstevel@tonic-gate " refers to %s (unresolved %d)", 9307c478bd9Sstevel@tonic-gate (w ? w : "anon"), h); 9317c478bd9Sstevel@tonic-gate } else { 9327c478bd9Sstevel@tonic-gate cp = tdefdecl(cp, h, &tdp); 9337c478bd9Sstevel@tonic-gate 9347c478bd9Sstevel@tonic-gate if (tdp->t_id && tdp->t_id != h) { 9357c478bd9Sstevel@tonic-gate tdesc_t *ntdp = xcalloc(sizeof (*ntdp)); 9367c478bd9Sstevel@tonic-gate 9377c478bd9Sstevel@tonic-gate ntdp->t_type = TYPEDEF; 9387c478bd9Sstevel@tonic-gate ntdp->t_tdesc = tdp; 9397c478bd9Sstevel@tonic-gate tdp = ntdp; 9407c478bd9Sstevel@tonic-gate } 9417c478bd9Sstevel@tonic-gate 9427c478bd9Sstevel@tonic-gate addhash(tdp, h); 9437c478bd9Sstevel@tonic-gate parse_debug(4, cp, 9447c478bd9Sstevel@tonic-gate " soudef now looking at "); 9457c478bd9Sstevel@tonic-gate cp++; 9467c478bd9Sstevel@tonic-gate } 9477c478bd9Sstevel@tonic-gate } else { 9487c478bd9Sstevel@tonic-gate parse_debug(3, NULL, " refers to %s (%d, %s)", 9494d232658Sjohnlev w ? w : "anon", h, tdesc_name(tdp)); 9507c478bd9Sstevel@tonic-gate } 9517c478bd9Sstevel@tonic-gate 9527c478bd9Sstevel@tonic-gate cp = offsize(cp, mlp); 9537c478bd9Sstevel@tonic-gate 9547c478bd9Sstevel@tonic-gate itdp = find_intrinsic(tdp); 9557c478bd9Sstevel@tonic-gate if (itdp->t_type == INTRINSIC) { 9567c478bd9Sstevel@tonic-gate if (mlp->ml_size != itdp->t_intr->intr_nbits) { 9577c478bd9Sstevel@tonic-gate parse_debug(4, cp, "making %d bit intrinsic " 9584d232658Sjohnlev "from %s", mlp->ml_size, tdesc_name(itdp)); 9597c478bd9Sstevel@tonic-gate mlp->ml_type = bitintrinsic(itdp, mlp->ml_size); 9607c478bd9Sstevel@tonic-gate } else 9617c478bd9Sstevel@tonic-gate mlp->ml_type = tdp; 9627c478bd9Sstevel@tonic-gate } else if (itdp->t_type == TYPEDEF_UNRES) { 9637c478bd9Sstevel@tonic-gate list_add(&typedbitfldmems, mlp); 9647c478bd9Sstevel@tonic-gate mlp->ml_type = tdp; 9657c478bd9Sstevel@tonic-gate } else { 9667c478bd9Sstevel@tonic-gate mlp->ml_type = tdp; 9677c478bd9Sstevel@tonic-gate } 9687c478bd9Sstevel@tonic-gate 9697c478bd9Sstevel@tonic-gate /* cp is now pointing to next field */ 9707c478bd9Sstevel@tonic-gate prev = &mlp->ml_next; 9717c478bd9Sstevel@tonic-gate } 9727c478bd9Sstevel@tonic-gate return (cp); 9737c478bd9Sstevel@tonic-gate } 9747c478bd9Sstevel@tonic-gate 9757c478bd9Sstevel@tonic-gate static char * 9767c478bd9Sstevel@tonic-gate arraydef(char *cp, tdesc_t **rtdp) 9777c478bd9Sstevel@tonic-gate { 9787c478bd9Sstevel@tonic-gate int start, end, h; 9797c478bd9Sstevel@tonic-gate 9807c478bd9Sstevel@tonic-gate cp = id(cp, &h); 9817c478bd9Sstevel@tonic-gate if (*cp++ != ';') 9827c478bd9Sstevel@tonic-gate expected("arraydef/1", ";", cp - 1); 9837c478bd9Sstevel@tonic-gate 9847c478bd9Sstevel@tonic-gate (*rtdp)->t_ardef = xcalloc(sizeof (ardef_t)); 9857c478bd9Sstevel@tonic-gate (*rtdp)->t_ardef->ad_idxtype = lookup(h); 9867c478bd9Sstevel@tonic-gate 9877c478bd9Sstevel@tonic-gate cp = number(cp, &start); /* lower */ 9887c478bd9Sstevel@tonic-gate if (*cp++ != ';') 9897c478bd9Sstevel@tonic-gate expected("arraydef/2", ";", cp - 1); 9907c478bd9Sstevel@tonic-gate 9917c478bd9Sstevel@tonic-gate if (*cp == 'S') { 992*53fb31f0SSurya Prakki /* 993*53fb31f0SSurya Prakki * variable length array - treat as null dimensioned 994*53fb31f0SSurya Prakki * 995*53fb31f0SSurya Prakki * For VLA variables on sparc, SS12 generated stab entry 996*53fb31f0SSurya Prakki * looks as follows: 997*53fb31f0SSurya Prakki * .stabs "buf:(0,28)=zr(0,4);0;S-12;(0,1)", 0x80, 0, 0, -16 998*53fb31f0SSurya Prakki * Whereas SS12u1 generated stab entry looks like this: 999*53fb31f0SSurya Prakki * .stabs "buf:(0,28)=zr(0,4);0;S0;(0,1)", 0x80, 0, 0, 0 1000*53fb31f0SSurya Prakki * On x86, both versions generate the first type of entry. 1001*53fb31f0SSurya Prakki * We should be able to parse both. 1002*53fb31f0SSurya Prakki */ 10037c478bd9Sstevel@tonic-gate cp++; 1004*53fb31f0SSurya Prakki if (*cp == '-') 1005*53fb31f0SSurya Prakki cp++; 10067c478bd9Sstevel@tonic-gate cp = number(cp, &end); 10077c478bd9Sstevel@tonic-gate end = start; 10087c478bd9Sstevel@tonic-gate } else { 1009*53fb31f0SSurya Prakki /* 1010*53fb31f0SSurya Prakki * normal fixed-dimension array 1011*53fb31f0SSurya Prakki * Stab entry for this looks as follows : 1012*53fb31f0SSurya Prakki * .stabs "x:(0,28)=ar(0,4);0;9;(0,3)", 0x80, 0, 40, 0 1013*53fb31f0SSurya Prakki */ 10147c478bd9Sstevel@tonic-gate cp = number(cp, &end); /* upper */ 10157c478bd9Sstevel@tonic-gate } 10167c478bd9Sstevel@tonic-gate 10177c478bd9Sstevel@tonic-gate if (*cp++ != ';') 10187c478bd9Sstevel@tonic-gate expected("arraydef/3", ";", cp - 1); 10197c478bd9Sstevel@tonic-gate (*rtdp)->t_ardef->ad_nelems = end - start + 1; 10207c478bd9Sstevel@tonic-gate cp = tdefdecl(cp, h, &((*rtdp)->t_ardef->ad_contents)); 10217c478bd9Sstevel@tonic-gate 10227c478bd9Sstevel@tonic-gate parse_debug(3, cp, "defined array idx type %d %d-%d next ", 10237c478bd9Sstevel@tonic-gate h, start, end); 10247c478bd9Sstevel@tonic-gate 10257c478bd9Sstevel@tonic-gate return (cp); 10267c478bd9Sstevel@tonic-gate } 10277c478bd9Sstevel@tonic-gate 10287c478bd9Sstevel@tonic-gate static void 10297c478bd9Sstevel@tonic-gate enumdef(char *cp, tdesc_t **rtdp) 10307c478bd9Sstevel@tonic-gate { 10317c478bd9Sstevel@tonic-gate elist_t *elp, **prev; 10327c478bd9Sstevel@tonic-gate char *w; 10337c478bd9Sstevel@tonic-gate 10347c478bd9Sstevel@tonic-gate (*rtdp)->t_type = ENUM; 10357c478bd9Sstevel@tonic-gate (*rtdp)->t_emem = NULL; 10367c478bd9Sstevel@tonic-gate 10377c478bd9Sstevel@tonic-gate prev = &((*rtdp)->t_emem); 10387c478bd9Sstevel@tonic-gate while (*cp != ';') { 10397c478bd9Sstevel@tonic-gate elp = xcalloc(sizeof (*elp)); 10407c478bd9Sstevel@tonic-gate elp->el_next = NULL; 10417c478bd9Sstevel@tonic-gate *prev = elp; 10427c478bd9Sstevel@tonic-gate cp = name(cp, &w); 10437c478bd9Sstevel@tonic-gate elp->el_name = w; 10447c478bd9Sstevel@tonic-gate cp = number(cp, &elp->el_number); 10454d232658Sjohnlev parse_debug(3, NULL, "enum %s: %s=%d", tdesc_name(*rtdp), 10467c478bd9Sstevel@tonic-gate elp->el_name, elp->el_number); 10477c478bd9Sstevel@tonic-gate prev = &elp->el_next; 10487c478bd9Sstevel@tonic-gate if (*cp++ != ',') 10497c478bd9Sstevel@tonic-gate expected("enumdef", ",", cp - 1); 10507c478bd9Sstevel@tonic-gate } 10517c478bd9Sstevel@tonic-gate } 10527c478bd9Sstevel@tonic-gate 10537c478bd9Sstevel@tonic-gate tdesc_t * 1054e824d57fSjohnlev lookup_name(tdesc_t **hash, const char *name) 10557c478bd9Sstevel@tonic-gate { 10567c478bd9Sstevel@tonic-gate int bucket = compute_sum(name); 10577c478bd9Sstevel@tonic-gate tdesc_t *tdp, *ttdp = NULL; 10587c478bd9Sstevel@tonic-gate 10597c478bd9Sstevel@tonic-gate for (tdp = hash[bucket]; tdp != NULL; tdp = tdp->t_next) { 10607c478bd9Sstevel@tonic-gate if (tdp->t_name != NULL && strcmp(tdp->t_name, name) == 0) { 10617c478bd9Sstevel@tonic-gate if (tdp->t_type == STRUCT || tdp->t_type == UNION || 10627c478bd9Sstevel@tonic-gate tdp->t_type == ENUM || tdp->t_type == INTRINSIC) 10637c478bd9Sstevel@tonic-gate return (tdp); 10647c478bd9Sstevel@tonic-gate if (tdp->t_type == TYPEDEF) 10657c478bd9Sstevel@tonic-gate ttdp = tdp; 10667c478bd9Sstevel@tonic-gate } 10677c478bd9Sstevel@tonic-gate } 10687c478bd9Sstevel@tonic-gate return (ttdp); 10697c478bd9Sstevel@tonic-gate } 10707c478bd9Sstevel@tonic-gate 10717c478bd9Sstevel@tonic-gate tdesc_t * 1072e824d57fSjohnlev lookupname(const char *name) 10737c478bd9Sstevel@tonic-gate { 10747c478bd9Sstevel@tonic-gate return (lookup_name(name_table, name)); 10757c478bd9Sstevel@tonic-gate } 10767c478bd9Sstevel@tonic-gate 10777c478bd9Sstevel@tonic-gate /* 10787c478bd9Sstevel@tonic-gate * Add a node to the hash queues. 10797c478bd9Sstevel@tonic-gate */ 10807c478bd9Sstevel@tonic-gate static void 10817c478bd9Sstevel@tonic-gate addhash(tdesc_t *tdp, int num) 10827c478bd9Sstevel@tonic-gate { 10837c478bd9Sstevel@tonic-gate int hash = HASH(num); 10847c478bd9Sstevel@tonic-gate tdesc_t *ttdp; 10857c478bd9Sstevel@tonic-gate char added_num = 0, added_name = 0; 10867c478bd9Sstevel@tonic-gate 10877c478bd9Sstevel@tonic-gate /* 10887c478bd9Sstevel@tonic-gate * If it already exists in the hash table don't add it again 10897c478bd9Sstevel@tonic-gate * (but still check to see if the name should be hashed). 10907c478bd9Sstevel@tonic-gate */ 10917c478bd9Sstevel@tonic-gate ttdp = lookup(num); 10927c478bd9Sstevel@tonic-gate 10937c478bd9Sstevel@tonic-gate if (ttdp == NULL) { 10947c478bd9Sstevel@tonic-gate tdp->t_id = num; 10957c478bd9Sstevel@tonic-gate tdp->t_hash = hash_table[hash]; 10967c478bd9Sstevel@tonic-gate hash_table[hash] = tdp; 10977c478bd9Sstevel@tonic-gate added_num = 1; 10987c478bd9Sstevel@tonic-gate } 10997c478bd9Sstevel@tonic-gate 11007c478bd9Sstevel@tonic-gate if (tdp->t_name != NULL) { 11017c478bd9Sstevel@tonic-gate ttdp = lookupname(tdp->t_name); 11027c478bd9Sstevel@tonic-gate if (ttdp == NULL) { 11037c478bd9Sstevel@tonic-gate hash = compute_sum(tdp->t_name); 11047c478bd9Sstevel@tonic-gate tdp->t_next = name_table[hash]; 11057c478bd9Sstevel@tonic-gate name_table[hash] = tdp; 11067c478bd9Sstevel@tonic-gate added_name = 1; 11077c478bd9Sstevel@tonic-gate } 11087c478bd9Sstevel@tonic-gate } 11097c478bd9Sstevel@tonic-gate if (!added_num && !added_name) { 11107c478bd9Sstevel@tonic-gate terminate("stabs: broken hash\n"); 11117c478bd9Sstevel@tonic-gate } 11127c478bd9Sstevel@tonic-gate } 11137c478bd9Sstevel@tonic-gate 11147c478bd9Sstevel@tonic-gate static int 1115e824d57fSjohnlev compute_sum(const char *w) 11167c478bd9Sstevel@tonic-gate { 11177c478bd9Sstevel@tonic-gate char c; 11187c478bd9Sstevel@tonic-gate int sum; 11197c478bd9Sstevel@tonic-gate 11207c478bd9Sstevel@tonic-gate for (sum = 0; (c = *w) != '\0'; sum += c, w++) 11217c478bd9Sstevel@tonic-gate ; 11227c478bd9Sstevel@tonic-gate return (HASH(sum)); 11237c478bd9Sstevel@tonic-gate } 11247c478bd9Sstevel@tonic-gate 11257c478bd9Sstevel@tonic-gate static void 11267c478bd9Sstevel@tonic-gate reset(void) 11277c478bd9Sstevel@tonic-gate { 11287c478bd9Sstevel@tonic-gate longjmp(resetbuf, 1); 11297c478bd9Sstevel@tonic-gate } 11307c478bd9Sstevel@tonic-gate 11317c478bd9Sstevel@tonic-gate void 11327c478bd9Sstevel@tonic-gate check_hash(void) 11337c478bd9Sstevel@tonic-gate { 11347c478bd9Sstevel@tonic-gate tdesc_t *tdp; 11357c478bd9Sstevel@tonic-gate int i; 11367c478bd9Sstevel@tonic-gate 11377c478bd9Sstevel@tonic-gate printf("checking hash\n"); 11387c478bd9Sstevel@tonic-gate for (i = 0; i < BUCKETS; i++) { 11397c478bd9Sstevel@tonic-gate if (hash_table[i]) { 11407c478bd9Sstevel@tonic-gate for (tdp = hash_table[i]->t_hash; 11417c478bd9Sstevel@tonic-gate tdp && tdp != hash_table[i]; 11427c478bd9Sstevel@tonic-gate tdp = tdp->t_hash) 11437c478bd9Sstevel@tonic-gate continue; 11447c478bd9Sstevel@tonic-gate if (tdp) { 11457c478bd9Sstevel@tonic-gate terminate("cycle in hash bucket %d\n", i); 11467c478bd9Sstevel@tonic-gate return; 11477c478bd9Sstevel@tonic-gate } 11487c478bd9Sstevel@tonic-gate } 11497c478bd9Sstevel@tonic-gate 11507c478bd9Sstevel@tonic-gate if (name_table[i]) { 11517c478bd9Sstevel@tonic-gate for (tdp = name_table[i]->t_next; 11527c478bd9Sstevel@tonic-gate tdp && tdp != name_table[i]; 11537c478bd9Sstevel@tonic-gate tdp = tdp->t_next) 11547c478bd9Sstevel@tonic-gate continue; 11557c478bd9Sstevel@tonic-gate if (tdp) { 11567c478bd9Sstevel@tonic-gate terminate("cycle in name bucket %d\n", i); 11577c478bd9Sstevel@tonic-gate return; 11587c478bd9Sstevel@tonic-gate } 11597c478bd9Sstevel@tonic-gate } 11607c478bd9Sstevel@tonic-gate } 11617c478bd9Sstevel@tonic-gate printf("done\n"); 11627c478bd9Sstevel@tonic-gate } 11637c478bd9Sstevel@tonic-gate 11647c478bd9Sstevel@tonic-gate /*ARGSUSED1*/ 11657c478bd9Sstevel@tonic-gate static int 11667c478bd9Sstevel@tonic-gate resolve_typed_bitfields_cb(mlist_t *ml, void *private) 11677c478bd9Sstevel@tonic-gate { 11687c478bd9Sstevel@tonic-gate tdesc_t *tdp = ml->ml_type; 11697c478bd9Sstevel@tonic-gate 11707c478bd9Sstevel@tonic-gate debug(3, "Resolving typed bitfields (member %s)\n", 11717c478bd9Sstevel@tonic-gate (ml->ml_name ? ml->ml_name : "(anon)")); 11727c478bd9Sstevel@tonic-gate 11737c478bd9Sstevel@tonic-gate while (tdp) { 11747c478bd9Sstevel@tonic-gate switch (tdp->t_type) { 11757c478bd9Sstevel@tonic-gate case INTRINSIC: 11767c478bd9Sstevel@tonic-gate if (ml->ml_size != tdp->t_intr->intr_nbits) { 11777c478bd9Sstevel@tonic-gate debug(3, "making %d bit intrinsic from %s", 11784d232658Sjohnlev ml->ml_size, tdesc_name(tdp)); 11797c478bd9Sstevel@tonic-gate ml->ml_type = bitintrinsic(tdp, ml->ml_size); 11807c478bd9Sstevel@tonic-gate } else { 11817c478bd9Sstevel@tonic-gate debug(3, "using existing %d bit %s intrinsic", 11824d232658Sjohnlev ml->ml_size, tdesc_name(tdp)); 11837c478bd9Sstevel@tonic-gate ml->ml_type = tdp; 11847c478bd9Sstevel@tonic-gate } 11857c478bd9Sstevel@tonic-gate return (1); 11867c478bd9Sstevel@tonic-gate 11877c478bd9Sstevel@tonic-gate case POINTER: 11887c478bd9Sstevel@tonic-gate case TYPEDEF: 11897c478bd9Sstevel@tonic-gate case VOLATILE: 11907c478bd9Sstevel@tonic-gate case CONST: 11917c478bd9Sstevel@tonic-gate case RESTRICT: 11927c478bd9Sstevel@tonic-gate tdp = tdp->t_tdesc; 11937c478bd9Sstevel@tonic-gate break; 11947c478bd9Sstevel@tonic-gate 11957c478bd9Sstevel@tonic-gate default: 11967c478bd9Sstevel@tonic-gate return (1); 11977c478bd9Sstevel@tonic-gate } 11987c478bd9Sstevel@tonic-gate } 11997c478bd9Sstevel@tonic-gate 12007c478bd9Sstevel@tonic-gate terminate("type chain for bitfield member %s has a NULL", ml->ml_name); 12017c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 12027c478bd9Sstevel@tonic-gate return (0); 12037c478bd9Sstevel@tonic-gate } 12047c478bd9Sstevel@tonic-gate 12057c478bd9Sstevel@tonic-gate void 12067c478bd9Sstevel@tonic-gate resolve_typed_bitfields(void) 12077c478bd9Sstevel@tonic-gate { 12087c478bd9Sstevel@tonic-gate (void) list_iter(typedbitfldmems, 12097c478bd9Sstevel@tonic-gate (int (*)())resolve_typed_bitfields_cb, NULL); 12107c478bd9Sstevel@tonic-gate } 1211