This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

better error reporting for genfoo


As genrecog et al get smarter about validating the md file, it
gets more and more irritating to find the problem given the 
extraordinarily lame error messages we give.

Well, no more.  Now, for the following input

   (define_insn "mismatch"
     [(set (match_operand:SI 0 "general_operand" "")
           (match_operand:DI 1 "general_operand" ""))]
     "" "")
   
   (define_insn "unknown"
     [(use (match_operand 0 "unknown_predicate" ""))]
     "" "")
   
   (define_insn "dup1"
     [(use (const_int 1))]
     "" "")
   
   (define_insn "dup2"
     [(use (const_int 1))]
     "" "")
   
   (define_insn "error"
     [(set (match_operand:SI "general_operand" "")
           (match_operand:SI 1 "general_operand" ""))]
     "" "")
   
we'll get something sensible:

   /home/rth/dummy:1: mode mismatch in set: SImode vs DImode
   /home/rth/dummy:1: warning: `general_operand' accepts const_int,
   /home/rth/dummy:1:   and used as destination of a set
   /home/rth/dummy:6: warning: `unknown_predicate' not in PREDICATE_CODES
   /home/rth/dummy:14: `dup2' matches `dup1'
   /home/rth/dummy:10: previous definition of `dup1'
   /home/rth/dummy:19: missing name or number
   /home/rth/dummy:19: following context is `"general_operand" "")'

In my fumble-fingered opinion, this is way way overdue.


r~

        * rtl.c (dump_and_abort): Remove.
        (fatal_with_file_and_line): New.
        (fatal_expected_char): New.
        (read_rtx_lineno, read_rtx_filename): New.
        (read_skip_spaces): Track line number.
        (read_name): Use fatal_with_file_and_line.
        (read_rtx): Use fatal_expected_char.  Track line number.
        * rtl.h (read_rtx_filename, read_rtx_lineno): Declare.

        * print-rtl.c (print_rtx): Don't special case LABEL_REF argument
        if it isn't a CODE_LABEL.

        * genattr.c (main): Set read_rtx_filename.
        * genattrtab.c (main): Likewise.
        * gencodes.c (main): Likewise.
        * genconfig.c (main): Likewise.
        * genemit.c (main): Likewise.
        * genextract.c (main): Likewise.
        * genflags.c (main): Likewise.
        * genopinit.c (main): Likewise.
        * genoutput.c (main): Likewise.
        * genpeep.c (main): Likewise.

        * genrecog.c (decision_test.u.insn): Add `lineno'.
        (pattern_lineno, error_count): New variables.
        (message_with_line): New.
        (add_to_sequence): Break out checking code to ...
        (validate_pattern): ... here.  Detect SET_DEST matching CONST_INT.
        (merge_insn): Use message_with_line.
        (make_insn_sequence): Use validate_pattern.  Record insn lineno.
        (main): Set read_rtx_filename, pattern_lineno.  Exit early on error.

Index: genattr.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/genattr.c,v
retrieving revision 1.28
diff -c -p -d -r1.28 genattr.c
*** genattr.c	1999/09/16 22:20:41	1.28
--- genattr.c	1999/10/14 03:34:33
*************** main (argc, argv)
*** 251,256 ****
--- 251,257 ----
        perror (argv[1]);
        return (FATAL_EXIT_CODE);
      }
+   read_rtx_filename = argv[1];
  
    printf ("/* Generated automatically by the program `genattr'\n\
  from the machine description file `md'.  */\n\n");
Index: genattrtab.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/genattrtab.c,v
retrieving revision 1.67
diff -c -p -d -r1.67 genattrtab.c
*** genattrtab.c	1999/10/04 06:08:16	1.67
--- genattrtab.c	1999/10/14 03:34:33
*************** main (argc, argv)
*** 6000,6005 ****
--- 6000,6006 ----
        perror (argv[1]);
        return (FATAL_EXIT_CODE);
      }
+   read_rtx_filename = argv[1];
  
    /* Set up true and false rtx's */
    true_rtx = rtx_alloc (CONST_INT);
