PageRenderTime 62ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/binutils-2.17/sim/igen/table.c

https://bitbucket.org/pizzafactory/blackfin-toolchain
C | 623 lines | 537 code | 43 blank | 43 comment | 78 complexity | e4d2618404646b1897b58a2bb1a61849 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.0, GPL-3.0, AGPL-1.0, LGPL-2.1
  1. /* The IGEN simulator generator for GDB, the GNU Debugger.
  2. Copyright 2002 Free Software Foundation, Inc.
  3. Contributed by Andrew Cagney.
  4. This file is part of GDB.
  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. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to the Free Software
  15. Foundation, Inc., 59 Temple Place - Suite 330,
  16. Boston, MA 02111-1307, USA. */
  17. #include <sys/types.h>
  18. #include <sys/stat.h>
  19. #include <stdio.h>
  20. #include <fcntl.h>
  21. #include <ctype.h>
  22. #include "config.h"
  23. #include "misc.h"
  24. #include "lf.h"
  25. #include "table.h"
  26. #ifdef HAVE_UNISTD_H
  27. #include <unistd.h>
  28. #endif
  29. #ifdef HAVE_STDLIB_H
  30. #include <stdlib.h>
  31. #endif
  32. typedef struct _open_table open_table;
  33. struct _open_table
  34. {
  35. size_t size;
  36. char *buffer;
  37. char *pos;
  38. line_ref pseudo_line;
  39. line_ref real_line;
  40. open_table *parent;
  41. table *root;
  42. };
  43. struct _table
  44. {
  45. open_table *current;
  46. };
  47. static line_ref *
  48. current_line (open_table * file)
  49. {
  50. line_ref *entry = ZALLOC (line_ref);
  51. *entry = file->pseudo_line;
  52. return entry;
  53. }
  54. static table_entry *
  55. new_table_entry (open_table * file, table_entry_type type)
  56. {
  57. table_entry *entry;
  58. entry = ZALLOC (table_entry);
  59. entry->file = file->root;
  60. entry->line = current_line (file);
  61. entry->type = type;
  62. return entry;
  63. }
  64. static void
  65. set_nr_table_entry_fields (table_entry *entry, int nr_fields)
  66. {
  67. entry->field = NZALLOC (char *, nr_fields + 1);
  68. entry->nr_fields = nr_fields;
  69. }
  70. void
  71. table_push (table *root,
  72. line_ref *line, table_include *includes, const char *file_name)
  73. {
  74. FILE *ff;
  75. open_table *file;
  76. table_include dummy;
  77. table_include *include = &dummy;
  78. /* dummy up a search of this directory */
  79. dummy.next = includes;
  80. dummy.dir = "";
  81. /* create a file descriptor */
  82. file = ZALLOC (open_table);
  83. if (file == NULL)
  84. {
  85. perror (file_name);
  86. exit (1);
  87. }
  88. file->root = root;
  89. file->parent = root->current;
  90. root->current = file;
  91. while (1)
  92. {
  93. /* save the file name */
  94. char *dup_name =
  95. NZALLOC (char, strlen (include->dir) + strlen (file_name) + 2);
  96. if (dup_name == NULL)
  97. {
  98. perror (file_name);
  99. exit (1);
  100. }
  101. if (include->dir[0] != '\0')
  102. {
  103. strcat (dup_name, include->dir);
  104. strcat (dup_name, "/");
  105. }
  106. strcat (dup_name, file_name);
  107. file->real_line.file_name = dup_name;
  108. file->pseudo_line.file_name = dup_name;
  109. /* open the file */
  110. ff = fopen (dup_name, "rb");
  111. if (ff)
  112. break;
  113. /* zfree (dup_name); */
  114. if (include->next == NULL)
  115. {
  116. if (line != NULL)
  117. error (line, "Problem opening file `%s'\n", file_name);
  118. perror (file_name);
  119. exit (1);
  120. }
  121. include = include->next;
  122. }
  123. /* determine the size */
  124. fseek (ff, 0, SEEK_END);
  125. file->size = ftell (ff);
  126. fseek (ff, 0, SEEK_SET);
  127. /* allocate this much memory */
  128. file->buffer = (char *) zalloc (file->size + 1);
  129. if (file->buffer == NULL)
  130. {
  131. perror (file_name);
  132. exit (1);
  133. }
  134. file->pos = file->buffer;
  135. /* read it all in */
  136. if (fread (file->buffer, 1, file->size, ff) < file->size)
  137. {
  138. perror (file_name);
  139. exit (1);
  140. }
  141. file->buffer[file->size] = '\0';
  142. /* set the initial line numbering */
  143. file->real_line.line_nr = 1; /* specifies current line */
  144. file->pseudo_line.line_nr = 1; /* specifies current line */
  145. /* done */
  146. fclose (ff);
  147. }
  148. table *
  149. table_open (const char *file_name)
  150. {
  151. table *root;
  152. /* create a file descriptor */
  153. root = ZALLOC (table);
  154. if (root == NULL)
  155. {
  156. perror (file_name);
  157. exit (1);
  158. }
  159. table_push (root, NULL, NULL, file_name);
  160. return root;
  161. }
  162. char *
  163. skip_spaces (char *chp)
  164. {
  165. while (1)
  166. {
  167. if (*chp == '\0' || *chp == '\n' || !isspace (*chp))
  168. return chp;
  169. chp++;
  170. }
  171. }
  172. char *
  173. back_spaces (char *start, char *chp)
  174. {
  175. while (1)
  176. {
  177. if (chp <= start || !isspace (chp[-1]))
  178. return chp;
  179. chp--;
  180. }
  181. }
  182. char *
  183. skip_digits (char *chp)
  184. {
  185. while (1)
  186. {
  187. if (*chp == '\0' || *chp == '\n' || !isdigit (*chp))
  188. return chp;
  189. chp++;
  190. }
  191. }
  192. char *
  193. skip_to_separator (char *chp, char *separators)
  194. {
  195. while (1)
  196. {
  197. char *sep = separators;
  198. while (1)
  199. {
  200. if (*chp == *sep)
  201. return chp;
  202. if (*sep == '\0')
  203. break;
  204. sep++;
  205. }
  206. chp++;
  207. }
  208. }
  209. static char *
  210. skip_to_null (char *chp)
  211. {
  212. return skip_to_separator (chp, "");
  213. }
  214. static char *
  215. skip_to_nl (char *chp)
  216. {
  217. return skip_to_separator (chp, "\n");
  218. }
  219. static void
  220. next_line (open_table * file)
  221. {
  222. file->pos = skip_to_nl (file->pos);
  223. if (*file->pos == '0')
  224. error (&file->pseudo_line, "Missing <nl> at end of line\n");
  225. *file->pos = '\0';
  226. file->pos += 1;
  227. file->real_line.line_nr += 1;
  228. file->pseudo_line.line_nr += 1;
  229. }
  230. extern table_entry *
  231. table_read (table *root)
  232. {
  233. open_table *file = root->current;
  234. table_entry *entry = NULL;
  235. while (1)
  236. {
  237. /* end-of-file? */
  238. while (*file->pos == '\0')
  239. {
  240. if (file->parent != NULL)
  241. {
  242. file = file->parent;
  243. root->current = file;
  244. }
  245. else
  246. return NULL;
  247. }
  248. /* code_block? */
  249. if (*file->pos == '{')
  250. {
  251. char *chp;
  252. next_line (file); /* discard leading brace */
  253. entry = new_table_entry (file, table_code_entry);
  254. chp = file->pos;
  255. /* determine how many lines are involved - look for <nl> "}" */
  256. {
  257. int nr_lines = 0;
  258. while (*file->pos != '}')
  259. {
  260. next_line (file);
  261. nr_lines++;
  262. }
  263. set_nr_table_entry_fields (entry, nr_lines);
  264. }
  265. /* now enter each line */
  266. {
  267. int line_nr;
  268. for (line_nr = 0; line_nr < entry->nr_fields; line_nr++)
  269. {
  270. if (strncmp (chp, " ", 2) == 0)
  271. entry->field[line_nr] = chp + 2;
  272. else
  273. entry->field[line_nr] = chp;
  274. chp = skip_to_null (chp) + 1;
  275. }
  276. /* skip trailing brace */
  277. ASSERT (*file->pos == '}');
  278. next_line (file);
  279. }
  280. break;
  281. }
  282. /* tab block? */
  283. if (*file->pos == '\t')
  284. {
  285. char *chp = file->pos;
  286. entry = new_table_entry (file, table_code_entry);
  287. /* determine how many lines are involved - look for <nl> !<tab> */
  288. {
  289. int nr_lines = 0;
  290. int nr_blank_lines = 0;
  291. while (1)
  292. {
  293. if (*file->pos == '\t')
  294. {
  295. nr_lines = nr_lines + nr_blank_lines + 1;
  296. nr_blank_lines = 0;
  297. next_line (file);
  298. }
  299. else
  300. {
  301. file->pos = skip_spaces (file->pos);
  302. if (*file->pos != '\n')
  303. break;
  304. nr_blank_lines++;
  305. next_line (file);
  306. }
  307. }
  308. set_nr_table_entry_fields (entry, nr_lines);
  309. }
  310. /* now enter each line */
  311. {
  312. int line_nr;
  313. for (line_nr = 0; line_nr < entry->nr_fields; line_nr++)
  314. {
  315. if (*chp == '\t')
  316. entry->field[line_nr] = chp + 1;
  317. else
  318. entry->field[line_nr] = ""; /* blank */
  319. chp = skip_to_null (chp) + 1;
  320. }
  321. }
  322. break;
  323. }
  324. /* cpp directive? */
  325. if (file->pos[0] == '#')
  326. {
  327. char *chp = skip_spaces (file->pos + 1);
  328. /* cpp line-nr directive - # <line-nr> "<file>" */
  329. if (isdigit (*chp)
  330. && *skip_digits (chp) == ' '
  331. && *skip_spaces (skip_digits (chp)) == '"')
  332. {
  333. int line_nr;
  334. char *file_name;
  335. file->pos = chp;
  336. /* parse the number */
  337. line_nr = atoi (file->pos) - 1;
  338. /* skip to the file name */
  339. while (file->pos[0] != '0'
  340. && file->pos[0] != '"' && file->pos[0] != '\0')
  341. file->pos++;
  342. if (file->pos[0] != '"')
  343. error (&file->real_line,
  344. "Missing opening quote in cpp directive\n");
  345. /* parse the file name */
  346. file->pos++;
  347. file_name = file->pos;
  348. while (file->pos[0] != '"' && file->pos[0] != '\0')
  349. file->pos++;
  350. if (file->pos[0] != '"')
  351. error (&file->real_line,
  352. "Missing closing quote in cpp directive\n");
  353. file->pos[0] = '\0';
  354. file->pos++;
  355. file->pos = skip_to_nl (file->pos);
  356. if (file->pos[0] != '\n')
  357. error (&file->real_line,
  358. "Missing newline in cpp directive\n");
  359. file->pseudo_line.file_name = file_name;
  360. file->pseudo_line.line_nr = line_nr;
  361. next_line (file);
  362. continue;
  363. }
  364. /* #define and #undef - not implemented yet */
  365. /* Old style # comment */
  366. next_line (file);
  367. continue;
  368. }
  369. /* blank line or end-of-file? */
  370. file->pos = skip_spaces (file->pos);
  371. if (*file->pos == '\0')
  372. error (&file->pseudo_line, "Missing <nl> at end of file\n");
  373. if (*file->pos == '\n')
  374. {
  375. next_line (file);
  376. continue;
  377. }
  378. /* comment - leading // or # - skip */
  379. if ((file->pos[0] == '/' && file->pos[1] == '/')
  380. || (file->pos[0] == '#'))
  381. {
  382. next_line (file);
  383. continue;
  384. }
  385. /* colon field */
  386. {
  387. char *chp = file->pos;
  388. entry = new_table_entry (file, table_colon_entry);
  389. next_line (file);
  390. /* figure out how many fields */
  391. {
  392. int nr_fields = 1;
  393. char *tmpch = chp;
  394. while (1)
  395. {
  396. tmpch = skip_to_separator (tmpch, "\\:");
  397. if (*tmpch == '\\')
  398. {
  399. /* eat the escaped character */
  400. char *cp = tmpch;
  401. while (cp[1] != '\0')
  402. {
  403. cp[0] = cp[1];
  404. cp++;
  405. }
  406. cp[0] = '\0';
  407. tmpch++;
  408. }
  409. else if (*tmpch != ':')
  410. break;
  411. else
  412. {
  413. *tmpch = '\0';
  414. tmpch++;
  415. nr_fields++;
  416. }
  417. }
  418. set_nr_table_entry_fields (entry, nr_fields);
  419. }
  420. /* now parse them */
  421. {
  422. int field_nr;
  423. for (field_nr = 0; field_nr < entry->nr_fields; field_nr++)
  424. {
  425. chp = skip_spaces (chp);
  426. entry->field[field_nr] = chp;
  427. chp = skip_to_null (chp);
  428. *back_spaces (entry->field[field_nr], chp) = '\0';
  429. chp++;
  430. }
  431. }
  432. break;
  433. }
  434. }
  435. ASSERT (entry == NULL || entry->field[entry->nr_fields] == NULL);
  436. return entry;
  437. }
  438. extern void
  439. table_print_code (lf *file, table_entry *entry)
  440. {
  441. int field_nr;
  442. int nr = 0;
  443. for (field_nr = 0; field_nr < entry->nr_fields; field_nr++)
  444. {
  445. char *chp = entry->field[field_nr];
  446. int in_bit_field = 0;
  447. if (*chp == '#')
  448. lf_indent_suppress (file);
  449. while (*chp != '\0')
  450. {
  451. if (chp[0] == '{' && !isspace (chp[1]) && chp[1] != '\0')
  452. {
  453. in_bit_field = 1;
  454. nr += lf_putchr (file, '_');
  455. }
  456. else if (in_bit_field && chp[0] == ':')
  457. {
  458. nr += lf_putchr (file, '_');
  459. }
  460. else if (in_bit_field && *chp == '}')
  461. {
  462. nr += lf_putchr (file, '_');
  463. in_bit_field = 0;
  464. }
  465. else
  466. {
  467. nr += lf_putchr (file, *chp);
  468. }
  469. chp++;
  470. }
  471. if (in_bit_field)
  472. {
  473. line_ref line = *entry->line;
  474. line.line_nr += field_nr;
  475. error (&line, "Bit field brace miss match\n");
  476. }
  477. nr += lf_putchr (file, '\n');
  478. }
  479. }
  480. void
  481. dump_line_ref (lf *file, char *prefix, const line_ref *line, char *suffix)
  482. {
  483. lf_printf (file, "%s(line_ref*) 0x%lx", prefix, (long) line);
  484. if (line != NULL)
  485. {
  486. lf_indent (file, +1);
  487. lf_printf (file, "\n(line_nr %d)", line->line_nr);
  488. lf_printf (file, "\n(file_name %s)", line->file_name);
  489. lf_indent (file, -1);
  490. }
  491. lf_printf (file, "%s", suffix);
  492. }
  493. static const char *
  494. table_entry_type_to_str (table_entry_type type)
  495. {
  496. switch (type)
  497. {
  498. case table_code_entry:
  499. return "code-entry";
  500. case table_colon_entry:
  501. return "colon-entry";
  502. }
  503. return "*invalid*";
  504. }
  505. void
  506. dump_table_entry (lf *file,
  507. char *prefix, const table_entry *entry, char *suffix)
  508. {
  509. lf_printf (file, "%s(table_entry*) 0x%lx", prefix, (long) entry);
  510. if (entry != NULL)
  511. {
  512. int field;
  513. lf_indent (file, +1);
  514. dump_line_ref (file, "\n(line ", entry->line, ")");
  515. lf_printf (file, "\n(type %s)", table_entry_type_to_str (entry->type));
  516. lf_printf (file, "\n(nr_fields %d)", entry->nr_fields);
  517. lf_printf (file, "\n(fields");
  518. lf_indent (file, +1);
  519. for (field = 0; field < entry->nr_fields; field++)
  520. lf_printf (file, "\n\"%s\"", entry->field[field]);
  521. lf_indent (file, -1);
  522. lf_printf (file, ")");
  523. lf_indent (file, -1);
  524. }
  525. lf_printf (file, "%s", suffix);
  526. }
  527. #ifdef MAIN
  528. int
  529. main (int argc, char **argv)
  530. {
  531. table *t;
  532. table_entry *entry;
  533. lf *l;
  534. int line_nr;
  535. if (argc != 2)
  536. {
  537. printf ("Usage: table <file>\n");
  538. exit (1);
  539. }
  540. t = table_open (argv[1]);
  541. l = lf_open ("-", "stdout", lf_omit_references, lf_is_text, "tmp-table");
  542. line_nr = 0;
  543. do
  544. {
  545. char line[10];
  546. entry = table_read (t);
  547. line_nr++;
  548. sprintf (line, "(%d ", line_nr);
  549. dump_table_entry (l, line, entry, ")\n");
  550. }
  551. while (entry != NULL);
  552. return 0;
  553. }
  554. #endif