#ifndef lint
static char rcsid[] = "$Header:stab.c 12.0$";
#endif
/* $Source: /ibm/acis/usr/src/lib/pcc_ca/RCS/stab.c,v $ */

#ifndef lint
static char *sccsid ="@(#)stab.c    1.10 (Berkeley) 10/22/83";
#endif
/*
 * Symbolic debugging info interface.
 *
 * Here we generate pseudo-ops that cause the assembler to put
 * symbolic debugging information into the object file.
 */

#ifdef unix
# include "mfile1.h"
# include <sys/types.h>
# include <a.out.h>
# include <stab.h>
#else
# include "doption h *"  /* circumvention for -D problem with preprocessor */
# include "mfile1 h *"
# include "types h *"
#ifdef FORUNIX
# include "aout h t"
# include "stab h t"
#else
# include "aout h *"
# include "stab h *"
#endif
#endif

#define private static
#define and &&
#define or ||
#define not !
#define div /
#define mod %
#define nil 0

#define bytes(bits) ((bits) / SZCHAR)
#define bsize(p) bytes(dimtab[p->sizoff])   /* size in bytes of a symbol */

#define NILINDEX -1
#define FORWARD -2

typedef int Boolean;

#define false 0
#define true 1

extern int ROdata;  /* data is Read-Only -- STATICS are not optimized!! */
extern int ddebug;
extern int gdebug;
extern char *malloc();
extern int optize;  /* added 12/84 by JEC for ibm032 optimizer */


int stabLCSYM;

/*
 * Flag for producing either sdb or dbx symbol information.
 */
int oldway = false;

/*
 * Generate debugging info for a parameter.
 * The offset isn't known when it is first entered into the symbol table
 * since the types are read later.
 */

fixarg(p)
register struct symtab *p;
{
	if (oldway) {
		old_fixarg(p);
	} 
	else if (gdebug) { 
		int off=bytes(argoff)-(ARGINIT/SZCHAR);
		printf("\t.stabs\t\"%s:p", p->sname);
		gentype(p);
		/*
		 * Check to see if this is a pointer.  If so leave the offset
		 * alone.  Otherwise, adjust the offset to the beginning of
		 *  a char, short or int.    --kas 10/16/86	
		 */
		if ( (p->stype&TMASK) == PTR )
			printf("\",0x%x,0,%d,%d\n", N_PSYM, bsize(p), off );
		else 
		    switch ( bsize(p)*SZCHAR ) {
		    case SZCHAR:
			printf("\",0x%x,0,%d,%d\n", N_PSYM, bsize(p), off+3 );
			break;
		    case SZSHORT:
			printf("\",0x%x,0,%d,%d\n", N_PSYM, bsize(p), off+2 );
			break;
		    default:
			printf("\",0x%x,0,%d,%d\n", N_PSYM, bsize(p), off );
			break;
		}
	}
}

/*
 * Determine if the given symbol is a global array with dimension 0,
 * which only makes sense if it's dimension is to be given later.
 * We therefore currently do not generate symbol information for
 * such entries.
 */

#define isglobal(class) ( \
class == EXTDEF or class == EXTERN or class == STATIC \
)

private Boolean zero_length_array(p)
register struct symtab *p;
{
	Boolean b;
	int t;

	if (not isglobal(p->sclass)) {
		b = false;
	} 
	else {
		t = p->stype;
		if (ISFTN(t)) {
			t = DECREF(t);
		}
		b = (Boolean) (ISARY(t) and dimtab[p->dimoff] == 0);
	}
	return b;
}

/*
 * Generate debugging info for a given symbol.
 */

