prsubr.c

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

C
927
字号
	     * 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;		}nextparam:	    /*	     * Now that we have the func/proc parameter type go back	     * and fill in the dummy func/proc decl type.	     */	    if (funcpar)		{		secthead->st_funcpar = funcpar;		prevsub->stdecl->st_dstruct = secthead->st_dstruct;		prevsub->stdecl->st_tipe = secthead->st_tipe;		prevsub->stdecl->st_uptr = secthead->st_uptr;		prevsub->stdecl->st_funcpar = funcpar;		if (funcpar == 1)		    {	/* function so fill in type entry */		    prevsub->ftype->st_dstruct = secthead->st_dstruct;		    prevsub->ftype->st_tipe = secthead->st_tipe;		    prevsub->ftype->st_uptr = secthead->st_uptr;		    prevsub->ftype->st_funcpar = 1;		    prevsub->ftype->st_class = FUNCC;  /* need for emit */		    }		else	/* proc so use type int for the type in C */		    secthead->st_tipe = INTTY;		}	    if (funcpar != 2)		scanner(0);		/* get SEMI or ")" */	    if (nexttoken != SEMICOLON && nexttoken != RIGHTPAREN)		if (nexttoken == ASSIGNOP)		    {		    scanner(0);		    /*		     * Check for VMS/Pascal "mechanism-specifier"		     */		    if (nexttoken == PERCENT)			{			scanner(0);			if (nexttoken == MECHT)			    scanner(0);			else			    myexit(2, "mechanism-specifier");			}		    buf[0] = '\0';		    getexpr(buf,0);		    secthead->st_value = malloc(strlen(buf) + 1);		    if (secthead->st_value == NULL)			myexit(-1,"");		    if (buf[0] == '(')			{			buf[0] = '{';			if (buf[strlen(buf)-1] == ')')			    buf[strlen(buf)-1] = '}';			}		    strcpy(secthead->st_value,buf);		    }		else		    myexit(2,"; or )");	    scanner(0);		/* get next token */	    }	while (nexttoken == IDENT || nexttoken == VART || nexttoken == PERCENT	    || nexttoken == FUNCTIONT || nexttoken == PROCEDURET);	funcst->st_nparams = num;	return(1);	}    else	return(0);}/* * labelseg:  Get a label segment.  Just scan it and ignore it, since * its unnecessary in C. */labelseg(){    if (nexttoken == LABELT)	{#	ifdef PRDEBUG	printd(stderr,"labelseg: got label token\n");#	endif	savecmt = 0;	scanner(0);		/* get label */	do	    {	    if (nexttoken != NUMCONST)		myexit(2, "numeric constant");	    scanner(0);		/* get next token */	    if (nexttoken == COMMA)		scanner(0);		/* get next token */	    }	while (nexttoken != SEMICOLON);	savecmt = 1;	scanner(0);		/* get next token */	savecmt = 0;	return(1);	}    else	return(0);}/* * commentseg:  Get a comment. */commentseg(tn)    struct treenode *tn;		/* ptr to decl begin block */{    struct stentry *st;			/* symbol table entry for comment */    if (nexttoken == COMMENT)	{#	ifdef PRDEBUG	printd(stderr,"commentseg: got COMMENT token\n");#	endif	st = getstentry();	st->st_class = COMTC;	st->st_cmt = scandata.si_cmtptr;	addsymbol(st);	if (tn->firstsym == NULL)	    tn->firstsym = st;	tn->lastsym = st;	savecmt = 0;	scanner(0);		/* next token after comment */	return(1);	}    else	return(0);}/* * Look for a subroutine segment (procedures & functions) * If getting func/proc parameter we will just set up a function decl. * * NOTE: uses global "prevsub".  This is needed to handle nested Pascal *	procedures, and get them un-nested in C. */subseg(parent, funcpar)    struct treenode *parent;    char funcpar;		/* 1 if getting func parameter */    				/* 2 if getting proc parameter */{    struct stentry *st;    struct treenode *tn;    char proc;    char fwd;			/* true if proc/funct found to be a fwd */    struct fwdstmt *fptr;	/* ptr to forward list */    char ext;    /*     * Check for VMS format of:  "[attributes] procedure/function name..."     */    if (nexttoken == LEFTBRACKET)	{	while (nexttoken != RIGHTBRACKET)	    scanner(0);	scanner(0);	}    for (; nexttoken == PROCEDURET || nexttoken == FUNCTIONT; )	{	if (nexttoken == PROCEDURET)	    proc = 1;	else	    proc = 0;	savecmt = 0;	scanner(0);			/* get proc name */	if (nexttoken != IDENT)	    myexit(2,"identifier");	/*	 * See if the proc/funct was already declared with a forward	 * statement.  If so point to the tree structure already built	 * for the declaration.	 */	fwd = 0;	if (funcpar == 0)	    for (fptr = fwdhead->next; fptr != NULL; fptr = fptr->next)		{		if (strcmp(fptr->tree->stdecl->st_name, scandata.si_name) == 0)		    {		    fwd = 1;		    break;		    }		}	if (fwd)	    tn = fptr->tree;	else	    {	    tn = gettn();	    if (proc)		tn->type = PDECLNODE;	    else		tn->type = FDECLNODE;	    }	if (fwd)	    {	    for (;nexttoken != SEMICOLON;)		scanner(0);	    lexlev++;	    /*	     * Turn on "st_emit" flag in parameter entries that go	     *    with the forward or external function.	     * Also stuff a pointer to the parameters into the active	     *    symbol table for this lexic level.	     */	    addsymbol(tn->firstc->firstsym);	    for (st = tn->firstc->firstsym; st != NULL; st = st->st_link)		{		st->st_emit = 1;		if (st == tn->firstc->lastsym)		    break;		}	    }	else	    {	    st = getstentry();	    if (proc)		st->st_class = PROCC;	    else		st->st_class = FUNCC;	    st->st_nparams = 0;	    st->st_name = getname(scandata.si_idlen);	    strcpy(st->st_name, scandata.si_name);	    tn->stdecl = st;	    st->st_dstruct = NOSTRUCT;	    st->st_tipe = INTTY;	    addsymbol(st);	    blkentry(tn);	    lexlev++;	    scanner(0);		/* get '(' or ';'  or ':' */	    (void) paramseg(tn->firstc, st, parent);	    if (!proc)		{		if (funcpar)		    {		    if (funcpar == 1)			{			st = getstentry();			tn->ftype = st;			/*			 * We will fill in the function type back in			 *   paramseg by using the prevsub pointer.			 */			 }		    }		else		    {		    if (nexttoken != COLON)			myexit(2,":");		    /*		     * Get the function type.		     * Also save the type info in the funct class stentry		     * for use in forward/external function type decls, and		     * for print formats from Pascal write stmts. 		     */		    scanner(0);		/* get funct type */		    st = getstentry();		    tn->ftype = st;		    if (!datatype(st))			myexit(3,"data type not recognized");		    tn->stdecl->st_dstruct = st->st_dstruct;		    tn->stdecl->st_tipe = st->st_tipe;		    tn->stdecl->st_uptr = st->st_uptr;		    scanner(0);		/* get ';' */		    }		}	    }	if (funcpar == 0)	    {	    savecmt = 1;	    scanner(0);		/* get nexttoken AFTER ';' */	    savecmt = 0;		(void) commentseg(tn->firstc->next);	    }	/*	 * Handle external declaration exactly as a forward declaration.	 * This will create a function type declaration in C.	 * Syntax: "function name (params): type; external;"	 *   The reserved word table in sc.c returns the token EXTERNALT	 *   for "extern" and "fortran" also.	 */	if (nexttoken == EXTERNALT || nexttoken == FORWARDT)	    {	    fwdcurr->next = getfwd();	    fwdcurr = fwdcurr->next;	    fwdcurr->tree = tn;	    /*	     * We want the "decl-begin" node (parent->prev->firstsym)	     * to point to the proc id in the symbol table, so that	     * a type definition will be produced for the proc id.	     */	    if (parent->prev->firstsym == NULL)		parent->prev->firstsym = tn->stdecl;	    parent->prev->lastsym = tn->stdecl;	    scanner(0);	    if (nexttoken == SEMICOLON)		{		savecmt = 1;		scanner(0);		savecmt = 0;		(void) commentseg(tn->firstc->next);		}	    }	else	    {	    if (parent->firstc == NULL)		parent->firstc = tn;	    parent->lastc = tn;	    if (prevsub != NULL)		prevsub->next = tn;	    prevsub = tn;	    /*	     * If getting func/proc parameter, then we are done	     * so return here.	     */	    if (funcpar)		return;	    (void) labelseg();		(void) commentseg(tn->firstc->next);	    (void) constseg(tn->firstc->next);		(void) commentseg(tn->firstc->next);	    (void) typeseg(tn->firstc->next);		(void) commentseg(tn->firstc->next);	    (void) varseg(tn->firstc->next,tn);		(void) commentseg(tn->firstc->next);	    /*	     * Here's the clever part for un-nesting Pascal procedures.	     * We want procs at same level, no nesting.  Global "prevsub"	     * takes care of holding a pointer to the current proc tree	     * node, so that it can be the next proc's prev.	     */	    (void) subseg(parent, 0);	    savecmt = 1;	    scanner(0);		/* skip over "begin" */	    savecmt = 0;	    (void) statelist(tn->lastc, FUNCLEVEL);	    }	stindex[lexlev] = NULL;	lexlev--;	/*	 * Check for VMS format of:  "[attributes] procedure/function name..."	 */	if (nexttoken == LEFTBRACKET)	    {	    while (nexttoken != RIGHTBRACKET)		scanner(0);	    scanner(0);	    }	}}/* * Look for a forward segment.  If forward keyword is found, make tree * structure entry for the func/proc now.  Get its params and save the * func/proc st entry & param info under this tree node in the special * forward list.  Then this special tree entry can be retrieved later * when the function body is encountered. * * syntax: "forward procedure (params);" */fwdseg(parent)    struct treenode *parent;		/* ptr to decl begin block */{    struct treenode *prev = NULL;    struct stentry *st;			/* for saving fwd info */    struct treenode *tn2;		/* for saving fwd info */    char proc;    for (; nexttoken == FORWARDT; )	{	savecmt = 0;	scanner(0);	fwdcurr->next = getfwd();	fwdcurr = fwdcurr->next;	tn2 = gettn();	fwdcurr->tree = tn2;	if (nexttoken == PROCEDURET)	    {	    proc = 1;	    tn2->type = PDECLNODE;	    }	else if (nexttoken == FUNCTIONT)	    {	    proc = 0;	    tn2->type = FDECLNODE;	    }	else myexit(2,"procedure or function");	st = getstentry();	scanner(0);			/* get proc name */	if (nexttoken != IDENT)	    myexit(2,"identifier");	if (proc)	    st->st_class = PROCC;	else	    st->st_class = FUNCC;	st->st_nparams = 0;	st->st_name = getname(scandata.si_idlen);	strcpy(st->st_name, scandata.si_name);	tn2->stdecl = st;	st->st_dstruct = NOSTRUCT;	st->st_tipe = INTTY;/*	if (parent->firstsym == NULL)	    parent->firstsym = st;	parent->lastsym = st;*/	/*	 * We want the "decl-begin" node (parent->prev->firstsym)	 * to point to the proc id in the symbol table, so that	 * a type definition will be produced for the proc id.	 */	if (parent->prev->firstsym == NULL)	    parent->prev->firstsym = tn2->stdecl;	parent->prev->lastsym = tn2->stdecl;	addsymbol(st);	blkentry(tn2);	lexlev++;	scanner(0);		/* get '(' or ';'  or ':' */	(void) paramseg(tn2->firstc, st, parent);	if (!proc)	    {	    if (nexttoken != COLON)		myexit(2,":");	    /*	     * Get the function type.	     * Also save the type info in the funct class stentry	     * for use in forward/external function type decls, and	     * for print formats from Pascal write stmts. 	     */	    scanner(0);	    st = getstentry();	    tn2->ftype = st;	    if (!datatype(st))		myexit(3,"data type not recognized");	    tn2->stdecl->st_dstruct = st->st_dstruct;	    tn2->stdecl->st_tipe = st->st_tipe;	    tn2->stdecl->st_uptr = st->st_uptr;	    scanner(0);		/* get ';' */	    }	savecmt = 1;	scanner(0);		/* get nexttoken AFTER ';' */	savecmt = 0;	(void) commentseg(tn2->firstc->next);	lexlev--;	}}

⌨️ 快捷键说明

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