OSDN Git Service

gcc/
[pf3gnuchains/gcc-fork.git] / gcc / read-md.c
1 /* MD reader for GCC.
2    Copyright (C) 1987, 1988, 1991, 1994, 1997, 1998, 1999, 2000, 2001, 2002,
3    2003, 2004, 2005, 2006, 2007, 2008, 2010
4    Free Software Foundation, Inc.
5
6 This file is part of GCC.
7
8 GCC is free software; you can redistribute it and/or modify it under
9 the terms of the GNU General Public License as published by the Free
10 Software Foundation; either version 3, or (at your option) any later
11 version.
12
13 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14 WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
16 for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with GCC; see the file COPYING3.  If not see
20 <http://www.gnu.org/licenses/>.  */
21
22 #include "bconfig.h"
23 #include "system.h"
24 #include "coretypes.h"
25 #include "hashtab.h"
26 #include "read-md.h"
27
28 /* Associates PTR (which can be a string, etc.) with the file location
29    specified by FILENAME and LINENO.  */
30 struct ptr_loc {
31   const void *ptr;
32   const char *filename;
33   int lineno;
34 };
35
36 /* Obstack used for allocating MD strings.  */
37 struct obstack string_obstack;
38
39 /* A table of ptr_locs, hashed on the PTR field.  */
40 static htab_t ptr_locs;
41
42 /* An obstack for the above.  Plain xmalloc is a bit heavyweight for a
43    small structure like ptr_loc.  */
44 static struct obstack ptr_loc_obstack;
45
46 /* A hash table of triples (A, B, C), where each of A, B and C is a condition
47    and A is equivalent to "B && C".  This is used to keep track of the source
48    of conditions that are made up of separate MD strings (such as the split
49    condition of a define_insn_and_split).  */
50 static htab_t joined_conditions;
51
52 /* An obstack for allocating joined_conditions entries.  */
53 static struct obstack joined_conditions_obstack;
54
55 /* The file we are reading.  */
56 FILE *read_md_file;
57
58 /* The filename of READ_MD_FILE.  */
59 const char *read_md_filename;
60
61 /* The current line number in READ_MD_FILE.  */
62 int read_md_lineno;
63
64 /* Return a hash value for the pointer pointed to by DEF.  */
65
66 static hashval_t
67 leading_ptr_hash (const void *def)
68 {
69   return htab_hash_pointer (*(const void *const *) def);
70 }
71
72 /* Return true if DEF1 and DEF2 are pointers to the same pointer.  */
73
74 static int
75 leading_ptr_eq_p (const void *def1, const void *def2)
76 {
77   return *(const void *const *) def1 == *(const void *const *) def2;
78 }
79
80 /* Associate PTR with the file position given by FILENAME and LINENO.  */
81
82 static void
83 set_md_ptr_loc (const void *ptr, const char *filename, int lineno)
84 {
85   struct ptr_loc *loc;
86
87   loc = (struct ptr_loc *) obstack_alloc (&ptr_loc_obstack,
88                                           sizeof (struct ptr_loc));
89   loc->ptr = ptr;
90   loc->filename = filename;
91   loc->lineno = lineno;
92   *htab_find_slot (ptr_locs, loc, INSERT) = loc;
93 }
94
95 /* Return the position associated with pointer PTR.  Return null if no
96    position was set.  */
97
98 static const struct ptr_loc *
99 get_md_ptr_loc (const void *ptr)
100 {
101   return (const struct ptr_loc *) htab_find (ptr_locs, &ptr);
102 }
103
104 /* Associate NEW_PTR with the same file position as OLD_PTR.  */
105
106 void
107 copy_md_ptr_loc (const void *new_ptr, const void *old_ptr)
108 {
109   const struct ptr_loc *loc = get_md_ptr_loc (old_ptr);
110   if (loc != 0)
111     set_md_ptr_loc (new_ptr, loc->filename, loc->lineno);
112 }
113
114 /* If PTR is associated with a known file position, print a #line
115    directive for it.  */
116
117 void
118 print_md_ptr_loc (const void *ptr)
119 {
120   const struct ptr_loc *loc = get_md_ptr_loc (ptr);
121   if (loc != 0)
122     printf ("#line %d \"%s\"\n", loc->lineno, loc->filename);
123 }
124
125 /* Return a condition that satisfies both COND1 and COND2.  Either string
126    may be null or empty.  */
127
128 const char *
129 join_c_conditions (const char *cond1, const char *cond2)
130 {
131   char *result;
132   const void **entry;
133
134   if (cond1 == 0 || cond1[0] == 0)
135     return cond2;
136
137   if (cond2 == 0 || cond2[0] == 0)
138     return cond1;
139
140   if (strcmp (cond1, cond2) == 0)
141     return cond1;
142
143   result = concat ("(", cond1, ") && (", cond2, ")", NULL);
144   obstack_ptr_grow (&joined_conditions_obstack, result);
145   obstack_ptr_grow (&joined_conditions_obstack, cond1);
146   obstack_ptr_grow (&joined_conditions_obstack, cond2);
147   entry = XOBFINISH (&joined_conditions_obstack, const void **);
148   *htab_find_slot (joined_conditions, entry, INSERT) = entry;
149   return result;
150 }
151
152 /* Print condition COND, wrapped in brackets.  If COND was created by
153    join_c_conditions, recursively invoke this function for the original
154    conditions and join the result with "&&".  Otherwise print a #line
155    directive for COND if its original file position is known.  */
156
157 void
158 print_c_condition (const char *cond)
159 {
160   const char **halves = (const char **) htab_find (joined_conditions, &cond);
161   if (halves != 0)
162     {
163       printf ("(");
164       print_c_condition (halves[1]);
165       printf (" && ");
166       print_c_condition (halves[2]);
167       printf (")");
168     }
169   else
170     {
171       putc ('\n', stdout);
172       print_md_ptr_loc (cond);
173       printf ("(%s)", cond);
174     }
175 }
176
177 /* A printf-like function for reporting an error against line LINENO
178    in the current MD file.  */
179
180 void
181 message_with_line (int lineno, const char *msg, ...)
182 {
183   va_list ap;
184
185   va_start (ap, msg);
186
187   fprintf (stderr, "%s:%d: ", read_md_filename, lineno);
188   vfprintf (stderr, msg, ap);
189   fputc ('\n', stderr);
190
191   va_end (ap);
192 }
193
194 /* A printf-like function for reporting an error against the current
195    position in the MD file.  */
196
197 void
198 fatal_with_file_and_line (const char *msg, ...)
199 {
200   char context[64];
201   size_t i;
202   int c;
203   va_list ap;
204
205   va_start (ap, msg);
206
207   fprintf (stderr, "%s:%d: ", read_md_filename, read_md_lineno);
208   vfprintf (stderr, msg, ap);
209   putc ('\n', stderr);
210
211   /* Gather some following context.  */
212   for (i = 0; i < sizeof (context)-1; ++i)
213     {
214       c = read_char ();
215       if (c == EOF)
216         break;
217       if (c == '\r' || c == '\n')
218         break;
219       context[i] = c;
220     }
221   context[i] = '\0';
222
223   fprintf (stderr, "%s:%d: following context is `%s'\n",
224            read_md_filename, read_md_lineno, context);
225
226   va_end (ap);
227   exit (1);
228 }
229
230 /* Report that we found character ACTUAL when we expected to find
231    character EXPECTED.  */
232
233 void
234 fatal_expected_char (int expected, int actual)
235 {
236   if (actual == EOF)
237     fatal_with_file_and_line ("expected character `%c', found EOF",
238                               expected);
239   else
240     fatal_with_file_and_line ("expected character `%c', found `%c'",
241                               expected, actual);
242 }
243
244 /* Read chars from the MD file until a non-whitespace char and return that.
245    Comments, both Lisp style and C style, are treated as whitespace.  */
246
247 int
248 read_skip_spaces (void)
249 {
250   int c;
251
252   while (1)
253     {
254       c = read_char ();
255       switch (c)
256         {
257         case '\n':
258           read_md_lineno++;
259           break;
260
261         case ' ': case '\t': case '\f': case '\r':
262           break;
263
264         case ';':
265           do
266             c = read_char ();
267           while (c != '\n' && c != EOF);
268           read_md_lineno++;
269           break;
270
271         case '/':
272           {
273             int prevc;
274             c = read_char ();
275             if (c != '*')
276               fatal_expected_char ('*', c);
277
278             prevc = 0;
279             while ((c = read_char ()) && c != EOF)
280               {
281                 if (c == '\n')
282                    read_md_lineno++;
283                 else if (prevc == '*' && c == '/')
284                   break;
285                 prevc = c;
286               }
287           }
288           break;
289
290         default:
291           return c;
292         }
293     }
294 }
295
296 /* Subroutine of the string readers.  Handles backslash escapes.
297    Caller has read the backslash, but not placed it into the obstack.  */
298
299 static void
300 read_escape (void)
301 {
302   int c = read_char ();
303
304   switch (c)
305     {
306       /* Backslash-newline is replaced by nothing, as in C.  */
307     case '\n':
308       read_md_lineno++;
309       return;
310
311       /* \" \' \\ are replaced by the second character.  */
312     case '\\':
313     case '"':
314     case '\'':
315       break;
316
317       /* Standard C string escapes:
318          \a \b \f \n \r \t \v
319          \[0-7] \x
320          all are passed through to the output string unmolested.
321          In normal use these wind up in a string constant processed
322          by the C compiler, which will translate them appropriately.
323          We do not bother checking that \[0-7] are followed by up to
324          two octal digits, or that \x is followed by N hex digits.
325          \? \u \U are left out because they are not in traditional C.  */
326     case 'a': case 'b': case 'f': case 'n': case 'r': case 't': case 'v':
327     case '0': case '1': case '2': case '3': case '4': case '5': case '6':
328     case '7': case 'x':
329       obstack_1grow (&string_obstack, '\\');
330       break;
331
332       /* \; makes stuff for a C string constant containing
333          newline and tab.  */
334     case ';':
335       obstack_grow (&string_obstack, "\\n\\t", 4);
336       return;
337
338       /* pass anything else through, but issue a warning.  */
339     default:
340       fprintf (stderr, "%s:%d: warning: unrecognized escape \\%c\n",
341                read_md_filename, read_md_lineno, c);
342       obstack_1grow (&string_obstack, '\\');
343       break;
344     }
345
346   obstack_1grow (&string_obstack, c);
347 }
348
349 /* Read a double-quoted string onto the obstack.  Caller has scanned
350    the leading quote.  */
351
352 char *
353 read_quoted_string (void)
354 {
355   int c;
356
357   while (1)
358     {
359       c = read_char (); /* Read the string  */
360       if (c == '\n')
361         read_md_lineno++;
362       else if (c == '\\')
363         {
364           read_escape ();
365           continue;
366         }
367       else if (c == '"' || c == EOF)
368         break;
369
370       obstack_1grow (&string_obstack, c);
371     }
372
373   obstack_1grow (&string_obstack, 0);
374   return XOBFINISH (&string_obstack, char *);
375 }
376
377 /* Read a braced string (a la Tcl) onto the string obstack.  Caller
378    has scanned the leading brace.  Note that unlike quoted strings,
379    the outermost braces _are_ included in the string constant.  */
380
381 static char *
382 read_braced_string (void)
383 {
384   int c;
385   int brace_depth = 1;  /* caller-processed */
386   unsigned long starting_read_md_lineno = read_md_lineno;
387
388   obstack_1grow (&string_obstack, '{');
389   while (brace_depth)
390     {
391       c = read_char (); /* Read the string  */
392
393       if (c == '\n')
394         read_md_lineno++;
395       else if (c == '{')
396         brace_depth++;
397       else if (c == '}')
398         brace_depth--;
399       else if (c == '\\')
400         {
401           read_escape ();
402           continue;
403         }
404       else if (c == EOF)
405         fatal_with_file_and_line
406           ("missing closing } for opening brace on line %lu",
407            starting_read_md_lineno);
408
409       obstack_1grow (&string_obstack, c);
410     }
411
412   obstack_1grow (&string_obstack, 0);
413   return XOBFINISH (&string_obstack, char *);
414 }
415
416 /* Read some kind of string constant.  This is the high-level routine
417    used by read_rtx.  It handles surrounding parentheses, leading star,
418    and dispatch to the appropriate string constant reader.  */
419
420 char *
421 read_string (int star_if_braced)
422 {
423   char *stringbuf;
424   int saw_paren = 0;
425   int c, old_lineno;
426
427   c = read_skip_spaces ();
428   if (c == '(')
429     {
430       saw_paren = 1;
431       c = read_skip_spaces ();
432     }
433
434   old_lineno = read_md_lineno;
435   if (c == '"')
436     stringbuf = read_quoted_string ();
437   else if (c == '{')
438     {
439       if (star_if_braced)
440         obstack_1grow (&string_obstack, '*');
441       stringbuf = read_braced_string ();
442     }
443   else
444     fatal_with_file_and_line ("expected `\"' or `{', found `%c'", c);
445
446   if (saw_paren)
447     {
448       c = read_skip_spaces ();
449       if (c != ')')
450         fatal_expected_char (')', c);
451     }
452
453   set_md_ptr_loc (stringbuf, read_md_filename, old_lineno);
454   return stringbuf;
455 }
456
457 /* Given a string, return the number of comma-separated elements in it.
458    Return 0 for the null string.  */
459
460 int
461 n_comma_elts (const char *s)
462 {
463   int n;
464
465   if (*s == '\0')
466     return 0;
467
468   for (n = 1; *s; s++)
469     if (*s == ',')
470       n++;
471
472   return n;
473 }
474
475 /* Given a pointer to a (char *), return a pointer to the beginning of the
476    next comma-separated element in the string.  Advance the pointer given
477    to the end of that element.  Return NULL if at end of string.  Caller
478    is responsible for copying the string if necessary.  White space between
479    a comma and an element is ignored.  */
480
481 const char *
482 scan_comma_elt (const char **pstr)
483 {
484   const char *start;
485   const char *p = *pstr;
486
487   if (*p == ',')
488     p++;
489   while (ISSPACE(*p))
490     p++;
491
492   if (*p == '\0')
493     return NULL;
494
495   start = p;
496
497   while (*p != ',' && *p != '\0')
498     p++;
499
500   *pstr = p;
501   return start;
502 }
503
504 /* Initialize this file's static data.  */
505
506 void
507 init_md_reader (void)
508 {
509   obstack_init (&string_obstack);
510   ptr_locs = htab_create (161, leading_ptr_hash, leading_ptr_eq_p, 0);
511   obstack_init (&ptr_loc_obstack);
512   joined_conditions = htab_create (161, leading_ptr_hash, leading_ptr_eq_p, 0);
513   obstack_init (&joined_conditions_obstack);
514 }