outstab(sym)
register struct symtab *sym;
{
	register struct symtab *p;
	register char *classname;
	register Boolean ignore;
	static Boolean firsttime = true;

	if( optize && sym->sclass != PARAM )
	    dns_sym(sym);

	if (oldway) {
		old_outstab(sym);
	} 
	else if (gdebug and not zero_length_array(sym)) {
		if (firsttime) {
			firsttime = false;
			inittypes();
		}
		ignore = false;
		p = sym;
		switch (p->sclass) {
		case REGISTER:
			classname = "r";
			break;

		/*
		 * Locals are the default class.
		 */
		case AUTO:
			classname = "";
			break;

		case STATIC:
			if (ISFTN(p->stype)) {
				ignore = true;
			} 
			else if (p->slevel > 1) {
				classname = "V";
			} 
			else {
				classname = "S";
			}
			break;

		case EXTDEF:
		case EXTERN:
			if (ISFTN(p->stype)) {
				ignore = true;
			} 
			else {
				classname = "G";
			}
			break;

		case TYPEDEF:
			classname = "t";
			break;

		case PARAM:
		case MOS:
		case MOU:
		case MOE:
			ignore = true;
			break;

		case ENAME:
		case UNAME:
		case STNAME:
			entertype(p->stype, NILINDEX, FORWARD, dimtab[p->sizoff + 3]);
			ignore = true;
			break;

		default:
			if ((p->sclass&FIELD) == 0) {
				printf("/* no info for %s (%d) */\n", p->sname, p->sclass);
			}
			ignore = true;
			break;
		}
		if (not ignore) {
			printf("\t.stabs\t\"%s:%s", p->sname, classname);
			gentype(p);
			geninfo(p);
		}
	}
}

/*
 * Since type names are lost in the travels and because C has
 * structural type equivalence we keep a table of type words that
 * we've already seen.  The first time we see a type, it is assigned
 * (inline) a number and future references just list that number.
 * Structures, unions, enums, and arrays must be handled carefully
 * since not all the necessary information is in the type word.
 */

typedef struct Typeid *Typeid;

struct Typeid {
	TWORD tword;
	int tarray;
	int tstruct;
	int tstrtag;
	int tnum;
	Typeid chain;
};

#define TABLESIZE 2003

private int tcount = 1;
private int t_int, t_char;
private Typeid typetable[TABLESIZE];

/*
 * Look for the given type word in the type table.
 */

private Typeid typelookup(type, arrindex, strindex, strtag)
TWORD type;
int arrindex;
int strindex;
int strtag;
{
	register TWORD tword;
	register int i1, i2;
	Typeid t;

	t = typetable[type mod TABLESIZE];
	while (t != nil) {
		if (t->tword == type and
		    strindex == t->tstruct and strtag == t->tstrtag) {
			if (arrindex == NILINDEX) {
				break;
			} 
			else {
				tword = type;
				i1 = arrindex;
				i2 = t->tarray;
				while (ISARY(tword) and dimtab[i1] == dimtab[i2]) {
					++i1;
					++i2;
					tword >>= TSHIFT;
				}
				if (!ISARY(tword)) {
					break;
				}
			}
		}
		t = t->chain;
	}
	return t;
}

/*
 * Enter a type word and associated symtab indices into the type table.
 */

private int entertype(type, arrindex, strindex, strtag)
TWORD type;
int arrindex;
int strindex;
int strtag;
{
	register Typeid t;
	register int i;

	t = (Typeid) malloc(sizeof(struct Typeid));
	t->tword = type;
	t->tarray = arrindex;
	t->tstruct = strindex;
	t->tstrtag = strtag;
	t->tnum = tcount;
	++tcount;
	i = type mod TABLESIZE;
	t->chain = typetable[i];
	typetable[i] = t;
	return t->tnum;
}

/*
 * Change the information associated with a type table entry.
 * Since I'm lazy this just creates a new entry with the number
 * as the old one.
 */

