This commit was generated by cvs2svn to track changes on a CVS vendor
[external/binutils.git] / sim / igen / lf.c
1 /*  This file is part of the program psim.
2
3     Copyright (C) 1994-1995, Andrew Cagney <cagney@highland.com.au>
4
5     This program is free software; you can redistribute it and/or modify
6     it under the terms of the GNU General Public License as published by
7     the Free Software Foundation; either version 2 of the License, or
8     (at your option) any later version.
9
10     This program is distributed in the hope that it will be useful,
11     but WITHOUT ANY WARRANTY; without even the implied warranty of
12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13     GNU General Public License for more details.
14  
15     You should have received a copy of the GNU General Public License
16     along with this program; if not, write to the Free Software
17     Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18  
19     */
20
21
22 #include <stdio.h>
23 #include <stdarg.h>
24 #include <ctype.h>
25
26 #include "config.h"
27 #include "misc.h"
28 #include "lf.h"
29
30 #ifdef HAVE_STDLIB_H
31 #include <stdlib.h>
32 #endif
33
34 #ifdef HAVE_STRING_H
35 #include <string.h>
36 #else
37 #ifdef HAVE_STRINGS_H
38 #include <strings.h>
39 #endif
40 #endif
41
42 struct _lf {
43   FILE *stream;
44   int line_nr; /* nr complete lines written, curr line is line_nr+1 */
45   int indent;
46   int line_blank;
47   const char *name;
48   const char *program;
49   lf_file_references references;
50   lf_file_type type;
51 };
52
53
54 lf *
55 lf_open (char *name,
56          char *real_name,
57          lf_file_references references,
58          lf_file_type type,
59          const char *program)
60 {
61   /* create a file object */
62   lf *new_lf = ZALLOC(lf);
63   ASSERT (new_lf != NULL);
64   new_lf->references = references;
65   new_lf->type = type;
66   new_lf->name = (real_name == NULL ? name : real_name);
67   new_lf->program = program;
68   /* attach to stdout if pipe */
69   if (!strcmp(name, "-")) {
70     new_lf->stream = stdout;
71   }
72   else {
73     /* create a new file */
74     new_lf->stream = fopen(name, "w");
75     if (new_lf->stream == NULL) {
76       perror(name);
77       exit(1);
78     }
79   }
80   return new_lf;
81 }
82
83
84 void
85 lf_close(lf *file)
86 {
87   if (file->stream != stdout) {
88     if (fclose(file->stream)) {
89       perror("lf_close.fclose");
90       exit(1);
91     }
92     free(file);
93   }
94 }
95
96
97 int
98 lf_putchr(lf *file,
99           const char chr)
100 {
101   int nr = 0;
102   if (chr == '\n') {
103     file->line_nr += 1;
104     file->line_blank = 1;
105   }
106   else if (file->line_blank) {
107     int pad;
108     for (pad = file->indent; pad > 0; pad--)
109       putc(' ', file->stream);
110     nr += file->indent;
111     file->line_blank = 0;
112   }
113   putc(chr, file->stream);
114   nr += 1;
115   return nr;
116 }
117
118 int
119 lf_write (lf *file,
120           const char *string,
121           int strlen_string)
122 {
123   int nr = 0;
124   int i;
125   for (i = 0; i < strlen_string; i++)
126     nr += lf_putchr (file, string[i]);
127   return nr;
128 }
129
130
131 void
132 lf_indent_suppress(lf *file)
133 {
134   file->line_blank = 0;
135 }
136
137
138 int
139 lf_putstr(lf *file,
140           const char *string)
141 {
142   int nr = 0;
143   const char *chp;
144   if (string != NULL) {
145     for (chp = string; *chp != '\0'; chp++) {
146       nr += lf_putchr(file, *chp);
147     }
148   }
149   return nr;
150 }
151
152 static int
153 do_lf_putunsigned(lf *file,
154               unsigned u)
155 {
156   int nr = 0;
157   if (u > 0) {
158     nr += do_lf_putunsigned(file, u / 10);
159     nr += lf_putchr(file, (u % 10) + '0');
160   }
161   return nr;
162 }
163
164
165 int
166 lf_putint(lf *file,
167           int decimal)
168 {
169   int nr = 0;
170   if (decimal == 0)
171     nr += lf_putchr(file, '0');
172   else if (decimal < 0) {
173     nr += lf_putchr(file, '-');
174     nr += do_lf_putunsigned(file, -decimal);
175   }
176   else if (decimal > 0) {
177     nr += do_lf_putunsigned(file, decimal);
178   }
179   else
180     ASSERT(0);
181   return nr;
182 }
183
184
185 int
186 lf_printf (lf *file,
187            const char *fmt,
188            ...)
189 {
190   int nr = 0;
191   char buf[1024];
192   va_list ap;
193
194   va_start (ap, fmt);
195   vsprintf (buf, fmt, ap);
196   /* FIXME - this is really stuffed but so is vsprintf() on a sun! */
197   ASSERT (strlen (buf) < sizeof (buf));
198   nr += lf_putstr (file, buf);
199   va_end(ap);
200   return nr;
201 }
202
203
204 int
205 lf_print__line_ref (lf *file,
206                     line_ref *line)
207 {
208   return lf_print__external_ref (file, line->line_nr, line->file_name);
209 }
210
211 int
212 lf_print__external_ref (lf *file,
213                         int line_nr,
214                         const char *file_name)
215 {
216   int nr = 0;
217   switch (file->references)
218     {
219     case lf_include_references:
220       lf_indent_suppress(file);
221       nr += lf_putstr (file, "#line ");
222       nr += lf_putint (file, line_nr);
223       nr += lf_putstr (file, " \"");
224       nr += lf_putstr (file, file_name);
225       nr += lf_putstr (file, "\"\n");
226       break;
227     case lf_omit_references:
228       nr += lf_putstr (file, "/* ");
229       nr += lf_putstr (file, file_name);
230       nr += lf_putstr (file, ":");
231       nr += lf_putint (file, line_nr);
232       nr += lf_putstr (file, "*/\n");
233       break;
234     }
235   return nr;
236 }
237
238 int
239 lf_print__internal_ref (lf *file)
240 {
241   int nr = 0;
242   nr += lf_print__external_ref (file, file->line_nr+2, file->name);
243   /* line_nr == last_line, want to number from next */
244   return nr;
245 }
246
247 void
248 lf_indent (lf *file, int delta)
249 {
250   file->indent += delta;
251 }
252
253
254 int
255 lf_print__gnu_copyleft (lf *file)
256 {
257   int nr = 0;
258   switch (file->type) {
259   case lf_is_c:
260   case lf_is_h:
261     nr += lf_printf(file, "\
262 /*  This file is part of the program psim.
263
264     Copyright (C) 1994-1997, Andrew Cagney <cagney@highland.com.au>
265
266     This program is free software; you can redistribute it and/or modify
267     it under the terms of the GNU General Public License as published by
268     the Free Software Foundation; either version 2 of the License, or
269     (at your option) any later version.
270
271     This program is distributed in the hope that it will be useful,
272     but WITHOUT ANY WARRANTY; without even the implied warranty of
273     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
274     GNU General Public License for more details.
275  
276     You should have received a copy of the GNU General Public License
277     along with this program; if not, write to the Free Software
278     Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
279  
280     --
281
282     This file was generated by the program %s */
283 ", filter_filename(file->program));
284     break;
285   default:
286     ASSERT(0);
287     break;
288   }
289   return nr;
290 }
291
292
293 int
294 lf_putbin(lf *file, int decimal, int width)
295 {
296   int nr = 0;
297   int bit;
298   ASSERT(width > 0);
299   for (bit = 1 << (width-1); bit != 0; bit >>= 1) {
300     if (decimal & bit)
301       nr += lf_putchr(file, '1');
302     else
303       nr += lf_putchr(file, '0');
304   }
305   return nr;
306 }
307
308 int
309 lf_print__this_file_is_empty(lf *file,
310                              const char *reason)
311 {
312   int nr = 0;
313   switch (file->type) {
314   case lf_is_c:
315   case lf_is_h:
316     nr += lf_printf (file,
317                     "/* This generated file (%s) is intentionally left blank",
318                     file->name);
319     if (reason != NULL)
320       nr += lf_printf (file, " - %s", reason);
321     nr += lf_printf (file, " */\n");
322     break;
323   default:
324     ERROR ("Bad switch");
325   }
326   return nr;
327 }
328
329 int
330 lf_print__ucase_filename(lf *file)
331 {
332   int nr = 0;
333   const char *chp = file->name;
334   while (*chp != '\0') {
335     char ch = *chp;
336     if (islower(ch)) {
337       nr += lf_putchr(file, toupper(ch));
338     }
339     else if (ch == '.')
340       nr += lf_putchr(file, '_');
341     else
342       nr += lf_putchr(file, ch);
343     chp++;
344   }
345   return nr;
346 }
347
348 int
349 lf_print__file_start(lf *file)
350 {
351   int nr = 0;
352   switch (file->type) {
353   case lf_is_h:
354   case lf_is_c:
355     nr += lf_print__gnu_copyleft(file);
356     nr += lf_printf(file, "\n");
357     nr += lf_printf(file, "#ifndef ");
358     nr += lf_print__ucase_filename(file);
359     nr += lf_printf(file, "\n");
360     nr += lf_printf(file, "#define ");
361     nr += lf_print__ucase_filename(file);
362     nr += lf_printf(file, "\n");
363     nr += lf_printf(file, "\n");
364     break;
365   default:
366     ASSERT(0);
367   }
368   return nr;
369 }
370
371
372 int
373 lf_print__file_finish(lf *file)
374 {
375   int nr = 0;
376   switch (file->type) {
377   case lf_is_h:
378   case lf_is_c:
379     nr += lf_printf(file, "\n");
380     nr += lf_printf(file, "#endif /* _");
381     nr += lf_print__ucase_filename(file);
382     nr += lf_printf(file, "_*/\n");
383     break;
384   default:
385     ASSERT(0);
386   }
387   return nr;
388 }
389
390
391 int
392 lf_print__function_type (lf *file,
393                          const char *type,
394                          const char *prefix,
395                          const char *trailing_space)
396 {
397   int nr = 0;
398   nr += lf_printf (file, "%s\\\n(%s)", prefix, type);
399   if (trailing_space != NULL)
400     nr += lf_printf (file, "%s", trailing_space);
401   return nr;
402 }
403
404 int
405 lf_print__function_type_function (lf *file,
406                                   print_function *print_type,
407                                   const char *prefix,
408                                   const char *trailing_space)
409 {
410   int nr = 0;
411   nr += lf_printf (file, "%s\\\n(", prefix);
412   nr += print_type (file);
413   nr += lf_printf (file, ")");
414   if (trailing_space != NULL)
415     nr += lf_printf (file, "%s", trailing_space);
416   return nr;
417 }
418