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