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 + -
显示快捷键?