xref: /csrg-svn/old/pcc/lint/lpass2/lpass2.c (revision 30938)
1 #ifndef lint
2 static char sccsid[] = "@(#)lpass2.c	1.7	(Berkeley)	04/22/87";
3 #endif lint
4 
5 # include "macdefs.h"
6 # include "manifest.h"
7 # include "lmanifest.h"
8 
9 # define USED 01
10 # define VUSED 02
11 # define EUSED 04
12 # define RVAL 010
13 # define VARARGS 0100
14 
15 # define NSZ 4096
16 # define TYSZ 3500
17 # define FSZ 500
18 # define NTY 50
19 
20 typedef struct sty STYPE;
21 struct sty { ATYPE t; STYPE *next; };
22 
23 typedef struct sym {
24 #ifndef FLEXNAMES
25 	char name[LCHNM];
26 #else
27 	char *name;
28 #endif
29 	short nargs;
30 	int decflag;
31 	int fline;
32 	STYPE symty;
33 	int fno;
34 	int use;
35 	} STAB;
36 
37 STAB stab[NSZ];
38 STAB *find();
39 
40 STYPE tary[TYSZ];
41 STYPE *tget();
42 
43 #ifndef FLEXNAMES
44 char fnm[FSZ][LFNM];
45 #else
46 char *fnm[FSZ];
47 #endif
48 
49 #ifdef FLEXNAMES
50 char *getstr();
51 #endif
52 
53 int tfree;  /* used to allocate types */
54 int ffree;  /* used to save filenames */
55 
56 struct ty atyp[NTY];
57 	/* r is where all the input ends up */
58 union rec r;
59 
60 int hflag = 0;
61 int pflag = 0;
62 int xflag = 0;
63 int uflag = 1;
64 int ddddd = 0;
65 int zflag = 0;
66 int Pflag = 0;
67 
68 int cfno;  /* current file number */
69 
70 main( argc, argv ) char *argv[]; {
71 	register char *p;
72 
73 	/* first argument is intermediate file */
74 	/* second argument is - options */
75 
76 	for( ; argc>2 && argv[argc-1][0] == '-' ; --argc ){
77 		for( p=argv[argc-1]; *p; ++p ){
78 			switch( *p ){
79 
80 			case 'h':
81 				hflag = 1;
82 				break;
83 
84 			case 'p':
85 				pflag = 1;
86 				break;
87 
88 			case 'x':
89 				xflag = 1;
90 				break;
91 
92 			case 'X':
93 				ddddd = 1;
94 				break;
95 
96 			case 'u':
97 				uflag = 0;
98 				break;
99 
100 			case 'z':
101 				zflag = 1;
102 				break;
103 
104 			case 'P':
105 				Pflag = 1;
106 				break;
107 
108 				}
109 			}
110 		}
111 
112 	if( argc < 2 || !freopen( argv[1], "r", stdin ) ){
113 		error( "cannot open intermediate file" );
114 		exit( 1 );
115 		}
116 	if( Pflag ){
117 		pfile();
118 		return( 0 );
119 		}
120 	mloop( LDI|LIB|LST );
121 	rewind( stdin );
122 	mloop( LDC|LDX );
123 	rewind( stdin );
124 	mloop( LRV|LUV|LUE|LUM );
125 	cleanup();
126 	return(0);
127 	}
128 
129 mloop( m ){
130 	/* do the main loop */
131 	register STAB *q;
132 
133 	while( lread(m) ){
134 		q = find();
135 		if( q->decflag ) chkcompat(q);
136 		else setuse(q);
137 		}
138 	}
139 
140 lread(m){ /* read a line into r.l */
141 
142 	register n;
143 
144 	for(;;) {
145 		if( fread( (char *)&r, sizeof(r), 1, stdin ) <= 0 ) return(0);
146 		if( r.l.decflag & LFN ){
147 			/* new filename */
148 #ifdef FLEXNAMES
149 			r.f.fn = getstr(0);
150 #endif
151 			if( Pflag ) return( 1 );
152 			setfno( r.f.fn );
153 			continue;
154 			}
155 #ifdef FLEXNAMES
156 		r.l.name = getstr(1);
157 #else /* !FLEXNAMES */
158 		portify(r.l.name);
159 #endif /* !FLEXNAMES */
160 		n = r.l.nargs;
161 		if( n<0 ) n = -n;
162 		if( n>=NTY ) error( "more than %d args?", n );
163 		fread( (char *)atyp, sizeof(ATYPE), n, stdin );
164 		if( ( r.l.decflag & m ) ) return( 1 );
165 		}
166 	}
167 
168 setfno( s ) char *s; {
169 	/* look up current file names */
170 	/* first, strip backwards to the beginning or to the first / */
171 	int i;
172 
173 	/* now look up s */
174 	for( i=0; i<ffree; ++i ){
175 #ifndef FLEXNAMES
176 		if( !strncmp( s, fnm[i], LFNM ) )
177 #else
178 		if (fnm[i] == s)
179 #endif
180 			{
181 			cfno = i;
182 			return;
183 			}
184 		}
185 	/* make a new entry */
186 	if( ffree >= FSZ ) error( "more than %d files", FSZ );
187 #ifndef FLEXNAMES
188 	strncpy( fnm[ffree], s, LFNM );
189 #else
190 	fnm[ffree] = s;
191 #endif
192 	cfno = ffree++;
193 	}
194 
195 /* VARARGS */
196 error( s, a ) char *s; {
197 
198 #ifndef FLEXNAMES
199 	fprintf( stderr, "pass 2 error:(file %.*s) ", LFNM, fnm[cfno] );
200 #else
201 	fprintf( stderr, "pass 2 error:(file %s) ", fnm[cfno] );
202 #endif
203 	fprintf( stderr, s, a );
204 	fprintf( stderr, "\n" );
205 	exit(1);
206 	}
207 
208 STAB *
209 find(){
210 	register h=0;
211 #ifndef FLEXNAMES
212 	h = hashstr(r.l.name, LCHNM) % NSZ;
213 #else
214 	h = (int)r.l.name % NSZ;
215 #endif
216 	{	register STAB *p, *q;
217 		for( p=q= &stab[h]; q->decflag; ){
218 #ifndef FLEXNAMES
219 			if( !strncmp( r.l.name, q->name, LCHNM))
220 #else
221 			if (r.l.name == q->name)
222 #endif
223 				if( ((q->decflag|r.l.decflag)&LST)==0 || q->fno==cfno )
224 					return(q);
225 			if( ++q >= &stab[NSZ] ) q = stab;
226 			if( q == p ) error( "too many names defined" );
227 			}
228 #ifndef FLEXNAMES
229 		strncpy( q->name, r.l.name, LCHNM );
230 #else
231 		q->name = r.l.name;
232 #endif
233 		return( q );
234 		}
235 	}
236 
237 STYPE *
238 tget(){
239 	if( tfree >= TYSZ ){
240 		error( "too many types needed" );
241 		}
242 	return( &tary[tfree++] );
243 	}
244 
245 chkcompat(q) STAB *q; {
246 	/* are the types, etc. in r.l and q compatible */
247 	register int i;
248 	STYPE *qq;
249 
250 	setuse(q);
251 
252 	/* argument check */
253 
254 	if( q->decflag & (LDI|LIB|LUV|LUE|LST) ){
255 		if( r.l.decflag & (LUV|LIB|LUE) ){
256 			if( q->nargs != r.l.nargs ){
257 				if( !(q->use&VARARGS) ){
258 #ifndef FLEXNAMES
259 					printf( "%.8s: variable # of args.", q->name );
260 #else
261 					printf( "%s: variable # of args.", q->name );
262 #endif
263 					viceversa(q);
264 					}
265 				if( r.l.nargs > q->nargs ) r.l.nargs = q->nargs;
266 				if( !(q->decflag & (LDI|LIB|LST) ) ) {
267 					q->nargs = r.l.nargs;
268 					q->use |= VARARGS;
269 					}
270 				}
271 			for( i=0,qq=q->symty.next; i<r.l.nargs; ++i,qq=qq->next){
272 				if( chktype( &qq->t, &atyp[i] ) ){
273 #ifndef FLEXNAMES
274 					printf( "%.8s, arg. %d used inconsistently",
275 #else
276 					printf( "%s, arg. %d used inconsistently",
277 #endif
278 						q->name, i+1 );
279 					viceversa(q);
280 					}
281 				}
282 			}
283 		}
284 
285 	if( (q->decflag&(LDI|LIB|LUV|LST)) && r.l.decflag==LUV ){
286 		if( chktype( &r.l.type, &q->symty.t ) ){
287 #ifndef FLEXNAMES
288 			printf( "%.8s value used inconsistently", q->name );
289 #else
290 			printf( "%s value used inconsistently", q->name );
291 #endif
292 			viceversa(q);
293 			}
294 		}
295 
296 	/* check for multiple declaration */
297 
298 	if( (q->decflag&(LDI|LST)) && (r.l.decflag&(LDI|LIB|LST)) ){
299 #ifndef FLEXNAMES
300 		printf( "%.8s multiply declared", q->name );
301 #else
302 		printf( "%s multiply declared", q->name );
303 #endif
304 		viceversa(q);
305 		}
306 
307 	/* do a bit of checking of definitions and uses... */
308 
309 	if( (q->decflag & (LDI|LIB|LDX|LDC|LUM|LST)) && (r.l.decflag & (LDX|LDC|LUM)) && q->symty.t.aty != r.l.type.aty ){
310 #ifndef FLEXNAMES
311 		printf( "%.8s value declared inconsistently", q->name );
312 #else
313 		printf( "%s value declared inconsistently", q->name );
314 #endif
315 		viceversa(q);
316 		}
317 
318 	/* better not call functions which are declared to be structure or union returning */
319 
320 	if( (q->decflag & (LDI|LIB|LDX|LDC|LST)) && (r.l.decflag & LUE) && q->symty.t.aty != r.l.type.aty ){
321 		/* only matters if the function returns union or structure */
322 		TWORD ty;
323 		ty = q->symty.t.aty;
324 		if( ISFTN(ty) && ((ty = DECREF(ty))==STRTY || ty==UNIONTY ) ){
325 #ifndef FLEXNAMES
326 			printf( "%.8s function value type must be declared before use", q->name );
327 #else
328 			printf( "%s function value type must be declared before use", q->name );
329 #endif
330 			viceversa(q);
331 			}
332 		}
333 
334 	if( pflag && q->decflag==LDX && r.l.decflag == LUM && !ISFTN(q->symty.t.aty) ){
335 		/* make the external declaration go away */
336 		/* in effect, it was used without being defined */
337 		}
338 	}
339 
340 viceversa(q) STAB *q; {
341 	/* print out file comparison */
342 #ifndef FLEXNAMES
343 	printf( "	%.*s(%d)  ::  %.*s(%d)\n",
344 		LFNM, fnm[q->fno], q->fline,
345 		LFNM, fnm[cfno], r.l.fline );
346 #else
347 	printf( "	%s(%d)  ::  %s(%d)\n",
348 		fnm[q->fno], q->fline,
349 		fnm[cfno], r.l.fline );
350 #endif
351 	}
352 
353 	/* messages for defintion/use */
354 char *
355 mess[2][2] ={
356 	"",
357 #ifndef FLEXNAMES
358 	"%.8s used( %.*s(%d) ), but not defined\n",
359 	"%.8s defined( %.*s(%d) ), but never used\n",
360 	"%.8s declared( %.*s(%d) ), but never used or defined\n"
361 #else
362 	"%s used( %s(%d) ), but not defined\n",
363 	"%s defined( %s(%d) ), but never used\n",
364 	"%s declared( %s(%d) ), but never used or defined\n"
365 #endif
366 	};
367 
368 lastone(q) STAB *q; {
369 
370 	register nu, nd, uses;
371 
372 	if( ddddd ) pst(q);
373 
374 	nu = nd = 0;
375 	uses = q->use;
376 
377 	if( !(uses&USED) && q->decflag != LIB ) {
378 #ifndef FLEXNAMES
379 		if( strncmp(q->name,"main",7) )
380 #else
381 		if (strcmp(q->name, "main"))
382 #endif
383 			nu = 1;
384 		}
385 
386 	if( !ISFTN(q->symty.t.aty) ){
387 		switch( q->decflag ){
388 
389 		case LIB:
390 			nu = nd = 0;  /* don't complain about uses on libraries */
391 			break;
392 		case LDX:
393 			if( !xflag ) break;
394 		case LUV:
395 		case LUE:
396 /* 01/04/80 */	case LUV | LUE:
397 		case LUM:
398 			nd = 1;
399 			}
400 		}
401 	if( uflag && ( nu || nd ) )
402 #ifndef FLEXNAMES
403 		printf( mess[nu][nd], q->name, LFNM, fnm[q->fno], q->fline );
404 #else
405 		printf( mess[nu][nd], q->name, fnm[q->fno], q->fline );
406 #endif
407 
408 	if( (uses&(RVAL+EUSED)) == (RVAL+EUSED) ){
409 		/* if functions is static, then print the file name too */
410 		if( q->decflag & LST )
411 #ifndef FLEXNAMES
412 			printf( "%.*s(%d):", LFNM, fnm[q->fno], q->fline );
413 #else
414 			printf( "%s(%d):", fnm[q->fno], q->fline );
415 #endif
416 #ifndef FLEXNAMES
417 		printf( "%.*s returns value which is %s ignored\n",
418 			LCHNM, q->name, uses&VUSED ? "sometimes" : "always" );
419 #else
420 		printf( "%s returns value which is %s ignored\n",
421 			q->name, uses&VUSED ? "sometimes" : "always" );
422 #endif
423 		}
424 
425 	if( (uses&(RVAL+VUSED)) == (VUSED) && (q->decflag&(LDI|LIB|LST)) ){
426 		if( q->decflag & LST )
427 #ifndef FLEXNAMES
428 			printf( "%.*s(%d):", LFNM, fnm[q->fno], q->fline );
429 #else
430 			printf( "%s(%d):", fnm[q->fno], q->fline );
431 #endif
432 #ifndef FLEXNAMES
433 		printf( "%.*s value is used, but none returned\n",
434 			LCHNM, q->name);
435 #else
436 		printf( "%s value is used, but none returned\n", q->name);
437 #endif
438 		}
439 	}
440 
441 cleanup(){ /* call lastone and die gracefully */
442 	STAB *q;
443 	for( q=stab; q< &stab[NSZ]; ++q ){
444 		if( q->decflag ) lastone(q);
445 		}
446 	exit(0);
447 	}
448 
449 setuse(q) STAB *q; { /* check new type to ensure that it is used */
450 
451 	if( !q->decflag ){ /* new one */
452 		q->decflag = r.l.decflag;
453 		q->symty.t = r.l.type;
454 		if( r.l.nargs < 0 ){
455 			q->nargs = -r.l.nargs;
456 			q->use = VARARGS;
457 			}
458 		else {
459 			q->nargs = r.l.nargs;
460 			q->use = 0;
461 			}
462 		q->fline = r.l.fline;
463 		q->fno = cfno;
464 		if( q->nargs ){
465 			int i;
466 			STYPE *qq;
467 			for( i=0,qq= &q->symty; i<q->nargs; ++i,qq=qq->next ){
468 				qq->next = tget();
469 				qq->next->t = atyp[i];
470 				}
471 			}
472 		}
473 
474 	switch( r.l.decflag ){
475 
476 	case LRV:
477 		q->use |= RVAL;
478 		return;
479 	case LUV:
480 		q->use |= VUSED+USED;
481 		return;
482 	case LUE:
483 		q->use |= EUSED+USED;
484 		return;
485 /* 01/04/80 */	case LUV | LUE:
486 	case LUM:
487 		q->use |= USED;
488 		return;
489 
490 		}
491 	}
492 
493 chktype( pt1, pt2 ) register ATYPE *pt1, *pt2; {
494 	TWORD t;
495 
496 	/* check the two type words to see if they are compatible */
497 	/* for the moment, enums are turned into ints, and should be checked as such */
498 	if( pt1->aty == ENUMTY ) pt1->aty =  INT;
499 	if( pt2->aty == ENUMTY ) pt2->aty = INT;
500 
501 	if( (t=BTYPE(pt1->aty)==STRTY) || t==UNIONTY ){
502 		if( pt1->aty != pt2->aty || pt1->extra1 != pt2->extra1 )
503 			return 1;
504 		/* if -z then don't worry about undefined structures,
505 		   as long as the names match */
506 		if( zflag && (pt1->extra == 0 || pt2->extra == 0) ) return 0;
507 		return pt1->extra != pt2->extra;
508 		}
509 
510 	if( pt2->extra ){ /* constant passed in */
511 		if( pt1->aty == UNSIGNED && pt2->aty == INT ) return( 0 );
512 		else if( pt1->aty == ULONG && pt2->aty == LONG ) return( 0 );
513 		}
514 	else if( pt1->extra ){ /* for symmetry */
515 		if( pt2->aty == UNSIGNED && pt1->aty == INT ) return( 0 );
516 		else if( pt2->aty == ULONG && pt1->aty == LONG ) return( 0 );
517 		}
518 
519 	return( pt1->aty != pt2->aty );
520 	}
521 
522 struct tb { int m; char * nm };
523 
524 struct tb dfs[] = {
525 	LDI, "LDI",
526 	LIB, "LIB",
527 	LDC, "LDC",
528 	LDX, "LDX",
529 	LRV, "LRV",
530 	LUV, "LUV",
531 	LUE, "LUE",
532 	LUM, "LUM",
533 	LST, "LST",
534 	LFN, "LFN",
535 	0, "" };
536 
537 struct tb us[] = {
538 	USED, "USED",
539 	VUSED, "VUSED",
540 	EUSED, "EUSED",
541 	RVAL, "RVAL",
542 	VARARGS, "VARARGS",
543 	0, "" };
544 
545 ptb( v, tp ) struct tb *tp; {
546 	/* print a value from the table */
547 	int flag;
548 	flag = 0;
549 	for( ; tp->m; ++tp ){
550 		if( v&tp->m ){
551 			if( flag++ ) putchar( '|' );
552 			printf( "%s", tp->nm );
553 			}
554 		}
555 	}
556 
557 pst( q ) STAB *q; {
558 	/* give a debugging output for q */
559 
560 #ifndef FLEXNAMES
561 	printf( "%.8s (", q->name );
562 #else
563 	printf( "%s (", q->name );
564 #endif
565 	ptb( q->decflag, dfs );
566 	printf( "), use= " );
567 	ptb( q->use, us );
568 	printf( ", line %d, nargs=%d\n", q->fline, q->nargs );
569 	}
570 
571 pfile() {
572 	/* print the input file in readable form */
573 	while( lread( LDI|LIB|LDC|LDX|LRV|LUV|LUE|LUM|LST|LFN ) )
574 		prc();
575 	}
576 
577 prc() {
578 	/* print out 'r' for debugging */
579 	register i, j, k;
580 
581 	printf( "decflag\t" );
582 	ptb( r.l.decflag, dfs );
583 	putchar( '\n' );
584 	if( r.l.decflag & LFN ){
585 #ifdef FLEXNAMES
586 		printf( "fn\t\t%s\n", r.f.fn );
587 #else
588 		printf( "fn\t%\t.*s\n", LFNM, r.f.fn );
589 #endif
590 		}
591 	else {
592 #ifdef FLEXNAMES
593 		printf( "name\t%s\n", r.l.name );
594 #else
595 		printf( "name\t%.*s\n", LCHNM, r.l.name );
596 #endif
597 		printf( "nargs\t%d\n", r.l.nargs );
598 		printf( "fline\t%d\n", r.l.fline );
599 		printf( "type.aty\t0%o (", r.l.type.aty );
600 		pty( r.l.type.aty, r.l.name );
601 		printf( ")\ntype.extra\t%d\n", r.l.type.extra );
602 		j = r.l.type.extra1;
603 		printf( "type.extra1\t0x%x (%d,%d)\n",
604 			j, j & X_NONAME ? 1 : 0, j & ~X_NONAME );
605 		k = r.l.nargs;
606 		if( k < 0 ) k = -k;
607 		for( i = 0; i < k; i++ ){
608 			printf( "atyp[%d].aty\t0%o (", i, atyp[i].aty );
609 			pty( atyp[i].aty, "" );
610 			printf( ")\natyp[%d].extra\t%d\n", i, atyp[i].extra);
611 			j = atyp[i].extra1;
612 			printf( "atyp[%d].extra1\t0x%x (%d,%d)\n",
613 				i, j, j & X_NONAME ? 1 : 0, j & ~X_NONAME );
614 			}
615 		}
616 		putchar( '\n' );
617 	}
618 
619 pty( t, name )  TWORD t; {
620 	static char * tnames[] = {
621 		"void", "farg", "char", "short",
622 		"int", "long", "float", "double",
623 		"struct xxx", "union %s", "enum", "moety",
624 		"unsigned char", "unsigned short", "unsigned", "unsigned long",
625 		"?", "?"
626 		};
627 
628 	printf( "%s ", tnames[BTYPE(t)] );
629 	pty1( t, name, (8 * sizeof (int) - BTSHIFT) / TSHIFT );
630 	}
631 
632 pty1( t, name, level ) TWORD t; {
633 	register TWORD u;
634 
635 	if( level < 0 ){
636 		printf( "%s", name );
637 		return;
638 		}
639 	u = t >> level * TSHIFT;
640 	if( ISPTR(u) ){
641 		printf( "*" );
642 		pty1( t, name, level-1 );
643 		}
644 	else if( ISFTN(u) ){
645 		if( level > 0 && ISPTR(u << TSHIFT) ){
646 			printf( "(" );
647 			pty1( t, name, level-1 );
648 			printf( ")()" );
649 			}
650 		else {
651 			pty1( t, name, level-1 );
652 			printf( "()" );
653 			}
654 		}
655 	else if( ISARY(u) ){
656 		if( level > 0 && ISPTR(u << TSHIFT) ){
657 			printf( "(" );
658 			pty1( t, name, level-1 );
659 			printf( ")[]" );
660 			}
661 		else {
662 			pty1( t, name, level-1 );
663 			printf( "[]" );
664 			}
665 		}
666 	else {
667 		pty1( t, name, level-1 );
668 		}
669 	}
670 
671 #ifdef FLEXNAMES
672 char *
673 getstr(doport)
674 {
675 	char buf[BUFSIZ];
676 	register char *cp = buf;
677 	register int c;
678 
679 	if (feof(stdin) || ferror(stdin))
680 		return("");
681 	while ((c = getchar()) > 0)
682 		*cp++ = c;
683 	if (c < 0) {
684 		error("intermediate file format error (getstr)");
685 		exit(1);
686 	}
687 	*cp++ = 0;
688 	if (doport)
689 		portify(buf);
690 	return (hash(buf));
691 }
692 
693 #define	NSAVETAB	4096
694 char	*savetab;
695 int	saveleft;
696 
697 char *
698 savestr(cp)
699 	register char *cp;
700 {
701 	register int len;
702 
703 	len = strlen(cp) + 1;
704 	if (len > saveleft) {
705 		saveleft = NSAVETAB;
706 		if (len > saveleft)
707 			saveleft = len;
708 		savetab = (char *)malloc(saveleft);
709 		if (savetab == 0) {
710 			error("ran out of memory (savestr)");
711 			exit(1);
712 		}
713 	}
714 	strncpy(savetab, cp, len);
715 	cp = savetab;
716 	savetab += len;
717 	saveleft -= len;
718 	return (cp);
719 }
720 
721 /*
722  * The definition for the segmented hash tables.
723  */
724 #define	MAXHASH	20
725 #define	HASHINC	1013
726 struct ht {
727 	char	**ht_low;
728 	char	**ht_high;
729 	int	ht_used;
730 } htab[MAXHASH];
731 
732 char *
733 hash(s)
734 	char *s;
735 {
736 	register char **h;
737 	register i;
738 	register char *cp;
739 	struct ht *htp;
740 	int sh;
741 
742 	sh = hashstr(s) % HASHINC;
743 	cp = s;
744 	/*
745 	 * There are as many as MAXHASH active
746 	 * hash tables at any given point in time.
747 	 * The search starts with the first table
748 	 * and continues through the active tables
749 	 * as necessary.
750 	 */
751 	for (htp = htab; htp < &htab[MAXHASH]; htp++) {
752 		if (htp->ht_low == 0) {
753 			register char **hp =
754 			    (char **) calloc(sizeof (char **), HASHINC);
755 			if (hp == 0) {
756 				error("ran out of memory (hash)");
757 				exit(1);
758 			}
759 			htp->ht_low = hp;
760 			htp->ht_high = htp->ht_low + HASHINC;
761 		}
762 		h = htp->ht_low + sh;
763 		/*
764 		 * quadratic rehash increment
765 		 * starts at 1 and incremented
766 		 * by two each rehash.
767 		 */
768 		i = 1;
769 		do {
770 			if (*h == 0) {
771 				if (htp->ht_used > (HASHINC * 3)/4)
772 					break;
773 				htp->ht_used++;
774 				*h = savestr(cp);
775 				return (*h);
776 			}
777 			if (**h == *cp && strcmp(*h, cp) == 0)
778 				return (*h);
779 			h += i;
780 			i += 2;
781 			if (h >= htp->ht_high)
782 				h -= HASHINC;
783 		} while (i < HASHINC);
784 	}
785 	error("ran out of hash tables");
786 	exit(1);
787 }
788 char	*tstrbuf[1];
789 #endif
790 
791 #include "ctype.h"
792 
793 portify(cp)
794 register char *	cp;
795 {
796 	register int	i;
797 
798 	if (!pflag)
799 		return;
800 	for (i = 0; i < 6; ++i)
801 		if (cp[i] == '\0')
802 			return;
803 		else if (isascii(cp[i]) && isupper(cp[i]))
804 			cp[i] = tolower(cp[i]);
805 	cp[i] = '\0';
806 }
807