Add the DragonFly cvs id and perform general cleanups on cvs/rcs/sccs ids. Most
[dragonfly.git] / usr.bin / lex / parse.y
1 /* parse.y - parser for flex input */
2
3 %token CHAR NUMBER SECTEND SCDECL XSCDECL NAME PREVCCL EOF_OP
4 %token OPTION_OP OPT_OUTFILE OPT_PREFIX OPT_YYCLASS
5
6 %token CCE_ALNUM CCE_ALPHA CCE_BLANK CCE_CNTRL CCE_DIGIT CCE_GRAPH
7 %token CCE_LOWER CCE_PRINT CCE_PUNCT CCE_SPACE CCE_UPPER CCE_XDIGIT
8
9 %{
10 /*-
11  * Copyright (c) 1990 The Regents of the University of California.
12  * All rights reserved.
13  *
14  * This code is derived from software contributed to Berkeley by
15  * Vern Paxson.
16  * 
17  * The United States Government has rights in this work pursuant
18  * to contract no. DE-AC03-76SF00098 between the United States
19  * Department of Energy and the University of California.
20  *
21  * Redistribution and use in source and binary forms are permitted provided
22  * that: (1) source distributions retain this entire copyright notice and
23  * comment, and (2) distributions including binaries display the following
24  * acknowledgement:  ``This product includes software developed by the
25  * University of California, Berkeley and its contributors'' in the
26  * documentation or other materials provided with the distribution and in
27  * all advertising materials mentioning features or use of this software.
28  * Neither the name of the University nor the names of its contributors may
29  * be used to endorse or promote products derived from this software without
30  * specific prior written permission.
31  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
32  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
33  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
34  */
35
36 /* $Header: /home/daffy/u0/vern/flex/RCS/parse.y,v 2.28 95/04/21 11:51:51 vern Exp $ */
37 /* $FreeBSD: src/usr.bin/lex/parse.y,v 1.3 1999/10/27 07:56:46 obrien Exp $ */
38 /* $DragonFly: src/usr.bin/lex/parse.y,v 1.2 2003/06/17 04:29:28 dillon Exp $ */
39
40
41 /* Some versions of bison are broken in that they use alloca() but don't
42  * declare it properly.  The following is the patented (just kidding!)
43  * #ifdef chud to fix the problem, courtesy of Francois Pinard.
44  */
45 #ifdef YYBISON
46 /* AIX requires this to be the first thing in the file.  What a piece.  */
47 # ifdef _AIX
48  #pragma alloca
49 # endif
50 #endif
51
52 #include "flexdef.h"
53
54 /* The remainder of the alloca() cruft has to come after including flexdef.h,
55  * so HAVE_ALLOCA_H is (possibly) defined.
56  */
57 #ifdef YYBISON
58 # ifdef __GNUC__
59 #  ifndef alloca
60 #   define alloca __builtin_alloca
61 #  endif
62 # else
63 #  if HAVE_ALLOCA_H
64 #   include <alloca.h>
65 #  else
66 #   ifdef __hpux
67 void *alloca ();
68 #   else
69 #    ifdef __TURBOC__
70 #     include <malloc.h>
71 #    else
72 char *alloca ();
73 #    endif
74 #   endif
75 #  endif
76 # endif
77 #endif
78
79 /* Bletch, ^^^^ that was ugly! */
80
81
82 int pat, scnum, eps, headcnt, trailcnt, anyccl, lastchar, i, rulelen;
83 int trlcontxt, xcluflg, currccl, cclsorted, varlength, variable_trail_rule;
84
85 int *scon_stk;
86 int scon_stk_ptr;
87
88 static int madeany = false;  /* whether we've made the '.' character class */
89 int previous_continued_action;  /* whether the previous rule's action was '|' */
90
91 /* Expand a POSIX character class expression. */
92 #define CCL_EXPR(func) \
93         { \
94         int c; \
95         for ( c = 0; c < csize; ++c ) \
96                 if ( isascii(c) && func(c) ) \
97                         ccladd( currccl, c ); \
98         }
99
100 /* While POSIX defines isblank(), it's not ANSI C. */
101 #define IS_BLANK(c) ((c) == ' ' || (c) == '\t')
102
103 /* On some over-ambitious machines, such as DEC Alpha's, the default
104  * token type is "long" instead of "int"; this leads to problems with
105  * declaring yylval in flexdef.h.  But so far, all the yacc's I've seen
106  * wrap their definitions of YYSTYPE with "#ifndef YYSTYPE"'s, so the
107  * following should ensure that the default token type is "int".
108  */
109 #define YYSTYPE int
110
111 %}
112
113 %%
114 goal            :  initlex sect1 sect1end sect2 initforrule
115                         { /* add default rule */
116                         int def_rule;
117
118                         pat = cclinit();
119                         cclnegate( pat );
120
121                         def_rule = mkstate( -pat );
122
123                         /* Remember the number of the default rule so we
124                          * don't generate "can't match" warnings for it.
125                          */
126                         default_rule = num_rules;
127
128                         finish_rule( def_rule, false, 0, 0 );
129
130                         for ( i = 1; i <= lastsc; ++i )
131                                 scset[i] = mkbranch( scset[i], def_rule );
132
133                         if ( spprdflt )
134                                 add_action(
135                                 "YY_FATAL_ERROR( \"flex scanner jammed\" )" );
136                         else
137                                 add_action( "ECHO" );
138
139                         add_action( ";\n\tYY_BREAK\n" );
140                         }
141                 ;
142
143 initlex         :
144                         { /* initialize for processing rules */
145
146                         /* Create default DFA start condition. */
147                         scinstal( "INITIAL", false );
148                         }
149                 ;
150
151 sect1           :  sect1 startconddecl namelist1
152                 |  sect1 options
153                 |
154                 |  error
155                         { synerr( "unknown error processing section 1" ); }
156                 ;
157
158 sect1end        :  SECTEND
159                         {
160                         check_options();
161                         scon_stk = allocate_integer_array( lastsc + 1 );
162                         scon_stk_ptr = 0;
163                         }
164                 ;
165
166 startconddecl   :  SCDECL
167                         { xcluflg = false; }
168
169                 |  XSCDECL
170                         { xcluflg = true; }
171                 ;
172
173 namelist1       :  namelist1 NAME
174                         { scinstal( nmstr, xcluflg ); }
175
176                 |  NAME
177                         { scinstal( nmstr, xcluflg ); }
178
179                 |  error
180                         { synerr( "bad start condition list" ); }
181                 ;
182
183 options         :  OPTION_OP optionlist
184                 ;
185
186 optionlist      :  optionlist option
187                 |
188                 ;
189
190 option          :  OPT_OUTFILE '=' NAME
191                         {
192                         outfilename = copy_string( nmstr );
193                         did_outfilename = 1;
194                         }
195                 |  OPT_PREFIX '=' NAME
196                         { prefix = copy_string( nmstr ); }
197                 |  OPT_YYCLASS '=' NAME
198                         { yyclass = copy_string( nmstr ); }
199                 ;
200
201 sect2           :  sect2 scon initforrule flexrule '\n'
202                         { scon_stk_ptr = $2; }
203                 |  sect2 scon '{' sect2 '}'
204                         { scon_stk_ptr = $2; }
205                 |
206                 ;
207
208 initforrule     :
209                         {
210                         /* Initialize for a parse of one rule. */
211                         trlcontxt = variable_trail_rule = varlength = false;
212                         trailcnt = headcnt = rulelen = 0;
213                         current_state_type = STATE_NORMAL;
214                         previous_continued_action = continued_action;
215                         in_rule = true;
216
217                         new_rule();
218                         }
219                 ;
220
221 flexrule        :  '^' rule
222                         {
223                         pat = $2;
224                         finish_rule( pat, variable_trail_rule,
225                                 headcnt, trailcnt );
226
227                         if ( scon_stk_ptr > 0 )
228                                 {
229                                 for ( i = 1; i <= scon_stk_ptr; ++i )
230                                         scbol[scon_stk[i]] =
231                                                 mkbranch( scbol[scon_stk[i]],
232                                                                 pat );
233                                 }
234
235                         else
236                                 {
237                                 /* Add to all non-exclusive start conditions,
238                                  * including the default (0) start condition.
239                                  */
240
241                                 for ( i = 1; i <= lastsc; ++i )
242                                         if ( ! scxclu[i] )
243                                                 scbol[i] = mkbranch( scbol[i],
244                                                                         pat );
245                                 }
246
247                         if ( ! bol_needed )
248                                 {
249                                 bol_needed = true;
250
251                                 if ( performance_report > 1 )
252                                         pinpoint_message(
253                         "'^' operator results in sub-optimal performance" );
254                                 }
255                         }
256
257                 |  rule
258                         {
259                         pat = $1;
260                         finish_rule( pat, variable_trail_rule,
261                                 headcnt, trailcnt );
262
263                         if ( scon_stk_ptr > 0 )
264                                 {
265                                 for ( i = 1; i <= scon_stk_ptr; ++i )
266                                         scset[scon_stk[i]] =
267                                                 mkbranch( scset[scon_stk[i]],
268                                                                 pat );
269                                 }
270
271                         else
272                                 {
273                                 for ( i = 1; i <= lastsc; ++i )
274                                         if ( ! scxclu[i] )
275                                                 scset[i] =
276                                                         mkbranch( scset[i],
277                                                                 pat );
278                                 }
279                         }
280
281                 |  EOF_OP
282                         {
283                         if ( scon_stk_ptr > 0 )
284                                 build_eof_action();
285         
286                         else
287                                 {
288                                 /* This EOF applies to all start conditions
289                                  * which don't already have EOF actions.
290                                  */
291                                 for ( i = 1; i <= lastsc; ++i )
292                                         if ( ! sceof[i] )
293                                                 scon_stk[++scon_stk_ptr] = i;
294
295                                 if ( scon_stk_ptr == 0 )
296                                         warn(
297                         "all start conditions already have <<EOF>> rules" );
298
299                                 else
300                                         build_eof_action();
301                                 }
302                         }
303
304                 |  error
305                         { synerr( "unrecognized rule" ); }
306                 ;
307
308 scon_stk_ptr    :
309                         { $$ = scon_stk_ptr; }
310                 ;
311
312 scon            :  '<' scon_stk_ptr namelist2 '>'
313                         { $$ = $2; }
314
315                 |  '<' '*' '>'
316                         {
317                         $$ = scon_stk_ptr;
318
319                         for ( i = 1; i <= lastsc; ++i )
320                                 {
321                                 int j;
322
323                                 for ( j = 1; j <= scon_stk_ptr; ++j )
324                                         if ( scon_stk[j] == i )
325                                                 break;
326
327                                 if ( j > scon_stk_ptr )
328                                         scon_stk[++scon_stk_ptr] = i;
329                                 }
330                         }
331
332                 |
333                         { $$ = scon_stk_ptr; }
334                 ;
335
336 namelist2       :  namelist2 ',' sconname
337
338                 |  sconname
339
340                 |  error
341                         { synerr( "bad start condition list" ); }
342                 ;
343
344 sconname        :  NAME
345                         {
346                         if ( (scnum = sclookup( nmstr )) == 0 )
347                                 format_pinpoint_message(
348                                         "undeclared start condition %s",
349                                         nmstr );
350                         else
351                                 {
352                                 for ( i = 1; i <= scon_stk_ptr; ++i )
353                                         if ( scon_stk[i] == scnum )
354                                                 {
355                                                 format_warn(
356                                                         "<%s> specified twice",
357                                                         scname[scnum] );
358                                                 break;
359                                                 }
360
361                                 if ( i > scon_stk_ptr )
362                                         scon_stk[++scon_stk_ptr] = scnum;
363                                 }
364                         }
365                 ;
366
367 rule            :  re2 re
368                         {
369                         if ( transchar[lastst[$2]] != SYM_EPSILON )
370                                 /* Provide final transition \now/ so it
371                                  * will be marked as a trailing context
372                                  * state.
373                                  */
374                                 $2 = link_machines( $2,
375                                                 mkstate( SYM_EPSILON ) );
376
377                         mark_beginning_as_normal( $2 );
378                         current_state_type = STATE_NORMAL;
379
380                         if ( previous_continued_action )
381                                 {
382                                 /* We need to treat this as variable trailing
383                                  * context so that the backup does not happen
384                                  * in the action but before the action switch
385                                  * statement.  If the backup happens in the
386                                  * action, then the rules "falling into" this
387                                  * one's action will *also* do the backup,
388                                  * erroneously.
389                                  */
390                                 if ( ! varlength || headcnt != 0 )
391                                         warn(
392                 "trailing context made variable due to preceding '|' action" );
393
394                                 /* Mark as variable. */
395                                 varlength = true;
396                                 headcnt = 0;
397                                 }
398
399                         if ( lex_compat || (varlength && headcnt == 0) )
400                                 { /* variable trailing context rule */
401                                 /* Mark the first part of the rule as the
402                                  * accepting "head" part of a trailing
403                                  * context rule.
404                                  *
405                                  * By the way, we didn't do this at the
406                                  * beginning of this production because back
407                                  * then current_state_type was set up for a
408                                  * trail rule, and add_accept() can create
409                                  * a new state ...
410                                  */
411                                 add_accept( $1,
412                                         num_rules | YY_TRAILING_HEAD_MASK );
413                                 variable_trail_rule = true;
414                                 }
415                         
416                         else
417                                 trailcnt = rulelen;
418
419                         $$ = link_machines( $1, $2 );
420                         }
421
422                 |  re2 re '$'
423                         { synerr( "trailing context used twice" ); }
424
425                 |  re '$'
426                         {
427                         headcnt = 0;
428                         trailcnt = 1;
429                         rulelen = 1;
430                         varlength = false;
431
432                         current_state_type = STATE_TRAILING_CONTEXT;
433
434                         if ( trlcontxt )
435                                 {
436                                 synerr( "trailing context used twice" );
437                                 $$ = mkstate( SYM_EPSILON );
438                                 }
439
440                         else if ( previous_continued_action )
441                                 {
442                                 /* See the comment in the rule for "re2 re"
443                                  * above.
444                                  */
445                                 warn(
446                 "trailing context made variable due to preceding '|' action" );
447
448                                 varlength = true;
449                                 }
450
451                         if ( lex_compat || varlength )
452                                 {
453                                 /* Again, see the comment in the rule for
454                                  * "re2 re" above.
455                                  */
456                                 add_accept( $1,
457                                         num_rules | YY_TRAILING_HEAD_MASK );
458                                 variable_trail_rule = true;
459                                 }
460
461                         trlcontxt = true;
462
463                         eps = mkstate( SYM_EPSILON );
464                         $$ = link_machines( $1,
465                                 link_machines( eps, mkstate( '\n' ) ) );
466                         }
467
468                 |  re
469                         {
470                         $$ = $1;
471
472                         if ( trlcontxt )
473                                 {
474                                 if ( lex_compat || (varlength && headcnt == 0) )
475                                         /* Both head and trail are
476                                          * variable-length.
477                                          */
478                                         variable_trail_rule = true;
479                                 else
480                                         trailcnt = rulelen;
481                                 }
482                         }
483                 ;
484
485
486 re              :  re '|' series
487                         {
488                         varlength = true;
489                         $$ = mkor( $1, $3 );
490                         }
491
492                 |  series
493                         { $$ = $1; }
494                 ;
495
496
497 re2             :  re '/'
498                         {
499                         /* This rule is written separately so the
500                          * reduction will occur before the trailing
501                          * series is parsed.
502                          */
503
504                         if ( trlcontxt )
505                                 synerr( "trailing context used twice" );
506                         else
507                                 trlcontxt = true;
508
509                         if ( varlength )
510                                 /* We hope the trailing context is
511                                  * fixed-length.
512                                  */
513                                 varlength = false;
514                         else
515                                 headcnt = rulelen;
516
517                         rulelen = 0;
518
519                         current_state_type = STATE_TRAILING_CONTEXT;
520                         $$ = $1;
521                         }
522                 ;
523
524 series          :  series singleton
525                         {
526                         /* This is where concatenation of adjacent patterns
527                          * gets done.
528                          */
529                         $$ = link_machines( $1, $2 );
530                         }
531
532                 |  singleton
533                         { $$ = $1; }
534                 ;
535
536 singleton       :  singleton '*'
537                         {
538                         varlength = true;
539
540                         $$ = mkclos( $1 );
541                         }
542
543                 |  singleton '+'
544                         {
545                         varlength = true;
546                         $$ = mkposcl( $1 );
547                         }
548
549                 |  singleton '?'
550                         {
551                         varlength = true;
552                         $$ = mkopt( $1 );
553                         }
554
555                 |  singleton '{' NUMBER ',' NUMBER '}'
556                         {
557                         varlength = true;
558
559                         if ( $3 > $5 || $3 < 0 )
560                                 {
561                                 synerr( "bad iteration values" );
562                                 $$ = $1;
563                                 }
564                         else
565                                 {
566                                 if ( $3 == 0 )
567                                         {
568                                         if ( $5 <= 0 )
569                                                 {
570                                                 synerr(
571                                                 "bad iteration values" );
572                                                 $$ = $1;
573                                                 }
574                                         else
575                                                 $$ = mkopt(
576                                                         mkrep( $1, 1, $5 ) );
577                                         }
578                                 else
579                                         $$ = mkrep( $1, $3, $5 );
580                                 }
581                         }
582
583                 |  singleton '{' NUMBER ',' '}'
584                         {
585                         varlength = true;
586
587                         if ( $3 <= 0 )
588                                 {
589                                 synerr( "iteration value must be positive" );
590                                 $$ = $1;
591                                 }
592
593                         else
594                                 $$ = mkrep( $1, $3, INFINITY );
595                         }
596
597                 |  singleton '{' NUMBER '}'
598                         {
599                         /* The singleton could be something like "(foo)",
600                          * in which case we have no idea what its length
601                          * is, so we punt here.
602                          */
603                         varlength = true;
604
605                         if ( $3 <= 0 )
606                                 {
607                                 synerr( "iteration value must be positive" );
608                                 $$ = $1;
609                                 }
610
611                         else
612                                 $$ = link_machines( $1,
613                                                 copysingl( $1, $3 - 1 ) );
614                         }
615
616                 |  '.'
617                         {
618                         if ( ! madeany )
619                                 {
620                                 /* Create the '.' character class. */
621                                 anyccl = cclinit();
622                                 ccladd( anyccl, '\n' );
623                                 cclnegate( anyccl );
624
625                                 if ( useecs )
626                                         mkeccl( ccltbl + cclmap[anyccl],
627                                                 ccllen[anyccl], nextecm,
628                                                 ecgroup, csize, csize );
629
630                                 madeany = true;
631                                 }
632
633                         ++rulelen;
634
635                         $$ = mkstate( -anyccl );
636                         }
637
638                 |  fullccl
639                         {
640                         if ( ! cclsorted )
641                                 /* Sort characters for fast searching.  We
642                                  * use a shell sort since this list could
643                                  * be large.
644                                  */
645                                 cshell( ccltbl + cclmap[$1], ccllen[$1], true );
646
647                         if ( useecs )
648                                 mkeccl( ccltbl + cclmap[$1], ccllen[$1],
649                                         nextecm, ecgroup, csize, csize );
650
651                         ++rulelen;
652
653                         $$ = mkstate( -$1 );
654                         }
655
656                 |  PREVCCL
657                         {
658                         ++rulelen;
659
660                         $$ = mkstate( -$1 );
661                         }
662
663                 |  '"' string '"'
664                         { $$ = $2; }
665
666                 |  '(' re ')'
667                         { $$ = $2; }
668
669                 |  CHAR
670                         {
671                         ++rulelen;
672
673                         if ( caseins && $1 >= 'A' && $1 <= 'Z' )
674                                 $1 = clower( $1 );
675
676                         $$ = mkstate( $1 );
677                         }
678                 ;
679
680 fullccl         :  '[' ccl ']'
681                         { $$ = $2; }
682
683                 |  '[' '^' ccl ']'
684                         {
685                         cclnegate( $3 );
686                         $$ = $3;
687                         }
688                 ;
689
690 ccl             :  ccl CHAR '-' CHAR
691                         {
692                         if ( caseins )
693                                 {
694                                 if ( $2 >= 'A' && $2 <= 'Z' )
695                                         $2 = clower( $2 );
696                                 if ( $4 >= 'A' && $4 <= 'Z' )
697                                         $4 = clower( $4 );
698                                 }
699
700                         if ( $2 > $4 )
701                                 synerr( "negative range in character class" );
702
703                         else
704                                 {
705                                 for ( i = $2; i <= $4; ++i )
706                                         ccladd( $1, i );
707
708                                 /* Keep track if this ccl is staying in
709                                  * alphabetical order.
710                                  */
711                                 cclsorted = cclsorted && ($2 > lastchar);
712                                 lastchar = $4;
713                                 }
714
715                         $$ = $1;
716                         }
717
718                 |  ccl CHAR
719                         {
720                         if ( caseins && $2 >= 'A' && $2 <= 'Z' )
721                                 $2 = clower( $2 );
722
723                         ccladd( $1, $2 );
724                         cclsorted = cclsorted && ($2 > lastchar);
725                         lastchar = $2;
726                         $$ = $1;
727                         }
728
729                 |  ccl ccl_expr
730                         {
731                         /* Too hard to properly maintain cclsorted. */
732                         cclsorted = false;
733                         $$ = $1;
734                         }
735
736                 |
737                         {
738                         cclsorted = true;
739                         lastchar = 0;
740                         currccl = $$ = cclinit();
741                         }
742                 ;
743
744 ccl_expr:          CCE_ALNUM    { CCL_EXPR(isalnum) }
745                 |  CCE_ALPHA    { CCL_EXPR(isalpha) }
746                 |  CCE_BLANK    { CCL_EXPR(IS_BLANK) }
747                 |  CCE_CNTRL    { CCL_EXPR(iscntrl) }
748                 |  CCE_DIGIT    { CCL_EXPR(isdigit) }
749                 |  CCE_GRAPH    { CCL_EXPR(isgraph) }
750                 |  CCE_LOWER    { CCL_EXPR(islower) }
751                 |  CCE_PRINT    { CCL_EXPR(isprint) }
752                 |  CCE_PUNCT    { CCL_EXPR(ispunct) }
753                 |  CCE_SPACE    { CCL_EXPR(isspace) }
754                 |  CCE_UPPER    {
755                                 if ( caseins )
756                                         CCL_EXPR(islower)
757                                 else
758                                         CCL_EXPR(isupper)
759                                 }
760                 |  CCE_XDIGIT   { CCL_EXPR(isxdigit) }
761                 ;
762                 
763 string          :  string CHAR
764                         {
765                         if ( caseins && $2 >= 'A' && $2 <= 'Z' )
766                                 $2 = clower( $2 );
767
768                         ++rulelen;
769
770                         $$ = link_machines( $1, mkstate( $2 ) );
771                         }
772
773                 |
774                         { $$ = mkstate( SYM_EPSILON ); }
775                 ;
776
777 %%
778
779
780 /* build_eof_action - build the "<<EOF>>" action for the active start
781  *                    conditions
782  */
783
784 void build_eof_action()
785         {
786         register int i;
787         char action_text[MAXLINE];
788
789         for ( i = 1; i <= scon_stk_ptr; ++i )
790                 {
791                 if ( sceof[scon_stk[i]] )
792                         format_pinpoint_message(
793                                 "multiple <<EOF>> rules for start condition %s",
794                                 scname[scon_stk[i]] );
795
796                 else
797                         {
798                         sceof[scon_stk[i]] = true;
799                         sprintf( action_text, "case YY_STATE_EOF(%s):\n",
800                                 scname[scon_stk[i]] );
801                         add_action( action_text );
802                         }
803                 }
804
805         line_directive_out( (FILE *) 0, 1 );
806
807         /* This isn't a normal rule after all - don't count it as
808          * such, so we don't have any holes in the rule numbering
809          * (which make generating "rule can never match" warnings
810          * more difficult.
811          */
812         --num_rules;
813         ++num_eof_rules;
814         }
815
816
817 /* format_synerr - write out formatted syntax error */
818
819 void format_synerr( msg, arg )
820 char msg[], arg[];
821         {
822         char errmsg[MAXLINE];
823
824         (void) sprintf( errmsg, msg, arg );
825         synerr( errmsg );
826         }
827
828
829 /* synerr - report a syntax error */
830
831 void synerr( str )
832 char str[];
833         {
834         syntaxerror = true;
835         pinpoint_message( str );
836         }
837
838
839 /* format_warn - write out formatted warning */
840
841 void format_warn( msg, arg )
842 char msg[], arg[];
843         {
844         char warn_msg[MAXLINE];
845
846         (void) sprintf( warn_msg, msg, arg );
847         warn( warn_msg );
848         }
849
850
851 /* warn - report a warning, unless -w was given */
852
853 void warn( str )
854 char str[];
855         {
856         line_warning( str, linenum );
857         }
858
859 /* format_pinpoint_message - write out a message formatted with one string,
860  *                           pinpointing its location
861  */
862
863 void format_pinpoint_message( msg, arg )
864 char msg[], arg[];
865         {
866         char errmsg[MAXLINE];
867
868         (void) sprintf( errmsg, msg, arg );
869         pinpoint_message( errmsg );
870         }
871
872
873 /* pinpoint_message - write out a message, pinpointing its location */
874
875 void pinpoint_message( str )
876 char str[];
877         {
878         line_pinpoint( str, linenum );
879         }
880
881
882 /* line_warning - report a warning at a given line, unless -w was given */
883
884 void line_warning( str, line )
885 char str[];
886 int line;
887         {
888         char warning[MAXLINE];
889
890         if ( ! nowarn )
891                 {
892                 sprintf( warning, "warning, %s", str );
893                 line_pinpoint( warning, line );
894                 }
895         }
896
897
898 /* line_pinpoint - write out a message, pinpointing it at the given line */
899
900 void line_pinpoint( str, line )
901 char str[];
902 int line;
903         {
904         fprintf( stderr, "\"%s\", line %d: %s\n", infilename, line, str );
905         }
906
907
908 /* yyerror - eat up an error message from the parser;
909  *           currently, messages are ignore
910  */
911
912 void yyerror( msg )
913 char msg[];
914         {
915         }