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