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