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