📄 scan.c
字号:
#ifndef lintstatic char *sccsid = "@(#)scan.c 4.3 (ULTRIX) 11/12/90";#endif lint/************************************************************************ * * * Copyright (c) 1985 - 1989 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. * * * * This software is derived from software received from the * * University of California, Berkeley, and from Bell * * Laboratories. Use, duplication, or disclosure is subject to * * restrictions under license agreements with University of * * California and with AT&T. * * * * 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. * * * ************************************************************************//************************************************************************ * * Modification History * * Jon Reeves, 10-May-89 * 006 Signals now return void. * * Lu Anne Van de Pas, 1-Apr-86 * 005 Set up signal handler to catch floating point expection trap (from * bsd4.3) * * Lu Anne Van de Pas, 02-Mar-86 * 004 Added support for single precision floating point constants * (e.g. 3.45f, 3e1f, 1.0e-3f ) added flag for adebug (actions) * * Victoria Holt, 26-Feb-86 * 003 Added support for const and volatile. * * David L Ballenger, 12-Sep-1985 * 002 Add code to handle '-' as both input and output file specs so that * ccom can be pipelined. * * Rich Phillips, 16-Aug-84 * 001 Put asm handling code in an action routine to be called by * the parser. This change causes asm's to be treated the same * as a function call to a function that does not return a value. * It also allows asm's to be used at the function declaration level. * * Changes have also been applied to allo.c,cgram.y,manifest,match.c * and table.c to change the asm handling. * * Based on: scan.c 1.3 (Berkeley) 12/24/82 * *****************************************************************/# include "mfile1"# include <a.out.h># include <stab.h># include <ctype.h># include <signal.h> /* temporarily */int asm_esc = 0; /* asm escaped used in file */ /* lexical actions */# define A_ERR 0 /* illegal character */# define A_LET 1 /* saw a letter */# define A_DIG 2 /* saw a digit */# define A_1C 3 /* return a single character */# define A_STR 4 /* string */# define A_CC 5 /* character constant */# define A_BCD 6 /* GCOS BCD constant */# define A_SL 7 /* saw a / */# define A_DOT 8 /* saw a . */# define A_PL 9 /* + */# define A_MI 10 /* - */# define A_EQ 11 /* = */# define A_NOT 12 /* ! */# define A_LT 13 /* < */# define A_GT 14 /* > */# define A_AND 16 /* & */# define A_OR 17 /* | */# define A_WS 18 /* whitespace (not \n) */# define A_NL 19 /* \n */ /* character classes */# define LEXLET 01# define LEXDIG 02# define LEXOCT 04# define LEXHEX 010# define LEXWS 020# define LEXDOT 040 /* reserved word actions */# define AR_TY 0 /* type word */# define AR_RW 1 /* simple reserved word */# define AR_CL 2 /* storage class word */# define AR_S 3 /* struct */# define AR_U 4 /* union */# define AR_E 5 /* enum */# define AR_A 6 /* asm */# define AR_TA 7 /* type attributes - const, volatile */ /* text buffer */#ifndef FLEXNAMES# define LXTSZ 100#else#define LXTSZ BUFSIZ#endifchar yytext[LXTSZ];char * lxgcp;int fflag=0; /*vdp004 do single precision arithmetic in 'f' */ char * asmptr; /*RAP001 pointer to asm contents between "'s*/extern int proflg;int adebug=0; /*vdp004 print actions from trees.c */ extern int idebug, bdebug, tdebug, edebug, ddebug, xdebug, gdebug;int bswitch; /* jpm: cld 153 */extern unsigned int offsz;int oldway; /* allocate storage so lint will compile as well */extern void fpe(); /*vdp05 routine to handle floating point exception*/struct sigvec fpe_sigvec; /*vdp05*/#ifndef LINTextern int lastloc;#endifunsigned caloff();/* ARGSUSED */mainp1( argc, argv ) int argc; char *argv[];{ /* control multiple files */ register i; register char *cp; int fdef = 0; char *release = "ULTRIX PCC version2.0"; offsz = caloff(); for( i=1; i<argc; ++i ) { cp = argv[i]; if (*cp == '-') { cp++; if (*cp == 'X') while(*++cp) { switch( *cp ){ case 'r': fprintf( stderr, "Release: %s\n", release ); break; case 'd': ++ddebug; break; case 'A': /* actions --trees.c */ ++adebug; break; case 'i': ++idebug; break; case 'b': ++bdebug; break; case 'S': /* jpm: cld 153 added bswitch */ ++bswitch; break; case 't': ++tdebug; break; case 'e': ++edebug; break; case 'x': ++xdebug; break; case 'P': /* profiling */ ++proflg; break; case 'g': ++gdebug; break; case 'G': ++gdebug; oldway = 1; break; } } else if (*cp == '\000') fdef++ ; } else switch( fdef++ ) { case 0: case 1: if(freopen(argv[i], fdef==1 ? "r" : "w", fdef==1 ? stdin : stdout) == NULL) { fprintf(stderr, "ccom:can't open %s\n", argv[i]); exit(1); } break; default:break; }}# ifdef ONEPASS p2init( argc, argv );# endif for( i=0; i<SYMTSZ; ++i ) stab[i].stype = TNULL; lxinit(); tinit(); mkdope(); lineno = 1; /* dimension table initialization */ dimtab[NULL] = 0; dimtab[CHAR] = SZCHAR; dimtab[INT] = SZINT; dimtab[FLOAT] = SZFLOAT; dimtab[DOUBLE] = SZDOUBLE; dimtab[LONG] = SZLONG; dimtab[SHORT] = SZSHORT; dimtab[UCHAR] = SZCHAR; dimtab[USHORT] = SZSHORT; dimtab[UNSIGNED] = SZINT; dimtab[ULONG] = SZLONG; /* starts past any of the above */ curdim = 16; reached = 1; /* vdp05 assign routine fpe() to handle * floating point exception */ fpe_sigvec.sv_handler = fpe; (void) sigvec(SIGFPE, &fpe_sigvec, (struct sigvec *) NULL); yyparse(); yyaccpt(); ejobcode( nerrors ? 1 : 0 ); return(nerrors?1:0); }# ifdef ibm# define CSMASK 0377# define CSSZ 256# else# define CSMASK 0177# define CSSZ 128# endifshort lxmask[CSSZ+1];lxenter( s, m ) register char *s; register short m; { /* enter a mask into lxmask */ register c; while( c= *s++ ) lxmask[c+1] |= m; }# define lxget(c,m) (lxgcp=yytext,lxmore(c,m))lxmore( c, m ) register c, m; { register char *cp; *(cp = lxgcp) = c; while( c=getchar(), lxmask[c+1]&m ){ if( cp < &yytext[LXTSZ-1] ){ *++cp = c; } } ungetc(c,stdin); *(lxgcp = cp+1) = '\0'; }struct lxdope { short lxch; /* the character */ short lxact; /* the action to be performed */ short lxtok; /* the token number to be returned */ short lxval; /* the value to be returned */ } lxdope[] = { '@', A_ERR, 0, 0, /* illegal characters go here... */ '_', A_LET, 0, 0, /* letters point here */ '0', A_DIG, 0, 0, /* digits point here */ ' ', A_WS, 0, 0, /* whitespace goes here */ '\n', A_NL, 0, 0, '"', A_STR, 0, 0, /* character string */ '\'', A_CC, 0, 0, /* character constant */ '`', A_BCD, 0, 0, /* GCOS BCD constant */ '(', A_1C, LP, 0, ')', A_1C, RP, 0, '{', A_1C, LC, 0, '}', A_1C, RC, 0, '[', A_1C, LB, 0, ']', A_1C, RB, 0, '*', A_1C, MUL, MUL, '?', A_1C, QUEST, 0, ':', A_1C, COLON, 0, '+', A_PL, PLUS, PLUS, '-', A_MI, MINUS, MINUS, '/', A_SL, DIVOP, DIV, '%', A_1C, DIVOP, MOD, '&', A_AND, AND, AND, '|', A_OR, OR, OR, '^', A_1C, ER, ER, '!', A_NOT, UNOP, NOT, '~', A_1C, UNOP, COMPL, ',', A_1C, CM, CM, ';', A_1C, SM, 0, '.', A_DOT, STROP, DOT, '<', A_LT, RELOP, LT, '>', A_GT, RELOP, GT, '=', A_EQ, ASSIGN, ASSIGN, -1, A_1C, 0, 0, };struct lxdope *lxcp[CSSZ+1];lxinit(){ register struct lxdope *p; register i; register char *cp; /* set up character classes */ lxenter( "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_$", LEXLET ); lxenter( "0123456789", LEXDIG ); lxenter( "0123456789abcdefABCDEF", LEXHEX ); /* \013 should become \v someday; \013 is OK for ASCII and EBCDIC */ lxenter( " \t\r\b\f\013", LEXWS ); lxenter( "01234567", LEXOCT ); lxmask['.'+1] |= LEXDOT; /* make lxcp point to appropriate lxdope entry for each character */ /* initialize error entries */ for( i= 0; i<=CSSZ; ++i ) lxcp[i] = lxdope; /* make unique entries */ for( p=lxdope; ; ++p ) { lxcp[p->lxch+1] = p; if( p->lxch < 0 ) break; } /* handle letters, digits, and whitespace */ /* by convention, first, second, and third places */ cp = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$"; while( *cp ) lxcp[*cp++ + 1] = &lxdope[1]; cp = "123456789"; while( *cp ) lxcp[*cp++ + 1] = &lxdope[2]; cp = "\t\b\r\f\013"; while( *cp ) lxcp[*cp++ + 1] = &lxdope[3]; /* first line might have title */ lxtitle(); }int lxmatch; /* character to be matched in char or string constant */lxstr(ct){ /* match a string or character constant, up to lxmatch */ register c; register val; register i; i=0; while( (c=getchar()) != lxmatch ){ switch( c ) { case EOF: uerror( "unexpected EOF" ); break; case '\n': uerror( "newline in string or char constant" ); ++lineno; break; case '\\': switch( c = getchar() ){ case '\n': ++lineno; continue; default: val = c; goto mkcc; case 'n': val = '\n'; goto mkcc; case 'r': val = '\r'; goto mkcc; case 'b': val = '\b'; goto mkcc; case 't': val = '\t'; goto mkcc; case 'f': val = '\f'; goto mkcc; case 'v': val = '\013'; goto mkcc; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': val = c-'0'; c=getchar(); /* try for 2 */ if( lxmask[c+1] & LEXOCT ){ val = (val<<3) | (c-'0'); c = getchar(); /* try for 3 */ if( lxmask[c+1] & LEXOCT ){ val = (val<<3) | (c-'0'); } else ungetc( c ,stdin); } else ungetc( c ,stdin); goto mkcc1; } default: val =c; mkcc: val = CCTRANS(val); mkcc1: if( lxmatch == '\'' ){ val = CHARCAST(val); /* it is, after all, a "character" constant */ makecc( val, i ); } else { /* stash the byte into the string */ if( strflg ) { if( ct==0 || i<ct ) putbyte( val ); else if( i == ct ) werror( "non-null byte ignored in string initializer" ); } else bycode( val, i ); } ++i; continue; } break; } /* end of string or char constant */ if( lxmatch == '"' ){ if( strflg ){ /* end the string */ if( ct==0 || i<ct ) putbyte( 0 ); /* the null at the end */ } else { /* the initializer gets a null byte */ bycode( 0, i++ ); bycode( -1, i ); dimtab[curdim] = i; /* in case of later sizeof ... */ } } else { /* end the character constant */ if( i == 0 ) uerror( "empty character constant" ); if( i>(SZINT/SZCHAR) || ( (pflag||hflag)&&i>1) ) uerror( "too many characters in character constant" ); } }lxcom(){ register c; /* saw a /*: process a comment */ for(;;){ switch( c = getchar() ){ case EOF: uerror( "unexpected EOF" ); return; case '\n': ++lineno; default: continue; case '*': if( (c = getchar()) == '/' ) return; else ungetc( c ,stdin); continue;# ifdef LINT case 'V': lxget( c, LEXLET|LEXDIG ); { extern int vaflag; int i; i = yytext[7]?yytext[7]-'0':0; yytext[7] = '\0'; if( strcmp( yytext, "VARARGS" ) ) continue; vaflag = i; continue; } case 'L': lxget( c, LEXLET ); if( strcmp( yytext, "LINTLIBRARY" ) ) continue; { extern int libflag; libflag = 1; } continue; case 'A': lxget( c, LEXLET ); if( strcmp( yytext, "ARGSUSED" ) ) continue; { extern int argflag, vflag; argflag = 1; vflag = 0; } continue; case 'N': lxget( c, LEXLET ); if( strcmp( yytext, "NOTREACHED" ) ) continue; reached = 0; continue;# endif } } }yylex(){ for(;;){ register lxchar; register struct lxdope *p; register struct symtab *sp; int id; switch( (p=lxcp[(lxchar=getchar())+1])->lxact ){ onechar: ungetc( lxchar ,stdin); case A_1C: /* eat up a single character, and return an opcode */ yylval.intval = p->lxval; return( p->lxtok ); case A_ERR: uerror( "illegal character: %03o (octal)", lxchar ); break; case A_LET: /* collect an identifier, check for reserved word, and return */ lxget( lxchar, LEXLET|LEXDIG ); /*RAP001 Set up asm to look like a name so a UNARY CALL to asm can be set up by the parser. */ if( (lxchar=lxres()) > 0 && lxchar != ASM) return( lxchar ); /* reserved word */ if( lxchar== 0 ) continue;#ifdef FLEXNAMES id = lookup( hash(yytext),#else id = lookup( yytext,#endif /* tag name for struct/union/enum */ (stwart&TAGNAME)? STAG: /* member name for struct/union */ (stwart&(INSTRUCT|INUNION|FUNNYNAME))?SMOS:0 ); sp = &stab[id]; if( sp->sclass == TYPEDEF && !stwart ){ stwart = instruct; yylval.nodep = mkty( sp->stype, sp->dimoff, sp->sizoff ); yylval.nodep->in.typattr = sp->stypattr; return( TYPE ); } stwart = (stwart&SEENAME) ? instruct : 0; yylval.intval = id; if (lxchar == ASM) /* RAP001 */ return ( ASM ); else return( NAME ); case A_DIG: /* collect a digit string, then look at last one... */ lastcon = 0; lxget( lxchar, LEXDIG ); switch( lxchar=getchar() ){ case 'x': case 'X': if( yytext[0] != '0' && !yytext[1] ) uerror( "illegal hex constant" ); lxmore( lxchar, LEXHEX ); /* convert the value */ { register char *cp; for( cp = yytext+2; *cp; ++cp ){ /* this code won't work for all wild character sets, but seems ok for ascii and ebcdic */ lastcon <<= 4; if( isdigit( *cp ) ) lastcon += *cp-'0'; else if( isupper( *cp ) ) lastcon += *cp - 'A'+ 10; else lastcon += *cp - 'a'+ 10; } } hexlong: /* criterion for longness for hex and octal constants is that it fit within 0177777 */ if( lastcon & ~0177777L ) yylval.intval = 1; else yylval.intval = 0; goto islong; case '.': lxmore( lxchar, LEXDIG ); getfp: if((lxchar=getchar()) == 'f' || lxchar == 'F') { /*vdp004 - floating point constant */ goto flt; } if (lxchar == 'e' || lxchar == 'E' ){ /* exponent */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -