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