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