static char sccsid
[] = "@(#)lpass2.c 1.5 (Berkeley) %G%";
typedef struct sty STYPE
;
struct sty
{ ATYPE t
; STYPE
*next
; };
int tfree
; /* used to allocate types */
int ffree
; /* used to save filenames */
/* r is where all the input ends up */
int cfno
; /* current file number */
main( argc
, argv
) char *argv
[]; {
/* first argument is intermediate file */
/* second argument is - options */
for( ; argc
>2 && argv
[argc
-1][0] == '-' ; --argc
){
for( p
=argv
[argc
-1]; *p
; ++p
){
if( argc
< 2 || !freopen( argv
[1], "r", stdin
) ){
error( "cannot open intermediate file" );
mloop( LRV
|LUV
|LUE
|LUM
);
if( q
->decflag
) chkcompat(q
);
lread(m
){ /* read a line into r.l */
if( fread( (char *)&r
, sizeof(r
), 1, stdin
) <= 0 ) return(0);
if( n
>=NTY
) error( "more than %d args?", n
);
fread( (char *)atyp
, sizeof(ATYPE
), n
, stdin
);
if( ( r
.l
.decflag
& m
) ) return( 1 );
/* look up current file names */
/* first, strip backwards to the beginning or to the first / */
for( i
=0; i
<ffree
; ++i
){
if( !strncmp( s
, fnm
[i
], LFNM
) )
if( ffree
>= FSZ
) error( "more than %d files", FSZ
);
strncpy( fnm
[ffree
], s
, LFNM
);
fprintf( stderr
, "pass 2 error:(file %.*s) ", LFNM
, fnm
[cfno
] );
fprintf( stderr
, "pass 2 error:(file %s) ", fnm
[cfno
] );
h
= hashstr(r
.l
.name
, LCHNM
) % NSZ
;
for( p
=q
= &stab
[h
]; q
->decflag
; ){
if( !strncmp( r
.l
.name
, q
->name
, LCHNM
))
if( ((q
->decflag
|r
.l
.decflag
)&LST
)==0 || q
->fno
==cfno
)
if( ++q
>= &stab
[NSZ
] ) q
= stab
;
if( q
== p
) error( "too many names defined" );
strncpy( q
->name
, r
.l
.name
, LCHNM
);
error( "too many types needed" );
return( &tary
[tfree
++] );
/* are the types, etc. in r.l and q compatible */
if( q
->decflag
& (LDI
|LIB
|LUV
|LUE
|LST
) ){
if( r
.l
.decflag
& (LUV
|LIB
|LUE
) ){
if( q
->nargs
!= r
.l
.nargs
){
printf( "%.8s: variable # of args.", q
->name
);
printf( "%s: variable # of args.", q
->name
);
if( r
.l
.nargs
> q
->nargs
) r
.l
.nargs
= q
->nargs
;
if( !(q
->decflag
& (LDI
|LIB
|LST
) ) ) {
for( i
=0,qq
=q
->symty
.next
; i
<r
.l
.nargs
; ++i
,qq
=qq
->next
){
if( chktype( &qq
->t
, &atyp
[i
] ) ){
printf( "%.8s, arg. %d used inconsistently",
printf( "%s, arg. %d used inconsistently",
if( (q
->decflag
&(LDI
|LIB
|LUV
|LST
)) && r
.l
.decflag
==LUV
){
if( chktype( &r
.l
.type
, &q
->symty
.t
) ){
printf( "%.8s value used inconsistently", q
->name
);
printf( "%s value used inconsistently", q
->name
);
/* check for multiple declaration */
if( (q
->decflag
&(LDI
|LST
)) && (r
.l
.decflag
&(LDI
|LIB
|LST
)) ){
printf( "%.8s multiply declared", q
->name
);
printf( "%s multiply declared", q
->name
);
/* do a bit of checking of definitions and uses... */
if( (q
->decflag
& (LDI
|LIB
|LDX
|LDC
|LUM
|LST
)) && (r
.l
.decflag
& (LDX
|LDC
|LUM
)) && q
->symty
.t
.aty
!= r
.l
.type
.aty
){
printf( "%.8s value declared inconsistently", q
->name
);
printf( "%s value declared inconsistently", q
->name
);
/* better not call functions which are declared to be structure or union returning */
if( (q
->decflag
& (LDI
|LIB
|LDX
|LDC
|LST
)) && (r
.l
.decflag
& LUE
) && q
->symty
.t
.aty
!= r
.l
.type
.aty
){
/* only matters if the function returns union or structure */
if( ISFTN(ty
) && ((ty
= DECREF(ty
))==STRTY
|| ty
==UNIONTY
) ){
printf( "%.8s function value type must be declared before use", q
->name
);
printf( "%s function value type must be declared before use", q
->name
);
if( pflag
&& q
->decflag
==LDX
&& r
.l
.decflag
== LUM
&& !ISFTN(q
->symty
.t
.aty
) ){
/* make the external declaration go away */
/* in effect, it was used without being defined */
/* print out file comparison */
printf( " %.*s(%d) :: %.*s(%d)\n",
LFNM
, fnm
[q
->fno
], q
->fline
,
LFNM
, fnm
[cfno
], r
.l
.fline
);
printf( " %s(%d) :: %s(%d)\n",
/* messages for defintion/use */
"%.8s used( %.*s(%d) ), but not defined\n",
"%.8s defined( %.*s(%d) ), but never used\n",
"%.8s declared( %.*s(%d) ), but never used or defined\n"
"%s used( %s(%d) ), but not defined\n",
"%s defined( %s(%d) ), but never used\n",
"%s declared( %s(%d) ), but never used or defined\n"
if( !(uses
&USED
) && q
->decflag
!= LIB
) {
if( strncmp(q
->name
,"main",7) )
if (strcmp(q
->name
, "main"))
if( !ISFTN(q
->symty
.t
.aty
) ){
nu
= nd
= 0; /* don't complain about uses on libraries */
/* 01/04/80 */ case LUV
| LUE
:
if( uflag
&& ( nu
|| nd
) )
printf( mess
[nu
][nd
], q
->name
, LFNM
, fnm
[q
->fno
], q
->fline
);
printf( mess
[nu
][nd
], q
->name
, fnm
[q
->fno
], q
->fline
);
if( (uses
&(RVAL
+EUSED
)) == (RVAL
+EUSED
) ){
/* if functions is static, then print the file name too */
printf( "%.*s(%d):", LFNM
, fnm
[q
->fno
], q
->fline
);
printf( "%s(%d):", fnm
[q
->fno
], q
->fline
);
printf( "%.*s returns value which is %s ignored\n",
LCHNM
, q
->name
, uses
&VUSED
? "sometimes" : "always" );
printf( "%s returns value which is %s ignored\n",
q
->name
, uses
&VUSED
? "sometimes" : "always" );
if( (uses
&(RVAL
+VUSED
)) == (VUSED
) && (q
->decflag
&(LDI
|LIB
|LST
)) ){
printf( "%.*s(%d):", LFNM
, fnm
[q
->fno
], q
->fline
);
printf( "%s(%d):", fnm
[q
->fno
], q
->fline
);
printf( "%.*s value is used, but none returned\n",
printf( "%s value is used, but none returned\n", q
->name
);
cleanup(){ /* call lastone and die gracefully */
for( q
=stab
; q
< &stab
[NSZ
]; ++q
){
if( q
->decflag
) lastone(q
);
setuse(q
) STAB
*q
; { /* check new type to ensure that it is used */
if( !q
->decflag
){ /* new one */
q
->decflag
= r
.l
.decflag
;
for( i
=0,qq
= &q
->symty
; i
<q
->nargs
; ++i
,qq
=qq
->next
){
/* 01/04/80 */ case LUV
| LUE
:
chktype( pt1
, pt2
) register ATYPE
*pt1
, *pt2
; {
/* check the two type words to see if they are compatible */
/* for the moment, enums are turned into ints, and should be checked as such */
if( pt1
->aty
== ENUMTY
) pt1
->aty
= INT
;
if( pt2
->aty
== ENUMTY
) pt2
->aty
= INT
;
if( (t
=BTYPE(pt1
->aty
)==STRTY
) || t
==UNIONTY
){
if( pt1
->aty
!= pt2
->aty
|| pt1
->extra1
!= pt2
->extra1
)
/* if -z then don't worry about undefined structures,
as long as the names match */
if( zflag
&& (pt1
->extra
== 0 || pt2
->extra
== 0) ) return 0;
return pt1
->extra
!= pt2
->extra
;
if( pt2
->extra
){ /* constant passed in */
if( pt1
->aty
== UNSIGNED
&& pt2
->aty
== INT
) return( 0 );
else if( pt1
->aty
== ULONG
&& pt2
->aty
== LONG
) return( 0 );
else if( pt1
->extra
){ /* for symmetry */
if( pt2
->aty
== UNSIGNED
&& pt1
->aty
== INT
) return( 0 );
else if( pt2
->aty
== ULONG
&& pt1
->aty
== LONG
) return( 0 );
return( pt1
->aty
!= pt2
->aty
);
struct tb
{ int m
; char * nm
};
ptb( v
, tp
) struct tb
*tp
; {
/* print a value from the table */
if( flag
++ ) putchar( '|' );
/* give a debugging output for q */
printf( "%.8s (", q
->name
);
printf( "%s (", q
->name
);
printf( ", line %d, nargs=%d\n", q
->fline
, q
->nargs
);
/* print the input file in readable form */
while( lread( LDI
|LIB
|LDC
|LDX
|LRV
|LUV
|LUE
|LUM
|LST
|LFN
) )
/* print out 'r' for debugging */
printf( "fn\t\t%s\n", r
.f
.fn
);
printf( "fn\t%\t.*s\n", LFNM
, r
.f
.fn
);
printf( "name\t%s\n", r
.l
.name
);
printf( "name\t%.*s\n", LCHNM
, r
.l
.name
);
printf( "nargs\t%d\n", r
.l
.nargs
);
printf( "fline\t%d\n", r
.l
.fline
);
printf( "type.aty\t0%o (", r
.l
.type
.aty
);
pty( r
.l
.type
.aty
, r
.l
.name
);
printf( ")\ntype.extra\t%d\n", r
.l
.type
.extra
);
printf( "type.extra1\t0x%x (%d,%d)\n",
j
, j
& X_NONAME
? 1 : 0, j
& ~X_NONAME
);
for( i
= 0; i
< k
; i
++ ){
printf( "atyp[%d].aty\t0%o (", i
, atyp
[i
].aty
);
printf( ")\natyp[%d].extra\t%d\n", i
, atyp
[i
].extra
);
printf( "atyp[%d].extra1\t0x%x (%d,%d)\n",
i
, j
, j
& X_NONAME
? 1 : 0, j
& ~X_NONAME
);
pty( t
, name
) TWORD t
; {
static char * tnames
[] = {
"void", "farg", "char", "short",
"int", "long", "float", "double",
"struct xxx", "union %s", "enum", "moety",
"unsigned char", "unsigned short", "unsigned", "unsigned long",
printf( "%s ", tnames
[BTYPE(t
)] );
pty1( t
, name
, (8 * sizeof (int) - BTSHIFT
) / TSHIFT
);
pty1( t
, name
, level
) TWORD t
; {
pty1( t
, name
, level
-1 );
if( level
> 0 && ISPTR(u
<< TSHIFT
) ){
pty1( t
, name
, level
-1 );
pty1( t
, name
, level
-1 );
if( level
> 0 && ISPTR(u
<< TSHIFT
) ){
pty1( t
, name
, level
-1 );
pty1( t
, name
, level
-1 );
pty1( t
, name
, level
-1 );
if (feof(stdin
) || ferror(stdin
))
while ((c
= getchar()) > 0)
error("intermediate file format error (getstr)");
savetab
= (char *)malloc(saveleft
);
error("ran out of memory (savestr)");
strncpy(savetab
, cp
, len
);
* The definition for the segmented hash tables.
sh
= hashstr(s
) % HASHINC
;
* There are as many as MAXHASH active
* hash tables at any given point in time.
* The search starts with the first table
* and continues through the active tables
for (htp
= htab
; htp
< &htab
[MAXHASH
]; htp
++) {
(char **) calloc(sizeof (char **), HASHINC
);
error("ran out of memory (hash)");
htp
->ht_high
= htp
->ht_low
+ HASHINC
;
* quadratic rehash increment
* starts at 1 and incremented
if (htp
->ht_used
> (HASHINC
* 3)/4)
if (**h
== *cp
&& strcmp(*h
, cp
) == 0)
error("ran out of hash tables");