lf.c 8.9 KB

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