private reentertype(typeid, type, arrindex, strindex, strtag)
Typeid typeid;
TWORD type;
int arrindex;
int strindex;
int strtag;
{
	register Typeid t;
	register int i;

	t = (Typeid) malloc(sizeof(struct Typeid));
	t->tword = type;
	t->tarray = arrindex;
	t->tstruct = strindex;
	t->tstrtag = strtag;
	t->tnum = typeid->tnum;
	i = type mod TABLESIZE;
	t->chain = typetable[i];
	typetable[i] = t;
}

/*
 * Initialize type table with predefined types.
 */

#define builtintype(type) entertype(type, NILINDEX, NILINDEX, NILINDEX)

private inittypes()
{
	int t;

	t_int = builtintype(INT);
	t_char = builtintype(CHAR);
	maketype("int", t_int, t_int, 0x80000000L, 0x7fffffffL);
	maketype("char", t_char, t_char, 0L, 127L);
	maketype("long", builtintype(LONG), t_int, 0x80000000L, 0x7fffffffL);
	maketype("short", builtintype(SHORT), t_int, 0xffff8000L, 0x7fffL);
	maketype("unsigned char", builtintype(UCHAR), t_int, 0L, 255L);
	maketype("unsigned short", builtintype(USHORT), t_int, 0L, 0xffffL);
	maketype("unsigned long", builtintype(ULONG), t_int, 0L, 0xffffffffL);
	maketype("unsigned int", builtintype(UNSIGNED), t_int,0L,0xffffffffL);
	maketype("float", builtintype(FLOAT), t_int, 4L, 0L);
	maketype("double", builtintype(DOUBLE), t_int, 8L, 0L);
	t = builtintype(UNDEF);
	printf("\t.stabs\t\"void:t%d=%d", t, t);
	geninfo(nil);
	t = builtintype(FARG);
	printf("\t.stabs\t\"???:t%d=%d", t, t_int);
	geninfo(nil);
}

/*
 * Generate info for a new range type.
 */

private maketype(name, tnum, eqtnum, lower, upper)
char *name;
int tnum, eqtnum;
long lower, upper;
{
	printf("\t.stabs\t\"%s:t%d=r%d;%d;%d;",name,tnum,eqtnum,lower,upper);
	geninfo(nil);
}

/*
 * Generate debugging information for the given type of the given symbol.
 */

private gentype(sym)
struct symtab *sym;
{
	register struct symtab *p;
	register TWORD t;
	register TWORD basictype;
	register Typeid typeid;
	int i, arrindex, strindex, strtag;

	p = sym;
	t = p->stype;
	if (ISFTN(t)) {
		t = DECREF(t);
	}
	basictype = BTYPE(t);
	if (ISARY(t)) {
		arrindex = p->dimoff;
	} 
	else {
		arrindex = NILINDEX;
	}
	if (basictype == STRTY or basictype == UNIONTY or basictype==ENUMTY) {
		strindex = dimtab[p->sizoff + 1];
		if (strindex == -1) {
			strindex = FORWARD;
			strtag = dimtab[p->sizoff + 3];
		} 
		else {
			strtag = NILINDEX;
		}
	} 
	else {
		strindex = NILINDEX;
		strtag = NILINDEX;
	}
	i = arrindex;
	typeid = typelookup(t, arrindex, strindex, strtag);
	while (t != basictype and typeid == nil) {
		printf("%d=", entertype(t, i, strindex, strtag));
		switch (t&TMASK) {
		case PTR:
			printf("*");
			break;

		case FTN:
			printf("f");
			break;

		case ARY:
			printf("ar%d;0;%d;", t_int, dimtab[i++] - 1);
			break;
		}
		t = DECREF(t);
		if (t == basictype) {
			typeid = typelookup(t, NILINDEX, strindex, strtag);
		} 
		else {
			typeid = typelookup(t, i, strindex, strtag);
		}
	}
	if (typeid == nil) {
		if (strindex == FORWARD) {
			typeid = typelookup(t, NILINDEX, FORWARD, dimtab[p->sizoff + 3]);
			if (typeid == nil) {
				cerror("unbelievable forward reference");
			}
			printf("%d", typeid->tnum);
		} 
		else {
			genstruct(t, NILINDEX, strindex, p->sname, bsize(p));
		}
	} 
	else {
		printf("%d", typeid->tnum);
	}
}

