(root)/
gawk-5.2.2/
msg.c
       1  /*
       2   * msg.c - routines for error messages.
       3   */
       4  
       5  /*
       6   * Copyright (C) 1986, 1988, 1989, 1991-2001, 2003, 2010-2013, 2017-2019,
       7   * 2021, 2022, 2023,
       8   * the Free Software Foundation, Inc.
       9   *
      10   * This file is part of GAWK, the GNU implementation of the
      11   * AWK Programming Language.
      12   *
      13   * GAWK is free software; you can redistribute it and/or modify
      14   * it under the terms of the GNU General Public License as published by
      15   * the Free Software Foundation; either version 3, or (at your option)
      16   * any later version.
      17   *
      18   * GAWK is distributed in the hope that it will be useful,
      19   * but WITHOUT ANY WARRANTY; without even the implied warranty of
      20   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      21   * GNU General Public License for more details.
      22   *
      23   * You should have received a copy of the GNU General Public License
      24   * along with this program; if not, write to the Free Software
      25   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
      26   */
      27  
      28  #include "awk.h"
      29  
      30  extern FILE *output_fp;
      31  int sourceline = 0;
      32  char *source = NULL;
      33  static const char *srcfile = NULL;
      34  static int srcline;
      35  
      36  jmp_buf fatal_tag;
      37  int fatal_tag_valid = 0;
      38  
      39  /* err --- print an error message with source line and file and record */
      40  
      41  /* VARARGS2 */
      42  void
      43  err(bool isfatal, const char *s, const char *emsg, va_list argp)
      44  {
      45  	char *file;
      46  	const char *me;
      47  
      48  	static bool first = true;
      49  	static bool add_src_info = false;
      50  	static long lineno_val = 0;	// Easter Egg
      51  
      52  	if (first) {
      53  		first = false;
      54  		add_src_info = (getenv("GAWK_MSG_SRC") != NULL);
      55  		if (! do_traditional) {
      56  			NODE *n = lookup("LINENO");
      57  
      58  			if (n != NULL && n->type == Node_var)
      59  				lineno_val = get_number_d(n->var_value);
      60  		}
      61  	}
      62  
      63  	(void) fflush(output_fp);
      64  	me = myname;
      65  	(void) fprintf(stderr, "%s: ", me);
      66  
      67  	if (srcfile != NULL && add_src_info) {
      68  		fprintf(stderr, "%s:%d:", srcfile, srcline);
      69  		srcfile = NULL;
      70  	}
      71  
      72  	if (sourceline > 0) {
      73  		if (source != NULL)
      74  			(void) fprintf(stderr, "%s:", source);
      75  		else
      76  			(void) fprintf(stderr, _("cmd. line:"));
      77  
      78  		(void) fprintf(stderr, "%ld: ", sourceline + lineno_val);
      79  	}
      80  
      81  #ifdef HAVE_MPFR
      82  	if (FNR_node && FNR_node->var_value && is_mpg_number(FNR_node->var_value)) {
      83  		NODE *val;
      84  		val = mpg_update_var(FNR_node);
      85  		assert((val->flags & MPZN) != 0);
      86  		if (mpz_sgn(val->mpg_i) > 0) {
      87  			int len = FILENAME_node->var_value->stlen;
      88  			file = FILENAME_node->var_value->stptr;
      89  			(void) putc('(', stderr);
      90  			if (file)
      91  				(void) fprintf(stderr, "FILENAME=%.*s ", len, file);
      92  			(void) mpfr_fprintf(stderr, "FNR=%Zd) ", val->mpg_i);
      93  		}
      94  	} else
      95  #endif
      96  	if (FNR > 0) {
      97  		int len = FILENAME_node->var_value->stlen;
      98  		file = FILENAME_node->var_value->stptr;
      99  		(void) putc('(', stderr);
     100  		if (file)
     101  			(void) fprintf(stderr, "FILENAME=%.*s ", len, file);
     102  		(void) fprintf(stderr, "FNR=%ld) ", FNR);
     103  	}
     104  
     105  	(void) fprintf(stderr, "%s", s);
     106  	vfprintf(stderr, emsg, argp);
     107  	(void) fprintf(stderr, "\n");
     108  	(void) fflush(stderr);
     109  
     110  	if (isfatal)
     111  		gawk_exit(EXIT_FATAL);
     112  
     113  }
     114  
     115  /* msg --- take a varargs error message and print it */
     116  
     117  void
     118  msg(const char *mesg, ...)
     119  {
     120  	va_list args;
     121  	va_start(args, mesg);
     122  	err(false, "", mesg, args);
     123  	va_end(args);
     124  }
     125  
     126  /* r_warning --- print a warning message */
     127  
     128  void
     129  r_warning(const char *mesg, ...)
     130  {
     131  	va_list args;
     132  	va_start(args, mesg);
     133  	err(false, _("warning: "), mesg, args);
     134  	va_end(args);
     135  }
     136  
     137  void
     138  error(const char *mesg, ...)
     139  {
     140  	va_list args;
     141  	va_start(args, mesg);
     142  	err(false, _("error: "), mesg, args);
     143  	va_end(args);
     144  }
     145  
     146  /* set_loc --- set location where a fatal error happened */
     147  
     148  void
     149  set_loc(const char *file, int line)
     150  {
     151  	srcfile = file;
     152  	srcline = line;
     153  
     154  	/* This stupid line keeps some compilers happy: */
     155  	file = srcfile; line = srcline;
     156  }
     157  
     158  /* r_fatal --- print a fatal error message */
     159  
     160  void
     161  r_fatal(const char *mesg, ...)
     162  {
     163  	va_list args;
     164  	va_start(args, mesg);
     165  	err(true, _("fatal: "), mesg, args);
     166  	va_end(args);
     167  }
     168  
     169  /* gawk_exit --- longjmp out if necessary */
     170  
     171  void
     172  gawk_exit(int status)
     173  {
     174  	if (fatal_tag_valid) {
     175  		exit_val = status;
     176  		longjmp(fatal_tag, 1);
     177  	}
     178  
     179  	final_exit(status);
     180  }
     181  
     182  /* final_exit --- run extension exit handlers and exit */
     183  
     184  void
     185  final_exit(int status)
     186  {
     187  	/* run any extension exit handlers */
     188  	run_ext_exit_handlers(status);
     189  
     190  	/* we could close_io() here */
     191  	close_extensions();
     192  
     193  	exit(status);
     194  }