Commit | Line | Data |
---|---|---|
c0bc4ef7 DF |
1 | /* |
2 | * Copyright (c) 1980 Regents of the University of California. | |
b0627149 KB |
3 | * Copyright (c) 1976 Board of Trustees of the University of Illinois. |
4 | * All rights reserved. | |
5 | * | |
6 | * Redistribution and use in source and binary forms are permitted | |
b36fc510 KB |
7 | * provided that the above copyright notice and this paragraph are |
8 | * duplicated in all such forms and that any documentation, | |
9 | * advertising materials, and other materials related to such | |
10 | * distribution and use acknowledge that the software was developed | |
11 | * by the University of California, Berkeley and the University | |
12 | * of Illinois, Urbana. The name of either | |
13 | * University may not be used to endorse or promote products derived | |
14 | * from this software without specific prior written permission. | |
15 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR | |
16 | * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED | |
17 | * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. | |
c0bc4ef7 DF |
18 | */ |
19 | ||
20 | #ifndef lint | |
21 | char copyright[] = | |
22 | "@(#) Copyright (c) 1980 Regents of the University of California.\n\ | |
b0627149 | 23 | Copyright (c) 1976 Board of Trustees of the University of Illinois.\n\ |
c0bc4ef7 | 24 | All rights reserved.\n"; |
b0627149 | 25 | #endif /* not lint */ |
c0bc4ef7 DF |
26 | |
27 | #ifndef lint | |
b36fc510 | 28 | static char sccsid[] = "@(#)indent.c 5.8 (Berkeley) %G%"; |
b0627149 | 29 | #endif /* not lint */ |
c6468b47 | 30 | |
b0627149 | 31 | /* |
c6468b47 | 32 | NAME: |
1009bf5e KM |
33 | indent main program |
34 | ||
c6468b47 | 35 | FUNCTION: |
1009bf5e KM |
36 | This is the main program of the indent program. Indent will take a C |
37 | program source and reformat it into a semi-reasonable form. | |
38 | ||
c6468b47 | 39 | ALGORITHM: |
1009bf5e KM |
40 | The routine lexi scans tokens and passes them back one at a time to the |
41 | main routine. The subroutine parse takes care of much of the work of | |
42 | figuring indentation level. | |
43 | ||
44 | 1) Call lexi | |
45 | 2) Enter a monster switch statement on the code returned by lexi. If | |
46 | the indentation level for the line yet to be printed should be | |
47 | changed, set the variable ps.ind_level. If the indentation level for | |
48 | the following line should be changed, set the variable ps.i_l_follow. | |
49 | ||
50 | */ | |
0a139d84 KB |
51 | #include "indent_globs.h" |
52 | #include "indent_codes.h" | |
c6468b47 | 53 | |
1009bf5e KM |
54 | char *in_name = "Standard Input"; /* will always point to name of |
55 | * input file */ | |
56 | char *out_name = "Standard Output"; /* will always point to | |
57 | * name of output file */ | |
58 | char bakfile[32] = ""; | |
c6468b47 | 59 | |
1009bf5e KM |
60 | main(argc, argv) |
61 | int argc; | |
62 | char **argv; | |
c6468b47 | 63 | { |
d1e6224c | 64 | extern int found_err; /* if any error occurred */ |
c6468b47 | 65 | |
1009bf5e KM |
66 | int dec_ind; /* current indentation for declarations */ |
67 | int di_stack[20]; /* a stack of structure indentation levels */ | |
68 | int flushed_nl; /* used when buffering up comments to | |
69 | * remember that a newline was passed over */ | |
70 | int force_nl; /* when true, code must be broken */ | |
71 | int hd_type; /* used to store type of stmt for if | |
72 | * (...), for (...), etc */ | |
73 | register int i; /* local loop counter */ | |
74 | register int j; /* local loop counter */ | |
75 | int scase; /* set to true when we see a case, so we | |
76 | * will know what to do with the following | |
77 | * colon */ | |
78 | int sp_sw; /* when true, we are in the expressin of | |
79 | * if(...), while(...), etc. */ | |
80 | int squest; /* when this is positive, we have seen a ? | |
81 | * without the matching : in a <c>?<s>:<s> | |
82 | * construct */ | |
83 | register char *t_ptr; /* used for copying tokens */ | |
84 | int type_code; /* the type of token, returned by lexi */ | |
85 | ||
86 | int last_else = 0; /* true iff last keyword was an else */ | |
87 | ||
88 | ||
89 | /*-----------------------------------------------*\ | |
c93d6f87 KM |
90 | | INITIALIZATION | |
91 | \*-----------------------------------------------*/ | |
c6468b47 KM |
92 | |
93 | ||
1009bf5e KM |
94 | ps.p_stack[0] = stmt; /* this is the parser's stack */ |
95 | ps.last_nl = true; /* this is true if the last thing scanned | |
96 | * was a newline */ | |
97 | ps.last_token = semicolon; | |
98 | combuf[0] = codebuf[0] = labbuf[0] = ' '; /* set up code, label, and | |
99 | * comment buffers */ | |
c6468b47 KM |
100 | combuf[1] = codebuf[1] = labbuf[1] = '\0'; |
101 | s_lab = e_lab = labbuf + 1; | |
102 | s_code = e_code = codebuf + 1; | |
103 | s_com = e_com = combuf + 1; | |
104 | ||
105 | buf_ptr = buf_end = in_buffer; | |
106 | line_no = 1; | |
1009bf5e | 107 | had_eof = ps.in_decl = ps.decl_on_line = break_comma = false; |
c6468b47 | 108 | sp_sw = force_nl = false; |
1009bf5e KM |
109 | ps.in_or_st = false; |
110 | ps.bl_line = true; | |
c6468b47 | 111 | dec_ind = 0; |
1009bf5e KM |
112 | di_stack[ps.dec_nest = 0] = 0; |
113 | ps.want_blank = ps.in_stmt = ps.ind_stmt = false; | |
c6468b47 KM |
114 | |
115 | ||
1009bf5e | 116 | scase = ps.pcase = false; |
c6468b47 KM |
117 | squest = 0; |
118 | sc_end = 0; | |
119 | bp_save = 0; | |
120 | be_save = 0; | |
121 | ||
1009bf5e | 122 | output = 0; |
c6468b47 KM |
123 | |
124 | ||
125 | ||
1009bf5e | 126 | /*--------------------------------------------------*\ |
c93d6f87 KM |
127 | | COMMAND LINE SCAN |
128 | \*--------------------------------------------------*/ | |
1009bf5e | 129 | |
c93d6f87 | 130 | set_defaults(); |
1009bf5e | 131 | |
c93d6f87 KM |
132 | /* |
133 | * Unfortunately, we must look for -npro here because the profiles | |
134 | * are read before the command line arguments. | |
135 | */ | |
1009bf5e KM |
136 | for (i = 1; i < argc; ++i) |
137 | if (strcmp(argv[i], "-npro") == 0) | |
138 | break; | |
139 | if (i >= argc) | |
140 | set_profile(); | |
c6468b47 | 141 | |
c93d6f87 KM |
142 | input = 0; /* cancel -st if it was in the profiles, */ |
143 | output = 0; /* as it doesn't make any sense there. */ | |
144 | ||
c6468b47 | 145 | for (i = 1; i < argc; ++i) { |
1009bf5e KM |
146 | |
147 | /* | |
148 | * look thru args (if any) for changes to defaults | |
149 | */ | |
c6468b47 | 150 | if (argv[i][0] != '-') {/* no flag on parameter */ |
1009bf5e KM |
151 | if (input == 0) { /* we must have the input file */ |
152 | in_name = argv[i]; /* remember name of input file */ | |
153 | input = fopen(in_name, "r"); | |
154 | if (input == 0) { /* check for open error */ | |
c93d6f87 KM |
155 | fprintf(stderr, "indent: can't open %s\n", argv[i]); |
156 | exit(1); | |
c6468b47 KM |
157 | } |
158 | continue; | |
1009bf5e KM |
159 | } else if (output == 0) { /* we have the output file */ |
160 | out_name = argv[i]; /* remember name of output file */ | |
161 | if (strcmp(in_name, out_name) == 0) { /* attempt to overwrite | |
162 | * the file */ | |
c93d6f87 KM |
163 | fprintf(stderr, "indent: input and output files must be different\n"); |
164 | exit(1); | |
c6468b47 | 165 | } |
1009bf5e KM |
166 | output = fopen(out_name, "w"); |
167 | if (output == 0) { /* check for create error */ | |
c93d6f87 KM |
168 | fprintf(stderr, "indent: can't create %s\n", argv[i]); |
169 | exit(1); | |
1009bf5e KM |
170 | } |
171 | continue; | |
172 | } | |
c93d6f87 KM |
173 | fprintf(stderr, "indent: unknown parameter: %s\n", argv[i]); |
174 | exit(1); | |
1009bf5e KM |
175 | } else |
176 | set_option(argv[i]); | |
177 | ||
178 | } /* end of for */ | |
179 | if (input == 0) { | |
180 | printf("Usage: indent file [ outfile ] [ options ]\n"); | |
c93d6f87 | 181 | exit(1); |
1009bf5e KM |
182 | } |
183 | if (output == 0) | |
184 | if (troff) | |
185 | output = stdout; | |
186 | else { | |
187 | out_name = in_name; | |
188 | bakcopy(); | |
c6468b47 | 189 | } |
c93d6f87 KM |
190 | |
191 | /* | |
192 | * Adjust parameters that are out of range, or set defaults if | |
193 | * no values were specified. | |
194 | */ | |
1009bf5e KM |
195 | if (ps.com_ind <= 1) |
196 | ps.com_ind = 2; /* dont put normal comments before column | |
197 | * 2 */ | |
198 | if (block_comment_max_col <= 0) | |
199 | block_comment_max_col = max_col; | |
200 | if (ps.decl_com_ind <= 0) /* if not specified by user, set this */ | |
c93d6f87 KM |
201 | ps.decl_com_ind = ps.ljust_decl ? ps.com_ind - 8 : ps.com_ind; |
202 | if (ps.decl_com_ind <= 1) | |
203 | ps.decl_com_ind = 2; | |
1009bf5e KM |
204 | if (continuation_indent == 0) |
205 | continuation_indent = ps.ind_size; | |
206 | fill_buffer(); /* get first batch of stuff into input | |
207 | * buffer */ | |
208 | ||
209 | parse(semicolon); | |
210 | { | |
211 | register char *p = buf_ptr; | |
212 | register col = 1; | |
213 | ||
214 | while (1) { | |
215 | if (*p == ' ') | |
216 | col++; | |
217 | else if (*p == '\t') | |
218 | col = ((col - 1) & ~7) + 9; | |
219 | else | |
220 | break; | |
221 | p++; | |
222 | }; | |
223 | if (col > ps.ind_size) | |
224 | ps.ind_level = ps.i_l_follow = col / ps.ind_size; | |
c6468b47 | 225 | } |
1009bf5e KM |
226 | if (troff) { |
227 | register char *p = in_name, | |
228 | *beg = in_name; | |
229 | ||
230 | while (*p) | |
231 | if (*p++ == '/') | |
232 | beg = p; | |
233 | fprintf(output, ".Fn \"%s\"\n", beg); | |
c6468b47 KM |
234 | } |
235 | ||
1009bf5e KM |
236 | /* |
237 | * START OF MAIN LOOP | |
238 | */ | |
c6468b47 | 239 | |
1009bf5e KM |
240 | while (1) { /* this is the main loop. it will go |
241 | * until we reach eof */ | |
242 | int is_procname; | |
c6468b47 | 243 | |
1009bf5e KM |
244 | type_code = lexi(); /* lexi reads one token. The actual |
245 | * characters read are stored in "token". | |
246 | * lexi returns a code indicating the type | |
247 | * of token */ | |
248 | is_procname = ps.procname[0]; | |
c6468b47 | 249 | |
1009bf5e KM |
250 | /* |
251 | * The following code moves everything following an if (), while | |
252 | * (), else, etc. up to the start of the following stmt to a | |
253 | * buffer. This allows proper handling of both kinds of brace | |
254 | * placement. | |
255 | */ | |
c6468b47 KM |
256 | |
257 | flushed_nl = false; | |
1009bf5e KM |
258 | while (ps.search_brace) { /* if we scanned an if(), while(), |
259 | * etc., we might need to copy | |
260 | * stuff into a buffer we must | |
261 | * loop, copying stuff into | |
262 | * save_com, until we find the | |
263 | * start of the stmt which follows | |
264 | * the if, or whatever */ | |
c6468b47 | 265 | switch (type_code) { |
1009bf5e | 266 | case newline: |
c6468b47 KM |
267 | ++line_no; |
268 | flushed_nl = true; | |
1009bf5e KM |
269 | case form_feed: |
270 | break; /* form feeds and newlines found here will | |
271 | * be ignored */ | |
272 | ||
273 | case lbrace: /* this is a brace that starts the | |
274 | * compound stmt */ | |
275 | if (sc_end == 0) { /* ignore buffering if a comment | |
276 | * wasnt stored up */ | |
277 | ps.search_brace = false; | |
c6468b47 KM |
278 | goto check_type; |
279 | } | |
c6468b47 | 280 | if (btype_2) { |
1009bf5e KM |
281 | save_com[0] = '{'; /* we either want to put |
282 | * the brace right after | |
283 | * the if */ | |
284 | goto sw_buffer; /* go to common code to get out of | |
285 | * this loop */ | |
c6468b47 | 286 | } |
1009bf5e KM |
287 | case comment: /* we have a comment, so we must copy it |
288 | * into the buffer */ | |
289 | if (!flushed_nl) { | |
290 | if (sc_end == 0) { /* if this is the first | |
291 | * comment, we must set up | |
292 | * the buffer */ | |
293 | save_com[0] = save_com[1] = ' '; | |
294 | sc_end = &(save_com[2]); | |
295 | } else { | |
296 | *sc_end++ = '\n'; /* add newline between | |
297 | * comments */ | |
298 | *sc_end++ = ' '; | |
299 | --line_no; | |
300 | } | |
301 | *sc_end++ = '/'; /* copy in start of | |
302 | * comment */ | |
303 | *sc_end++ = '*'; | |
304 | ||
305 | for (;;) { /* loop until we get to the end of | |
306 | * the comment */ | |
307 | *sc_end = *buf_ptr++; | |
308 | if (buf_ptr >= buf_end) | |
309 | fill_buffer(); | |
310 | ||
311 | if (*sc_end++ == '*' && *buf_ptr == '/') | |
312 | break; /* we are at end of comment */ | |
313 | ||
314 | if (sc_end >= &(save_com[sc_size])) { /* check for temp buffer | |
315 | * overflow */ | |
316 | diag(1, "Internal buffer overflow - Move big comment from right after if, while, or whatever."); | |
317 | fflush(output); | |
c93d6f87 | 318 | exit(1); |
1009bf5e KM |
319 | } |
320 | } | |
321 | *sc_end++ = '/'; /* add ending slash */ | |
322 | if (++buf_ptr >= buf_end) /* get past / in buffer */ | |
323 | fill_buffer(); | |
324 | break; | |
325 | } | |
326 | default: /* it is the start of a normal statment */ | |
327 | if (flushed_nl) /* if we flushed a newline, make | |
328 | * sure it is put back */ | |
c6468b47 | 329 | force_nl = true; |
1009bf5e KM |
330 | if (type_code == sp_paren && *token == 'i' |
331 | && last_else && ps.else_if | |
332 | || type_code == sp_nparen && *token == 'e' | |
333 | && e_code != s_code && e_code[-1] == '}') | |
334 | force_nl = false; | |
c6468b47 | 335 | |
1009bf5e KM |
336 | if (sc_end == 0) { /* ignore buffering if comment |
337 | * wasnt saved up */ | |
338 | ps.search_brace = false; | |
c6468b47 KM |
339 | goto check_type; |
340 | } | |
1009bf5e KM |
341 | if (force_nl) { /* if we should insert a nl here, |
342 | * put it into the buffer */ | |
c6468b47 | 343 | force_nl = false; |
1009bf5e KM |
344 | --line_no; /* this will be re-increased when |
345 | * the nl is read from the buffer */ | |
c6468b47 KM |
346 | *sc_end++ = '\n'; |
347 | *sc_end++ = ' '; | |
1009bf5e KM |
348 | if (verbose && !flushed_nl) /* print error msg if |
349 | * the line was not | |
350 | * already broken */ | |
351 | diag(0, "Line broken"); | |
c6468b47 KM |
352 | flushed_nl = false; |
353 | } | |
c6468b47 | 354 | for (t_ptr = token; *t_ptr; ++t_ptr) |
1009bf5e KM |
355 | *sc_end++ = *t_ptr; /* copy token into temp |
356 | * buffer */ | |
357 | ||
358 | sw_buffer: | |
359 | ps.search_brace = false; /* stop looking for start | |
360 | * of stmt */ | |
361 | bp_save = buf_ptr; /* save current input buffer */ | |
c6468b47 | 362 | be_save = buf_end; |
1009bf5e KM |
363 | buf_ptr = save_com; /* fix so that subsequent calls to |
364 | * lexi will take tokens out of | |
365 | * save_com */ | |
366 | *sc_end++ = ' '; /* add trailing blank, just in | |
367 | * case */ | |
c6468b47 KM |
368 | buf_end = sc_end; |
369 | sc_end = 0; | |
370 | break; | |
1009bf5e KM |
371 | } /* end of switch */ |
372 | if (type_code != 0) /* we must make this check, just in case | |
373 | * there was an unexpected EOF */ | |
374 | type_code = lexi(); /* read another token */ | |
375 | is_procname = ps.procname[0]; | |
376 | } /* end of while (serach_brace) */ | |
377 | last_else = 0; | |
378 | check_type: | |
379 | if (type_code == 0) { /* we got eof */ | |
c6468b47 | 380 | if (s_lab != e_lab || s_code != e_code |
1009bf5e KM |
381 | || s_com != e_com) /* must dump end of line */ |
382 | dump_line(); | |
383 | if (ps.tos > 1) /* check for balanced braces */ | |
384 | diag(1, "Stuff missing from end of file."); | |
385 | ||
c6468b47 | 386 | if (verbose) { |
1009bf5e KM |
387 | printf("There were %d output lines and %d comments\n", |
388 | ps.out_lines, ps.out_coms); | |
389 | printf("(Lines with comments)/(Lines with code): %6.3f\n", | |
390 | (1.0 * ps.com_lines) / code_lines); | |
c6468b47 | 391 | } |
1009bf5e | 392 | fflush(output); |
d1e6224c | 393 | exit(ps.tos > 1 || found_err); |
c6468b47 | 394 | } |
c6468b47 | 395 | if ( |
1009bf5e KM |
396 | (type_code != comment) && |
397 | (type_code != newline) && | |
398 | (type_code != preesc) && | |
399 | (type_code != form_feed)) { | |
c6468b47 | 400 | if ( |
1009bf5e KM |
401 | force_nl |
402 | && | |
403 | (type_code != semicolon) && | |
404 | ( | |
405 | type_code != lbrace | |
406 | || | |
407 | !btype_2 | |
408 | )) { /* we should force a broken line here */ | |
c6468b47 | 409 | if (verbose && !flushed_nl) |
1009bf5e | 410 | diag(0, "Line broken"); |
c6468b47 | 411 | flushed_nl = false; |
1009bf5e KM |
412 | dump_line(); |
413 | ps.want_blank = false; /* dont insert blank at line start */ | |
c6468b47 KM |
414 | force_nl = false; |
415 | } | |
1009bf5e KM |
416 | ps.in_stmt = true; /* turn on flag which causes an extra |
417 | * level of indentation. this is turned | |
418 | * off by a ; or '}' */ | |
419 | if (s_com != e_com) { /* the turkey has embedded a | |
420 | * comment in a line. fix it */ | |
c6468b47 KM |
421 | *e_code++ = ' '; |
422 | for (t_ptr = s_com; *t_ptr; ++t_ptr) | |
423 | *e_code++ = *t_ptr; | |
424 | *e_code++ = ' '; | |
1009bf5e KM |
425 | *e_code = '\0'; /* null terminate code sect */ |
426 | ps.want_blank = false; | |
c6468b47 KM |
427 | e_com = s_com; |
428 | } | |
1009bf5e KM |
429 | } else if (type_code != comment) /* preserve force_nl thru |
430 | * a comment */ | |
431 | force_nl = false; | |
432 | ||
433 | /* | |
434 | * cancel forced newline after newline, form feed, etc | |
435 | */ | |
c6468b47 KM |
436 | |
437 | ||
438 | ||
1009bf5e | 439 | /*----------------------------------------------------*\ |
c93d6f87 KM |
440 | | do switch on type of token scanned |
441 | \*----------------------------------------------------*/ | |
1009bf5e | 442 | switch (type_code) { /* now, decide what to do with the token */ |
c6468b47 | 443 | |
1009bf5e KM |
444 | case form_feed: /* found a form feed in line */ |
445 | ps.use_ff = true; /* a form feed is treated much | |
446 | * like a newline */ | |
447 | dump_line(); | |
448 | ps.want_blank = false; | |
c6468b47 KM |
449 | break; |
450 | ||
1009bf5e KM |
451 | case newline: |
452 | if (ps.last_token != comma || ps.p_l_follow > 0 | |
453 | || !ps.leave_comma || !break_comma || s_com != e_com) { | |
454 | dump_line(); | |
455 | ps.want_blank = false; | |
456 | } | |
457 | ++line_no; /* keep track of input line number */ | |
c6468b47 KM |
458 | break; |
459 | ||
1009bf5e KM |
460 | case lparen: /* got a '(' or '[' */ |
461 | ++ps.p_l_follow;/* count parens to make Healy happy */ | |
462 | if (ps.want_blank && *token != '[' && | |
463 | (ps.last_token != ident || proc_calls_space | |
464 | || (ps.its_a_keyword && !ps.sizeof_keyword))) | |
c6468b47 | 465 | *e_code++ = ' '; |
1009bf5e KM |
466 | if (ps.in_decl && !ps.block_init) |
467 | if (troff && !ps.dumped_decl_indent) { | |
468 | ps.dumped_decl_indent = 1; | |
469 | sprintf(e_code, "\\c\n.Du %dp+\200p \"%s\"\n", dec_ind * 7, token); | |
470 | e_code += strlen(e_code); | |
471 | } else { | |
472 | while ((e_code - s_code) < dec_ind) | |
473 | *e_code++ = ' '; | |
474 | *e_code++ = token[0]; | |
475 | } else | |
476 | *e_code++ = token[0]; | |
477 | ps.paren_indents[ps.p_l_follow - 1] = e_code - s_code; | |
478 | ps.want_blank = false; | |
479 | if (ps.in_or_st && *token == '(') { | |
480 | ||
481 | /* | |
482 | * this is a kluge to make sure that declarations will | |
483 | * be aligned right if proc decl has an explicit type | |
484 | * on it, i.e. "int a(x) {..." | |
485 | */ | |
486 | parse(semicolon); /* I said this was a kluge... */ | |
487 | ps.in_or_st = false; /* turn off flag for | |
488 | * structure decl or | |
489 | * initialization */ | |
c6468b47 | 490 | } |
1009bf5e | 491 | if (ps.sizeof_keyword) ps.sizeof_mask |= 1<<ps.p_l_follow; |
c6468b47 KM |
492 | break; |
493 | ||
1009bf5e KM |
494 | case rparen: /* got a ')' or ']' */ |
495 | if (ps.cast_mask & (1 << ps.p_l_follow) & ~ps.sizeof_mask) { | |
496 | ps.last_u_d = true; | |
497 | ps.cast_mask &= (1 << ps.p_l_follow) - 1; | |
c6468b47 | 498 | } |
1009bf5e KM |
499 | ps.sizeof_mask &= (1 << ps.p_l_follow) - 1; |
500 | if (--ps.p_l_follow < 0) { | |
501 | ps.p_l_follow = 0; | |
502 | diag(0, "Extra %c", *token); | |
503 | } | |
504 | if (e_code == s_code) /* if the paren starts the line */ | |
505 | ps.paren_level = ps.p_l_follow; /* then indent it */ | |
c6468b47 KM |
506 | |
507 | *e_code++ = token[0]; | |
1009bf5e | 508 | ps.want_blank = true; |
c6468b47 | 509 | |
1009bf5e KM |
510 | if (sp_sw && (ps.p_l_follow == 0)) { /* check for end of if |
511 | * (...), or some such */ | |
c6468b47 | 512 | sp_sw = false; |
1009bf5e KM |
513 | force_nl = true; /* must force newline after if */ |
514 | ps.last_u_d = true; /* inform lexi that a following | |
515 | * operator is unary */ | |
516 | ps.in_stmt = false; /* dont use stmt continuation | |
517 | * indentation */ | |
518 | ||
519 | parse(hd_type); /* let parser worry about if, or | |
520 | * whatever */ | |
c6468b47 | 521 | } |
1009bf5e KM |
522 | ps.search_brace = btype_2; /* this should insure that |
523 | * constructs such as | |
524 | * main(){...} and | |
525 | * int[]{...} have their | |
526 | * braces put in the right | |
527 | * place */ | |
c6468b47 KM |
528 | break; |
529 | ||
1009bf5e KM |
530 | case unary_op: /* this could be any unary operation */ |
531 | if (ps.want_blank) | |
c6468b47 KM |
532 | *e_code++ = ' '; |
533 | ||
1009bf5e KM |
534 | if (troff && !ps.dumped_decl_indent && ps.in_decl) { |
535 | sprintf(e_code, "\\c\n.Du %dp+\200p \"%s\"\n", dec_ind * 7, token); | |
536 | ps.dumped_decl_indent = 1; | |
537 | e_code += strlen(e_code); | |
538 | } else { | |
539 | char *res = token; | |
540 | ||
541 | if (ps.in_decl && !ps.block_init) { /* if this is a unary op | |
542 | * in a declaration, we | |
543 | * should indent this | |
544 | * token */ | |
545 | for (i = 0; token[i]; ++i); /* find length of token */ | |
546 | while ((e_code - s_code) < (dec_ind - i)) | |
547 | *e_code++ = ' '; /* pad it */ | |
548 | } | |
549 | if (troff && token[0] == '-' && token[1] == '>') | |
550 | res = "\\(->"; | |
551 | for (t_ptr = res; *t_ptr; ++t_ptr) | |
552 | *e_code++ = *t_ptr; | |
c6468b47 | 553 | } |
1009bf5e | 554 | ps.want_blank = false; |
c6468b47 KM |
555 | break; |
556 | ||
1009bf5e KM |
557 | case binary_op: /* any binary operation */ |
558 | do_binary: | |
559 | if (ps.want_blank) | |
c6468b47 | 560 | *e_code++ = ' '; |
1009bf5e KM |
561 | { |
562 | char *res = token; | |
563 | ||
564 | if (troff) | |
565 | switch (token[0]) { | |
566 | case '<': | |
567 | if (token[1] == '=') | |
568 | res = "\\(<="; | |
569 | break; | |
570 | case '>': | |
571 | if (token[1] == '=') | |
572 | res = "\\(>="; | |
573 | break; | |
574 | case '!': | |
575 | if (token[1] == '=') | |
576 | res = "\\(!="; | |
577 | break; | |
578 | case '|': | |
579 | if (token[1] == '|') | |
580 | res = "\\(br\\(br"; | |
581 | else if (token[1] == 0) | |
582 | res = "\\(br"; | |
583 | break; | |
5c6e73ac KM |
584 | case '-': |
585 | if (token[1] == '>') | |
586 | res = "\\(->"; | |
1009bf5e KM |
587 | } |
588 | for (t_ptr = res; *t_ptr; ++t_ptr) | |
589 | *e_code++ = *t_ptr; /* move the operator */ | |
590 | } | |
591 | ps.want_blank = true; | |
c6468b47 KM |
592 | break; |
593 | ||
1009bf5e | 594 | case postop: /* got a trailing ++ or -- */ |
c6468b47 KM |
595 | *e_code++ = token[0]; |
596 | *e_code++ = token[1]; | |
1009bf5e | 597 | ps.want_blank = true; |
c6468b47 KM |
598 | break; |
599 | ||
1009bf5e KM |
600 | case question: /* got a ? */ |
601 | squest++; /* this will be used when a later colon | |
602 | * appears so we can distinguish the | |
603 | * <c>?<n>:<n> construct */ | |
604 | if (ps.want_blank) | |
c6468b47 KM |
605 | *e_code++ = ' '; |
606 | *e_code++ = '?'; | |
1009bf5e | 607 | ps.want_blank = true; |
c6468b47 KM |
608 | break; |
609 | ||
1009bf5e KM |
610 | case casestmt: /* got word 'case' or 'default' */ |
611 | scase = true; /* so we can process the later colon | |
612 | * properly */ | |
613 | goto copy_id; | |
c6468b47 | 614 | |
1009bf5e KM |
615 | case colon: /* got a ':' */ |
616 | if (squest > 0) { /* it is part of the <c>?<n>: <n> | |
617 | * construct */ | |
c6468b47 | 618 | --squest; |
1009bf5e | 619 | if (ps.want_blank) |
c6468b47 KM |
620 | *e_code++ = ' '; |
621 | *e_code++ = ':'; | |
1009bf5e | 622 | ps.want_blank = true; |
c6468b47 KM |
623 | break; |
624 | } | |
1009bf5e KM |
625 | if (ps.in_decl) { |
626 | *e_code++ = ':'; | |
627 | ps.want_blank = false; | |
628 | break; | |
629 | } | |
630 | ps.in_stmt = false; /* seeing a label does not imply | |
631 | * we are in a stmt */ | |
c6468b47 | 632 | for (t_ptr = s_code; *t_ptr; ++t_ptr) |
1009bf5e KM |
633 | *e_lab++ = *t_ptr; /* turn everything so far into a |
634 | * label */ | |
c6468b47 KM |
635 | e_code = s_code; |
636 | *e_lab++ = ':'; | |
637 | *e_lab++ = ' '; | |
638 | *e_lab = '\0'; | |
639 | ||
1009bf5e KM |
640 | force_nl = ps.pcase = scase; /* ps.pcase will be used |
641 | * by dump_line to decide | |
642 | * how to indent the | |
643 | * label. force_nl will | |
644 | * force a case n: to be | |
645 | * on a line by itself */ | |
c6468b47 | 646 | scase = false; |
1009bf5e | 647 | ps.want_blank = false; |
c6468b47 KM |
648 | break; |
649 | ||
1009bf5e KM |
650 | case semicolon: /* got a ';' */ |
651 | ps.in_or_st = false; /* we are not in an initialization | |
652 | * or structure declaration */ | |
653 | scase = false; /* these will only need resetting in a | |
654 | * error */ | |
c6468b47 | 655 | squest = 0; |
1009bf5e KM |
656 | if (ps.last_token == rparen) |
657 | ps.in_parameter_declaration = 0; | |
658 | ps.cast_mask = 0; | |
659 | ps.sizeof_mask = 0; | |
660 | ps.block_init = 0; | |
661 | ps.just_saw_decl--; | |
662 | ||
663 | if (ps.in_decl && s_code == e_code && !ps.block_init) | |
c6468b47 KM |
664 | while ((e_code - s_code) < (dec_ind - 1)) |
665 | *e_code++ = ' '; | |
666 | ||
1009bf5e KM |
667 | ps.in_decl = (ps.dec_nest > 0); /* if we were in a first |
668 | * level structure | |
669 | * declaration, we arent | |
670 | * any more */ | |
671 | ||
672 | if ((!sp_sw || hd_type != forstmt) && ps.p_l_follow > 0) { | |
673 | ||
674 | /* | |
675 | * This should be true iff there were unbalanced | |
676 | * parens in the stmt. It is a bit complicated, | |
677 | * because the semicolon might be in a for stmt | |
678 | */ | |
679 | diag(1, "Unbalanced parens"); | |
680 | ps.p_l_follow = 0; | |
681 | if (sp_sw) {/* this is a check for a if, while, etc. | |
682 | * with unbalanced parens */ | |
c6468b47 | 683 | sp_sw = false; |
1009bf5e | 684 | parse(hd_type); /* dont lose the if, or whatever */ |
c6468b47 KM |
685 | } |
686 | } | |
c6468b47 | 687 | *e_code++ = ';'; |
1009bf5e KM |
688 | ps.want_blank = true; |
689 | ps.in_stmt = (ps.p_l_follow > 0); /* we are no longer in | |
690 | * the middle of a stmt */ | |
691 | ||
692 | if (!sp_sw) { /* if not if for (;;) */ | |
693 | parse(semicolon); /* let parser know about end of | |
694 | * stmt */ | |
695 | force_nl = true; /* force newline after a end of | |
696 | * stmt */ | |
c6468b47 | 697 | } |
c6468b47 KM |
698 | break; |
699 | ||
1009bf5e KM |
700 | case lbrace: /* got a '{' */ |
701 | ps.in_stmt = false; /* dont indent the {} */ | |
702 | if (!ps.block_init) | |
703 | force_nl = true; /* force other stuff on same line | |
704 | * as '{' onto new line */ | |
705 | ||
706 | if (s_code != e_code && !ps.block_init) { | |
707 | if (!btype_2) { | |
708 | dump_line(); | |
709 | ps.want_blank = false; | |
710 | } else if (ps.in_parameter_declaration && !ps.in_or_st) { | |
711 | ps.i_l_follow = 0; | |
712 | dump_line(); | |
713 | ps.want_blank = false; | |
714 | } | |
c6468b47 | 715 | } |
1009bf5e KM |
716 | if (ps.in_parameter_declaration) |
717 | prefix_blankline_requested = 0; | |
718 | ||
c93d6f87 | 719 | if (ps.p_l_follow > 0) { /* check for preceding |
1009bf5e KM |
720 | * unbalanced parens */ |
721 | diag(1, "Unbalanced parens"); | |
722 | ps.p_l_follow = 0; | |
723 | if (sp_sw) {/* check for unclosed if, for, etc. */ | |
c6468b47 | 724 | sp_sw = false; |
1009bf5e KM |
725 | parse(hd_type); |
726 | ps.ind_level = ps.i_l_follow; | |
c6468b47 KM |
727 | } |
728 | } | |
c6468b47 | 729 | if (s_code == e_code) |
1009bf5e KM |
730 | ps.ind_stmt = false; /* dont put extra |
731 | * indentation on line | |
732 | * with '{' */ | |
733 | if (ps.in_decl && ps.in_or_st) { /* this is either a | |
734 | * structure declaration | |
735 | * or an init */ | |
736 | di_stack[ps.dec_nest++] = dec_ind; | |
c6468b47 | 737 | dec_ind = 0; |
1009bf5e KM |
738 | } else { |
739 | ps.decl_on_line = false; /* we cant be in the | |
740 | * middle of a | |
741 | * declaration, so dont do | |
742 | * special indentation of | |
743 | * comments */ | |
744 | ps.in_parameter_declaration = 0; | |
c6468b47 | 745 | } |
1009bf5e KM |
746 | parse(lbrace); /* let parser know about this */ |
747 | if (ps.want_blank) /* put a blank before '{' if '{' | |
748 | * is not at start of line */ | |
c6468b47 | 749 | *e_code++ = ' '; |
1009bf5e | 750 | ps.want_blank = false; |
c6468b47 | 751 | *e_code++ = '{'; |
1009bf5e | 752 | ps.just_saw_decl = 0; |
c6468b47 KM |
753 | break; |
754 | ||
1009bf5e KM |
755 | case rbrace: /* got a '}' */ |
756 | if (ps.p_l_follow) { /* check for unclosed if, for, | |
757 | * else. */ | |
758 | diag(1, "Unbalanced parens"); | |
759 | ps.p_l_follow = 0; | |
c6468b47 KM |
760 | sp_sw = false; |
761 | } | |
1009bf5e KM |
762 | ps.just_saw_decl = 0; |
763 | if (s_code != e_code && !ps.block_init) { /* '}' must be first on | |
764 | * line */ | |
c6468b47 | 765 | if (verbose) |
1009bf5e KM |
766 | diag(0, "Line broken"); |
767 | dump_line(); | |
c6468b47 | 768 | } |
c6468b47 | 769 | *e_code++ = '}'; |
1009bf5e KM |
770 | ps.want_blank = true; |
771 | ps.in_stmt = ps.ind_stmt = false; | |
772 | if (ps.dec_nest > 0) { /* we are in multi-level structure | |
773 | * declaration */ | |
774 | dec_ind = di_stack[--ps.dec_nest]; | |
775 | if (ps.dec_nest == 0 && !ps.in_parameter_declaration) | |
776 | ps.just_saw_decl = 2; | |
777 | ps.in_decl = true; | |
c6468b47 | 778 | } |
1009bf5e KM |
779 | prefix_blankline_requested = 0; |
780 | parse(rbrace); /* let parser know about this */ | |
781 | ps.search_brace = cuddle_else && ps.p_stack[ps.tos] == ifhead && ps.il[ps.tos] >= ps.ind_level; | |
782 | if (ps.tos <= 1 && blanklines_after_procs && ps.dec_nest <= 0) | |
783 | postfix_blankline_requested = 1; | |
c6468b47 KM |
784 | break; |
785 | ||
1009bf5e | 786 | case swstmt: /* got keyword "switch" */ |
c6468b47 | 787 | sp_sw = true; |
1009bf5e KM |
788 | hd_type = swstmt; /* keep this for when we have seen |
789 | * the expression */ | |
790 | goto copy_id; /* go move the token into buffer */ | |
c6468b47 | 791 | |
1009bf5e KM |
792 | case sp_paren: /* token is if, while, for */ |
793 | sp_sw = true; /* the interesting stuff is done after the | |
794 | * expression is scanned */ | |
c6468b47 | 795 | hd_type = (*token == 'i' ? ifstmt : |
1009bf5e KM |
796 | (*token == 'w' ? whilestmt : forstmt)); |
797 | ||
798 | /* | |
799 | * remember the type of header for later use by parser | |
800 | */ | |
801 | goto copy_id; /* copy the token into line */ | |
802 | ||
803 | case sp_nparen: /* got else, do */ | |
804 | ps.in_stmt = false; | |
805 | if (*token == 'e') { | |
806 | if (e_code != s_code && (!cuddle_else || e_code[-1] != '}')) { | |
807 | if (verbose) | |
808 | diag(0, "Line broken"); | |
809 | dump_line(); /* make sure this starts a line */ | |
810 | ps.want_blank = false; | |
811 | } | |
812 | force_nl = true; /* also, following stuff must go | |
813 | * onto new line */ | |
814 | last_else = 1; | |
815 | parse(elselit); | |
816 | } else { | |
817 | if (e_code != s_code) { /* make sure this starts a | |
818 | * line */ | |
819 | if (verbose) | |
820 | diag(0, "Line broken"); | |
821 | dump_line(); | |
822 | ps.want_blank = false; | |
823 | } | |
824 | force_nl = true; /* also, following stuff must go | |
825 | * onto new line */ | |
826 | last_else = 0; | |
827 | parse(dolit); | |
c6468b47 | 828 | } |
1009bf5e KM |
829 | goto copy_id; /* move the token into line */ |
830 | ||
831 | case decl: /* we have a declaration type (int, | |
832 | * register, etc.) */ | |
833 | parse(decl); /* let parser worry about indentation */ | |
834 | if (ps.last_token == rparen && ps.tos <= 1) | |
835 | ps.in_parameter_declaration = 1; | |
836 | if (ps.in_parameter_declaration && ps.indent_parameters && ps.dec_nest == 0) { | |
837 | ps.ind_level = ps.i_l_follow = 1; | |
838 | ps.ind_stmt = 0; | |
839 | } | |
840 | ps.in_or_st = true; /* this might be a structure or | |
841 | * initialization declaration */ | |
842 | ps.in_decl = ps.decl_on_line = true; | |
843 | if ( /* !ps.in_or_st && */ ps.dec_nest <= 0) | |
844 | ps.just_saw_decl = 2; | |
845 | prefix_blankline_requested = 0; | |
846 | for (i = 0; token[i++];); /* get length of token */ | |
847 | ||
848 | /* | |
849 | * dec_ind = e_code - s_code + (ps.decl_indent>i ? | |
850 | * ps.decl_indent : i); | |
851 | */ | |
852 | dec_ind = ps.decl_indent > 0 ? ps.decl_indent : i; | |
c6468b47 KM |
853 | goto copy_id; |
854 | ||
1009bf5e KM |
855 | case ident: /* got an identifier or constant */ |
856 | if (ps.in_decl) { /* if we are in a declaration, we | |
857 | * must indent identifier */ | |
858 | if (ps.want_blank) | |
c6468b47 | 859 | *e_code++ = ' '; |
1009bf5e KM |
860 | ps.want_blank = false; |
861 | if (is_procname == 0 || !procnames_start_line) { | |
862 | if (!ps.block_init) | |
863 | if (troff && !ps.dumped_decl_indent) { | |
864 | sprintf(e_code, "\\c\n.De %dp+\200p\n", dec_ind * 7); | |
865 | ps.dumped_decl_indent = 1; | |
866 | e_code += strlen(e_code); | |
867 | } else | |
868 | while ((e_code - s_code) < dec_ind) | |
869 | *e_code++ = ' '; | |
870 | } else { | |
871 | if (dec_ind && s_code != e_code) | |
872 | dump_line(); | |
873 | dec_ind = 0; | |
874 | ps.want_blank = false; | |
c6468b47 | 875 | } |
1009bf5e KM |
876 | } else if (sp_sw && ps.p_l_follow == 0) { |
877 | sp_sw = false; | |
878 | force_nl = true; | |
879 | ps.last_u_d = true; | |
880 | ps.in_stmt = false; | |
881 | parse(hd_type); | |
882 | } | |
883 | copy_id: | |
884 | if (ps.want_blank) | |
c6468b47 | 885 | *e_code++ = ' '; |
1009bf5e KM |
886 | if (troff && ps.its_a_keyword) { |
887 | *e_code++ = BACKSLASH; | |
888 | *e_code++ = 'f'; | |
889 | *e_code++ = 'B'; | |
890 | } | |
c6468b47 KM |
891 | for (t_ptr = token; *t_ptr; ++t_ptr) |
892 | *e_code++ = *t_ptr; | |
1009bf5e KM |
893 | if (troff && ps.its_a_keyword) { |
894 | *e_code++ = BACKSLASH; | |
895 | *e_code++ = 'f'; | |
896 | *e_code++ = 'R'; | |
897 | } | |
898 | ps.want_blank = true; | |
c6468b47 KM |
899 | break; |
900 | ||
1009bf5e KM |
901 | case period: /* treat a period kind of like a binary |
902 | * operation */ | |
903 | *e_code++ = '.';/* move the period into line */ | |
904 | ps.want_blank = false; /* dont put a blank after a period */ | |
c6468b47 KM |
905 | break; |
906 | ||
1009bf5e KM |
907 | case comma: |
908 | ps.want_blank = (s_code != e_code); /* only put blank after | |
909 | * comma if comma does | |
910 | * not start the line */ | |
911 | if (ps.in_decl && is_procname == 0 && !ps.block_init) | |
c6468b47 KM |
912 | while ((e_code - s_code) < (dec_ind - 1)) |
913 | *e_code++ = ' '; | |
914 | ||
915 | *e_code++ = ','; | |
1009bf5e KM |
916 | if (ps.p_l_follow == 0) { |
917 | ps.block_init = 0; | |
918 | if (break_comma && !ps.leave_comma) | |
919 | force_nl = true; | |
920 | } | |
c6468b47 KM |
921 | break; |
922 | ||
1009bf5e KM |
923 | case preesc: /* got the character '#' */ |
924 | if ((s_com != e_com) || | |
925 | (s_lab != e_lab) || | |
926 | (s_code != e_code)) | |
927 | dump_line(); | |
928 | *e_lab++ = '#'; /* move whole line to 'label' buffer */ | |
929 | { | |
930 | int in_comment = 0; | |
931 | char *com_start = 0; | |
932 | char quote = 0; | |
933 | char *com_end = 0; | |
934 | ||
935 | while (*buf_ptr != '\n' || in_comment) { | |
936 | *e_lab = *buf_ptr++; | |
937 | if (buf_ptr >= buf_end) | |
938 | fill_buffer(); | |
939 | switch (*e_lab++) { | |
940 | case BACKSLASH: | |
941 | if (troff) | |
942 | *e_lab++ = BACKSLASH; | |
943 | if (!in_comment) { | |
944 | *e_lab++ = *buf_ptr++; | |
945 | if (buf_ptr >= buf_end) | |
946 | fill_buffer(); | |
947 | } | |
948 | break; | |
949 | case '/': | |
950 | if (*buf_ptr == '*' && !in_comment && !quote) { | |
951 | in_comment = 1; | |
952 | *e_lab++ = *buf_ptr++; | |
953 | com_start = e_lab - 2; | |
954 | } | |
955 | break; | |
956 | case '"': | |
957 | if (quote == '"') | |
958 | quote = 0; | |
959 | break; | |
960 | case '\'': | |
961 | if (quote == '\'') | |
962 | quote = 0; | |
963 | break; | |
964 | case '*': | |
965 | if (*buf_ptr == '/' && in_comment) { | |
966 | in_comment = 0; | |
967 | *e_lab++ = *buf_ptr++; | |
968 | com_end = e_lab; | |
969 | } | |
970 | break; | |
971 | } | |
972 | } | |
973 | while (e_lab > s_lab && (e_lab[-1] == ' ' || e_lab[-1] == '\t')) | |
974 | e_lab--; | |
975 | if (e_lab == com_end && bp_save == 0) { /* comment on | |
976 | * preprocessor line */ | |
977 | if (sc_end == 0) /* if this is the first | |
978 | * comment, we must set up | |
979 | * the buffer */ | |
980 | sc_end = &(save_com[0]); | |
981 | else { | |
982 | *sc_end++ = '\n'; /* add newline between | |
983 | * comments */ | |
984 | *sc_end++ = ' '; | |
985 | --line_no; | |
986 | } | |
987 | bcopy(com_start, sc_end, com_end - com_start); | |
988 | sc_end += com_end - com_start; | |
989 | e_lab = com_start; | |
990 | while (e_lab > s_lab && (e_lab[-1] == ' ' || e_lab[-1] == '\t')) | |
991 | e_lab--; | |
992 | bp_save = buf_ptr; /* save current input | |
993 | * buffer */ | |
994 | be_save = buf_end; | |
995 | buf_ptr = save_com; /* fix so that subsequent | |
996 | * calls to lexi will take | |
997 | * tokens out of save_com */ | |
998 | *sc_end++ = ' '; /* add trailing blank, | |
999 | * just in case */ | |
1000 | buf_end = sc_end; | |
1001 | sc_end = 0; | |
1002 | } | |
1003 | *e_lab = '\0'; /* null terminate line */ | |
1004 | ps.pcase = false; | |
c6468b47 | 1005 | } |
1009bf5e KM |
1006 | if (strncmp(s_lab, "#if", 3) == 0) |
1007 | if (ifdef_level < sizeof state_stack / sizeof state_stack[0]) { | |
1008 | match_state[ifdef_level].tos = -1; | |
1009 | state_stack[ifdef_level++] = ps; | |
1010 | } else | |
1011 | diag(1, "#if stack overflow"); | |
1012 | else if (strncmp(s_lab, "#else", 5) == 0) | |
1013 | if (ifdef_level <= 0) | |
1014 | diag(1, "Unmatched #else"); | |
1015 | else { | |
1016 | match_state[ifdef_level - 1] = ps; | |
1017 | ps = state_stack[ifdef_level - 1]; | |
1018 | } else if (strncmp(s_lab, "#endif", 6) == 0) | |
1019 | if (ifdef_level <= 0) | |
1020 | diag(1, "Unmatched #endif"); | |
1021 | else { | |
1022 | ifdef_level--; | |
1023 | #ifdef undef | |
1024 | ||
1025 | /* | |
1026 | * This match needs to be more intelligent before | |
1027 | * the message is useful | |
1028 | */ | |
1029 | if (match_state[ifdef_level].tos >= 0 | |
1030 | && bcmp(&ps, &match_state[ifdef_level], sizeof ps)) | |
1031 | diag(0, "Syntactically inconsistant #ifdef alternatives."); | |
1032 | #endif | |
c6468b47 | 1033 | } |
1009bf5e KM |
1034 | break; /* subsequent processing of the newline |
1035 | * character will cause the line to be | |
1036 | * printed */ | |
1037 | ||
1038 | case comment: /* we have gotten a /* this is a biggie */ | |
1039 | proc_comment: | |
1040 | if (flushed_nl) { /* we should force a broken line | |
1041 | * here */ | |
1042 | flushed_nl = false; | |
1043 | dump_line(); | |
1044 | ps.want_blank = false; /* dont insert blank at | |
1045 | * line start */ | |
1046 | force_nl = false; | |
c6468b47 | 1047 | } |
1009bf5e | 1048 | pr_comment(); |
c6468b47 | 1049 | break; |
1009bf5e KM |
1050 | } /* end of big switch stmt */ |
1051 | *e_code = '\0'; /* make sure code section is null | |
1052 | * terminated */ | |
1053 | if (type_code != comment && type_code != newline && type_code != preesc) | |
1054 | ps.last_token = type_code; | |
1055 | } /* end of main while (1) loop */ | |
c6468b47 KM |
1056 | }; |
1057 | ||
1058 | /* | |
c93d6f87 KM |
1059 | * copy input file to backup file. If in_name is /blah/blah/blah/file, then |
1060 | * backup file will be "file.BAK". Then make the backup file the input and | |
1061 | * original input file the output. | |
c6468b47 | 1062 | */ |
1009bf5e KM |
1063 | bakcopy() |
1064 | { | |
1065 | int n, | |
1066 | bakchn; | |
c93d6f87 | 1067 | char buff[BUFSIZ]; |
1009bf5e | 1068 | register char *p; |
c93d6f87 | 1069 | char *rindex(); |
1009bf5e | 1070 | |
c93d6f87 | 1071 | if ((p = rindex(in_name, '/')) != NULL) |
c6468b47 | 1072 | p++; |
c93d6f87 KM |
1073 | else |
1074 | p = in_name; | |
1009bf5e | 1075 | sprintf(bakfile, "%s.BAK", p); |
c6468b47 | 1076 | |
1009bf5e KM |
1077 | /* copy in_name to backup file */ |
1078 | bakchn = creat(bakfile, 0600); | |
c6468b47 | 1079 | if (bakchn < 0) { |
c93d6f87 KM |
1080 | fprintf(stderr, "indent: can't create backup file \"%s\"\n", bakfile); |
1081 | exit(1); | |
1082 | } | |
1083 | while ((n = read(fileno(input), buff, sizeof buff)) > 0) | |
1084 | if (write(bakchn, buff, n) != n) { | |
1085 | fprintf(stderr, "indent: error writing backup file \"%s\"\n", | |
1086 | bakfile); | |
1087 | exit(1); | |
1088 | } | |
1089 | if (n < 0) { | |
1090 | fprintf(stderr, "indent: error reading input file \"%s\"\n", in_name); | |
1091 | exit(1); | |
c6468b47 | 1092 | } |
1009bf5e KM |
1093 | close(bakchn); |
1094 | fclose(input); | |
c6468b47 | 1095 | |
1009bf5e KM |
1096 | /* re-open backup file as the input file */ |
1097 | input = fopen(bakfile, "r"); | |
c93d6f87 KM |
1098 | if (input == NULL) { |
1099 | fprintf(stderr, "indent: can't re-open backup file\n"); | |
1100 | exit(1); | |
c6468b47 | 1101 | } |
1009bf5e KM |
1102 | /* now the original input file will be the output */ |
1103 | output = fopen(in_name, "w"); | |
c93d6f87 KM |
1104 | if (output == NULL) { |
1105 | fprintf(stderr, "indent: can't create %s\n", in_name); | |
1009bf5e | 1106 | unlink(bakfile); |
c93d6f87 | 1107 | exit(1); |
c6468b47 KM |
1108 | } |
1109 | } |