lf.c revision 1.3
1/* The IGEN simulator generator for GDB, the GNU Debugger. 2 3 Copyright 2002-2015 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 89void 90lf_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 104int 105lf_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 126int 127lf_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 137void 138lf_indent_suppress (lf *file) 139{ 140 file->line_blank = 0; 141} 142 143 144int 145lf_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 159static int 160do_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 172int 173lf_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 193int 194lf_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 210int 211lf_print__line_ref (lf *file, line_ref *line) 212{ 213 return lf_print__external_ref (file, line->line_nr, line->file_name); 214} 215 216int 217lf_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 241int 242lf_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 250void 251lf_indent (lf *file, int delta) 252{ 253 file->indent += delta; 254} 255 256 257int 258lf_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 296int 297lf_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 312int 313lf_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 333int 334lf_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 354int 355lf_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 379int 380lf_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 399int 400lf_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 411int 412lf_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