/*
 * Generate type information for structures, unions, and enumerations.
 */

private genstruct(t, structid, index, name, size)
TWORD t;
int structid;
int index;
char *name;
int size;
{
	register int i;
	register struct symtab *field;
	int id;

	if (structid == NILINDEX) {
		id = entertype(t, NILINDEX, index, NILINDEX);
	} 
	else {
		id = structid;
	}
	switch (t) {
	case STRTY:
	case UNIONTY:
		printf("%d=%c%d", id, t == STRTY ? 's' : 'u', size);
		i = index;
		while (dimtab[i] != -1) {
			field = &stab[dimtab[i]];
			printf("%s:", field->sname);
			gentype(field);
			if (field->sclass > FIELD) {
				printf(",%d,%d;", field->offset, field->sclass - FIELD);
			} 
			else {
				printf(",%d,%d;", field->offset,
				tsize(field->stype, field->dimoff, field->sizoff));
			}
			++i;
		}
		putchar(';');
		break;

	case ENUMTY:
		printf("%d=e", id);
		i = index;
		while (dimtab[i] != -1) {
			field = &stab[dimtab[i]];
			printf("%s:%d,", field->sname, field->offset);
			i++;
		}
		putchar(';');
		break;

	default:
		cerror("couldn't find basic type %d for %s\n", t, name);
		break;
	}
}

/*
 * Generate offset and size info.
 */

private geninfo(p)
register struct symtab *p;
{
	if (p == nil) {
		printf("\",0x%x,0,0,0\n", N_LSYM);
	} 
	else {
	    switch (p->sclass) {
	    case EXTERN:
	    case EXTDEF:
		if (ISFTN(p->stype)) {
		    printf("\",0x%x,0,%d,_.%s\n", N_FUN, bsize(p), p->sname);
		} 
		else {
		    printf("\",0x%x,0,%d,0\n", N_GSYM, bsize(p));
		}
		break;

	    case STATIC:
	    {
		int sz;
		if (ISFTN(p->stype)) {
		    printf("\",0x%x,0,%d,_.%s\n", N_FUN, bsize(p), p->sname);
		} 
		else {
		    sz = tsize(p->stype, p->dimoff, p->sizoff )/SZCHAR;
		    if (p->slevel > 1) {
			if ( stabLCSYM && (sz > 8 || ROdata) ) {
			    /* uninitialized static > 2 words */
			    printf("\",0x%x,0,%d,LCOM%d\n",N_LCSYM,bsize(p),p->offset);
			}	
		        else {
			    printf("\",0x%x,0,%d,L%d\n", N_STSYM,bsize(p), p->offset);
			}
		    } 
		    else {
			if (stabLCSYM && (sz > 8 || ROdata) ) {
			    /* uninitialized static > 2 words */
			    printf("\",0x%x,0,%d,_%s\n", N_LCSYM, bsize(p), p->sname);
			} 
			else {
			    printf("\",0x%x,0,%d,_%s\n", N_STSYM, bsize(p), p->sname);
			}
		    }
		}
		break;
	    }

	    case REGISTER:
		printf("\",0x%x,0,%d,%d\n", N_RSYM, bsize(p), p->offset);
		break;

	    case PARAM:
	    {
		int off=bytes(argoff)-(ARGINIT/SZCHAR);
		if ( (p->stype&TMASK) == PTR )
		    printf("\",0x%x,0,%d,%d\n", N_PSYM, bsize(p), off );
		else 
		    switch ( bsize(p)*SZCHAR ) {
		    case SZCHAR:
			printf("\",0x%x,0,%d,%d\n", N_PSYM, bsize(p), off+3 );
			break;
		    case SZSHORT:
			printf("\",0x%x,0,%d,%d\n", N_PSYM, bsize(p), off+2 );
			break;
		    default:
			printf("\",0x%x,0,%d,%d\n", N_PSYM, bsize(p), off );
			break;
		    }
		break;
	    }

	    default:
		printf("\",0x%x,0,%d,%d\n", N_LSYM, bsize(p), bytes(p->offset+AUTOINIT));
		break;
	    }
	}
}

