st_parse.c revision 970495fcbe163a92c91929e60f2f45102d42c9cb
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/*
* This file is a sewer.
*/
#include <limits.h>
#include <stdarg.h>
#include <stdio.h>
#include <assert.h>
#include <strings.h>
#include <setjmp.h>
#include <ctype.h>
#include "ctftools.h"
#include "memory.h"
#include "list.h"
#define BUCKETS 128
#define TYPEPAIRMULT 10000
static int faketypenumber = 100000000;
static void reset(void);
static int compute_sum(const char *w);
extern int debug_level;
int debug_parse = DEBUG_PARSE;
/*PRINTFLIKE3*/
static void
{
char buf[1024];
char tmp[32];
int i;
return;
for (i = 0; i < 30; i++) {
if (cp[i] == '\0')
break;
}
tmp[i] = '\0';
} else {
}
}
/* Report unexpected syntax in stabs. */
static void
char *who, /* what function, or part thereof, is reporting */
char *what, /* what was expected */
char *where, /* where we were in the line of input */
int line)
{
reset();
}
/*ARGSUSED*/
void
{
int i;
for (i = 0; i < BUCKETS; i++) {
hash_table[i] = NULL;
name_table[i] = NULL;
}
if (typedbitfldmems != NULL) {
}
}
void
{
}
static tdesc_t *
{
return (tdp);
}
char *
{
int tid;
if (*cp == '=') {
return (NULL);
}
return (cp);
}
static iitype_t
{
int nargs = 0;
int va = 0;
/*
* name:P prototype
* name:F global function
* name:f static function
*/
switch (*cp++) {
case 'P':
break;
case 'F':
break;
case 'f':
break;
default:
}
return (-1);
if (*cp)
if (*cp == '0') {
va = 1;
continue;
}
nargs++;
if (nargs > FUNCARG_DEF)
return (-1);
}
return (iitype);
}
static iitype_t
{
/*
* name:G global variable
* name:S static variable
*/
switch (*cp++) {
case 'G':
break;
case 'S':
break;
case 'p':
break;
case '(':
cp--;
/*FALLTHROUGH*/
case 'r':
case 'V':
break;
default:
}
return (-1);
return (iitype);
}
static iitype_t
{
int tid;
if (*cp++ != 't')
if (*cp++ != '=')
}
}
}
return (-1);
}
return (II_TYPE);
}
static iitype_t
{
int tid;
if (*cp++ != 'T')
if (*cp++ != '=')
}
}
} else {
}
switch (*cp++) {
case 's':
break;
case 'u':
break;
case 'e':
break;
default:
break;
}
return (II_SOU);
}
int
{
int rc;
/*
* set up for reset()
*/
return (-1);
case N_FUN:
break;
case N_LSYM:
if (*cp == 't')
parse = parse_type;
else if (*cp == 'T')
else
break;
case N_GSYM:
case N_LCSYM:
case N_PSYM:
case N_ROSYM:
case N_RSYM:
case N_STSYM:
break;
default:
return (-1);
}
return (rc);
}
return (1);
}
/*
* Check if we have this node in the hash table already
*/
tdesc_t *
lookup(int h)
{
return (tdp);
}
return (NULL);
}
static char *
{
char c;
;
--cp;
return (cp);
}
static char *
{
int len;
c = *cp++;
if (c == ':')
*w = NULL;
;
if (c != ':')
reset();
*new = '\0';
} else
reset();
return (cp);
}
static char *
{
char *next;
return (next);
}
static char *
{
cp++;
if (*cp++ != ',')
if (*cp++ != ')')
*h = n1;
} else {
}
return (cp);
}
static int
{
warning("duplicate entry\n");
return (-1);
}
return (0);
}
static char *
{
char *w;
int c, h2;
char type;
/* Type codes */
case 'b': /* integer */
case 'R': /* fp */
break;
case '(': /* equiv to another type */
/*
* The 6.2 compiler, and possibly others, will
* sometimes emit the same stab for a forward
* declaration twice. That is, "(1,2)=xsfoo:"
* will sometimes show up in two different
* places. This is, of course, quite fun. We
* want CTF to work in spite of the compiler,
* so we'll let this one through.
*/
char *nm;
c2 - 1);
}
terminate("Stabs error: Attempt to "
"redefine type (%d,%d) as "
"something else: %s\n",
c2 - 1);
}
h2 = faketypenumber++;
} else {
terminate("Stabs error: Attempting to "
}
}
if (*cp != '=') {
/* record it as unresolved */
h2);
break;
} else
cp++;
/* define a new type */
}
} else { /* that type is already defined */
} else {
"No duplicate typedef anon for ref");
}
}
break;
case '*':
break;
case 'f':
/*
* The 6.1 compiler will sometimes generate incorrect stabs for
* function pointers (it'll get the return type wrong). This
* causes merges to fail. We therefore treat function pointers
* as if they all point to functions that return int. When
* 4432549 is fixed, the lookupname() call below should be
* replaced with `ntdp'.
*/
break;
case 'a':
case 'z':
cp++;
if (*cp++ != 'r')
break;
case 'x':
c = *++cp;
if (c != 's' && c != 'u' && c != 'e')
/*
* We explicitly don't set t_id here - the caller will do it.
* The caller may want to use a real type ID, or they may
* choose to make one up.
*/
break;
case 'B': /* volatile */
break;
case 'k': /* const */
break;
case 'K': /* restricted */
break;
case 'u':
case 's':
cp++;
break;
default:
}
return (cp);
}
static char *
{
switch (*cp++) {
case 'b':
if (*cp == 's')
else if (*cp != 'u')
cp++;
if (*cp++ != ';')
if (*cp++ != ';')
break;
case 'R':
cp += i;
if (*cp++ != ';')
break;
}
return (cp);
}
static tdesc_t *
{
return (newtdp);
}
static char *
{
if (*cp == ',')
cp++;
if (*cp++ != ',')
if (*cp++ != ';')
return (cp);
}
static tdesc_t *
{
for (;;) {
case TYPEDEF:
case VOLATILE:
case CONST:
case RESTRICT:
break;
default:
return (tdp);
}
}
}
static char *
{
char *w;
int h;
int size;
/*
* An '@' here indicates a bitmask follows. This is so the
* compiler can pass information to debuggers about how structures
* are passed in the v9 world. We don't need this information
* so we skip over it.
*/
if (cp[0] == '@') {
cp += 3;
}
/* now fill up the fields */
/*
* find the tdesc struct in the hash table for this type
* and stick a ptr in here
*/
if (*cp++ != '=') {
" refers to %s (unresolved %d)",
(w ? w : "anon"), h);
} else {
}
" soudef now looking at ");
cp++;
}
} else {
}
} else
} else {
}
/* cp is now pointing to next field */
}
return (cp);
}
static char *
{
if (*cp++ != ';')
if (*cp++ != ';')
if (*cp == 'S') {
/* variable length array - treat as null dimensioned */
cp++;
if (*cp++ != '-')
} else {
/* normal fixed-dimension array */
}
if (*cp++ != ';')
return (cp);
}
static void
{
char *w;
while (*cp != ';') {
if (*cp++ != ',')
}
}
tdesc_t *
{
return (tdp);
}
}
return (ttdp);
}
tdesc_t *
lookupname(const char *name)
{
}
/*
* Add a node to the hash queues.
*/
static void
{
char added_num = 0, added_name = 0;
/*
* If it already exists in the hash table don't add it again
* (but still check to see if the name should be hashed).
*/
added_num = 1;
}
added_name = 1;
}
}
if (!added_num && !added_name) {
terminate("stabs: broken hash\n");
}
}
static int
compute_sum(const char *w)
{
char c;
int sum;
;
}
static void
reset(void)
{
}
void
check_hash(void)
{
int i;
printf("checking hash\n");
for (i = 0; i < BUCKETS; i++) {
if (hash_table[i]) {
continue;
if (tdp) {
terminate("cycle in hash bucket %d\n", i);
return;
}
}
if (name_table[i]) {
continue;
if (tdp) {
terminate("cycle in name bucket %d\n", i);
return;
}
}
}
printf("done\n");
}
/*ARGSUSED1*/
static int
{
while (tdp) {
case INTRINSIC:
} else {
}
return (1);
case POINTER:
case TYPEDEF:
case VOLATILE:
case CONST:
case RESTRICT:
break;
default:
return (1);
}
}
/*NOTREACHED*/
return (0);
}
void
resolve_typed_bitfields(void)
{
(void) list_iter(typedbitfldmems,
(int (*)())resolve_typed_bitfields_cb, NULL);
}