prsubr.c

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

C
927
字号
#ifndef lintstatic char *sccsid = "@(#)prsubr.c	4.1	ULTRIX	7/17/90";#endif lint/************************************************************************ *									* *			Copyright (c) 1986 by				* *		Digital Equipment Corporation, Maynard, MA		* *			All rights reserved.				* *									* *   This software is furnished under a license and may be used and	* *   copied  only  in accordance with the terms of such license and	* *   with the  inclusion  of  the  above  copyright  notice.   This	* *   software  or  any  other copies thereof may not be provided or	* *   otherwise made available to any other person.  No title to and	* *   ownership of the software is hereby transferred.			* *									* *   The information in this software is subject to change  without	* *   notice  and should not be construed as a commitment by Digital	* *   Equipment Corporation.						* *									* *   Digital assumes no responsibility for the use  or  reliability	* *   of its software on equipment which is not supplied by Digital.	* *									* ************************************************************************//* * File: 	prsubr.c * * Pascal to C translator - Parser for: *			  - subroutines (procedures/functions) *			  - parameters  *			  - main program *			  - includes *			  - label declarations *			  - comments */#include <stdio.h>#include "ptoc.h"#ifdef PRDEBUGint prdebug = 1;#define printd if (prdebug) fprintf#define printd10 if (prdebug >= 10) fprintf#endifextern enum token nexttoken;	/* next Pascal token obtained as input */extern struct scaninfo scandata;extern int linecounter;extern char tokenahead;extern int linesize;				/* # of chars in inputline */extern char ahead;				/* got 'nextchar' ahead flag */extern char endofinput;extern int charcounter;extern FILE *fp;			/* file to scan from */extern currfile[LINELENGTH];extern char nextchar;extern line inputline;extern int doincl;			/* > 1 when processing include file */extern struct treenode *procindex[MAXLEV];extern struct stentry *stindex[MAXLEV];	/* sym table pts by lexic level */extern int lexlev;				/* current lexical level */extern struct fwdstmt *fwdhead;		/* head of list of fwd decls */extern struct fwdstmt *fwdcurr;extern int savecmt;			/* True when comment saved */char gotprog;				/* True if program token scanned */enum token holdtoken;struct treenode *prevsub;		/* ptr to prev subroutine */char *malloc();struct stentry *getstentry();char *getname();struct pairs *getpairs();struct stentry *findany();struct treenode *gettn();struct fwdstmt *getfwd();/* * prog: Get a program stmt.  Symbol table head and tail are set up here. */prog(){    gotprog = 0;    lexlev = 0;    stindex[0] = getstentry();	/* dummy header, not filled in */    /*     * The builtin symbols get defined before the program node, thus     * they are not printed during code emiting.     */    builtins();    scanner(0);    if (nexttoken == PROGRAMT || nexttoken == MODULET)	{#       ifdef PRDEBUG	printd(stderr,"prog: got program token\n");#       endif	if (nexttoken == PROGRAMT)	    gotprog = 1;	/*	 * Scan program name, optional (input,output), up thru ";"	 */	for (; nexttoken != SEMICOLON ;)	    scanner(0);	savecmt = 1;	scanner(0);	}    progseg(0);              /* get program segment */    return(1);}/* * progseg:  Get a program segment (body). */progseg(incl)    char incl;			/* == 1 if processing an include file */{    struct treenode *tn;    struct stentry *st;    if (incl == 1)	tn = procindex[0];    else	{	tn = gettn();	tn->type = PROGNODE;	procindex[0] = tn;	blkentry(tn);	tn->firstc = tn->firstc->next;		/* no begin block for params */	tn->firstc->next->next = NULL;		/* no begin block for stmts */	lexlev = 1;	/*	 * Setup include of <stdio.h> and maxint symbol	 */	st = getstentry();	st->st_name = getname(9);	strcpy(st->st_name, "<stdio.h>");	st->st_class = INCLUDEC;	addsymbol(st);	if (tn->firstc->firstsym == NULL)	   tn->firstc->firstsym = st;	tn->firstc->lastsym = st;	st = getstentry();	st->st_class = CONSTC;	st->st_name = getname(6);	strcpy(st->st_name, "maxint");	st->st_cval = MAXINT;	st->st_tipe = INTTY;	addsymbol(st);	if (tn->firstc->firstsym == NULL)	   tn->firstc->firstsym = st;	tn->firstc->lastsym = st;	}    /*     * Pass ptr to decl_begin block     */	(void) commentseg(tn->firstc);    (void) includeseg(tn->firstc);    (void) labelseg();	(void) commentseg(tn->firstc);    (void) includeseg(tn->firstc);    (void) constseg(tn->firstc);	(void) commentseg(tn->firstc);    (void) includeseg(tn->firstc);    (void) typeseg(tn->firstc);	(void) commentseg(tn->firstc);    (void) includeseg(tn->firstc);    /*     * Add var "readln_dummy" to use for scanning thru "newline".     * Needed for Pascal "readln".     */	st = getstentry();	inittvf(st);	st->st_name = getname(12);	strcpy(st->st_name, "readln_dummy");	st->st_lexlev = lexlev;	st->st_dstruct = ARRS;	st->st_tipe = CHARTY;	st->st_class = VARC;	st->st_numdims = 1;	st->st_bounds = getpairs();	st->st_bounds->pr_upper = 10;	addsymbol(st);	if (tn->firstc->firstsym == NULL)	    tn->firstc->firstsym = st;	tn->firstc->lastsym = st;    (void) varseg(tn->firstc,tn);	(void) commentseg(tn->firstc);    (void) includeseg(tn->firstc);    (void) fwdseg(tn->firstc->next);	(void) commentseg(tn->firstc);    (void) includeseg(tn->firstc);    /*     * Pass ptr to proc_begin block     */    prevsub = NULL;    (void) subseg(tn->firstc->next, 0);    if (incl == 0 && gotprog == 1)	(void) mainstmts(tn->firstc->next);		/* create "main" proc */}/* * includeseg:  Get an include segment. */includeseg(tn)    struct treenode *tn;		/* ptr to decl begin block */{    struct stentry *st;			/* current var symbol */    FILE *sfile;    int slinesize;    int slinecounter;    int scharcounter;    char sahead;    char stokenahead;    char snextchar;    enum token snexttoken;    line sinputline;    char scurrfile[LINELENGTH];    char unixform;			/* true if unix format include */    /*     * Accept Berkeley Pascal include syntax:  #include "file"     *         and VMS Pascal include syntax:  %include 'file'     */    while (nexttoken == POUND || nexttoken == PERCENT)	{	if (nexttoken == POUND)	    unixform = 1;	else	    unixform = 0;	scanner(0);	if (nexttoken != INCLUDET)	    myexit(2,"include");	if (unixform)	    {	    scanner(0);	    if (nexttoken != QUOTE)		myexit(2,"string");	    }	else	    {	    scanner(0);	    if (nexttoken != CHARCONST)		myexit(2,"string");	    }	st = getstentry();	st->st_name = getname(strlen(scandata.si_name));	strcpy(st->st_name, scandata.si_name);	st->st_class = INCLUDEC;	addsymbol(st);	if (tn->firstsym == NULL)	   tn->firstsym = st;	tn->lastsym = st;	savecmt = 1;	scanner(0);	savecmt = 0;	if (nexttoken == COMMENT)	    {	    st->st_cmt = scandata.si_cmtptr;	    /* comment loop here ? to get multiple comments in a row */	    savecmt = 1;	    scanner(0);	    savecmt = 0;	    commentseg(tn);	    }	/*	 * Process include file	 *	 * Save scanner variables, to preserve state in present file.	 */	slinesize = linesize;	slinecounter = linecounter;	scharcounter = charcounter;	sahead = ahead;	stokenahead = tokenahead;	snextchar = nextchar;	snexttoken = nexttoken;	strcpy(sinputline, inputline);	strcpy(scurrfile, currfile);	sfile = fp;	/*	 * See if include file can be opened.	 */	fp = fopen(st->st_name, "r");	if (fp == NULL)	    myexit(5,st->st_name);	/*	 * Re-initilize scanner variables for new file	 */	ahead = 0;	tokenahead = 0;	endofinput = 0;	linecounter = 0;	linesize = 0;	charcounter = LINELENGTH;	strcpy(currfile, st->st_name);	doincl++;	scanner(0);	progseg(1);	doincl--;	fclose(fp);	/*	 * Restore scanner variables, to previous state.	 */	linesize = slinesize;	linecounter = slinecounter;	charcounter = scharcounter;	ahead = sahead;	tokenahead = stokenahead;	endofinput = 0;	nextchar = snextchar;	nexttoken = snexttoken;	strcpy(inputline, sinputline);	strcpy(currfile, scurrfile);	fp = sfile;	}}/* * paramseg:  Get a param segment. */paramseg(tn, funcst, parent)    struct treenode *tn;		/* ptr to param begin block */    struct stentry *funcst;		/* st entry for proc/func */    struct treenode *parent;		/* for getting func/proc as param.					   parent level for func definition */{    struct stentry *st;			/* current var symbol */    struct stentry *secthead;		/* head of a section of var decls:					   eg: v1,v2,v3: data-type */    struct stentry *sect;		/* ptr to current stentry */    struct stentry *dupst;		/* to fill out dupvar st_entryies */    char buf[LINELENGTH];		/* to hold init value */    int num = 0;			/* nparam counter */    char var;    char funcpar;			/* == 1 if getting func param */    					/* == 2 if getting proc param */    if (nexttoken == LEFTPAREN)	{#	ifdef PRDEBUG	printd(stderr,"paramseg: got LEFTPAREN token\n");#	endif	savecmt = 0;	scanner(0);			/* get VAR or id */	do	    {	    var = 0;	    funcpar = 0;	    if (nexttoken == VART)		{		var = 1;		scanner(0);		}	    secthead = NULL;	    do		{		/*		 * Check for VMS/Pascal "mechanism-specifier"		 */		if (nexttoken == PERCENT)		    {		    scanner(0);		    if (nexttoken == MECHT)			scanner(0);		    else			myexit(2, "mechanism-specifier");		    }		st = getstentry();		inittvf(st);		/*		 * String together constructs like v1, v2, v3: type;		 */		if (secthead == NULL)		    {		    secthead = st;		    sect = st;		    }		else		    {		    sect->st_dupvar = st;		    sect = st;		    }		/*		 * If func/proc as a parameter call subseg to get		 *   the function decl set up:  Pass funcpar to indicate		 *   that we're getting a func/proc parameter.		 * When we return "prevsub" points to the dummy function		 *   decl that we set up.  So we can fill in the type.		 */		if (nexttoken == FUNCTIONT)		    funcpar = 1;		if (nexttoken == PROCEDURET)		    funcpar = 2;		if (funcpar)		    {		    lexlev--;		    subseg(parent,funcpar);		    strcpy(scandata.si_name, prevsub->stdecl->st_name);		    scandata.si_idlen = strlen(prevsub->stdecl->st_name);		    lexlev++;		    }		st->st_name = getname(scandata.si_idlen);		strcpy(st->st_name, scandata.si_name);		st->st_class = VARC;		if (var)		    st->st_byref = 1;		addsymbol(st);		num++;		if (tn->firstsym == NULL)		    tn->firstsym = st;		tn->lastsym =st;		if (funcst->st_fparam == NULL)		    funcst->st_fparam = st;		funcst->st_lparam = st;		/*		 * Only get next token if not a proc/func parameter		 * If it is a procedure parameter skip getting the type		 *    (nexttoken == ";" or ")"		 */		if (funcpar == 0)		    scanner(0);		/* get next token: , or : */		else if (funcpar == 2)			 goto nextparam;	/* forgive me! */		if (nexttoken == COMMA)		    scanner(0);		}	    while (nexttoken != COLON);	    scanner(0);		/* get type */	    /*	     * Check for VMS format of:  "id: [attributes] type;"	     */	    if (nexttoken == LEFTBRACKET)		{		while (nexttoken != RIGHTBRACKET)		    scanner(0);		scanner(0);		}	    /*	     * Fill in data type for head variable in this `section':	     *    eg. v1, v2, v3: 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 gets used in a	     * "with" stmt.	     *	     * Also save other "type" fields for help in processing "with"

⌨️ 快捷键说明

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