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