⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 c.c

📁 <B>Digital的Unix操作系统VAX 4.2源码</B>
💻 C
字号:
/*#@(#)c.c	4.1	Ultrix	7/17/90*//* Copyright (c) 1982 Regents of the University of California */static char sccsid[] = "@(#)c.c 1.6 8/5/83";static char rcsid[] = "$Header: c.c,v 1.3 84/03/27 10:19:40 linton Exp $";/* * C-dependent symbol routines. */#include "defs.h"#include "symbols.h"#include "printsym.h"#include "languages.h"#include "c.h"#include "tree.h"#include "eval.h"#include "operators.h"#include "mappings.h"#include "process.h"#include "runtime.h"#include "machine.h"#ifndef public# include "tree.h"#endif#define isdouble(range) ( \    range->symvalue.rangev.upper == 0 and range->symvalue.rangev.lower > 0 \)#define isrange(t, name) (t->class == RANGE and istypename(t->type, name))private Language langC;/* * Initialize C language information. */public c_init(){    langC = language_define("c", ".c");    language_setop(langC, L_PRINTDECL, c_printdecl);    language_setop(langC, L_PRINTVAL, c_printval);    language_setop(langC, L_TYPEMATCH, c_typematch);    language_setop(langC, L_BUILDAREF, c_buildaref);    language_setop(langC, L_EVALAREF, c_evalaref);    language_setop(langC, L_MODINIT, c_modinit);    language_setop(langC, L_HASMODULES, c_hasmodules);    language_setop(langC, L_PASSADDR, c_passaddr);}/* * Test if two types are compatible. */public Boolean c_typematch(type1, type2)Symbol type1, type2;{    Boolean b;    register Symbol t1, t2, tmp;    t1 = type1;    t2 = type2;    if (t1 == t2) {	b = true;    } else {	t1 = rtype(t1);	t2 = rtype(t2);	if (t1 == t_char->type or t1 == t_int->type or t1 == t_real->type) {	    tmp = t1;	    t1 = t2;	    t2 = tmp;	}	b = (Boolean) (	    (		isrange(t1, "int") and		(t2 == t_int->type or t2 == t_char->type)	    ) or (		isrange(t1, "char") and		(t2 == t_char->type or t2 == t_int->type)	    ) or (		t1->class == RANGE and isdouble(t1) and t2 == t_real->type	    ) or (		t1->type == t2->type and (		    (t1->class == t2->class) or		    (t1->class == SCAL and t2->class == CONST) or		    (t1->class == CONST and t2->class == SCAL)		)	    ) or (		t1->class == PTR and c_typematch(t1->type, t_char) and		t2->class == ARRAY and c_typematch(t2->type, t_char) and		t2->language == primlang	    )	);    }    return b;}/* * Decide if a field is a bit field. */private Boolean isbitfield(s)register Symbol s;{    Boolean b;    register Integer off, len;    register Symbol t;    off = s->symvalue.field.offset;    len = s->symvalue.field.length;    if ((off mod BITSPERBYTE) != 0 or (len mod BITSPERBYTE) != 0) {	b = true;    } else {	t = rtype(s->type);	b = (Boolean)	    (t->class == SCAL and len != (sizeof(int)*BITSPERBYTE) or	    len != (size(t)*BITSPERBYTE)	);    }    return b;}/* * Print out the declaration of a C variable. */public c_printdecl(s)Symbol s;{    printdecl(s, 0);}private printdecl(s, indent)register Symbol s;Integer indent;{    register Symbol t;    Boolean semicolon, newline;    semicolon = true;    newline = true;    if (indent > 0) {	printf("%*c", indent, ' ');    }    if (s->class == TYPE) {	printf("typedef ");    }    switch (s->class) {	case CONST:	    if (s->type->class == SCAL) {		printf("(enumeration constant, ord %ld)",		    s->symvalue.iconval);	    } else {		printf("const %s = ", symname(s));		printval(s);	    }	    break;	case TYPE:	case VAR:	    if (s->class != TYPE) {		if (s->level == 1 and s->block != program) {		    printf("static ");		} else if (s->level < 0) {		    printf("register ");		}	    }	    if (s->type->class == ARRAY) {		printtype(s->type, s->type->type, indent);		t = rtype(s->type->chain);		assert(t->class == RANGE);		printf(" %s[%d]", symname(s), t->symvalue.rangev.upper + 1);	    } else {		printtype(s, s->type, indent);		if (s->type->class != PTR) {		    printf(" ");		}		printf("%s", symname(s));	    }	    break;	case FIELD:	    if (s->type->class == ARRAY) {		printtype(s->type, s->type->type, indent);		t = rtype(s->type->chain);		assert(t->class == RANGE);		printf(" %s[%d]", symname(s), t->symvalue.rangev.upper + 1);	    } else {		printtype(s, s->type, indent);		if (s->type->class != PTR) {		    printf(" ");		}		printf("%s", symname(s));	    }	    if (isbitfield(s)) {		printf(" : %d", s->symvalue.field.length);	    }	    break;	case TAG:	    if (s->type == nil) {		findtype(s);		if (s->type == nil) {		    error("unexpected missing type information");		}	    }	    printtype(s, s->type, indent);	    break;	case RANGE:	case ARRAY:	case RECORD:	case VARNT:	case PTR:	    semicolon = false;	    printtype(s, s, indent);	    break;	case PROC:	    semicolon = false;	    printf("%s", symname(s));	    c_listparams(s);	    newline = false;	    break;	case FUNC:	    semicolon = false;	    if (not istypename(s->type, "void")) {		printtype(s, s->type, indent);		printf(" ");	    }	    printf("%s", symname(s));	    c_listparams(s);	    newline = false;	    break;	case MODULE:	    semicolon = false;	    printf("source file \"%s.c\"", symname(s));	    break;	case PROG:	    semicolon = false;	    printf("executable file \"%s\"", symname(s));	    break;	default:	    error("class %s in c_printdecl", classname(s));    }    if (semicolon) {	putchar(';');    }    if (newline) {	putchar('\n');    }}/* * Recursive whiz-bang procedure to print the type portion * of a declaration. * * The symbol associated with the type is passed to allow * searching for type names without getting "type blah = blah". */private printtype(s, t, indent)Symbol s;Symbol t;Integer indent;{    register Symbol i;    long r0, r1;    register String p;    checkref(s);    checkref(t);    switch (t->class) {	case VAR:	case CONST:	case PROC:	    panic("printtype: class %s", classname(t));	    break;	case ARRAY:	    printf("array[");	    i = t->chain;	    if (i != nil) {		for (;;) {		    printtype(i, i, indent);		    i = i->chain;		    if (i == nil) {			break;		    }		    printf(", ");		}	    }	    printf("] of ");	    printtype(t, t->type, indent);	    break;	case RECORD:	case VARNT:	    printf("%s ", c_classname(t));	    if (s->name != nil and s->class == TAG) {		p = symname(s);		if (p[0] == '$' and p[1] == '$') {		    printf("%s ", &p[2]);		} else {		    printf("%s ", p);		}	    }	    printf("{\n", t->class == RECORD ? "struct" : "union");	    for (i = t->chain; i != nil; i = i->chain) {		assert(i->class == FIELD);		printdecl(i, indent+4);	    }	    if (indent > 0) {		printf("%*c", indent, ' ');	    }	    printf("}");	    break;	case RANGE:	    r0 = t->symvalue.rangev.lower;	    r1 = t->symvalue.rangev.upper;	    if (istypename(t->type, "char")) {		if (r0 < 0x20 or r0 > 0x7e) {		    printf("%ld..", r0);		} else {		    printf("'%c'..", (char) r0);		}		if (r1 < 0x20 or r1 > 0x7e) {		    printf("\\%lo", r1);		} else {		    printf("'%c'", (char) r1);		}	    } else if (r0 > 0 and r1 == 0) {		printf("%ld byte real", r0);	    } else if (r0 >= 0) {		printf("%lu..%lu", r0, r1);	    } else {		printf("%ld..%ld", r0, r1);	    }	    break;	case PTR:	    printtype(t, t->type, indent);	    if (t->type->class != PTR) {		printf(" ");	    }	    printf("*");	    break;	case FUNC:	case FFUNC:	    printtype(t, t->type, indent);	    printf("()");	    break;	case TYPE:	    if (t->name != nil) {		printname(stdout, t);	    } else {		printtype(t, t->type, indent);	    }	    break;	case TYPEREF:	    printf("@%s", symname(t));	    break;	case SCAL:	    printf("enum ");	    if (s->name != nil and s->class == TAG) {		printf("%s ", symname(s));	    }	    printf("{ ");	    i = t->chain;	    if (i != nil) {		for (;;) {		    printf("%s", symname(i));		    i = i->chain;		if (i == nil) break;		    printf(", ");		}	    }	    printf(" }");	    break;	case TAG:	    if (t->type == nil) {		printf("unresolved tag %s", symname(t));	    } else {		i = rtype(t->type);		printf("%s %s", c_classname(i), symname(t));	    }	    break;	default:	    printf("(class %d)", t->class);	    break;    }}/* * List the parameters of a procedure or function. * No attempt is made to combine like types. */public c_listparams(s)Symbol s;{    register Symbol t;    putchar('(');    for (t = s->chain; t != nil; t = t->chain) {	printf("%s", symname(t));	if (t->chain != nil) {	    printf(", ");	}    }    putchar(')');    if (s->chain != nil) {	printf("\n");	for (t = s->chain; t != nil; t = t->chain) {	    if (t->class != VAR) {		panic("unexpected class %d for parameter", t->class);	    }	    printdecl(t, 0);	}    } else {	putchar('\n');    }}/* * Print out the value on the top of the expression stack * in the format for the type of the given symbol. */public c_printval(s)Symbol s;{    register Symbol t;    register Address a;    integer i, len;    switch (s->class) {	case CONST:	case TYPE:	case VAR:	case REF:	case FVAR:	case TAG:	    c_printval(s->type);	    break;	case FIELD:	    if (isbitfield(s)) {		i = 0;		popn(size(s), &i);		i >>= (s->symvalue.field.offset mod BITSPERBYTE);		i &= ((1 << s->symvalue.field.length) - 1);		t = rtype(s->type);		if (t->class == SCAL) {		    printenum(i, t);		} else {		    printrange(i, t);		}	    } else {		c_printval(s->type);	    }	    break;	case ARRAY:	    t = rtype(s->type);	    if ((t->class == RANGE and istypename(t->type, "char")) or		t == t_char->type	    ) {		len = size(s);		sp -= len;		printf("\"%.*s\"", len, sp);	    } else {		printarray(s);	    }	    break;	case RECORD:	    c_printstruct(s);	    break;	case RANGE:	    if (istypename(s->type, "boolean")) {		printrange(popsmall(s), s);	    } else if (istypename(s->type, "char")) {		printrange(pop(char), s);	    } else if (isdouble(s)) {		switch (s->symvalue.rangev.lower) {		    case sizeof(float):			prtreal(pop(float));			break;		    case sizeof(double):			prtreal(pop(double));			break;		    default:			panic("bad real size %d", t->symvalue.rangev.lower);			break;		}	    } else {		printrange(popsmall(s), s);	    }	    break;	case PTR:	    t = rtype(s->type);	    a = pop(Address);	    if (a == 0) {		printf("(nil)");	    } else if (t->class == RANGE and istypename(t->type, "char")) {		printstring(a);	    } else {		printf("0x%x", a);	    }	    break;	case SCAL:	    i = pop(Integer);	    printenum(i, s);	    break;	default:	    if (ord(s->class) > ord(TYPEREF)) {		panic("printval: bad class %d", ord(s->class));	    }	    sp -= size(s);	    printf("[%s]", c_classname(s));	    break;    }}/* * Print out a C structure. */private c_printstruct(s)Symbol s;{    register Symbol f;    register Stack *savesp;    register Integer n, off, len;    sp -= size(s);    savesp = sp;    printf("(");    f = s->chain;    for (;;) {	off = f->symvalue.field.offset;	len = f->symvalue.field.length;	n = (off + len + BITSPERBYTE - 1) div BITSPERBYTE;	sp += n;	printf("%s = ", symname(f));	c_printval(f);	sp = savesp;	f = f->chain;    if (f == nil) break;	printf(", ");    }    printf(")");}/* * Print out a range type (integer, char, or boolean). */private printrange(i, t)Integer i;register Symbol t;{    if (istypename(t->type, "boolean")) {	printf(((Boolean) i) == true ? "true" : "false");    } else if (istypename(t->type, "char")) {	putchar('\'');	printchar(i);	putchar('\'');    } else if (t->symvalue.rangev.lower >= 0) {	printf("%lu", i);    } else {	printf("%ld", i);    }}/* * Print out a null-terminated string (pointer to char) * starting at the given address. */private printstring(addr)Address addr;{    register Address a;    register Integer i, len;    register Boolean endofstring;    union {	char ch[sizeof(Word)];	int word;    } u;    putchar('"');    a = addr;    endofstring = false;    while (not endofstring) {	dread(&u, a, sizeof(u));	i = 0;	do {	    if (u.ch[i] == '\0') {		endofstring = true;	    } else {		printchar(u.ch[i]);	    }	    ++i;	} while (i < sizeof(Word) and not endofstring);	a += sizeof(Word);    }    putchar('"');}/* * Print out an enumerated value by finding the corresponding * name in the enumeration list. */private printenum(i, t)Integer i;Symbol t;{    register Symbol e;    e = t->chain;    while (e != nil and e->symvalue.iconval != i) {	e = e->chain;    }    if (e != nil) {	printf("%s", symname(e));    } else {	printf("%d", i);    }}/* * Return the C name for the particular class of a symbol. */public String c_classname(s)Symbol s;{    String str;    switch (s->class) {	case RECORD:	    str = "struct";	    break;	case VARNT:	    str = "union";	    break;	case SCAL:	    str = "enum";	    break;	default:	    str = classname(s);    }    return str;}public Node c_buildaref(a, slist)Node a, slist;{    register Symbol t;    register Node p;    Symbol etype, atype, eltype;    Node esub, r;    r = a;    t = rtype(a->nodetype);    eltype = t->type;    if (t->class == PTR) {	p = slist->value.arg[0];	if (not compatible(p->nodetype, t_int)) {	    beginerrmsg();	    fprintf(stderr, "bad type for subscript of ");	    prtree(stderr, a);	    enderrmsg();	}	r = build(O_MUL, p, build(O_LCON, (long) size(eltype)));	r = build(O_ADD, build(O_RVAL, a), r);	r->nodetype = eltype;    } else if (t->class != ARRAY) {	beginerrmsg();	prtree(stderr, a);	fprintf(stderr, " is not an array");	enderrmsg();    } else {	p = slist;	t = t->chain;	for (; p != nil and t != nil; p = p->value.arg[1], t = t->chain) {	    esub = p->value.arg[0];	    etype = rtype(esub->nodetype);	    atype = rtype(t);	    if (not compatible(atype, etype)) {		beginerrmsg();		fprintf(stderr, "subscript ");		prtree(stderr, esub);		fprintf(stderr, " is the wrong type");		enderrmsg();	    }	    r = build(O_INDEX, r, esub);	    r->nodetype = eltype;	}	if (p != nil or t != nil) {	    beginerrmsg();	    if (p != nil) {		fprintf(stderr, "too many subscripts for ");	    } else {		fprintf(stderr, "not enough subscripts for ");	    }	    prtree(stderr, a);	    enderrmsg();	}    }    return r;}/* * Evaluate a subscript index. */public int c_evalaref(s, i)Symbol s;long i;{    long lb, ub;    s = rtype(s)->chain;    lb = s->symvalue.rangev.lower;    ub = s->symvalue.rangev.upper;    if (i < lb or i > ub) {	error("subscript out of range");    }    return (i - lb);}/* * Initialize typetable information. */public c_modinit (typetable)Symbol typetable[];{    /* nothing right now */}public boolean c_hasmodules (){    return false;}public boolean c_passaddr (param, exprtype)Symbol param, exprtype;{    boolean b;    Symbol t;    t = rtype(exprtype);    b = (boolean) (t->class == ARRAY);    return b;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -