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 44 struct _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 57 lf * 58 lf_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 89 lf_file_type 90 lf_get_file_type (const lf *file) 91 { 92 return file->type; 93 } 94 95 96 void 97 lf_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 111 int 112 lf_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 133 int 134 lf_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 144 void 145 lf_indent_suppress (lf *file) 146 { 147 file->line_blank = 0; 148 } 149 150 151 int 152 lf_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 166 static int 167 do_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 179 int 180 lf_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 200 int 201 lf_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 217 int 218 lf_print__line_ref (lf *file, line_ref *line) 219 { 220 return lf_print__external_ref (file, line->line_nr, line->file_name); 221 } 222 223 int 224 lf_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 248 int 249 lf_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 257 void 258 lf_indent (lf *file, int delta) 259 { 260 file->indent += delta; 261 } 262 263 264 int 265 lf_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 303 int 304 lf_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 319 int 320 lf_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 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 { 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 361 int 362 lf_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 386 int 387 lf_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 406 int 407 lf_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 418 int 419 lf_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