/* Output like sprintf to a buffer of specified size.
Also takes args differently: pass one pointer to an array of strings
in addition to the format string which is separate.
- Copyright (C) 1985, 2001, 2002, 2003, 2004, 2005,
- 2006, 2007, 2008 Free Software Foundation, Inc.
+ Copyright (C) 1985, 2001-2011 Free Software Foundation, Inc.
This file is part of GNU Emacs.
-GNU Emacs is free software; you can redistribute it and/or modify
+GNU Emacs 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 3, or (at your option)
-any later version.
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
GNU Emacs is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
-Boston, MA 02110-1301, USA. */
+along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include <config.h>
#include <stdio.h>
#include <ctype.h>
+#include <setjmp.h>
#ifdef STDC_HEADERS
#include <float.h>
#endif
-#ifdef HAVE_UNISTD_H
#include <unistd.h>
-#endif
-
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
#include "lisp.h"
-#ifndef DBL_MAX_10_EXP
-#define DBL_MAX_10_EXP 308 /* IEEE double */
-#endif
-
/* Since we use the macro CHAR_HEAD_P, we have to include this, but
don't have to include others because CHAR_HEAD_P does not contains
another macro. */
#include "character.h"
-static int doprnt1 ();
+#ifndef DBL_MAX_10_EXP
+#define DBL_MAX_10_EXP 308 /* IEEE double */
+#endif
/* Generate output from a format-spec FORMAT,
terminated at position FORMAT_END.
String arguments are passed as C strings.
Integers are passed as C integers. */
-int
-doprnt (buffer, bufsize, format, format_end, nargs, args)
- char *buffer;
- register int bufsize;
- char *format;
- char *format_end;
- int nargs;
- char **args;
-{
- return doprnt1 (0, buffer, bufsize, format, format_end, nargs, args);
-}
-
-/* Like doprnt except that strings in ARGS are passed
- as Lisp_Object. */
-
-int
-doprnt_lisp (buffer, bufsize, format, format_end, nargs, args)
- char *buffer;
- register int bufsize;
- char *format;
- char *format_end;
- int nargs;
- char **args;
+EMACS_INT
+doprnt (char *buffer, register int bufsize, const char *format,
+ const char *format_end, va_list ap)
{
- return doprnt1 (1, buffer, bufsize, format, format_end, nargs, args);
-}
-
-static int
-doprnt1 (lispstrings, buffer, bufsize, format, format_end, nargs, args)
- int lispstrings;
- char *buffer;
- register int bufsize;
- char *format;
- char *format_end;
- int nargs;
- char **args;
-{
- int cnt = 0; /* Number of arg to gobble next */
- register char *fmt = format; /* Pointer into format string */
+ const char *fmt = format; /* Pointer into format string */
register char *bufptr = buffer; /* Pointer into output buffer.. */
/* Use this for sprintf unless we need something really big. */
char fixed_buffer[20]; /* Default buffer for small formatting. */
char *fmtcpy;
int minlen;
- unsigned char charbuf[5]; /* Used for %c. */
+ unsigned char charbuf[MAX_MULTIBYTE_LENGTH + 1]; /* Used for %c. */
if (format_end == 0)
format_end = format + strlen (format);
if (*fmt == '%') /* Check for a '%' character */
{
unsigned size_bound = 0;
- int width; /* Columns occupied by STRING. */
+ EMACS_INT width; /* Columns occupied by STRING. */
fmt++;
/* Copy this one %-spec into fmtcpy. */
unsigned n = *fmt - '0';
while ('0' <= fmt[1] && fmt[1] <= '9')
{
- if (n * 10 / 10 != n
- || (n = n * 10 + (fmt[1] - '0')) < n)
+ if (n * 10 + fmt[1] - '0' < n)
error ("Format width or precision too large");
+ n = n * 10 + fmt[1] - '0';
*string++ = *++fmt;
}
case 'd':
case 'o':
case 'x':
- if (cnt == nargs)
- error ("Not enough arguments for format string");
if (sizeof (int) == sizeof (EMACS_INT))
;
else if (sizeof (long) == sizeof (EMACS_INT))
string++;
else
abort ();
- sprintf (sprintf_buffer, fmtcpy, args[cnt++]);
+ sprintf (sprintf_buffer, fmtcpy, va_arg(ap, char *));
/* Now copy into final output, truncating as nec. */
string = (unsigned char *) sprintf_buffer;
goto doit;
case 'e':
case 'g':
{
- union { double d; char *half[2]; } u;
- if (cnt + 1 == nargs)
- error ("Not enough arguments for format string");
- u.half[0] = args[cnt++];
- u.half[1] = args[cnt++];
- sprintf (sprintf_buffer, fmtcpy, u.d);
+ double d = va_arg(ap, double);
+ sprintf (sprintf_buffer, fmtcpy, d);
/* Now copy into final output, truncating as nec. */
string = (unsigned char *) sprintf_buffer;
goto doit;
case 'S':
string[-1] = 's';
case 's':
- if (cnt == nargs)
- error ("Not enough arguments for format string");
if (fmtcpy[1] != 's')
minlen = atoi (&fmtcpy[1]);
- if (lispstrings)
- {
- string = ((struct Lisp_String *) args[cnt])->data;
- tem = STRING_BYTES ((struct Lisp_String *) args[cnt]);
- cnt++;
- }
- else
- {
- string = (unsigned char *) args[cnt++];
- tem = strlen (string);
- }
+ string = va_arg(ap, unsigned char *);
+ tem = strlen (string);
width = strwidth (string, tem);
goto doit1;
/* Truncate the string at character boundary. */
tem = bufsize;
while (!CHAR_HEAD_P (string[tem - 1])) tem--;
- bcopy (string, bufptr, tem);
+ memcpy (bufptr, string, tem);
/* We must calculate WIDTH again. */
width = strwidth (bufptr, tem);
}
else
- bcopy (string, bufptr, tem);
+ memcpy (bufptr, string, tem);
bufptr += tem;
bufsize -= tem;
if (minlen < 0)
continue;
case 'c':
- if (cnt == nargs)
- error ("Not enough arguments for format string");
- tem = CHAR_STRING ((int) (EMACS_INT) args[cnt], charbuf);
- string = charbuf;
- cnt++;
- string[tem] = 0;
- width = strwidth (string, tem);
- if (fmtcpy[1] != 'c')
- minlen = atoi (&fmtcpy[1]);
- goto doit1;
+ {
+ /* Sometimes for %c we pass a char, which would widen
+ to int. Sometimes we pass XFASTINT() or XINT()
+ values, which would be EMACS_INT. Let's hope that
+ both are passed the same way, otherwise we'll need
+ to rewrite callers. */
+ EMACS_INT chr = va_arg(ap, EMACS_INT);
+ tem = CHAR_STRING ((int) chr, charbuf);
+ string = charbuf;
+ string[tem] = 0;
+ width = strwidth (string, tem);
+ if (fmtcpy[1] != 'c')
+ minlen = atoi (&fmtcpy[1]);
+ goto doit1;
+ }
case '%':
fmt--; /* Drop thru and this % will be treated as normal */
};
/* If we had to malloc something, free it. */
- if (big_buffer)
- xfree (big_buffer);
+ xfree (big_buffer);
*bufptr = 0; /* Make sure our string end with a '\0' */
return bufptr - buffer;
}
-/* arch-tag: aa0ab528-7c5f-4c73-894c-aa2526a1efb3
- (do not change this comment) */