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