Index: gencodes.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/gencodes.c,v
retrieving revision 1.24
diff -c -p -d -r1.24 gencodes.c
*** gencodes.c	1999/09/15 14:13:46	1.24
--- gencodes.c	1999/10/14 03:34:33
*************** main (argc, argv)
*** 98,103 ****
--- 98,104 ----
        perror (argv[1]);
        return (FATAL_EXIT_CODE);
      }
+   read_rtx_filename = argv[1];
  
    printf ("/* Generated automatically by the program `gencodes'\n\
  from the machine description file `md'.  */\n\n");
Index: genconfig.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/genconfig.c,v
retrieving revision 1.28
diff -c -p -d -r1.28 genconfig.c
*** genconfig.c	1999/10/06 17:22:54	1.28
--- genconfig.c	1999/10/14 03:34:33
*************** main (argc, argv)
*** 297,302 ****
--- 297,303 ----
        perror (argv[1]);
        return (FATAL_EXIT_CODE);
      }
+   read_rtx_filename = argv[1];
  
    printf ("/* Generated automatically by the program `genconfig'\n\
  from the machine description file `md'.  */\n\n");
Index: genemit.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/genemit.c,v
retrieving revision 1.47
diff -c -p -d -r1.47 genemit.c
*** genemit.c	1999/09/20 09:59:56	1.47
--- genemit.c	1999/10/14 03:34:33
*************** main (argc, argv)
*** 787,792 ****
--- 787,793 ----
        perror (argv[1]);
        return (FATAL_EXIT_CODE);
      }
+   read_rtx_filename = argv[1];
  
    /* Assign sequential codes to all entries in the machine description
       in parallel with the tables in insn-output.c.  */
Index: genextract.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/genextract.c,v
retrieving revision 1.35
diff -c -p -d -r1.35 genextract.c
*** genextract.c	1999/09/15 14:13:47	1.35
--- genextract.c	1999/10/14 03:34:33
*************** main (argc, argv)
*** 400,405 ****
--- 400,406 ----
        perror (argv[1]);
        return (FATAL_EXIT_CODE);
      }
+   read_rtx_filename = argv[1];
  
    /* Assign sequential codes to all entries in the machine description
       in parallel with the tables in insn-output.c.  */
Index: genflags.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/genflags.c,v
retrieving revision 1.24
diff -c -p -d -r1.24 genflags.c
*** genflags.c	1999/09/15 14:13:48	1.24
--- genflags.c	1999/10/14 03:34:33
*************** main (argc, argv)
*** 224,229 ****
--- 224,230 ----
        perror (argv[1]);
        return (FATAL_EXIT_CODE);
      }
+   read_rtx_filename = argv[1];
  
    printf ("/* Generated automatically by the program `genflags'\n\
  from the machine description file `md'.  */\n\n");
Index: genopinit.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/genopinit.c,v
retrieving revision 1.32
diff -c -p -d -r1.32 genopinit.c
*** genopinit.c	1999/09/23 11:34:49	1.32
--- genopinit.c	1999/10/14 03:34:33
*************** main (argc, argv)
*** 327,332 ****
--- 327,333 ----
        perror (argv[1]);
        return (FATAL_EXIT_CODE);
      }
+   read_rtx_filename = argv[1];
  
    printf ("/* Generated automatically by the program `genopinit'\n\
  from the machine description file `md'.  */\n\n");
Index: genoutput.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/genoutput.c,v
retrieving revision 1.37
diff -c -p -d -r1.37 genoutput.c
*** genoutput.c	1999/10/12 03:28:42	1.37
--- genoutput.c	1999/10/14 03:34:33
*************** main (argc, argv)
*** 907,912 ****
--- 907,913 ----
        perror (argv[1]);
        return (FATAL_EXIT_CODE);
      }
+   read_rtx_filename = argv[1];
  
    output_prologue ();
    next_code_number = 0;
Index: genpeep.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/genpeep.c,v
retrieving revision 1.37
diff -c -p -d -r1.37 genpeep.c
*** genpeep.c	1999/09/23 17:46:22	1.37
--- genpeep.c	1999/10/14 03:34:33
*************** main (argc, argv)
*** 424,429 ****
--- 424,430 ----
        perror (argv[1]);
        return (FATAL_EXIT_CODE);
      }
+   read_rtx_filename = argv[1];
  
    printf ("/* Generated automatically by the program `genpeep'\n\
  from the machine description file `md'.  */\n\n");
Index: genrecog.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/genrecog.c,v
retrieving revision 1.60
diff -c -p -d -r1.60 genrecog.c
*** genrecog.c	1999/10/13 17:22:40	1.60
--- genrecog.c	1999/10/14 03:34:33
*************** struct decision_test
*** 115,120 ****
--- 115,121 ----
  
      struct {
        int code_number;		/* Insn number matched.  */
+       int lineno;		/* Line number of the insn.  */
        int num_clobbers_to_add;	/* Number of CLOBBERs to be added.  */
      } insn;
    } u;
*************** static int next_index;
*** 170,175 ****
--- 171,182 ----
     allocate in each subroutine we make.  */
  
  static int max_depth;
+ 
+ /* The line number of the start of the pattern currently being processed.  */
+ static int pattern_lineno;
+ 
+ /* Count of errors.  */
+ static int error_count;
  
  /* This table contains a list of the rtl codes that can possibly match a
     predicate defined in recog.c.  The function `maybe_both_true' uses it to
*************** static struct decision *new_decision
*** 213,218 ****
--- 220,227 ----
    PROTO((const char *, struct decision_head *));
  static struct decision_test *new_decision_test
    PROTO((enum decision_type, struct decision_test ***));
+ static void validate_pattern
+   PROTO((rtx, int));
  static struct decision *add_to_sequence
    PROTO((rtx, struct decision_head *, const char *, enum routine_type, int));
  
*************** static void debug_decision_2
*** 284,289 ****
--- 293,321 ----
  extern void debug_decision
    PROTO((struct decision *));
  
+ static void
+ message_with_line VPROTO ((int lineno, const char *msg, ...))
+ {
+ #ifndef ANSI_PROTOTYPES
+   int lineno;
+   const char *msg;
+ #endif
+   va_list ap;
+ 
+   VA_START (ap, msg);
+ 
+ #ifndef ANSI_PROTOTYPES
+   lineno = va_arg (ap, int);
+   msg = va_arg (ap, const char *);
+ #endif
+ 
+   fprintf (stderr, "%s:%d: ", read_rtx_filename, lineno);
+   vfprintf (stderr, msg, ap);
+   fputc ('\n', stderr);
+ 
+   va_end (ap);
+ }
+ 
  /* Create a new node in sequence after LAST.  */
  
  static struct decision *
*************** new_decision_test (type, pplace)
*** 324,329 ****
--- 356,497 ----
    return test;
  }
  
