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