table.c 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345
  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 <sys/types.h>
  15. #include <sys/stat.h>
  16. #include <stdio.h>
  17. #include <fcntl.h>
  18. #include <ctype.h>
  19. #include "build-config.h"
  20. #include "misc.h"
  21. #include "lf.h"
  22. #include "table.h"
  23. #ifdef HAVE_UNISTD_H
  24. #include <unistd.h>
  25. #endif
  26. #ifdef HAVE_STDLIB_H
  27. #include <stdlib.h>
  28. #endif
  29. typedef struct _open_table open_table;
  30. struct _open_table {
  31. size_t size;
  32. char *buffer;
  33. char *pos;
  34. int line_nr;
  35. int nr_fields;
  36. int nr_model_fields;
  37. char *file_name;
  38. open_table *parent;
  39. table *root;
  40. };
  41. struct _table {
  42. open_table *current;
  43. };
  44. void
  45. table_push (table *root,
  46. table_include *includes,
  47. const char *file_name,
  48. int nr_fields,
  49. int nr_model_fields)
  50. {
  51. int fd;
  52. struct stat stat_buf;
  53. open_table *file;
  54. table_include dummy;
  55. table_include *include = &dummy;
  56. int nr;
  57. /* dummy up a search of this directory */
  58. dummy.next = includes;
  59. dummy.dir = "";
  60. /* create a file descriptor */
  61. file = ZALLOC (open_table);
  62. ASSERT(file != NULL);
  63. file->nr_fields = nr_fields;
  64. file->nr_model_fields = nr_model_fields;
  65. file->root = root;
  66. file->parent = root->current;
  67. root->current = file;
  68. while (1)
  69. {
  70. /* save the file name */
  71. char *dup_name = NZALLOC (char, strlen (include->dir) + strlen (file_name) + 2);
  72. if (dup_name == NULL)
  73. {
  74. perror (file_name);
  75. exit (1);
  76. }
  77. if (include->dir[0] != '\0')
  78. {
  79. strcat (dup_name, include->dir);
  80. strcat (dup_name, "/");
  81. }
  82. strcat (dup_name, file_name);
  83. file->file_name = dup_name;
  84. /* open the file */
  85. fd = open (dup_name, O_RDONLY, 0);
  86. if (fd >= 0)
  87. break;
  88. /* free (dup_name); */
  89. if (include->next == NULL)
  90. {
  91. error ("Problem opening file `%s'\n", file_name);
  92. perror (file_name);
  93. exit (1);
  94. }
  95. include = include->next;
  96. }
  97. /* determine the size */
  98. if (fstat(fd, &stat_buf) < 0) {
  99. perror("table_open.fstat");
  100. exit(1);
  101. }
  102. file->size = stat_buf.st_size;
  103. /* allocate this much memory */
  104. file->buffer = (char*)zalloc(file->size+1);
  105. if(file->buffer == NULL) {
  106. perror("table_open.calloc.file->size+1");
  107. exit(1);
  108. }
  109. file->pos = file->buffer;
  110. /* read it in */
  111. #ifdef __CYGWIN32__
  112. if ((file->size) && ((nr = read(fd, file->buffer, file->size)) <= 0)) {
  113. #else
  114. if ((nr = read(fd, file->buffer, file->size)) < file->size) {
  115. #endif
  116. perror("table_open.read");
  117. exit(1);
  118. }
  119. file->size = nr;
  120. file->buffer[file->size] = '\0';
  121. /* done */
  122. close(fd);
  123. }
  124. extern table *
  125. table_open(const char *file_name,
  126. int nr_fields,
  127. int nr_model_fields)
  128. {
  129. table *root;
  130. /* create a file descriptor */
  131. root = ZALLOC (table);
  132. if (root == NULL)
  133. {
  134. perror (file_name);
  135. exit (1);
  136. }
  137. table_push (root, NULL, file_name, nr_fields, nr_model_fields);
  138. return root;
  139. }
  140. extern table_entry *
  141. table_entry_read(table *root)
  142. {
  143. open_table *file = root->current;
  144. int field;
  145. table_entry *entry;
  146. /* skip comments/blanks */
  147. while(1) {
  148. /* end-of-file? */
  149. while (*file->pos == '\0')
  150. {
  151. if (file->parent != NULL)
  152. {
  153. file = file->parent;
  154. root->current = file;
  155. }
  156. else
  157. return NULL;
  158. }
  159. /* leading white space */
  160. while (*file->pos != '\0'
  161. && *file->pos != '\n'
  162. && isspace(*file->pos))
  163. file->pos++;
  164. /* comment */
  165. if (*file->pos == '#') {
  166. do {
  167. file->pos++;
  168. } while (*file->pos != '\0' && *file->pos != '\n');
  169. }
  170. /* end of line? */
  171. if (*file->pos == '\n') {
  172. file->pos++;
  173. file->line_nr++;
  174. }
  175. else
  176. break;
  177. }
  178. /* create this new entry */
  179. entry = (table_entry*)zalloc(sizeof(table_entry)
  180. + (file->nr_fields + 1) * sizeof(char*));
  181. ASSERT(entry != NULL);
  182. entry->file_name = file->file_name;
  183. entry->nr_fields = file->nr_fields;
  184. /* break the line into its colon delimitered fields */
  185. for (field = 0; field < file->nr_fields-1; field++) {
  186. entry->fields[field] = file->pos;
  187. while(*file->pos && *file->pos != ':' && *file->pos != '\n')
  188. file->pos++;
  189. if (*file->pos == ':') {
  190. *file->pos = '\0';
  191. file->pos++;
  192. }
  193. }
  194. /* any trailing stuff not the last field */
  195. ASSERT(field == file->nr_fields-1);
  196. entry->fields[field] = file->pos;
  197. while (*file->pos && *file->pos != '\n') {
  198. file->pos++;
  199. }
  200. if (*file->pos == '\n') {
  201. *file->pos = '\0';
  202. file->pos++;
  203. }
  204. file->line_nr++;
  205. /* if following lines begin with a star, add them to the model
  206. section. */
  207. while ((file->nr_model_fields > 0) && (*file->pos == '*')) {
  208. table_model_entry *model = (table_model_entry*)zalloc(sizeof(table_model_entry)
  209. + (file->nr_model_fields + 1) * sizeof(char*));
  210. if (entry->model_last)
  211. entry->model_last->next = model;
  212. else
  213. entry->model_first = model;
  214. entry->model_last = model;
  215. /* break the line into its colon delimitered fields */
  216. file->pos++;
  217. for (field = 0; field < file->nr_model_fields-1; field++) {
  218. model->fields[field] = file->pos;
  219. while(*file->pos && *file->pos != ':' && *file->pos != '\n')
  220. file->pos++;
  221. if (*file->pos == ':') {
  222. *file->pos = '\0';
  223. file->pos++;
  224. }
  225. }
  226. /* any trailing stuff not the last field */
  227. ASSERT(field == file->nr_model_fields-1);
  228. model->fields[field] = file->pos;
  229. while (*file->pos && *file->pos != '\n') {
  230. file->pos++;
  231. }
  232. if (*file->pos == '\n') {
  233. *file->pos = '\0';
  234. file->pos++;
  235. }
  236. file->line_nr++;
  237. model->line_nr = file->line_nr;
  238. }
  239. entry->line_nr = file->line_nr;
  240. /* if following lines are tab indented, put in the annex */
  241. if (*file->pos == '\t') {
  242. entry->annex = file->pos;
  243. do {
  244. do {
  245. file->pos++;
  246. } while (*file->pos != '\0' && *file->pos != '\n');
  247. if (*file->pos == '\n') {
  248. char *save_pos = ++file->pos;
  249. int extra_lines = 0;
  250. file->line_nr++;
  251. /* Allow tab indented to have blank lines */
  252. while (*save_pos == '\n') {
  253. save_pos++;
  254. extra_lines++;
  255. }
  256. if (*save_pos == '\t') {
  257. file->pos = save_pos;
  258. file->line_nr += extra_lines;
  259. }
  260. }
  261. } while (*file->pos != '\0' && *file->pos == '\t');
  262. if (file->pos[-1] == '\n')
  263. file->pos[-1] = '\0';
  264. }
  265. else
  266. entry->annex = NULL;
  267. /* return it */
  268. return entry;
  269. }
  270. extern void
  271. dump_table_entry(table_entry *entry,
  272. int indent)
  273. {
  274. printf("(table_entry*)%p\n", entry);
  275. if (entry != NULL) {
  276. int field;
  277. char sep;
  278. sep = ' ';
  279. dumpf(indent, "(fields");
  280. for (field = 0; field < entry->nr_fields; field++) {
  281. printf("%c%s", sep, entry->fields[field]);
  282. sep = ':';
  283. }
  284. printf(")\n");
  285. dumpf(indent, "(line_nr %d)\n", entry->line_nr);
  286. dumpf(indent, "(file_name %s)\n", entry->file_name);
  287. dumpf(indent, "(annex\n%s\n", entry->annex);
  288. dumpf(indent, " )\n");
  289. }
  290. }
  291. extern void
  292. table_entry_print_cpp_line_nr(lf *file,
  293. table_entry *entry)
  294. {
  295. lf_print__external_reference(file, entry->line_nr, entry->file_name);
  296. }