+ /* Check for various errors in patterns.  */
+ 
+ static void
+ validate_pattern (pattern, set_dest)
+      rtx pattern;
+      int set_dest;
+ {
+   const char *fmt;
+   RTX_CODE code;
+   int i, j, len;
+ 
+   code = GET_CODE (pattern);
+   switch (code)
+     {
+     case MATCH_SCRATCH:
+     case MATCH_INSN:
+       return;
+ 
+     case MATCH_OPERAND:
+       {
+ 	const char *pred_name = XSTR (pattern, 1);
+ 
+ 	if (pred_name[0] != 0)
+ 	  {
+ 	    /* See if we know about this predicate and save its number.  If
+ 	       we do, and it only accepts one code, note that fact.  The
+ 	       predicate `const_int_operand' only tests for a CONST_INT, so
+ 	       if we do so we can avoid calling it at all.
+ 
+ 	       Finally, if we know that the predicate does not allow
+ 	       CONST_INT, we know that the only way the predicate can match
+ 	       is if the modes match (here we use the kludge of relying on
+ 	       the fact that "address_operand" accepts CONST_INT; otherwise,
+ 	       it would have to be a special case), so we can test the mode
+ 	       (but we need not).  This fact should considerably simplify the
+ 	       generated code.  */
+ 
+ 	    for (i = 0; i < (int) NUM_KNOWN_PREDS; i++)
+ 	      if (! strcmp (preds[i].name, pred_name))
+ 		break;
+ 
+ 	    if (i < (int) NUM_KNOWN_PREDS)
+ 	      {
+ 		int j, allows_const_int;
+ 
+ 		allows_const_int = 0;
+ 		for (j = 0; preds[i].codes[j] != 0; j++)
+ 		  if (preds[i].codes[j] == CONST_INT)
+ 		    {
+ 		      allows_const_int = 1;
+ 		      break;
+ 		    }
+ 
+ 		if (allows_const_int && set_dest)
+ 		  {
+ 		    message_with_line (pattern_lineno,
+ 				       "warning: `%s' accepts const_int,",
+ 				       pred_name);
+ 		    message_with_line (pattern_lineno,
+ 				       "  and used as destination of a set");
+ 		  }
+ 	      }
+ 	    else
+ 	      {
+ #ifdef PREDICATE_CODES
+ 		/* If the port has a list of the predicates it uses but
+ 		   omits one, warn.  */
+ 		message_with_line (pattern_lineno, "warning: `%s' not in PREDICATE_CODES", pred_name);
+ #endif
+ 	      }
+ 	  }
+ 
+ 	return;
+       }
+ 
+     case SET:
+       /* The operands of a SET must have the same mode unless one
+ 	 is VOIDmode.  */
+       if (GET_MODE (SET_SRC (pattern)) != VOIDmode
+ 	  && GET_MODE (SET_DEST (pattern)) != VOIDmode
+ 	  && GET_MODE (SET_SRC (pattern)) != GET_MODE (SET_DEST (pattern))
+ 	  /* The mode of an ADDRESS_OPERAND is the mode of the memory
+ 	     reference, not the mode of the address.  */
+ 	  && ! (GET_CODE (SET_SRC (pattern)) == MATCH_OPERAND
+ 		&& ! strcmp (XSTR (SET_SRC (pattern), 1), "address_operand")))
+ 	{
+ 	  message_with_line (pattern_lineno,
+ 			     "mode mismatch in set: %smode vs %smode",
+ 			     GET_MODE_NAME (GET_MODE (SET_DEST (pattern))),
+ 			     GET_MODE_NAME (GET_MODE (SET_SRC (pattern))));
+ 	  error_count++;
+ 	}
+ 
+       validate_pattern (SET_DEST (pattern), 1);
+       validate_pattern (SET_SRC (pattern), 0);
+       return;
+       
+     case LABEL_REF:
+       if (GET_MODE (XEXP (pattern, 0)) != VOIDmode)
+ 	{
+ 	  message_with_line (pattern_lineno,
+ 			     "operand to label_ref %smode not VOIDmode",
+ 			     GET_MODE_NAME (GET_MODE (XEXP (pattern, 0))));
+ 	  error_count++;
+ 	}
+       break;
+ 
+     default:
+       break;
+     }
+ 
+   fmt = GET_RTX_FORMAT (code);
+   len = GET_RTX_LENGTH (code);
+   for (i = 0; i < len; i++)
+     {
+       switch (fmt[i])
+ 	{
+ 	case 'e': case 'u':
+ 	  validate_pattern (XEXP (pattern, i), 0);
+ 	  break;
+ 
+ 	case 'E':
+ 	  for (j = 0; j < XVECLEN (pattern, i); j++)
+ 	    validate_pattern (XVECEXP (pattern, i, j), 0);
+ 	  break;
+ 
+ 	case 'i': case 'w': case '0': case 's':
+ 	  break;
+ 
+ 	default:
+ 	  abort ();
+ 	}
+     }
+ 
+ }
+ 
  /* Create a chain of nodes to verify that an rtl expression matches
     PATTERN.
  
*************** add_to_sequence (pattern, last, position
*** 465,479 ****
  		    }
  	      }
  	    else
! 	      {
! 		test->u.pred.index = -1;
! #ifdef PREDICATE_CODES
! 		/* If the port has a list of the predicates it uses but
! 		   omits one, warn.  */
! 		fprintf (stderr, "Warning: `%s' not in PREDICATE_CODES\n",
! 			 pred_name);
! #endif
! 	      }
  	  }
  
  	/* Can't enforce a mode if we allow const_int.  */
--- 633,639 ----
  		    }
  	      }
  	    else
! 	      test->u.pred.index = -1;
  	  }
  
  	/* Can't enforce a mode if we allow const_int.  */
