Convert consecutive FSF copyright years to ranges.
[bpt/emacs.git] / src / doprnt.c
index 6351657..979cce3 100644 (file)
@@ -1,15 +1,14 @@
 /* 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
@@ -17,39 +16,30 @@ 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 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.
@@ -61,45 +51,11 @@ static int doprnt1 ();
    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.  */
@@ -119,7 +75,7 @@ doprnt1 (lispstrings, buffer, bufsize, format, format_end, nargs, args)
   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);
@@ -137,7 +93,7 @@ doprnt1 (lispstrings, buffer, bufsize, format, format_end, nargs, args)
       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.  */
@@ -155,9 +111,9 @@ doprnt1 (lispstrings, buffer, bufsize, format, format_end, nargs, args)
                  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;
                    }
 
@@ -198,8 +154,6 @@ doprnt1 (lispstrings, buffer, bufsize, format, format_end, nargs, args)
            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))
@@ -210,7 +164,7 @@ doprnt1 (lispstrings, buffer, bufsize, format, format_end, nargs, args)
                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;
@@ -219,12 +173,8 @@ doprnt1 (lispstrings, buffer, bufsize, format, format_end, nargs, args)
            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;
@@ -233,21 +183,10 @@ doprnt1 (lispstrings, buffer, bufsize, format, format_end, nargs, args)
            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;
 
@@ -275,12 +214,12 @@ doprnt1 (lispstrings, buffer, bufsize, format, format_end, nargs, args)
                  /* 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)
@@ -296,16 +235,21 @@ doprnt1 (lispstrings, buffer, bufsize, format, format_end, nargs, args)
              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 */
@@ -328,12 +272,9 @@ doprnt1 (lispstrings, buffer, bufsize, format, format_end, nargs, args)
     };
 
   /* 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) */