sc.c

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

C
975
字号
#ifndef lintstatic	char	*sccsid = "@(#)sc.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: 	sc.c * * Pascal to C languge translator - scanner *//*	Modification History: sc.c * * 21-July-87 afd *	If line longer than 132 chars, exit. *	We used to try to skip over rest of line (after 132) but we were *	   accidently reading stdin not file pointer!  When reading from file *	   you don't get ';' at end of line and soon get a syntax error. * */#include <stdio.h>#include "ptoc.h"#ifdef SCDEBUGint scdebug = 1;#define printd if (prdebug) fprintf#define printd10 if (prdebug >= 10) fprintf#endifextern enum token    restoken[NRESERVES+1],		/* reserved words */    chartoken[127+1],			/* legal one char tokens */    nexttoken;				/* next Pascal token obtained as input */extern char tokenahead;			/* 'nexttoken' ahead flag */extern int linecounter;extern struct scaninfo scandata;extern int linesize;				/* # of chars in inputline */extern char ahead;				/* got 'nextchar' ahead flag */extern char endofinput;extern int charcounter;extern int savecmt;			/* True when comment saved */extern FILE *fp;			/* file to scan from */extern int doincl;			/* > 0 when processing include file */struct cmtinfo *getcmtinfo();char *getname();int curley;				/* true if '{' found *//* scanner data structures */int resindex[SYMBOLMAX+1];		/* index into resword for [n]					   char Pascal reserved words */symbol resword[NRESERVES+1];		/* Pascal reserved words */int resnext[NRESERVES+1];		/* link to next reserved word of [n] *//* local variables */char nextchar;				/* next char from inputline */line inputline;				/* next whole input line *//***************************************************************************//* * Get a new input line from the source file.  It is read into the * global variable "inputline". */getline(){    int i;    int c;		/* input char */    for (i=0; i < LINELENGTH-1 && (c = getc(fp)) != EOF && c != '\n'; i++)	inputline[i] = c;    inputline[i] = ' ';    linesize = i;    if (c == EOF)	endofinput = 1;    else	if (c != '\n')	    myexit(6,"");    linecounter++;}/* * Gets the next char from the current input line and puts it in the * global var nextchar. */getnext(){    if (endofinput)	nextchar = ' ';    else	{	if (charcounter >= linesize)	    {	    getline();	    if (endofinput)		nextchar = ' ';	    else		{		charcounter = 0;		nextchar = inputline[charcounter];		}	    }	else	    {	    charcounter++;	    nextchar = inputline[charcounter];	    }	}}/* * Build up the next token.  It calls getnext when it needs another char. */scanner(noreal)    char noreal;	/* Real numbers not allowed when getting array or			 * subrange declaration.  This is to avoid			 * confussion with "[1." and the start of a real number			 */{    char found;    if (tokenahead)	{	tokenahead = 0;	return;	}    curley = 0;    do	{	if (ahead)	    ahead = 0;	else	    getnext();	found = 1;	if (endofinput)	    nexttoken = ILLEGALTOKE;	else	    switch (nextchar) {	    case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':	    case 'g': case 'h': case 'i': case 'j': case 'k': case 'l':	    case 'm': case 'n': case 'o': case 'p': case 'q': case 'r':	    case 's': case 't': case 'u': case 'v': case 'w': case 'x':	    case 'y': case 'z':	    case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':	    case 'G': case 'H': case 'I': case 'J': case 'K': case 'L':	    case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':	    case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':	    case 'Y': case 'Z':	    case '$':				/* for VMS/Pascal */		word();#		ifdef SCDEBUG		printd(stderr,"scanner: got word %s\n", scandata.si_name);#		endif		break;	    case '0': case '1': case '2': case '3': case '4': case '5':	    case '6': case '7': case '8': case '9':		number(noreal);#		ifdef SCDEBUG		printd(stderr,"scanner: got word %s\n", scandata.st_cval);#		endif		break;/* FIX - make this more efficient, by looping here to skip over blanks &tabs */	    case ' ':	    case '\t':		found = 0;		getnext();		ahead = 1;		break;	    case '{':		curley = 1;		getcomment();    		break;	    case '(':		getnext();		if (nextchar == '*')		    getcomment();    		else		    {		    nexttoken = LEFTPAREN;		    ahead = 1;		    }		break;	    case '\'':		charconst();		break;	    case '"':		strconst();		break;	    case '.':		dot();		break;	    case ':':		colon();		break;	    case '<': case '>':  case '=':		relation();		break;	    default:		nexttoken = chartoken[nextchar];#		ifdef SCDEBUG		printd(stderr,"scanner: got char token %c\n", nextchar);#		endif	    }   /* switch */	}    while (!found);}		/* * Comment scan. * If "savecmt" is set then store the comment in a *   linked list of structures.  Each structure contains one line of *   the comment. * Else, scan & ignore the comment. */getcomment(){    char gotast = 0;		/* set true when '*' scanned */    int i;			/* loop index */    int linenumber;		/* last linenumber */    char first = 1;    struct cmtinfo *headptr = NULL;    struct cmtinfo *ptr;    /*     * Don't want to save any comments if processing an include file     */    if (doincl)	savecmt = 0;    ptr = getcmtinfo();    headptr = ptr;    linenumber = linecounter;    for (i=0;; i++)	{	getnext();	if (savecmt && linenumber != linecounter)	    {	    ptr->cmt = getname(i);	    strncpy(ptr->cmt, scandata.si_name,i);	    strcat(ptr->cmt, "\0");	    linenumber = linecounter;	    i = 0;	    ptr->next = getcmtinfo();	    ptr = ptr->next;	    }	if (curley == 1)	    {	    if (nextchar == '}')		break;	    }	else	    if (gotast == 1 && nextchar == ')')		break;	if (savecmt)	    scandata.si_name[i] = nextchar;	gotast = 0;	if (nextchar == '*')	    gotast = 1;	}    if (savecmt)	{	ptr->cmt = getname(i);	if (curley == 0)	    i--;	strncpy(ptr->cmt, scandata.si_name,i);	strcat(ptr->cmt, "\0");	nexttoken = COMMENT;	scandata.si_cmtptr = headptr;	}    else	scanner(0);		/* get next token after comment */}		/* * Called if the first char of token was a letter.  It scans until the *   nextchar is not a letter, digit, or underscore (or $). * The '$' is accepted for VMS/Pascal compatibility but it is  *   simply discarded. */word(){    int index;    char foundit;    int j;    if (nextchar >= 'A' && nextchar <= 'Z')	nextchar = nextchar + 'a' - 'A';    scandata.si_name[0] = nextchar;    j = 1;    getnext();    for (; (nextchar >= 'A' && nextchar <= 'Z') ||	   (nextchar >= 'a' && nextchar <= 'z') ||	   (nextchar >= '0' && nextchar <= '9') ||	   (nextchar == '_')||(nextchar == '$') ;)	{	if (j < WORDLENGTH-1)	    if (nextchar != '$')		{		if (nextchar >= 'A' && nextchar <= 'Z')		    nextchar = nextchar + 'a' - 'A';		scandata.si_name[j++] = nextchar;		}	getnext();	}    scandata.si_name[j] = '\0';    ahead = 1;    scandata.si_idlen = j;    /* look for word in reserved word table */    foundit = 0;    if (scandata.si_idlen > SYMBOLMAX)	index = 0;    else	index = resindex[scandata.si_idlen];    for (; !foundit && index != 0;)	{	if (!strcmp(resword[index], scandata.si_name))	    {	    nexttoken = restoken[index];	    foundit = 1;	    }	else	    index = resnext[index];	}    if (!foundit)	nexttoken = IDENT;}/* * Called if first char of token was a digit. Scans until a non digit * is found. * Save the numeric string in 'name' field for expression parsing. */number(noreal)    char noreal;	/* Real numbers not allowed when getting array or			 * subrange declaration.  This is to avoid			 * confussion with "[1." and the start of a real number			 */{    int nextdigit;    float realvalue;    int j = 0;    float mult;    int power;		/* for Pascal exponent notation */    int expon;		/* for Pascal exponent notation */    int i;    char neg;		/* for negative number */    scandata.si_cvalue = 0;    scandata.si_dflag = 1;    nexttoken = NUMCONST;    do	{	nextdigit = nextchar - '0';	scandata.si_cvalue = scandata.si_cvalue * 10 + nextdigit;	scandata.si_name[j++] = nextchar;	getnext();	}    while (nextchar >= '0' && nextchar <= '9');    if (nextchar == '.' && (!noreal))	{	scandata.si_name[j++] = nextchar;	getnext();	scandata.si_dflag = 2;	mult = 10;	while (nextchar >= '0' && nextchar <= '9')	    {	    realvalue = (nextchar - '0') * (1/mult);	    scandata.si_cvalue += realvalue;	    scandata.si_name[j++] = nextchar;	    mult = mult * 10;	    getnext();	    }	}    neg = 0;    if (nextchar == 'E')	{	getnext();	if (nextchar == '-')	    {	    neg = 1;	    getnext();	    scandata.si_name[j++] = '/';	    }	else	    {	    scandata.si_name[j++] = '*';	    if (nextchar == '+')		getnext();	    }	scandata.si_name[j++] = '(';	scandata.si_name[j++] = '1';	expon = 0;	while (nextchar >= '0' && nextchar <= '9')	    {	    nextdigit = nextchar - '0';	    expon = expon * 10 + nextdigit;	    getnext();	    }	power = 1;	for (i = 0; i < expon; i++)	    {	    scandata.si_name[j++] = '0';	    power = power * 10;	    }	if (neg)	    scandata.si_cvalue = scandata.si_cvalue / power;	else	    scandata.si_cvalue = scandata.si_cvalue * power;	scandata.si_name[j++] = ')';	}    scandata.si_name[j] = '\0';    ahead = 1;}/* * Called if first char of token was a single quot. * Token is constant. */charconst(){    int i;    nexttoken = CHARCONST;    scandata.si_dflag = 0;    getnext();    for (i = 0; nextchar != '\''; i++)	{	scandata.si_name[i] = nextchar;	getnext();	}    scandata.si_name[i] = '\0';    scandata.si_idlen = i;}/* * Called if first char of token was a quot ("). * Token is QUOTE.  Only needed for include syntax. */strconst(){    int i;

⌨️ 快捷键说明

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