1 /** \file
2  * Copyright (c) 1999, 2000 Carlo Wood.  All rights reserved.<br>
3  * Copyright (c) 1994 Joseph Arceneaux.  All rights reserved.<br>
4  * Copyright (c) 1985 Sun Microsystems, Inc. <br>
5  * Copyright (c) 1980 The Regents of the University of California.<br>
6  * Copyright (c) 1976 Board of Trustees of the University of Illinois. All rights reserved.<br>
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * - 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * - 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * - 3. Neither the name of the University nor the names of its contributors
17  *    may be used to endorse or promote products derived from this software
18  *    without specific prior written permission.<br>
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30  * SUCH DAMAGE.
31  *
32  * This program is free software; you can redistribute it and/or
33  * modify it under the terms of the GNU General Public License
34  * as published by the Free Software Foundation; either version 3
35  * of the License, or (at your option) any later version.
36  *
37  * This program is distributed in the hope that it will be useful,
38  * but WITHOUT ANY WARRANTY; without even the implied warranty of
39  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
40  * GNU General Public License for more details.
41  *
42  * You should have received a copy of the GNU General Public License
43  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
44  *
45  */
46 
47 #include "sys.h"
48 #include "indent.h"
49 #include "parse.h"
50 #include "globs.h"
51 
52 RCSTAG_CC ("$Id$");
53 
54 parser_state_ty *parser_state_tos = NULL;
55 
56 #define INITIAL_BUFFER_SIZE 1000
57 #define INITIAL_STACK_SIZE 2
58 
59 /**
60  *
61  */
62 
init_parser(void)63 extern void init_parser(void)
64 {
65     parser_state_tos = xmalloc(sizeof (parser_state_ty));
66 
67     /* GDB_HOOK_parser_state_tos */
68     parser_state_tos->p_stack_size  = INITIAL_STACK_SIZE;
69     parser_state_tos->p_stack       = xmalloc(INITIAL_STACK_SIZE * sizeof (codes_ty));
70     parser_state_tos->il            = xmalloc(INITIAL_STACK_SIZE * sizeof (int));
71     parser_state_tos->cstk          = xmalloc(INITIAL_STACK_SIZE * sizeof (int));
72     parser_state_tos->paren_indents_size = 8;
73     parser_state_tos->paren_indents = xmalloc(parser_state_tos->paren_indents_size * sizeof (short));
74 
75     /* Although these are supposed to grow if we reach the end,
76      * I can find no place in the code which does this. */
77     combuf = xmalloc(INITIAL_BUFFER_SIZE);
78     labbuf = xmalloc(INITIAL_BUFFER_SIZE);
79     codebuf = xmalloc(INITIAL_BUFFER_SIZE);
80 
81     save_com.size = INITIAL_BUFFER_SIZE;
82     save_com.end = save_com.ptr = xmalloc(save_com.size);
83     save_com.len = save_com.column = 0;
84 
85     di_stack_alloc = 2;
86     di_stack = xmalloc(di_stack_alloc * sizeof (*di_stack));
87 }
88 
89 /**
90  * Free all memory allocated in init_parser().
91  */
uninit_parser(void)92 extern void uninit_parser(void)
93 {
94     if (!parser_state_tos)
95     {
96         return;
97     }
98 
99     xfree(parser_state_tos->p_stack);
100     xfree(parser_state_tos->il);
101     xfree(parser_state_tos->cstk);
102     xfree(parser_state_tos->paren_indents);
103     xfree(parser_state_tos);
104     xfree(save_com.ptr);
105     xfree(combuf);
106     xfree(labbuf);
107     xfree(codebuf);
108     xfree(di_stack);
109     parser_state_tos = NULL;
110 }
111 
112 /**
113  *
114  */
115 
reset_parser(void)116 extern void reset_parser(void)
117 {
118     parser_state_tos->next             = 0;
119     parser_state_tos->tos              = 0;
120     parser_state_tos->p_stack[0]       = stmt;    /*!< this is the parser's stack */
121     parser_state_tos->last_nl          = true;    /*!< this is true if the last thing
122                                                    * scanned was a newline */
123     parser_state_tos->last_token       = start_token;
124     parser_state_tos->last_saw_nl      = false;
125     parser_state_tos->broken_at_non_nl = false;
126     parser_state_tos->box_com          = false;
127     parser_state_tos->cast_mask        = 0;
128     parser_state_tos->noncast_mask     = 0;
129     parser_state_tos->sizeof_mask      = 0;
130     parser_state_tos->block_init       = 0;
131     parser_state_tos->block_init_level = 0;
132     parser_state_tos->col_1            = false;
133     parser_state_tos->com_col          = 0;
134     parser_state_tos->dec_nest         = 0;
135     parser_state_tos->i_l_follow       = 0;
136     parser_state_tos->ind_level        = 0;
137     parser_state_tos->last_u_d         = false;
138     parser_state_tos->p_l_follow       = 0;
139     parser_state_tos->paren_level      = 0;
140     parser_state_tos->paren_depth      = 0;
141     parser_state_tos->search_brace     = false;
142     parser_state_tos->use_ff           = false;
143     parser_state_tos->its_a_keyword    = false;
144     parser_state_tos->sizeof_keyword   = false;
145     parser_state_tos->in_parameter_declaration = false;
146     parser_state_tos->just_saw_decl    = 0;
147     parser_state_tos->in_decl          = false;
148     parser_state_tos->decl_on_line     = false;
149     parser_state_tos->in_or_st         = 0;
150     parser_state_tos->want_blank       = false;
151     parser_state_tos->in_stmt          = false;
152     parser_state_tos->ind_stmt         = false;
153     parser_state_tos->procname         = "\0";
154     parser_state_tos->procname_end     = "\0";
155     parser_state_tos->classname        = "\0";
156     parser_state_tos->classname_end    = "\0";
157     parser_state_tos->pcase            = false;
158     parser_state_tos->dec_nest         = 0;
159     parser_state_tos->can_break        = bb_none;
160     parser_state_tos->saw_double_colon = false;
161     parser_state_tos->is_func_ptr_decl = false;
162 
163     parser_state_tos->il[0]            = 0;
164     parser_state_tos->cstk[0]          = 0;
165 
166     save_com.len = save_com.column = 0;
167 
168     di_stack[parser_state_tos->dec_nest] = 0;
169 
170     l_com = combuf + INITIAL_BUFFER_SIZE - 5;
171     l_lab = labbuf + INITIAL_BUFFER_SIZE - 5;
172     l_code = codebuf + INITIAL_BUFFER_SIZE - 5;
173     combuf[0] = codebuf[0] = labbuf[0] = ' ';
174     combuf[1] = codebuf[1] = labbuf[1] = '\0';
175 
176     else_or_endif = false;
177     s_lab = e_lab = labbuf + 1;
178     s_code = e_code = codebuf + 1;
179     s_com = e_com = combuf + 1;
180 
181     line_no = 1;
182     had_eof = false;
183     break_comma = false;
184     bp_save = 0;
185     be_save = 0;
186 
187     if (settings.tabsize <= 0)
188     {
189         settings.tabsize = 1;
190     }
191 
192     prefix_blankline_requested = 0;
193 }
194 
195 /**
196  * like ++parser_state_tos->tos but checks for stack overflow and extends
197  * stack if necessary.
198   */
199 
inc_pstack(void)200 extern int inc_pstack(void)
201 {
202     if (++parser_state_tos->tos >= parser_state_tos->p_stack_size)
203     {
204         parser_state_tos->p_stack_size *= 2;
205         parser_state_tos->p_stack =
206                 xrealloc(parser_state_tos->p_stack,
207                          parser_state_tos->p_stack_size * sizeof(codes_ty));
208         parser_state_tos->il =
209                 xrealloc(parser_state_tos->il,
210                           parser_state_tos->p_stack_size * sizeof(int));
211         parser_state_tos->cstk =
212                 xrealloc(parser_state_tos->cstk,
213                          parser_state_tos->p_stack_size * sizeof(int));
214     }
215 
216     parser_state_tos->cstk[parser_state_tos->tos] = parser_state_tos->cstk[parser_state_tos->tos - 1];
217     return parser_state_tos->tos;
218 }
219 
220 #ifdef DEBUG
221 /**
222  *
223  */
224 
225 static char **debug_symbol_strings;
226 
227 /**
228  *
229  */
230 
debug_init(void)231 extern void debug_init(void)
232 {
233     int size = ((int) number_of_codes) * sizeof (char *);
234 
235     debug_symbol_strings = xmalloc (size);
236 
237     debug_symbol_strings[code_eof]      = "code_eof";
238     debug_symbol_strings[newline]       = "newline";
239     debug_symbol_strings[lparen]        = "lparen";
240     debug_symbol_strings[rparen]        = "rparen";
241     debug_symbol_strings[start_token]   = "start_token";
242     debug_symbol_strings[unary_op]      = "unary_op";
243     debug_symbol_strings[binary_op]     = "binary_op";
244     debug_symbol_strings[postop]        = "postop";
245     debug_symbol_strings[question]      = "question";
246     debug_symbol_strings[casestmt]      = "casestmt";
247     debug_symbol_strings[colon]         = "colon";
248     debug_symbol_strings[doublecolon]   = "doublecolon";
249     debug_symbol_strings[semicolon]     = "semicolon";
250     debug_symbol_strings[lbrace]        = "lbrace";
251     debug_symbol_strings[rbrace]        = "rbrace";
252     debug_symbol_strings[ident]         = "ident";
253     debug_symbol_strings[overloaded]    = "overloaded";
254     debug_symbol_strings[cpp_operator]  = "cpp_operator";
255     debug_symbol_strings[comma]         = "comma";
256     debug_symbol_strings[comment]       = "comment";
257     debug_symbol_strings[cplus_comment] = "cplus_comment";
258     debug_symbol_strings[swstmt]        = "swstmt";
259     debug_symbol_strings[preesc]        = "preesc";
260     debug_symbol_strings[form_feed]     = "form_feed";
261     debug_symbol_strings[decl]          = "decl";
262     debug_symbol_strings[sp_paren]      = "sp_paren";
263     debug_symbol_strings[sp_nparen]     = "sp_nparen";
264     debug_symbol_strings[sp_else]       = "sp_else";
265     debug_symbol_strings[ifstmt]        = "ifstmt";
266     debug_symbol_strings[elseifstmt]    = "elseifstmt";
267     debug_symbol_strings[whilestmt]     = "whilestmt";
268     debug_symbol_strings[forstmt]       = "forstmt";
269     debug_symbol_strings[stmt]          = "stmt";
270     debug_symbol_strings[stmtl]         = "stmtl";
271     debug_symbol_strings[elselit]       = "elselit";
272     debug_symbol_strings[dolit]         = "dolit";
273     debug_symbol_strings[dohead]        = "dohead";
274     debug_symbol_strings[dostmt]        = "dostmt";
275     debug_symbol_strings[ifhead]        = "ifhead";
276     debug_symbol_strings[elsehead]      = "elsehead";
277     debug_symbol_strings[struct_delim]  = "struct_delim";
278     debug_symbol_strings[attribute]     = "attribute";
279 }
280 
281 #endif
282 
283 /**
284  *
285  */
286 
parse(codes_ty tk)287 extern exit_values_ty parse (
288    codes_ty tk)               /*!< the code for the construct scanned */
289 {
290     int i;
291 
292 #ifdef DEBUG
293     if (debug)
294     {
295         if (tk >= code_eof && tk < number_of_codes)
296         {
297             printf ("Parse: %s\n", debug_symbol_strings[tk]);
298         }
299         else
300         {
301             printf ("Parse: Unknown code: %d for %s\n", (int) tk, token ? token : "NULL");
302         }
303     }
304 #endif
305 
306     while ((parser_state_tos->p_stack[parser_state_tos->tos] == ifhead) &&
307            (tk != elselit))
308     {
309         /* true if we have an if without an else */
310 
311         /* apply the if(..) stmt ::= stmt reduction */
312 
313         parser_state_tos->p_stack[parser_state_tos->tos] = stmt;
314         reduce ();              /* see if this allows any reduction */
315     }
316 
317 
318     switch (tk)
319     {
320         /* go on and figure out what to do with the input */
321 
322         case decl:
323             /* scanned a declaration word */
324             parser_state_tos->search_brace = settings.braces_on_struct_decl_line;
325 
326             /* indicate that following brace should be on same line */
327 
328             if ((parser_state_tos->p_stack[parser_state_tos->tos] != decl) &&
329                 (parser_state_tos->block_init == 0))
330             {
331                 /* only put one declaration onto stack */
332 
333                 break_comma = true;     /* while in declaration, newline should be
334                                          * forced after comma */
335                 inc_pstack ();
336                 parser_state_tos->p_stack[parser_state_tos->tos] = decl;
337                 parser_state_tos->il[parser_state_tos->tos] = parser_state_tos->i_l_follow;
338 
339                 if (settings.ljust_decl)
340                 {                       /* only do if we want left justified
341                                          * declarations */
342                     parser_state_tos->ind_level = 0;
343                     for (i = parser_state_tos->tos - 1; i > 0; --i)
344                     {
345                         if (parser_state_tos->p_stack[i] == decl)
346                         {
347                             /* indentation is number of declaration levels deep we are
348                              * times spaces per level */
349                             parser_state_tos->ind_level += settings.ind_size;
350                         }
351                     }
352 
353                     parser_state_tos->i_l_follow = parser_state_tos->ind_level;
354                 }
355             }
356             break;
357 
358         case ifstmt:            /* scanned if (...) */
359             if (parser_state_tos->p_stack[parser_state_tos->tos] == elsehead)
360             {
361                 parser_state_tos->i_l_follow = parser_state_tos->il[parser_state_tos->tos];
362             }
363             /* falls through */
364 
365         case dolit:             /* 'do' */
366         case forstmt:           /* for (...) */
367         case casestmt:          /* case n: */
368             inc_pstack ();
369             parser_state_tos->p_stack[parser_state_tos->tos] = tk;
370             parser_state_tos->ind_level                 = parser_state_tos->i_l_follow;
371             parser_state_tos->il[parser_state_tos->tos] = parser_state_tos->ind_level;
372 
373             if (tk != casestmt)
374             {
375                 parser_state_tos->i_l_follow += settings.ind_size;       /* subsequent statements
376                                                                  * should be indented */
377             }
378 
379             parser_state_tos->search_brace = settings.btype_2;
380             break;
381 
382         case lbrace:            /* scanned { */
383             break_comma = false;        /* don't break comma in an initial list */
384             if (parser_state_tos->p_stack[parser_state_tos->tos] == stmt
385                 || parser_state_tos->p_stack[parser_state_tos->tos] == stmtl)
386             {
387                 /* it is a random, isolated stmt group or a declaration */
388                 parser_state_tos->i_l_follow += settings.ind_size;
389             }
390             else if (parser_state_tos->p_stack[parser_state_tos->tos] == decl)
391             {
392                 parser_state_tos->i_l_follow += settings.ind_size;
393 
394                 if ( ( (parser_state_tos->last_rw == rw_struct_like) ||
395                        (parser_state_tos->last_rw == rw_enum)) &&
396                      ( (parser_state_tos->block_init != 1) ||
397                        (parser_state_tos->block_init_level == 0)) &&
398                      (parser_state_tos->last_token != rparen) &&
399                      (!settings.braces_on_struct_decl_line))
400                 {
401                     parser_state_tos->ind_level += settings.struct_brace_indent;
402                     parser_state_tos->i_l_follow += settings.struct_brace_indent;
403                 }
404             }
405             else if (parser_state_tos->p_stack[parser_state_tos->tos] == casestmt)
406             {
407                 parser_state_tos->ind_level += settings.case_brace_indent - settings.ind_size;
408                 parser_state_tos->i_l_follow += settings.case_brace_indent;
409             }
410             else
411             {
412                 /* It is a group as part of a while, for, etc. */
413 
414                 /* Only do this if there is nothing on the line */
415                 if (s_code == e_code)
416                 {
417                     parser_state_tos->ind_level -= settings.ind_size;
418                 }
419 
420                 /* For -bl formatting, indent by settings.brace_indent additional spaces
421                  * e.g. if (foo == bar) { <--> settings.brace_indent spaces (in this
422                  * example, 4) */
423 
424                 if (!settings.btype_2)
425                 {
426                     parser_state_tos->ind_level += settings.brace_indent;
427                     parser_state_tos->i_l_follow += settings.brace_indent;
428                 }
429 
430                 if (parser_state_tos->p_stack[parser_state_tos->tos] == swstmt)
431                 {
432                     parser_state_tos->i_l_follow += settings.case_indent;
433                 }
434             }
435 
436             inc_pstack ();
437             parser_state_tos->p_stack[parser_state_tos->tos] = lbrace;
438             parser_state_tos->il[parser_state_tos->tos] = parser_state_tos->ind_level;
439 
440             inc_pstack ();
441             parser_state_tos->p_stack[parser_state_tos->tos] = stmt;
442 
443             /* allow null stmt between braces */
444 
445             parser_state_tos->il[parser_state_tos->tos] = parser_state_tos->i_l_follow;
446             break;
447 
448         case whilestmt:         /* scanned while (...) */
449             if (parser_state_tos->p_stack[parser_state_tos->tos] == dohead)
450             {
451                 /* it is matched with do stmt */
452                 parser_state_tos->i_l_follow = parser_state_tos->il[parser_state_tos->tos];
453                 parser_state_tos->ind_level   = parser_state_tos->il[parser_state_tos->tos];
454                 inc_pstack ();
455                 parser_state_tos->p_stack[parser_state_tos->tos] = whilestmt;
456 
457                 parser_state_tos->ind_level                 = parser_state_tos->i_l_follow;
458                 parser_state_tos->il[parser_state_tos->tos] = parser_state_tos->i_l_follow;
459             }
460             else
461             {                   /* it is a while loop */
462                 inc_pstack ();
463                 parser_state_tos->p_stack[parser_state_tos->tos] = whilestmt;
464                 parser_state_tos->il[parser_state_tos->tos] = parser_state_tos->i_l_follow;
465                 parser_state_tos->i_l_follow += settings.ind_size;
466                 parser_state_tos->search_brace = settings.btype_2;
467             }
468 
469             break;
470 
471         case elselit:           /* scanned an else */
472 
473             if (parser_state_tos->p_stack[parser_state_tos->tos] != ifhead)
474             {
475                 ERROR(_("Unmatched 'else'"), NULL, NULL);
476             }
477             else
478             {
479                 /* indentation for else should be same as for if */
480                 parser_state_tos->ind_level = parser_state_tos->il[parser_state_tos->tos];
481 
482                 /* everything following should be in 1 level */
483                 parser_state_tos->i_l_follow = (parser_state_tos->ind_level + settings.ind_size);
484 
485                 parser_state_tos->p_stack[parser_state_tos->tos] = elsehead;
486                 /* remember if with else */
487                 parser_state_tos->search_brace = true;
488             }
489             break;
490 
491         case rbrace:            /* scanned a } */
492             /* stack should have <lbrace> <stmt> or <lbrace> <stmtl> */
493             if ((parser_state_tos->tos > 0) && (parser_state_tos->p_stack[parser_state_tos->tos - 1] == lbrace))
494             {
495                 parser_state_tos->i_l_follow = parser_state_tos->il[--parser_state_tos->tos];
496                 parser_state_tos->ind_level  = parser_state_tos->i_l_follow;
497                 parser_state_tos->p_stack[parser_state_tos->tos] = stmt;
498             }
499             else
500             {
501                 ERROR(_("Stmt nesting error."), NULL, NULL);
502             }
503             break;
504 
505         case swstmt:            /* had switch (...) */
506             inc_pstack ();
507             parser_state_tos->p_stack[parser_state_tos->tos] = swstmt;
508             parser_state_tos->cstk[parser_state_tos->tos] = settings.case_indent + parser_state_tos->i_l_follow;
509             if (!settings.btype_2)
510             {
511                 parser_state_tos->cstk[parser_state_tos->tos] += settings.brace_indent;
512             }
513 
514             /* save current case indent level */
515             parser_state_tos->il[parser_state_tos->tos] = parser_state_tos->i_l_follow;
516 
517             /* case labels should be one level down from switch, plus
518              * `settings.case_indent' if any.  Then, statements should be the `settings.ind_size'
519              * further. */
520 
521             parser_state_tos->i_l_follow += settings.ind_size;
522             parser_state_tos->search_brace = settings.btype_2;
523             break;
524 
525         case semicolon:         /* this indicates a simple stmt */
526             break_comma = false;        /* turn off flag to break after commas in a
527                                          * declaration */
528 
529             if (parser_state_tos->p_stack[parser_state_tos->tos] == dostmt)
530             {
531                 parser_state_tos->p_stack[parser_state_tos->tos] = stmt;
532             }
533             else
534             {
535                 inc_pstack ();
536                 parser_state_tos->p_stack[parser_state_tos->tos] = stmt;
537                 parser_state_tos->il[parser_state_tos->tos] = parser_state_tos->ind_level;
538             }
539             break;
540 
541             /* This is a fatal error which cases the program to exit. */
542         default:
543             fatal (_("Unknown code to parser"), 0);
544     }
545 
546     reduce ();                  /* see if any reduction can be done */
547 
548 #ifdef DEBUG
549     if (debug)
550     {
551         printf ("\n");
552 
553         printf ("ParseStack [%d]:\n", (int) parser_state_tos->p_stack_size);
554 
555         for (i = 1; i <= parser_state_tos->tos; ++i)
556         {
557             printf ("  stack[%d] =>  stack: %d [%-10s]  ind_level: %d\n",
558                     (int)i, (int)parser_state_tos->p_stack[i],
559                     debug_symbol_strings[parser_state_tos->p_stack[i]],
560                     (int)parser_state_tos->il[i]);
561         }
562 
563         printf ("\n");
564     }
565 #endif
566 
567     return total_success;
568 }
569 
570 /**
571  * NAME: reduce
572  *
573  * FUNCTION: Implements the reduce part of the parsing algorithm
574  *
575  * ALGORITHM: The following reductions are done.  Reductions are repeated until
576  *  no more are possible.
577  *
578  *  Old TOS              New TOS [stmt] [stmt]           [stmtl] [stmtl] [stmt]
579  *     [stmtl] do [stmt]                 dohead [dohead] [whilestmt]
580  *     [dostmt] if [stmt]                "ifstmt" switch [stmt]          [stmt]
581  *     decl [stmt]               [stmt] "ifelse" [stmt]          [stmt] for
582  *     [stmt]                    [stmt] while [stmt]                     [stmt]
583  *     "dostmt" while            [stmt]
584  *
585  *  On each reduction, parser_state_tos->i_l_follow (the indentation for the
586  *     following line) is set to the indentation level associated with the old
587  *     TOS.
588  *
589  *  PARAMETERS: None
590  *
591  *  RETURNS: Nothing
592  *
593  *  GLOBALS: parser_state_tos->cstk parser_state_tos->i_l_follow =
594  *     parser_state_tos->il parser_state_tos->p_stack = parser_state_tos->tos =
595  *
596  *  CALLS: None
597  *
598  *  CALLED BY: parse
599  *
600  *  HISTORY: initial coding         November 1976   D A Willcox of CAC
601  *
602  */
603 
reduce(void)604 extern void reduce(void)
605 {
606     int i;
607 
608     for (;;)
609     {
610         /* keep looping until there is nothing left to reduce */
611 
612         switch (parser_state_tos->p_stack[parser_state_tos->tos])
613         {
614             case stmt:
615                 if (parser_state_tos->tos == 0) return;
616                 switch (parser_state_tos->p_stack[parser_state_tos->tos - 1])
617                 {
618                     case stmt:
619                     case stmtl:
620                         /* stmtl stmt or stmt stmt */
621                         parser_state_tos->p_stack[--parser_state_tos->tos] = stmtl;
622                         break;
623 
624                     case dolit: /* [do] [stmt] */
625                         parser_state_tos->p_stack[--parser_state_tos->tos] = dohead;
626                         parser_state_tos->i_l_follow = parser_state_tos->il[parser_state_tos->tos];
627                         break;
628 
629                     case ifstmt:
630                         /* [if] [stmt] */
631                         parser_state_tos->p_stack[--parser_state_tos->tos] = ifhead;
632                         for (i = parser_state_tos->tos - 1;
633                              ( (parser_state_tos->p_stack[i] != stmt) &&
634                                (parser_state_tos->p_stack[i] != stmtl) &&
635                                (parser_state_tos->p_stack[i] != lbrace));
636                              --i)
637                         {
638                         }
639 
640                         parser_state_tos->i_l_follow = parser_state_tos->il[i];
641 
642                         /* for the time being, we will assume that there is no else on
643                          * this if, and set the indentation level accordingly. If an
644                          * else is scanned, it will be fixed up later */
645 
646                         break;
647 
648                     case swstmt:
649                         /* [switch] [stmt] */
650                     case decl:          /* finish of a declaration */
651                     case elsehead:
652                         /* [[if] [stmt] else] [stmt] */
653                     case forstmt:
654                         /* [for] [stmt] */
655                     case casestmt:
656                         /* [case n:] [stmt] */
657                     case whilestmt:
658                         /* [while] [stmt] */
659                         parser_state_tos->p_stack[--parser_state_tos->tos] = stmt;
660                         parser_state_tos->i_l_follow = parser_state_tos->il[parser_state_tos->tos];
661                         break;
662 
663                     default:            /* [anything else] [stmt] */
664                         return;
665 
666                 }                       /* end of section for [stmt] on top of stack */
667                 break;
668 
669             case whilestmt:     /* while (...) on top */
670                 if (parser_state_tos->p_stack[parser_state_tos->tos - 1] == dohead)
671                 {
672                     /* it is termination of a do while */
673                     parser_state_tos->p_stack[--parser_state_tos->tos] = dostmt;
674                     break;
675                 }
676                 else
677                     return;
678 
679             default:            /* anything else on top */
680                 return;
681 
682         }
683     }
684 }
685 
686 /**
687  * This kludge is called from main.  It is just like parse(semicolon) except
688  * that it does not clear break_comma.  Leaving break_comma alone is
689  * necessary to make sure that "int foo(), bar()" gets formatted correctly
690  * under -bc.  */
691 
parse_lparen_in_decl(void)692 extern void parse_lparen_in_decl(void)
693 {
694    inc_pstack ();
695    parser_state_tos->p_stack[parser_state_tos->tos] = stmt;
696    parser_state_tos->il[parser_state_tos->tos]      = parser_state_tos->ind_level;
697 
698    reduce ();
699 }
700