emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Emacs-diffs] Changes to emacs/src/doprnt.c [emacs-unicode-2]


From: Kenichi Handa
Subject: [Emacs-diffs] Changes to emacs/src/doprnt.c [emacs-unicode-2]
Date: Mon, 08 Sep 2003 08:48:49 -0400

Index: emacs/src/doprnt.c
diff -c /dev/null emacs/src/doprnt.c:1.39.6.1
*** /dev/null   Mon Sep  8 08:48:49 2003
--- emacs/src/doprnt.c  Mon Sep  8 08:48:10 2003
***************
*** 0 ****
--- 1,336 ----
+ /* 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 Free Software Foundation, Inc.
+ 
+ This file is part of GNU Emacs.
+ 
+ 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 2, 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
+ 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., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.  */
+ 
+ 
+ #include <config.h>
+ #include <stdio.h>
+ #include <ctype.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 ();
+ 
+ /* Generate output from a format-spec FORMAT,
+    terminated at position FORMAT_END.
+    Output goes in BUFFER, which has room for BUFSIZE chars.
+    If the output does not fit, truncate it to fit.
+    Returns the number of bytes stored into BUFFER.
+    ARGS points to the vector of arguments, and NARGS says how many.
+    A double counts as two arguments.
+    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;
+ {
+   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 */
+   register char *bufptr = buffer; /* Pointer into output buffer.. */
+ 
+   /* Use this for sprintf unless we need something really big.  */
+   char tembuf[DBL_MAX_10_EXP + 100];
+ 
+   /* Size of sprintf_buffer.  */
+   int size_allocated = sizeof (tembuf);
+ 
+   /* Buffer to use for sprintf.  Either tembuf or same as BIG_BUFFER.  */
+   char *sprintf_buffer = tembuf;
+ 
+   /* Buffer we have got with malloc.  */
+   char *big_buffer = 0;
+ 
+   register int tem;
+   unsigned char *string;
+   char fixed_buffer[20];      /* Default buffer for small formatting. */
+   char *fmtcpy;
+   int minlen;
+   unsigned char charbuf[5];   /* Used for %c.  */
+ 
+   if (format_end == 0)
+     format_end = format + strlen (format);
+ 
+   if ((format_end - format + 1) < sizeof (fixed_buffer))
+     fmtcpy = fixed_buffer;
+   else
+     fmtcpy = (char *) alloca (format_end - format + 1);
+ 
+   bufsize--;
+ 
+   /* Loop until end of format string or buffer full. */
+   while (fmt != format_end && bufsize > 0)
+     {
+       if (*fmt == '%')        /* Check for a '%' character */
+       {
+         int size_bound = 0;
+         int width;            /* Columns occupied by STRING.  */
+ 
+         fmt++;
+         /* Copy this one %-spec into fmtcpy.  */
+         string = (unsigned char *)fmtcpy;
+         *string++ = '%';
+         while (1)
+           {
+             *string++ = *fmt;
+             if ('0' <= *fmt && *fmt <= '9')
+               {
+                 /* Get an idea of how much space we might need.
+                    This might be a field width or a precision; e.g.
+                    %1.1000f and %1000.1f both might need 1000+ bytes.
+                    Parse the width or precision, checking for overflow.  */
+                 int n = *fmt - '0';
+                 while ('0' <= fmt[1] && fmt[1] <= '9')
+                   {
+                     if (n * 10 / 10 != n
+                         || (n = n * 10 + (fmt[1] - '0')) < 0)
+                       error ("Format width or precision too large");
+                     *string++ = *++fmt;
+                   }
+ 
+                 if (size_bound < n)
+                   size_bound = n;
+               }
+             else if (*fmt == '-' || *fmt == ' ' || *fmt == '.')
+               ;
+             else
+               break;
+             fmt++;
+           }
+         *string = 0;
+ 
+         /* Make the size bound large enough to handle floating point formats
+            with large numbers.  */
+         size_bound += DBL_MAX_10_EXP + 50;
+ 
+         if (size_bound < 0)
+           error ("Format width or precision too large");
+ 
+         /* Make sure we have that much.  */
+         if (size_bound > size_allocated)
+           {
+             if (big_buffer)
+               big_buffer = (char *) xrealloc (big_buffer, size_bound);
+             else
+               big_buffer = (char *) xmalloc (size_bound);
+             sprintf_buffer = big_buffer;
+             size_allocated = size_bound;
+           }
+         minlen = 0;
+         switch (*fmt++)
+           {
+           default:
+             error ("Invalid format operation %%%c", fmt[-1]);
+ 
+ /*        case 'b': */
+           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))
+               /* Insert an `l' the right place.  */
+               string[1] = string[0],
+               string[0] = string[-1],
+               string[-1] = 'l',
+               string++;
+             else
+               abort ();
+             sprintf (sprintf_buffer, fmtcpy, args[cnt++]);
+             /* Now copy into final output, truncating as nec.  */
+             string = (unsigned char *)sprintf_buffer;
+             goto doit;
+ 
+           case 'f':
+           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);
+               /* 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);
+               }
+             width = strwidth (string, tem);
+             goto doit1;
+ 
+             /* Copy string into final output, truncating if no room.  */
+           doit:
+             /* Coming here means STRING contains ASCII only.  */
+             width = tem = strlen (string);
+           doit1:
+             /* We have already calculated:
+                TEM -- length of STRING,
+                WIDTH -- columns occupied by STRING when displayed, and
+                MINLEN -- minimum columns of the output.  */
+             if (minlen > 0)
+               {
+                 while (minlen > width && bufsize > 0)
+                   {
+                     *bufptr++ = ' ';
+                     bufsize--;
+                     minlen--;
+                   }
+                 minlen = 0;
+               }
+             if (tem > bufsize)
+               {
+                 /* Truncate the string at character boundary.  */
+                 tem = bufsize;
+                 while (!CHAR_HEAD_P (string[tem - 1])) tem--;
+                 bcopy (string, bufptr, tem);
+                 /* We must calculate WIDTH again.  */
+                 width = strwidth (bufptr, tem);
+               }
+             else
+               bcopy (string, bufptr, tem);
+             bufptr += tem;
+             bufsize -= tem;
+             if (minlen < 0)
+               {
+                 while (minlen < - width && bufsize > 0)
+                   {
+                     *bufptr++ = ' ';
+                     bufsize--;
+                     minlen++;
+                   }
+                 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;
+ 
+           case '%':
+             fmt--;    /* Drop thru and this % will be treated as normal */
+           }
+       }
+ 
+       {
+       /* Just some character; Copy it if the whole multi-byte form
+          fit in the buffer.  */
+       char *save_bufptr = bufptr;
+ 
+       do { *bufptr++ = *fmt++; }
+       while (--bufsize > 0 && !CHAR_HEAD_P (*fmt));
+       if (!CHAR_HEAD_P (*fmt))
+         {
+           bufptr = save_bufptr;
+           break;
+         }
+       }
+     };
+ 
+   /* If we had to malloc something, free it.  */
+   if (big_buffer)
+     xfree (big_buffer);
+ 
+   *bufptr = 0;                /* Make sure our string end with a '\0' */
+   return bufptr - buffer;
+ }




reply via email to

[Prev in Thread] Current Thread [Next in Thread]