*************** add_to_sequence (pattern, last, position
*** 526,557 ****
        pattern = XEXP (pattern, 0);
        goto restart;
  
-     case SET:
-       /* The operands of a SET must have the same mode unless one
- 	 is VOIDmode.  */
-       if (GET_MODE (SET_SRC (pattern)) != VOIDmode
- 	  && GET_MODE (SET_DEST (pattern)) != VOIDmode
- 	  && GET_MODE (SET_SRC (pattern)) != GET_MODE (SET_DEST (pattern))
- 	  /* The mode of an ADDRESS_OPERAND is the mode of the memory
- 	     reference, not the mode of the address.  */
- 	  && ! (GET_CODE (SET_SRC (pattern)) == MATCH_OPERAND
- 		&& ! strcmp (XSTR (SET_SRC (pattern), 1), "address_operand")))
- 	{
- 	  print_rtl (stderr, pattern);
- 	  fputc ('\n', stderr);
- 	  fatal ("mode mismatch in SET");
- 	}
-       break;
-       
-     case LABEL_REF:
-       if (GET_MODE (XEXP (pattern, 0)) != VOIDmode)
- 	{
- 	  print_rtl (stderr, pattern);
- 	  fputc ('\n', stderr);
- 	  fatal ("operand to LABEL_REF not VOIDmode");
- 	}
-       break;
- 
      default:
        break;
      }
--- 686,691 ----
*************** merge_accept_insn (oldd, addd)
*** 966,976 ****
      }
    else
      {
!       fatal ("Two actions at one point in tree for insns \"%s\" (%d) and \"%s\" (%d)",
! 	     get_insn_name (old->u.insn.code_number),
! 	     old->u.insn.code_number,
! 	     get_insn_name (add->u.insn.code_number),
! 	     add->u.insn.code_number);
      }
  }
  
--- 1100,1111 ----
      }
    else
      {
!       message_with_line (add->u.insn.lineno, "`%s' matches `%s'",
! 			 get_insn_name (add->u.insn.code_number),
! 			 get_insn_name (old->u.insn.code_number));
!       message_with_line (old->u.insn.lineno, "previous definition of `%s'",
! 			 get_insn_name (old->u.insn.code_number));
!       error_count++;
      }
  }
  
*************** make_insn_sequence (insn, type)
*** 2015,2020 ****
--- 2150,2157 ----
        PUT_MODE (x, VOIDmode);
      }
  
+   validate_pattern (x, 0);
+ 
    memset(&head, 0, sizeof(head));
    last = add_to_sequence (x, &head, "", type, 1);
  
*************** make_insn_sequence (insn, type)
*** 2037,2042 ****
--- 2174,2180 ----
  
    test = new_decision_test (DT_accept_insn, &place);
    test->u.insn.code_number = next_insn_code;
+   test->u.insn.lineno = pattern_lineno;
    test->u.insn.num_clobbers_to_add = 0;
  
    switch (type)
*************** make_insn_sequence (insn, type)
*** 2103,2108 ****
--- 2241,2247 ----
  
  	      test = new_decision_test (DT_accept_insn, &place);
  	      test->u.insn.code_number = next_insn_code;
+ 	      test->u.insn.lineno = pattern_lineno;
  	      test->u.insn.num_clobbers_to_add = XVECLEN (x, 0) - i;
  
  	      merge_trees (&head, &clobber_head);
*************** main (argc, argv)
*** 2171,2176 ****
--- 2310,2316 ----
        perror (argv[1]);
        return FATAL_EXIT_CODE;
      }
+   read_rtx_filename = argv[1];
  
    next_insn_code = 0;
    next_index = 0;
*************** main (argc, argv)
*** 2185,2190 ****
--- 2325,2331 ----
        if (c == EOF)
  	break;
        ungetc (c, infile);
+       pattern_lineno = read_rtx_lineno;
  
        desc = read_rtx (infile);
        if (GET_CODE (desc) == DEFINE_INSN)
*************** main (argc, argv)
*** 2208,2213 ****
--- 2349,2357 ----
  	next_insn_code++;
        next_index++;
      }
+ 
+   if (error_count)
+     return FATAL_EXIT_CODE;
  
    puts ("\n\n");
  
Index: print-rtl.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/print-rtl.c,v
retrieving revision 1.36
diff -c -p -d -r1.36 print-rtl.c
*** print-rtl.c	1999/09/15 23:05:04	1.36
--- print-rtl.c	1999/10/14 03:34:33
*************** print_rtx (in_rtx)
*** 200,205 ****
--- 200,206 ----
  	break;
  
        case 'e':
