10Sstevel@tonic-gate /* 20Sstevel@tonic-gate * CDDL HEADER START 30Sstevel@tonic-gate * 40Sstevel@tonic-gate * The contents of this file are subject to the terms of the 51882Sjohnlev * Common Development and Distribution License (the "License"). 61882Sjohnlev * You may not use this file except in compliance with the License. 70Sstevel@tonic-gate * 80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 100Sstevel@tonic-gate * See the License for the specific language governing permissions 110Sstevel@tonic-gate * and limitations under the License. 120Sstevel@tonic-gate * 130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 180Sstevel@tonic-gate * 190Sstevel@tonic-gate * CDDL HEADER END 200Sstevel@tonic-gate */ 210Sstevel@tonic-gate /* 221882Sjohnlev * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 230Sstevel@tonic-gate * Use is subject to license terms. 240Sstevel@tonic-gate */ 250Sstevel@tonic-gate 260Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 270Sstevel@tonic-gate 280Sstevel@tonic-gate /* 290Sstevel@tonic-gate * This file is a sewer. 300Sstevel@tonic-gate */ 310Sstevel@tonic-gate 320Sstevel@tonic-gate #include <limits.h> 330Sstevel@tonic-gate #include <stdarg.h> 340Sstevel@tonic-gate #include <stdio.h> 350Sstevel@tonic-gate #include <assert.h> 360Sstevel@tonic-gate #include <strings.h> 370Sstevel@tonic-gate #include <setjmp.h> 380Sstevel@tonic-gate #include <ctype.h> 390Sstevel@tonic-gate #include <uts/common/sys/ctf.h> 400Sstevel@tonic-gate 410Sstevel@tonic-gate #include "ctftools.h" 420Sstevel@tonic-gate #include "memory.h" 430Sstevel@tonic-gate #include "list.h" 440Sstevel@tonic-gate 450Sstevel@tonic-gate #define HASH(NUM) ((int)(NUM & (BUCKETS - 1))) 460Sstevel@tonic-gate #define BUCKETS 128 470Sstevel@tonic-gate 480Sstevel@tonic-gate #define TYPEPAIRMULT 10000 490Sstevel@tonic-gate #define MAKETYPEID(file, num) ((file) * TYPEPAIRMULT + num) 500Sstevel@tonic-gate #define TYPEFILE(tid) ((tid) / TYPEPAIRMULT) 510Sstevel@tonic-gate #define TYPENUM(tid) ((tid) % TYPEPAIRMULT) 520Sstevel@tonic-gate 530Sstevel@tonic-gate #define expected(a, b, c) _expected(a, b, c, __LINE__) 540Sstevel@tonic-gate 550Sstevel@tonic-gate static int faketypenumber = 100000000; 560Sstevel@tonic-gate 570Sstevel@tonic-gate static tdesc_t *hash_table[BUCKETS]; 580Sstevel@tonic-gate static tdesc_t *name_table[BUCKETS]; 590Sstevel@tonic-gate 600Sstevel@tonic-gate list_t *typedbitfldmems; 610Sstevel@tonic-gate 620Sstevel@tonic-gate static void reset(void); 630Sstevel@tonic-gate static jmp_buf resetbuf; 640Sstevel@tonic-gate 650Sstevel@tonic-gate static char *soudef(char *cp, stabtype_t type, tdesc_t **rtdp); 660Sstevel@tonic-gate static void enumdef(char *cp, tdesc_t **rtdp); 67*2722Sjohnlev static int compute_sum(const char *w); 680Sstevel@tonic-gate 690Sstevel@tonic-gate static char *number(char *cp, int *n); 700Sstevel@tonic-gate static char *name(char *cp, char **w); 710Sstevel@tonic-gate static char *id(char *cp, int *h); 720Sstevel@tonic-gate static char *whitesp(char *cp); 730Sstevel@tonic-gate static void addhash(tdesc_t *tdp, int num); 740Sstevel@tonic-gate static int tagadd(char *w, int h, tdesc_t *tdp); 750Sstevel@tonic-gate static char *tdefdecl(char *cp, int h, tdesc_t **rtdp); 760Sstevel@tonic-gate static char *intrinsic(char *cp, tdesc_t **rtdp); 770Sstevel@tonic-gate static char *arraydef(char *cp, tdesc_t **rtdp); 780Sstevel@tonic-gate 790Sstevel@tonic-gate extern int debug_level; 800Sstevel@tonic-gate int debug_parse = DEBUG_PARSE; 810Sstevel@tonic-gate 820Sstevel@tonic-gate /*PRINTFLIKE3*/ 830Sstevel@tonic-gate static void 840Sstevel@tonic-gate parse_debug(int level, char *cp, char *fmt, ...) 850Sstevel@tonic-gate { 860Sstevel@tonic-gate va_list ap; 870Sstevel@tonic-gate char buf[1024]; 880Sstevel@tonic-gate char tmp[32]; 890Sstevel@tonic-gate int i; 900Sstevel@tonic-gate 910Sstevel@tonic-gate if (level > debug_level || !debug_parse) 920Sstevel@tonic-gate return; 930Sstevel@tonic-gate 940Sstevel@tonic-gate if (cp != NULL) { 950Sstevel@tonic-gate for (i = 0; i < 30; i++) { 960Sstevel@tonic-gate if (cp[i] == '\0') 970Sstevel@tonic-gate break; 980Sstevel@tonic-gate if (!iscntrl(cp[i])) 990Sstevel@tonic-gate tmp[i] = cp[i]; 1000Sstevel@tonic-gate } 1010Sstevel@tonic-gate tmp[i] = '\0'; 1020Sstevel@tonic-gate (void) snprintf(buf, sizeof (buf), "%s [cp='%s']\n", fmt, tmp); 1030Sstevel@tonic-gate } else { 1040Sstevel@tonic-gate strcpy(buf, fmt); 1050Sstevel@tonic-gate strcat(buf, "\n"); 1060Sstevel@tonic-gate } 1070Sstevel@tonic-gate 1080Sstevel@tonic-gate va_start(ap, fmt); 1090Sstevel@tonic-gate vadebug(level, buf, ap); 1100Sstevel@tonic-gate va_end(ap); 1110Sstevel@tonic-gate } 1120Sstevel@tonic-gate 1130Sstevel@tonic-gate /* Report unexpected syntax in stabs. */ 1140Sstevel@tonic-gate static void 1150Sstevel@tonic-gate _expected( 1160Sstevel@tonic-gate char *who, /* what function, or part thereof, is reporting */ 1170Sstevel@tonic-gate char *what, /* what was expected */ 1180Sstevel@tonic-gate char *where, /* where we were in the line of input */ 1190Sstevel@tonic-gate int line) 1200Sstevel@tonic-gate { 1210Sstevel@tonic-gate fprintf(stderr, "%s, expecting \"%s\" at \"%s\"\n", who, what, where); 1220Sstevel@tonic-gate fprintf(stderr, "code line: %d, file %s\n", line, 1230Sstevel@tonic-gate (curhdr ? curhdr : "NO FILE")); 1240Sstevel@tonic-gate reset(); 1250Sstevel@tonic-gate } 1260Sstevel@tonic-gate 1270Sstevel@tonic-gate /*ARGSUSED*/ 1280Sstevel@tonic-gate void 1290Sstevel@tonic-gate parse_init(tdata_t *td) 1300Sstevel@tonic-gate { 1310Sstevel@tonic-gate int i; 1320Sstevel@tonic-gate 1330Sstevel@tonic-gate for (i = 0; i < BUCKETS; i++) { 1340Sstevel@tonic-gate hash_table[i] = NULL; 1350Sstevel@tonic-gate name_table[i] = NULL; 1360Sstevel@tonic-gate } 1370Sstevel@tonic-gate 1380Sstevel@tonic-gate if (typedbitfldmems != NULL) { 1390Sstevel@tonic-gate list_free(typedbitfldmems, NULL, NULL); 1400Sstevel@tonic-gate typedbitfldmems = NULL; 1410Sstevel@tonic-gate } 1420Sstevel@tonic-gate } 1430Sstevel@tonic-gate 1440Sstevel@tonic-gate void 1450Sstevel@tonic-gate parse_finish(tdata_t *td) 1460Sstevel@tonic-gate { 1470Sstevel@tonic-gate td->td_nextid = ++faketypenumber; 1480Sstevel@tonic-gate } 1490Sstevel@tonic-gate 1500Sstevel@tonic-gate static tdesc_t * 1510Sstevel@tonic-gate unres_new(int tid) 1520Sstevel@tonic-gate { 1530Sstevel@tonic-gate tdesc_t *tdp; 1540Sstevel@tonic-gate 1550Sstevel@tonic-gate tdp = xcalloc(sizeof (*tdp)); 1560Sstevel@tonic-gate tdp->t_type = TYPEDEF_UNRES; 1570Sstevel@tonic-gate tdp->t_id = tid; 1580Sstevel@tonic-gate 1590Sstevel@tonic-gate return (tdp); 1600Sstevel@tonic-gate } 1610Sstevel@tonic-gate 1620Sstevel@tonic-gate char * 1630Sstevel@tonic-gate read_tid(char *cp, tdesc_t **tdpp) 1640Sstevel@tonic-gate { 1650Sstevel@tonic-gate tdesc_t *tdp; 1660Sstevel@tonic-gate int tid; 1670Sstevel@tonic-gate 1680Sstevel@tonic-gate cp = id(cp, &tid); 1690Sstevel@tonic-gate 1700Sstevel@tonic-gate assert(tid != 0); 1710Sstevel@tonic-gate 1720Sstevel@tonic-gate if (*cp == '=') { 1730Sstevel@tonic-gate if (!(cp = tdefdecl(cp + 1, tid, &tdp))) 1740Sstevel@tonic-gate return (NULL); 1750Sstevel@tonic-gate if (tdp->t_id && tdp->t_id != tid) { 1760Sstevel@tonic-gate tdesc_t *ntdp = xcalloc(sizeof (*ntdp)); 1770Sstevel@tonic-gate 1780Sstevel@tonic-gate ntdp->t_type = TYPEDEF; 1790Sstevel@tonic-gate ntdp->t_tdesc = tdp; 1800Sstevel@tonic-gate tdp = ntdp; 1810Sstevel@tonic-gate } 1820Sstevel@tonic-gate addhash(tdp, tid); 1830Sstevel@tonic-gate } else if ((tdp = lookup(tid)) == NULL) 1840Sstevel@tonic-gate tdp = unres_new(tid); 1850Sstevel@tonic-gate 1860Sstevel@tonic-gate *tdpp = tdp; 1870Sstevel@tonic-gate return (cp); 1880Sstevel@tonic-gate } 1890Sstevel@tonic-gate 1900Sstevel@tonic-gate static iitype_t 1910Sstevel@tonic-gate parse_fun(char *cp, iidesc_t *ii) 1920Sstevel@tonic-gate { 1930Sstevel@tonic-gate iitype_t iitype; 1940Sstevel@tonic-gate tdesc_t *tdp; 1950Sstevel@tonic-gate tdesc_t **args = NULL; 1960Sstevel@tonic-gate int nargs = 0; 1970Sstevel@tonic-gate int va = 0; 1980Sstevel@tonic-gate 1990Sstevel@tonic-gate /* 2000Sstevel@tonic-gate * name:P prototype 2010Sstevel@tonic-gate * name:F global function 2020Sstevel@tonic-gate * name:f static function 2030Sstevel@tonic-gate */ 2040Sstevel@tonic-gate switch (*cp++) { 2050Sstevel@tonic-gate case 'P': 2060Sstevel@tonic-gate iitype = II_NOT; /* not interesting */ 2070Sstevel@tonic-gate break; 2080Sstevel@tonic-gate 2090Sstevel@tonic-gate case 'F': 2100Sstevel@tonic-gate iitype = II_GFUN; 2110Sstevel@tonic-gate break; 2120Sstevel@tonic-gate 2130Sstevel@tonic-gate case 'f': 2140Sstevel@tonic-gate iitype = II_SFUN; 2150Sstevel@tonic-gate break; 2160Sstevel@tonic-gate 2170Sstevel@tonic-gate default: 2180Sstevel@tonic-gate expected("parse_nfun", "[PfF]", cp - 1); 2190Sstevel@tonic-gate } 2200Sstevel@tonic-gate 2210Sstevel@tonic-gate if (!(cp = read_tid(cp, &tdp))) 2220Sstevel@tonic-gate return (-1); 2230Sstevel@tonic-gate 2240Sstevel@tonic-gate if (*cp) 2250Sstevel@tonic-gate args = xmalloc(sizeof (tdesc_t *) * FUNCARG_DEF); 2260Sstevel@tonic-gate 2270Sstevel@tonic-gate while (*cp && *++cp) { 2280Sstevel@tonic-gate if (*cp == '0') { 2290Sstevel@tonic-gate va = 1; 2300Sstevel@tonic-gate continue; 2310Sstevel@tonic-gate } 2320Sstevel@tonic-gate 2330Sstevel@tonic-gate nargs++; 2340Sstevel@tonic-gate if (nargs > FUNCARG_DEF) 2350Sstevel@tonic-gate args = xrealloc(args, sizeof (tdesc_t *) * nargs); 2360Sstevel@tonic-gate if (!(cp = read_tid(cp, &args[nargs - 1]))) 2370Sstevel@tonic-gate return (-1); 2380Sstevel@tonic-gate } 2390Sstevel@tonic-gate 2400Sstevel@tonic-gate ii->ii_type = iitype; 2410Sstevel@tonic-gate ii->ii_dtype = tdp; 2420Sstevel@tonic-gate ii->ii_nargs = nargs; 2430Sstevel@tonic-gate ii->ii_args = args; 2440Sstevel@tonic-gate ii->ii_vargs = va; 2450Sstevel@tonic-gate 2460Sstevel@tonic-gate return (iitype); 2470Sstevel@tonic-gate } 2480Sstevel@tonic-gate 2490Sstevel@tonic-gate static iitype_t 2500Sstevel@tonic-gate parse_sym(char *cp, iidesc_t *ii) 2510Sstevel@tonic-gate { 2520Sstevel@tonic-gate tdesc_t *tdp; 2530Sstevel@tonic-gate iitype_t iitype; 2540Sstevel@tonic-gate 2550Sstevel@tonic-gate /* 2560Sstevel@tonic-gate * name:G global variable 2570Sstevel@tonic-gate * name:S static variable 2580Sstevel@tonic-gate */ 2590Sstevel@tonic-gate switch (*cp++) { 2600Sstevel@tonic-gate case 'G': 2610Sstevel@tonic-gate iitype = II_GVAR; 2620Sstevel@tonic-gate break; 2630Sstevel@tonic-gate case 'S': 2640Sstevel@tonic-gate iitype = II_SVAR; 2650Sstevel@tonic-gate break; 2660Sstevel@tonic-gate case 'p': 2670Sstevel@tonic-gate iitype = II_PSYM; 2680Sstevel@tonic-gate break; 2690Sstevel@tonic-gate case '(': 2700Sstevel@tonic-gate cp--; 2710Sstevel@tonic-gate /*FALLTHROUGH*/ 2720Sstevel@tonic-gate case 'r': 2730Sstevel@tonic-gate case 'V': 2740Sstevel@tonic-gate iitype = II_NOT; /* not interesting */ 2750Sstevel@tonic-gate break; 2760Sstevel@tonic-gate default: 2770Sstevel@tonic-gate expected("parse_sym", "[GprSV(]", cp - 1); 2780Sstevel@tonic-gate } 2790Sstevel@tonic-gate 2800Sstevel@tonic-gate if (!(cp = read_tid(cp, &tdp))) 2810Sstevel@tonic-gate return (-1); 2820Sstevel@tonic-gate 2830Sstevel@tonic-gate ii->ii_type = iitype; 2840Sstevel@tonic-gate ii->ii_dtype = tdp; 2850Sstevel@tonic-gate 2860Sstevel@tonic-gate return (iitype); 2870Sstevel@tonic-gate } 2880Sstevel@tonic-gate 2890Sstevel@tonic-gate static iitype_t 2900Sstevel@tonic-gate parse_type(char *cp, iidesc_t *ii) 2910Sstevel@tonic-gate { 2920Sstevel@tonic-gate tdesc_t *tdp, *ntdp; 2930Sstevel@tonic-gate int tid; 2940Sstevel@tonic-gate 2950Sstevel@tonic-gate if (*cp++ != 't') 2960Sstevel@tonic-gate expected("parse_type", "t (type)", cp - 1); 2970Sstevel@tonic-gate 2980Sstevel@tonic-gate cp = id(cp, &tid); 2990Sstevel@tonic-gate if ((tdp = lookup(tid)) == NULL) { 3000Sstevel@tonic-gate if (*cp++ != '=') 3010Sstevel@tonic-gate expected("parse_type", "= (definition)", cp - 1); 3020Sstevel@tonic-gate 3030Sstevel@tonic-gate (void) tdefdecl(cp, tid, &tdp); 3040Sstevel@tonic-gate 3050Sstevel@tonic-gate if (tdp->t_id == tid) { 3060Sstevel@tonic-gate assert(tdp->t_type != TYPEDEF); 3070Sstevel@tonic-gate assert(!lookup(tdp->t_id)); 3080Sstevel@tonic-gate 3090Sstevel@tonic-gate if (!streq(tdp->t_name, ii->ii_name)) { 3100Sstevel@tonic-gate ntdp = xcalloc(sizeof (*ntdp)); 3110Sstevel@tonic-gate ntdp->t_name = xstrdup(ii->ii_name); 3120Sstevel@tonic-gate ntdp->t_type = TYPEDEF; 3130Sstevel@tonic-gate ntdp->t_tdesc = tdp; 3140Sstevel@tonic-gate tdp->t_id = faketypenumber++; 3150Sstevel@tonic-gate tdp = ntdp; 3160Sstevel@tonic-gate } 3170Sstevel@tonic-gate } else if (tdp->t_id == 0) { 3180Sstevel@tonic-gate assert(tdp->t_type == FORWARD || 3190Sstevel@tonic-gate tdp->t_type == INTRINSIC); 3200Sstevel@tonic-gate 3210Sstevel@tonic-gate if (tdp->t_name && !streq(tdp->t_name, ii->ii_name)) { 3220Sstevel@tonic-gate ntdp = xcalloc(sizeof (*ntdp)); 3230Sstevel@tonic-gate ntdp->t_name = xstrdup(ii->ii_name); 3240Sstevel@tonic-gate ntdp->t_type = TYPEDEF; 3250Sstevel@tonic-gate ntdp->t_tdesc = tdp; 3260Sstevel@tonic-gate tdp->t_id = faketypenumber++; 3270Sstevel@tonic-gate tdp = ntdp; 3280Sstevel@tonic-gate } 3290Sstevel@tonic-gate } else if (tdp->t_id != tid) { 3300Sstevel@tonic-gate ntdp = xcalloc(sizeof (*ntdp)); 3310Sstevel@tonic-gate ntdp->t_name = xstrdup(ii->ii_name); 3320Sstevel@tonic-gate ntdp->t_type = TYPEDEF; 3330Sstevel@tonic-gate ntdp->t_tdesc = tdp; 3340Sstevel@tonic-gate tdp = ntdp; 3350Sstevel@tonic-gate } 3360Sstevel@tonic-gate 3370Sstevel@tonic-gate if (tagadd(ii->ii_name, tid, tdp) < 0) 3380Sstevel@tonic-gate return (-1); 3390Sstevel@tonic-gate } 3400Sstevel@tonic-gate 3410Sstevel@tonic-gate ii->ii_type = II_TYPE; 3420Sstevel@tonic-gate ii->ii_dtype = tdp; 3430Sstevel@tonic-gate return (II_TYPE); 3440Sstevel@tonic-gate } 3450Sstevel@tonic-gate 3460Sstevel@tonic-gate static iitype_t 3470Sstevel@tonic-gate parse_sou(char *cp, iidesc_t *idp) 3480Sstevel@tonic-gate { 3490Sstevel@tonic-gate tdesc_t *rtdp; 3500Sstevel@tonic-gate int tid; 3510Sstevel@tonic-gate 3520Sstevel@tonic-gate if (*cp++ != 'T') 3530Sstevel@tonic-gate expected("parse_sou", "T (sou)", cp - 1); 3540Sstevel@tonic-gate 3550Sstevel@tonic-gate cp = id(cp, &tid); 3560Sstevel@tonic-gate if (*cp++ != '=') 3570Sstevel@tonic-gate expected("parse_sou", "= (definition)", cp - 1); 3580Sstevel@tonic-gate 3590Sstevel@tonic-gate parse_debug(1, NULL, "parse_sou: declaring '%s'", idp->ii_name ? 3600Sstevel@tonic-gate idp->ii_name : "(anon)"); 3610Sstevel@tonic-gate if ((rtdp = lookup(tid)) != NULL) { 3620Sstevel@tonic-gate if (idp->ii_name != NULL) { 3630Sstevel@tonic-gate if (rtdp->t_name != NULL && 3640Sstevel@tonic-gate strcmp(rtdp->t_name, idp->ii_name) != 0) { 3650Sstevel@tonic-gate tdesc_t *tdp; 3660Sstevel@tonic-gate 3670Sstevel@tonic-gate tdp = xcalloc(sizeof (*tdp)); 3680Sstevel@tonic-gate tdp->t_name = xstrdup(idp->ii_name); 3690Sstevel@tonic-gate tdp->t_type = TYPEDEF; 3700Sstevel@tonic-gate tdp->t_tdesc = rtdp; 3710Sstevel@tonic-gate addhash(tdp, tid); /* for *(x,y) types */ 3720Sstevel@tonic-gate parse_debug(3, NULL, " %s defined as %s(%d)", 3731882Sjohnlev idp->ii_name, tdesc_name(rtdp), tid); 3740Sstevel@tonic-gate } else if (rtdp->t_name == NULL) { 3750Sstevel@tonic-gate rtdp->t_name = xstrdup(idp->ii_name); 3760Sstevel@tonic-gate addhash(rtdp, tid); 3770Sstevel@tonic-gate } 3780Sstevel@tonic-gate } 3790Sstevel@tonic-gate } else { 3800Sstevel@tonic-gate rtdp = xcalloc(sizeof (*rtdp)); 3810Sstevel@tonic-gate rtdp->t_name = idp->ii_name ? xstrdup(idp->ii_name) : NULL; 3820Sstevel@tonic-gate addhash(rtdp, tid); 3830Sstevel@tonic-gate } 3840Sstevel@tonic-gate 3850Sstevel@tonic-gate switch (*cp++) { 3860Sstevel@tonic-gate case 's': 3870Sstevel@tonic-gate (void) soudef(cp, STRUCT, &rtdp); 3880Sstevel@tonic-gate break; 3890Sstevel@tonic-gate case 'u': 3900Sstevel@tonic-gate (void) soudef(cp, UNION, &rtdp); 3910Sstevel@tonic-gate break; 3920Sstevel@tonic-gate case 'e': 3930Sstevel@tonic-gate enumdef(cp, &rtdp); 3940Sstevel@tonic-gate break; 3950Sstevel@tonic-gate default: 3960Sstevel@tonic-gate expected("parse_sou", "<tag type s/u/e>", cp - 1); 3970Sstevel@tonic-gate break; 3980Sstevel@tonic-gate } 3990Sstevel@tonic-gate 4000Sstevel@tonic-gate idp->ii_type = II_SOU; 4010Sstevel@tonic-gate idp->ii_dtype = rtdp; 4020Sstevel@tonic-gate return (II_SOU); 4030Sstevel@tonic-gate } 4040Sstevel@tonic-gate 4050Sstevel@tonic-gate int 4060Sstevel@tonic-gate parse_stab(stab_t *stab, char *cp, iidesc_t **iidescp) 4070Sstevel@tonic-gate { 4080Sstevel@tonic-gate iidesc_t *ii = NULL; 4090Sstevel@tonic-gate iitype_t (*parse)(char *, iidesc_t *); 4100Sstevel@tonic-gate int rc; 4110Sstevel@tonic-gate 4120Sstevel@tonic-gate /* 4130Sstevel@tonic-gate * set up for reset() 4140Sstevel@tonic-gate */ 4150Sstevel@tonic-gate if (setjmp(resetbuf)) 4160Sstevel@tonic-gate return (-1); 4170Sstevel@tonic-gate 4180Sstevel@tonic-gate cp = whitesp(cp); 4190Sstevel@tonic-gate ii = iidesc_new(NULL); 4200Sstevel@tonic-gate cp = name(cp, &ii->ii_name); 4210Sstevel@tonic-gate 4220Sstevel@tonic-gate switch (stab->n_type) { 4230Sstevel@tonic-gate case N_FUN: 4240Sstevel@tonic-gate parse = parse_fun; 4250Sstevel@tonic-gate break; 4260Sstevel@tonic-gate 4270Sstevel@tonic-gate case N_LSYM: 4280Sstevel@tonic-gate if (*cp == 't') 4290Sstevel@tonic-gate parse = parse_type; 4300Sstevel@tonic-gate else if (*cp == 'T') 4310Sstevel@tonic-gate parse = parse_sou; 4320Sstevel@tonic-gate else 4330Sstevel@tonic-gate parse = parse_sym; 4340Sstevel@tonic-gate break; 4350Sstevel@tonic-gate 4360Sstevel@tonic-gate case N_GSYM: 4370Sstevel@tonic-gate case N_LCSYM: 4380Sstevel@tonic-gate case N_PSYM: 4390Sstevel@tonic-gate case N_ROSYM: 4400Sstevel@tonic-gate case N_RSYM: 4410Sstevel@tonic-gate case N_STSYM: 4420Sstevel@tonic-gate parse = parse_sym; 4430Sstevel@tonic-gate break; 4440Sstevel@tonic-gate default: 4450Sstevel@tonic-gate parse_debug(1, cp, "Unknown stab type %#x", stab->n_type); 4460Sstevel@tonic-gate bzero(&resetbuf, sizeof (resetbuf)); 4470Sstevel@tonic-gate return (-1); 4480Sstevel@tonic-gate } 4490Sstevel@tonic-gate 4500Sstevel@tonic-gate rc = parse(cp, ii); 4510Sstevel@tonic-gate bzero(&resetbuf, sizeof (resetbuf)); 4520Sstevel@tonic-gate 4530Sstevel@tonic-gate if (rc < 0 || ii->ii_type == II_NOT) { 4540Sstevel@tonic-gate iidesc_free(ii, NULL); 4550Sstevel@tonic-gate return (rc); 4560Sstevel@tonic-gate } 4570Sstevel@tonic-gate 4580Sstevel@tonic-gate *iidescp = ii; 4590Sstevel@tonic-gate 4600Sstevel@tonic-gate return (1); 4610Sstevel@tonic-gate } 4620Sstevel@tonic-gate 4630Sstevel@tonic-gate /* 4640Sstevel@tonic-gate * Check if we have this node in the hash table already 4650Sstevel@tonic-gate */ 4660Sstevel@tonic-gate tdesc_t * 4670Sstevel@tonic-gate lookup(int h) 4680Sstevel@tonic-gate { 4690Sstevel@tonic-gate int bucket = HASH(h); 4700Sstevel@tonic-gate tdesc_t *tdp = hash_table[bucket]; 4710Sstevel@tonic-gate 4720Sstevel@tonic-gate while (tdp != NULL) { 4730Sstevel@tonic-gate if (tdp->t_id == h) 4740Sstevel@tonic-gate return (tdp); 4750Sstevel@tonic-gate tdp = tdp->t_hash; 4760Sstevel@tonic-gate } 4770Sstevel@tonic-gate return (NULL); 4780Sstevel@tonic-gate } 4790Sstevel@tonic-gate 4800Sstevel@tonic-gate static char * 4810Sstevel@tonic-gate whitesp(char *cp) 4820Sstevel@tonic-gate { 4830Sstevel@tonic-gate char c; 4840Sstevel@tonic-gate 4850Sstevel@tonic-gate for (c = *cp++; isspace(c); c = *cp++); 4860Sstevel@tonic-gate --cp; 4870Sstevel@tonic-gate return (cp); 4880Sstevel@tonic-gate } 4890Sstevel@tonic-gate 4900Sstevel@tonic-gate static char * 4910Sstevel@tonic-gate name(char *cp, char **w) 4920Sstevel@tonic-gate { 4930Sstevel@tonic-gate char *new, *orig, c; 4940Sstevel@tonic-gate int len; 4950Sstevel@tonic-gate 4960Sstevel@tonic-gate orig = cp; 4970Sstevel@tonic-gate c = *cp++; 4980Sstevel@tonic-gate if (c == ':') 4990Sstevel@tonic-gate *w = NULL; 5000Sstevel@tonic-gate else if (isalpha(c) || strchr("_.$", c)) { 5010Sstevel@tonic-gate for (c = *cp++; isalnum(c) || strchr(" _.$", c); c = *cp++) 5020Sstevel@tonic-gate ; 5030Sstevel@tonic-gate if (c != ':') 5040Sstevel@tonic-gate reset(); 5050Sstevel@tonic-gate len = cp - orig; 5060Sstevel@tonic-gate new = xmalloc(len); 5070Sstevel@tonic-gate while (orig < cp - 1) 5080Sstevel@tonic-gate *new++ = *orig++; 5090Sstevel@tonic-gate *new = '\0'; 5100Sstevel@tonic-gate *w = new - (len - 1); 5110Sstevel@tonic-gate } else 5120Sstevel@tonic-gate reset(); 5130Sstevel@tonic-gate 5140Sstevel@tonic-gate return (cp); 5150Sstevel@tonic-gate } 5160Sstevel@tonic-gate 5170Sstevel@tonic-gate static char * 5180Sstevel@tonic-gate number(char *cp, int *n) 5190Sstevel@tonic-gate { 5200Sstevel@tonic-gate char *next; 5210Sstevel@tonic-gate 5220Sstevel@tonic-gate *n = (int)strtol(cp, &next, 10); 5230Sstevel@tonic-gate if (next == cp) 5240Sstevel@tonic-gate expected("number", "<number>", cp); 5250Sstevel@tonic-gate return (next); 5260Sstevel@tonic-gate } 5270Sstevel@tonic-gate 5280Sstevel@tonic-gate static char * 5290Sstevel@tonic-gate id(char *cp, int *h) 5300Sstevel@tonic-gate { 5310Sstevel@tonic-gate int n1, n2; 5320Sstevel@tonic-gate 5330Sstevel@tonic-gate if (*cp == '(') { /* SunPro style */ 5340Sstevel@tonic-gate cp++; 5350Sstevel@tonic-gate cp = number(cp, &n1); 5360Sstevel@tonic-gate if (*cp++ != ',') 5370Sstevel@tonic-gate expected("id", ",", cp - 1); 5380Sstevel@tonic-gate cp = number(cp, &n2); 5390Sstevel@tonic-gate if (*cp++ != ')') 5400Sstevel@tonic-gate expected("id", ")", cp - 1); 5410Sstevel@tonic-gate *h = MAKETYPEID(n1, n2); 5420Sstevel@tonic-gate } else if (isdigit(*cp)) { /* gcc style */ 5430Sstevel@tonic-gate cp = number(cp, &n1); 5440Sstevel@tonic-gate *h = n1; 5450Sstevel@tonic-gate } else { 5460Sstevel@tonic-gate expected("id", "(/0-9", cp); 5470Sstevel@tonic-gate } 5480Sstevel@tonic-gate return (cp); 5490Sstevel@tonic-gate } 5500Sstevel@tonic-gate 5510Sstevel@tonic-gate static int 5520Sstevel@tonic-gate tagadd(char *w, int h, tdesc_t *tdp) 5530Sstevel@tonic-gate { 5540Sstevel@tonic-gate tdesc_t *otdp; 5550Sstevel@tonic-gate 5560Sstevel@tonic-gate tdp->t_name = w; 5570Sstevel@tonic-gate if (!(otdp = lookup(h))) 5580Sstevel@tonic-gate addhash(tdp, h); 5590Sstevel@tonic-gate else if (otdp != tdp) { 5600Sstevel@tonic-gate warning("duplicate entry\n"); 5611882Sjohnlev warning(" old: %s %d (%d,%d)\n", tdesc_name(otdp), 5620Sstevel@tonic-gate otdp->t_type, TYPEFILE(otdp->t_id), TYPENUM(otdp->t_id)); 5631882Sjohnlev warning(" new: %s %d (%d,%d)\n", tdesc_name(tdp), 5640Sstevel@tonic-gate tdp->t_type, TYPEFILE(tdp->t_id), TYPENUM(tdp->t_id)); 5650Sstevel@tonic-gate return (-1); 5660Sstevel@tonic-gate } 5670Sstevel@tonic-gate 5680Sstevel@tonic-gate return (0); 5690Sstevel@tonic-gate } 5700Sstevel@tonic-gate 5710Sstevel@tonic-gate static char * 5720Sstevel@tonic-gate tdefdecl(char *cp, int h, tdesc_t **rtdp) 5730Sstevel@tonic-gate { 5740Sstevel@tonic-gate tdesc_t *ntdp; 5750Sstevel@tonic-gate char *w; 5760Sstevel@tonic-gate int c, h2; 5770Sstevel@tonic-gate char type; 5780Sstevel@tonic-gate 5790Sstevel@tonic-gate parse_debug(3, cp, "tdefdecl h=%d", h); 5800Sstevel@tonic-gate 5810Sstevel@tonic-gate /* Type codes */ 5820Sstevel@tonic-gate switch (type = *cp) { 5830Sstevel@tonic-gate case 'b': /* integer */ 5840Sstevel@tonic-gate case 'R': /* fp */ 5850Sstevel@tonic-gate cp = intrinsic(cp, rtdp); 5860Sstevel@tonic-gate break; 5870Sstevel@tonic-gate case '(': /* equiv to another type */ 5880Sstevel@tonic-gate cp = id(cp, &h2); 5890Sstevel@tonic-gate ntdp = lookup(h2); 5900Sstevel@tonic-gate 5910Sstevel@tonic-gate if (ntdp != NULL && *cp == '=') { 5920Sstevel@tonic-gate if (ntdp->t_type == FORWARD && *(cp + 1) == 'x') { 5930Sstevel@tonic-gate /* 5940Sstevel@tonic-gate * The 6.2 compiler, and possibly others, will 5950Sstevel@tonic-gate * sometimes emit the same stab for a forward 5960Sstevel@tonic-gate * declaration twice. That is, "(1,2)=xsfoo:" 5970Sstevel@tonic-gate * will sometimes show up in two different 5980Sstevel@tonic-gate * places. This is, of course, quite fun. We 5990Sstevel@tonic-gate * want CTF to work in spite of the compiler, 6000Sstevel@tonic-gate * so we'll let this one through. 6010Sstevel@tonic-gate */ 6020Sstevel@tonic-gate char *c2 = cp + 2; 6030Sstevel@tonic-gate char *nm; 6040Sstevel@tonic-gate 6050Sstevel@tonic-gate if (!strchr("sue", *c2++)) { 6060Sstevel@tonic-gate expected("tdefdecl/x-redefine", "[sue]", 6070Sstevel@tonic-gate c2 - 1); 6080Sstevel@tonic-gate } 6090Sstevel@tonic-gate 6100Sstevel@tonic-gate c2 = name(c2, &nm); 6110Sstevel@tonic-gate if (strcmp(nm, ntdp->t_name) != 0) { 6120Sstevel@tonic-gate terminate("Stabs error: Attempt to " 6130Sstevel@tonic-gate "redefine type (%d,%d) as " 6140Sstevel@tonic-gate "something else: %s\n", 6150Sstevel@tonic-gate TYPEFILE(h2), TYPENUM(h2), 6160Sstevel@tonic-gate c2 - 1); 6170Sstevel@tonic-gate } 6180Sstevel@tonic-gate free(nm); 6190Sstevel@tonic-gate 6200Sstevel@tonic-gate h2 = faketypenumber++; 6210Sstevel@tonic-gate ntdp = NULL; 6220Sstevel@tonic-gate } else { 6230Sstevel@tonic-gate terminate("Stabs error: Attempting to " 6240Sstevel@tonic-gate "redefine type (%d,%d)\n", TYPEFILE(h2), 6250Sstevel@tonic-gate TYPENUM(h2)); 6260Sstevel@tonic-gate } 6270Sstevel@tonic-gate } 6280Sstevel@tonic-gate 6290Sstevel@tonic-gate if (ntdp == NULL) { /* if that type isn't defined yet */ 6300Sstevel@tonic-gate if (*cp != '=') { 6310Sstevel@tonic-gate /* record it as unresolved */ 6320Sstevel@tonic-gate parse_debug(3, NULL, "tdefdecl unres type %d", 6330Sstevel@tonic-gate h2); 6340Sstevel@tonic-gate *rtdp = calloc(sizeof (**rtdp), 1); 6350Sstevel@tonic-gate (*rtdp)->t_type = TYPEDEF_UNRES; 6360Sstevel@tonic-gate (*rtdp)->t_id = h2; 6370Sstevel@tonic-gate break; 6380Sstevel@tonic-gate } else 6390Sstevel@tonic-gate cp++; 6400Sstevel@tonic-gate 6410Sstevel@tonic-gate /* define a new type */ 6420Sstevel@tonic-gate cp = tdefdecl(cp, h2, rtdp); 6430Sstevel@tonic-gate if ((*rtdp)->t_id && (*rtdp)->t_id != h2) { 6440Sstevel@tonic-gate ntdp = calloc(sizeof (*ntdp), 1); 6450Sstevel@tonic-gate ntdp->t_type = TYPEDEF; 6460Sstevel@tonic-gate ntdp->t_tdesc = *rtdp; 6470Sstevel@tonic-gate *rtdp = ntdp; 6480Sstevel@tonic-gate } 6490Sstevel@tonic-gate 6500Sstevel@tonic-gate addhash(*rtdp, h2); 6510Sstevel@tonic-gate 6520Sstevel@tonic-gate } else { /* that type is already defined */ 6530Sstevel@tonic-gate if (ntdp->t_type != TYPEDEF || ntdp->t_name != NULL) { 6540Sstevel@tonic-gate *rtdp = ntdp; 6550Sstevel@tonic-gate } else { 6560Sstevel@tonic-gate parse_debug(3, NULL, 6570Sstevel@tonic-gate "No duplicate typedef anon for ref"); 6580Sstevel@tonic-gate *rtdp = ntdp; 6590Sstevel@tonic-gate } 6600Sstevel@tonic-gate } 6610Sstevel@tonic-gate break; 6620Sstevel@tonic-gate case '*': 6630Sstevel@tonic-gate ntdp = NULL; 6640Sstevel@tonic-gate cp = tdefdecl(cp + 1, h, &ntdp); 6650Sstevel@tonic-gate if (ntdp == NULL) 6660Sstevel@tonic-gate expected("tdefdecl/*", "id", cp); 6670Sstevel@tonic-gate 6680Sstevel@tonic-gate if (!ntdp->t_id) 6690Sstevel@tonic-gate ntdp->t_id = faketypenumber++; 6700Sstevel@tonic-gate 6710Sstevel@tonic-gate *rtdp = xcalloc(sizeof (**rtdp)); 6720Sstevel@tonic-gate (*rtdp)->t_type = POINTER; 6730Sstevel@tonic-gate (*rtdp)->t_size = 0; 6740Sstevel@tonic-gate (*rtdp)->t_id = h; 6750Sstevel@tonic-gate (*rtdp)->t_tdesc = ntdp; 6760Sstevel@tonic-gate break; 6770Sstevel@tonic-gate case 'f': 6780Sstevel@tonic-gate cp = tdefdecl(cp + 1, h, &ntdp); 6790Sstevel@tonic-gate *rtdp = xcalloc(sizeof (**rtdp)); 6800Sstevel@tonic-gate (*rtdp)->t_type = FUNCTION; 6810Sstevel@tonic-gate (*rtdp)->t_size = 0; 6820Sstevel@tonic-gate (*rtdp)->t_id = h; 6830Sstevel@tonic-gate (*rtdp)->t_fndef = xcalloc(sizeof (fndef_t)); 6840Sstevel@tonic-gate /* 6850Sstevel@tonic-gate * The 6.1 compiler will sometimes generate incorrect stabs for 6860Sstevel@tonic-gate * function pointers (it'll get the return type wrong). This 6870Sstevel@tonic-gate * causes merges to fail. We therefore treat function pointers 6880Sstevel@tonic-gate * as if they all point to functions that return int. When 6890Sstevel@tonic-gate * 4432549 is fixed, the lookupname() call below should be 6900Sstevel@tonic-gate * replaced with `ntdp'. 6910Sstevel@tonic-gate */ 6920Sstevel@tonic-gate (*rtdp)->t_fndef->fn_ret = lookupname("int"); 6930Sstevel@tonic-gate break; 6940Sstevel@tonic-gate case 'a': 6950Sstevel@tonic-gate case 'z': 6960Sstevel@tonic-gate cp++; 6970Sstevel@tonic-gate if (*cp++ != 'r') 6980Sstevel@tonic-gate expected("tdefdecl/[az]", "r", cp - 1); 6990Sstevel@tonic-gate *rtdp = xcalloc(sizeof (**rtdp)); 7000Sstevel@tonic-gate (*rtdp)->t_type = ARRAY; 7010Sstevel@tonic-gate (*rtdp)->t_id = h; 7020Sstevel@tonic-gate cp = arraydef(cp, rtdp); 7030Sstevel@tonic-gate break; 7040Sstevel@tonic-gate case 'x': 7050Sstevel@tonic-gate c = *++cp; 7060Sstevel@tonic-gate if (c != 's' && c != 'u' && c != 'e') 7070Sstevel@tonic-gate expected("tdefdecl/x", "[sue]", cp - 1); 7080Sstevel@tonic-gate cp = name(cp + 1, &w); 7090Sstevel@tonic-gate 7100Sstevel@tonic-gate ntdp = xcalloc(sizeof (*ntdp)); 7110Sstevel@tonic-gate ntdp->t_type = FORWARD; 7120Sstevel@tonic-gate ntdp->t_name = w; 7130Sstevel@tonic-gate /* 7140Sstevel@tonic-gate * We explicitly don't set t_id here - the caller will do it. 7150Sstevel@tonic-gate * The caller may want to use a real type ID, or they may 7160Sstevel@tonic-gate * choose to make one up. 7170Sstevel@tonic-gate */ 7180Sstevel@tonic-gate 7190Sstevel@tonic-gate *rtdp = ntdp; 7200Sstevel@tonic-gate break; 7210Sstevel@tonic-gate 7220Sstevel@tonic-gate case 'B': /* volatile */ 7230Sstevel@tonic-gate cp = tdefdecl(cp + 1, h, &ntdp); 7240Sstevel@tonic-gate 7250Sstevel@tonic-gate if (!ntdp->t_id) 7260Sstevel@tonic-gate ntdp->t_id = faketypenumber++; 7270Sstevel@tonic-gate 7280Sstevel@tonic-gate *rtdp = xcalloc(sizeof (**rtdp)); 7290Sstevel@tonic-gate (*rtdp)->t_type = VOLATILE; 7300Sstevel@tonic-gate (*rtdp)->t_size = 0; 7310Sstevel@tonic-gate (*rtdp)->t_tdesc = ntdp; 7320Sstevel@tonic-gate (*rtdp)->t_id = h; 7330Sstevel@tonic-gate break; 7340Sstevel@tonic-gate 7350Sstevel@tonic-gate case 'k': /* const */ 7360Sstevel@tonic-gate cp = tdefdecl(cp + 1, h, &ntdp); 7370Sstevel@tonic-gate 7380Sstevel@tonic-gate if (!ntdp->t_id) 7390Sstevel@tonic-gate ntdp->t_id = faketypenumber++; 7400Sstevel@tonic-gate 7410Sstevel@tonic-gate *rtdp = xcalloc(sizeof (**rtdp)); 7420Sstevel@tonic-gate (*rtdp)->t_type = CONST; 7430Sstevel@tonic-gate (*rtdp)->t_size = 0; 7440Sstevel@tonic-gate (*rtdp)->t_tdesc = ntdp; 7450Sstevel@tonic-gate (*rtdp)->t_id = h; 7460Sstevel@tonic-gate break; 7470Sstevel@tonic-gate 7480Sstevel@tonic-gate case 'K': /* restricted */ 7490Sstevel@tonic-gate cp = tdefdecl(cp + 1, h, &ntdp); 7500Sstevel@tonic-gate 7510Sstevel@tonic-gate if (!ntdp->t_id) 7520Sstevel@tonic-gate ntdp->t_id = faketypenumber++; 7530Sstevel@tonic-gate 7540Sstevel@tonic-gate *rtdp = xcalloc(sizeof (**rtdp)); 7550Sstevel@tonic-gate (*rtdp)->t_type = RESTRICT; 7560Sstevel@tonic-gate (*rtdp)->t_size = 0; 7570Sstevel@tonic-gate (*rtdp)->t_tdesc = ntdp; 7580Sstevel@tonic-gate (*rtdp)->t_id = h; 7590Sstevel@tonic-gate break; 7600Sstevel@tonic-gate 7610Sstevel@tonic-gate case 'u': 7620Sstevel@tonic-gate case 's': 7630Sstevel@tonic-gate cp++; 7640Sstevel@tonic-gate 7650Sstevel@tonic-gate *rtdp = xcalloc(sizeof (**rtdp)); 7660Sstevel@tonic-gate (*rtdp)->t_name = NULL; 7670Sstevel@tonic-gate cp = soudef(cp, (type == 'u') ? UNION : STRUCT, rtdp); 7680Sstevel@tonic-gate break; 7690Sstevel@tonic-gate default: 7700Sstevel@tonic-gate expected("tdefdecl", "<type code>", cp); 7710Sstevel@tonic-gate } 7720Sstevel@tonic-gate return (cp); 7730Sstevel@tonic-gate } 7740Sstevel@tonic-gate 7750Sstevel@tonic-gate static char * 7760Sstevel@tonic-gate intrinsic(char *cp, tdesc_t **rtdp) 7770Sstevel@tonic-gate { 7780Sstevel@tonic-gate intr_t *intr = xcalloc(sizeof (intr_t)); 7790Sstevel@tonic-gate tdesc_t *tdp; 7800Sstevel@tonic-gate int width, fmt, i; 7810Sstevel@tonic-gate 7820Sstevel@tonic-gate switch (*cp++) { 7830Sstevel@tonic-gate case 'b': 7840Sstevel@tonic-gate intr->intr_type = INTR_INT; 7850Sstevel@tonic-gate if (*cp == 's') 7860Sstevel@tonic-gate intr->intr_signed = 1; 7870Sstevel@tonic-gate else if (*cp != 'u') 7880Sstevel@tonic-gate expected("intrinsic/b", "[su]", cp); 7890Sstevel@tonic-gate cp++; 7900Sstevel@tonic-gate 7910Sstevel@tonic-gate if (strchr("cbv", *cp)) 7920Sstevel@tonic-gate intr->intr_iformat = *cp++; 7930Sstevel@tonic-gate 7940Sstevel@tonic-gate cp = number(cp, &width); 7950Sstevel@tonic-gate if (*cp++ != ';') 7960Sstevel@tonic-gate expected("intrinsic/b", "; (post-width)", cp - 1); 7970Sstevel@tonic-gate 7980Sstevel@tonic-gate cp = number(cp, &intr->intr_offset); 7990Sstevel@tonic-gate if (*cp++ != ';') 8000Sstevel@tonic-gate expected("intrinsic/b", "; (post-offset)", cp - 1); 8010Sstevel@tonic-gate 8020Sstevel@tonic-gate cp = number(cp, &intr->intr_nbits); 8030Sstevel@tonic-gate break; 8040Sstevel@tonic-gate 8050Sstevel@tonic-gate case 'R': 8060Sstevel@tonic-gate intr->intr_type = INTR_REAL; 8070Sstevel@tonic-gate for (fmt = 0, i = 0; isdigit(*(cp + i)); i++) 8080Sstevel@tonic-gate fmt = fmt * 10 + (*(cp + i) - '0'); 8090Sstevel@tonic-gate 8100Sstevel@tonic-gate if (fmt < 1 || fmt > CTF_FP_MAX) 8110Sstevel@tonic-gate expected("intrinsic/R", "number <= CTF_FP_MAX", cp); 8120Sstevel@tonic-gate 8130Sstevel@tonic-gate intr->intr_fformat = fmt; 8140Sstevel@tonic-gate cp += i; 8150Sstevel@tonic-gate 8160Sstevel@tonic-gate if (*cp++ != ';') 8170Sstevel@tonic-gate expected("intrinsic/R", ";", cp - 1); 8180Sstevel@tonic-gate cp = number(cp, &width); 8190Sstevel@tonic-gate 8200Sstevel@tonic-gate intr->intr_nbits = width * 8; 8210Sstevel@tonic-gate break; 8220Sstevel@tonic-gate } 8230Sstevel@tonic-gate 8240Sstevel@tonic-gate tdp = xcalloc(sizeof (*tdp)); 8250Sstevel@tonic-gate tdp->t_type = INTRINSIC; 8260Sstevel@tonic-gate tdp->t_size = width; 8270Sstevel@tonic-gate tdp->t_name = NULL; 8280Sstevel@tonic-gate tdp->t_intr = intr; 8290Sstevel@tonic-gate parse_debug(3, NULL, "intrinsic: size=%d", width); 8300Sstevel@tonic-gate *rtdp = tdp; 8310Sstevel@tonic-gate 8320Sstevel@tonic-gate return (cp); 8330Sstevel@tonic-gate } 8340Sstevel@tonic-gate 8350Sstevel@tonic-gate static tdesc_t * 8360Sstevel@tonic-gate bitintrinsic(tdesc_t *template, int nbits) 8370Sstevel@tonic-gate { 8380Sstevel@tonic-gate tdesc_t *newtdp = xcalloc(sizeof (tdesc_t)); 8390Sstevel@tonic-gate 8400Sstevel@tonic-gate newtdp->t_name = xstrdup(template->t_name); 8410Sstevel@tonic-gate newtdp->t_id = faketypenumber++; 8420Sstevel@tonic-gate newtdp->t_type = INTRINSIC; 8430Sstevel@tonic-gate newtdp->t_size = template->t_size; 8440Sstevel@tonic-gate newtdp->t_intr = xmalloc(sizeof (intr_t)); 8450Sstevel@tonic-gate bcopy(template->t_intr, newtdp->t_intr, sizeof (intr_t)); 8460Sstevel@tonic-gate newtdp->t_intr->intr_nbits = nbits; 8470Sstevel@tonic-gate 8480Sstevel@tonic-gate return (newtdp); 8490Sstevel@tonic-gate } 8500Sstevel@tonic-gate 8510Sstevel@tonic-gate static char * 8520Sstevel@tonic-gate offsize(char *cp, mlist_t *mlp) 8530Sstevel@tonic-gate { 8540Sstevel@tonic-gate int offset, size; 8550Sstevel@tonic-gate 8560Sstevel@tonic-gate if (*cp == ',') 8570Sstevel@tonic-gate cp++; 8580Sstevel@tonic-gate cp = number(cp, &offset); 8590Sstevel@tonic-gate if (*cp++ != ',') 8600Sstevel@tonic-gate expected("offsize/2", ",", cp - 1); 8610Sstevel@tonic-gate cp = number(cp, &size); 8620Sstevel@tonic-gate if (*cp++ != ';') 8630Sstevel@tonic-gate expected("offsize/3", ";", cp - 1); 8640Sstevel@tonic-gate mlp->ml_offset = offset; 8650Sstevel@tonic-gate mlp->ml_size = size; 8660Sstevel@tonic-gate return (cp); 8670Sstevel@tonic-gate } 8680Sstevel@tonic-gate 8690Sstevel@tonic-gate static tdesc_t * 8700Sstevel@tonic-gate find_intrinsic(tdesc_t *tdp) 8710Sstevel@tonic-gate { 8720Sstevel@tonic-gate for (;;) { 8730Sstevel@tonic-gate switch (tdp->t_type) { 8740Sstevel@tonic-gate case TYPEDEF: 8750Sstevel@tonic-gate case VOLATILE: 8760Sstevel@tonic-gate case CONST: 8770Sstevel@tonic-gate case RESTRICT: 8780Sstevel@tonic-gate tdp = tdp->t_tdesc; 8790Sstevel@tonic-gate break; 8800Sstevel@tonic-gate 8810Sstevel@tonic-gate default: 8820Sstevel@tonic-gate return (tdp); 8830Sstevel@tonic-gate } 8840Sstevel@tonic-gate } 8850Sstevel@tonic-gate } 8860Sstevel@tonic-gate 8870Sstevel@tonic-gate static char * 8880Sstevel@tonic-gate soudef(char *cp, stabtype_t type, tdesc_t **rtdp) 8890Sstevel@tonic-gate { 8900Sstevel@tonic-gate mlist_t *mlp, **prev; 8910Sstevel@tonic-gate char *w; 8920Sstevel@tonic-gate int h; 8930Sstevel@tonic-gate int size; 8940Sstevel@tonic-gate tdesc_t *tdp, *itdp; 8950Sstevel@tonic-gate 8960Sstevel@tonic-gate cp = number(cp, &size); 8970Sstevel@tonic-gate (*rtdp)->t_size = size; 8980Sstevel@tonic-gate (*rtdp)->t_type = type; /* s or u */ 8990Sstevel@tonic-gate 9000Sstevel@tonic-gate /* 9010Sstevel@tonic-gate * An '@' here indicates a bitmask follows. This is so the 9020Sstevel@tonic-gate * compiler can pass information to debuggers about how structures 9030Sstevel@tonic-gate * are passed in the v9 world. We don't need this information 9040Sstevel@tonic-gate * so we skip over it. 9050Sstevel@tonic-gate */ 9060Sstevel@tonic-gate if (cp[0] == '@') { 9070Sstevel@tonic-gate cp += 3; 9080Sstevel@tonic-gate } 9090Sstevel@tonic-gate 9101882Sjohnlev parse_debug(3, cp, "soudef: %s size=%d", tdesc_name(*rtdp), 9110Sstevel@tonic-gate (*rtdp)->t_size); 9120Sstevel@tonic-gate 9130Sstevel@tonic-gate prev = &((*rtdp)->t_members); 9140Sstevel@tonic-gate /* now fill up the fields */ 9150Sstevel@tonic-gate while ((*cp != '\0') && (*cp != ';')) { /* signifies end of fields */ 9160Sstevel@tonic-gate mlp = xcalloc(sizeof (*mlp)); 9170Sstevel@tonic-gate *prev = mlp; 9180Sstevel@tonic-gate cp = name(cp, &w); 9190Sstevel@tonic-gate mlp->ml_name = w; 9200Sstevel@tonic-gate cp = id(cp, &h); 9210Sstevel@tonic-gate /* 9220Sstevel@tonic-gate * find the tdesc struct in the hash table for this type 9230Sstevel@tonic-gate * and stick a ptr in here 9240Sstevel@tonic-gate */ 9250Sstevel@tonic-gate tdp = lookup(h); 9260Sstevel@tonic-gate if (tdp == NULL) { /* not in hash list */ 9270Sstevel@tonic-gate parse_debug(3, NULL, " defines %s (%d)", w, h); 9280Sstevel@tonic-gate if (*cp++ != '=') { 9290Sstevel@tonic-gate tdp = unres_new(h); 9300Sstevel@tonic-gate parse_debug(3, NULL, 9310Sstevel@tonic-gate " refers to %s (unresolved %d)", 9320Sstevel@tonic-gate (w ? w : "anon"), h); 9330Sstevel@tonic-gate } else { 9340Sstevel@tonic-gate cp = tdefdecl(cp, h, &tdp); 9350Sstevel@tonic-gate 9360Sstevel@tonic-gate if (tdp->t_id && tdp->t_id != h) { 9370Sstevel@tonic-gate tdesc_t *ntdp = xcalloc(sizeof (*ntdp)); 9380Sstevel@tonic-gate 9390Sstevel@tonic-gate ntdp->t_type = TYPEDEF; 9400Sstevel@tonic-gate ntdp->t_tdesc = tdp; 9410Sstevel@tonic-gate tdp = ntdp; 9420Sstevel@tonic-gate } 9430Sstevel@tonic-gate 9440Sstevel@tonic-gate addhash(tdp, h); 9450Sstevel@tonic-gate parse_debug(4, cp, 9460Sstevel@tonic-gate " soudef now looking at "); 9470Sstevel@tonic-gate cp++; 9480Sstevel@tonic-gate } 9490Sstevel@tonic-gate } else { 9500Sstevel@tonic-gate parse_debug(3, NULL, " refers to %s (%d, %s)", 9511882Sjohnlev w ? w : "anon", h, tdesc_name(tdp)); 9520Sstevel@tonic-gate } 9530Sstevel@tonic-gate 9540Sstevel@tonic-gate cp = offsize(cp, mlp); 9550Sstevel@tonic-gate 9560Sstevel@tonic-gate itdp = find_intrinsic(tdp); 9570Sstevel@tonic-gate if (itdp->t_type == INTRINSIC) { 9580Sstevel@tonic-gate if (mlp->ml_size != itdp->t_intr->intr_nbits) { 9590Sstevel@tonic-gate parse_debug(4, cp, "making %d bit intrinsic " 9601882Sjohnlev "from %s", mlp->ml_size, tdesc_name(itdp)); 9610Sstevel@tonic-gate mlp->ml_type = bitintrinsic(itdp, mlp->ml_size); 9620Sstevel@tonic-gate } else 9630Sstevel@tonic-gate mlp->ml_type = tdp; 9640Sstevel@tonic-gate } else if (itdp->t_type == TYPEDEF_UNRES) { 9650Sstevel@tonic-gate list_add(&typedbitfldmems, mlp); 9660Sstevel@tonic-gate mlp->ml_type = tdp; 9670Sstevel@tonic-gate } else { 9680Sstevel@tonic-gate mlp->ml_type = tdp; 9690Sstevel@tonic-gate } 9700Sstevel@tonic-gate 9710Sstevel@tonic-gate /* cp is now pointing to next field */ 9720Sstevel@tonic-gate prev = &mlp->ml_next; 9730Sstevel@tonic-gate } 9740Sstevel@tonic-gate return (cp); 9750Sstevel@tonic-gate } 9760Sstevel@tonic-gate 9770Sstevel@tonic-gate static char * 9780Sstevel@tonic-gate arraydef(char *cp, tdesc_t **rtdp) 9790Sstevel@tonic-gate { 9800Sstevel@tonic-gate int start, end, h; 9810Sstevel@tonic-gate 9820Sstevel@tonic-gate cp = id(cp, &h); 9830Sstevel@tonic-gate if (*cp++ != ';') 9840Sstevel@tonic-gate expected("arraydef/1", ";", cp - 1); 9850Sstevel@tonic-gate 9860Sstevel@tonic-gate (*rtdp)->t_ardef = xcalloc(sizeof (ardef_t)); 9870Sstevel@tonic-gate (*rtdp)->t_ardef->ad_idxtype = lookup(h); 9880Sstevel@tonic-gate 9890Sstevel@tonic-gate cp = number(cp, &start); /* lower */ 9900Sstevel@tonic-gate if (*cp++ != ';') 9910Sstevel@tonic-gate expected("arraydef/2", ";", cp - 1); 9920Sstevel@tonic-gate 9930Sstevel@tonic-gate if (*cp == 'S') { 9940Sstevel@tonic-gate /* variable length array - treat as null dimensioned */ 9950Sstevel@tonic-gate cp++; 9960Sstevel@tonic-gate if (*cp++ != '-') 9970Sstevel@tonic-gate expected("arraydef/fpoff-sep", "-", cp - 1); 9980Sstevel@tonic-gate cp = number(cp, &end); 9990Sstevel@tonic-gate end = start; 10000Sstevel@tonic-gate } else { 10010Sstevel@tonic-gate /* normal fixed-dimension array */ 10020Sstevel@tonic-gate cp = number(cp, &end); /* upper */ 10030Sstevel@tonic-gate } 10040Sstevel@tonic-gate 10050Sstevel@tonic-gate if (*cp++ != ';') 10060Sstevel@tonic-gate expected("arraydef/3", ";", cp - 1); 10070Sstevel@tonic-gate (*rtdp)->t_ardef->ad_nelems = end - start + 1; 10080Sstevel@tonic-gate cp = tdefdecl(cp, h, &((*rtdp)->t_ardef->ad_contents)); 10090Sstevel@tonic-gate 10100Sstevel@tonic-gate parse_debug(3, cp, "defined array idx type %d %d-%d next ", 10110Sstevel@tonic-gate h, start, end); 10120Sstevel@tonic-gate 10130Sstevel@tonic-gate return (cp); 10140Sstevel@tonic-gate } 10150Sstevel@tonic-gate 10160Sstevel@tonic-gate static void 10170Sstevel@tonic-gate enumdef(char *cp, tdesc_t **rtdp) 10180Sstevel@tonic-gate { 10190Sstevel@tonic-gate elist_t *elp, **prev; 10200Sstevel@tonic-gate char *w; 10210Sstevel@tonic-gate 10220Sstevel@tonic-gate (*rtdp)->t_type = ENUM; 10230Sstevel@tonic-gate (*rtdp)->t_emem = NULL; 10240Sstevel@tonic-gate 10250Sstevel@tonic-gate prev = &((*rtdp)->t_emem); 10260Sstevel@tonic-gate while (*cp != ';') { 10270Sstevel@tonic-gate elp = xcalloc(sizeof (*elp)); 10280Sstevel@tonic-gate elp->el_next = NULL; 10290Sstevel@tonic-gate *prev = elp; 10300Sstevel@tonic-gate cp = name(cp, &w); 10310Sstevel@tonic-gate elp->el_name = w; 10320Sstevel@tonic-gate cp = number(cp, &elp->el_number); 10331882Sjohnlev parse_debug(3, NULL, "enum %s: %s=%d", tdesc_name(*rtdp), 10340Sstevel@tonic-gate elp->el_name, elp->el_number); 10350Sstevel@tonic-gate prev = &elp->el_next; 10360Sstevel@tonic-gate if (*cp++ != ',') 10370Sstevel@tonic-gate expected("enumdef", ",", cp - 1); 10380Sstevel@tonic-gate } 10390Sstevel@tonic-gate } 10400Sstevel@tonic-gate 10410Sstevel@tonic-gate tdesc_t * 1042*2722Sjohnlev lookup_name(tdesc_t **hash, const char *name) 10430Sstevel@tonic-gate { 10440Sstevel@tonic-gate int bucket = compute_sum(name); 10450Sstevel@tonic-gate tdesc_t *tdp, *ttdp = NULL; 10460Sstevel@tonic-gate 10470Sstevel@tonic-gate for (tdp = hash[bucket]; tdp != NULL; tdp = tdp->t_next) { 10480Sstevel@tonic-gate if (tdp->t_name != NULL && strcmp(tdp->t_name, name) == 0) { 10490Sstevel@tonic-gate if (tdp->t_type == STRUCT || tdp->t_type == UNION || 10500Sstevel@tonic-gate tdp->t_type == ENUM || tdp->t_type == INTRINSIC) 10510Sstevel@tonic-gate return (tdp); 10520Sstevel@tonic-gate if (tdp->t_type == TYPEDEF) 10530Sstevel@tonic-gate ttdp = tdp; 10540Sstevel@tonic-gate } 10550Sstevel@tonic-gate } 10560Sstevel@tonic-gate return (ttdp); 10570Sstevel@tonic-gate } 10580Sstevel@tonic-gate 10590Sstevel@tonic-gate tdesc_t * 1060*2722Sjohnlev lookupname(const char *name) 10610Sstevel@tonic-gate { 10620Sstevel@tonic-gate return (lookup_name(name_table, name)); 10630Sstevel@tonic-gate } 10640Sstevel@tonic-gate 10650Sstevel@tonic-gate /* 10660Sstevel@tonic-gate * Add a node to the hash queues. 10670Sstevel@tonic-gate */ 10680Sstevel@tonic-gate static void 10690Sstevel@tonic-gate addhash(tdesc_t *tdp, int num) 10700Sstevel@tonic-gate { 10710Sstevel@tonic-gate int hash = HASH(num); 10720Sstevel@tonic-gate tdesc_t *ttdp; 10730Sstevel@tonic-gate char added_num = 0, added_name = 0; 10740Sstevel@tonic-gate 10750Sstevel@tonic-gate /* 10760Sstevel@tonic-gate * If it already exists in the hash table don't add it again 10770Sstevel@tonic-gate * (but still check to see if the name should be hashed). 10780Sstevel@tonic-gate */ 10790Sstevel@tonic-gate ttdp = lookup(num); 10800Sstevel@tonic-gate 10810Sstevel@tonic-gate if (ttdp == NULL) { 10820Sstevel@tonic-gate tdp->t_id = num; 10830Sstevel@tonic-gate tdp->t_hash = hash_table[hash]; 10840Sstevel@tonic-gate hash_table[hash] = tdp; 10850Sstevel@tonic-gate added_num = 1; 10860Sstevel@tonic-gate } 10870Sstevel@tonic-gate 10880Sstevel@tonic-gate if (tdp->t_name != NULL) { 10890Sstevel@tonic-gate ttdp = lookupname(tdp->t_name); 10900Sstevel@tonic-gate if (ttdp == NULL) { 10910Sstevel@tonic-gate hash = compute_sum(tdp->t_name); 10920Sstevel@tonic-gate tdp->t_next = name_table[hash]; 10930Sstevel@tonic-gate name_table[hash] = tdp; 10940Sstevel@tonic-gate added_name = 1; 10950Sstevel@tonic-gate } 10960Sstevel@tonic-gate } 10970Sstevel@tonic-gate if (!added_num && !added_name) { 10980Sstevel@tonic-gate terminate("stabs: broken hash\n"); 10990Sstevel@tonic-gate } 11000Sstevel@tonic-gate } 11010Sstevel@tonic-gate 11020Sstevel@tonic-gate static int 1103*2722Sjohnlev compute_sum(const char *w) 11040Sstevel@tonic-gate { 11050Sstevel@tonic-gate char c; 11060Sstevel@tonic-gate int sum; 11070Sstevel@tonic-gate 11080Sstevel@tonic-gate for (sum = 0; (c = *w) != '\0'; sum += c, w++) 11090Sstevel@tonic-gate ; 11100Sstevel@tonic-gate return (HASH(sum)); 11110Sstevel@tonic-gate } 11120Sstevel@tonic-gate 11130Sstevel@tonic-gate static void 11140Sstevel@tonic-gate reset(void) 11150Sstevel@tonic-gate { 11160Sstevel@tonic-gate longjmp(resetbuf, 1); 11170Sstevel@tonic-gate } 11180Sstevel@tonic-gate 11190Sstevel@tonic-gate void 11200Sstevel@tonic-gate check_hash(void) 11210Sstevel@tonic-gate { 11220Sstevel@tonic-gate tdesc_t *tdp; 11230Sstevel@tonic-gate int i; 11240Sstevel@tonic-gate 11250Sstevel@tonic-gate printf("checking hash\n"); 11260Sstevel@tonic-gate for (i = 0; i < BUCKETS; i++) { 11270Sstevel@tonic-gate if (hash_table[i]) { 11280Sstevel@tonic-gate for (tdp = hash_table[i]->t_hash; 11290Sstevel@tonic-gate tdp && tdp != hash_table[i]; 11300Sstevel@tonic-gate tdp = tdp->t_hash) 11310Sstevel@tonic-gate continue; 11320Sstevel@tonic-gate if (tdp) { 11330Sstevel@tonic-gate terminate("cycle in hash bucket %d\n", i); 11340Sstevel@tonic-gate return; 11350Sstevel@tonic-gate } 11360Sstevel@tonic-gate } 11370Sstevel@tonic-gate 11380Sstevel@tonic-gate if (name_table[i]) { 11390Sstevel@tonic-gate for (tdp = name_table[i]->t_next; 11400Sstevel@tonic-gate tdp && tdp != name_table[i]; 11410Sstevel@tonic-gate tdp = tdp->t_next) 11420Sstevel@tonic-gate continue; 11430Sstevel@tonic-gate if (tdp) { 11440Sstevel@tonic-gate terminate("cycle in name bucket %d\n", i); 11450Sstevel@tonic-gate return; 11460Sstevel@tonic-gate } 11470Sstevel@tonic-gate } 11480Sstevel@tonic-gate } 11490Sstevel@tonic-gate printf("done\n"); 11500Sstevel@tonic-gate } 11510Sstevel@tonic-gate 11520Sstevel@tonic-gate /*ARGSUSED1*/ 11530Sstevel@tonic-gate static int 11540Sstevel@tonic-gate resolve_typed_bitfields_cb(mlist_t *ml, void *private) 11550Sstevel@tonic-gate { 11560Sstevel@tonic-gate tdesc_t *tdp = ml->ml_type; 11570Sstevel@tonic-gate 11580Sstevel@tonic-gate debug(3, "Resolving typed bitfields (member %s)\n", 11590Sstevel@tonic-gate (ml->ml_name ? ml->ml_name : "(anon)")); 11600Sstevel@tonic-gate 11610Sstevel@tonic-gate while (tdp) { 11620Sstevel@tonic-gate switch (tdp->t_type) { 11630Sstevel@tonic-gate case INTRINSIC: 11640Sstevel@tonic-gate if (ml->ml_size != tdp->t_intr->intr_nbits) { 11650Sstevel@tonic-gate debug(3, "making %d bit intrinsic from %s", 11661882Sjohnlev ml->ml_size, tdesc_name(tdp)); 11670Sstevel@tonic-gate ml->ml_type = bitintrinsic(tdp, ml->ml_size); 11680Sstevel@tonic-gate } else { 11690Sstevel@tonic-gate debug(3, "using existing %d bit %s intrinsic", 11701882Sjohnlev ml->ml_size, tdesc_name(tdp)); 11710Sstevel@tonic-gate ml->ml_type = tdp; 11720Sstevel@tonic-gate } 11730Sstevel@tonic-gate return (1); 11740Sstevel@tonic-gate 11750Sstevel@tonic-gate case POINTER: 11760Sstevel@tonic-gate case TYPEDEF: 11770Sstevel@tonic-gate case VOLATILE: 11780Sstevel@tonic-gate case CONST: 11790Sstevel@tonic-gate case RESTRICT: 11800Sstevel@tonic-gate tdp = tdp->t_tdesc; 11810Sstevel@tonic-gate break; 11820Sstevel@tonic-gate 11830Sstevel@tonic-gate default: 11840Sstevel@tonic-gate return (1); 11850Sstevel@tonic-gate } 11860Sstevel@tonic-gate } 11870Sstevel@tonic-gate 11880Sstevel@tonic-gate terminate("type chain for bitfield member %s has a NULL", ml->ml_name); 11890Sstevel@tonic-gate /*NOTREACHED*/ 11900Sstevel@tonic-gate return (0); 11910Sstevel@tonic-gate } 11920Sstevel@tonic-gate 11930Sstevel@tonic-gate void 11940Sstevel@tonic-gate resolve_typed_bitfields(void) 11950Sstevel@tonic-gate { 11960Sstevel@tonic-gate (void) list_iter(typedbitfldmems, 11970Sstevel@tonic-gate (int (*)())resolve_typed_bitfields_cb, NULL); 11980Sstevel@tonic-gate } 1199