Partially sync files.el from XEmacs 21.5 for wildcard support.
[sxemacs] / src / doprnt.c
index c66ec4c..efedd95 100644 (file)
@@ -29,6 +29,7 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>. */
 
 #include "buffer.h"
 #include "lstream.h"
+#include "ent/ent.h"
 
 static const char *const valid_flags = "-+ #0";
 static const char *const valid_converters = "dic" "oxX" "feEgG" "sS" "b"
@@ -397,6 +398,10 @@ get_doprnt_args(printf_spec_dynarr *specs, va_list vargs)
        printf_arg_t arg;
        REGISTER int i;
        int args_needed = get_args_needed(specs);
+       int spec_len = -1;
+
+       if (specs)
+               spec_len = Dynarr_length(specs);
 
        xzero(arg);
        for (i = 1; i <= args_needed; i++) {
@@ -404,14 +409,14 @@ get_doprnt_args(printf_spec_dynarr *specs, va_list vargs)
                char ch;
                printf_spec_t spec = 0;
 
-               for (j = 0; j < Dynarr_length(specs); j++) {
+               for (j = 0; j < spec_len; j++) {
                        spec = Dynarr_atp(specs, j);
                        if (spec->argnum == i) {
                                break;
                        }
                }
 
-               if (j == Dynarr_length(specs))
+               if (j >= spec_len)
                        error("No conversion spec for argument %d", i);
 
                ch = spec->converter;
@@ -485,7 +490,7 @@ __ulong_to_bit_string(char *p, long unsigned int number)
 {
        int i, seen_high_order = 0;
        char *origp = p;
-  
+
        for (i = ((SIZEOF_LONG * 8) - 1); i >= 0; --i) {
                if (number & 1UL << i) {
                        seen_high_order = 1;
@@ -743,7 +748,7 @@ emacs_doprnt_smZ(Lisp_Object stream, EMACS_INT Z, printf_spec_t s,  char ch)
        } else /* ch == 'b' */ {
                text_len = __ulong_to_bit_string(text, Z);
        }
-
+       assert(text_len >= 0 && text_len < alloc_sz);
        /* postprocess, move stuff around, insert naughts, etc. */
        text_len = __postproc2(s, text, text_len, alloc_sz);
 
@@ -961,6 +966,7 @@ emacs_doprnt_number(Lisp_Object stream,
                char *p = constructed_spec;
                int length, alloca_sz = max_float_print_size;
                int min = spec->minwidth, prec = spec->precision;
+               int max_spec = sizeof(constructed_spec);
 
 #if 0
                /* absolute non-sense :O ...
@@ -996,20 +1002,27 @@ emacs_doprnt_number(Lisp_Object stream,
                        *p++ = '0';
 
                if (spec->minwidth >= 0) {
-                       long_to_string(p, spec->minwidth);
+                       long_to_string(p, spec->minwidth, max_spec);
+                       max_spec -= strlen(p);
                        p += strlen (p);
                }
                if (spec->precision >= 0) {
                        *p++ = '.';
-                       long_to_string(p, spec->precision);
+                       --max_spec;
+                       long_to_string(p, spec->precision, max_spec);
+                       max_spec -= strlen(p);
                        p += strlen (p);
                }
 
 #if fpfloat_long_double_p
                *p++ = 'L';
+               --max_spec;
 #endif
                *p++ = ch;
+               --max_spec;
                *p++ = '\0';
+               --max_spec;
+               assert(max_spec >= 0);
                if (NILP(obj))
                        length = snprintf(text_to_print, alloca_sz,
                                          constructed_spec, arg.d);
@@ -1017,9 +1030,10 @@ emacs_doprnt_number(Lisp_Object stream,
                        length = snprintf(text_to_print, alloca_sz,
                                          constructed_spec, XFLOAT_DATA(obj));
 
-               if (length > alloca_sz)
+               if (length > alloca_sz) {
+                       /* should we really silently truncate?! */
                        length = alloca_sz;
-
+               }
                doprnt_1(stream, (Bufbyte *)text_to_print, length, 0, -1, 0, 0);
                return;
 
@@ -1320,7 +1334,7 @@ emacs_doprnt_1(Lisp_Object stream, const Bufbyte * format_nonreloc,
                args = get_doprnt_args(specs, vargs);
        }
 
-       for (i = 0; i < Dynarr_length(specs); i++) {
+       for (i = 0; specs && i < Dynarr_length(specs); i++) {
                printf_spec_t spec = Dynarr_atp(specs, i);
                char ch;
 
@@ -1345,26 +1359,30 @@ emacs_doprnt_1(Lisp_Object stream, const Bufbyte * format_nonreloc,
                   was specified as an argument.  Extract the data and forward
                   it to the next spec, to which it will apply.  */
                if (ch == '*') {
-                       printf_spec_t nextspec = Dynarr_atp(specs, i + 1);
-                       Lisp_Object obj = largs[spec->argnum - 1];
+                       if(!largs) {
+                               error("Invalid largs and '*' converter in emacs_doprnt_1");
+                       } else {
+                               printf_spec_t nextspec = Dynarr_atp(specs, i + 1);
+                               Lisp_Object obj = largs[spec->argnum - 1];
 
-                       if (INTP(obj)) {
-                               if (spec->forwarding_precision) {
-                                       nextspec->precision = XINT(obj);
-                                       nextspec->minwidth = spec->minwidth;
-                               } else {
-                                       nextspec->minwidth = XINT(obj);
-                                       if (XINT(obj) < 0) {
-                                               spec->minus_flag = 1;
-                                               nextspec->minwidth =
-                                                   -nextspec->minwidth;
+                               if (INTP(obj)) {
+                                       if (spec->forwarding_precision) {
+                                               nextspec->precision = XINT(obj);
+                                               nextspec->minwidth = spec->minwidth;
+                                       } else {
+                                               nextspec->minwidth = XINT(obj);
+                                               if (XINT(obj) < 0) {
+                                                       spec->minus_flag = 1;
+                                                       nextspec->minwidth =
+                                                               -nextspec->minwidth;
+                                               }
                                        }
+                                       nextspec->minus_flag = spec->minus_flag;
+                                       nextspec->plus_flag = spec->plus_flag;
+                                       nextspec->space_flag = spec->space_flag;
+                                       nextspec->number_flag = spec->number_flag;
+                                       nextspec->zero_flag = spec->zero_flag;
                                }
-                               nextspec->minus_flag = spec->minus_flag;
-                               nextspec->plus_flag = spec->plus_flag;
-                               nextspec->space_flag = spec->space_flag;
-                               nextspec->number_flag = spec->number_flag;
-                               nextspec->zero_flag = spec->zero_flag;
                        }
                        continue;
                }