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