home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 11 Util / 11-Util.zip / MAWK113.ZIP / mawk113 / error.c < prev    next >
C/C++ Source or Header  |  1993-01-22  |  8KB  |  391 lines

  1.  
  2. /********************************************
  3. error.c
  4. copyright 1991, 1992 Michael D. Brennan
  5.  
  6. This is a source file for mawk, an implementation of
  7. the AWK programming language.
  8.  
  9. Mawk is distributed without warranty under the terms of
  10. the GNU General Public License, version 2, 1991.
  11. ********************************************/
  12.  
  13.  
  14. /* $Log: error.c,v $
  15.  * Revision 5.3  1993/01/22  14:55:46  mike
  16.  * trivial change for unexpected_char()
  17.  *
  18.  * Revision 5.2  1992/10/02  23:26:04  mike
  19.  * using vargs.h
  20.  *
  21.  * Revision 5.1  1991/12/05  07:55:48  brennan
  22.  * 1.1 pre-release
  23.  *
  24. */
  25.  
  26.  
  27. #include  "mawk.h"
  28. #include  "scan.h"
  29. #include  "bi_vars.h"
  30. #include  "vargs.h"
  31.  
  32.  
  33. #ifndef  EOF
  34. #define  EOF  (-1)
  35. #endif
  36.  
  37. static void  PROTO( rt_where, (void) ) ;
  38. static void  PROTO( unexpected_char, (void) ) ;
  39. static void  PROTO( missing, (int, char *, int) ) ;
  40. static char *PROTO( type_to_str, (int) ) ;
  41.  
  42. #if HAVE_STRERROR == 0
  43. #define strerror(n) ((n)>0&&(n)<sys_nerr?sys_errlist[n]:(char*)0)
  44. extern int sys_nerr ;
  45. extern char *sys_errlist[];
  46. #endif
  47.  
  48.  
  49. #ifdef  USE_SIMPLE_VFPRINTF
  50. #define  vfprintf  simple_vfprintf
  51. #endif
  52.  
  53.  
  54. extern int NR_flag ; /* on if tracking NR */
  55.  
  56.  
  57. static struct token_str  {
  58. short token ;
  59. char *str ; }  token_str[] = {
  60. EOF , "end of file" ,
  61. NL , "end of line",
  62. SEMI_COLON , ";" ,
  63. LBRACE , "{" ,
  64. RBRACE , "}" ,
  65. SC_FAKE_SEMI_COLON, "}",
  66. LPAREN , "(" ,
  67. RPAREN , ")" ,
  68. LBOX , "[",
  69. RBOX , "]",
  70. QMARK , "?",
  71. COLON , ":",
  72. OR, "||",
  73. AND, "&&",
  74. ASSIGN , "=" ,
  75. ADD_ASG, "+=",
  76. SUB_ASG, "-=",
  77. MUL_ASG, "*=",
  78. DIV_ASG, "/=",
  79. MOD_ASG, "%=",
  80. POW_ASG, "^=",
  81. EQ  , "==" ,
  82. NEQ , "!=",
  83. LT, "<" ,
  84. LTE, "<=" ,
  85. GT, ">",
  86. GTE, ">=" ,
  87. MATCH, string_buff,
  88. PLUS , "+" ,
  89. MINUS, "-" ,
  90. MUL , "*" ,
  91. DIV, "/"  , 
  92. MOD, "%" ,
  93. POW, "^" ,
  94. NOT, "!" ,
  95. COMMA, "," ,
  96. INC_or_DEC , string_buff ,
  97. DOUBLE  , string_buff ,
  98. STRING_  , string_buff ,
  99. ID  , string_buff ,
  100. FUNCT_ID  , string_buff ,
  101. BUILTIN  , string_buff ,
  102. IO_OUT , string_buff ,
  103. IO_IN, "<" ,
  104. PIPE, "|" ,
  105. DOLLAR, "$" ,
  106. FIELD, "$" ,
  107. 0, (char *) 0 } ;
  108.  
  109. /* if paren_cnt >0 and we see one of these, we are missing a ')' */
  110. static int missing_rparen[] =
  111. { EOF, NL, SEMI_COLON, SC_FAKE_SEMI_COLON, RBRACE, 0 } ;
  112.  
  113. /* ditto for '}' */
  114. static int missing_rbrace[] =
  115. { EOF, BEGIN, END , 0 } ;
  116.  
  117. static void missing( c, n , ln)
  118.   int c ;
  119.   char *n ;
  120.   int ln ;
  121. { char *s0, *s1 ;
  122.  
  123.   if ( pfile_name )
  124.   { s0 = pfile_name ; s1 = ": " ; }
  125.   else s0 = s1 = "" ;
  126.  
  127.   errmsg(0, "%s%sline %u: missing %c near %s" ,s0, s1, ln, c, n) ; 
  128. }  
  129.  
  130. void  yyerror(s)
  131.   char *s ; /* we won't use s as input 
  132.   (yacc and bison force this).
  133.   We will use s for storage to keep lint or the compiler
  134.   off our back */
  135. { struct token_str *p ;
  136.   int *ip ;
  137.  
  138.   s = (char *) 0 ;
  139.  
  140.   for ( p = token_str ; p->token ; p++ )
  141.       if ( current_token == p->token )
  142.       { s = p->str ; break ; }
  143.  
  144.   if ( ! s )  /* search the keywords */
  145.          s = find_kw_str(current_token) ;
  146.  
  147.   if ( s )
  148.   {
  149.     if ( paren_cnt )
  150.         for( ip = missing_rparen ; *ip ; ip++)
  151.           if ( *ip == current_token )
  152.           { missing(')', s, token_lineno) ;
  153.             paren_cnt = 0 ;
  154.             goto done ;
  155.           }
  156.  
  157.     if ( brace_cnt )
  158.         for( ip = missing_rbrace ; *ip ; ip++)
  159.           if ( *ip == current_token )
  160.           { missing('}', s, token_lineno) ;
  161.             brace_cnt = 0 ;
  162.             goto done ;
  163.           }
  164.  
  165.     compile_error("syntax error at or near %s", s) ;
  166.  
  167.   }
  168.   else  /* special cases */
  169.   switch ( current_token )
  170.   {
  171.     case UNEXPECTED :
  172.             unexpected_char() ; 
  173.             goto done ;
  174.  
  175.     case BAD_DECIMAL :
  176.             compile_error(
  177.               "syntax error in decimal constant %s",
  178.               string_buff ) ;
  179.             break ;
  180.  
  181.     case RE :
  182.             compile_error(
  183.             "syntax error at or near /%s/", 
  184.             string_buff ) ;
  185.             break ;
  186.  
  187.     default :
  188.             compile_error("syntax error") ;
  189.             break ;
  190.   }
  191.   return ;
  192.  
  193. done :
  194.   if ( ++compile_error_count == MAX_COMPILE_ERRORS ) mawk_exit(1) ;
  195. }
  196.  
  197.  
  198. /* generic error message with a hook into the system error 
  199.    messages if errnum > 0 */
  200.  
  201. void  errmsg VA_ALIST2(int , errnum, char *, format)
  202.   va_list args ;
  203.  
  204.   fprintf(stderr, "%s: " , progname) ;
  205.  
  206.   VA_START2(args, int, errnum, char *, format) ;
  207.   (void) vfprintf(stderr, format, args) ;
  208.   va_end(args) ;
  209.  
  210.   if ( errnum > 0 ) fprintf(stderr, " (%s)" , strerror(errnum) ) ;
  211.  
  212.   fprintf( stderr, "\n") ;
  213. }
  214.  
  215. void  compile_error  VA_ALIST(char *, format)
  216.   va_list args ;
  217.   char *s0, *s1 ;
  218.  
  219.   /* with multiple program files put program name in
  220.      error message */
  221.   if ( pfile_name )
  222.   { s0 = pfile_name ; s1 = ": " ; }
  223.   else
  224.   { s0 = s1 = "" ; }
  225.  
  226.   fprintf(stderr, "%s: %s%sline %u: " , progname, s0, s1,token_lineno) ;
  227.   VA_START(args, char *, format) ;
  228.   vfprintf(stderr, format, args) ;
  229.   va_end(args) ;
  230.   fprintf(stderr, "\n") ;
  231.   if ( ++compile_error_count == MAX_COMPILE_ERRORS ) mawk_exit(1) ;
  232. }
  233.  
  234. void  rt_error VA_ALIST( char *, format)
  235.   va_list args ;
  236.  
  237.   fprintf(stderr, "%s: run time error: " , progname ) ;
  238.   VA_START(args, char *, format) ;
  239.   vfprintf(stderr, format, args) ;
  240.   va_end(args) ;
  241.   putc('\n',stderr) ;
  242.   rt_where() ;
  243.   mawk_exit(1) ;
  244. }
  245.  
  246.  
  247. void bozo(s)
  248.   char *s ;
  249.   errmsg(0, "bozo: %s" , s) ; 
  250.   mawk_exit(1) ;
  251. }
  252.  
  253. void overflow(s, size)
  254.   char *s ; unsigned size ;
  255.   errmsg(0 , "program limit exceeded: %s size=%u", s, size) ;
  256.   mawk_exit(1) ; 
  257. }
  258.  
  259.  
  260. /* print as much as we know about where a rt error occured */
  261.  
  262. static void rt_where()
  263. {
  264.   if ( FILENAME->type != C_STRING ) cast1_to_s(FILENAME) ;
  265.   if ( TEST2(NR) != TWO_DOUBLES ) cast2_to_d(NR) ;
  266.  
  267.   fprintf(stderr, "\tFILENAME=\"%s\"", string(FILENAME)->str) ;
  268.   if ( NR_flag ) 
  269.       fprintf(stderr, " FNR=%g NR=%g" , FNR->dval, NR->dval) ;
  270.  
  271.   fprintf(stderr, "\n") ;
  272. }
  273.  
  274. /* run time */
  275. void rt_overflow(s, size)
  276.   char *s ; unsigned size ;
  277.   errmsg(0 , "program limit exceeded: %s size=%u", s, size) ;
  278.   rt_where() ;
  279.   mawk_exit(1) ;
  280. }
  281.  
  282. static void unexpected_char()
  283. { int c = yylval.ival ;
  284.  
  285.   fprintf(stderr, "%s: %u: ", progname, token_lineno) ;
  286.   if ( c > ' ' && c < 127 )
  287.       fprintf(stderr, "unexpected character '%c'\n" , c) ;
  288.   else
  289.       fprintf(stderr, "unexpected character 0x%02x\n" , c) ;
  290. }
  291.  
  292. static char *type_to_str( type )
  293.   int type ;
  294. { char *retval ;
  295.  
  296.   switch( type )
  297.   {
  298.     case  ST_VAR :  retval = "variable" ; break ;
  299.     case  ST_ARRAY :  retval = "array" ; break ;
  300.     case  ST_FUNCT :  retval = "function" ; break ;
  301.     case  ST_LOCAL_VAR : retval = "local variable" ; break ;
  302.     case  ST_LOCAL_ARRAY : retval = "local array" ; break ;
  303.     default : bozo("type_to_str") ;
  304.   }
  305.   return retval ;
  306. }
  307.  
  308. /* emit an error message about a type clash */
  309. void type_error(p)
  310.   SYMTAB *p ;
  311. { compile_error("illegal reference to %s %s", 
  312.     type_to_str(p->type) , p->name) ;
  313. }
  314.  
  315.  
  316.  
  317.  
  318. #ifdef  USE_SIMPLE_VFPRINTF
  319.  
  320. /* a minimal vfprintf  */
  321. int simple_vfprintf( fp, format, argp)
  322.   FILE *fp ;
  323.   char *format ; 
  324.   va_list  argp ;
  325.   char *q , *p, *t ;
  326.   int l_flag ;
  327.   char xbuff[64] ;
  328.  
  329.   q = format ;
  330.   xbuff[0] = '%' ;
  331.  
  332.   while ( *q != 0 )
  333.   { 
  334.     if ( *q != '%' )
  335.     {
  336.       putc(*q, fp) ; q++ ; continue ;
  337.     }
  338.  
  339.     /* mark the start with p */
  340.     p = ++q ;  t = xbuff + 1 ;
  341.  
  342.     if ( *q == '-' )  *t++ = *q++ ;
  343.     while ( scan_code[*(unsigned char*)q] == SC_DIGIT ) *t++ = *q++ ;
  344.     if ( *q == '.' )
  345.     { *t++ = *q++ ;
  346.       while ( scan_code[*(unsigned char*)q] == SC_DIGIT ) *t++ = *q++ ;
  347.     }
  348.  
  349.     if ( *q == 'l' )  { l_flag = 1 ; *t++ = *q++ ; }
  350.     else l_flag = 0 ;
  351.  
  352.     
  353.     *t = *q++ ; t[1] = 0 ;
  354.  
  355.     switch( *t )
  356.     {
  357.       case 'c' :  
  358.       case 'd' :
  359.       case 'o' :
  360.       case 'x' :
  361.       case 'u' :
  362.            if ( l_flag )  fprintf(fp, xbuff, va_arg(argp,long) ) ;
  363.            else  fprintf(fp, xbuff, va_arg(argp, int)) ;
  364.            break ;
  365.  
  366.       case  's' :
  367.            fprintf(fp, xbuff, va_arg(argp, char*)) ;
  368.            break ;
  369.  
  370.       case  'g' :
  371.       case  'f' :
  372.            fprintf(fp, xbuff, va_arg(argp, double)) ;
  373.            break ;
  374.  
  375.       default:
  376.            putc('%', fp) ; 
  377.            q = p ;
  378.            break ;
  379.     }
  380.   }
  381.   return 0 ; /* shut up */
  382. }
  383.  
  384. #endif  /* USE_SIMPLE_VFPRINTF */
  385.  
  386.  
  387.