+       do_e:
  	indent += 2;
  	if (!sawclose)
  	  fprintf (outfile, " ");
*************** print_rtx (in_rtx)
*** 298,303 ****
--- 299,307 ----
        case 'u':
  	if (XEXP (in_rtx, i) != NULL)
  	  {
+ 	    if (GET_CODE (XEXP (in_rtx, i)) != CODE_LABEL)
+ 	      goto do_e;
+ 
  	    if (flag_dump_unnumbered)
  	      fputc ('#', outfile);
  	    else
Index: rtl.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/rtl.c,v
retrieving revision 1.48
diff -c -p -d -r1.48 rtl.c
*** rtl.c	1999/10/11 18:42:36	1.48
--- rtl.c	1999/10/14 03:34:33
*************** const char * const reg_note_name[] = { "
*** 259,265 ****
  			  "REG_FRAME_RELATED_EXPR", "REG_EH_REGION",
  			  "REG_EH_RETHROW", "REG_SAVE_NOTE" };
  
! static void dump_and_abort	PROTO((int, int, FILE *)) ATTRIBUTE_NORETURN;
  static void read_name		PROTO((char *, FILE *));
  static const char *trim_filename PROTO((const char *));
  
--- 259,267 ----
  			  "REG_FRAME_RELATED_EXPR", "REG_EH_REGION",
  			  "REG_EH_RETHROW", "REG_SAVE_NOTE" };
  
! static void fatal_with_file_and_line PVPROTO((FILE *, const char *, ...))
!   ATTRIBUTE_NORETURN;
! static void fatal_expected_char PROTO((FILE *, int, int)) ATTRIBUTE_NORETURN;
  static void read_name		PROTO((char *, FILE *));
  static const char *trim_filename PROTO((const char *));
  
*************** shallow_copy_rtx (orig)
*** 582,613 ****
  
  /* Subroutines of read_rtx.  */
  
! /* Dump code after printing a message.  Used when read_rtx finds
!    invalid data.  */
  
  static void
! dump_and_abort (expected_c, actual_c, infile)
!      int expected_c, actual_c;
!      FILE *infile;
  {
!   int c, i;
  
!   if (expected_c >= 0)
!     fprintf (stderr,
! 	     "Expected character %c.  Found character %c.",
! 	     expected_c, actual_c);
!   fprintf (stderr, "  At file position: %ld\n", ftell (infile));
!   fprintf (stderr, "Following characters are:\n\t");
!   for (i = 0; i < 200; i++)
      {
        c = getc (infile);
!       if (EOF == c) break;
!       putc (c, stderr);
      }
!   fprintf (stderr, "Aborting.\n");
!   abort ();
  }
  
  /* Read chars from INFILE until a non-whitespace char
     and return that.  Comments, both Lisp style and C style,
     are treated as whitespace.
--- 584,649 ----
  
  /* Subroutines of read_rtx.  */
  
! /* The current line number for the file.  */
! int read_rtx_lineno = 1;
  
+ /* The filename for aborting with file and line.  */
+ const char *read_rtx_filename = "<unknown>";
+ 
  static void
! fatal_with_file_and_line VPROTO((FILE *infile, const char *msg, ...))
  {
! #ifndef ANSI_PROTOTYPES
!   FILE *infile;
!   const char *msg;
! #endif
!   va_list ap;
!   char context[64];
!   size_t i;
!   int c;
  
!   VA_START (ap, msg);
! 
! #ifndef ANSI_PROTOTYPES
!   infile = va_arg (ap, FILE *);
!   msg = va_arg (ap, const char *);
! #endif
! 
!   fprintf (stderr, "%s:%d: ", read_rtx_filename, read_rtx_lineno);
!   vfprintf (stderr, msg, ap);
!   putc ('\n', stderr);
! 
!   /* Gather some following context.  */
!   for (i = 0; i < sizeof(context)-1; ++i)
      {
        c = getc (infile);
!       if (c == EOF)
! 	break;
!       if (c == '\r' || c == '\n')
! 	break;
!       context[i] = c;
      }
!   context[i] = '\0';
! 
!   fprintf (stderr, "%s:%d: following context is `%s'\n",
! 	   read_rtx_filename, read_rtx_lineno, context);
! 
!   va_end (ap);
!   exit (1);
  }
  
