881 lines
		
	
	
	
		
			16 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			881 lines
		
	
	
	
		
			16 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/****************************************************************
 | 
						|
Copyright 1990 by AT&T Bell Laboratories and Bellcore.
 | 
						|
 | 
						|
Permission to use, copy, modify, and distribute this software
 | 
						|
and its documentation for any purpose and without fee is hereby
 | 
						|
granted, provided that the above copyright notice appear in all
 | 
						|
copies and that both that the copyright notice and this
 | 
						|
permission notice and warranty disclaimer appear in supporting
 | 
						|
documentation, and that the names of AT&T Bell Laboratories or
 | 
						|
Bellcore or any of their entities not be used in advertising or
 | 
						|
publicity pertaining to distribution of the software without
 | 
						|
specific, written prior permission.
 | 
						|
 | 
						|
AT&T and Bellcore disclaim all warranties with regard to this
 | 
						|
software, including all implied warranties of merchantability
 | 
						|
and fitness.  In no event shall AT&T or Bellcore be liable for
 | 
						|
any special, indirect or consequential damages or any damages
 | 
						|
whatsoever resulting from loss of use, data or profits, whether
 | 
						|
in an action of contract, negligence or other tortious action,
 | 
						|
arising out of or in connection with the use or performance of
 | 
						|
this software.
 | 
						|
****************************************************************/
 | 
						|
 | 
						|
#include "defs.h"
 | 
						|
 | 
						|
 static char Ptok[128], Pct[Table_size];
 | 
						|
 static char *Pfname;
 | 
						|
 static long Plineno;
 | 
						|
 static int Pbad;
 | 
						|
 static int *tfirst, *tlast, *tnext, tmax;
 | 
						|
 | 
						|
#define P_space	1
 | 
						|
#define P_anum	2
 | 
						|
#define P_delim	3
 | 
						|
#define P_slash	4
 | 
						|
 | 
						|
#define TGULP	100
 | 
						|
 | 
						|
 static void
 | 
						|
trealloc()
 | 
						|
{
 | 
						|
	int k = tmax;
 | 
						|
	tfirst = (int *)realloc((char *)tfirst,
 | 
						|
		(tmax += TGULP)*sizeof(int));
 | 
						|
	if (!tfirst) {
 | 
						|
		fprintf(stderr,
 | 
						|
		"Pfile: realloc failure!\n");
 | 
						|
		exit(2);
 | 
						|
		}
 | 
						|
	tlast = tfirst + tmax;
 | 
						|
	tnext = tfirst + k;
 | 
						|
	}
 | 
						|
 | 
						|
 static void
 | 
						|
badchar(c)
 | 
						|
 int c;
 | 
						|
{
 | 
						|
	fprintf(stderr,
 | 
						|
		"unexpected character 0x%.2x = '%c' on line %ld of %s\n",
 | 
						|
		c, c, Plineno, Pfname);
 | 
						|
	exit(2);
 | 
						|
	}
 | 
						|
 | 
						|
 static void
 | 
						|
bad_type()
 | 
						|
{
 | 
						|
	fprintf(stderr,
 | 
						|
		"unexpected type \"%s\" on line %ld of %s\n",
 | 
						|
		Ptok, Plineno, Pfname);
 | 
						|
	exit(2);
 | 
						|
	}
 | 
						|
 | 
						|
 static void
 | 
						|
badflag(tname, option)
 | 
						|
 char *tname, *option;
 | 
						|
{
 | 
						|
	fprintf(stderr, "%s type from `f2c -%s` on line %ld of %s\n",
 | 
						|
		tname, option, Plineno, Pfname);
 | 
						|
	Pbad++;
 | 
						|
	}
 | 
						|
 | 
						|
 static void
 | 
						|
detected(msg)
 | 
						|
 char *msg;
 | 
						|
{
 | 
						|
	fprintf(stderr,
 | 
						|
	"%sdetected on line %ld of %s\n", msg, Plineno, Pfname);
 | 
						|
	Pbad++;
 | 
						|
	}
 | 
						|
 | 
						|
 static void
 | 
						|
checklogical(k)
 | 
						|
 int k;
 | 
						|
{
 | 
						|
	static int lastmsg = 0;
 | 
						|
	static int seen[2] = {0,0};
 | 
						|
 | 
						|
	seen[k] = 1;
 | 
						|
	if (seen[1-k]) {
 | 
						|
		if (lastmsg < 3) {
 | 
						|
			lastmsg = 3;
 | 
						|
			detected(
 | 
						|
	"Illegal combination of LOGICAL types -- mixing -I4 with -I2 or -i2\n\t");
 | 
						|
			}
 | 
						|
		return;
 | 
						|
		}
 | 
						|
	if (k) {
 | 
						|
		if (tylogical == TYLONG || lastmsg >= 2)
 | 
						|
			return;
 | 
						|
		if (!lastmsg) {
 | 
						|
			lastmsg = 2;
 | 
						|
			badflag("LOGICAL", "I4");
 | 
						|
			}
 | 
						|
		}
 | 
						|
	else {
 | 
						|
		if (tylogical == TYSHORT || lastmsg & 1)
 | 
						|
			return;
 | 
						|
		if (!lastmsg) {
 | 
						|
			lastmsg = 1;
 | 
						|
			badflag("LOGICAL", "i2` or `f2c -I2");
 | 
						|
			}
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
 static void
 | 
						|
checkreal(k)
 | 
						|
{
 | 
						|
	static int warned = 0;
 | 
						|
	static int seen[2] = {0,0};
 | 
						|
 | 
						|
	seen[k] = 1;
 | 
						|
	if (seen[1-k]) {
 | 
						|
		if (warned < 2)
 | 
						|
			detected("Illegal mixture of -R and -!R ");
 | 
						|
		warned = 2;
 | 
						|
		return;
 | 
						|
		}
 | 
						|
	if (k == forcedouble || warned)
 | 
						|
		return;
 | 
						|
	warned = 1;
 | 
						|
	badflag("REAL return", k ? "!R" : "R");
 | 
						|
	}
 | 
						|
 | 
						|
 static void
 | 
						|
Pnotboth(e)
 | 
						|
 Extsym *e;
 | 
						|
{
 | 
						|
	if (e->curno)
 | 
						|
		return;
 | 
						|
	Pbad++;
 | 
						|
	e->curno = 1;
 | 
						|
	fprintf(stderr,
 | 
						|
	"%s cannot be both a procedure and a common block (line %ld of %s)\n",
 | 
						|
		e->fextname, Plineno, Pfname);
 | 
						|
	}
 | 
						|
 | 
						|
 static int
 | 
						|
numread(pf, n)
 | 
						|
 register FILE *pf;
 | 
						|
 int *n;
 | 
						|
{
 | 
						|
	register int c, k;
 | 
						|
 | 
						|
	if ((c = getc(pf)) < '0' || c > '9')
 | 
						|
		return c;
 | 
						|
	k = c - '0';
 | 
						|
	for(;;) {
 | 
						|
		if ((c = getc(pf)) == ' ') {
 | 
						|
			*n = k;
 | 
						|
			return c;
 | 
						|
			}
 | 
						|
		if (c < '0' || c > '9')
 | 
						|
			break;
 | 
						|
		k = 10*k + c - '0';
 | 
						|
		}
 | 
						|
	return c;
 | 
						|
	}
 | 
						|
 | 
						|
 static void argverify(), Pbadret();
 | 
						|
 | 
						|
 static int
 | 
						|
readref(pf, e, ftype)
 | 
						|
 register FILE *pf;
 | 
						|
 Extsym *e;
 | 
						|
 int ftype;
 | 
						|
{
 | 
						|
	register int c, *t;
 | 
						|
	int i, nargs, type;
 | 
						|
	Argtypes *at;
 | 
						|
	Atype *a, *ae;
 | 
						|
 | 
						|
	if (ftype > TYSUBR)
 | 
						|
		return 0;
 | 
						|
	if ((c = numread(pf, &nargs)) != ' ') {
 | 
						|
		if (c != ':')
 | 
						|
			return c == EOF;
 | 
						|
		/* just a typed external */
 | 
						|
		if (e->extstg == STGUNKNOWN) {
 | 
						|
			at = 0;
 | 
						|
			goto justsym;
 | 
						|
			}
 | 
						|
		if (e->extstg == STGEXT) {
 | 
						|
			if (e->extype != ftype)
 | 
						|
				Pbadret(ftype, e);
 | 
						|
			}
 | 
						|
		else
 | 
						|
			Pnotboth(e);
 | 
						|
		return 0;
 | 
						|
		}
 | 
						|
 | 
						|
	tnext = tfirst;
 | 
						|
	for(i = 0; i < nargs; i++) {
 | 
						|
		if ((c = numread(pf, &type)) != ' '
 | 
						|
		|| type >= 500
 | 
						|
		|| type != TYFTNLEN + 100 && type % 100 > TYSUBR)
 | 
						|
			return c == EOF;
 | 
						|
		if (tnext >= tlast)
 | 
						|
			trealloc();
 | 
						|
		*tnext++ = type;
 | 
						|
		}
 | 
						|
 | 
						|
	if (e->extstg == STGUNKNOWN) {
 | 
						|
 save_at:
 | 
						|
		at = (Argtypes *)
 | 
						|
			gmem(sizeof(Argtypes) + (nargs-1)*sizeof(Atype), 1);
 | 
						|
		at->nargs = nargs;
 | 
						|
		at->changes = 0;
 | 
						|
		t = tfirst;
 | 
						|
		a = at->atypes;
 | 
						|
		for(ae = a + nargs; a < ae; a++) {
 | 
						|
			a->type = *t++;
 | 
						|
			a->cp = 0;
 | 
						|
			}
 | 
						|
 justsym:
 | 
						|
		e->extstg = STGEXT;
 | 
						|
		e->extype = ftype;
 | 
						|
		e->arginfo = at;
 | 
						|
		}
 | 
						|
	else if (e->extstg != STGEXT) {
 | 
						|
		Pnotboth(e);
 | 
						|
		}
 | 
						|
	else if (!e->arginfo) {
 | 
						|
		if (e->extype != ftype)
 | 
						|
			Pbadret(ftype, e);
 | 
						|
		else
 | 
						|
			goto save_at;
 | 
						|
		}
 | 
						|
	else
 | 
						|
		argverify(ftype, e);
 | 
						|
	return 0;
 | 
						|
	}
 | 
						|
 | 
						|
 static int
 | 
						|
comlen(pf)
 | 
						|
 register FILE *pf;
 | 
						|
{
 | 
						|
	register int c;
 | 
						|
	register char *s, *se;
 | 
						|
	char buf[128], cbuf[128];
 | 
						|
	int refread;
 | 
						|
	long L;
 | 
						|
	Extsym *e;
 | 
						|
 | 
						|
	if ((c = getc(pf)) == EOF)
 | 
						|
		return 1;
 | 
						|
	if (c == ' ') {
 | 
						|
		refread = 0;
 | 
						|
		s = "comlen ";
 | 
						|
		}
 | 
						|
	else if (c == ':') {
 | 
						|
		refread = 1;
 | 
						|
		s = "ref: ";
 | 
						|
		}
 | 
						|
	else {
 | 
						|
 ret0:
 | 
						|
		if (c == '*')
 | 
						|
			ungetc(c,pf);
 | 
						|
		return 0;
 | 
						|
		}
 | 
						|
	while(*s) {
 | 
						|
		if ((c = getc(pf)) == EOF)
 | 
						|
			return 1;
 | 
						|
		if (c != *s++)
 | 
						|
			goto ret0;
 | 
						|
		}
 | 
						|
	s = buf;
 | 
						|
	se = buf + sizeof(buf) - 1;
 | 
						|
	for(;;) {
 | 
						|
		if ((c = getc(pf)) == EOF)
 | 
						|
			return 1;
 | 
						|
		if (c == ' ')
 | 
						|
			break;
 | 
						|
		if (s >= se || Pct[c] != P_anum)
 | 
						|
			goto ret0;
 | 
						|
		*s++ = c;
 | 
						|
		}
 | 
						|
	*s-- = 0;
 | 
						|
	if (s <= buf || *s != '_')
 | 
						|
		return 0;
 | 
						|
	strcpy(cbuf,buf);
 | 
						|
	*s-- = 0;
 | 
						|
	if (*s == '_') {
 | 
						|
		*s-- = 0;
 | 
						|
		if (s <= buf)
 | 
						|
			return 0;
 | 
						|
		}
 | 
						|
	for(L = 0;;) {
 | 
						|
		if ((c = getc(pf)) == EOF)
 | 
						|
			return 1;
 | 
						|
		if (c == ' ')
 | 
						|
			break;
 | 
						|
		if (c < '0' && c > '9')
 | 
						|
			goto ret0;
 | 
						|
		L = 10*L + c - '0';
 | 
						|
		}
 | 
						|
	if (!L && !refread)
 | 
						|
		return 0;
 | 
						|
	e = mkext(buf, cbuf);
 | 
						|
	if (refread)
 | 
						|
		return readref(pf, e, (int)L);
 | 
						|
	if (e->extstg == STGUNKNOWN) {
 | 
						|
		e->extstg = STGCOMMON;
 | 
						|
		e->maxleng = L;
 | 
						|
		}
 | 
						|
	else if (e->extstg != STGCOMMON)
 | 
						|
		Pnotboth(e);
 | 
						|
	else if (e->maxleng != L) {
 | 
						|
		fprintf(stderr,
 | 
						|
	"incompatible lengths for common block %s (line %ld of %s)\n",
 | 
						|
				    buf, Plineno, Pfname);
 | 
						|
		if (e->maxleng < L)
 | 
						|
			e->maxleng = L;
 | 
						|
		}
 | 
						|
	return 0;
 | 
						|
	}
 | 
						|
 | 
						|
 static int
 | 
						|
Ptoken(pf, canend)
 | 
						|
 FILE *pf;
 | 
						|
 int canend;
 | 
						|
{
 | 
						|
	register int c;
 | 
						|
	register char *s, *se;
 | 
						|
 | 
						|
 top:
 | 
						|
	for(;;) {
 | 
						|
		c = getc(pf);
 | 
						|
		if (c == EOF) {
 | 
						|
			if (canend)
 | 
						|
				return 0;
 | 
						|
			goto badeof;
 | 
						|
			}
 | 
						|
		if (Pct[c] != P_space)
 | 
						|
			break;
 | 
						|
		if (c == '\n')
 | 
						|
			Plineno++;
 | 
						|
		}
 | 
						|
	switch(Pct[c]) {
 | 
						|
		case P_anum:
 | 
						|
			if (c == '_')
 | 
						|
				badchar(c);
 | 
						|
			s = Ptok;
 | 
						|
			se = s + sizeof(Ptok) - 1;
 | 
						|
			do {
 | 
						|
				if (s < se)
 | 
						|
					*s++ = c;
 | 
						|
				if ((c = getc(pf)) == EOF) {
 | 
						|
 badeof:
 | 
						|
					fprintf(stderr,
 | 
						|
					"unexpected end of file in %s\n",
 | 
						|
						Pfname);
 | 
						|
					exit(2);
 | 
						|
					}
 | 
						|
				}
 | 
						|
				while(Pct[c] == P_anum);
 | 
						|
			ungetc(c,pf);
 | 
						|
			*s = 0;
 | 
						|
			return P_anum;
 | 
						|
 | 
						|
		case P_delim:
 | 
						|
			return c;
 | 
						|
 | 
						|
		case P_slash:
 | 
						|
			if ((c = getc(pf)) != '*') {
 | 
						|
				if (c == EOF)
 | 
						|
					goto badeof;
 | 
						|
				badchar('/');
 | 
						|
				}
 | 
						|
			if (canend && comlen(pf))
 | 
						|
				goto badeof;
 | 
						|
			for(;;) {
 | 
						|
				while((c = getc(pf)) != '*') {
 | 
						|
					if (c == EOF)
 | 
						|
						goto badeof;
 | 
						|
					if (c == '\n')
 | 
						|
						Plineno++;
 | 
						|
					}
 | 
						|
 slashseek:
 | 
						|
				switch(getc(pf)) {
 | 
						|
					case '/':
 | 
						|
						goto top;
 | 
						|
					case EOF:
 | 
						|
						goto badeof;
 | 
						|
					case '*':
 | 
						|
						goto slashseek;
 | 
						|
					}
 | 
						|
				}
 | 
						|
		default:
 | 
						|
			badchar(c);
 | 
						|
		}
 | 
						|
	/* NOT REACHED */
 | 
						|
	return 0;
 | 
						|
	}
 | 
						|
 | 
						|
 static int
 | 
						|
Pftype()
 | 
						|
{
 | 
						|
	switch(Ptok[0]) {
 | 
						|
		case 'C':
 | 
						|
			if (!strcmp(Ptok+1, "_f"))
 | 
						|
				return TYCOMPLEX;
 | 
						|
			break;
 | 
						|
		case 'E':
 | 
						|
			if (!strcmp(Ptok+1, "_f")) {
 | 
						|
				/* TYREAL under forcedouble */
 | 
						|
				checkreal(1);
 | 
						|
				return TYREAL;
 | 
						|
				}
 | 
						|
			break;
 | 
						|
		case 'H':
 | 
						|
			if (!strcmp(Ptok+1, "_f"))
 | 
						|
				return TYCHAR;
 | 
						|
			break;
 | 
						|
		case 'Z':
 | 
						|
			if (!strcmp(Ptok+1, "_f"))
 | 
						|
				return TYDCOMPLEX;
 | 
						|
			break;
 | 
						|
		case 'd':
 | 
						|
			if (!strcmp(Ptok+1, "oublereal"))
 | 
						|
				return TYDREAL;
 | 
						|
			break;
 | 
						|
		case 'i':
 | 
						|
			if (!strcmp(Ptok+1, "nt"))
 | 
						|
				return TYSUBR;
 | 
						|
			if (!strcmp(Ptok+1, "nteger"))
 | 
						|
				return TYLONG;
 | 
						|
			break;
 | 
						|
		case 'l':
 | 
						|
			if (!strcmp(Ptok+1, "ogical")) {
 | 
						|
				checklogical(1);
 | 
						|
				return TYLOGICAL;
 | 
						|
				}
 | 
						|
			break;
 | 
						|
		case 'r':
 | 
						|
			if (!strcmp(Ptok+1, "eal")) {
 | 
						|
				checkreal(0);
 | 
						|
				return TYREAL;
 | 
						|
				}
 | 
						|
			break;
 | 
						|
		case 's':
 | 
						|
			if (!strcmp(Ptok+1, "hortint"))
 | 
						|
				return TYSHORT;
 | 
						|
			if (!strcmp(Ptok+1, "hortlogical")) {
 | 
						|
				checklogical(0);
 | 
						|
				return TYLOGICAL;
 | 
						|
				}
 | 
						|
			break;
 | 
						|
		}
 | 
						|
	bad_type();
 | 
						|
	/* NOT REACHED */
 | 
						|
	return 0;
 | 
						|
	}
 | 
						|
 | 
						|
 static void
 | 
						|
wanted(i, what)
 | 
						|
 int i;
 | 
						|
 char *what;
 | 
						|
{
 | 
						|
	if (i != P_anum) {
 | 
						|
		Ptok[0] = i;
 | 
						|
		Ptok[1] = 0;
 | 
						|
		}
 | 
						|
	fprintf(stderr,"Error: expected %s, not \"%s\" (line %ld of %s)\n",
 | 
						|
		what, Ptok, Plineno, Pfname);
 | 
						|
	exit(2);
 | 
						|
	}
 | 
						|
 | 
						|
 static int
 | 
						|
Ptype(pf)
 | 
						|
 FILE *pf;
 | 
						|
{
 | 
						|
	int i, rv;
 | 
						|
 | 
						|
	i = Ptoken(pf,0);
 | 
						|
	if (i == ')')
 | 
						|
		return 0;
 | 
						|
	if (i != P_anum)
 | 
						|
		badchar(i);
 | 
						|
 | 
						|
	rv = 0;
 | 
						|
	switch(Ptok[0]) {
 | 
						|
		case 'C':
 | 
						|
			if (!strcmp(Ptok+1, "_fp"))
 | 
						|
				rv = TYCOMPLEX+200;
 | 
						|
			break;
 | 
						|
		case 'D':
 | 
						|
			if (!strcmp(Ptok+1, "_fp"))
 | 
						|
				rv = TYDREAL+200;
 | 
						|
			break;
 | 
						|
		case 'E':
 | 
						|
		case 'R':
 | 
						|
			if (!strcmp(Ptok+1, "_fp"))
 | 
						|
				rv = TYREAL+200;
 | 
						|
			break;
 | 
						|
		case 'H':
 | 
						|
			if (!strcmp(Ptok+1, "_fp"))
 | 
						|
				rv = TYCHAR+200;
 | 
						|
			break;
 | 
						|
		case 'I':
 | 
						|
			if (!strcmp(Ptok+1, "_fp"))
 | 
						|
				rv = TYLONG+200;
 | 
						|
			break;
 | 
						|
		case 'J':
 | 
						|
			if (!strcmp(Ptok+1, "_fp"))
 | 
						|
				rv = TYSHORT+200;
 | 
						|
			break;
 | 
						|
		case 'K':
 | 
						|
			checklogical(0);
 | 
						|
			goto Logical;
 | 
						|
		case 'L':
 | 
						|
			checklogical(1);
 | 
						|
 Logical:
 | 
						|
			if (!strcmp(Ptok+1, "_fp"))
 | 
						|
				rv = TYLOGICAL+200;
 | 
						|
			break;
 | 
						|
		case 'S':
 | 
						|
			if (!strcmp(Ptok+1, "_fp"))
 | 
						|
				rv = TYSUBR+200;
 | 
						|
			break;
 | 
						|
		case 'U':
 | 
						|
			if (!strcmp(Ptok+1, "_fp"))
 | 
						|
				rv = TYUNKNOWN+300;
 | 
						|
			break;
 | 
						|
		case 'Z':
 | 
						|
			if (!strcmp(Ptok+1, "_fp"))
 | 
						|
				rv = TYDCOMPLEX+200;
 | 
						|
			break;
 | 
						|
		case 'c':
 | 
						|
			if (!strcmp(Ptok+1, "har"))
 | 
						|
				rv = TYCHAR;
 | 
						|
			else if (!strcmp(Ptok+1, "omplex"))
 | 
						|
				rv = TYCOMPLEX;
 | 
						|
			break;
 | 
						|
		case 'd':
 | 
						|
			if (!strcmp(Ptok+1, "oublereal"))
 | 
						|
				rv = TYDREAL;
 | 
						|
			else if (!strcmp(Ptok+1, "oublecomplex"))
 | 
						|
				rv = TYDCOMPLEX;
 | 
						|
			break;
 | 
						|
		case 'f':
 | 
						|
			if (!strcmp(Ptok+1, "tnlen"))
 | 
						|
				rv = TYFTNLEN+100;
 | 
						|
			break;
 | 
						|
		case 'i':
 | 
						|
			if (!strcmp(Ptok+1, "nteger"))
 | 
						|
				rv = TYLONG;
 | 
						|
			break;
 | 
						|
		case 'l':
 | 
						|
			if (!strcmp(Ptok+1, "ogical")) {
 | 
						|
				checklogical(1);
 | 
						|
				rv = TYLOGICAL;
 | 
						|
				}
 | 
						|
			break;
 | 
						|
		case 'r':
 | 
						|
			if (!strcmp(Ptok+1, "eal"))
 | 
						|
				rv = TYREAL;
 | 
						|
			break;
 | 
						|
		case 's':
 | 
						|
			if (!strcmp(Ptok+1, "hortint"))
 | 
						|
				rv = TYSHORT;
 | 
						|
			else if (!strcmp(Ptok+1, "hortlogical")) {
 | 
						|
				checklogical(0);
 | 
						|
				rv = TYLOGICAL;
 | 
						|
				}
 | 
						|
			break;
 | 
						|
		case 'v':
 | 
						|
			if (tnext == tfirst && !strcmp(Ptok+1, "oid")) {
 | 
						|
				if ((i = Ptoken(pf,0)) != /*(*/ ')')
 | 
						|
					wanted(i, /*(*/ "\")\"");
 | 
						|
				return 0;
 | 
						|
				}
 | 
						|
		}
 | 
						|
	if (!rv)
 | 
						|
		bad_type();
 | 
						|
	if (rv < 100 && (i = Ptoken(pf,0)) != '*')
 | 
						|
			wanted(i, "\"*\"");
 | 
						|
	if ((i = Ptoken(pf,0)) == P_anum)
 | 
						|
		i = Ptoken(pf,0);	/* skip variable name */
 | 
						|
	switch(i) {
 | 
						|
		case ')':
 | 
						|
			ungetc(i,pf);
 | 
						|
			break;
 | 
						|
		case ',':
 | 
						|
			break;
 | 
						|
		default:
 | 
						|
			wanted(i, "\",\" or \")\"");
 | 
						|
		}
 | 
						|
	return rv;
 | 
						|
	}
 | 
						|
 | 
						|
 static char *
 | 
						|
trimunder()
 | 
						|
{
 | 
						|
	register char *s;
 | 
						|
	register int n;
 | 
						|
	static char buf[128];
 | 
						|
 | 
						|
	s = Ptok + strlen(Ptok) - 1;
 | 
						|
	if (*s != '_') {
 | 
						|
		fprintf(stderr,
 | 
						|
			"warning: %s does not end in _ (line %ld of %s)\n",
 | 
						|
			Ptok, Plineno, Pfname);
 | 
						|
		return Ptok;
 | 
						|
		}
 | 
						|
	if (s[-1] == '_')
 | 
						|
		s--;
 | 
						|
	strncpy(buf, Ptok, n = s - Ptok);
 | 
						|
	buf[n] = 0;
 | 
						|
	return buf;
 | 
						|
	}
 | 
						|
 | 
						|
 static void
 | 
						|
Pbadmsg(msg, p)
 | 
						|
 char *msg;
 | 
						|
 Extsym *p;
 | 
						|
{
 | 
						|
	Pbad++;
 | 
						|
	fprintf(stderr, "%s for %s (line %ld of %s):\n\t", msg,
 | 
						|
		p->fextname, Plineno, Pfname);
 | 
						|
	p->arginfo->nargs = -1;
 | 
						|
	}
 | 
						|
 | 
						|
 char *Argtype();
 | 
						|
 | 
						|
 static void
 | 
						|
Pbadret(ftype, p)
 | 
						|
 int ftype;
 | 
						|
 Extsym *p;
 | 
						|
{
 | 
						|
	char buf1[32], buf2[32];
 | 
						|
 | 
						|
	Pbadmsg("inconsistent types",p);
 | 
						|
	fprintf(stderr, "here %s, previously %s\n",
 | 
						|
		Argtype(ftype+200,buf1),
 | 
						|
		Argtype(p->extype+200,buf2));
 | 
						|
	}
 | 
						|
 | 
						|
 static void
 | 
						|
argverify(ftype, p)
 | 
						|
 int ftype;
 | 
						|
 Extsym *p;
 | 
						|
{
 | 
						|
	Argtypes *at;
 | 
						|
	register Atype *aty;
 | 
						|
	int i, j, k;
 | 
						|
	register int *t, *te;
 | 
						|
	char buf1[32], buf2[32];
 | 
						|
	int type_fixup();
 | 
						|
 | 
						|
	at = p->arginfo;
 | 
						|
	if (at->nargs < 0)
 | 
						|
		return;
 | 
						|
	if (p->extype != ftype) {
 | 
						|
		Pbadret(ftype, p);
 | 
						|
		return;
 | 
						|
		}
 | 
						|
	t = tfirst;
 | 
						|
	te = tnext;
 | 
						|
	i = te - t;
 | 
						|
	if (at->nargs != i) {
 | 
						|
		j = at->nargs;
 | 
						|
		Pbadmsg("differing numbers of arguments",p);
 | 
						|
		fprintf(stderr, "here %d, previously %d\n",
 | 
						|
			i, j);
 | 
						|
		return;
 | 
						|
		}
 | 
						|
	for(aty = at->atypes; t < te; t++, aty++) {
 | 
						|
		if (*t == aty->type)
 | 
						|
			continue;
 | 
						|
		j = aty->type;
 | 
						|
		k = *t;
 | 
						|
		if (k >= 300 || k == j)
 | 
						|
			continue;
 | 
						|
		if (j >= 300) {
 | 
						|
			if (k >= 200) {
 | 
						|
				if (k == TYUNKNOWN + 200)
 | 
						|
					continue;
 | 
						|
				if (j % 100 != k - 200
 | 
						|
				 && k != TYSUBR + 200
 | 
						|
				 && j != TYUNKNOWN + 300
 | 
						|
				 && !type_fixup(at,aty,k))
 | 
						|
					goto badtypes;
 | 
						|
				}
 | 
						|
			else if (j % 100 % TYSUBR != k % TYSUBR
 | 
						|
					&& !type_fixup(at,aty,k))
 | 
						|
				goto badtypes;
 | 
						|
			}
 | 
						|
		else if (k < 200 || j < 200)
 | 
						|
			goto badtypes;
 | 
						|
		else if (k == TYUNKNOWN+200)
 | 
						|
			continue;
 | 
						|
		else if (j != TYUNKNOWN+200)
 | 
						|
			{
 | 
						|
 badtypes:
 | 
						|
			Pbadmsg("differing calling sequences",p);
 | 
						|
			i = t - tfirst + 1;
 | 
						|
			fprintf(stderr,
 | 
						|
				"arg %d: here %s, prevously %s\n",
 | 
						|
				i, Argtype(k,buf1), Argtype(j,buf2));
 | 
						|
			return;
 | 
						|
			}
 | 
						|
		/* We've subsequently learned the right type,
 | 
						|
		   as in the call on zoo below...
 | 
						|
 | 
						|
			subroutine foo(x, zap)
 | 
						|
			external zap
 | 
						|
			call goo(zap)
 | 
						|
			x = zap(3)
 | 
						|
			call zoo(zap)
 | 
						|
			end
 | 
						|
		 */
 | 
						|
		aty->type = k;
 | 
						|
		at->changes = 1;
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
 static void
 | 
						|
newarg(ftype, p)
 | 
						|
 int ftype;
 | 
						|
 Extsym *p;
 | 
						|
{
 | 
						|
	Argtypes *at;
 | 
						|
	register Atype *aty;
 | 
						|
	register int *t, *te;
 | 
						|
	int i, k;
 | 
						|
 | 
						|
	if (p->extstg == STGCOMMON) {
 | 
						|
		Pnotboth(p);
 | 
						|
		return;
 | 
						|
		}
 | 
						|
	p->extstg = STGEXT;
 | 
						|
	p->extype = ftype;
 | 
						|
	p->exproto = 1;
 | 
						|
	t = tfirst;
 | 
						|
	te = tnext;
 | 
						|
	i = te - t;
 | 
						|
	k = sizeof(Argtypes) + (i-1)*sizeof(Atype);
 | 
						|
	at = p->arginfo = (Argtypes *)gmem(k,1);
 | 
						|
	at->nargs = i;
 | 
						|
	at->changes = 0;
 | 
						|
	for(aty = at->atypes; t < te; aty++) {
 | 
						|
		aty->type = *t++;
 | 
						|
		aty->cp = 0;
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
 static int
 | 
						|
Pfile(fname)
 | 
						|
 char *fname;
 | 
						|
{
 | 
						|
	char *s;
 | 
						|
	int ftype, i;
 | 
						|
	FILE *pf;
 | 
						|
	Extsym *p;
 | 
						|
 | 
						|
	for(s = fname; *s; s++);
 | 
						|
	if (s - fname < 2
 | 
						|
	|| s[-2] != '.'
 | 
						|
	|| (s[-1] != 'P' && s[-1] != 'p'))
 | 
						|
		return 0;
 | 
						|
 | 
						|
	if (!(pf = fopen(fname, textread))) {
 | 
						|
		fprintf(stderr, "can't open %s\n", fname);
 | 
						|
		exit(2);
 | 
						|
		}
 | 
						|
	Pfname = fname;
 | 
						|
	Plineno = 1;
 | 
						|
	if (!Pct[' ']) {
 | 
						|
		for(s = " \t\n\r\013\f"; *s; s++) /* ACK_MOD: \v is not K&R C */
 | 
						|
			Pct[*s] = P_space;
 | 
						|
		for(s = "*,();"; *s; s++)
 | 
						|
			Pct[*s] = P_delim;
 | 
						|
		for(i = '0'; i <= '9'; i++)
 | 
						|
			Pct[i] = P_anum;
 | 
						|
		for(s = "abcdefghijklmnopqrstuvwxyz"; i = *s; s++)
 | 
						|
			Pct[i] = Pct[i+'A'-'a'] = P_anum;
 | 
						|
		Pct['_'] = P_anum;
 | 
						|
		Pct['/'] = P_slash;
 | 
						|
		}
 | 
						|
 | 
						|
	for(;;) {
 | 
						|
		if (!(i = Ptoken(pf,1)))
 | 
						|
			break;
 | 
						|
		if (i != P_anum
 | 
						|
		|| !strcmp(Ptok, "extern")
 | 
						|
		&& (i = Ptoken(pf,0)) != P_anum)
 | 
						|
			badchar(i);
 | 
						|
		ftype = Pftype();
 | 
						|
 getname:
 | 
						|
		if ((i = Ptoken(pf,0)) != P_anum)
 | 
						|
			badchar(i);
 | 
						|
		p = mkext(trimunder(), Ptok);
 | 
						|
 | 
						|
		if ((i = Ptoken(pf,0)) != '(')
 | 
						|
			badchar(i);
 | 
						|
		tnext = tfirst;
 | 
						|
		while(i = Ptype(pf)) {
 | 
						|
			if (tnext >= tlast)
 | 
						|
				trealloc();
 | 
						|
			*tnext++ = i;
 | 
						|
			}
 | 
						|
		if (p->arginfo)
 | 
						|
			argverify(ftype, p);
 | 
						|
		else
 | 
						|
			newarg(ftype, p);
 | 
						|
		i = Ptoken(pf,0);
 | 
						|
		switch(i) {
 | 
						|
			case ';':
 | 
						|
				break;
 | 
						|
			case ',':
 | 
						|
				goto getname;
 | 
						|
			default:
 | 
						|
				wanted(i, "\";\" or \",\"");
 | 
						|
			}
 | 
						|
		}
 | 
						|
	fclose(pf);
 | 
						|
	return 1;
 | 
						|
	}
 | 
						|
 | 
						|
 void
 | 
						|
read_Pfiles(ffiles)
 | 
						|
 char **ffiles;
 | 
						|
{
 | 
						|
	char **f1files, **f1files0, *s;
 | 
						|
	int k;
 | 
						|
	register Extsym *e, *ee;
 | 
						|
	register Argtypes *at;
 | 
						|
	extern int retcode;
 | 
						|
 | 
						|
	f1files0 = f1files = ffiles;
 | 
						|
	while(s = *ffiles++)
 | 
						|
		if (!Pfile(s))
 | 
						|
			*f1files++ = s;
 | 
						|
	if (Pbad)
 | 
						|
		retcode = 8;
 | 
						|
	if (tfirst) {
 | 
						|
		free((char *)tfirst);
 | 
						|
		/* following should be unnecessary, as we won't be back here */
 | 
						|
		tfirst = tnext = tlast = 0;
 | 
						|
		tmax = 0;
 | 
						|
		}
 | 
						|
	*f1files = 0;
 | 
						|
	if (f1files == f1files0)
 | 
						|
		f1files[1] = 0;
 | 
						|
 | 
						|
	k = 0;
 | 
						|
	ee = nextext;
 | 
						|
	for (e = extsymtab; e < ee; e++)
 | 
						|
		if (e->extstg == STGEXT
 | 
						|
		&& (at = e->arginfo)) {
 | 
						|
			if (at->nargs < 0 || at->changes)
 | 
						|
				k++;
 | 
						|
			at->changes = 2;
 | 
						|
			}
 | 
						|
	if (k) {
 | 
						|
		fprintf(diagfile,
 | 
						|
		"%d prototype%s updated while reading prototypes.\n", k,
 | 
						|
			k > 1 ? "s" : "");
 | 
						|
		}
 | 
						|
	fflush(diagfile);
 | 
						|
	}
 |