my_error.c 4.51 KB
Newer Older
unknown's avatar
unknown committed
1 2 3 4 5 6 7 8
/* Copyright (C) 2000 MySQL AB

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
unknown's avatar
unknown committed
9
   but WITHOUT ANY WARRANTY; without even the implied warranty of
unknown's avatar
unknown committed
10 11 12 13 14 15
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
unknown's avatar
unknown committed
16 17 18 19 20 21 22 23 24

#include "mysys_priv.h"
#include "mysys_err.h"
#include <m_string.h>
#include <stdarg.h>
#include <m_ctype.h>

/* Define some external variables for error handling */

25
const char ** NEAR my_errmsg[MAXMAPS]={0,0,0,0};
unknown's avatar
unknown committed
26 27
char NEAR errbuff[NRERRBUFFS][ERRMSGSIZE];

unknown's avatar
unknown committed
28 29 30 31 32 33 34 35
/*
   Error message to user

   SYNOPSIS
     my_error()
       nr	Errno
       MyFlags	Flags
       ...	variable list
36 37 38 39
   NOTE
    The following subset of printf format is supported:
    "%[0-9.-]*l?[sdu]", where all length flags are parsed but ignored.

40 41
    Additionally "%.*s" is supported and "%.*[ud]" is correctly parsed but
    the length value is ignored.
unknown's avatar
unknown committed
42
*/
unknown's avatar
unknown committed
43 44 45 46 47 48 49 50 51

int my_error(int nr,myf MyFlags, ...)
{
  va_list	ap;
  uint		olen, plen;
  reg1 const char *tpos;
  reg2 char	*endpos;
  char		* par;
  char		ebuff[ERRMSGSIZE+20];
52
  int           prec_chars; /* output precision */
53
  my_bool       prec_supplied;
unknown's avatar
unknown committed
54
  DBUG_ENTER("my_error");
55
  LINT_INIT(prec_chars); /* protected by prec_supplied */
unknown's avatar
unknown committed
56 57 58 59

  va_start(ap,MyFlags);
  DBUG_PRINT("my", ("nr: %d  MyFlags: %d  errno: %d", nr, MyFlags, errno));

60
  if (nr / ERRMOD == GLOB && my_errmsg[GLOB] == 0)
unknown's avatar
unknown committed
61 62
    init_glob_errs();

63
  olen=(uint) strlen(tpos=my_errmsg[nr / ERRMOD][nr % ERRMOD]);
unknown's avatar
unknown committed
64 65 66 67 68 69 70 71 72 73 74 75 76 77 78
  endpos=ebuff;

  while (*tpos)
  {
    if (tpos[0] != '%')
    {
      *endpos++= *tpos++;	/* Copy ordinary char */
      continue;
    }
    if (*++tpos == '%')		/* test if %% */
    {
      olen--;
    }
    else
    {
79 80 81 82 83
      /*
        Skip size/precision flags to be compatible with printf.
        The only size/precision flag supported is "%.*s".
        If "%.*u" or "%.*d" are encountered, the precision number is read
        from the variable argument list but its value is ignored.
84 85 86 87 88 89 90 91 92 93 94 95 96 97
      */
      prec_supplied= 0;
      if (*tpos== '.')
      {
        tpos++;
        olen--;
        if (*tpos == '*')
        {
          tpos++;
          olen--;
          prec_chars= va_arg(ap, int); /* get length parameter */
          prec_supplied= 1;
        }
      }
98

99 100
      if (!prec_supplied)
      {
101
        while (my_isdigit(&my_charset_latin1, *tpos) || *tpos == '.' ||
102
               *tpos == '-')
103 104 105
	  tpos++;

        if (*tpos == 'l')				/* Skip 'l' argument */
106 107 108
	  tpos++;
      }

unknown's avatar
unknown committed
109 110
      if (*tpos == 's')				/* String parameter */
      {
111 112
	par= va_arg(ap, char *);
	plen= (uint) strlen(par);
113 114
        if (prec_supplied && prec_chars > 0)
          plen= min((uint)prec_chars, plen);
unknown's avatar
unknown committed
115 116
	if (olen + plen < ERRMSGSIZE+2)		/* Replace if possible */
	{
117 118
          strmake(endpos, par, plen);
          endpos+= plen;
119
          tpos++;
120
          olen+= plen-2;
121
          continue;
unknown's avatar
unknown committed
122 123 124 125 126
	}
      }
      else if (*tpos == 'd' || *tpos == 'u')	/* Integer parameter */
      {
	register int iarg;
127
	iarg= va_arg(ap, int);
unknown's avatar
unknown committed
128
	if (*tpos == 'd')
129
	  plen= (uint) (int10_to_str((long) iarg, endpos, -10) - endpos);
unknown's avatar
unknown committed
130
	else
131
	  plen= (uint) (int10_to_str((long) (uint) iarg, endpos, 10) - endpos);
unknown's avatar
unknown committed
132 133
	if (olen + plen < ERRMSGSIZE+2) /* Replace parameter if possible */
	{
134
	  endpos+= plen;
unknown's avatar
unknown committed
135
	  tpos++;
136
	  olen+= plen-2;
unknown's avatar
unknown committed
137 138 139 140
	  continue;
	}
      }
    }
141
    *endpos++= '%';		/* % used as % or unknown code */
unknown's avatar
unknown committed
142
  }
143
  *endpos= '\0';			/* End of errmessage */
unknown's avatar
unknown committed
144 145 146 147
  va_end(ap);
  DBUG_RETURN((*error_handler_hook)(nr, ebuff, MyFlags));
}

unknown's avatar
unknown committed
148 149 150 151 152 153 154 155 156 157
/*
  Error as printf

  SYNOPSIS
    my_printf_error()
      error	Errno
      format	Format string
      MyFlags	Flags
      ...	variable list
*/
unknown's avatar
unknown committed
158

159
int my_printf_error(uint error, const char *format, myf MyFlags, ...)
unknown's avatar
unknown committed
160 161 162 163 164 165 166 167 168 169
{
  va_list args;
  char ebuff[ERRMSGSIZE+20];

  va_start(args,MyFlags);
  (void) vsprintf (ebuff,format,args);
  va_end(args);
  return (*error_handler_hook)(error, ebuff, MyFlags);
}

unknown's avatar
unknown committed
170 171 172 173 174 175 176 177 178
/*
  Give message using error_handler_hook

  SYNOPSIS
    my_message()
      error	Errno
      str	Error message
      MyFlags	Flags
*/
unknown's avatar
unknown committed
179 180 181 182 183

int my_message(uint error, const char *str, register myf MyFlags)
{
  return (*error_handler_hook)(error, str, MyFlags);
}