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