xref: /csrg-svn/old/dbx/check.c (revision 38105)
121600Sdist /*
2*38105Sbostic  * Copyright (c) 1983 The Regents of the University of California.
3*38105Sbostic  * All rights reserved.
4*38105Sbostic  *
5*38105Sbostic  * Redistribution and use in source and binary forms are permitted
6*38105Sbostic  * provided that the above copyright notice and this paragraph are
7*38105Sbostic  * duplicated in all such forms and that any documentation,
8*38105Sbostic  * advertising materials, and other materials related to such
9*38105Sbostic  * distribution and use acknowledge that the software was developed
10*38105Sbostic  * by the University of California, Berkeley.  The name of the
11*38105Sbostic  * University may not be used to endorse or promote products derived
12*38105Sbostic  * from this software without specific prior written permission.
13*38105Sbostic  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14*38105Sbostic  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15*38105Sbostic  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
1621600Sdist  */
179660Slinton 
1821600Sdist #ifndef lint
19*38105Sbostic static char sccsid[] = "@(#)check.c	5.3 (Berkeley) 05/23/89";
20*38105Sbostic #endif /* not lint */
219660Slinton 
229660Slinton /*
239660Slinton  * Check a tree for semantic correctness.
249660Slinton  */
259660Slinton 
269660Slinton #include "defs.h"
279660Slinton #include "tree.h"
289660Slinton #include "operators.h"
299660Slinton #include "events.h"
309660Slinton #include "symbols.h"
319660Slinton #include "scanner.h"
329660Slinton #include "source.h"
339660Slinton #include "object.h"
349660Slinton #include "mappings.h"
359660Slinton #include "process.h"
3618214Slinton #include <signal.h>
379660Slinton 
389660Slinton #ifndef public
399660Slinton #endif
409660Slinton 
419660Slinton /*
429660Slinton  * Check that the nodes in a tree have the correct arguments
439660Slinton  * in order to be evaluated.  Basically the error checking here
449660Slinton  * frees the evaluation routines from worrying about anything
459660Slinton  * except dynamic errors, e.g. subscript out of range.
469660Slinton  */
479660Slinton 
489660Slinton public check(p)
499660Slinton register Node p;
509660Slinton {
5118214Slinton     Node p1, p2;
529660Slinton     Address addr;
539660Slinton     Symbol f;
549660Slinton 
559660Slinton     checkref(p);
569660Slinton     switch (p->op) {
5718214Slinton 	case O_ASSIGN:
5818214Slinton 	    p1 = p->value.arg[0];
5918214Slinton 	    p2 = p->value.arg[1];
6025811Sdonn 	    if (varIsSet("$unsafeassign")) {
6125811Sdonn 		if (size(p1->nodetype) != size(p2->nodetype)) {
6225811Sdonn 		    error("incompatible sizes");
6325811Sdonn 		}
6425811Sdonn 	    } else if (not compatible(p1->nodetype, p2->nodetype)) {
6518214Slinton 		error("incompatible types");
6618214Slinton 	    }
6718214Slinton 	    break;
6818214Slinton 
6918214Slinton 	case O_CATCH:
7018214Slinton 	case O_IGNORE:
7118214Slinton 	    if (p->value.lcon < 0 or p->value.lcon > NSIG) {
7218214Slinton 		error("invalid signal number");
7318214Slinton 	    }
7418214Slinton 	    break;
7518214Slinton 
7618214Slinton 	case O_CONT:
7718214Slinton 	    if (p->value.lcon != DEFSIG and (
7818214Slinton 		p->value.lcon < 0 or p->value.lcon > NSIG)
7918214Slinton 	    ) {
8018214Slinton 		error("invalid signal number");
8118214Slinton 	    }
8218214Slinton 	    break;
8318214Slinton 
8418214Slinton 	case O_DUMP:
8518214Slinton 	    if (p->value.arg[0] != nil) {
8618214Slinton 		if (p->value.arg[0]->op == O_SYM) {
8718214Slinton 		    f = p->value.arg[0]->value.sym;
8818214Slinton 		    if (not isblock(f)) {
8918214Slinton 			error("\"%s\" is not a block", symname(f));
9018214Slinton 		    }
9118214Slinton 		} else {
9218214Slinton 		    beginerrmsg();
9318214Slinton 		    fprintf(stderr, "expected a symbol, found \"");
9418214Slinton 		    prtree(stderr, p->value.arg[0]);
9518214Slinton 		    fprintf(stderr, "\"");
9618214Slinton 		    enderrmsg();
9718214Slinton 		}
9818214Slinton 	    }
9918214Slinton 	    break;
10018214Slinton 
1019660Slinton 	case O_LIST:
1029660Slinton 	    if (p->value.arg[0]->op == O_SYM) {
1039660Slinton 		f = p->value.arg[0]->value.sym;
1049660Slinton 		if (not isblock(f) or ismodule(f)) {
1059660Slinton 		    error("\"%s\" is not a procedure or function", symname(f));
1069660Slinton 		}
1079660Slinton 		addr = firstline(f);
1089660Slinton 		if (addr == NOADDR) {
1099660Slinton 		    error("\"%s\" is empty", symname(f));
1109660Slinton 		}
1119660Slinton 	    }
1129660Slinton 	    break;
1139660Slinton 
1149660Slinton 	case O_TRACE:
1159660Slinton 	case O_TRACEI:
1169660Slinton 	    chktrace(p);
1179660Slinton 	    break;
1189660Slinton 
1199660Slinton 	case O_STOP:
1209660Slinton 	case O_STOPI:
1219660Slinton 	    chkstop(p);
1229660Slinton 	    break;
1239660Slinton 
12418214Slinton 	case O_CALLPROC:
12516607Ssam 	case O_CALL:
12616607Ssam 	    if (not isroutine(p->value.arg[0]->nodetype)) {
12716607Ssam 		beginerrmsg();
12816607Ssam 		fprintf(stderr, "\"");
12916607Ssam 		prtree(stderr, p->value.arg[0]);
13016607Ssam 		fprintf(stderr, "\" not call-able");
13116607Ssam 		enderrmsg();
13216607Ssam 	    }
13316607Ssam 	    break;
13416607Ssam 
13518214Slinton 	case O_WHEREIS:
13618214Slinton 	    if (p->value.arg[0]->op == O_SYM and
13718214Slinton 	      p->value.arg[0]->value.sym == nil) {
13818214Slinton 		error("symbol not defined");
13918214Slinton 	    }
14018214Slinton 	    break;
14118214Slinton 
1429660Slinton 	default:
1439660Slinton 	    break;
1449660Slinton     }
1459660Slinton }
1469660Slinton 
1479660Slinton /*
1489660Slinton  * Check arguments to a trace command.
1499660Slinton  */
1509660Slinton 
1519660Slinton private chktrace(p)
1529660Slinton Node p;
1539660Slinton {
1549660Slinton     Node exp, place, cond;
1559660Slinton 
1569660Slinton     exp = p->value.arg[0];
1579660Slinton     place = p->value.arg[1];
1589660Slinton     cond = p->value.arg[2];
1599660Slinton     if (exp == nil) {
1609660Slinton 	chkblock(place);
1619660Slinton     } else if (exp->op == O_LCON or exp->op == O_QLINE) {
1629660Slinton 	if (place != nil) {
1639660Slinton 	    error("unexpected \"at\" or \"in\"");
1649660Slinton 	}
1659660Slinton 	if (p->op == O_TRACE) {
1669660Slinton 	    chkline(exp);
1679660Slinton 	} else {
1689660Slinton 	    chkaddr(exp);
1699660Slinton 	}
1709660Slinton     } else if (place != nil and (place->op == O_QLINE or place->op == O_LCON)) {
1719660Slinton 	if (p->op == O_TRACE) {
1729660Slinton 	    chkline(place);
1739660Slinton 	} else {
1749660Slinton 	    chkaddr(place);
1759660Slinton 	}
1769660Slinton     } else {
1779861Slinton 	if (exp->op != O_RVAL and exp->op != O_SYM and exp->op != O_CALL) {
1789660Slinton 	    error("can't trace expressions");
1799660Slinton 	}
1809660Slinton 	chkblock(place);
1819660Slinton     }
1829660Slinton }
1839660Slinton 
1849660Slinton /*
1859660Slinton  * Check arguments to a stop command.
1869660Slinton  */
1879660Slinton 
1889660Slinton private chkstop(p)
1899660Slinton Node p;
1909660Slinton {
1919660Slinton     Node exp, place, cond;
1929660Slinton 
1939660Slinton     exp = p->value.arg[0];
1949660Slinton     place = p->value.arg[1];
1959660Slinton     cond = p->value.arg[2];
1969660Slinton     if (exp != nil) {
19714444Slinton 	if (exp->op != O_RVAL and exp->op != O_SYM and exp->op != O_LCON) {
1989660Slinton 	    beginerrmsg();
1999660Slinton 	    fprintf(stderr, "expected variable, found ");
2009660Slinton 	    prtree(stderr, exp);
2019660Slinton 	    enderrmsg();
2029660Slinton 	}
2039660Slinton 	chkblock(place);
20416607Ssam     } else if (place != nil) {
20516607Ssam 	if (place->op == O_SYM) {
20616607Ssam 	    chkblock(place);
2079660Slinton 	} else {
20816607Ssam 	    if (p->op == O_STOP) {
20916607Ssam 		chkline(place);
21016607Ssam 	    } else {
21116607Ssam 		chkaddr(place);
21216607Ssam 	    }
2139660Slinton 	}
2149660Slinton     }
2159660Slinton }
2169660Slinton 
2179660Slinton /*
2189660Slinton  * Check to see that the given node specifies some subprogram.
2199660Slinton  * Nil is ok since that means the entire program.
2209660Slinton  */
2219660Slinton 
2229660Slinton private chkblock(b)
2239660Slinton Node b;
2249660Slinton {
22516607Ssam     Symbol p, outer;
22616607Ssam 
2279660Slinton     if (b != nil) {
2289660Slinton 	if (b->op != O_SYM) {
2299660Slinton 	    beginerrmsg();
2309660Slinton 	    fprintf(stderr, "expected subprogram, found ");
2319660Slinton 	    prtree(stderr, b);
2329660Slinton 	    enderrmsg();
23316607Ssam 	} else if (ismodule(b->value.sym)) {
23416607Ssam 	    outer = b->value.sym;
23516607Ssam 	    while (outer != nil) {
23616607Ssam 		find(p, outer->name) where p->block == outer endfind(p);
23716607Ssam 		if (p == nil) {
23816607Ssam 		    outer = nil;
23916607Ssam 		    error("\"%s\" is not a subprogram", symname(b->value.sym));
24016607Ssam 		} else if (ismodule(p)) {
24116607Ssam 		    outer = p;
24216607Ssam 		} else {
24316607Ssam 		    outer = nil;
24416607Ssam 		    b->value.sym = p;
24516607Ssam 		}
24616607Ssam 	    }
24718214Slinton 	} else if (
24818214Slinton 	    b->value.sym->class == VAR and
24918214Slinton 	    b->value.sym->name == b->value.sym->block->name and
25018214Slinton 	    b->value.sym->block->class == FUNC
25118214Slinton 	) {
25218214Slinton 	    b->value.sym = b->value.sym->block;
25316607Ssam 	} else if (not isblock(b->value.sym)) {
2549660Slinton 	    error("\"%s\" is not a subprogram", symname(b->value.sym));
2559660Slinton 	}
2569660Slinton     }
2579660Slinton }
2589660Slinton 
2599660Slinton /*
2609660Slinton  * Check to make sure a node corresponds to a source line.
2619660Slinton  */
2629660Slinton 
2639660Slinton private chkline(p)
2649660Slinton Node p;
2659660Slinton {
2669660Slinton     if (p == nil) {
2679660Slinton 	error("missing line");
2689660Slinton     } else if (p->op != O_QLINE and p->op != O_LCON) {
2699660Slinton 	error("expected source line number, found \"%t\"", p);
2709660Slinton     }
2719660Slinton }
2729660Slinton 
2739660Slinton /*
2749660Slinton  * Check to make sure a node corresponds to an address.
2759660Slinton  */
2769660Slinton 
2779660Slinton private chkaddr(p)
2789660Slinton Node p;
2799660Slinton {
2809660Slinton     if (p == nil) {
2819660Slinton 	error("missing address");
2829660Slinton     } else if (p->op != O_LCON and p->op != O_QLINE) {
2839660Slinton 	beginerrmsg();
2849660Slinton 	fprintf(stderr, "expected address, found \"");
2859660Slinton 	prtree(stderr, p);
2869660Slinton 	fprintf(stderr, "\"");
2879660Slinton 	enderrmsg();
2889660Slinton     }
2899660Slinton }
290