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