mv as from usr.bin to pgrm
[unix-history] / usr / src / old / yacc / y2.c
CommitLineData
129f3ce3
RH
1#ifndef lint
2static char sccsid[] = "@(#)y2.c 4.1 (Berkeley) %G%";
3#endif not lint
4
5# include "dextern"
6# define IDENTIFIER 257
7# define MARK 258
8# define TERM 259
9# define LEFT 260
10# define RIGHT 261
11# define BINARY 262
12# define PREC 263
13# define LCURLY 264
14# define C_IDENTIFIER 265 /* name followed by colon */
15# define NUMBER 266
16# define START 267
17# define TYPEDEF 268
18# define TYPENAME 269
19# define UNION 270
20# define ENDFILE 0
21
22 /* communication variables between various I/O routines */
23
24char *infile; /* input file name */
25int numbval; /* value of an input number */
26char tokname[NAMESIZE]; /* input token name */
27
28 /* storage of names */
29
30char cnames[CNAMSZ]; /* place where token and nonterminal names are stored */
31int cnamsz = CNAMSZ; /* size of cnames */
32char * cnamp = cnames; /* place where next name is to be put in */
33int ndefout = 3; /* number of defined symbols output */
34
35 /* storage of types */
36int ntypes; /* number of types defined */
37char * typeset[NTYPES]; /* pointers to type tags */
38
39 /* symbol tables for tokens and nonterminals */
40
41int ntokens = 0;
42struct toksymb tokset[NTERMS];
43int toklev[NTERMS];
44int nnonter = -1;
45struct ntsymb nontrst[NNONTERM];
46int start; /* start symbol */
47
48 /* assigned token type values */
49int extval = 0;
50
51 /* input and output file descriptors */
52
53FILE * finput; /* yacc input file */
54FILE * faction; /* file for saving actions */
55FILE * fdefine; /* file for # defines */
56FILE * ftable; /* y.tab.c file */
57FILE * ftemp; /* tempfile to pass 2 */
58FILE * foutput; /* y.output file */
59
60 /* storage for grammar rules */
61
62int mem0[MEMSIZE] ; /* production storage */
63int *mem = mem0;
64int nprod= 1; /* number of productions */
65int *prdptr[NPROD]; /* pointers to descriptions of productions */
66int levprd[NPROD] ; /* precedence levels for the productions */
67
68
69setup(argc,argv) int argc; char *argv[];
70{ int i,j,lev,t, ty;
71 int c;
72 int *p;
73 char actname[8];
74
75 foutput = NULL;
76 fdefine = NULL;
77 i = 1;
78 while( argc >= 2 && argv[1][0] == '-' ) {
79 while( *++(argv[1]) ){
80 switch( *argv[1] ){
81 case 'v':
82 case 'V':
83 foutput = fopen(FILEU, "w" );
84 if( foutput == NULL ) error( "cannot open y.output" );
85 continue;
86 case 'D':
87 case 'd':
88 fdefine = fopen( FILED, "w" );
89 continue;
90 case 'o':
91 case 'O':
92 fprintf( stderr, "`o' flag now default in yacc\n" );
93 continue;
94
95 case 'r':
96 case 'R':
97 error( "Ratfor Yacc is dead: sorry...\n" );
98
99 default:
100 error( "illegal option: %c", *argv[1]);
101 }
102 }
103 argv++;
104 argc--;
105 }
106
107 ftable = fopen( OFILE, "w" );
108 if( ftable == NULL ) error( "cannot open table file" );
109
110 ftemp = fopen( TEMPNAME, "w" );
111 faction = fopen( ACTNAME, "w" );
112 if( ftemp==NULL || faction==NULL ) error( "cannot open temp file" );
113
114 if( argc < 2 || ((finput=fopen( infile=argv[1], "r" )) == NULL ) ){
115 error( "cannot open input file" );
116 }
117
118 cnamp = cnames;
119 defin(0,"$end");
120 extval = 0400;
121 defin(0,"error");
122 defin(1,"$accept");
123 mem=mem0;
124 lev = 0;
125 ty = 0;
126 i=0;
127
128 /* sorry -- no yacc parser here.....
129 we must bootstrap somehow... */
130
131 for( t=gettok(); t!=MARK && t!= ENDFILE; ){
132 switch( t ){
133
134 case ';':
135 t = gettok();
136 break;
137
138 case START:
139 if( (t=gettok()) != IDENTIFIER ){
140 error( "bad %%start construction" );
141 }
142 start = chfind(1,tokname);
143 t = gettok();
144 continue;
145
146 case TYPEDEF:
147 if( (t=gettok()) != TYPENAME ) error( "bad syntax in %%type" );
148 ty = numbval;
149 for(;;){
150 t = gettok();
151 switch( t ){
152
153 case IDENTIFIER:
154 if( (t=chfind( 1, tokname ) ) < NTBASE ) {
155 j = TYPE( toklev[t] );
156 if( j!= 0 && j != ty ){
157 error( "type redeclaration of token %s",
158 tokset[t].name );
159 }
160 else SETTYPE( toklev[t],ty);
161 }
162 else {
163 j = nontrst[t-NTBASE].tvalue;
164 if( j != 0 && j != ty ){
165 error( "type redeclaration of nonterminal %s",
166 nontrst[t-NTBASE].name );
167 }
168 else nontrst[t-NTBASE].tvalue = ty;
169 }
170 case ',':
171 continue;
172
173 case ';':
174 t = gettok();
175 break;
176 default:
177 break;
178 }
179 break;
180 }
181 continue;
182
183 case UNION:
184 /* copy the union declaration to the output */
185 cpyunion();
186 t = gettok();
187 continue;
188
189 case LEFT:
190 case BINARY:
191 case RIGHT:
192 ++i;
193 case TERM:
194 lev = t-TERM; /* nonzero means new prec. and assoc. */
195 ty = 0;
196
197 /* get identifiers so defined */
198
199 t = gettok();
200 if( t == TYPENAME ){ /* there is a type defined */
201 ty = numbval;
202 t = gettok();
203 }
204
205 for(;;) {
206 switch( t ){
207
208 case ',':
209 t = gettok();
210 continue;
211
212 case ';':
213 break;
214
215 case IDENTIFIER:
216 j = chfind(0,tokname);
217 if( lev ){
218 if( ASSOC(toklev[j]) ) error( "redeclaration of precedence of %s", tokname );
219 SETASC(toklev[j],lev);
220 SETPLEV(toklev[j],i);
221 }
222 if( ty ){
223 if( TYPE(toklev[j]) ) error( "redeclaration of type of %s", tokname );
224 SETTYPE(toklev[j],ty);
225 }
226 if( (t=gettok()) == NUMBER ){
227 tokset[j].value = numbval;
228 if( j < ndefout && j>2 ){
229 error( "please define type number of %s earlier",
230 tokset[j].name );
231 }
232 t=gettok();
233 }
234 continue;
235
236 }
237
238 break;
239 }
240
241 continue;
242
243 case LCURLY:
244 defout();
245 cpycode();
246 t = gettok();
247 continue;
248
249 default:
250 error( "syntax error" );
251
252 }
253
254 }
255
256 if( t == ENDFILE ){
257 error( "unexpected EOF before %%" );
258 }
259
260 /* t is MARK */
261
262 defout();
263
264 fprintf( ftable, "#define yyclearin yychar = -1\n" );
265 fprintf( ftable, "#define yyerrok yyerrflag = 0\n" );
266 fprintf( ftable, "extern int yychar;\nextern short yyerrflag;\n" );
267 fprintf( ftable, "#ifndef YYMAXDEPTH\n#define YYMAXDEPTH 150\n#endif\n" );
268 if( !ntypes ) fprintf( ftable, "#ifndef YYSTYPE\n#define YYSTYPE int\n#endif\n" );
269 fprintf( ftable, "YYSTYPE yylval, yyval;\n" );
270
271 prdptr[0]=mem;
272 /* added production */
273 *mem++ = NTBASE;
274 *mem++ = start; /* if start is 0, we will overwrite with the lhs of the first rule */
275 *mem++ = 1;
276 *mem++ = 0;
277 prdptr[1]=mem;
278
279 while( (t=gettok()) == LCURLY ) cpycode();
280
281 if( t != C_IDENTIFIER ) error( "bad syntax on first rule" );
282
283 if( !start ) prdptr[0][1] = chfind(1,tokname);
284
285 /* read rules */
286
287 while( t!=MARK && t!=ENDFILE ){
288
289 /* process a rule */
290
291 if( t == '|' ){
292 *mem++ = *prdptr[nprod-1];
293 }
294 else if( t == C_IDENTIFIER ){
295 *mem = chfind(1,tokname);
296 if( *mem < NTBASE ) error( "token illegal on LHS of grammar rule" );
297 ++mem;
298 }
299 else error( "illegal rule: missing semicolon or | ?" );
300
301 /* read rule body */
302
303
304 t = gettok();
305 more_rule:
306 while( t == IDENTIFIER ) {
307 *mem = chfind(1,tokname);
308 if( *mem<NTBASE ) levprd[nprod] = toklev[*mem];
309 ++mem;
310 t = gettok();
311 }
312
313
314 if( t == PREC ){
315 if( gettok()!=IDENTIFIER) error( "illegal %%prec syntax" );
316 j = chfind(2,tokname);
317 if( j>=NTBASE)error("nonterminal %s illegal after %%prec", nontrst[j-NTBASE].name);
318 levprd[nprod]=toklev[j];
319 t = gettok();
320 }
321
322 if( t == '=' ){
323 levprd[nprod] |= ACTFLAG;
324 fprintf( faction, "\ncase %d:", nprod );
325 cpyact( mem-prdptr[nprod]-1 );
326 fprintf( faction, " break;" );
327 if( (t=gettok()) == IDENTIFIER ){
328 /* action within rule... */
329
330 sprintf( actname, "$$%d", nprod );
331 j = chfind(1,actname); /* make it a nonterminal */
332
333 /* the current rule will become rule number nprod+1 */
334 /* move the contents down, and make room for the null */
335
336 for( p=mem; p>=prdptr[nprod]; --p ) p[2] = *p;
337 mem += 2;
338
339 /* enter null production for action */
340
341 p = prdptr[nprod];
342
343 *p++ = j;
344 *p++ = -nprod;
345
346 /* update the production information */
347
348 levprd[nprod+1] = levprd[nprod] & ~ACTFLAG;
349 levprd[nprod] = ACTFLAG;
350
351 if( ++nprod >= NPROD ) error( "more than %d rules", NPROD );
352 prdptr[nprod] = p;
353
354 /* make the action appear in the original rule */
355 *mem++ = j;
356
357 /* get some more of the rule */
358
359 goto more_rule;
360 }
361
362 }
363
364 while( t == ';' ) t = gettok();
365
366 *mem++ = -nprod;
367
368 /* check that default action is reasonable */
369
370 if( ntypes && !(levprd[nprod]&ACTFLAG) && nontrst[*prdptr[nprod]-NTBASE].tvalue ){
371 /* no explicit action, LHS has value */
372 register tempty;
373 tempty = prdptr[nprod][1];
374 if( tempty < 0 ) error( "must return a value, since LHS has a type" );
375 else if( tempty >= NTBASE ) tempty = nontrst[tempty-NTBASE].tvalue;
376 else tempty = TYPE( toklev[tempty] );
377 if( tempty != nontrst[*prdptr[nprod]-NTBASE].tvalue ){
378 error( "default action causes potential type clash" );
379 }
380 }
381
382 if( ++nprod >= NPROD ) error( "more than %d rules", NPROD );
383 prdptr[nprod] = mem;
384 levprd[nprod]=0;
385
386 }
387
388 /* end of all rules */
389
390 finact();
391 if( t == MARK ){
392 fprintf( ftable, "\n# line %d \"%s\"\n", lineno, infile );
393 while( (c=getc(finput)) != EOF ) putc( c, ftable );
394 }
395 fclose( finput );
396 }
397
398finact(){
399 /* finish action routine */
400
401 fclose(faction);
402
403 fprintf( ftable, "# define YYERRCODE %d\n", tokset[2].value );
404
405 }
406
407defin( t, s ) register char *s; {
408/* define s to be a terminal if t=0
409 or a nonterminal if t=1 */
410
411 register val;
412
413 if (t) {
414 if( ++nnonter >= NNONTERM ) error("too many nonterminals, limit %d",NNONTERM);
415 nontrst[nnonter].name = cstash(s);
416 return( NTBASE + nnonter );
417 }
418 /* must be a token */
419 if( ++ntokens >= NTERMS ) error("too many terminals, limit %d",NTERMS );
420 tokset[ntokens].name = cstash(s);
421
422 /* establish value for token */
423
424 if( s[0]==' ' && s[2]=='\0' ) /* single character literal */
425 val = s[1];
426 else if ( s[0]==' ' && s[1]=='\\' ) { /* escape sequence */
427 if( s[3] == '\0' ){ /* single character escape sequence */
428 switch ( s[2] ){
429 /* character which is escaped */
430 case 'n': val = '\n'; break;
431 case 'r': val = '\r'; break;
432 case 'b': val = '\b'; break;
433 case 't': val = '\t'; break;
434 case 'f': val = '\f'; break;
435 case '\'': val = '\''; break;
436 case '"': val = '"'; break;
437 case '\\': val = '\\'; break;
438 default: error( "invalid escape" );
439 }
440 }
441 else if( s[2] <= '7' && s[2]>='0' ){ /* \nnn sequence */
442 if( s[3]<'0' || s[3] > '7' || s[4]<'0' ||
443 s[4]>'7' || s[5] != '\0' ) error("illegal \\nnn construction" );
444 val = 64*s[2] + 8*s[3] + s[4] - 73*'0';
445 if( val == 0 ) error( "'\\000' is illegal" );
446 }
447 }
448 else {
449 val = extval++;
450 }
451 tokset[ntokens].value = val;
452 toklev[ntokens] = 0;
453 return( ntokens );
454 }
455
456defout(){ /* write out the defines (at the end of the declaration section) */
457
458 register int i, c;
459 register char *cp;
460
461 for( i=ndefout; i<=ntokens; ++i ){
462
463 cp = tokset[i].name;
464 if( *cp == ' ' ) ++cp; /* literals */
465
466 for( ; (c= *cp)!='\0'; ++cp ){
467
468 if( islower(c) || isupper(c) || isdigit(c) || c=='_' ); /* VOID */
469 else goto nodef;
470 }
471
472 fprintf( ftable, "# define %s %d\n", tokset[i].name, tokset[i].value );
473 if( fdefine != NULL ) fprintf( fdefine, "# define %s %d\n", tokset[i].name, tokset[i].value );
474
475 nodef: ;
476 }
477
478 ndefout = ntokens+1;
479
480 }
481
482char *
483cstash( s ) register char *s; {
484 char *temp;
485
486 temp = cnamp;
487 do {
488 if( cnamp >= &cnames[cnamsz] ) error("too many characters in id's and literals" );
489 else *cnamp++ = *s;
490 } while ( *s++ );
491 return( temp );
492 }
493
494gettok() {
495 register i, base;
496 static int peekline; /* number of '\n' seen in lookahead */
497 register c, match, reserve;
498
499begin:
500 reserve = 0;
501 lineno += peekline;
502 peekline = 0;
503 c = getc(finput);
504 while( c==' ' || c=='\n' || c=='\t' || c=='\f' ){
505 if( c == '\n' ) ++lineno;
506 c=getc(finput);
507 }
508 if( c == '/' ){ /* skip comment */
509 lineno += skipcom();
510 goto begin;
511 }
512
513 switch(c){
514
515 case EOF:
516 return(ENDFILE);
517 case '{':
518 ungetc( c, finput );
519 return( '=' ); /* action ... */
520 case '<': /* get, and look up, a type name (union member name) */
521 i = 0;
522 while( (c=getc(finput)) != '>' && c>=0 && c!= '\n' ){
523 tokname[i] = c;
524 if( ++i >= NAMESIZE ) --i;
525 }
526 if( c != '>' ) error( "unterminated < ... > clause" );
527 tokname[i] = '\0';
528 for( i=1; i<=ntypes; ++i ){
529 if( !strcmp( typeset[i], tokname ) ){
530 numbval = i;
531 return( TYPENAME );
532 }
533 }
534 typeset[numbval = ++ntypes] = cstash( tokname );
535 return( TYPENAME );
536
537 case '"':
538 case '\'':
539 match = c;
540 tokname[0] = ' ';
541 i = 1;
542 for(;;){
543 c = getc(finput);
544 if( c == '\n' || c == EOF )
545 error("illegal or missing ' or \"" );
546 if( c == '\\' ){
547 c = getc(finput);
548 tokname[i] = '\\';
549 if( ++i >= NAMESIZE ) --i;
550 }
551 else if( c == match ) break;
552 tokname[i] = c;
553 if( ++i >= NAMESIZE ) --i;
554 }
555 break;
556
557 case '%':
558 case '\\':
559
560 switch(c=getc(finput)) {
561
562 case '0': return(TERM);
563 case '<': return(LEFT);
564 case '2': return(BINARY);
565 case '>': return(RIGHT);
566 case '%':
567 case '\\': return(MARK);
568 case '=': return(PREC);
569 case '{': return(LCURLY);
570 default: reserve = 1;
571 }
572
573 default:
574
575 if( isdigit(c) ){ /* number */
576 numbval = c-'0' ;
577 base = (c=='0') ? 8 : 10 ;
578 for( c=getc(finput); isdigit(c) ; c=getc(finput) ){
579 numbval = numbval*base + c - '0';
580 }
581 ungetc( c, finput );
582 return(NUMBER);
583 }
584 else if( islower(c) || isupper(c) || c=='_' || c=='.' || c=='$' ){
585 i = 0;
586 while( islower(c) || isupper(c) || isdigit(c) || c=='_' || c=='.' || c=='$' ){
587 tokname[i] = c;
588 if( reserve && isupper(c) ) tokname[i] += 'a'-'A';
589 if( ++i >= NAMESIZE ) --i;
590 c = getc(finput);
591 }
592 }
593 else return(c);
594
595 ungetc( c, finput );
596 }
597
598 tokname[i] = '\0';
599
600 if( reserve ){ /* find a reserved word */
601 if( !strcmp(tokname,"term")) return( TERM );
602 if( !strcmp(tokname,"token")) return( TERM );
603 if( !strcmp(tokname,"left")) return( LEFT );
604 if( !strcmp(tokname,"nonassoc")) return( BINARY );
605 if( !strcmp(tokname,"binary")) return( BINARY );
606 if( !strcmp(tokname,"right")) return( RIGHT );
607 if( !strcmp(tokname,"prec")) return( PREC );
608 if( !strcmp(tokname,"start")) return( START );
609 if( !strcmp(tokname,"type")) return( TYPEDEF );
610 if( !strcmp(tokname,"union")) return( UNION );
611 error("invalid escape, or illegal reserved word: %s", tokname );
612 }
613
614 /* look ahead to distinguish IDENTIFIER from C_IDENTIFIER */
615
616 c = getc(finput);
617 while( c==' ' || c=='\t'|| c=='\n' || c=='\f' || c== '/' ) {
618 if( c == '\n' ) ++peekline;
619 else if( c == '/' ){ /* look for comments */
620 peekline += skipcom();
621 }
622 c = getc(finput);
623 }
624 if( c == ':' ) return( C_IDENTIFIER );
625 ungetc( c, finput );
626 return( IDENTIFIER );
627}
628
629fdtype( t ){ /* determine the type of a symbol */
630 register v;
631 if( t >= NTBASE ) v = nontrst[t-NTBASE].tvalue;
632 else v = TYPE( toklev[t] );
633 if( v <= 0 ) error( "must specify type for %s", (t>=NTBASE)?nontrst[t-NTBASE].name:
634 tokset[t].name );
635 return( v );
636 }
637
638chfind( t, s ) register char *s; {
639 int i;
640
641 if (s[0]==' ')t=0;
642 TLOOP(i){
643 if(!strcmp(s,tokset[i].name)){
644 return( i );
645 }
646 }
647 NTLOOP(i){
648 if(!strcmp(s,nontrst[i].name)) {
649 return( i+NTBASE );
650 }
651 }
652 /* cannot find name */
653 if( t>1 )
654 error( "%s should have been defined earlier", s );
655 return( defin( t, s ) );
656 }
657
658cpyunion(){
659 /* copy the union declaration to the output, and the define file if present */
660
661 int level, c;
662 fprintf( ftable, "\n# line %d \"%s\"\n", lineno, infile );
663 fprintf( ftable, "typedef union " );
664 if( fdefine ) fprintf( fdefine, "\ntypedef union " );
665
666 level = 0;
667 for(;;){
668 if( (c=getc(finput)) < 0 ) error( "EOF encountered while processing %%union" );
669 putc( c, ftable );
670 if( fdefine ) putc( c, fdefine );
671
672 switch( c ){
673
674 case '\n':
675 ++lineno;
676 break;
677
678 case '{':
679 ++level;
680 break;
681
682 case '}':
683 --level;
684 if( level == 0 ) { /* we are finished copying */
685 fprintf( ftable, " YYSTYPE;\n" );
686 if( fdefine ) fprintf( fdefine, " YYSTYPE;\nextern YYSTYPE yylval;\n" );
687 return;
688 }
689 }
690 }
691 }
692
693cpycode(){ /* copies code between \{ and \} */
694
695 int c;
696 c = getc(finput);
697 if( c == '\n' ) {
698 c = getc(finput);
699 lineno++;
700 }
701 fprintf( ftable, "\n# line %d \"%s\"\n", lineno, infile );
702 while( c>=0 ){
703 if( c=='\\' )
704 if( (c=getc(finput)) == '}' ) return;
705 else putc('\\', ftable );
706 if( c=='%' )
707 if( (c=getc(finput)) == '}' ) return;
708 else putc('%', ftable );
709 putc( c , ftable );
710 if( c == '\n' ) ++lineno;
711 c = getc(finput);
712 }
713 error("eof before %%}" );
714 }
715
716skipcom(){ /* skip over comments */
717 register c, i=0; /* i is the number of lines skipped */
718
719 /* skipcom is called after reading a / */
720
721 if( getc(finput) != '*' ) error( "illegal comment" );
722 c = getc(finput);
723 while( c != EOF ){
724 while( c == '*' ){
725 if( (c=getc(finput)) == '/' ) return( i );
726 }
727 if( c == '\n' ) ++i;
728 c = getc(finput);
729 }
730 error( "EOF inside comment" );
731 /* NOTREACHED */
732 }
733
734cpyact(offset){ /* copy C action to the next ; or closing } */
735 int brac, c, match, j, s, tok;
736
737 fprintf( faction, "\n# line %d \"%s\"\n", lineno, infile );
738
739 brac = 0;
740
741loop:
742 c = getc(finput);
743swt:
744 switch( c ){
745
746case ';':
747 if( brac == 0 ){
748 putc( c , faction );
749 return;
750 }
751 goto lcopy;
752
753case '{':
754 brac++;
755 goto lcopy;
756
757case '$':
758 s = 1;
759 tok = -1;
760 c = getc(finput);
761 if( c == '<' ){ /* type description */
762 ungetc( c, finput );
763 if( gettok() != TYPENAME ) error( "bad syntax on $<ident> clause" );
764 tok = numbval;
765 c = getc(finput);
766 }
767 if( c == '$' ){
768 fprintf( faction, "yyval");
769 if( ntypes ){ /* put out the proper tag... */
770 if( tok < 0 ) tok = fdtype( *prdptr[nprod] );
771 fprintf( faction, ".%s", typeset[tok] );
772 }
773 goto loop;
774 }
775 if( c == '-' ){
776 s = -s;
777 c = getc(finput);
778 }
779 if( isdigit(c) ){
780 j=0;
781 while( isdigit(c) ){
782 j= j*10+c-'0';
783 c = getc(finput);
784 }
785
786 j = j*s - offset;
787 if( j > 0 ){
788 error( "Illegal use of $%d", j+offset );
789 }
790
791 fprintf( faction, "yypvt[-%d]", -j );
792 if( ntypes ){ /* put out the proper tag */
793 if( j+offset <= 0 && tok < 0 ) error( "must specify type of $%d", j+offset );
794 if( tok < 0 ) tok = fdtype( prdptr[nprod][j+offset] );
795 fprintf( faction, ".%s", typeset[tok] );
796 }
797 goto swt;
798 }
799 putc( '$' , faction );
800 if( s<0 ) putc('-', faction );
801 goto swt;
802
803case '}':
804 if( --brac ) goto lcopy;
805 putc( c, faction );
806 return;
807
808
809case '/': /* look for comments */
810 putc( c , faction );
811 c = getc(finput);
812 if( c != '*' ) goto swt;
813
814 /* it really is a comment */
815
816 putc( c , faction );
817 c = getc(finput);
818 while( c != EOF ){
819 while( c=='*' ){
820 putc( c , faction );
821 if( (c=getc(finput)) == '/' ) goto lcopy;
822 }
823 putc( c , faction );
824 if( c == '\n' )++lineno;
825 c = getc(finput);
826 }
827 error( "EOF inside comment" );
828
829case '\'': /* character constant */
830 match = '\'';
831 goto string;
832
833case '"': /* character string */
834 match = '"';
835
836 string:
837
838 putc( c , faction );
839 while( c=getc(finput) ){
840
841 if( c=='\\' ){
842 putc( c , faction );
843 c=getc(finput);
844 if( c == '\n' ) ++lineno;
845 }
846 else if( c==match ) goto lcopy;
847 else if( c=='\n' ) error( "newline in string or char. const." );
848 putc( c , faction );
849 }
850 error( "EOF in string or character constant" );
851
852case EOF:
853 error("action does not terminate" );
854
855case '\n': ++lineno;
856 goto lcopy;
857
858 }
859
860lcopy:
861 putc( c , faction );
862 goto loop;
863 }