Annotation of src/usr.bin/indent/io.c, Revision 1.2
1.2 ! deraadt 1: /* $OpenBSD$ */
! 2:
1.1 deraadt 3: /*
4: * Copyright (c) 1985 Sun Microsystems, Inc.
5: * Copyright (c) 1980 The Regents of the University of California.
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
39: /*static char sccsid[] = "from: @(#)io.c 5.15 (Berkeley) 2/26/91";*/
1.2 ! deraadt 40: static char rcsid[] = "$OpenBSD: io.c,v 1.1.1.1 1995/10/18 08:45:25 deraadt 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>
47: #include "indent_globs.h"
48:
49:
50: int comment_open;
51: static paren_target;
52:
53: dump_line()
54: { /* dump_line is the routine that actually
55: * effects the printing of the new source. It
56: * prints the label section, followed by the
57: * code section with the appropriate nesting
58: * level, followed by any comments */
59: register int cur_col,
60: target_col;
61: static not_first_line;
62:
63: if (ps.procname[0]) {
64: if (troff) {
65: if (comment_open) {
66: comment_open = 0;
67: fprintf(output, ".*/\n");
68: }
69: fprintf(output, ".Pr \"%s\"\n", ps.procname);
70: }
71: ps.ind_level = 0;
72: ps.procname[0] = 0;
73: }
74: if (s_code == e_code && s_lab == e_lab && s_com == e_com) {
75: if (suppress_blanklines > 0)
76: suppress_blanklines--;
77: else {
78: ps.bl_line = true;
79: n_real_blanklines++;
80: }
81: }
82: else if (!inhibit_formatting) {
83: suppress_blanklines = 0;
84: ps.bl_line = false;
85: if (prefix_blankline_requested && not_first_line)
86: if (swallow_optional_blanklines) {
87: if (n_real_blanklines == 1)
88: n_real_blanklines = 0;
89: }
90: else {
91: if (n_real_blanklines == 0)
92: n_real_blanklines = 1;
93: }
94: while (--n_real_blanklines >= 0)
95: putc('\n', output);
96: n_real_blanklines = 0;
97: if (ps.ind_level == 0)
98: ps.ind_stmt = 0; /* this is a class A kludge. dont do
99: * additional statement indentation if we are
100: * at bracket level 0 */
101:
102: if (e_lab != s_lab || e_code != s_code)
103: ++code_lines; /* keep count of lines with code */
104:
105:
106: if (e_lab != s_lab) { /* print lab, if any */
107: if (comment_open) {
108: comment_open = 0;
109: fprintf(output, ".*/\n");
110: }
111: while (e_lab > s_lab && (e_lab[-1] == ' ' || e_lab[-1] == '\t'))
112: e_lab--;
113: cur_col = pad_output(1, compute_label_target());
114: if (s_lab[0] == '#' && (strncmp(s_lab, "#else", 5) == 0
115: || strncmp(s_lab, "#endif", 6) == 0)) {
116: register char *s = s_lab;
117: if (e_lab[-1] == '\n') e_lab--;
118: do putc(*s++, output);
119: while (s < e_lab && 'a' <= *s && *s<='z');
120: while ((*s == ' ' || *s == '\t') && s < e_lab)
121: s++;
122: if (s < e_lab)
123: fprintf(output, s[0]=='/' && s[1]=='*' ? "\t%.*s" : "\t/* %.*s */",
124: e_lab - s, s);
125: }
126: else fprintf(output, "%.*s", e_lab - s_lab, s_lab);
127: cur_col = count_spaces(cur_col, s_lab);
128: }
129: else
130: cur_col = 1; /* there is no label section */
131:
132: ps.pcase = false;
133:
134: if (s_code != e_code) { /* print code section, if any */
135: register char *p;
136:
137: if (comment_open) {
138: comment_open = 0;
139: fprintf(output, ".*/\n");
140: }
141: target_col = compute_code_target();
142: {
143: register i;
144:
145: for (i = 0; i < ps.p_l_follow; i++)
146: if (ps.paren_indents[i] >= 0)
147: ps.paren_indents[i] = -(ps.paren_indents[i] + target_col);
148: }
149: cur_col = pad_output(cur_col, target_col);
150: for (p = s_code; p < e_code; p++)
151: if (*p == (char) 0200)
152: fprintf(output, "%d", target_col * 7);
153: else
154: putc(*p, output);
155: cur_col = count_spaces(cur_col, s_code);
156: }
157: if (s_com != e_com)
158: if (troff) {
159: int all_here = 0;
160: register char *p;
161:
162: if (e_com[-1] == '/' && e_com[-2] == '*')
163: e_com -= 2, all_here++;
164: while (e_com > s_com && e_com[-1] == ' ')
165: e_com--;
166: *e_com = 0;
167: p = s_com;
168: while (*p == ' ')
169: p++;
170: if (p[0] == '/' && p[1] == '*')
171: p += 2, all_here++;
172: else if (p[0] == '*')
173: p += p[1] == '/' ? 2 : 1;
174: while (*p == ' ')
175: p++;
176: if (*p == 0)
177: goto inhibit_newline;
178: if (comment_open < 2 && ps.box_com) {
179: comment_open = 0;
180: fprintf(output, ".*/\n");
181: }
182: if (comment_open == 0) {
183: if ('a' <= *p && *p <= 'z')
184: *p = *p + 'A' - 'a';
185: if (e_com - p < 50 && all_here == 2) {
186: register char *follow = p;
187: fprintf(output, "\n.nr C! \\w\1");
188: while (follow < e_com) {
189: switch (*follow) {
190: case '\n':
191: putc(' ', output);
192: case 1:
193: break;
194: case '\\':
195: putc('\\', output);
196: default:
197: putc(*follow, output);
198: }
199: follow++;
200: }
201: putc(1, output);
202: }
203: fprintf(output, "\n./* %dp %d %dp\n",
204: ps.com_col * 7,
205: (s_code != e_code || s_lab != e_lab) - ps.box_com,
206: target_col * 7);
207: }
208: comment_open = 1 + ps.box_com;
209: while (*p) {
210: if (*p == BACKSLASH)
211: putc(BACKSLASH, output);
212: putc(*p++, output);
213: }
214: }
215: else { /* print comment, if any */
216: register target = ps.com_col;
217: register char *com_st = s_com;
218:
219: target += ps.comment_delta;
220: while (*com_st == '\t')
221: com_st++, target += 8; /* ? */
222: while (target <= 0)
223: if (*com_st == ' ')
224: target++, com_st++;
225: else if (*com_st == '\t')
226: target = ((target - 1) & ~7) + 9, com_st++;
227: else
228: target = 1;
229: if (cur_col > target) { /* if comment cant fit on this line,
230: * put it on next line */
231: putc('\n', output);
232: cur_col = 1;
233: ++ps.out_lines;
234: }
235: while (e_com > com_st && isspace(e_com[-1]))
236: e_com--;
237: cur_col = pad_output(cur_col, target);
238: if (!ps.box_com) {
239: if (star_comment_cont && (com_st[1] != '*' || e_com <= com_st + 1))
240: if (com_st[1] == ' ' && com_st[0] == ' ' && e_com > com_st + 1)
241: com_st[1] = '*';
242: else
243: fwrite(" * ", com_st[0] == '\t' ? 2 : com_st[0] == '*' ? 1 : 3, 1, output);
244: }
245: fwrite(com_st, e_com - com_st, 1, output);
246: ps.comment_delta = ps.n_comment_delta;
247: cur_col = count_spaces(cur_col, com_st);
248: ++ps.com_lines; /* count lines with comments */
249: }
250: if (ps.use_ff)
251: putc('\014', output);
252: else
253: putc('\n', output);
254: inhibit_newline:
255: ++ps.out_lines;
256: if (ps.just_saw_decl == 1 && blanklines_after_declarations) {
257: prefix_blankline_requested = 1;
258: ps.just_saw_decl = 0;
259: }
260: else
261: prefix_blankline_requested = postfix_blankline_requested;
262: postfix_blankline_requested = 0;
263: }
264: ps.decl_on_line = ps.in_decl; /* if we are in the middle of a
265: * declaration, remember that fact for
266: * proper comment indentation */
267: ps.ind_stmt = ps.in_stmt & ~ps.in_decl; /* next line should be
268: * indented if we have not
269: * completed this stmt and if
270: * we are not in the middle of
271: * a declaration */
272: ps.use_ff = false;
273: ps.dumped_decl_indent = 0;
274: *(e_lab = s_lab) = '\0'; /* reset buffers */
275: *(e_code = s_code) = '\0';
276: *(e_com = s_com) = '\0';
277: ps.ind_level = ps.i_l_follow;
278: ps.paren_level = ps.p_l_follow;
279: paren_target = -ps.paren_indents[ps.paren_level - 1];
280: not_first_line = 1;
281: return;
282: }
283:
284: compute_code_target()
285: {
286: register target_col = ps.ind_size * ps.ind_level + 1;
287:
288: if (ps.paren_level)
289: if (!lineup_to_parens)
290: target_col += continuation_indent * ps.paren_level;
291: else {
292: register w;
293: register t = paren_target;
294:
295: if ((w = count_spaces(t, s_code) - max_col) > 0
296: && count_spaces(target_col, s_code) <= max_col) {
297: t -= w + 1;
298: if (t > target_col)
299: target_col = t;
300: }
301: else
302: target_col = t;
303: }
304: else if (ps.ind_stmt)
305: target_col += continuation_indent;
306: return target_col;
307: }
308:
309: compute_label_target()
310: {
311: return
312: ps.pcase ? (int) (case_ind * ps.ind_size) + 1
313: : *s_lab == '#' ? 1
314: : ps.ind_size * (ps.ind_level - label_offset) + 1;
315: }
316:
317:
318: /*
319: * Copyright (C) 1976 by the Board of Trustees of the University of Illinois
320: *
321: * All rights reserved
322: *
323: *
324: * NAME: fill_buffer
325: *
326: * FUNCTION: Reads one block of input into input_buffer
327: *
328: * HISTORY: initial coding November 1976 D A Willcox of CAC 1/7/77 A
329: * Willcox of CAC Added check for switch back to partly full input
330: * buffer from temporary buffer
331: *
332: */
333: int
334: fill_buffer()
335: { /* this routine reads stuff from the input */
336: register char *p;
337: register int i;
338: register FILE *f = input;
339:
340: if (bp_save != 0) { /* there is a partly filled input buffer left */
341: buf_ptr = bp_save; /* dont read anything, just switch buffers */
342: buf_end = be_save;
343: bp_save = be_save = 0;
344: if (buf_ptr < buf_end)
345: return; /* only return if there is really something in
346: * this buffer */
347: }
348: for (p = in_buffer;;) {
349: if (p >= in_buffer_limit) {
350: register size = (in_buffer_limit - in_buffer) * 2 + 10;
351: register offset = p - in_buffer;
352: in_buffer = (char *) realloc(in_buffer, size);
353: if (in_buffer == 0)
354: err("input line too long");
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;
370: if (p[-2] == '/' && p[-3] == '*') {
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;
390: else if (*p == 'O')
391: if (*++p == 'N')
392: p++, com = 1;
393: else if (*p == 'F' && *++p == 'F')
394: p++, com = 2;
395: while (*p == ' ' || *p == '\t')
396: p++;
397: if (p[0] == '*' && p[1] == '/' && p[2] == '\n' && com) {
398: if (s_com != e_com || s_lab != e_lab || s_code != e_code)
399: dump_line();
400: if (!(inhibit_formatting = com - 1)) {
401: n_real_blanklines = 0;
402: postfix_blankline_requested = 0;
403: prefix_blankline_requested = 0;
404: suppress_blanklines = 1;
405: }
406: }
407: }
408: }
409: }
410: }
411: if (inhibit_formatting) {
412: p = in_buffer;
413: do
414: putc(*p, output);
415: while (*p++ != '\n');
416: }
417: return;
418: }
419:
420: /*
421: * Copyright (C) 1976 by the Board of Trustees of the University of Illinois
422: *
423: * All rights reserved
424: *
425: *
426: * NAME: pad_output
427: *
428: * FUNCTION: Writes tabs and spaces to move the current column up to the desired
429: * position.
430: *
431: * ALGORITHM: Put tabs and/or blanks into pobuf, then write pobuf.
432: *
433: * PARAMETERS: current integer The current column target
434: * nteger The desired column
435: *
436: * RETURNS: Integer value of the new column. (If current >= target, no action is
437: * taken, and current is returned.
438: *
439: * GLOBALS: None
440: *
441: * CALLS: write (sys)
442: *
443: * CALLED BY: dump_line
444: *
445: * HISTORY: initial coding November 1976 D A Willcox of CAC
446: *
447: */
448: pad_output(current, target) /* writes tabs and blanks (if necessary) to
449: * get the current output position up to the
450: * target column */
451: int current; /* the current column value */
452: int target; /* position we want it at */
453: {
454: register int curr; /* internal column pointer */
455: register int tcur;
456:
457: if (troff)
458: fprintf(output, "\\h'|%dp'", (target - 1) * 7);
459: else {
460: if (current >= target)
461: return (current); /* line is already long enough */
462: curr = current;
463: while ((tcur = ((curr - 1) & tabmask) + tabsize + 1) <= target) {
464: putc('\t', output);
465: curr = tcur;
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
494: count_spaces(current, buffer)
495: /*
496: * this routine figures out where the character position will be after
497: * printing the text in buffer starting at column "current"
498: */
499: int current;
500: char *buffer;
501: {
502: register char *buf; /* used to look thru buffer */
503: register int cur; /* current character counter */
504:
505: cur = current;
506:
507: for (buf = buffer; *buf != '\0'; ++buf) {
508: switch (*buf) {
509:
510: case '\n':
511: case 014: /* form feed */
512: cur = 1;
513: break;
514:
515: case '\t':
516: cur = ((cur - 1) & tabmask) + tabsize + 1;
517: break;
518:
519: case 010: /* backspace */
520: --cur;
521: break;
522:
523: default:
524: ++cur;
525: break;
526: } /* end of switch */
527: } /* end of for loop */
528: return (cur);
529: }
530:
531: int found_err;
532: /* VARARGS2 */
533: diag(level, msg, a, b)
534: char *msg;
535: {
536: if (level)
537: found_err = 1;
538: if (output == stdout) {
539: fprintf(stdout, "/**INDENT** %s@%d: ", level == 0 ? "Warning" : "Error", line_no);
540: fprintf(stdout, msg, a, b);
541: fprintf(stdout, " */\n");
542: }
543: else {
544: fprintf(stderr, "%s@%d: ", level == 0 ? "Warning" : "Error", line_no);
545: fprintf(stderr, msg, a, b);
546: fprintf(stderr, "\n");
547: }
548: }
549:
550: writefdef(f, nm)
551: register struct fstate *f;
552: {
553: fprintf(output, ".ds f%c %s\n.nr s%c %d\n",
554: nm, f->font, nm, f->size);
555: }
556:
557: char *
558: chfont(of, nf, s)
559: register struct fstate *of,
560: *nf;
561: char *s;
562: {
563: if (of->font[0] != nf->font[0]
564: || of->font[1] != nf->font[1]) {
565: *s++ = '\\';
566: *s++ = 'f';
567: if (nf->font[1]) {
568: *s++ = '(';
569: *s++ = nf->font[0];
570: *s++ = nf->font[1];
571: }
572: else
573: *s++ = nf->font[0];
574: }
575: if (nf->size != of->size) {
576: *s++ = '\\';
577: *s++ = 's';
578: if (nf->size < of->size) {
579: *s++ = '-';
580: *s++ = '0' + of->size - nf->size;
581: }
582: else {
583: *s++ = '+';
584: *s++ = '0' + nf->size - of->size;
585: }
586: }
587: return s;
588: }
589:
590:
591: parsefont(f, s0)
592: register struct fstate *f;
593: char *s0;
594: {
595: register char *s = s0;
596: int sizedelta = 0;
597: bzero(f, sizeof *f);
598: while (*s) {
599: if (isdigit(*s))
600: f->size = f->size * 10 + *s - '0';
601: else if (isupper(*s))
602: if (f->font[0])
603: f->font[1] = *s;
604: else
605: f->font[0] = *s;
606: else if (*s == 'c')
607: f->allcaps = 1;
608: else if (*s == '+')
609: sizedelta++;
610: else if (*s == '-')
611: sizedelta--;
612: else {
613: fprintf(stderr, "indent: bad font specification: %s\n", s0);
614: exit(1);
615: }
616: s++;
617: }
618: if (f->font[0] == 0)
619: f->font[0] = 'R';
620: if (bodyf.size == 0)
621: bodyf.size = 11;
622: if (f->size == 0)
623: f->size = bodyf.size + sizedelta;
624: else if (sizedelta > 0)
625: f->size += bodyf.size;
626: else
627: f->size = bodyf.size - f->size;
628: }