+ /* Dump code after printing a message.  Used when read_rtx finds
+    invalid data.  */
+ 
+ static void
+ fatal_expected_char (infile, expected_c, actual_c)
+      FILE *infile;
+      int expected_c, actual_c;
+ {
+   fatal_with_file_and_line (infile, "expected character `%c', found `%c'",
+ 			    expected_c, actual_c);
+ }
+ 
  /* Read chars from INFILE until a non-whitespace char
     and return that.  Comments, both Lisp style and C style,
     are treated as whitespace.
*************** read_skip_spaces (infile)
*** 618,650 ****
       FILE *infile;
  {
    register int c;
!   while ((c = getc (infile)))
      {
!       if (c == ' ' || c == '\n' || c == '\t' || c == '\f')
! 	;
!       else if (c == ';')
! 	{
! 	  while ((c = getc (infile)) && c != '\n' && c != EOF)
! 	    ;
! 	}
!       else if (c == '/')
  	{
! 	  register int prevc;
! 	  c = getc (infile);
! 	  if (c != '*')
! 	    dump_and_abort ('*', c, infile);
  	  
! 	  prevc = 0;
! 	  while ((c = getc (infile)) && c != EOF)
! 	    {
! 	      if (prevc == '*' && c == '/')
! 		break;
! 	      prevc = c;
! 	    }
  	}
-       else break;
      }
-   return c;
  }
  
  /* Read an rtx code name into the buffer STR[].
--- 654,701 ----
       FILE *infile;
  {
    register int c;
!   while (1)
      {
!       c = getc (infile);
!       switch (c)
  	{
! 	case '\n':
! 	  read_rtx_lineno++;
! 	  break;
! 
! 	case ' ': case '\t': case '\f': case '\r':
! 	  break;
! 
! 	case ';':
! 	  do 
! 	    c = getc (infile);
! 	  while (c != '\n' && c != EOF);
! 	  read_rtx_lineno++;
! 	  break;
! 
! 	case '/':
! 	  {
! 	    register int prevc;
! 	    c = getc (infile);
! 	    if (c != '*')
! 	      fatal_expected_char (infile, '*', c);
  	  
! 	    prevc = 0;
! 	    while ((c = getc (infile)) && c != EOF)
! 	      {
! 		if (c == '\n')
! 		   read_rtx_lineno++;
! 	        else if (prevc == '*' && c == '/')
! 		  break;
! 	        prevc = c;
! 	      }
! 	  }
! 	  break;
! 
! 	default:
! 	  return c;
  	}
      }
  }
  
  /* Read an rtx code name into the buffer STR[].
*************** read_name (str, infile)
*** 675,684 ****
        c = getc (infile);
      }
    if (p == str)
!     {
!       fprintf (stderr, "missing name or number");
!       dump_and_abort (-1, -1, infile);
!     }
  
    *p = 0;
  }
--- 726,734 ----
        c = getc (infile);
      }
    if (p == str)
!     fatal_with_file_and_line (infile, "missing name or number");
!   if (c == '\n')
!     read_rtx_lineno++;
  
    *p = 0;
  }
*************** read_rtx (infile)
*** 745,756 ****
    struct rtx_list
      {
        struct rtx_list *next;
!       rtx value;		/* Value of this node...		*/
      };
  
    c = read_skip_spaces (infile); /* Should be open paren.  */
    if (c != '(')
!     dump_and_abort ('(', c, infile);
  
    read_name (tmp_char, infile);
  
--- 795,806 ----
    struct rtx_list
      {
        struct rtx_list *next;
!       rtx value;		/* Value of this node.  */
      };
  
    c = read_skip_spaces (infile); /* Should be open paren.  */
    if (c != '(')
!     fatal_expected_char (infile, '(', c);
  
    read_name (tmp_char, infile);
  
*************** read_rtx (infile)
*** 831,837 ****
  
  	  c = read_skip_spaces (infile);
  	  if (c != '[')
! 	    dump_and_abort ('[', c, infile);
  
  	  /* add expressions to a list, while keeping a count */
  	  next_rtx = NULL;
