*** empty log message ***
[external/binutils.git] / sim / ppc / 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 "build-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 void
119 lf_indent_suppress(lf *file)
120 {
121   file->line_blank = 0;
122 }
123
124
125 int
126 lf_putstr(lf *file,
127           const char *string)
128 {
129   int nr = 0;
130   const char *chp;
131   if (string != NULL) {
132     for (chp = string; *chp != '\0'; chp++) {
133       nr += lf_putchr(file, *chp);
134     }
135   }
136   return nr;
137 }
138
139 static int
140 do_lf_putunsigned(lf *file,
141               unsigned u)
142 {
143   int nr = 0;
144   if (u > 0) {
145     nr += do_lf_putunsigned(file, u / 10);
146     nr += lf_putchr(file, (u % 10) + '0');
147   }
148   return nr;
149 }
150
151
152 int
153 lf_putint(lf *file,
154           int decimal)
155 {
156   int nr = 0;
157   if (decimal == 0)
158     nr += lf_putchr(file, '0');
159   else if (decimal < 0) {
160     nr += lf_putchr(file, '-');
161     nr += do_lf_putunsigned(file, -decimal);
162   }
163   else if (decimal > 0) {
164     nr += do_lf_putunsigned(file, decimal);
165   }
166   else
167     ASSERT(0);
168   return nr;
169 }
170
171
172 int
173 lf_printf(lf *file,
174           const char *fmt,
175           ...)
176 {
177   int nr = 0;
178   char buf[1024];
179   va_list ap;
180
181   va_start(ap, fmt);
182   vsprintf(buf, fmt, ap);
183   /* FIXME - this is really stuffed but so is vsprintf() on a sun! */
184   ASSERT(strlen(buf) > 0 && strlen(buf) < sizeof(buf));
185   nr += lf_putstr(file, buf);
186   va_end(ap);
187   return nr;
188 }
189
190
191 int
192 lf_print__c_code(lf *file,
193                  const char *code)
194 {
195   int nr = 0;
196   const char *chp = code;
197   int in_bit_field = 0;
198   while (*chp != '\0') {
199     if (*chp == '\t')
200       chp++;
201     if (*chp == '#')
202       lf_indent_suppress(file);
203     while (*chp != '\0' && *chp != '\n') {
204       if (chp[0] == '{' && !isspace(chp[1])) {
205         in_bit_field = 1;
206         nr += lf_putchr(file, '_');
207       }
208       else if (in_bit_field && chp[0] == ':') {
209         nr += lf_putchr(file, '_');
210       }
211       else if (in_bit_field && *chp == '}') {
212         nr += lf_putchr(file, '_');
213         in_bit_field = 0;
214       }
215       else {
216         nr += lf_putchr(file, *chp);
217       }
218       chp++;
219     }
220     if (in_bit_field)
221       error("bit field paren miss match some where\n");
222     if (*chp == '\n') {
223       nr += lf_putchr(file, '\n');
224       chp++;
225     }
226   }
227   nr += lf_putchr(file, '\n');
228   return nr;
229 }
230
231
232 int
233 lf_print__external_reference(lf *file,
234                              int line_nr,
235                              const char *file_name)
236 {
237   int nr = 0;
238   switch (file->references) {
239   case lf_include_references:
240     lf_indent_suppress(file);
241     nr += lf_putstr(file, "#line ");
242     nr += lf_putint(file, line_nr);
243     nr += lf_putstr(file, " \"");
244     nr += lf_putstr(file, file_name);
245     nr += lf_putstr(file, "\"\n");
246     break;
247   case lf_omit_references:
248     break;
249   }
250   return nr;
251 }
252
253 int
254 lf_print__internal_reference(lf *file)
255 {
256   int nr = 0;
257   nr += lf_print__external_reference(file, file->line_nr+2, file->name);
258   /* line_nr == last_line, want to number from next */
259   return nr;
260 }
261
262 void
263 lf_indent(lf *file, int delta)
264 {
265   file->indent += delta;
266 }
267
268
269 int
270 lf_print__gnu_copyleft(lf *file)
271 {
272   int nr = 0;
273   switch (file->type) {
274   case lf_is_c:
275   case lf_is_h:
276     nr += lf_printf(file, "\n\
277 /*  This file is part of the program psim.\n\
278 \n\
279     Copyright (C) 1994-1995, Andrew Cagney <cagney@highland.com.au>\n\
280 \n\
281     This program is free software; you can redistribute it and/or modify\n\
282     it under the terms of the GNU General Public License as published by\n\
283     the Free Software Foundation; either version 2 of the License, or\n\
284     (at your option) any later version.\n\
285 \n\
286     This program is distributed in the hope that it will be useful,\n\
287     but WITHOUT ANY WARRANTY; without even the implied warranty of\n\
288     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n\
289     GNU General Public License for more details.\n\
290  \n\
291     You should have received a copy of the GNU General Public License\n\
292     along with this program; if not, write to the Free Software\n\
293     Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\n\
294  \n\
295     --\n\
296 \n\
297     This file was generated by the program %s */\n\
298 ", filter_filename(file->program));
299     break;
300   default:
301     ASSERT(0);
302     break;
303   }
304   return nr;
305 }
306
307
308 int
309 lf_putbin(lf *file, int decimal, int width)
310 {
311   int nr = 0;
312   int bit;
313   ASSERT(width > 0);
314   for (bit = 1 << (width-1); bit != 0; bit >>= 1) {
315     if (decimal & bit)
316       nr += lf_putchr(file, '1');
317     else
318       nr += lf_putchr(file, '0');
319   }
320   return nr;
321 }
322
323 int
324 lf_print__this_file_is_empty(lf *file)
325 {
326   int nr = 0;
327   switch (file->type) {
328   case lf_is_c:
329   case lf_is_h:
330     nr += lf_printf(file,
331                     "/* This generated file (%s) is intentionally left blank */\n",
332                     file->name);
333     break;
334   default:
335     ASSERT(0);
336   }
337   return nr;
338 }
339
340 int
341 lf_print__ucase_filename(lf *file)
342 {
343   int nr = 0;
344   const char *chp = file->name;
345   while (*chp != '\0') {
346     char ch = *chp;
347     if (islower(ch)) {
348       nr += lf_putchr(file, toupper(ch));
349     }
350     else if (ch == '.')
351       nr += lf_putchr(file, '_');
352     else
353       nr += lf_putchr(file, ch);
354     chp++;
355   }
356   return nr;
357 }
358
359 int
360 lf_print__file_start(lf *file)
361 {
362   int nr = 0;
363   switch (file->type) {
364   case lf_is_h:
365   case lf_is_c:
366     nr += lf_print__gnu_copyleft(file);
367     nr += lf_printf(file, "\n");
368     nr += lf_printf(file, "#ifndef _");
369     nr += lf_print__ucase_filename(file);
370     nr += lf_printf(file, "_\n");
371     nr += lf_printf(file, "#define _");
372     nr += lf_print__ucase_filename(file);
373     nr += lf_printf(file, "_\n");
374     nr += lf_printf(file, "\n");
375     break;
376   default:
377     ASSERT(0);
378   }
379   return nr;
380 }
381
382
383 int
384 lf_print__file_finish(lf *file)
385 {
386   int nr = 0;
387   switch (file->type) {
388   case lf_is_h:
389   case lf_is_c:
390     nr += lf_printf(file, "\n");
391     nr += lf_printf(file, "#endif /* _");
392     nr += lf_print__ucase_filename(file);
393     nr += lf_printf(file, "_*/\n");
394     break;
395   default:
396     ASSERT(0);
397   }
398   return nr;
399 }
400
401
402 int
403 lf_print_function_type(lf *file,
404                        const char *type,
405                        const char *prefix,
406                        const char *trailing_space)
407 {
408   int nr = 0;
409   nr += lf_printf(file, "%s\\\n(%s)", prefix, type);
410   if (trailing_space != NULL)
411     nr += lf_printf(file, "%s", trailing_space);
412 #if 0
413   const char *type_pointer = strrchr(type, '*');
414   int type_pointer_offset = (type_pointer != NULL
415                              ? type_pointer - type
416                              : 0);
417   if (type_pointer == NULL) {
418     lf_printf(file, "%s %s", type, prefix);
419   }
420   else {
421     char *munged_type = (char*)zalloc(strlen(type)
422                                       + strlen(prefix)
423                                       + strlen(" * ")
424                                       + 1);
425     strcpy(munged_type, type);
426     munged_type[type_pointer_offset] = '\0';
427     if (type_pointer_offset > 0 && type[type_pointer_offset-1] != ' ')
428       strcat(munged_type, " ");
429     strcat(munged_type, prefix);
430     strcat(munged_type, " ");
431     strcat(munged_type, type + type_pointer_offset);
432     lf_printf(file, "%s", munged_type);
433     free(munged_type);
434   }
435   if (trailing_space != NULL && type_pointer_offset < strlen(type) - 1)
436     lf_printf(file, trailing_space);
437 #endif
438   return nr;
439 }
440