-w is obsolete
[unix-history] / usr / src / usr.bin / indent / io.c
CommitLineData
c0bc4ef7
DF
1/*
2 * Copyright (c) 1980 Regents of the University of California.
3 * All rights reserved. The Berkeley software License Agreement
4 * specifies the terms and conditions for redistribution.
5 */
6
7#ifndef lint
c93d6f87 8static char sccsid[] = "@(#)io.c 5.3 (Berkeley) %G%";
c0bc4ef7 9#endif not lint
87ba9e01 10
1009bf5e
KM
11/*-
12 * Copyright (C) 1976
13 * by the
14 * Board of Trustees
15 * of the
16 * University of Illinois
17 * All rights reserved
18 * FILE NAME:
19 * io.c
20 * PURPOSE:
21 * Contains routines to handle i/o related stuff for indent.
22 * GLOBALS:
23 * None
24 * FUNCTIONS:
25 * dump_line
26 * fill_buffer
27 * pad_output
28 * count_spaces
29 * eqin
30 * cmp
31 *
32 */\f
33/*-
34 *
35 * Copyright (C) 1976
36 * by the
37 * Board of Trustees
38 * of the
39 * University of Illinois
40 *
41 * All rights reserved
42 *
43 *
44 * NAME:
45 * dump_line
46 *
47 * FUNCTION:
48 * Does the actual printing of the stored up line
49 *
50 * ALGORITHM:
51 * For each of the label, code, and comment sections which are used on
52 * this line:
53 *
54 * 1) Use pad_output to get the section aligned properly.
55 * 2) write the section
56 *
57 * The indentation level used for the code is set by ps.ind_level. After
58 * printing, ps.ind_level is set to ps.i_l_follow.
59 *
60 * An extra level of indentation is added if ps.ind_stmt is 1. After
61 * printing, ps.ind_stmt is set to 1 iff the line just printed has an
62 * unterminated, non-declaration statement.
63 *
64 * HISTORY:
65 * initial coding November 1976 D A Willcox of CAC
66 *
67 */\f
87ba9e01
KM
68#include "indent_globs.h";
69
70
71
1009bf5e
KM
72int ff = 014; /* used to write a form feed */
73int comment_open;
74static paren_target;
87ba9e01 75
1009bf5e
KM
76dump_line()
77{ /* dump_line is the routine that actually
78 * effects the printing of the new source.
79 * It prints the label section, followed
80 * by the code section with the
81 * appropriate nesting level, followed by
82 * any comments */
83 register int cur_col,
84 temp_col,
85 target_col;
87ba9e01 86
1009bf5e
KM
87 if (ps.procname[0]) {
88 if (troff)
89 fprintf(output, ".Pr \"%s\"\n", ps.procname);
90 ps.ind_level = 0;
91 ps.procname[0] = 0;
92 }
93 if (s_code == e_code && s_lab == e_lab && s_com == e_com) {
94 if (suppress_blanklines>0) suppress_blanklines--;
87ba9e01 95 else {
1009bf5e
KM
96 ps.bl_line = true;
97 n_real_blanklines++;
87ba9e01 98 }
87ba9e01 99 }
1009bf5e
KM
100 else if (!inhibit_formatting) {
101 suppress_blanklines = 0;
102 ps.bl_line = false;
103 if (prefix_blankline_requested)
104 if (swallow_optional_blanklines) {
105 if (n_real_blanklines == 1)
106 n_real_blanklines = 0;
107 }
108 else {
109 if (n_real_blanklines == 0)
110 n_real_blanklines = 1;
111 }
112 while (--n_real_blanklines >= 0)
113 putc('\n', output);
114 n_real_blanklines = 0;
115 if (ps.ind_level == 0)
116 ps.ind_stmt = 0; /* this is a class A kludge. dont do
117 * additional statement indentation if we
118 * are at bracket level 0 */
119
120 if (e_lab != s_lab || e_code != s_code)
121 ++code_lines; /* keep count of lines with code */
122
123
124 if (e_lab != s_lab) { /* print lab, if any */
125 if (comment_open) {
126 comment_open = 0;
127 fprintf(output, ".*/\n");
128 }
129 while (e_lab > s_lab && (e_lab[-1] == ' ' || e_lab[-1] == '\t'))
130 e_lab--;
131 cur_col = pad_output(1, compute_label_target());
132 fprintf(output, "%.*s", e_lab - s_lab, s_lab);
133 cur_col = count_spaces(cur_col, s_lab);
87ba9e01 134 }
1009bf5e
KM
135 else
136 cur_col = 1; /* there is no label section */
137
138 ps.pcase = false;
139
140 if (s_code != e_code) { /* print code section, if any */
141 register char *p;
142
143 if (comment_open) {
144 comment_open = 0;
145 fprintf(output, ".*/\n");
146 }
147 target_col = compute_code_target();
148 {
149 register i;
150
151 for (i = 0; i < ps.p_l_follow; i++)
152 if (ps.paren_indents[i] >= 0)
153 ps.paren_indents[i] = -(ps.paren_indents[i] + target_col);
154 }
155 cur_col = pad_output(cur_col, target_col);
156 for (p = s_code; p < e_code; p++)
157 if (*p == 0200)
158 fprintf(output, "%d", target_col * 7);
159 else
160 putc(*p, output);
161 cur_col = count_spaces(cur_col, s_code);
162 }
163 if (s_com != e_com)
164 if (troff) {
165 register char *p;
166
167 if (e_com[-1] == '/' && e_com[-2] == '*')
168 e_com -= 2;
169 while (e_com > s_com && e_com[-1] == ' ')
170 e_com--;
171 *e_com = 0;
172 p = s_com;
173 while (*p == ' ')
174 p++;
175 if (p[0] == '/' && p[1] == '*')
176 p += 2;
177 else if (p[0] == '*')
178 p += p[1] == '/' ? 2 : 1;
179 while (*p == ' ')
180 p++;
181 if (*p == 0)
182 goto inhibit_newline;
183 if (!comment_open) {
184 if ('a' <= *p && *p <= 'z')
185 *p = *p + 'A' - 'a';
186 if (s_code != e_code || s_lab != e_lab) {
187 fprintf(output, "\\c\n./* %dp 1 %dp\n",
188 ps.com_col * 7, target_col * 7);
189 }
190 else
191 fprintf(output, "./* %dp 0 %dp\n",
192 ps.com_col * 7, target_col * 7);
193 }
194 comment_open = 1;
195 while (*p) {
196 if (*p == BACKSLASH)
197 putc(BACKSLASH, output);
198 putc(*p++, output);
199 }
200 }
201 else { /* print comment, if any */
202 register target = ps.com_col;
203 register char *com_st = s_com;
204
205 target += ps.comment_delta;
206 while (target <= 0)
207 if (*s_com == ' ')
208 target++, s_com++;
209 else if (*s_com == '\t')
210 target = ((target - 1) & ~7) + 9, s_com++;
211 else
212 target = 1;
213 if (cur_col > target) { /* if comment cant fit on this
214 * line, put it on next line */
215 putc('\n', output);
216 cur_col = 1;
217 ++ps.out_lines;
218 }
219 cur_col = pad_output(cur_col, target);
220 if (!ps.box_com) {
221 if (star_comment_cont && com_st[1] != '*')
222 if (com_st[1] == ' ' && com_st[0] == ' ')
223 com_st[1] = '*';
224 else
225 fwrite(" * ", com_st[0] == '\t' ? 2 : com_st[0] == '*' ? 1 : 3, 1, output);
226 }
227 fwrite(com_st, e_com - com_st, 1, output);
228 ps.comment_delta = ps.n_comment_delta;
229 cur_col = count_spaces(cur_col, com_st);
230 ++ps.com_lines; /* count lines with comments */
231 }
232 if (ps.use_ff)
233 putc('\014', output);
234 else
235 putc('\n', output);
236inhibit_newline:
237 ++ps.out_lines;
238 if (ps.just_saw_decl == 1 && blanklines_after_declarations) {
239 prefix_blankline_requested = 1;
240 ps.just_saw_decl = 0;
241 }
242 else
243 prefix_blankline_requested = postfix_blankline_requested;
244 postfix_blankline_requested = 0;
87ba9e01 245 }
1009bf5e
KM
246 ps.decl_on_line = ps.in_decl; /* if we are in the middle of a
247 * declaration, remember that fact
248 * for proper comment indentation */
249 ps.ind_stmt = ps.in_stmt & ~ps.in_decl; /* next line should be
250 * indented if we have not
251 * completed this stmt and
252 * if we are not in the
253 * middle of a declaration */
254 ps.use_ff = false;
255 ps.dumped_decl_indent = 0;
256 *(e_lab = s_lab) = '\0'; /* reset buffers */
87ba9e01
KM
257 *(e_code = s_code) = '\0';
258 *(e_com = s_com) = '\0';
1009bf5e
KM
259 ps.ind_level = ps.i_l_follow;
260 ps.paren_level = ps.p_l_follow;
261 paren_target = -ps.paren_indents[ps.paren_level - 1];
87ba9e01
KM
262 return;
263};
87ba9e01 264
1009bf5e
KM
265compute_code_target() {
266 register target_col = ps.ind_size * ps.ind_level + 1;
87ba9e01 267
1009bf5e
KM
268 if (ps.paren_level)
269 if (!lineup_to_parens)
270 target_col += continuation_indent * ps.paren_level;
271 else {
272 register w;
273 register t = paren_target;
274
275 if ((w = count_spaces(t, s_code) - max_col) > 0
276 && count_spaces(target_col, s_code) <= max_col) {
277 t -= w + 1;
278 if (t > target_col)
279 target_col = t;
280 }
281 else
282 target_col = t;
283 }
284 else if (ps.ind_stmt)
285 target_col += continuation_indent;
286 return target_col;
287}
87ba9e01 288
1009bf5e
KM
289compute_label_target()
290{
291 return
292 ps.pcase ? (int) (case_ind * ps.ind_size) +1
293 : *s_lab == '#' ? 1
294 : ps.ind_size * (ps.ind_level - label_offset) +1;
295}
87ba9e01 296
87ba9e01 297
1009bf5e
KM
298/*
299 * Copyright (C) 1976 by the Board of Trustees of the University of
300 * Illinois
301 *
302 * All rights reserved
303 *
304 *
305 * NAME: fill_buffer
306 *
307 * FUNCTION: Reads one block of input into input_buffer
308 *
309 * HISTORY: initial coding November 1976 D A Willcox of CAC 1/7/77
310 * A Willcox of CAC Added check for switch back to partly full input
311 * buffer from temporary buffer
312 *
313 */\f
314int
315fill_buffer()
316{ /* this routine reads stuff from the input */
317 int count;
318 register char *p;
319 register int i;
320 register FILE *f = input;
321
322 if (bp_save != 0) { /* there is a partly filled input buffer
323 * left */
324 buf_ptr = bp_save; /* dont read anything, just switch buffers */
87ba9e01
KM
325 buf_end = be_save;
326 bp_save = be_save = 0;
327 if (buf_ptr < buf_end)
1009bf5e
KM
328 return; /* only return if there is really
329 * something in this buffer */
87ba9e01 330 }
1009bf5e
KM
331 p = in_buffer;
332 buf_ptr = p;
333 while ((*p++ = i = getc(f)) != EOF && i != '\n');
334 if (i == EOF) {
335 p[-1] = ' ';
336 *p++ = '\n';
87ba9e01 337 had_eof = true;
87ba9e01 338 }
1009bf5e
KM
339 buf_end = p;
340 if (p[-2] == '/' && p[-3] == '*') {
341 if (in_buffer[3] == 'I' && strncmp(in_buffer, "/**INDENT**", 11) == 0)
342 fill_buffer(); /* flush indent error message */
343 else {
344 int com = 0;
345
346 p = in_buffer;
347 while (*p == ' ' || *p == '\t')
348 p++;
349 if (*p == '/' && p[1] == '*') {
350 p += 2;
351 while (*p == ' ' || *p == '\t')
352 p++;
353 if (p[0] == 'I' && p[1] == 'N' && p[2] == 'D' && p[3] == 'E'
354 && p[4] == 'N' && p[5] == 'T') {
355 p += 6;
356 while (*p == ' ' || *p == '\t')
357 p++;
358 if (*p == '*')
359 com = 1;
360 else if (*p == 'O')
361 if (*++p == 'N')
362 p++, com = 1;
363 else if (*p == 'F' && *++p == 'F')
364 p++, com = 2;
365 while (*p == ' ' || *p == '\t')
366 p++;
367 if (p[0] == '*' && p[1] == '/' && p[2] == '\n' && com) {
368 if (s_com != e_com || s_lab != e_lab || s_code != e_code)
369 dump_line();
370 if (!(inhibit_formatting = com - 1)) {
371 n_real_blanklines = 0;
372 postfix_blankline_requested = 0;
373 prefix_blankline_requested = 0;
374 suppress_blanklines = 1;
375 }
376 }
377 }
378 }
379 }
380 }
381 if (inhibit_formatting) {
382 p = in_buffer;
383 do
384 putc(*p, output);
385 while (*p++ != '\n');
386 }
87ba9e01
KM
387 return;
388};
87ba9e01 389
1009bf5e
KM
390/*
391 * Copyright (C) 1976 by the Board of Trustees of the University of
392 * Illinois
393 *
394 * All rights reserved
395 *
396 *
397 * NAME: pad_output
398 *
399 * FUNCTION: Writes tabs and spaces to move the current column up to the
400 * desired position.
401 *
402 * ALGORITHM: Put tabs and/or blanks into pobuf, then write pobuf.
403 *
404 * PARAMETERS: current integer The current column target
405 * nteger The desired column
406 *
407 * RETURNS: Integer value of the new column. (If current >= target, no
408 * action is taken, and current is returned.
409 *
410 * GLOBALS: None
411 *
412 * CALLS: write (sys)
413 *
414 * CALLED BY: dump_line
415 *
416 * HISTORY: initial coding November 1976 D A Willcox of CAC
417 *
418 */\f
419pad_output(current, target) /* writes tabs and blanks (if necessary)
420 * to get the current output position up
421 * to the target column */
422 int current; /* the current column value */
423 int target; /* position we want it at */
87ba9e01 424{
1009bf5e 425 register int curr; /* internal column pointer */
87ba9e01
KM
426 register int tcur;
427
1009bf5e
KM
428 if (troff)
429 fprintf(output, "\\h'|%dp'", (target - 1) * 7);
430 else {
431 if (current >= target)
432 return (current); /* line is already long enough */
433 curr = current;
434 while ((tcur = ((curr - 1) & tabmask) + tabsize + 1) <= target) {
435 putc('\t', output);
87ba9e01
KM
436 curr = tcur;
437 }
1009bf5e
KM
438 while (curr++ < target)
439 putc(' ', output); /* pad with final blanks */
87ba9e01 440 }
87ba9e01
KM
441 return (target);
442};
87ba9e01 443
1009bf5e
KM
444/*
445 * Copyright (C) 1976 by the Board of Trustees of the University of
446 * Illinois
447 *
448 * All rights reserved
449 *
450 *
451 * NAME: count_spaces
452 *
453 * FUNCTION: Find out where printing of a given string will leave the current
454 * character position on output.
455 *
456 * ALGORITHM: Run thru input string and add appropriate values to current
457 * position.
458 *
459 * RETURNS: Integer value of position after printing "buffer" starting in
460 * column "current".
461 *
462 * HISTORY: initial coding November 1976 D A Willcox of CAC
463 *
464 */\f
465int
466count_spaces(current, buffer)
87ba9e01 467
1009bf5e
KM
468/*
469 * this routine figures out where the character position will be after
470 * printing the text in buffer starting at column "current"
471 */
472 int current;
473 char *buffer;
87ba9e01 474{
1009bf5e
KM
475 register char *buf; /* used to look thru buffer */
476 register int cur; /* current character counter */
87ba9e01
KM
477
478 cur = current;
479
480 for (buf = buffer; *buf != '\0'; ++buf) {
481 switch (*buf) {
482
1009bf5e
KM
483 case '\n':
484 case 014: /* form feed */
87ba9e01
KM
485 cur = 1;
486 break;
487
1009bf5e 488 case '\t':
87ba9e01
KM
489 cur = ((cur - 1) & tabmask) + tabsize + 1;
490 break;
491
1009bf5e 492 case '\b': /* this is a backspace */
87ba9e01
KM
493 --cur;
494 break;
495
1009bf5e 496 default:
87ba9e01
KM
497 ++cur;
498 break;
1009bf5e
KM
499 } /* end of switch */
500 } /* end of for loop */
87ba9e01
KM
501 return (cur);
502};
87ba9e01 503
1009bf5e 504diag(level, msg, a, b)
87ba9e01 505{
1009bf5e
KM
506 if (output == stdout) {
507 fprintf(stdout, "/**INDENT** %s@%d: ", level == 0 ? "Warning" : "Error", line_no);
508 fprintf(stdout, msg, a, b);
509 fprintf(stdout, " */\n");
87ba9e01 510 }
1009bf5e
KM
511 else {
512 fprintf(stderr, "%s@%d: ", level == 0 ? "Warning" : "Error", line_no);
513 fprintf(stderr, msg, a, b);
514 fprintf(stderr, "\n");
87ba9e01 515 }
87ba9e01 516}