* configure.tgt: Add tx49 configury based on 4300.
[deliverable/binutils-gdb.git] / sim / igen / table.c
1 /* This file is part of the program psim.
2
3 Copyright (C) 1994-1995,1997 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 <sys/types.h>
23 #include <sys/stat.h>
24 #include <stdio.h>
25 #include <fcntl.h>
26 #include <ctype.h>
27
28 #include "config.h"
29 #include "misc.h"
30 #include "lf.h"
31 #include "table.h"
32
33 #ifdef HAVE_UNISTD_H
34 #include <unistd.h>
35 #endif
36
37 #ifdef HAVE_STDLIB_H
38 #include <stdlib.h>
39 #endif
40
41 typedef struct _open_table open_table;
42 struct _open_table {
43 size_t size;
44 char *buffer;
45 char *pos;
46 line_ref pseudo_line;
47 line_ref real_line;
48 open_table *parent;
49 table *root;
50 };
51 struct _table {
52 open_table *current;
53 };
54
55
56 static line_ref *
57 current_line (open_table *file)
58 {
59 line_ref *entry = ZALLOC (line_ref);
60 *entry = file->pseudo_line;
61 return entry;
62 }
63
64 static table_entry *
65 new_table_entry (open_table *file,
66 table_entry_type type)
67 {
68 table_entry *entry;
69 entry = ZALLOC (table_entry);
70 entry->file = file->root;
71 entry->line = current_line (file);
72 entry->type = type;
73 return entry;
74 }
75
76 static void
77 set_nr_table_entry_fields (table_entry *entry,
78 int nr_fields)
79 {
80 entry->field = NZALLOC (char*, nr_fields + 1);
81 entry->nr_fields = nr_fields;
82 }
83
84
85 void
86 table_push (table *root,
87 line_ref *line,
88 table_include *includes,
89 const char *file_name)
90 {
91 int fd;
92 struct stat stat_buf;
93 open_table *file;
94 table_include dummy;
95 table_include *include = &dummy;
96
97 /* dummy up a search of this directory */
98 dummy.next = includes;
99 dummy.dir = "";
100
101 /* create a file descriptor */
102 file = ZALLOC (open_table);
103 if (file == NULL)
104 {
105 perror (file_name);
106 exit (1);
107 }
108 file->root = root;
109 file->parent = root->current;
110 root->current = file;
111
112 while (1)
113 {
114 /* save the file name */
115 char *dup_name = NZALLOC (char, strlen (include->dir) + strlen (file_name) + 2);
116 if (dup_name == NULL)
117 {
118 perror (file_name);
119 exit (1);
120 }
121 if (include->dir[0] != '\0')
122 {
123 strcat (dup_name, include->dir);
124 strcat (dup_name, "/");
125 }
126 strcat (dup_name, file_name);
127 file->real_line.file_name = dup_name;
128 file->pseudo_line.file_name = dup_name;
129 printf ("Trying `%s'\n", dup_name);
130 /* open the file */
131 fd = open (dup_name, O_RDONLY, 0);
132 if (fd >= 0)
133 break;
134 /* zfree (dup_name); */
135 if (include->next == NULL)
136 {
137 if (line != NULL)
138 error (line, "Problem opening file `%s'\n", file_name);
139 perror (file_name);
140 exit (1);
141 }
142 include = include->next;
143 }
144
145
146 /* determine the size */
147 if (fstat (fd, &stat_buf) < 0) {
148 perror (file_name);
149 exit (1);
150 }
151 file->size = stat_buf.st_size;
152
153 /* allocate this much memory */
154 file->buffer = (char*) zalloc (file->size + 1);
155 if (file->buffer == NULL)
156 {
157 perror (file_name);
158 exit (1);
159 }
160 file->pos = file->buffer;
161
162 /* read it all in */
163 if (read (fd, file->buffer, file->size) < file->size) {
164 perror (file_name);
165 exit (1);
166 }
167 file->buffer[file->size] = '\0';
168
169 /* set the initial line numbering */
170 file->real_line.line_nr = 1; /* specifies current line */
171 file->pseudo_line.line_nr = 1; /* specifies current line */
172
173 /* done */
174 close (fd);
175 }
176
177 table *
178 table_open (const char *file_name)
179 {
180 table *root;
181
182 /* create a file descriptor */
183 root = ZALLOC (table);
184 if (root == NULL)
185 {
186 perror (file_name);
187 exit (1);
188 }
189
190 table_push (root, NULL, NULL, file_name);
191 return root;
192 }
193
194 char *
195 skip_spaces (char *chp)
196 {
197 while (1)
198 {
199 if (*chp == '\0'
200 || *chp == '\n'
201 || !isspace (*chp))
202 return chp;
203 chp++;
204 }
205 }
206
207
208 char *
209 back_spaces (char *start, char *chp)
210 {
211 while (1)
212 {
213 if (chp <= start
214 || !isspace (chp[-1]))
215 return chp;
216 chp--;
217 }
218 }
219
220 char *
221 skip_digits (char *chp)
222 {
223 while (1)
224 {
225 if (*chp == '\0'
226 || *chp == '\n'
227 || !isdigit (*chp))
228 return chp;
229 chp++;
230 }
231 }
232
233 char *
234 skip_to_separator (char *chp,
235 char *separators)
236 {
237 while (1)
238 {
239 char *sep = separators;
240 while (1)
241 {
242 if (*chp == *sep)
243 return chp;
244 if (*sep == '\0')
245 break;
246 sep++;
247 }
248 chp++;
249 }
250 }
251
252 static char *
253 skip_to_null (char *chp)
254 {
255 return skip_to_separator (chp, "");
256 }
257
258
259 static char *
260 skip_to_nl (char * chp)
261 {
262 return skip_to_separator (chp, "\n");
263 }
264
265
266 static void
267 next_line (open_table *file)
268 {
269 file->pos = skip_to_nl (file->pos);
270 if (*file->pos == '0')
271 error (&file->pseudo_line, "Missing <nl> at end of line\n");
272 *file->pos = '\0';
273 file->pos += 1;
274 file->real_line.line_nr += 1;
275 file->pseudo_line.line_nr += 1;
276 }
277
278
279 extern table_entry *
280 table_read (table *root)
281 {
282 open_table *file = root->current;
283 table_entry *entry = NULL;
284 while(1)
285 {
286
287 /* end-of-file? */
288 while (*file->pos == '\0')
289 {
290 if (file->parent != NULL)
291 {
292 file = file->parent;
293 root->current = file;
294 }
295 else
296 return NULL;
297 }
298
299 /* code_block? */
300 if (*file->pos == '{')
301 {
302 char *chp;
303 next_line (file); /* discard leading brace */
304 entry = new_table_entry (file, table_code_entry);
305 chp = file->pos;
306 /* determine how many lines are involved - look for <nl> "}" */
307 {
308 int nr_lines = 0;
309 while (*file->pos != '}')
310 {
311 next_line (file);
312 nr_lines++;
313 }
314 set_nr_table_entry_fields (entry, nr_lines);
315 }
316 /* now enter each line */
317 {
318 int line_nr;
319 for (line_nr = 0; line_nr < entry->nr_fields; line_nr++)
320 {
321 if (strncmp (chp, " ", 2) == 0)
322 entry->field[line_nr] = chp + 2;
323 else
324 entry->field[line_nr] = chp;
325 chp = skip_to_null (chp) + 1;
326 }
327 /* skip trailing brace */
328 ASSERT (*file->pos == '}');
329 next_line (file);
330 }
331 break;
332 }
333
334 /* tab block? */
335 if (*file->pos == '\t')
336 {
337 char *chp = file->pos;
338 entry = new_table_entry (file, table_code_entry);
339 /* determine how many lines are involved - look for <nl> !<tab> */
340 {
341 int nr_lines = 0;
342 int nr_blank_lines = 0;
343 while (1)
344 {
345 if (*file->pos == '\t')
346 {
347 nr_lines = nr_lines + nr_blank_lines + 1;
348 nr_blank_lines = 0;
349 next_line (file);
350 }
351 else
352 {
353 file->pos = skip_spaces (file->pos);
354 if (*file->pos != '\n')
355 break;
356 nr_blank_lines++;
357 next_line (file);
358 }
359 }
360 set_nr_table_entry_fields (entry, nr_lines);
361 }
362 /* now enter each line */
363 {
364 int line_nr;
365 for (line_nr = 0; line_nr < entry->nr_fields; line_nr++)
366 {
367 if (*chp == '\t')
368 entry->field[line_nr] = chp + 1;
369 else
370 entry->field[line_nr] = ""; /* blank */
371 chp = skip_to_null (chp) + 1;
372 }
373 }
374 break;
375 }
376
377 /* cpp directive? */
378 if (file->pos[0] == '#')
379 {
380 char *chp = skip_spaces (file->pos + 1);
381
382 /* cpp line-nr directive - # <line-nr> "<file>" */
383 if (isdigit (*chp)
384 && *skip_digits (chp) == ' '
385 && *skip_spaces (skip_digits (chp)) == '"')
386 {
387 int line_nr;
388 char *file_name;
389 file->pos = chp;
390 /* parse the number */
391 line_nr = atoi(file->pos) - 1;
392 /* skip to the file name */
393 while (file->pos[0] != '0'
394 && file->pos[0] != '"'
395 && file->pos[0] != '\0')
396 file->pos++;
397 if (file->pos[0] != '"')
398 error (&file->real_line, "Missing opening quote in cpp directive\n");
399 /* parse the file name */
400 file->pos++;
401 file_name = file->pos;
402 while (file->pos[0] != '"'
403 && file->pos[0] != '\0')
404 file->pos++;
405 if (file->pos[0] != '"')
406 error (&file->real_line, "Missing closing quote in cpp directive\n");
407 file->pos[0] = '\0';
408 file->pos++;
409 file->pos = skip_to_nl (file->pos);
410 if (file->pos[0] != '\n')
411 error (&file->real_line, "Missing newline in cpp directive\n");
412 file->pseudo_line.file_name = file_name;
413 file->pseudo_line.line_nr = line_nr;
414 next_line (file);
415 continue;
416 }
417
418 /* #define and #undef - not implemented yet */
419
420 /* Old style # comment */
421 next_line (file);
422 continue;
423 }
424
425 /* blank line or end-of-file? */
426 file->pos = skip_spaces (file->pos);
427 if (*file->pos == '\0')
428 error (&file->pseudo_line, "Missing <nl> at end of file\n");
429 if (*file->pos == '\n')
430 {
431 next_line (file);
432 continue;
433 }
434
435 /* comment - leading // or # - skip */
436 if ((file->pos[0] == '/' && file->pos[1] == '/')
437 || (file->pos[0] == '#'))
438 {
439 next_line (file);
440 continue;
441 }
442
443 /* colon field */
444 {
445 char *chp = file->pos;
446 entry = new_table_entry (file, table_colon_entry);
447 next_line (file);
448 /* figure out how many fields */
449 {
450 int nr_fields = 1;
451 char *tmpch = chp;
452 while (1)
453 {
454 tmpch = skip_to_separator (tmpch, "\\:");
455 if (*tmpch == '\\')
456 {
457 /* eat the escaped character */
458 char *cp = tmpch;
459 while (cp[1] != '\0')
460 {
461 cp[0] = cp[1];
462 cp++;
463 }
464 cp[0] = '\0';
465 tmpch++;
466 }
467 else if (*tmpch != ':')
468 break;
469 else
470 {
471 *tmpch = '\0';
472 tmpch++;
473 nr_fields++;
474 }
475 }
476 set_nr_table_entry_fields (entry, nr_fields);
477 }
478 /* now parse them */
479 {
480 int field_nr;
481 for (field_nr = 0; field_nr < entry->nr_fields; field_nr++)
482 {
483 chp = skip_spaces (chp);
484 entry->field[field_nr] = chp;
485 chp = skip_to_null (chp);
486 *back_spaces (entry->field[field_nr], chp) = '\0';
487 chp++;
488 }
489 }
490 break;
491 }
492
493 }
494
495 ASSERT (entry == NULL || entry->field[entry->nr_fields] == NULL);
496 return entry;
497 }
498
499 extern void
500 table_print_code (lf *file,
501 table_entry *entry)
502 {
503 int field_nr;
504 int nr = 0;
505 for (field_nr = 0;
506 field_nr < entry->nr_fields;
507 field_nr++)
508 {
509 char *chp = entry->field[field_nr];
510 int in_bit_field = 0;
511 if (*chp == '#')
512 lf_indent_suppress(file);
513 while (*chp != '\0')
514 {
515 if (chp[0] == '{'
516 && !isspace(chp[1])
517 && chp[1] != '\0')
518 {
519 in_bit_field = 1;
520 nr += lf_putchr(file, '_');
521 }
522 else if (in_bit_field && chp[0] == ':')
523 {
524 nr += lf_putchr(file, '_');
525 }
526 else if (in_bit_field && *chp == '}')
527 {
528 nr += lf_putchr(file, '_');
529 in_bit_field = 0;
530 }
531 else
532 {
533 nr += lf_putchr(file, *chp);
534 }
535 chp++;
536 }
537 if (in_bit_field)
538 {
539 line_ref line = *entry->line;
540 line.line_nr += field_nr;
541 error (&line, "Bit field brace miss match\n");
542 }
543 nr += lf_putchr(file, '\n');
544 }
545 }
546
547
548
549 void
550 dump_line_ref (lf *file,
551 char *prefix,
552 const line_ref *line,
553 char *suffix)
554 {
555 lf_printf (file, "%s(line_ref*) 0x%lx", prefix, (long) line);
556 if (line != NULL)
557 {
558 lf_indent (file, +1);
559 lf_printf (file, "\n(line_nr %d)", line->line_nr);
560 lf_printf (file, "\n(file_name %s)", line->file_name);
561 lf_indent (file, -1);
562 }
563 lf_printf (file, "%s", suffix);
564 }
565
566
567 static const char *
568 table_entry_type_to_str (table_entry_type type)
569 {
570 switch (type)
571 {
572 case table_code_entry: return "code-entry";
573 case table_colon_entry: return "colon-entry";
574 }
575 return "*invalid*";
576 }
577
578 void
579 dump_table_entry(lf *file,
580 char *prefix,
581 const table_entry *entry,
582 char *suffix)
583 {
584 lf_printf (file, "%s(table_entry*) 0x%lx", prefix, (long) entry);
585 if (entry != NULL)
586 {
587 int field;
588 lf_indent (file, +1);
589 dump_line_ref (file, "\n(line ", entry->line, ")");
590 lf_printf (file, "\n(type %s)", table_entry_type_to_str (entry->type));
591 lf_printf (file, "\n(nr_fields %d)", entry->nr_fields);
592 lf_printf (file, "\n(fields");
593 lf_indent (file, +1);
594 for (field = 0; field < entry->nr_fields; field++)
595 lf_printf (file, "\n\"%s\"", entry->field[field]);
596 lf_indent (file, -1);
597 lf_printf (file, ")");
598 lf_indent (file, -1);
599 }
600 lf_printf (file, "%s", suffix);
601 }
602
603
604 #ifdef MAIN
605 int
606 main(int argc, char **argv)
607 {
608 table *t;
609 table_entry *entry;
610 lf *l;
611 int line_nr;
612
613 if (argc != 2)
614 {
615 printf("Usage: table <file>\n");
616 exit (1);
617 }
618
619 t = table_open (argv[1]);
620 l = lf_open ("-", "stdout", lf_omit_references, lf_is_text, "tmp-table");
621
622 line_nr = 0;
623 do
624 {
625 char line[10];
626 entry = table_read (t);
627 line_nr ++;
628 sprintf (line, "(%d ", line_nr);
629 dump_table_entry (l, line, entry, ")\n");
630 }
631 while (entry != NULL);
632
633 return 0;
634 }
635 #endif
This page took 0.064962 seconds and 4 git commands to generate.