+
+ /*
+ * check that two function/procedure namelist entries are compatible
+ */
+bool
+fcompat( formal , actual )
+ struct nl *formal;
+ struct nl *actual;
+{
+ register struct nl *f_chain;
+ register struct nl *a_chain;
+ bool compat = TRUE;
+
+ if ( formal == NIL || actual == NIL ) {
+ return FALSE;
+ }
+ for (a_chain = plist(actual), f_chain = plist(formal);
+ f_chain != NIL;
+ f_chain = f_chain->chain, a_chain = a_chain->chain) {
+ if (a_chain == NIL) {
+ error("%s %s declared on line %d has more arguments than",
+ parnam(formal->class), formal->symbol,
+ linenum(formal));
+ cerror("%s %s declared on line %d",
+ parnam(actual->class), actual->symbol,
+ linenum(actual));
+ return FALSE;
+ }
+ if ( a_chain -> class != f_chain -> class ) {
+ error("%s parameter %s of %s declared on line %d is not identical",
+ parnam(f_chain->class), f_chain->symbol,
+ formal->symbol, linenum(formal));
+ cerror("with %s parameter %s of %s declared on line %d",
+ parnam(a_chain->class), a_chain->symbol,
+ actual->symbol, linenum(actual));
+ compat = FALSE;
+ } else if (a_chain->class == FFUNC || a_chain->class == FPROC) {
+ compat = (compat && fcompat(f_chain, a_chain));
+ }
+ if ((a_chain->class != FPROC && f_chain->class != FPROC) &&
+ (a_chain->type != f_chain->type)) {
+ error("Type of %s parameter %s of %s declared on line %d is not identical",
+ parnam(f_chain->class), f_chain->symbol,
+ formal->symbol, linenum(formal));
+ cerror("to type of %s parameter %s of %s declared on line %d",
+ parnam(a_chain->class), a_chain->symbol,
+ actual->symbol, linenum(actual));
+ compat = FALSE;
+ }
+ }
+ if (a_chain != NIL) {
+ error("%s %s declared on line %d has fewer arguments than",
+ parnam(formal->class), formal->symbol,
+ linenum(formal));
+ cerror("%s %s declared on line %d",
+ parnam(actual->class), actual->symbol,
+ linenum(actual));
+ return FALSE;
+ }
+ return compat;
+}
+
+char *
+parnam(nltype)
+ int nltype;
+{
+ switch(nltype) {
+ case REF:
+ return "var";
+ case VAR:
+ return "value";
+ case FUNC:
+ case FFUNC:
+ return "function";
+ case PROC:
+ case FPROC:
+ return "procedure";
+ default:
+ return "SNARK";
+ }
+}
+
+plist(p)
+ struct nl *p;
+{
+ switch (p->class) {
+ case FFUNC:
+ case FPROC:
+ return p->ptr[ NL_FCHAIN ];
+ case PROC:
+ case FUNC:
+ return p->chain;
+ default:
+ panic("plist");
+ }
+}
+
+linenum(p)
+ struct nl *p;
+{
+ if (p->class == FUNC)
+ return p->ptr[NL_FVAR]->value[NL_LINENO];
+ return p->value[NL_LINENO];
+}