--- 881,887 ----
  
  	  c = read_skip_spaces (infile);
  	  if (c != '[')
! 	    fatal_expected_char (infile, '[', c);
  
  	  /* add expressions to a list, while keeping a count */
  	  next_rtx = NULL;
*************** read_rtx (infile)
*** 887,897 ****
  	      c = read_skip_spaces (infile);
  	    }
  	  if (c != '"')
! 	    dump_and_abort ('"', c, infile);
  
  	  while (1)
  	    {
  	      c = getc (infile); /* Read the string  */
  	      if (c == '\\')
  		{
  		  c = getc (infile);	/* Read the string  */
--- 937,949 ----
  	      c = read_skip_spaces (infile);
  	    }
  	  if (c != '"')
! 	    fatal_expected_char (infile, '"', c);
  
  	  while (1)
  	    {
  	      c = getc (infile); /* Read the string  */
+ 	      if (c == '\n')
+ 		read_rtx_lineno++;
  	      if (c == '\\')
  		{
  		  c = getc (infile);	/* Read the string  */
*************** read_rtx (infile)
*** 916,922 ****
  	    {
  	      c = read_skip_spaces (infile);
  	      if (c != ')')
! 		dump_and_abort (')', c, infile);
  	    }
  	  XSTR (return_rtx, i) = stringbuf;
  	}
--- 968,974 ----
  	    {
  	      c = read_skip_spaces (infile);
  	      if (c != ')')
! 		fatal_expected_char (infile, ')', c);
  	    }
  	  XSTR (return_rtx, i) = stringbuf;
  	}
*************** read_rtx (infile)
*** 959,965 ****
  
    c = read_skip_spaces (infile);
    if (c != ')')
!     dump_and_abort (')', c, infile);
  
    return return_rtx;
  }
--- 1011,1017 ----
  
    c = read_skip_spaces (infile);
    if (c != ')')
!     fatal_expected_char (infile, ')', c);
  
    return return_rtx;
  }
Index: rtl.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/rtl.h,v
retrieving revision 1.144
diff -c -p -d -r1.144 rtl.h
*** rtl.h	1999/10/13 17:09:18	1.144
--- rtl.h	1999/10/14 03:34:33
*************** extern rtx gen_rtx			PVPROTO((enum rtx_c
*** 963,972 ****
  						 enum machine_mode, ...));
  extern rtvec gen_rtvec			PVPROTO((int, ...));
  
- #ifdef BUFSIZ
- extern rtx read_rtx			PROTO((FILE *));
- #endif
- 
  extern char *oballoc			PROTO((int));
  extern char *permalloc			PROTO((int));
  extern rtx rtx_alloc			PROTO((RTX_CODE));
--- 963,968 ----
*************** extern void gcc_obstack_init		PROTO ((st
*** 1379,1388 ****
  extern void pop_obstacks		PROTO ((void));
  extern void push_obstacks		PROTO ((struct obstack *,
  						struct obstack *));
- #ifdef BUFSIZ
- extern int read_skip_spaces		PROTO ((FILE *));
- #endif
- 
  /* In cse.c */
  struct cse_basic_block_data;
  extern int rtx_cost			PROTO ((rtx, enum rtx_code));
--- 1375,1380 ----
*************** extern void rrotate_double	PROTO ((HOST_
*** 1642,1648 ****
  					HOST_WIDE_INT *));
  
  /* In calls.c */
- /* Emit library call.  */                                           
  extern void emit_library_call		PVPROTO ((rtx, int, enum machine_mode,
  						  int, ...));
  extern rtx emit_library_call_value	PVPROTO((rtx, rtx, int,
--- 1634,1639 ----
*************** extern void init_varasm_once		PROTO ((vo
*** 1661,1666 ****
--- 1652,1665 ----
  /* In rtl.c */
  extern void init_rtl			PROTO ((void));
  extern void rtx_free			PROTO ((rtx));
+ 
+ #ifdef BUFSIZ
+ extern int read_skip_spaces		PROTO ((FILE *));
+ extern rtx read_rtx			PROTO ((FILE *));
+ #endif
+ 
+ extern const char *read_rtx_filename;
+ extern int read_rtx_lineno;
  
  /* Redefine abort to report an internal error w/o coredump, and
     reporting the location of the error in the source file.  This logic


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]