This commit was generated by cvs2svn to track changes on a CVS vendor
[unix-history] / usr.bin / f2c / niceprintf.c
CommitLineData
f1525c23
WH
1/****************************************************************
2Copyright 1990, 1991, 1993 by AT&T Bell Laboratories and Bellcore.
3
4Permission to use, copy, modify, and distribute this software
5and its documentation for any purpose and without fee is hereby
6granted, provided that the above copyright notice appear in all
7copies and that both that the copyright notice and this
8permission notice and warranty disclaimer appear in supporting
9documentation, and that the names of AT&T Bell Laboratories or
10Bellcore or any of their entities not be used in advertising or
11publicity pertaining to distribution of the software without
12specific, written prior permission.
13
14AT&T and Bellcore disclaim all warranties with regard to this
15software, including all implied warranties of merchantability
16and fitness. In no event shall AT&T or Bellcore be liable for
17any special, indirect or consequential damages or any damages
18whatsoever resulting from loss of use, data or profits, whether
19in an action of contract, negligence or other tortious action,
20arising out of or in connection with the use or performance of
21this 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
31static int last_was_newline = 0;
32int indent = 0;
33int in_comment = 0;
34int in_define = 0;
35 extern int gflag1;
36 extern char *file_name;
37
38 static int
39write_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*/
81int margin_printf (fp, a, b, c, d, e, f, g)
82FILE *fp;
83char *a;
84long 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*/
90int nice_printf (fp, a, b, c, d, e, f, g)
91FILE *fp;
92char *a;
93long 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
110static char *output_buf;
111static char *next_slot;
112static char *string_start;
113
114static char *word_start = NULL;
115static int cursor_pos = 0;
116static int In_string = 0;
117
118 void
119np_init()
120{
121 next_slot = output_buf = Alloc(MAX_OUTPUT_SIZE);
122 memset(output_buf, 0, MAX_OUTPUT_SIZE);
123 }
124
125 static char *
126adjust_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
155fwd_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
169int ind_printf (use_indent, fp, a, b, c, d, e, f, g)
170int use_indent;
171FILE *fp;
172char *a;
173long 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 */