/*
 * Generate information for a newly-defined structure.
 */

outstruct(szindex, paramindex)
int szindex, paramindex;
{
	register Typeid typeid;
	register struct symtab *p;
	register int i, t, strindex;

	if (oldway) {
		/* do nothing */;
	} 
	else if (gdebug) {
		i = dimtab[szindex + 3];
		p = &stab[i];
		if (p->sname != nil) {
			strindex = dimtab[p->sizoff + 1];
			typeid = typelookup(p->stype, NILINDEX, FORWARD, i);
			if (typeid == nil) {
				t = 0;
			} 
			else {
				t = typeid->tnum;
				reentertype(typeid, p->stype, NILINDEX, strindex, NILINDEX);
			}
			printf("\t.stabs\t\"%s:T", p->sname);
			genstruct(p->stype, t, strindex, p->sname, bsize(p));
			geninfo(p);
		}
	}
}

pstab(name, type)
register char *name;
register int type;
{
	if (!gdebug) {
		return;
	} 
	else if (oldway) {
		old_pstab(name, type);
		return;
	}
	/* locctr(PROG);  /* .stabs must appear in .text for c2 */
#ifdef ASSTRINGS
	if ( name[0] == '\0')
	    printf("\t.stabn\t");
	else
#ifndef FLEXNAMES
	    printf("\t.stabs\t\"%.8s\",", name);
#else
	printf("\t.stabs\t\"%s\",", name);
#endif
#else
	printf("    .stab   ");
	for(i=0; i<8; i++)
		if (c = name[i]) 
			printf("'%c,", c);
		else printf("0,");
#endif
	printf("0%o,", type);
}

#ifdef STABDOT
pstabdot(type, value)
register int type;
register int value;
{
	if ( ! gdebug) {
		return;
	} 
	else if (oldway) {
		old_pstabdot(type, value);
		return;
	}
	/* locctr(PROG);  /* .stabs must appear in .text for c2 */
	printf("\t.stabd\t");
	printf("0%o,0,0%o\n",type, value);
}
#endif

extern char NULLNAME[8];
extern int  labelno;
extern int  fdefflag;

psline()
{
	static int lastlineno;
	register char *cp, *cq;
	register int i;

	if (!gdebug) {
		return;
	} 
	else if (oldway) {
		old_psline();
		return;
	}

	cq = ititle;
	cp = ftitle;

	while ( *cq ) if ( *cp++ != *cq++ ) goto neq;
	if ( *cp == '\0' ) goto eq;

neq:    
	for (i=0; i<100; i++)
		ititle[i] = '\0';
	cp = ftitle;
	cq = ititle;
	while ( *cp )
	    *cq++ = *cp++;
	*cq = '\0';
	*--cq = '\0';
#ifndef FLEXNAMES
	for ( cp = ititle+1; *(cp-1); cp += 8 ) {
		pstab(cp, N_SOL);
		if (gdebug) printf("0,0,LL%d\n", labelno);
	}
#else
	pstab(ititle+1, N_SOL);
	if (gdebug) printf("0,0,LL%d\n", labelno);
#endif
	*cq = '"';
	printf("LL%d:\n", labelno++);

eq: 
	if (lineno == lastlineno) return;
	lastlineno = lineno;

	if (fdefflag) {
#ifdef STABDOT
		pstabdot(N_SLINE, lineno);
#else
		pstab(NULLNAME, N_SLINE);
		printf("0,%d,LL%d\n", lineno, labelno);
		printf("LL%d:\n", labelno++);
#endif
	}
}

