1 /* Copyright (c) 1985 Sun Microsystems, Inc. Copyright (c) 1980 The Regents
2    of the University of California. Copyright (c) 1976 Board of Trustees of
3    the University of Illinois. All rights reserved.
4 
5    Redistribution and use in source and binary forms are permitted provided
6    that the above copyright notice and this paragraph are duplicated in all
7    such forms and that any documentation, advertising materials, and other
8    materials related to such distribution and use acknowledge that the
9    software was developed by the University of California, Berkeley, the
10    University of Illinois, Urbana, and Sun Microsystems, Inc.  The name of
11    either University or Sun Microsystems may not be used to endorse or
12    promote products derived from this software without specific prior written
13    permission. THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14    IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES
15    OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */
16 
17 #include "sys.h"
18 #include "indent.h"
19 
20 struct parser_state *parser_state_tos;
21 
22 #define INITIAL_BUFFER_SIZE 1000
23 #define INITIAL_STACK_SIZE 2
24 
25 void
init_parser()26 init_parser ()
27 {
28   parser_state_tos
29     = (struct parser_state *) xmalloc (sizeof (struct parser_state));
30 
31   parser_state_tos->p_stack_size = INITIAL_STACK_SIZE;
32   parser_state_tos->p_stack
33     = (enum codes *) xmalloc (INITIAL_STACK_SIZE * sizeof (enum codes));
34   parser_state_tos->il = (int *) xmalloc (INITIAL_STACK_SIZE * sizeof (int));
35   parser_state_tos->cstk
36     = (int *) xmalloc (INITIAL_STACK_SIZE * sizeof (int));
37   parser_state_tos->paren_indents = (short *) xmalloc (sizeof (short));
38 
39   /* Although these are supposed to grow if we reach the end,
40      I can find no place in the code which does this. */
41   combuf = (char *) xmalloc (INITIAL_BUFFER_SIZE);
42   labbuf = (char *) xmalloc (INITIAL_BUFFER_SIZE);
43   codebuf = (char *) xmalloc (INITIAL_BUFFER_SIZE);
44 
45   save_com.size = INITIAL_BUFFER_SIZE;
46   save_com.end = save_com.ptr = xmalloc (save_com.size);
47 
48   di_stack_alloc = 2;
49   di_stack = (int *) xmalloc (di_stack_alloc * sizeof (*di_stack));
50 }
51 
52 void
reset_parser()53 reset_parser ()
54 {
55   parser_state_tos->next = 0;
56   parser_state_tos->tos = 0;
57   parser_state_tos->paren_indents_size = 1;
58   parser_state_tos->p_stack[0] = stmt;	/* this is the parser's stack */
59   parser_state_tos->last_nl = true;	/* this is true if the last thing
60 					   scanned was a newline */
61   parser_state_tos->last_token = semicolon;
62   parser_state_tos->box_com = false;
63   parser_state_tos->comment_delta = 0;
64   parser_state_tos->n_comment_delta = 0;
65   parser_state_tos->cast_mask = 0;
66   parser_state_tos->noncast_mask = 0;
67   parser_state_tos->sizeof_mask = 0;
68   parser_state_tos->block_init = false;
69   parser_state_tos->block_init_level = 0;
70   parser_state_tos->col_1 = false;
71   parser_state_tos->com_col = 0;
72   parser_state_tos->dec_nest = 0;
73   parser_state_tos->i_l_follow = 0;
74   parser_state_tos->ind_level = 0;
75   parser_state_tos->last_u_d = false;
76   parser_state_tos->p_l_follow = 0;
77   parser_state_tos->paren_level = 0;
78   parser_state_tos->paren_depth = 0;
79   parser_state_tos->search_brace = false;
80   parser_state_tos->use_ff = false;
81   parser_state_tos->its_a_keyword = false;
82   parser_state_tos->sizeof_keyword = false;
83   parser_state_tos->dumped_decl_indent = false;
84   parser_state_tos->in_parameter_declaration = false;
85   parser_state_tos->just_saw_decl = false;
86   parser_state_tos->in_decl = false;
87   parser_state_tos->decl_on_line = false;
88   parser_state_tos->in_or_st = false;
89   parser_state_tos->bl_line = true;
90   parser_state_tos->want_blank = false;
91   parser_state_tos->in_stmt = false;
92   parser_state_tos->ind_stmt = false;
93   parser_state_tos->procname = "\0";
94   parser_state_tos->procname_end = "\0";
95   parser_state_tos->pcase = false;
96   parser_state_tos->dec_nest = 0;
97   di_stack[parser_state_tos->dec_nest] = 0;
98 
99   l_com = combuf + INITIAL_BUFFER_SIZE - 5;
100   l_lab = labbuf + INITIAL_BUFFER_SIZE - 5;
101   l_code = codebuf + INITIAL_BUFFER_SIZE - 5;
102   combuf[0] = codebuf[0] = labbuf[0] = ' ';
103   combuf[1] = codebuf[1] = labbuf[1] = '\0';
104 
105   else_if = 1;
106   else_or_endif = false;
107   s_lab = e_lab = labbuf + 1;
108   s_code = e_code = codebuf + 1;
109   s_com = e_com = combuf + 1;
110 
111   line_no = 1;
112   had_eof = false;
113   break_comma = false;
114   bp_save = 0;
115   be_save = 0;
116 }
117 
118 /* like ++parser_state_tos->tos but checks for stack overflow and extends
119    stack if necessary.  */
120 static int
inc_pstack()121 inc_pstack ()
122 {
123   if (++parser_state_tos->tos >= parser_state_tos->p_stack_size)
124     {
125       parser_state_tos->p_stack_size *= 2;
126       parser_state_tos->p_stack = (enum codes *)
127 	xrealloc (parser_state_tos->p_stack,
128 		  parser_state_tos->p_stack_size * sizeof (enum codes));
129       parser_state_tos->il = (int *)
130 	xrealloc (parser_state_tos->il,
131 		  parser_state_tos->p_stack_size * sizeof (int));
132       parser_state_tos->cstk = (int *)
133 	xrealloc (parser_state_tos->cstk,
134 		  parser_state_tos->p_stack_size * sizeof (int));
135     }
136   return parser_state_tos->tos;
137 }
138 
139 #ifdef DEBUG
140 static char **debug_symbol_strings;
141 
142 void
debug_init()143 debug_init ()
144 {
145   int size = ((int) period + 4) * sizeof (char *);
146 
147   debug_symbol_strings = (char **) xmalloc (size);
148 
149   debug_symbol_strings[code_eof] = "code_eof";
150   debug_symbol_strings[newline] = "newline";
151   debug_symbol_strings[lparen] = "lparen";
152   debug_symbol_strings[rparen] = "rparen";
153   debug_symbol_strings[unary_op] = "unary_op";
154   debug_symbol_strings[binary_op] = "binary_op";
155   debug_symbol_strings[postop] = "postop";
156   debug_symbol_strings[question] = "question";
157   debug_symbol_strings[casestmt] = "casestmt";
158   debug_symbol_strings[colon] = "colon";
159   debug_symbol_strings[semicolon] = "semicolon";
160   debug_symbol_strings[lbrace] = "lbrace";
161   debug_symbol_strings[rbrace] = "rbrace";
162   debug_symbol_strings[ident] = "ident";
163   debug_symbol_strings[comma] = "comma";
164   debug_symbol_strings[comment] = "comment";
165   debug_symbol_strings[swstmt] = "swstmt";
166   debug_symbol_strings[preesc] = "preesc";
167   debug_symbol_strings[form_feed] = "form_feed";
168   debug_symbol_strings[decl] = "decl";
169   debug_symbol_strings[sp_paren] = "sp_paren";
170   debug_symbol_strings[sp_nparen] = "sp_nparen";
171   debug_symbol_strings[ifstmt] = "ifstmt";
172   debug_symbol_strings[whilestmt] = "whilestmt";
173   debug_symbol_strings[forstmt] = "forstmt";
174   debug_symbol_strings[stmt] = "stmt";
175   debug_symbol_strings[stmtl] = "stmtl";
176   debug_symbol_strings[elselit] = "elselit";
177   debug_symbol_strings[dolit] = "dolit";
178   debug_symbol_strings[dohead] = "dohead";
179   debug_symbol_strings[dostmt] = "dostmt";
180   debug_symbol_strings[ifhead] = "ifhead";
181   debug_symbol_strings[elsehead] = "elsehead";
182   debug_symbol_strings[period] = "period";
183 }
184 
185 #endif
186 
187 void
parse(tk)188 parse (tk)
189      enum codes tk;		/* the code for the construct scanned */
190 {
191   int i;
192 
193 #ifdef DEBUG
194   if (debug)
195     {
196       if (tk >= code_eof && tk <= period)
197 	printf ("Parse: %s\n", debug_symbol_strings[tk]);
198       else
199 	printf ("Parse: Unknown code: %d for %s\n",
200 		tk, token ? token : "NULL");
201     }
202 #endif
203 
204   while (parser_state_tos->p_stack[parser_state_tos->tos] == ifhead
205 	 && tk != elselit)
206     {
207       /* true if we have an if without an else */
208 
209       /* apply the if(..) stmt ::= stmt reduction */
210       parser_state_tos->p_stack[parser_state_tos->tos] = stmt;
211       reduce ();		/* see if this allows any reduction */
212     }
213 
214 
215   switch (tk)
216     {				/* go on and figure out what to do with the
217 				   input */
218 
219     case decl:			/* scanned a declaration word */
220       parser_state_tos->search_brace = btype_2;
221       /* indicate that following brace should be on same line */
222       if (parser_state_tos->p_stack[parser_state_tos->tos] != decl)
223 	{			/* only put one declaration onto stack */
224 	  break_comma = true;	/* while in declaration, newline should be
225 				   forced after comma */
226 	  inc_pstack ();
227 	  parser_state_tos->p_stack[parser_state_tos->tos] = decl;
228 	  parser_state_tos->il[parser_state_tos->tos] =
229 	    parser_state_tos->i_l_follow;
230 
231 	  if (ljust_decl)
232 	    {			/* only do if we want left justified
233 				   declarations */
234 	      parser_state_tos->ind_level = 0;
235 	      for (i = parser_state_tos->tos - 1; i > 0; --i)
236 		if (parser_state_tos->p_stack[i] == decl)
237 		  /* indentation is number of declaration levels deep we are
238 		     times spaces per level */
239 		  parser_state_tos->ind_level += ind_size;
240 	      parser_state_tos->i_l_follow = parser_state_tos->ind_level;
241 	    }
242 	}
243       break;
244 
245     case ifstmt:		/* scanned if (...) */
246       if (parser_state_tos->p_stack[parser_state_tos->tos] == elsehead && else_if)	/* "else if ..." */
247 	parser_state_tos->i_l_follow
248 	  = parser_state_tos->il[parser_state_tos->tos];
249     case dolit:		/* 'do' */
250     case forstmt:		/* for (...) */
251       inc_pstack ();
252       parser_state_tos->p_stack[parser_state_tos->tos] = tk;
253       parser_state_tos->il[parser_state_tos->tos]
254 	= parser_state_tos->ind_level = parser_state_tos->i_l_follow;
255       parser_state_tos->i_l_follow += ind_size;	/* subsequent statements
256 						   should be indented 1 */
257       parser_state_tos->search_brace = btype_2;
258       break;
259 
260     case lbrace:		/* scanned { */
261       break_comma = false;	/* don't break comma in an initial list */
262       if (parser_state_tos->p_stack[parser_state_tos->tos] == stmt
263 	  || parser_state_tos->p_stack[parser_state_tos->tos] == stmtl)
264 	/* it is a random, isolated stmt group or a declaration */
265 	parser_state_tos->i_l_follow += ind_size;
266       else if (parser_state_tos->p_stack[parser_state_tos->tos] == decl)
267 	{
268 	  parser_state_tos->i_l_follow += ind_size;
269 	  if (parser_state_tos->last_rw == rw_struct_like
270 	      && !btype_2 && !parser_state_tos->col_1)
271 	    {
272 	      parser_state_tos->ind_level += brace_indent;
273 	      parser_state_tos->i_l_follow += brace_indent;
274 	    }
275 	}
276       else
277 	{
278 	  if (s_code == e_code)
279 	    {
280 	      /* only do this if there is nothing on the line */
281 
282 	      parser_state_tos->ind_level -= ind_size;
283 	      /* it is a group as part of a while, for, etc. */
284 
285 	      /* For -bl formatting, indent by brace_indent additional spaces
286 	         e.g. if (foo == bar) { <--> brace_indent spaces (in this
287 	         example, 4) */
288 	      if (!btype_2)
289 		{
290 		  parser_state_tos->ind_level += brace_indent;
291 		  parser_state_tos->i_l_follow += brace_indent;
292 		  if (parser_state_tos->p_stack[parser_state_tos->tos]
293 		      == swstmt)
294 		    case_ind += brace_indent;
295 		}
296 
297 	      if (parser_state_tos->p_stack[parser_state_tos->tos] == swstmt
298 		  && case_indent >= ind_size)
299 		parser_state_tos->ind_level -= ind_size;
300 	      /* for a switch, brace should be two levels out from the code */
301 	    }
302 	}
303 
304       inc_pstack ();
305       parser_state_tos->p_stack[parser_state_tos->tos] = lbrace;
306       parser_state_tos->il[parser_state_tos->tos] =
307 	parser_state_tos->ind_level;
308       inc_pstack ();
309       parser_state_tos->p_stack[parser_state_tos->tos] = stmt;
310       /* allow null stmt between braces */
311       parser_state_tos->il[parser_state_tos->tos] =
312 	parser_state_tos->i_l_follow;
313       break;
314 
315     case whilestmt:		/* scanned while (...) */
316       if (parser_state_tos->p_stack[parser_state_tos->tos] == dohead)
317 	{
318 	  /* it is matched with do stmt */
319 	  parser_state_tos->ind_level = parser_state_tos->i_l_follow
320 	    = parser_state_tos->il[parser_state_tos->tos];
321 	  inc_pstack ();
322 	  parser_state_tos->p_stack[parser_state_tos->tos] = whilestmt;
323 	  parser_state_tos->il[parser_state_tos->tos]
324 	    = parser_state_tos->ind_level = parser_state_tos->i_l_follow;
325 	}
326       else
327 	{			/* it is a while loop */
328 	  inc_pstack ();
329 	  parser_state_tos->p_stack[parser_state_tos->tos] = whilestmt;
330 	  parser_state_tos->il[parser_state_tos->tos] =
331 	    parser_state_tos->i_l_follow;
332 	  parser_state_tos->i_l_follow += ind_size;
333 	  parser_state_tos->search_brace = btype_2;
334 	}
335 
336       break;
337 
338     case elselit:		/* scanned an else */
339 
340       if (parser_state_tos->p_stack[parser_state_tos->tos] != ifhead)
341 	diag (1, "Unmatched 'else'");
342       else
343 	{
344 	  /* indentation for else should be same as for if */
345 	  parser_state_tos->ind_level
346 	    = parser_state_tos->il[parser_state_tos->tos];
347 	  /* everything following should be in 1 level */
348 	  parser_state_tos->i_l_follow = (parser_state_tos->ind_level
349 					  + ind_size);
350 
351 	  parser_state_tos->p_stack[parser_state_tos->tos] = elsehead;
352 	  /* remember if with else */
353 	  parser_state_tos->search_brace = btype_2 | else_if;
354 	}
355       break;
356 
357     case rbrace:		/* scanned a } */
358       /* stack should have <lbrace> <stmt> or <lbrace> <stmtl> */
359       if (parser_state_tos->p_stack[parser_state_tos->tos - 1] == lbrace)
360 	{
361 	  parser_state_tos->ind_level = parser_state_tos->i_l_follow
362 	    = parser_state_tos->il[--parser_state_tos->tos];
363 	  parser_state_tos->p_stack[parser_state_tos->tos] = stmt;
364 	}
365       else
366 	diag (1, "Stmt nesting error.");
367       break;
368 
369     case swstmt:		/* had switch (...) */
370       inc_pstack ();
371       parser_state_tos->p_stack[parser_state_tos->tos] = swstmt;
372       parser_state_tos->cstk[parser_state_tos->tos] = case_ind;
373       /* save current case indent level */
374       parser_state_tos->il[parser_state_tos->tos] =
375 	parser_state_tos->i_l_follow;
376       case_ind = parser_state_tos->i_l_follow + case_indent;	/* cases should be one
377 								   level down from
378 								   switch */
379       /* statements should be two levels in */
380       parser_state_tos->i_l_follow += case_indent + ind_size;
381 
382       parser_state_tos->search_brace = btype_2;
383       break;
384 
385     case semicolon:		/* this indicates a simple stmt */
386       break_comma = false;	/* turn off flag to break after commas in a
387 				   declaration */
388       if (parser_state_tos->p_stack[parser_state_tos->tos] == dostmt)
389 	{
390 	  parser_state_tos->p_stack[parser_state_tos->tos] = stmt;
391 	}
392       else
393 	{
394 	  inc_pstack ();
395 	  parser_state_tos->p_stack[parser_state_tos->tos] = stmt;
396 	  parser_state_tos->il[parser_state_tos->tos]
397 	    = parser_state_tos->ind_level;
398 	}
399       break;
400 
401     default:			/* this is an error */
402       diag (1, "Unknown code to parser");
403       return;
404 
405 
406     }				/* end of switch */
407 
408   reduce ();			/* see if any reduction can be done */
409 
410 #ifdef DEBUG
411   if (debug)
412     {
413       printf ("\nParseStack [%d]:\n", parser_state_tos->p_stack_size);
414       for (i = 1; i <= parser_state_tos->tos; ++i)
415 	printf ("  stack[%d] =>   stack: %d   ind_level: %d\n",
416 		i, parser_state_tos->p_stack[i], parser_state_tos->il[i]);
417       printf ("\n");
418     }
419 #endif
420 
421   return;
422 }
423 
424 /* NAME: reduce
425 
426 FUNCTION: Implements the reduce part of the parsing algorithm
427 
428 ALGORITHM: The following reductions are done.  Reductions are repeated until
429    no more are possible.
430 
431 Old TOS		     New TOS <stmt> <stmt>	     <stmtl> <stmtl> <stmt>
432    <stmtl> do <stmt>		     dohead <dohead> <whilestmt>
433    <dostmt> if <stmt>		     "ifstmt" switch <stmt>	     <stmt>
434    decl <stmt>		     <stmt> "ifelse" <stmt>	     <stmt> for
435    <stmt>		     <stmt> while <stmt>		     <stmt>
436    "dostmt" while	     <stmt>
437 
438 On each reduction, parser_state_tos->i_l_follow (the indentation for the
439    following line) is set to the indentation level associated with the old
440    TOS.
441 
442 PARAMETERS: None
443 
444 RETURNS: Nothing
445 
446 GLOBALS: parser_state_tos->cstk parser_state_tos->i_l_follow =
447    parser_state_tos->il parser_state_tos->p_stack = parser_state_tos->tos =
448 
449 CALLS: None
450 
451 CALLED BY: parse
452 
453 HISTORY: initial coding 	November 1976	D A Willcox of CAC
454 
455 */
456 /*----------------------------------------------*\
457 |   REDUCTION PHASE				    |
458 \*----------------------------------------------*/
reduce()459 reduce ()
460 {
461 
462   register int i;
463 
464   for (;;)
465     {				/* keep looping until there is nothing left
466 				   to reduce */
467 
468       switch (parser_state_tos->p_stack[parser_state_tos->tos])
469 	{
470 
471 	case stmt:
472 	  switch (parser_state_tos->p_stack[parser_state_tos->tos - 1])
473 	    {
474 
475 	    case stmt:
476 	    case stmtl:
477 	      /* stmtl stmt or stmt stmt */
478 	      parser_state_tos->p_stack[--parser_state_tos->tos] = stmtl;
479 	      break;
480 
481 	    case dolit:	/* <do> <stmt> */
482 	      parser_state_tos->p_stack[--parser_state_tos->tos] = dohead;
483 	      parser_state_tos->i_l_follow
484 		= parser_state_tos->il[parser_state_tos->tos];
485 	      break;
486 
487 	    case ifstmt:
488 	      /* <if> <stmt> */
489 	      parser_state_tos->p_stack[--parser_state_tos->tos] = ifhead;
490 	      for (i = parser_state_tos->tos - 1;
491 		   (parser_state_tos->p_stack[i] != stmt
492 		    && parser_state_tos->p_stack[i] != stmtl
493 		    && parser_state_tos->p_stack[i] != lbrace); --i);
494 	      parser_state_tos->i_l_follow = parser_state_tos->il[i];
495 	      /* for the time being, we will assume that there is no else on
496 	         this if, and set the indentation level accordingly. If an
497 	         else is scanned, it will be fixed up later */
498 	      break;
499 
500 	    case swstmt:
501 	      /* <switch> <stmt> */
502 	      case_ind = parser_state_tos->cstk[parser_state_tos->tos - 1];
503 
504 	    case decl:		/* finish of a declaration */
505 	    case elsehead:
506 	      /* <<if> <stmt> else> <stmt> */
507 	    case forstmt:
508 	      /* <for> <stmt> */
509 	    case whilestmt:
510 	      /* <while> <stmt> */
511 	      parser_state_tos->p_stack[--parser_state_tos->tos] = stmt;
512 	      parser_state_tos->i_l_follow =
513 		parser_state_tos->il[parser_state_tos->tos];
514 	      break;
515 
516 	    default:		/* <anything else> <stmt> */
517 	      return;
518 
519 	    }			/* end of section for <stmt> on top of stack */
520 	  break;
521 
522 	case whilestmt:	/* while (...) on top */
523 	  if (parser_state_tos->p_stack[parser_state_tos->tos - 1] == dohead)
524 	    {
525 	      /* it is termination of a do while */
526 #if 0
527 	      parser_state_tos->p_stack[--parser_state_tos->tos] = stmt;
528 #endif
529 	      parser_state_tos->p_stack[--parser_state_tos->tos] = dostmt;
530 	      break;
531 	    }
532 	  else
533 	    return;
534 
535 	default:		/* anything else on top */
536 	  return;
537 
538 	}
539     }
540 }
541 
542 /* This kludge is called from main.  It is just like parse(semicolon) except
543    that it does not clear break_comma.  Leaving break_comma alone is
544    necessary to make sure that "int foo(), bar()" gets formatted correctly
545    under -bc.  */
546 
547 INLINE void
parse_lparen_in_decl()548 parse_lparen_in_decl ()
549 {
550   inc_pstack ();
551   parser_state_tos->p_stack[parser_state_tos->tos] = stmt;
552   parser_state_tos->il[parser_state_tos->tos] = parser_state_tos->ind_level;
553 
554   reduce ();
555 }
556