Commit | Line | Data |
---|---|---|
f1525c23 WH |
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, infname ? infname : 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 */ |