xref: /netbsd-src/external/gpl3/gdb.old/dist/sim/igen/lf.c (revision 8b657b0747480f8989760d71343d6dd33f8d4cf9)
1 /* The IGEN simulator generator for GDB, the GNU Debugger.
2 
3    Copyright 2002-2023 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 3 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, see <http://www.gnu.org/licenses/>.  */
21 
22 
23 
24 #include <stdio.h>
25 #include <stdarg.h>
26 #include <ctype.h>
27 
28 #include "misc.h"
29 #include "lf.h"
30 
31 #include <stdlib.h>
32 #include <string.h>
33 
34 struct _lf
35 {
36   FILE *stream;
37   int line_nr;			/* nr complete lines written, curr line is line_nr+1 */
38   int indent;
39   int line_blank;
40   const char *name;
41   const char *program;
42   lf_file_references references;
43   lf_file_type type;
44 };
45 
46 
47 lf *
48 lf_open (const char *name,
49 	 const char *real_name,
50 	 lf_file_references references,
51 	 lf_file_type type, const char *program)
52 {
53   /* create a file object */
54   lf *new_lf = ZALLOC (lf);
55   ASSERT (new_lf != NULL);
56   new_lf->references = references;
57   new_lf->type = type;
58   new_lf->name = (real_name == NULL ? name : real_name);
59   new_lf->program = program;
60   /* attach to stdout if pipe */
61   if (!strcmp (name, "-"))
62     {
63       new_lf->stream = stdout;
64     }
65   else
66     {
67       /* create a new file */
68       new_lf->stream = fopen (name, "w");
69       if (new_lf->stream == NULL)
70 	{
71 	  perror (name);
72 	  exit (1);
73 	}
74     }
75   return new_lf;
76 }
77 
78 
79 lf_file_type
80 lf_get_file_type (const lf *file)
81 {
82   return file->type;
83 }
84 
85 
86 void
87 lf_close (lf *file)
88 {
89   if (file->stream != stdout)
90     {
91       if (fclose (file->stream))
92 	{
93 	  perror ("lf_close.fclose");
94 	  exit (1);
95 	}
96       free (file);
97     }
98 }
99 
100 
101 int
102 lf_putchr (lf *file, const char chr)
103 {
104   int nr = 0;
105   if (chr == '\n')
106     {
107       file->line_nr += 1;
108       file->line_blank = 1;
109     }
110   else if (file->line_blank)
111     {
112       int pad;
113       for (pad = file->indent; pad > 0; pad--)
114 	putc (' ', file->stream);
115       nr += file->indent;
116       file->line_blank = 0;
117     }
118   putc (chr, file->stream);
119   nr += 1;
120   return nr;
121 }
122 
123 int
124 lf_write (lf *file, const char *string, int strlen_string)
125 {
126   int nr = 0;
127   int i;
128   for (i = 0; i < strlen_string; i++)
129     nr += lf_putchr (file, string[i]);
130   return nr;
131 }
132 
133 
134 void
135 lf_indent_suppress (lf *file)
136 {
137   file->line_blank = 0;
138 }
139 
140 
141 int
142 lf_putstr (lf *file, const char *string)
143 {
144   int nr = 0;
145   const char *chp;
146   if (string != NULL)
147     {
148       for (chp = string; *chp != '\0'; chp++)
149 	{
150 	  nr += lf_putchr (file, *chp);
151 	}
152     }
153   return nr;
154 }
155 
156 static int
157 do_lf_putunsigned (lf *file, unsigned u)
158 {
159   int nr = 0;
160   if (u > 0)
161     {
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, int decimal)
171 {
172   int nr = 0;
173   if (decimal == 0)
174     nr += lf_putchr (file, '0');
175   else if (decimal < 0)
176     {
177       nr += lf_putchr (file, '-');
178       nr += do_lf_putunsigned (file, -decimal);
179     }
180   else if (decimal > 0)
181     {
182       nr += do_lf_putunsigned (file, decimal);
183     }
184   else
185     ASSERT (0);
186   return nr;
187 }
188 
189 
190 int
191 lf_printf (lf *file, const char *fmt, ...)
192 {
193   int nr = 0;
194   char buf[1024];
195   va_list ap;
196 
197   va_start (ap, fmt);
198   vsprintf (buf, fmt, ap);
199   /* FIXME - this is really stuffed but so is vsprintf() on a sun! */
200   ASSERT (strlen (buf) < sizeof (buf));
201   nr += lf_putstr (file, buf);
202   va_end (ap);
203   return nr;
204 }
205 
206 
207 int
208 lf_print__line_ref (lf *file, const line_ref *line)
209 {
210   return lf_print__external_ref (file, line->line_nr, line->file_name);
211 }
212 
213 int
214 lf_print__external_ref (lf *file, int line_nr, 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     {
260     case lf_is_c:
261     case lf_is_h:
262       nr += lf_printf (file, "\
263 /* This file is part of GDB.\n\
264 \n\
265    Copyright 2002, 2007 Free Software Foundation, Inc.\n\
266 \n\
267    This program is free software; you can redistribute it and/or modify\n\
268    it under the terms of the GNU General Public License as published by\n\
269    the Free Software Foundation; either version 3 of the License, or\n\
270    (at your option) any later version.\n\
271 \n\
272    This program is distributed in the hope that it will be useful,\n\
273    but WITHOUT ANY WARRANTY; without even the implied warranty of\n\
274    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n\
275    GNU General Public License for more details.\n\
276 \n\
277    You should have received a copy of the GNU General Public License\n\
278    along with this program.  If not, see <http://www.gnu.org/licenses/>.\n\
279 \n\
280    --\n\
281 \n\
282    This file was generated by the program %s */\n\
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     {
301       if (decimal & bit)
302 	nr += lf_putchr (file, '1');
303       else
304 	nr += lf_putchr (file, '0');
305     }
306   return nr;
307 }
308 
309 int
310 lf_print__this_file_is_empty (lf *file, const char *reason)
311 {
312   int nr = 0;
313   switch (file->type)
314     {
315     case lf_is_c:
316     case lf_is_h:
317       nr += lf_printf (file,
318 		       "/* This generated file (%s) is intentionally left blank",
319 		       file->name);
320       if (reason != NULL)
321 	nr += lf_printf (file, " - %s", reason);
322       nr += lf_printf (file, " */\n");
323       break;
324     default:
325       ERROR ("Bad switch");
326     }
327   return nr;
328 }
329 
330 int
331 lf_print__ucase_filename (lf *file)
332 {
333   int nr = 0;
334   const char *chp = file->name;
335   while (*chp != '\0')
336     {
337       char ch = *chp;
338       if (islower (ch))
339 	{
340 	  nr += lf_putchr (file, toupper (ch));
341 	}
342       else if (ch == '.')
343 	nr += lf_putchr (file, '_');
344       else
345 	nr += lf_putchr (file, ch);
346       chp++;
347     }
348   return nr;
349 }
350 
351 int
352 lf_print__file_start (lf *file)
353 {
354   int nr = 0;
355   switch (file->type)
356     {
357     case lf_is_h:
358     case lf_is_c:
359       nr += lf_print__gnu_copyleft (file);
360       nr += lf_printf (file, "\n");
361       nr += lf_printf (file, "#ifndef ");
362       nr += lf_print__ucase_filename (file);
363       nr += lf_printf (file, "\n");
364       nr += lf_printf (file, "#define ");
365       nr += lf_print__ucase_filename (file);
366       nr += lf_printf (file, "\n");
367       nr += lf_printf (file, "\n");
368       break;
369     default:
370       ASSERT (0);
371     }
372   return nr;
373 }
374 
375 
376 int
377 lf_print__file_finish (lf *file)
378 {
379   int nr = 0;
380   switch (file->type)
381     {
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, const char *trailing_space)
400 {
401   int nr = 0;
402   nr += lf_printf (file, "%s\\\n(%s)", prefix, type);
403   if (trailing_space != NULL)
404     nr += lf_printf (file, "%s", trailing_space);
405   return nr;
406 }
407 
408 int
409 lf_print__function_type_function (lf *file,
410 				  print_function * print_type,
411 				  const char *prefix,
412 				  const char *trailing_space)
413 {
414   int nr = 0;
415   nr += lf_printf (file, "%s\\\n(", prefix);
416   nr += print_type (file);
417   nr += lf_printf (file, ")");
418   if (trailing_space != NULL)
419     nr += lf_printf (file, "%s", trailing_space);
420   return nr;
421 }
422