static char *sccsid
="@(#)scan.c 1.3 (Berkeley) %G%";
int asm_esc
= 0; /* asm escaped used in file */
# 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_NOT 12 /* ! */
# define A_AND 16 /* & */
# define A_WS 18 /* whitespace (not \n) */
# define A_NL 19 /* \n */
/* 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 */
int oldway
; /* allocate storage so lint will compile as well */
mainp1( argc
, argv
) int argc
; char *argv
[]; { /* control multiple files */
extern int idebug
, bdebug
, tdebug
, edebug
, ddebug
, xdebug
, gdebug
;
extern unsigned int offsz
;
char *release
= "PCC/364r1 vax uts3.0";
if( *(cp
=argv
[i
]) == '-' && *++cp
== 'X' ){
fprintf( stderr
, "Release: %s\n",
case 'P': /* profiling */
if( *(argv
[i
]) != '-' ) switch( fdef
++ ) {
if( freopen(argv
[i
], fdef
==1 ? "r" : "w", fdef
==1 ? stdin
: stdout
) == NULL
) {
fprintf(stderr
, "ccom:can't open %s\n", argv
[i
]);
for( i
=0; i
<SYMTSZ
; ++i
) stab
[i
].stype
= TNULL
;
/* dimension table initialization */
dimtab
[DOUBLE
] = SZDOUBLE
;
dimtab
[USHORT
] = SZSHORT
;
dimtab
[UNSIGNED
] = SZINT
;
/* starts past any of the above */
ejobcode( nerrors
? 1 : 0 );
lxenter( s
, m
) register char *s
; register short m
; {
/* enter a mask into lxmask */
while( c
= *s
++ ) lxmask
[c
+1] |= m
;
# define lxget(c,m) (lxgcp=yytext,lxmore(c,m))
lxmore( c
, m
) register c
, m
; {
while( c
=getchar(), lxmask
[c
+1]&m
){
if( cp
< &yytext
[LXTSZ
-1] ){
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 */
'@', 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 */
'"', A_STR
, 0, 0, /* character string */
'\'', A_CC
, 0, 0, /* character constant */
'`', A_BCD
, 0, 0, /* GCOS BCD constant */
'=', A_EQ
, ASSIGN
, ASSIGN
,
struct lxdope
*lxcp
[CSSZ
+1];
register struct lxdope
*p
;
/* 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
);
/* 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 */
/* handle letters, digits, and whitespace */
/* by convention, first, second, and third places */
cp
= "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$";
while( *cp
) lxcp
[*cp
++ + 1] = &lxdope
[1];
while( *cp
) lxcp
[*cp
++ + 1] = &lxdope
[2];
while( *cp
) lxcp
[*cp
++ + 1] = &lxdope
[3];
/* first line might have title */
int lxmatch
; /* character to be matched in char or string constant */
/* match a string or character constant, up to lxmatch */
while( (c
=getchar()) != lxmatch
){
uerror( "unexpected EOF" );
uerror( "newline in string or char constant" );
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');
val
= CHARCAST(val
); /* it is, after all, a "character" constant */
else { /* stash the byte into the string */
if( ct
==0 || i
<ct
) putbyte( val
);
else if( i
== ct
) werror( "non-null byte ignored in string initializer" );
/* end of string or char constant */
if( strflg
){ /* end the string */
if( ct
==0 || i
<ct
) putbyte( 0 ); /* the null at the end */
else { /* the initializer gets a null byte */
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" );
/* saw a /*: process a comment */
uerror( "unexpected EOF" );
if( (c
= getchar()) == '/' ) return;
lxget( c
, LEXLET
|LEXDIG
);
i
= yytext
[7]?yytext
[7]-'0':0;
if( strcmp( yytext
, "VARARGS" ) ) continue;
if( strcmp( yytext
, "LINTLIBRARY" ) ) continue;
if( strcmp( yytext
, "ARGSUSED" ) ) continue;
extern int argflag
, vflag
;
if( strcmp( yytext
, "NOTREACHED" ) ) continue;
register struct lxdope
*p
;
register struct symtab
*sp
;
switch( (p
=lxcp
[(lxchar
=getchar())+1])->lxact
){
/* eat up a single character, and return an opcode */
yylval
.intval
= p
->lxval
;
uerror( "illegal character: %03o (octal)", lxchar
);
/* collect an identifier, check for reserved word, and return */
lxget( lxchar
, LEXLET
|LEXDIG
);
if( (lxchar
=lxres()) > 0 ) return( lxchar
); /* reserved word */
if( lxchar
== 0 ) continue;
id
= lookup( hash(yytext
),
/* tag name for struct/union/enum */
/* member name for struct/union */
(stwart
&(INSTRUCT
|INUNION
|FUNNYNAME
))?SMOS
:0 );
if( sp
->sclass
== TYPEDEF
&& !stwart
){
yylval
.nodep
= mkty( sp
->stype
, sp
->dimoff
, sp
->sizoff
);
stwart
= (stwart
&SEENAME
) ? instruct
: 0;
/* collect a digit string, then look at last one... */
switch( lxchar
=getchar() ){
if( yytext
[0] != '0' && !yytext
[1] ) uerror( "illegal hex constant" );
lxmore( lxchar
, LEXHEX
);
for( cp
= yytext
+2; *cp
; ++cp
){
/* this code won't work for all wild character sets,
but seems ok for ascii and ebcdic */
if( isdigit( *cp
) ) lastcon
+= *cp
-'0';
else if( isupper( *cp
) ) lastcon
+= *cp
- 'A'+ 10;
else lastcon
+= *cp
- 'a'+ 10;
/* criterion for longness for hex and octal constants is that it
if( lastcon
& ~0177777L ) yylval
.intval
= 1;
lxmore( lxchar
, LEXDIG
);
if( (lxchar
=getchar()) == 'e' || lxchar
== 'E' ){ /* exponent */
if( (lxchar
=getchar()) == '+' || lxchar
== '-' ){
lxmore( lxchar
, LEXDIG
);
/* now have the whole thing... */
return( isitfloat( yytext
) );
for( cp
= yytext
+1; *cp
; ++cp
){
for( cp
= yytext
; *cp
; ++cp
){
lastcon
= lastcon
* 10 + *cp
- '0';
/* decide if it is long or not (decimal case) */
/* if it is positive and fits in 15 bits, or negative and
and fits in 15 bits plus an extended sign, it is int; otherwise long */
/* if there is an l or L following, all bets are off... */
if( v
== 0 || v
== ~077777L ) yylval
.intval
= 0;
/* finally, look for trailing L or l */
if( (lxchar
= getchar()) == 'L' || lxchar
== 'l' ) yylval
.intval
= 1;
else ungetc( lxchar
,stdin
);
/* look for a dot: if followed by a digit, floating point */
if( lxmask
[lxchar
+1] & LEXDIG
){
for( i
=0; i
<LXTSZ
; ++i
){
if( ( j
= getchar() ) == '`' ) break;
uerror( "newline in BCD constant" );
if( i
>6 ) uerror( "BCD constant exceeds 6 characters" );
else strtob( yytext
, &lastcon
, i
);
uerror( "gcos BCD constant illegal" );
yylval
.intval
= 0; /* not long */
if( (lxchar
=getchar()) != '*' ) goto onechar
;
if( (lxchar
=getchar()) != '=' ) goto onechar
;
if( (lxchar
=getchar()) == '-' ){
if( lxchar
!= '>' ) goto onechar
;
if( (lxchar
=getchar()) != '+' ) goto onechar
;
if( (lxchar
=getchar()) != '&' ) goto onechar
;
return( yylval
.intval
= ANDAND
);
if( (lxchar
=getchar()) != '|' ) goto onechar
;
return( yylval
.intval
= OROR
);
if( (lxchar
=getchar()) == '<' ){
if( lxchar
!= '=' ) goto onechar
;
if( (lxchar
=getchar()) == '>' ){
if( lxchar
!= '=' ) goto onechar
;
switch( lxchar
= getchar() ){
yylval
.intval
= ASG PLUS
;
yylval
.intval
= ASG MINUS
;
if( lxmask
[ (lxchar
=getchar())+1] & (LEXLET
|LEXDIG
|LEXDOT
) ){
werror( "ambiguous assignment: assignment op taken" );
if( (lxchar
=getchar()) != '<' ){
uerror( "=<%c illegal", lxchar
);
if( (lxchar
=getchar()) != '>' ){
uerror( "=>%c illegal", lxchar
);
cerror( "yylex error, character %03o (octal)", lxchar
);
/* ordinarily, repeat here... */
cerror( "out of switch in yylex" );
/* dope for reserved, in alphabetical order */
char *lxrch
; /* name of reserved word */
short lxract
; /* reserved word action */
short lxrval
; /* value to be returned */
"continue", AR_RW
, CONTINUE
,
"default", AR_RW
, DEFAULT
,
"fortran", AR_CL
, FORTRAN
,
"register", AR_CL
, REGISTER
,
"typedef", AR_CL
, TYPEDEF
,
"unsigned", AR_TY
, UNSIGNED
,
"void", AR_TY
, UNDEF
, /* tymerge adds FTN */
"", 0, 0, /* to stop the search */
/* check to see of yytext is reserved; if so,
/* do the appropriate action and return */
/* otherwise, return -1 */
register struct lxrdope
*p
;
if( !islower(ch
) ) return( -1 );
for( p
= lxrdope
+c
; p
->lxrch
[0] == ch
; ++p
){
if( !strcmp( yytext
, p
->lxrch
) ){ /* match */
yylval
.nodep
= mkty( (TWORD
)p
->lxrval
, 0, p
->lxrval
);
/* ordinary reserved word */
return( yylval
.intval
= p
->lxrval
);
yylval
.intval
= p
->lxrval
;
stwart
= INSTRUCT
|SEENAME
|TAGNAME
;
yylval
.intval
= INSTRUCT
;
stwart
= INUNION
|SEENAME
|TAGNAME
;
stwart
= SEENAME
|TAGNAME
;
return( yylval
.intval
= ENUM
);
asm_esc
= 1; /* warn the world! */
if( getchar() != '(' ) goto badasm
;
if( getchar() != '"' ) goto badasm
;
while( (c
=getchar()) != '"' ){
if( c
=='\n' || c
==EOF
) goto badasm
;
if( getchar() != ')' ) goto badasm
;
uerror( "bad asm construction" );
cerror( "bad AR_?? action" );
/* called after a newline; set linenumber and file name */
for(;;){ /* might be several such lines in a row */
if( (c
=getchar()) != '#' ){
if( c
!= EOF
) ungetc(c
,stdin
);
if ( lastloc
!= PROG
) return;
while ( *cp
) if (*cp
++ != *cq
++) return;
for( c
=getchar(); isdigit(c
); c
=getchar() ){
if( (c
=getchar()) != '\n' ){
for( cp
=ftitle
; c
!='\n'; c
=getchar(),++cp
){
for ( cp
= ititle
+1; *(cp
-1); cp
+= 8 ) {
if (gdebug
) printf("0,0,LL%d\n", labelno
);
if (gdebug
) printf("0,0,LL%d\n", labelno
);
printf("LL%d:\n", labelno
++);
savetab
= (char *)malloc(saveleft
);
cerror("Ran out of memory (savestr)");
strncpy(savetab
, cp
, len
);
* The definition for the segmented hash tables.
* The hash function is a modular hash of
* the sum of the characters with the sum
* doubled before each successive character
sh
= (i
&077777) % HASHINC
;
* There are as many as MAXHASH active
* hash tables at any given point in time.
* The search starts with the first table
* and continues through the active tables
for (htp
= htab
; htp
< &htab
[MAXHASH
]; htp
++) {
(char **) calloc(sizeof (char **), HASHINC
);
cerror("ran out of memory (hash)");
htp
->ht_high
= htp
->ht_low
+ HASHINC
;
* quadratic rehash increment
* starts at 1 and incremented
if (htp
->ht_used
> (HASHINC
* 3)/4)
if (**h
== *cp
&& strcmp(*h
, cp
) == 0)
cerror("ran out of hash tables");