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