prdecl.c

来自「<B>Digital的Unix操作系统VAX 4.2源码</B>」· C语言 代码 · 共 1,179 行 · 第 1/2 页

C
1,179
字号
	else	    {	    tokenahead = 1;	    strcpy(scandata.si_name,holdname);	    st->st_tipe = USERTYPE;	    if (st->st_dstruct == NOSTRUCT)		st->st_dstruct = UDEFS;	    st->st_uptr = findany(scandata.si_name);	    /*	     * If ptr is to an object that is not defined yet, then create	     * a dummy stentry to store the objects name.	     */	    if (st->st_uptr == NULL)		{		if (st->st_dstruct == PTRS)		    {		    st->st_uptr = getstentry();		    st->st_uptr->st_name = getname(scandata.si_idlen);		    strcpy(st->st_uptr->st_name, scandata.si_name);		    fprintf(stderr, "\"%s\", line %d: Warning: Pointer to an object that is not defined yet.\n", currfile, linecounter);		    fprintf(stderr, "     This is illegal in C.\n");		    }		else		    myexit(1,scandata.si_name);		}	    }	break;    case LEFTPAREN:		/* Enumerated type */	st->st_dstruct = UDEFS;	st->st_tipe = ENUMTY;	scanner(0);		/* get id */	if (nexttoken != IDENT)	    myexit(2,"identifier");	i = 1;	hold = st;	st = getstentry();	st->st_name = getname(scandata.si_idlen);	strcpy(st->st_name, scandata.si_name);	st->st_class = CONSTC;	st->st_tipe = ENUMTY;	st->st_cval = i-1;	st->st_enumptr = hold;	/* pt back to enum type */	hold->st_uptr = st;	/* pt enum type to 1st const */	addsymbol(st);	scanner(0);	for (; nexttoken == COMMA ;)	    {	    scanner(0);			/* get id */	    if (nexttoken != IDENT)		myexit(2,"identifier");	    i++;	    st = getstentry();	    st->st_name = getname(scandata.si_idlen);	    strcpy(st->st_name, scandata.si_name);	    st->st_class = CONSTC;	    st->st_tipe = ENUMTY;	    st->st_cval = i-1;	    st->st_enumptr = hold;	    addsymbol(st);	    scanner(0);			/* comma or left paren */	    }	if (nexttoken != RIGHTPAREN)	    myexit(2,")");	hold->st_numdims = i;	break;    case NUMCONST:		/* SUBRANGE */    case CHARCONST:	st->st_dstruct = SUBRANGES;	getrange(st,1);		/* 1=lower bound */	scanner(0);		/* get .. */	scanner(0);		/* get next const */	if (nexttoken == MINUS || nexttoken == PLUS)	    scanner(1);	getrange(st,0);		/* 0=upper bound */	break;    default:	return(0);    }    return(1);}/* * <array_type> ::=  *       [ packed ] array [ <simple_type> {,<simple_type> *} ] of <simple_type> *                        ^                                  ^       ^ *                                                                   | *					          should really be "datatype" * * RESTRICTIONS: *   1. We only deal with the upper bound since all C arrays start at 0 and go *	up.  Thus if negative Pascal Bounds are used, they are ignored! *   2. We only handle arrays of simple types. */arraytype(st)    struct stentry *st;{    struct pairs *pr, *newpr;    struct stentry *stptr;    int numdims = 1;    if ((nexttoken != ARRAYT) && (nexttoken != VARYING))	return(0);    else {	scanner(0); 	/* get [ */	if (nexttoken != LEFTBRACKET)	    myexit(2,"[");	else {	    st->st_dstruct = ARRS;	    for (;;)		{		scanner(1);	/* 1st bound (1 for no reals, despite '.') */		if (nexttoken == MINUS)		    scanner(1);		holdtoken = nexttoken;		scanner(0);	/* .. or , or ] */		switch (nexttoken) {		    case DOTDOT:			scanner(0);	/* upper bound */			if (nexttoken == MINUS)			    scanner(1);			holdtoken = nexttoken;			scanner(0);	/* , or ] */			/* fall into */		    case COMMA:		    case RIGHTBRACKET:			newpr = getpairs();			if (numdims == 1)			    st->st_bounds = newpr;			else			    pr->pr_next = newpr;			pr = newpr;			switch (holdtoken) {			    case IDENT:				if ((stptr = findany(scandata.si_name)) == NULL)				    myexit(1,scandata.si_name);				pr->pr_uuser = stptr;				if (stptr->st_class == CONSTC)				    pr->pr_upper = -1;  /* flag to use const name */				else if (stptr->st_bounds != NULL)					 {				         if (stptr->st_bounds->pr_uuser != NULL && 					     stptr->st_bounds->pr_uuser->st_class == CONSTC)					     {					     pr->pr_upper = -1;  /* flag to use const name */					     pr->pr_uuser = stptr->st_bounds->pr_uuser;					     }					 else					     pr->pr_upper = stptr->st_bounds->pr_upper + 1;					 }				else if (stptr->st_dstruct == UDEFS &&				         stptr->st_tipe == ENUMTY)					 pr->pr_upper = stptr->st_numdims;				break;			    case CHARCONST:				pr->pr_upper = scandata.si_name[0] + 1;				break;			    case NUMCONST:				pr->pr_upper = scandata.si_cvalue + 1;				break;			    case BOOLEANT:				pr->pr_upper = 2;				break;			    default:				myexit(3,"bad array dimension");			    }	/* switch 2 */			break;		    default:			myexit(3,"bad array dimension");		    }	/* switch 1 */		if (nexttoken == RIGHTBRACKET)		    break;		numdims++;		}   /* for */	    st->st_numdims = numdims;	    scanner(0);	    if (nexttoken != OFT)		myexit(2,"of");	    scanner(0);	/* type */	    if (!simpletype(st))		{		st->st_tipe = INTTY;		fprintf(stderr, "\"%s\", line %d: Warning: Array of complex type not supported, using integer\n", currfile, linecounter);		while (nexttoken != SEMICOLON)		    scanner(0);		tokenahead = 1;		}	    }	/* nexttoken == LEFTBRACKET */	}   /* nexttoken == ARRAYT */}/* * Getrange.  Get subrange bounds. * Call with st = the stentry for the type id.  The pairs record will *   be set up here. */getrange(st, lower)    struct stentry *st;    char lower;			/* 1 = getting lower, else upper */{    struct pairs *pr;    if (lower)	{	pr = getpairs();	st->st_bounds = pr;	}    else	pr = st->st_bounds;    switch (nexttoken) {	case NUMCONST:	    if (lower)		{		st->st_tipe = INTTY;		/* Base type of subrange */		pr->pr_lower = scandata.si_cvalue;		pr->pr_bound = INTTY;		}	    else		pr->pr_upper = scandata.si_cvalue;	    break;	case CHARCONST:	    if (lower)		{		st->st_tipe = CHARTY;		/* Base type of subrange */		pr->pr_lower = scandata.si_name[0];		pr->pr_bound = CHARTY;		}	    else		pr->pr_upper = scandata.si_name[0];	    break;	case IDENT:	    if (lower)		{		pr->pr_luser = findany(scandata.si_name);		if (pr->pr_luser == NULL)		    myexit(1,scandata.si_name);		if (pr->pr_luser->st_tipe == ENUMTY &&		    pr->pr_luser->st_class == CONSTC)		    {		    st->st_tipe = USERTYPE;		    st->st_uptr = pr->pr_luser->st_enumptr;		    }		else		    st->st_tipe = pr->pr_luser->st_tipe; /* Base type of subrange */		pr->pr_bound = USERTYPE;		}	    else		{		pr->pr_uuser = findany(scandata.si_name);		if (pr->pr_uuser == NULL)		    myexit(1,scandata.si_name);		pr->pr_upper = pr->pr_uuser->st_cval;	/* so value can be							   obtained for							   array bound*/		}	    break;	default:	    myexit(3,"bad subrange bound");    };}fieldlist(st,varec)    struct stentry *st;    int varec;			/* true if in varient record */{    int numdims = 0;		/* syntactically legal to have no fields */    struct stentry *rechead;	/* hold ptr to fill in # of fields */    struct stentry *secthead;	/* head of a sect of fields: f1,f2: type; */    struct stentry *sect;	/* to build up this "section" */    struct stentry *save_st;	/* save ptr to prior field & fill in "st_next" */    struct stentry *dupst;	/* to fill out dupvar st_entryies */    int undims = 0;		/* number of fields in varient record (union) */    struct stentry *unhead;	/* hold ptr to union field */    char holdname[LINELENGTH];	/* hold last symbol name for 'look-ahead' */    char lookahead = 0;		/* set true for varient record look ahead */    char union_name[LINELENGTH]; /* name of union to pass to 'dodefines' */    rechead = st;    scanner(0);			/* get 1st field id */    do	{	secthead = NULL;	do	    {	    if (nexttoken != IDENT)		if ((nexttoken == ENDT) || (varec && nexttoken == RIGHTPAREN))		    {		    rechead->st_numdims = numdims;		    return(1);		    }		else		    if (nexttoken == CASET)			goto docase;		    else			myexit(2,"end");	    numdims++;	    save_st = st;	    st = getstentry();	    inittvf(st);	    addsymbol(st);	/* ASDEP did this in-line here */	    /*	     * If this is the first field name of a given field stmt,	     *   then set up "secthead" and link "st_next".	     * Else,	     *   string together constructs like f1, f2, f3: type;	     *   with "st_dupvar".  We don't want the "st_next" link	     *   between "dupvar's" (because "st_next" is the way to	     *   get from a section head to a nested record).	     */	    if (secthead == NULL)		{		secthead = st;		sect = st;		if (save_st->st_next == NULL)		    save_st->st_next = st;		}	    else		{		sect->st_dupvar = st;		sect = st;		}	    st->st_name = getname(scandata.si_idlen+1);	/* +1 for "u" in unions */	    if (varec)		strcpy(st->st_name, "u");	    else		strcpy(st->st_name, "");	    strcat(st->st_name, scandata.si_name);	    st->st_class = FIELDC;	    savecmt = 0;	    /*	     * If we were a token ahead from varient record look-ahead (below)	     * then we've already scanned the ":" so just set nexttoken.	     */	    if (lookahead)		{		nexttoken = COLON;		lookahead = 0;		}	    else		scanner(0);		/* get next token */	    if (nexttoken == COMMA)		scanner(0);	    }	while (nexttoken != COLON);		scanner(0);	/*	 * Fill in data type for "head" variable in this `section':	 *    eg. f1, f2, f3: data-type;	 */	if (!datatype(secthead))	    myexit(3,"data type not recognized");	/* 	 * Make dupvar's "st_next" field's point to same place as	 * the secthead's st_next.  Needed to find subfields under the	 * dupvar, if the dupvar is of type record and get used in a	 * "with" stmt.	 *	 * Also save other "type" fields for help in processing "with"	 * statements.	 */	for (dupst = secthead->st_dupvar; dupst != NULL; dupst = dupst->st_dupvar)	    {	    dupst->st_next = secthead->st_next;	    dupst->st_lexlev = secthead->st_lexlev;	    dupst->st_dstruct = secthead->st_dstruct;	    dupst->st_tipe = secthead->st_tipe;	    dupst->st_class = secthead->st_class;	    dupst->st_uptr = secthead->st_uptr;	    dupst->st_numdims = secthead->st_numdims;	    dupst->st_bounds = secthead->st_bounds;	    }	scanner(0);		/* get SEMI (or "end" or ")" ) */	if (nexttoken == SEMICOLON)	    {	    savecmt = 1;	    scanner(0);		/* get next token (IDENT or END) */	    savecmt = 0;	    if (nexttoken == COMMENT)		{		secthead->st_cmt = scandata.si_cmtptr;		savecmt = 0;		scanner(0);		}	    }docase:	if (nexttoken == CASET)	    {	/* handle varient field of record */	    scanner(0);	    /*	     * Verify type of case variable	     */	    switch (nexttoken) {	    case BOOLEANT:	    case CHART:	    case INTEGERT:	    case IDENT:		 break;	    default:		 myexit(2,"scaler type");		 break;	    }	    /*	     * Look ahead to distinguish between the 2 legal formats:	     *     case var: type of	     *     case scaler-type of	     */	    strcpy(holdname,scandata.si_name);	    scanner(0);			/* look ahead */	    if (nexttoken != OFT)		if (nexttoken == COLON)		    {		    nexttoken = IDENT;		    strcpy(scandata.si_name,holdname);		    lookahead = 1;		    }		else		    myexit(2,":");	    }	}    while (nexttoken == IDENT);    /*     * Handle fields within varient part of a record.     * In C we will have a union with each Pascal "tag" section     * making a struct within the union.     */    if (nexttoken == OFT)	{	numdims++;	save_st = st;	/*	 * Create C union, named "un"	 */	st = getstentry();	inittvf(st);	if (save_st->st_next == NULL)	    save_st->st_next = st;	st->st_name = getname(5);	strcpy(st->st_name, "un_");	itoa(varec,scandata.si_name);	strcat(st->st_name, scandata.si_name);	st->st_class = FIELDC;	st->st_dstruct = RECORDS;	st->st_tipe = UNIONTY;	addsymbol(st);	unhead = st;	undims = 0;	lexlev++;	scanner(0);	varec++;	/*	 * Loop until end of Pascal varient record.	 * Each Pascal tag field section, will be a struct in C.	 * These structs get dummy names: un1, un2, un3, etc.	 */	while ((nexttoken != ENDT) && (!(varec && nexttoken == RIGHTPAREN)))	    {	    while (nexttoken != LEFTPAREN)		scanner(0);	    undims++;	    st = getstentry();	    inittvf(st);	    if (unhead->st_next == NULL)		unhead->st_next = st;	    st->st_name = getname(6);	    strcpy(st->st_name, "un");	    itoa(undims,scandata.si_name);	    strcat(st->st_name, scandata.si_name);	    st->st_class = FIELDC;	    st->st_dstruct = RECORDS;	    addsymbol(st);	    lexlev++;	    /*	     * Recursive call to fieldlist to get the fields under	     * this varient tag section.	     */	    fieldlist(st,varec);	    stindex[lexlev] = NULL;	/* terminate inner level */	    lexlev--;	    scanner(0);		/* get ";" or "end" */	    if (nexttoken == SEMICOLON)		{		savecmt = 1;		scanner(0);		savecmt = 0;		if (nexttoken == COMMENT)		    {		    st->st_cmt = scandata.si_cmtptr;		    scanner(0);		    }		}	    }	/* end while nexttoken != ENDT */	unhead->st_numdims = undims;	stindex[lexlev] = NULL;  /* terminate union level */	lexlev--;	/*	 * If we finished the highest lexic level varient (varec == 1)	 * then make stentries for "defines".  This way the added C union &	 * inner struct levels will be transparent to the program code.	 */	if (varec == 1)	    {	    for (st = rechead->st_next; st->st_tipe != UNIONTY; st = st->st_link)		if (st == NULL)		    myexit(3,"internal error in dodefines");	    strcpy(union_name,"");	    lexlev--;	    dodefines(st,union_name);	    lexlev++;	    }	varec--;	}   /* end if nexttoken == OFT */    if (nexttoken != ENDT && nexttoken != RIGHTPAREN)	myexit(2,"end or )");    rechead->st_numdims = numdims;}/* * Make st entries for "defines".  This way the added C union & * inner struct levels will be transparent to the program code. */dodefines(unionptr,union_name)    struct stentry *unionptr;    char *union_name;{    register struct stentry *st, *dst, *subrecst;    register int j, subrec_num, i, union_num;    char definestr[LINELENGTH];    /*     * Get the union name     */    strcat(union_name, unionptr->st_name);    strcat(union_name, ".");    union_num = unionptr->st_numdims;    st = unionptr->st_next;    /*     * Get ptr to inner record     */    subrecst = st;    for (i = 0; i < union_num; i++, subrecst = subrecst->st_link)	{	subrec_num = subrecst->st_numdims;	if (subrec_num == 0)	    continue;	/*	 * Get the inner record name	 */	strcpy(definestr, union_name);	strcat(definestr, subrecst->st_name);	strcat(definestr, ".");	st = subrecst->st_next;	for (j = 0; j < subrec_num; j++)	    {	    if (st->st_tipe == UNIONTY)		{		dodefines(st, definestr);		continue;		}	    dst = getstentry();	    inittvf(dst);	    dst->st_class = DEFINEC;	    dst->st_name = getname(strlen(st->st_name));	    strcpy(dst->st_name, st->st_name+1);	/* skip over "u" */	    dst->st_cmt = getcmtinfo();	    dst->st_cmt->cmt = getname(strlen(definestr)+strlen(st->st_name));	    strcpy(dst->st_cmt->cmt, definestr);	    strcat(dst->st_cmt->cmt, st->st_name);	    addsymbol(dst);	    st = st->st_link;	    /* skip over enum constants */	    }	}}

⌨️ 快捷键说明

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