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);
 | |
| 	}
 |