* c0 source temp1 temp2 [ profileflag ]
* temp1 contains some ascii text and the binary expression
* trees. Each tree is introduced by the # character.
* Strings are put on temp2, which cc tacks onto
struct tname funcblk
{ NAME
, 0, 0, REG
, 0, 0 };
int *treespace
{ osspace
};
register struct kwtab
*ip
;
if((fin
=open(argv
[1],0))<0) {
error("Can't find %s", argv
[1]);
if (fcreat(argv
[2], obuf
)<0 || fcreat(argv
[3], sbuf
)<0) {
error("Can't create temp");
* The hash table locations of the keywords
* are marked; if an identifier hashes to one of
* these locations, it is looked up in in the keyword
for (ip
=kwtab
; (sp
= ip
->kwname
); ip
++) {
hshtab
[i
%hshsiz
].hflag
= FKEYW
;
* Look up the identifier in symbuf in the symbol table.
* If it hashes to the same spot as a keyword, try the keyword table
* first. An initial "." is ignored in the hash.
* Return is a ptr to the symbol table entry.
register struct hshtab
*rp
;
rp
= &hshtab
[ihash
%hshsiz
];
while (*(np
= rp
->name
)) {
for (sp
=symbuf
; sp
<symbuf
+ncps
;)
if (++rp
>= &hshtab
[hshsiz
])
if(++hshused
>= hshsiz
) {
error("Symbol table overflow");
for (np
=rp
->name
; sp
<symbuf
+ncps
;)
* Search the keyword table.
* Ignore initial "." to avoid member-of-structure
register struct kwtab
*kp
;
for (kp
=kwtab
; (p2
= kp
->kwname
); kp
++) {
* Return the next symbol from the input.
* peeksym is a pushed-back symbol, peekc is a pushed-back
* character (after peeksym).
* mosflg means that the next symbol, if an identifier,
* is a member of structure or a structure tag, and it
* gets a "." prepended to it to distinguish
* it from other identifiers.
case INSERT
: /* ignore newlines */
return(subseq(c
,PLUS
,INCBEF
));
return(subseq(c
,subseq('>',MINUS
,ARROW
),DECBEF
));
if (subseq(' ',0,1)) return(ASSIGN
);
if (c
>=PLUS
&& c
<=EXOR
) {
&& (c
==MINUS
|| c
==AND
|| c
==TIMES
)) {
error("Warning: assignment operator assumed");
if (subseq(c
,0,1)) return(LSHIFT
);
return(subseq('=',LESS
,LESSEQ
));
if (subseq(c
,0,1)) return(RSHIFT
);
return(subseq('=',GREAT
,GREATEQ
));
return(subseq('=',EXCLA
,NEQUAL
));
while ((c
= spnextchar()) != EOF
) {
if (spnextchar() == '/') {
error("Nonterminated comment");
if ((c
=getnum(c
=='0'?8:10)) == FCON
)
while(ctab
[c
]==LETTER
|| ctab
[c
]==DIGIT
) {
if (sp
<symbuf
+ncps
) *sp
++ = c
;
if ((c
=lookup())==KEYW
&& cval
==SIZEOF
)
return(subseq('&', AND
, LOGAND
));
return(subseq('|', OR
, LOGOR
));
error("Unknown character");
* If the next input character is c, return a and advance.
* Otherwise push back the character and return a.
* Read a double-quoted string, placing it on the
while((c
=mapch('"')) >= 0) {
if (sp
>= &savstr
[STRSIZ
]) {
error("String too long");
* Write out a string, either in-line
* or in the string temp file labelled by
outcode("BNB", LABEL
, lab
, BDATA
);
for (sp
= savstr
; sp
<strptr
; )
outcode("1N", *sp
++ & 0377);
* read a single-quoted character constant.
* The routine is sensitive to the layout of
while((c
=mapch('\'')) >= 0)
error("Long character constant");
* Read a character in a string or character constant,
* detecting the end of the string.
* It implements the escape sequences.
error("Nonterminated string");
case '0': case '1': case '2': case '3':
case '4': case '5': case '6': case '7':
while (++c
<=3 && '0'<=a
&& a
<='7') {
* Read an expression and return a pointer to its tree.
* It's the classical bottom-up, priority-driven scheme.
* The initflg prevents the parse from going past
* "," or ":" because those delimitesrs are special
* in initializer (and some other) expressions.
int *op
, opst
[SSIZE
], *pp
, prst
[SSIZE
];
register struct hshtab
*cs
;
if (cs
->hclass
==0 && cs
->htype
==0)
outcode("BBNB1N1N1N1N0B", DATA
,LABEL
,
cval
, WDATA
, fcval
, PROG
);
*cp
++ = block(1,o
,(o
==CON
?INT
:DOUBLE
),0,cval
);
/* fake a static char array */
*cp
++ = block(3, NAME
, ARRAY
+CHAR
,0,STATIC
,0,cval
);
error("Expression overflow");
if ((peeksym
=symbol())==FCON
) {
p
= (opdope
[o
]>>9) & 077;
if ((o
==COMMA
|| o
==COLON
) && initflg
)
if (p
>ps
|| p
==ps
&& (opdope
[o
]&RASSOC
)!=0) {
if (op
>= &opst
[SSIZE
-1]) {
error("expression overflow");
build(0); /* flush conversions */
*cp
++ = block(0,0,0,0); /* 0 arg call */
*cp
++ = block(1, CON
, INT
, 0, 1);
error("Expression syntax");
* Generate a tree node for a name.
* All the relevant info from the symbol table is
* copied out, including the name if it's an external.
* This is because the symbol table is gone in the next
* pass, so a ptr isn't sufficient.
register struct hshtab
*cs
;
register struct tname
*tp
;
tp
= gblock(sizeof(*tp
)/NCPW
);
if ((tp
->class = cs
->hclass
)==0)
if (cs
->hclass
==EXTERN
) {
gblock((ncps
-NCPW
)/NCPW
);