|
|
1.1 root 1: /****************************************************************
2: Copyright 1990, 1991, 1993 by AT&T Bell Laboratories and Bellcore.
3:
4: Permission to use, copy, modify, and distribute this software
5: and its documentation for any purpose and without fee is hereby
6: granted, provided that the above copyright notice appear in all
7: copies and that both that the copyright notice and this
8: permission notice and warranty disclaimer appear in supporting
9: documentation, and that the names of AT&T Bell Laboratories or
10: Bellcore or any of their entities not be used in advertising or
11: publicity pertaining to distribution of the software without
12: specific, written prior permission.
13:
14: AT&T and Bellcore disclaim all warranties with regard to this
15: software, including all implied warranties of merchantability
16: and fitness. In no event shall AT&T or Bellcore be liable for
17: any special, indirect or consequential damages or any damages
18: whatsoever resulting from loss of use, data or profits, whether
19: in an action of contract, negligence or other tortious action,
20: arising out of or in connection with the use or performance of
21: this software.
22: ****************************************************************/
23:
24: #include "defs.h"
25: #include "names.h"
26: #include "output.h"
27:
28: #define TOO_LONG_INDENT (2 * tab_size)
29: #define MAX_INDENT 44
30: #define MIN_INDENT 22
31: static int last_was_newline = 0;
32: int indent = 0;
33: int in_comment = 0;
34: int in_define = 0;
35: extern int gflag1;
36: extern char *file_name;
37:
38: static int
39: write_indent(fp, use_indent, extra_indent, start, end)
40: FILE *fp;
41: int use_indent, extra_indent;
42: char *start, *end;
43: {
44: int ind, tab;
45:
46: if (gflag1 && last_was_newline)
47: fprintf(fp, "#line %ld \"%s\"\n", lineno, file_name);
48: if (in_define == 1) {
49: in_define = 2;
50: use_indent = 0;
51: }
52: if (last_was_newline && use_indent) {
53: if (*start == '\n') do {
54: putc('\n', fp);
55: if (++start > end)
56: return;
57: }
58: while(*start == '\n');
59:
60: ind = indent <= MAX_INDENT
61: ? indent
62: : MIN_INDENT + indent % (MAX_INDENT - MIN_INDENT);
63:
64: tab = ind + extra_indent;
65:
66: while (tab > 7) {
67: putc ('\t', fp);
68: tab -= 8;
69: } /* while */
70:
71: while (tab-- > 0)
72: putc (' ', fp);
73: } /* if last_was_newline */
74:
75: while (start <= end)
76: putc (*start++, fp);
77: } /* write_indent */
78:
79:
80: /*VARARGS2*/
81: int margin_printf (fp, a, b, c, d, e, f, g)
82: FILE *fp;
83: char *a;
84: long b, c, d, e, f, g;
85: {
86: ind_printf (0, fp, a, b, c, d, e, f, g);
87: } /* margin_printf */
88:
89: /*VARARGS2*/
90: int nice_printf (fp, a, b, c, d, e, f, g)
91: FILE *fp;
92: char *a;
93: long b, c, d, e, f, g;
94: {
95: ind_printf (1, fp, a, b, c, d, e, f, g);
96: } /* nice_printf */
97:
98:
99: #define max_line_len c_output_line_length
100: /* 74Number of characters allowed on an output
101: line. This assumes newlines are handled
102: nicely, i.e. a newline after a full text
103: line on a terminal is ignored */
104:
105: /* output_buf holds the text of the next line to be printed. It gets
106: flushed when a newline is printed. next_slot points to the next
107: available location in the output buffer, i.e. where the next call to
108: nice_printf will have its output stored */
109:
110: static char *output_buf;
111: static char *next_slot;
112: static char *string_start;
113:
114: static char *word_start = NULL;
115: static int cursor_pos = 0;
116: static int In_string = 0;
117:
118: void
119: np_init()
120: {
121: next_slot = output_buf = Alloc(MAX_OUTPUT_SIZE);
122: memset(output_buf, 0, MAX_OUTPUT_SIZE);
123: }
124:
125: static char *
126: adjust_pointer_in_string(pointer)
127: register char *pointer;
128: {
129: register char *s, *s1, *se, *s0;
130:
131: /* arrange not to break \002 */
132: s1 = string_start ? string_start : output_buf;
133: for(s = s1; s < pointer; s++) {
134: s0 = s1;
135: s1 = s;
136: if (*s == '\\') {
137: se = s++ + 4;
138: if (se > pointer)
139: break;
140: if (*s < '0' || *s > '7')
141: continue;
142: while(++s < se)
143: if (*s < '0' || *s > '7')
144: break;
145: --s;
146: }
147: }
148: return s0 - 1;
149: }
150:
151: /* ANSI says strcpy's behavior is undefined for overlapping args,
152: * so we roll our own fwd_strcpy: */
153:
154: static void
155: fwd_strcpy(t, s)
156: register char *t, *s;
157: { while(*t++ = *s++); }
158:
159: /* isident -- true iff character could belong to a unit. C allows
160: letters, numbers and underscores in identifiers. This also doubles as
161: a check for numeric constants, since we include the decimal point and
162: minus sign. The minus has to be here, since the constant "10e-2"
163: cannot be broken up. The '.' also prevents structure references from
164: being broken, which is a quite acceptable side effect */
165:
166: #define isident(x) (Tr[x] & 1)
167: #define isntident(x) (!Tr[x])
168:
169: int ind_printf (use_indent, fp, a, b, c, d, e, f, g)
170: int use_indent;
171: FILE *fp;
172: char *a;
173: long b, c, d, e, f, g;
174: {
175: extern int max_line_len;
176: extern FILEP c_file;
177: extern char tr_tab[]; /* in output.c */
178: register char *Tr = tr_tab;
179: int ch, inc, ind;
180: static int extra_indent, last_indent, set_cursor = 1;
181:
182: cursor_pos += indent - last_indent;
183: last_indent = indent;
184: sprintf (next_slot, a, b, c, d, e, f, g);
185:
186: if (fp != c_file) {
187: fprintf (fp,"%s", next_slot);
188: return 1;
189: } /* if fp != c_file */
190:
191: do {
192: char *pointer;
193:
194: /* The for loop will parse one output line */
195:
196: if (set_cursor) {
197: ind = indent <= MAX_INDENT
198: ? indent
199: : MIN_INDENT + indent % (MAX_INDENT - MIN_INDENT);
200: cursor_pos = ind + extra_indent;
201: set_cursor = 0;
202: }
203: if (in_comment)
204: for (pointer = next_slot; *pointer && *pointer != '\n' &&
205: cursor_pos <= max_line_len; pointer++)
206: cursor_pos++;
207: else
208: for (pointer = next_slot; *pointer && *pointer != '\n' &&
209: cursor_pos <= max_line_len; pointer++) {
210:
211: /* Update state variables here */
212:
213: if (In_string) {
214: switch(*pointer) {
215: case '\\':
216: if (++cursor_pos > max_line_len) {
217: cursor_pos -= 2;
218: --pointer;
219: goto overflow;
220: }
221: ++pointer;
222: break;
223: case '"':
224: In_string = 0;
225: word_start = 0;
226: }
227: }
228: else switch (*pointer) {
229: case '"':
230: if (cursor_pos + 5 > max_line_len) {
231: word_start = 0;
232: --pointer;
233: goto overflow;
234: }
235: In_string = 1;
236: string_start = word_start = pointer;
237: break;
238: case '\'':
239: if (pointer[1] == '\\')
240: if ((ch = pointer[2]) >= '0' && ch <= '7')
241: for(inc = 3; pointer[inc] != '\''
242: && ++inc < 5;);
243: else
244: inc = 3;
245: else
246: inc = 2;
247: /*debug*/ if (pointer[inc] != '\'')
248: /*debug*/ fatalstr("Bad character constant %.10s",
249: pointer);
250: if ((cursor_pos += inc) > max_line_len) {
251: cursor_pos -= inc;
252: word_start = 0;
253: --pointer;
254: goto overflow;
255: }
256: word_start = pointer;
257: pointer += inc;
258: break;
259: case '\t':
260: cursor_pos = 8 * ((cursor_pos + 8) / 8) - 1;
261: break;
262: default: {
263:
264: /* HACK Assumes that all characters in an atomic C token will be written
265: at the same time. Must check for tokens first, since '-' is considered
266: part of an identifier; checking isident first would mean breaking up "->" */
267:
268: if (word_start) {
269: if (isntident(*(unsigned char *)pointer))
270: word_start = NULL;
271: }
272: else if (isident(*(unsigned char *)pointer))
273: word_start = pointer;
274: break;
275: } /* default */
276: } /* switch */
277: cursor_pos++;
278: } /* for pointer = next_slot */
279: overflow:
280: if (*pointer == '\0') {
281:
282: /* The output line is not complete, so break out and don't output
283: anything. The current line fragment will be stored in the buffer */
284:
285: next_slot = pointer;
286: break;
287: } else {
288: char last_char;
289: int in_string0 = In_string;
290:
291: /* If the line was too long, move pointer back to the character before
292: the current word. This allows line breaking on word boundaries. Make
293: sure that 80 character comment lines get broken up somehow. We assume
294: that any non-string 80 character identifier must be in a comment.
295: */
296:
297: if (*pointer == '\n')
298: in_define = 0;
299: else if (word_start && word_start > output_buf)
300: if (In_string)
301: if (string_start && pointer - string_start < 5)
302: pointer = string_start - 1;
303: else {
304: pointer = adjust_pointer_in_string(pointer);
305: string_start = 0;
306: }
307: else if (word_start == string_start
308: && pointer - string_start >= 5) {
309: pointer = adjust_pointer_in_string(next_slot);
310: In_string = 1;
311: string_start = 0;
312: }
313: else
314: pointer = word_start - 1;
315: else if (cursor_pos > max_line_len) {
316: #ifndef ANSI_Libraries
317: extern char *strchr();
318: #endif
319: if (In_string) {
320: pointer = adjust_pointer_in_string(pointer);
321: if (string_start && pointer > string_start)
322: string_start = 0;
323: }
324: else if (strchr("&*+-/<=>|", *pointer)
325: && strchr("!%&*+-/<=>^|", pointer[-1])) {
326: pointer -= 2;
327: if (strchr("<>", *pointer)) /* <<=, >>= */
328: pointer--;
329: }
330: else {
331: if (word_start)
332: while(isident(*(unsigned char *)pointer))
333: pointer++;
334: pointer--;
335: }
336: }
337: last_char = *pointer;
338: write_indent(fp, use_indent, extra_indent, output_buf, pointer);
339: next_slot = output_buf;
340: if (In_string && !string_start && Ansi == 1 && last_char != '\n')
341: *next_slot++ = '"';
342: fwd_strcpy(next_slot, pointer + 1);
343:
344: /* insert a line break */
345:
346: if (last_char == '\n') {
347: if (In_string)
348: last_was_newline = 0;
349: else {
350: last_was_newline = 1;
351: extra_indent = 0;
352: }
353: }
354: else {
355: extra_indent = TOO_LONG_INDENT;
356: if (In_string && !string_start) {
357: if (Ansi == 1) {
358: fprintf(fp, "\"\n");
359: use_indent = 1;
360: last_was_newline = 1;
361: }
362: else {
363: fprintf(fp, "\\\n");
364: last_was_newline = 0;
365: }
366: In_string = in_string0;
367: }
368: else {
369: if (in_define)
370: putc('\\', fp);
371: putc ('\n', fp);
372: last_was_newline = 1;
373: }
374: } /* if *pointer != '\n' */
375:
376: if (In_string && Ansi != 1 && !string_start)
377: cursor_pos = 0;
378: else
379: set_cursor = 1;
380:
381: string_start = word_start = NULL;
382:
383: } /* else */
384:
385: } while (*next_slot);
386:
387: return 0;
388: } /* ind_printf */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.