Research V7 development
[unix-history] / usr / src / cmd / mip / scan.c
CommitLineData
3f3984db
SJ
1# include "mfile1"
2# include <ctype.h>
3 /* temporarily */
4
5 /* lexical actions */
6
7# define A_ERR 0 /* illegal character */
8# define A_LET 1 /* saw a letter */
9# define A_DIG 2 /* saw a digit */
10# define A_1C 3 /* return a single character */
11# define A_STR 4 /* string */
12# define A_CC 5 /* character constant */
13# define A_BCD 6 /* GCOS BCD constant */
14# define A_SL 7 /* saw a / */
15# define A_DOT 8 /* saw a . */
16# define A_PL 9 /* + */
17# define A_MI 10 /* - */
18# define A_EQ 11 /* = */
19# define A_NOT 12 /* ! */
20# define A_LT 13 /* < */
21# define A_GT 14 /* > */
22# define A_AND 16 /* & */
23# define A_OR 17 /* | */
24# define A_WS 18 /* whitespace (not \n) */
25# define A_NL 19 /* \n */
26
27 /* character classes */
28
29# define LEXLET 01
30# define LEXDIG 02
31# define LEXOCT 04
32# define LEXHEX 010
33# define LEXWS 020
34# define LEXDOT 040
35
36 /* reserved word actions */
37
38# define AR_TY 0 /* type word */
39# define AR_RW 1 /* simple reserved word */
40# define AR_CL 2 /* storage class word */
41# define AR_S 3 /* struct */
42# define AR_U 4 /* union */
43# define AR_E 5 /* enum */
44# define AR_A 6 /* asm */
45
46 /* text buffer */
47# define LXTSZ 100
48char yytext[LXTSZ];
49char * lxgcp;
50
51
52 /* ARGSUSED */
53mainp1( argc, argv ) int argc; char *argv[]; { /* control multiple files */
54
55 register i;
56 register char *cp;
57 extern int idebug, bdebug, tdebug, edebug, ddebug, xdebug;
58
59 for( i=1; i<argc; ++i ){
60 if( *(cp=argv[i]) == '-' && *++cp == 'X' ){
61 while( *++cp ){
62 switch( *cp ){
63
64 case 'd':
65 ++ddebug;
66 break;
67 case 'i':
68 ++idebug;
69 break;
70 case 'b':
71 ++bdebug;
72 break;
73 case 't':
74 ++tdebug;
75 break;
76 case 'e':
77 ++edebug;
78 break;
79 case 'x':
80 ++xdebug;
81 break;
82 }
83 }
84 }
85 }
86
87# ifdef ONEPASS
88 p2init( argc, argv );
89# endif
90
91 for( i=0; i<SYMTSZ; ++i ) stab[i].stype = TNULL;
92
93 lxinit();
94 tinit();
95 mkdope();
96
97 lineno = 1;
98
99 /* dimension table initialization */
100
101 dimtab[NULL] = 0;
102 dimtab[CHAR] = SZCHAR;
103 dimtab[INT] = SZINT;
104 dimtab[FLOAT] = SZFLOAT;
105 dimtab[DOUBLE] = SZDOUBLE;
106 dimtab[LONG] = SZLONG;
107 dimtab[SHORT] = SZSHORT;
108 dimtab[UCHAR] = SZCHAR;
109 dimtab[USHORT] = SZSHORT;
110 dimtab[UNSIGNED] = SZINT;
111 dimtab[ULONG] = SZLONG;
112 /* starts past any of the above */
113 curdim = 16;
114 reached = 1;
115
116 yyparse();
117 yyaccpt();
118
119 ejobcode( nerrors ? 1 : 0 );
120 return(nerrors?1:0);
121
122 }
123
124# ifdef ibm
125
126# define CSMASK 0377
127# define CSSZ 256
128
129# else
130
131# define CSMASK 0177
132# define CSSZ 128
133
134# endif
135
136short lxmask[CSSZ+1];
137
138lxenter( s, m ) register char *s; register short m; {
139 /* enter a mask into lxmask */
140 register c;
141
142 while( c= *s++ ) lxmask[c+1] |= m;
143
144 }
145
146
147# define lxget(c,m) (lxgcp=yytext,lxmore(c,m))
148
149lxmore( c, m ) register c, m; {
150 register char *cp;
151
152 *(cp = lxgcp) = c;
153 while( c=getchar(), lxmask[c+1]&m ){
154 if( cp < &yytext[LXTSZ-1] ){
155 *++cp = c;
156 }
157 }
158 ungetc(c,stdin);
159 *(lxgcp = cp+1) = '\0';
160 }
161
162struct lxdope {
163 short lxch; /* the character */
164 short lxact; /* the action to be performed */
165 short lxtok; /* the token number to be returned */
166 short lxval; /* the value to be returned */
167 } lxdope[] = {
168
169 '$', A_ERR, 0, 0, /* illegal characters go here... */
170 '_', A_LET, 0, 0, /* letters point here */
171 '0', A_DIG, 0, 0, /* digits point here */
172 ' ', A_WS, 0, 0, /* whitespace goes here */
173 '\n', A_NL, 0, 0,
174 '"', A_STR, 0, 0, /* character string */
175 '\'', A_CC, 0, 0, /* character constant */
176 '`', A_BCD, 0, 0, /* GCOS BCD constant */
177 '(', A_1C, LP, 0,
178 ')', A_1C, RP, 0,
179 '{', A_1C, LC, 0,
180 '}', A_1C, RC, 0,
181 '[', A_1C, LB, 0,
182 ']', A_1C, RB, 0,
183 '*', A_1C, MUL, MUL,
184 '?', A_1C, QUEST, 0,
185 ':', A_1C, COLON, 0,
186 '+', A_PL, PLUS, PLUS,
187 '-', A_MI, MINUS, MINUS,
188 '/', A_SL, DIVOP, DIV,
189 '%', A_1C, DIVOP, MOD,
190 '&', A_AND, AND, AND,
191 '|', A_OR, OR, OR,
192 '^', A_1C, ER, ER,
193 '!', A_NOT, UNOP, NOT,
194 '~', A_1C, UNOP, COMPL,
195 ',', A_1C, CM, CM,
196 ';', A_1C, SM, 0,
197 '.', A_DOT, STROP, DOT,
198 '<', A_LT, RELOP, LT,
199 '>', A_GT, RELOP, GT,
200 '=', A_EQ, ASSIGN, ASSIGN,
201 -1, A_1C, 0, 0,
202 };
203
204struct lxdope *lxcp[CSSZ+1];
205
206lxinit(){
207 register struct lxdope *p;
208 register i;
209 register char *cp;
210 /* set up character classes */
211
212 lxenter( "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_", LEXLET );
213 lxenter( "0123456789", LEXDIG );
214 lxenter( "0123456789abcdefABCDEF", LEXHEX );
215 lxenter( " \t\r\b\f", LEXWS );
216 lxenter( "01234567", LEXOCT );
217 lxmask['.'+1] |= LEXDOT;
218
219 /* make lxcp point to appropriate lxdope entry for each character */
220
221 /* initialize error entries */
222
223 for( i= 0; i<=CSSZ; ++i ) lxcp[i] = lxdope;
224
225 /* make unique entries */
226
227 for( p=lxdope; ; ++p ) {
228 lxcp[p->lxch+1] = p;
229 if( p->lxch < 0 ) break;
230 }
231
232 /* handle letters, digits, and whitespace */
233 /* by convention, first, second, and third places */
234
235 cp = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
236 while( *cp ) lxcp[*cp++ + 1] = &lxdope[1];
237 cp = "123456789";
238 while( *cp ) lxcp[*cp++ + 1] = &lxdope[2];
239 cp = "\t\b\r\f";
240 while( *cp ) lxcp[*cp++ + 1] = &lxdope[3];
241
242 /* first line might have title */
243 lxtitle();
244
245 }
246
247int lxmatch; /* character to be matched in char or string constant */
248
249lxstr(ct){
250 /* match a string or character constant, up to lxmatch */
251
252 register c;
253 register val;
254 register i;
255
256 i=0;
257 while( (c=getchar()) != lxmatch ){
258 switch( c ) {
259
260 case EOF:
261 uerror( "unexpected EOF" );
262 break;
263
264 case '\n':
265 uerror( "newline in string or char constant" );
266 ++lineno;
267 break;
268
269 case '\\':
270 switch( c = getchar() ){
271
272 case '\n':
273 ++lineno;
274 continue;
275
276 default:
277 val = c;
278 goto mkcc;
279
280 case 'n':
281 val = '\n';
282 goto mkcc;
283
284 case 'r':
285 val = '\r';
286 goto mkcc;
287
288 case 'b':
289 val = '\b';
290 goto mkcc;
291
292 case 't':
293 val = '\t';
294 goto mkcc;
295
296 case 'f':
297 val = '\f';
298 goto mkcc;
299
300 case '0':
301 case '1':
302 case '2':
303 case '3':
304 case '4':
305 case '5':
306 case '6':
307 case '7':
308 val = c-'0';
309 c=getchar(); /* try for 2 */
310 if( lxmask[c+1] & LEXOCT ){
311 val = (val<<3) | (c-'0');
312 c = getchar(); /* try for 3 */
313 if( lxmask[c+1] & LEXOCT ){
314 val = (val<<3) | (c-'0');
315 }
316 else ungetc( c ,stdin);
317 }
318 else ungetc( c ,stdin);
319
320 goto mkcc1;
321
322 }
323 default:
324 val =c;
325 mkcc:
326 val = CCTRANS(val);
327 mkcc1:
328 if( lxmatch == '\'' ){
329 val = CHARCAST(val); /* it is, after all, a "character" constant */
330 makecc( val, i );
331 }
332 else { /* stash the byte into the string */
333 if( strflg ) {
334 if( ct==0 || i<ct ) putbyte( val );
335 else if( i == ct ) werror( "non-null byte ignored in string initializer" );
336 }
337 else bycode( val, i );
338 }
339 ++i;
340 continue;
341 }
342 break;
343 }
344 /* end of string or char constant */
345
346 if( lxmatch == '"' ){
347 if( strflg ){ /* end the string */
348 if( ct==0 || i<ct ) putbyte( 0 ); /* the null at the end */
349 }
350 else { /* the initializer gets a null byte */
351 bycode( 0, i++ );
352 bycode( -1, i );
353 dimtab[curdim] = i; /* in case of later sizeof ... */
354 }
355 }
356 else { /* end the character constant */
357 if( i == 0 ) uerror( "empty character constant" );
358 if( i>(SZINT/SZCHAR) || ( (pflag||hflag)&&i>1) )
359 uerror( "too many characters in character constant" );
360 }
361 }
362
363lxcom(){
364 register c;
365 /* saw a /*: process a comment */
366
367 for(;;){
368
369 switch( c = getchar() ){
370
371 case EOF:
372 uerror( "unexpected EOF" );
373 return;
374
375 case '\n':
376 ++lineno;
377
378 default:
379 continue;
380
381 case '*':
382 if( (c = getchar()) == '/' ) return;
383 else ungetc( c ,stdin);
384 continue;
385
386# ifdef LINT
387 case 'V':
388 lxget( c, LEXLET|LEXDIG );
389 {
390 extern int vaflag;
391 int i;
392 i = yytext[7]?yytext[7]-'0':0;
393 yytext[7] = '\0';
394 if( strcmp( yytext, "VARARGS" ) ) continue;
395 vaflag = i;
396 continue;
397 }
398 case 'L':
399 lxget( c, LEXLET );
400 if( strcmp( yytext, "LINTLIBRARY" ) ) continue;
401 {
402 extern int libflag;
403 libflag = 1;
404 }
405 continue;
406
407 case 'A':
408 lxget( c, LEXLET );
409 if( strcmp( yytext, "ARGSUSED" ) ) continue;
410 {
411 extern int argflag, vflag;
412 argflag = 1;
413 vflag = 0;
414 }
415 continue;
416
417 case 'N':
418 lxget( c, LEXLET );
419 if( strcmp( yytext, "NOTREACHED" ) ) continue;
420 reached = 0;
421 continue;
422# endif
423 }
424 }
425 }
426
427yylex(){
428 for(;;){
429
430 register lxchar;
431 register struct lxdope *p;
432 register struct symtab *sp;
433 int id;
434
435 switch( (p=lxcp[(lxchar=getchar())+1])->lxact ){
436
437 onechar:
438 ungetc( lxchar ,stdin);
439
440 case A_1C:
441 /* eat up a single character, and return an opcode */
442
443 yylval.intval = p->lxval;
444 return( p->lxtok );
445
446 case A_ERR:
447 uerror( "illegal character: %03o (octal)", lxchar );
448 break;
449
450 case A_LET:
451 /* collect an identifier, check for reserved word, and return */
452 lxget( lxchar, LEXLET|LEXDIG );
453 if( (lxchar=lxres()) > 0 ) return( lxchar ); /* reserved word */
454 if( lxchar== 0 ) continue;
455 id = lookup( yytext, (stwart&(INSTRUCT|INUNION|FUNNYNAME))?SMOS:0 );
456 sp = &stab[id];
457 if( sp->sclass == TYPEDEF && !stwart ){
458 stwart = instruct;
459 yylval.nodep = mkty( sp->stype, sp->dimoff, sp->sizoff );
460 return( TYPE );
461 }
462 stwart = (stwart&SEENAME) ? instruct : 0;
463 yylval.intval = id;
464 return( NAME );
465
466 case A_DIG:
467 /* collect a digit string, then look at last one... */
468 lastcon = 0;
469 lxget( lxchar, LEXDIG );
470 switch( lxchar=getchar() ){
471
472 case 'x':
473 case 'X':
474 if( yytext[0] != '0' && !yytext[1] ) uerror( "illegal hex constant" );
475 lxmore( lxchar, LEXHEX );
476 /* convert the value */
477 {
478 register char *cp;
479 for( cp = yytext+2; *cp; ++cp ){
480 /* this code won't work for all wild character sets,
481 but seems ok for ascii and ebcdic */
482 lastcon <<= 4;
483 if( isdigit( *cp ) ) lastcon += *cp-'0';
484 else if( isupper( *cp ) ) lastcon += *cp - 'A'+ 10;
485 else lastcon += *cp - 'a'+ 10;
486 }
487 }
488
489 hexlong:
490 /* criterion for longness for hex and octal constants is that it
491 fit within 0177777 */
492 if( lastcon & ~0177777L ) yylval.intval = 1;
493 else yylval.intval = 0;
494
495 goto islong;
496
497 case '.':
498 lxmore( lxchar, LEXDIG );
499
500 getfp:
501 if( (lxchar=getchar()) == 'e' || lxchar == 'E' ){ /* exponent */
502
503 case 'e':
504 case 'E':
505 if( (lxchar=getchar()) == '+' || lxchar == '-' ){
506 *lxgcp++ = 'e';
507 }
508 else {
509 ungetc(lxchar,stdin);
510 lxchar = 'e';
511 }
512 lxmore( lxchar, LEXDIG );
513 /* now have the whole thing... */
514 }
515 else { /* no exponent */
516 ungetc( lxchar ,stdin);
517 }
518 return( isitfloat( yytext ) );
519
520 default:
521 ungetc( lxchar ,stdin);
522 if( yytext[0] == '0' ){
523 /* convert in octal */
524 register char *cp;
525 for( cp = yytext+1; *cp; ++cp ){
526 lastcon <<= 3;
527 lastcon += *cp - '0';
528 }
529 goto hexlong;
530 }
531 else {
532 /* convert in decimal */
533 register char *cp;
534 for( cp = yytext; *cp; ++cp ){
535 lastcon = lastcon * 10 + *cp - '0';
536 }
537 }
538
539 /* decide if it is long or not (decimal case) */
540
541 /* if it is positive and fits in 15 bits, or negative and
542 and fits in 15 bits plus an extended sign, it is int; otherwise long */
543 /* if there is an l or L following, all bets are off... */
544
545 { CONSZ v;
546 v = lastcon & ~077777L;
547 if( v == 0 || v == ~077777L ) yylval.intval = 0;
548 else yylval.intval = 1;
549 }
550
551 islong:
552 /* finally, look for trailing L or l */
553 if( (lxchar = getchar()) == 'L' || lxchar == 'l' ) yylval.intval = 1;
554 else ungetc( lxchar ,stdin);
555 return( ICON );
556 }
557
558 case A_DOT:
559 /* look for a dot: if followed by a digit, floating point */
560 lxchar = getchar();
561 if( lxmask[lxchar+1] & LEXDIG ){
562 ungetc(lxchar,stdin);
563 lxget( '.', LEXDIG );
564 goto getfp;
565 }
566 stwart = FUNNYNAME;
567 goto onechar;
568
569 case A_STR:
570 /* string constant */
571 lxmatch = '"';
572 return( STRING );
573
574 case A_CC:
575 /* character constant */
576 lxmatch = '\'';
577 lastcon = 0;
578 lxstr(0);
579 yylval.intval = 0;
580 return( ICON );
581
582 case A_BCD:
583 {
584 register i;
585 int j;
586 for( i=0; i<LXTSZ; ++i ){
587 if( ( j = getchar() ) == '`' ) break;
588 if( j == '\n' ){
589 uerror( "newline in BCD constant" );
590 break;
591 }
592 yytext[i] = j;
593 }
594 yytext[i] = '\0';
595 if( i>6 ) uerror( "BCD constant exceeds 6 characters" );
596# ifdef gcos
597 else strtob( yytext, &lastcon, i );
598 lastcon >>= 6*(6-i);
599# else
600 uerror( "gcos BCD constant illegal" );
601# endif
602 yylval.intval = 0; /* not long */
603 return( ICON );
604 }
605
606 case A_SL:
607 /* / */
608 if( (lxchar=getchar()) != '*' ) goto onechar;
609 lxcom();
610 case A_WS:
611 continue;
612
613 case A_NL:
614 ++lineno;
615 lxtitle();
616 continue;
617
618 case A_NOT:
619 /* ! */
620 if( (lxchar=getchar()) != '=' ) goto onechar;
621 yylval.intval = NE;
622 return( EQUOP );
623
624 case A_MI:
625 /* - */
626 if( (lxchar=getchar()) == '-' ){
627 yylval.intval = DECR;
628 return( INCOP );
629 }
630 if( lxchar != '>' ) goto onechar;
631 stwart = FUNNYNAME;
632 yylval.intval=STREF;
633 return( STROP );
634
635 case A_PL:
636 /* + */
637 if( (lxchar=getchar()) != '+' ) goto onechar;
638 yylval.intval = INCR;
639 return( INCOP );
640
641 case A_AND:
642 /* & */
643 if( (lxchar=getchar()) != '&' ) goto onechar;
644 return( yylval.intval = ANDAND );
645
646 case A_OR:
647 /* | */
648 if( (lxchar=getchar()) != '|' ) goto onechar;
649 return( yylval.intval = OROR );
650
651 case A_LT:
652 /* < */
653 if( (lxchar=getchar()) == '<' ){
654 yylval.intval = LS;
655 return( SHIFTOP );
656 }
657 if( lxchar != '=' ) goto onechar;
658 yylval.intval = LE;
659 return( RELOP );
660
661 case A_GT:
662 /* > */
663 if( (lxchar=getchar()) == '>' ){
664 yylval.intval = RS;
665 return(SHIFTOP );
666 }
667 if( lxchar != '=' ) goto onechar;
668 yylval.intval = GE;
669 return( RELOP );
670
671 case A_EQ:
672 /* = */
673 switch( lxchar = getchar() ){
674
675 case '=':
676 yylval.intval = EQ;
677 return( EQUOP );
678
679 case '+':
680 yylval.intval = ASG PLUS;
681 break;
682
683 case '-':
684 yylval.intval = ASG MINUS;
685
686 warn:
687 if( lxmask[ (lxchar=getchar())+1] & (LEXLET|LEXDIG|LEXDOT) ){
688 werror( "ambiguous assignment: assignment op taken" );
689 }
690 ungetc( lxchar ,stdin);
691 break;
692
693 case '*':
694 yylval.intval = ASG MUL;
695 goto warn;
696
697 case '/':
698 yylval.intval = ASG DIV;
699 break;
700
701 case '%':
702 yylval.intval = ASG MOD;
703 break;
704
705 case '&':
706 yylval.intval = ASG AND;
707 break;
708
709 case '|':
710 yylval.intval = ASG OR;
711 break;
712
713 case '^':
714 yylval.intval = ASG ER;
715 break;
716
717 case '<':
718 if( (lxchar=getchar()) != '<' ){
719 uerror( "=<%c illegal", lxchar );
720 }
721 yylval.intval = ASG LS;
722 break;
723
724 case '>':
725 if( (lxchar=getchar()) != '>' ){
726 uerror( "=>%c illegal", lxchar );
727 }
728 yylval.intval = ASG RS;
729 break;
730
731 default:
732 goto onechar;
733
734 }
735
736 return( ASOP );
737
738 default:
739 cerror( "yylex error, character %03o (octal)", lxchar );
740
741 }
742
743 /* ordinarily, repeat here... */
744 cerror( "out of switch in yylex" );
745
746 }
747
748 }
749
750struct lxrdope {
751 /* dope for reserved, in alphabetical order */
752
753 char *lxrch; /* name of reserved word */
754 short lxract; /* reserved word action */
755 short lxrval; /* value to be returned */
756 } lxrdope[] = {
757
758 "asm", AR_A, 0,
759 "auto", AR_CL, AUTO,
760 "break", AR_RW, BREAK,
761 "char", AR_TY, CHAR,
762 "case", AR_RW, CASE,
763 "continue", AR_RW, CONTINUE,
764 "double", AR_TY, DOUBLE,
765 "default", AR_RW, DEFAULT,
766 "do", AR_RW, DO,
767 "extern", AR_CL, EXTERN,
768 "else", AR_RW, ELSE,
769 "enum", AR_E, ENUM,
770 "for", AR_RW, FOR,
771 "float", AR_TY, FLOAT,
772 "fortran", AR_CL, FORTRAN,
773 "goto", AR_RW, GOTO,
774 "if", AR_RW, IF,
775 "int", AR_TY, INT,
776 "long", AR_TY, LONG,
777 "return", AR_RW, RETURN,
778 "register", AR_CL, REGISTER,
779 "switch", AR_RW, SWITCH,
780 "struct", AR_S, 0,
781 "sizeof", AR_RW, SIZEOF,
782 "short", AR_TY, SHORT,
783 "static", AR_CL, STATIC,
784 "typedef", AR_CL, TYPEDEF,
785 "unsigned", AR_TY, UNSIGNED,
786 "union", AR_U, 0,
787 "while", AR_RW, WHILE,
788 "", 0, 0, /* to stop the search */
789 };
790
791lxres() {
792 /* check to see of yytext is reserved; if so,
793 /* do the appropriate action and return */
794 /* otherwise, return -1 */
795
796 register c, ch;
797 register struct lxrdope *p;
798
799 ch = yytext[0];
800
801 if( !islower(ch) ) return( -1 );
802
803 switch( ch ){
804
805 case 'a':
806 c=0; break;
807 case 'b':
808 c=2; break;
809 case 'c':
810 c=3; break;
811 case 'd':
812 c=6; break;
813 case 'e':
814 c=9; break;
815 case 'f':
816 c=12; break;
817 case 'g':
818 c=15; break;
819 case 'i':
820 c=16; break;
821 case 'l':
822 c=18; break;
823 case 'r':
824 c=19; break;
825 case 's':
826 c=21; break;
827 case 't':
828 c=26; break;
829 case 'u':
830 c=27; break;
831 case 'w':
832 c=29; break;
833
834 default:
835 return( -1 );
836 }
837
838 for( p= lxrdope+c; p->lxrch[0] == ch; ++p ){
839 if( !strcmp( yytext, p->lxrch ) ){ /* match */
840 switch( p->lxract ){
841
842 case AR_TY:
843 /* type word */
844 stwart = instruct;
845 yylval.nodep = mkty( (TWORD)p->lxrval, 0, p->lxrval );
846 return( TYPE );
847
848 case AR_RW:
849 /* ordinary reserved word */
850 return( yylval.intval = p->lxrval );
851
852 case AR_CL:
853 /* class word */
854 yylval.intval = p->lxrval;
855 return( CLASS );
856
857 case AR_S:
858 /* struct */
859 stwart = INSTRUCT|SEENAME;
860 yylval.intval = INSTRUCT;
861 return( STRUCT );
862
863 case AR_U:
864 /* union */
865 stwart = INUNION|SEENAME;
866 yylval.intval = INUNION;
867 return( STRUCT );
868
869 case AR_E:
870 /* enums */
871 stwart = SEENAME;
872 return( yylval.intval = ENUM );
873
874 case AR_A:
875 /* asm */
876 lxget( ' ', LEXWS );
877 if( getchar() != '(' ) goto badasm;
878 lxget( ' ', LEXWS );
879 if( getchar() != '"' ) goto badasm;
880# ifndef ONEPASS
881# ifndef LINT
882 putchar(')');
883# endif
884# endif
885 while( (c=getchar()) != '"' ){
886 if( c=='\n' || c==EOF ) goto badasm;
887# ifndef LINT
888 putchar(c);
889# endif
890 }
891 lxget( ' ', LEXWS );
892 if( getchar() != ')' ) goto badasm;
893# ifndef LINT
894 putchar('\n');
895# endif
896 return( 0 );
897
898 badasm:
899 uerror( "bad asm construction" );
900 return( 0 );
901
902 default:
903 cerror( "bad AR_?? action" );
904 }
905 }
906 }
907 return( -1 );
908 }
909
910lxtitle(){
911 /* called after a newline; set linenumber and file name */
912
913 register c, val;
914 register char *cp;
915
916 for(;;){ /* might be several such lines in a row */
917 if( (c=getchar()) != '#' ){
918 if( c != EOF ) ungetc(c,stdin);
919 return;
920 }
921
922 lxget( ' ', LEXWS );
923 val = 0;
924 for( c=getchar(); isdigit(c); c=getchar() ){
925 val = val*10+ c - '0';
926 }
927 ungetc( c, stdin );
928 lineno = val;
929 lxget( ' ', LEXWS );
930 if( (c=getchar()) != '\n' ){
931 for( cp=ftitle; c!='\n'; c=getchar(),++cp ){
932 *cp = c;
933 }
934 *cp = '\0';
935 }
936 }
937 }