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