]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - sim/igen/lf.c
PR31796, Internal error in write_function_pdata at obj-coff-seh
[thirdparty/binutils-gdb.git] / sim / igen / lf.c
CommitLineData
feaee4bd 1/* The IGEN simulator generator for GDB, the GNU Debugger.
c906108c 2
1d506c26 3 Copyright 2002-2024 Free Software Foundation, Inc.
c906108c 4
feaee4bd
AC
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
4744ac1b 11 the Free Software Foundation; either version 3 of the License, or
feaee4bd
AC
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
4744ac1b 20 along with this program. If not, see <http://www.gnu.org/licenses/>. */
c906108c 21
c906108c 22
a5f08108 23#include <stdbool.h>
c906108c
SS
24#include <stdio.h>
25#include <stdarg.h>
26#include <ctype.h>
27
c906108c
SS
28#include "misc.h"
29#include "lf.h"
30
c906108c 31#include <stdlib.h>
c906108c 32#include <string.h>
c906108c 33
4e0bf4c4
AC
34struct _lf
35{
c906108c 36 FILE *stream;
4e0bf4c4 37 int line_nr; /* nr complete lines written, curr line is line_nr+1 */
c906108c
SS
38 int indent;
39 int line_blank;
a5f08108
MF
40 const char *name; /* Output name with diagnostics. */
41 const char *filename; /* Output filename. */
42 char *tmpname; /* Temporary output filename. */
c906108c
SS
43 const char *program;
44 lf_file_references references;
45 lf_file_type type;
46};
47
48
49lf *
fa654e74
MF
50lf_open (const char *name,
51 const char *real_name,
c906108c 52 lf_file_references references,
4e0bf4c4 53 lf_file_type type, const char *program)
c906108c
SS
54{
55 /* create a file object */
4e0bf4c4 56 lf *new_lf = ZALLOC (lf);
c906108c
SS
57 ASSERT (new_lf != NULL);
58 new_lf->references = references;
59 new_lf->type = type;
60 new_lf->name = (real_name == NULL ? name : real_name);
a5f08108 61 new_lf->filename = name;
c906108c
SS
62 new_lf->program = program;
63 /* attach to stdout if pipe */
4e0bf4c4
AC
64 if (!strcmp (name, "-"))
65 {
66 new_lf->stream = stdout;
67 }
68 else
69 {
70 /* create a new file */
a5f08108
MF
71 char *tmpname = zalloc (strlen (name) + 5);
72 sprintf (tmpname, "%s.tmp", name);
73 new_lf->filename = name;
74 new_lf->tmpname = tmpname;
75 new_lf->stream = fopen (tmpname, "w+");
4e0bf4c4
AC
76 if (new_lf->stream == NULL)
77 {
78 perror (name);
79 exit (1);
80 }
c906108c 81 }
c906108c
SS
82 return new_lf;
83}
84
85
c4df5bbe
SH
86lf_file_type
87lf_get_file_type (const lf *file)
88{
89 return file->type;
90}
91
92
c906108c 93void
4e0bf4c4 94lf_close (lf *file)
c906108c 95{
a5f08108
MF
96 FILE *fp;
97 bool update = true;
98
99 /* If we wrote to stdout, no house keeping needed. */
100 if (file->stream == stdout)
101 return;
102
103 /* Rename the temp file to the real file if it's changed. */
104 fp = fopen (file->filename, "r");
105 if (fp != NULL)
4e0bf4c4 106 {
a5f08108
MF
107 off_t len;
108
109 fseek (fp, 0, SEEK_END);
110 len = ftell (fp);
111
112 if (len == ftell (file->stream))
4e0bf4c4 113 {
a5f08108
MF
114 off_t off;
115 size_t cnt;
116 char *oldbuf = zalloc (len);
117 char *newbuf = zalloc (len);
118
119 rewind (fp);
120 off = 0;
121 while ((cnt = fread (oldbuf + off, 1, len - off, fp)) > 0)
122 off += cnt;
123 ASSERT (off == len);
124
125 rewind (file->stream);
126 off = 0;
127 while ((cnt = fread (newbuf + off, 1, len - off, file->stream)) > 0)
128 off += cnt;
129 ASSERT (off == len);
130
131 if (memcmp (oldbuf, newbuf, len) == 0)
132 update = false;
133 }
134
135 fclose (fp);
136 }
137
138 if (fclose (file->stream))
139 {
140 perror ("lf_close.fclose");
141 exit (1);
142 }
143
144 if (update)
145 {
146 if (rename (file->tmpname, file->filename) != 0)
147 {
148 perror ("lf_close.rename");
149 exit (1);
150 }
151 }
152 else
153 {
154 if (remove (file->tmpname) != 0)
155 {
156 perror ("lf_close.unlink");
4e0bf4c4
AC
157 exit (1);
158 }
c906108c 159 }
a5f08108
MF
160
161 free (file->tmpname);
162 free (file);
c906108c
SS
163}
164
165
166int
4e0bf4c4 167lf_putchr (lf *file, const char chr)
c906108c
SS
168{
169 int nr = 0;
4e0bf4c4
AC
170 if (chr == '\n')
171 {
172 file->line_nr += 1;
173 file->line_blank = 1;
174 }
175 else if (file->line_blank)
176 {
177 int pad;
178 for (pad = file->indent; pad > 0; pad--)
179 putc (' ', file->stream);
180 nr += file->indent;
181 file->line_blank = 0;
182 }
183 putc (chr, file->stream);
c906108c
SS
184 nr += 1;
185 return nr;
186}
187
188int
4e0bf4c4 189lf_write (lf *file, const char *string, int strlen_string)
c906108c
SS
190{
191 int nr = 0;
192 int i;
193 for (i = 0; i < strlen_string; i++)
194 nr += lf_putchr (file, string[i]);
195 return nr;
196}
197
198
199void
4e0bf4c4 200lf_indent_suppress (lf *file)
c906108c
SS
201{
202 file->line_blank = 0;
203}
204
205
206int
4e0bf4c4 207lf_putstr (lf *file, const char *string)
c906108c
SS
208{
209 int nr = 0;
210 const char *chp;
4e0bf4c4
AC
211 if (string != NULL)
212 {
213 for (chp = string; *chp != '\0'; chp++)
214 {
215 nr += lf_putchr (file, *chp);
216 }
c906108c 217 }
c906108c
SS
218 return nr;
219}
220
221static int
4e0bf4c4 222do_lf_putunsigned (lf *file, unsigned u)
c906108c
SS
223{
224 int nr = 0;
4e0bf4c4
AC
225 if (u > 0)
226 {
227 nr += do_lf_putunsigned (file, u / 10);
228 nr += lf_putchr (file, (u % 10) + '0');
229 }
c906108c
SS
230 return nr;
231}
232
233
234int
4e0bf4c4 235lf_putint (lf *file, int decimal)
c906108c
SS
236{
237 int nr = 0;
238 if (decimal == 0)
4e0bf4c4
AC
239 nr += lf_putchr (file, '0');
240 else if (decimal < 0)
241 {
242 nr += lf_putchr (file, '-');
243 nr += do_lf_putunsigned (file, -decimal);
244 }
245 else if (decimal > 0)
246 {
247 nr += do_lf_putunsigned (file, decimal);
248 }
c906108c 249 else
4e0bf4c4 250 ASSERT (0);
c906108c
SS
251 return nr;
252}
253
254
255int
4e0bf4c4 256lf_printf (lf *file, const char *fmt, ...)
c906108c
SS
257{
258 int nr = 0;
259 char buf[1024];
260 va_list ap;
261
262 va_start (ap, fmt);
263 vsprintf (buf, fmt, ap);
264 /* FIXME - this is really stuffed but so is vsprintf() on a sun! */
265 ASSERT (strlen (buf) < sizeof (buf));
266 nr += lf_putstr (file, buf);
4e0bf4c4 267 va_end (ap);
c906108c
SS
268 return nr;
269}
270
271
272int
fa654e74 273lf_print__line_ref (lf *file, const line_ref *line)
c906108c
SS
274{
275 return lf_print__external_ref (file, line->line_nr, line->file_name);
276}
277
278int
4e0bf4c4 279lf_print__external_ref (lf *file, int line_nr, const char *file_name)
c906108c
SS
280{
281 int nr = 0;
282 switch (file->references)
283 {
284 case lf_include_references:
4e0bf4c4 285 lf_indent_suppress (file);
c906108c
SS
286 nr += lf_putstr (file, "#line ");
287 nr += lf_putint (file, line_nr);
288 nr += lf_putstr (file, " \"");
289 nr += lf_putstr (file, file_name);
290 nr += lf_putstr (file, "\"\n");
291 break;
292 case lf_omit_references:
293 nr += lf_putstr (file, "/* ");
294 nr += lf_putstr (file, file_name);
295 nr += lf_putstr (file, ":");
296 nr += lf_putint (file, line_nr);
297 nr += lf_putstr (file, "*/\n");
298 break;
299 }
300 return nr;
301}
302
303int
304lf_print__internal_ref (lf *file)
305{
306 int nr = 0;
4e0bf4c4 307 nr += lf_print__external_ref (file, file->line_nr + 2, file->name);
c906108c
SS
308 /* line_nr == last_line, want to number from next */
309 return nr;
310}
311
312void
313lf_indent (lf *file, int delta)
314{
315 file->indent += delta;
316}
317
318
319int
320lf_print__gnu_copyleft (lf *file)
321{
322 int nr = 0;
4e0bf4c4
AC
323 switch (file->type)
324 {
325 case lf_is_c:
326 case lf_is_h:
327 nr += lf_printf (file, "\
feaee4bd 328/* This file is part of GDB.\n\
4e62efb8 329\n\
dfee3164 330 Copyright 2002, 2007 Free Software Foundation, Inc.\n\
4e62efb8 331\n\
feaee4bd
AC
332 This program is free software; you can redistribute it and/or modify\n\
333 it under the terms of the GNU General Public License as published by\n\
dfee3164 334 the Free Software Foundation; either version 3 of the License, or\n\
feaee4bd 335 (at your option) any later version.\n\
4e62efb8 336\n\
feaee4bd
AC
337 This program is distributed in the hope that it will be useful,\n\
338 but WITHOUT ANY WARRANTY; without even the implied warranty of\n\
339 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n\
340 GNU General Public License for more details.\n\
dfee3164 341\n\
feaee4bd 342 You should have received a copy of the GNU General Public License\n\
dfee3164 343 along with this program. If not, see <http://www.gnu.org/licenses/>.\n\
4e62efb8 344\n\
feaee4bd 345 --\n\
4e62efb8 346\n\
feaee4bd 347 This file was generated by the program %s */\n\
4e0bf4c4
AC
348", filter_filename (file->program));
349 break;
350 default:
351 ASSERT (0);
352 break;
353 }
c906108c
SS
354 return nr;
355}
356
357
358int
4e0bf4c4 359lf_putbin (lf *file, int decimal, int width)
c906108c
SS
360{
361 int nr = 0;
362 int bit;
4e0bf4c4
AC
363 ASSERT (width > 0);
364 for (bit = 1 << (width - 1); bit != 0; bit >>= 1)
365 {
366 if (decimal & bit)
367 nr += lf_putchr (file, '1');
368 else
369 nr += lf_putchr (file, '0');
370 }
c906108c
SS
371 return nr;
372}
373
374int
4e0bf4c4 375lf_print__this_file_is_empty (lf *file, const char *reason)
c906108c
SS
376{
377 int nr = 0;
4e0bf4c4
AC
378 switch (file->type)
379 {
380 case lf_is_c:
381 case lf_is_h:
382 nr += lf_printf (file,
383 "/* This generated file (%s) is intentionally left blank",
384 file->name);
385 if (reason != NULL)
386 nr += lf_printf (file, " - %s", reason);
387 nr += lf_printf (file, " */\n");
388 break;
389 default:
390 ERROR ("Bad switch");
391 }
c906108c
SS
392 return nr;
393}
394
395int
4e0bf4c4 396lf_print__ucase_filename (lf *file)
c906108c
SS
397{
398 int nr = 0;
399 const char *chp = file->name;
4e0bf4c4
AC
400 while (*chp != '\0')
401 {
402 char ch = *chp;
403 if (islower (ch))
404 {
405 nr += lf_putchr (file, toupper (ch));
406 }
407 else if (ch == '.')
408 nr += lf_putchr (file, '_');
409 else
410 nr += lf_putchr (file, ch);
411 chp++;
c906108c 412 }
c906108c
SS
413 return nr;
414}
415
416int
4e0bf4c4 417lf_print__file_start (lf *file)
c906108c
SS
418{
419 int nr = 0;
4e0bf4c4
AC
420 switch (file->type)
421 {
422 case lf_is_h:
423 case lf_is_c:
424 nr += lf_print__gnu_copyleft (file);
425 nr += lf_printf (file, "\n");
426 nr += lf_printf (file, "#ifndef ");
427 nr += lf_print__ucase_filename (file);
428 nr += lf_printf (file, "\n");
429 nr += lf_printf (file, "#define ");
430 nr += lf_print__ucase_filename (file);
431 nr += lf_printf (file, "\n");
432 nr += lf_printf (file, "\n");
433 break;
434 default:
435 ASSERT (0);
436 }
c906108c
SS
437 return nr;
438}
439
440
441int
4e0bf4c4 442lf_print__file_finish (lf *file)
c906108c
SS
443{
444 int nr = 0;
4e0bf4c4
AC
445 switch (file->type)
446 {
447 case lf_is_h:
448 case lf_is_c:
449 nr += lf_printf (file, "\n");
450 nr += lf_printf (file, "#endif /* _");
451 nr += lf_print__ucase_filename (file);
452 nr += lf_printf (file, "_*/\n");
453 break;
454 default:
455 ASSERT (0);
456 }
c906108c
SS
457 return nr;
458}
459
460
461int
462lf_print__function_type (lf *file,
463 const char *type,
4e0bf4c4 464 const char *prefix, const char *trailing_space)
c906108c
SS
465{
466 int nr = 0;
467 nr += lf_printf (file, "%s\\\n(%s)", prefix, type);
468 if (trailing_space != NULL)
469 nr += lf_printf (file, "%s", trailing_space);
470 return nr;
471}
472
473int
474lf_print__function_type_function (lf *file,
4e0bf4c4 475 print_function * print_type,
c906108c
SS
476 const char *prefix,
477 const char *trailing_space)
478{
479 int nr = 0;
480 nr += lf_printf (file, "%s\\\n(", prefix);
481 nr += print_type (file);
482 nr += lf_printf (file, ")");
483 if (trailing_space != NULL)
484 nr += lf_printf (file, "%s", trailing_space);
485 return nr;
486}