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