plcstab(level)
register int level;
{
	if (!gdebug) {
		return;
	} 
	else if (oldway) {
		old_plcstab(level);
		return;
	}
locctr( PROG );
#ifdef STABDOT
	pstabdot(N_LBRAC, level);
#else
	pstab(NULLNAME, N_LBRAC);
	printf("0,%d,LL%d\n", level, labelno);
	printf("LL%d:\n", labelno++);
#endif
}

prcstab(level)
register int level;
{
	if (!gdebug) {
		return;
	} 
	else if (oldway) {
		old_prcstab(level);
		return;
	}
#ifdef STABDOT
	pstabdot(N_RBRAC, level);
#else
	pstab(NULLNAME, N_RBRAC);
	printf("0,%d,LL%d\n", level, labelno);
	printf("LL%d:\n", labelno++);
#endif
}

pfstab(sname)
register char *sname;
{
	register struct symtab *p;

	if (gdebug) {
		if (oldway) {
			old_pfstab(sname);
		} 
		else {
			p = &stab[lookup(sname, 0)];
			printf("\t.stabs\t\"%s:", p->sname);
			putchar((p->sclass == STATIC) ? 'f' : 'F');
			gentype(p);
			geninfo(p);
		}
	}
}

/*
 * Old way of doing things.
 */

private old_fixarg(p)
struct symtab *p; 
{
	if (gdebug) {
		old_pstab(p->sname, N_PSYM);
		if (gdebug) printf("0,%d,%d\n", p->stype, argoff/SZCHAR);
		old_poffs(p);
	}
}

private old_outstab(p)
struct symtab *p; 
{
	register TWORD ptype;
	register char *pname;
	register char pclass;
	register int poffset;

	if (!gdebug) return;

	ptype = p->stype;
	pname = p->sname;
	pclass = p->sclass;
	poffset = p->offset;

	if (ISFTN(ptype)) {
		return;
	}

	switch (pclass) {

	case AUTO:
		old_pstab(pname, N_LSYM);
		printf("0,%d,%d\n", ptype, (-poffset)/SZCHAR);
		old_poffs(p);
		return;

	case EXTDEF:
	case EXTERN:
		old_pstab(pname, N_GSYM);
		printf("0,%d,0\n", ptype);
		old_poffs(p);
		return;

	case STATIC:
	{
#ifdef LCOMM
	/* This code never seems to be called.  If it ever is, you 
	 * may need this code because of the .lcomm optimization 
	 * implemented (see geninfo)  -- kas 
	 *	if (ISFTN(p->stype)) {
	 *	      printf("\",0x%x,0,%d,_.%s\n", N_FUN, bsize(p), p->sname);
	 *	} 
	 *	else { 
	 *	      int sz = tsize( ptype, p->dimoff, poffset ) / SZCHAR;
	 *	      old_pstab(pname, (stabLCSYM && (sz > 8 || ROdata) ) ? 
	 *					N_LCSYM : N_STSYM);
	 *	} 
	 *	
	 */

		/* stabLCSYM = 1 during nidcl so we can get stab type right */
		int sz = tsize( ptype, p->dimoff, poffset ) / SZCHAR;
		old_pstab(pname, (stabLCSYM && (sz > 8 || ROdata)) ? N_LCSYM:N_STSYM);
#else
		old_pstab(pname, N_STSYM);
#endif
		if (p->slevel > 1) {
			printf("0,%d,L%d\n", ptype, poffset);
		} 
		else {
			printf("0,%d,%s\n", ptype, exname(pname));
		}
		old_poffs(p);
		return;
	}
	case REGISTER:
		old_pstab(pname, N_RSYM);
		printf("0,%d,%d\n", ptype, poffset);
		old_poffs(p);
		return;

	case MOS:
	case MOU:
		old_pstab(pname, N_SSYM);
		printf("0,%d,%d\n", ptype, poffset/SZCHAR);
		old_poffs(p);
		return;

	case PARAM:
		/* parameter stab entries are processed in dclargs() */
		return;

	default:
#ifndef FLEXNAMES
		if (ddebug) printf("    No .stab for %.8s\n", pname);
#else
		if (ddebug) printf("    No .stab for %s\n", pname);
#endif

	}
}

