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