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