lf.c 8.8 KB

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