private old_pstab(name, type)
char *name;
int type; 
{
	if (!gdebug) return;
	/* locctr(PROG);  /* .stabs must appear in .text for c2 */
#ifdef ASSTRINGS
	if ( name[0] == '\0')
	    printf("\t.stabn\t");
	else
#ifndef FLEXNAMES
		printf("\t.stabs\t\"%.8s\", ", name);
#else
	printf("\t.stabs\t\"%s\", ", name);
#endif
#else
	printf("    .stab   ");
	for(i=0; i<8; i++)
		if (c = name[i]) printf("'%c,", c);
		else printf("0,");
#endif
	printf("0%o,", type);
}

#ifdef STABDOT
private old_pstabdot(type, value)
int type;
int value;
{
	if ( ! gdebug) return;
	/* locctr(PROG);  /* .stabs must appear in .text for c2 */
	printf("\t.stabd\t");
	printf("0%o,0,0%o\n",type, value);
}
#endif

private old_poffs(p)
register struct symtab *p; 
{
	int s;
	if (!gdebug) return;
	if ((s = dimtab[p->sizoff]/SZCHAR) > 1) {
		old_pstab(p->sname, N_LENG);
		printf("1,0,%d\n", s);
	}
}

private old_psline() {
	static int lastlineno;
	register char *cp, *cq;
	register int i;

	if (!gdebug) return;

	cq = ititle;
	cp = ftitle;

	while ( *cq ) if ( *cp++ != *cq++ ) goto neq;
	if ( *cp == '\0' ) goto eq;

neq:    
	for (i=0; i<100; i++)
		ititle[i] = '\0';
	cp = ftitle;
	cq = ititle;
	while ( *cp )
	    *cq++ = *cp++;
	*cq = '\0';
	*--cq = '\0';
#ifndef FLEXNAMES
	for ( cp = ititle+1; *(cp-1); cp += 8 ) {
		old_pstab(cp, N_SOL);
		if (gdebug) printf("0,0,LL%d\n", labelno);
	}
#else
	old_pstab(ititle+1, N_SOL);
	if (gdebug) printf("0,0,LL%d\n", labelno);
#endif
	*cq = '"';
	printf("LL%d:\n", labelno++);

eq: 
	if (lineno == lastlineno) return;
	lastlineno = lineno;

	if (fdefflag) {
#ifdef STABDOT
		old_pstabdot(N_SLINE, lineno);
#else
		old_pstab(NULLNAME, N_SLINE);
		printf("0,%d,LL%d\n", lineno, labelno);
		printf("LL%d:\n", labelno++);
#endif
	}
}

private old_plcstab(level) {
	if (!gdebug) return;
#ifdef STABDOT
	old_pstabdot(N_LBRAC, level);
#else
	old_pstab(NULLNAME, N_LBRAC);
	printf("0,%d,LL%d\n", level, labelno);
	printf("LL%d:\n", labelno++);
#endif
}

private old_prcstab(level) {
	if (!gdebug) return;
#ifdef STABDOT
	pstabdot(N_RBRAC, level);
#else
	pstab(NULLNAME, N_RBRAC);
	printf("0,%d,LL%d\n", level, labelno);
	printf("LL%d:\n", labelno++);
#endif
}

private old_pfstab(sname)
char *sname; 
{
	if (!gdebug) return;
	pstab(sname, N_FUN);
#ifndef FLEXNAMES
	printf("0,%d,_%.7s\n", lineno, sname);
#else
	printf("0,%d,_.%s\n", lineno, sname);
#endif
}
