1 diff -Nur coreutils-5.0.orig/lib/xalloc.h coreutils-5.0/lib/xalloc.h
2 --- coreutils-5.0.orig/lib/xalloc.h Tue Oct 31 08:09:56 2000
3 +++ coreutils-5.0/lib/xalloc.h Mon Dec 1 16:46:22 2003
5 memory allocation failure. */
6 extern void xalloc_die PARAMS ((void)) ATTRIBUTE_NORETURN;
8 -void *xmalloc PARAMS ((size_t n));
9 +void *xmalloc PARAMS ((size_t s));
10 +void *xnmalloc PARAMS ((size_t n, size_t s));
11 +void *xzalloc PARAMS ((size_t s));
12 void *xcalloc PARAMS ((size_t n, size_t s));
13 -void *xrealloc PARAMS ((void *p, size_t n));
14 +void *xrealloc PARAMS ((void *p, size_t s));
15 +void *xnrealloc PARAMS ((void *p, size_t n, size_t s));
16 char *xstrdup PARAMS ((const char *str));
17 +void *xclone PARAMS ((void const *p, size_t s));
19 -# define XMALLOC(Type, N_items) ((Type *) xmalloc (sizeof (Type) * (N_items)))
20 -# define XCALLOC(Type, N_items) ((Type *) xcalloc (sizeof (Type), (N_items)))
21 -# define XREALLOC(Ptr, Type, N_items) \
22 - ((Type *) xrealloc ((void *) (Ptr), sizeof (Type) * (N_items)))
24 -/* Declare and alloc memory for VAR of type TYPE. */
25 -# define NEW(Type, Var) Type *(Var) = XMALLOC (Type, 1)
27 -/* Free VAR only if non NULL. */
28 -# define XFREE(Var) \
34 -/* Return a pointer to a malloc'ed copy of the array SRC of NUM elements. */
35 -# define CCLONE(Src, Num) \
36 - (memcpy (xmalloc (sizeof (*Src) * (Num)), (Src), sizeof (*Src) * (Num)))
38 -/* Return a malloc'ed copy of SRC. */
39 -# define CLONE(Src) CCLONE (Src, 1)
41 +/* These macros are deprecated; they will go away soon, and are retained
42 + temporarily only to ease conversion to the functions described above. */
43 +# define CCLONE(p, n) xclone (p, (n) * sizeof *(p))
44 +# define CLONE(p) xclone (p, sizeof *(p))
45 +# define NEW(type, var) type *var = xmalloc (sizeof (type))
46 +# define XCALLOC(type, n) xcalloc (n, sizeof (type))
47 +# define XMALLOC(type, n) xnmalloc (n, sizeof (type))
48 +# define XREALLOC(p, type, n) xnrealloc (p, n, sizeof (type))
49 +# define XFREE(p) free (p)
51 #endif /* !XALLOC_H_ */
52 diff -Nur coreutils-5.0.orig/lib/xmalloc.c coreutils-5.0/lib/xmalloc.c
53 --- coreutils-5.0.orig/lib/xmalloc.c Thu Nov 21 21:39:59 2002
54 +++ coreutils-5.0/lib/xmalloc.c Mon Dec 1 16:46:22 2003
56 #include <sys/types.h>
59 +# include <stdbool.h>
67 /* The following tests require AC_PREREQ(2.54). */
70 +# define SIZE_MAX ((size_t) -1)
74 "you must run the autoconf test for a GNU libc compatible malloc"
77 /* If non NULL, call this function when memory is exhausted. */
78 void (*xalloc_fail_func) PARAMS ((void)) = 0;
80 +/* Return true if array of N objects, each of size S, cannot exist due
81 + to arithmetic overflow. S must be nonzero. */
84 +array_size_overflow (size_t n, size_t s)
86 + return SIZE_MAX / s < n;
89 /* If XALLOC_FAIL_FUNC is NULL, or does return, display this message
90 before exiting when memory is exhausted. Goes through gettext. */
91 char const xalloc_msg_memory_exhausted[] = N_("memory exhausted");
93 error (xalloc_exit_failure, 0, "%s", _(xalloc_msg_memory_exhausted));
94 /* The `noreturn' cannot be given to error, since it may return if
95 its first argument is 0. To help compilers understand the
96 - xalloc_die does terminate, call exit. */
97 - exit (EXIT_FAILURE);
98 + xalloc_die does terminate, call abort. */
102 +/* Allocate an array of N objects, each with S bytes of memory,
103 + dynamically, with error checking. S must be nonzero. */
106 +xnmalloc (size_t n, size_t s)
109 + if (array_size_overflow (n, s) || ! (p = malloc (n * s)))
114 /* Allocate N bytes of memory dynamically, with error checking. */
120 + return xnmalloc (n, 1);
125 +/* Change the size of an allocated block of memory P to an array of N
126 + objects each of S bytes, with error checking. S must be nonzero. */
129 +xnrealloc (void *p, size_t n, size_t s)
131 + if (array_size_overflow (n, s) || ! (p = realloc (p, n * s)))
137 xrealloc (void *p, size_t n)
139 - p = realloc (p, n);
143 + return xnrealloc (p, n, 1);
146 -/* Allocate memory for N elements of S bytes, with error checking. */
147 +/* Allocate S bytes of zeroed memory dynamically, with error checking.
148 + There's no need for xnzalloc (N, S), since it would be equivalent
149 + to xcalloc (N, S). */
154 + return memset (xmalloc (s), 0, s);
157 +/* Allocate zeroed memory for N elements of S bytes, with error
158 + checking. S must be nonzero. */
161 xcalloc (size_t n, size_t s)
167 + /* Test for overflow, since some calloc implementations don't have
168 + proper overflow checks. */
169 + if (array_size_overflow (n, s) || ! (p = calloc (n, s)))
174 +/* Clone an object P of size S, with error checking. There's no need
175 + for xnclone (P, N, S), since xclone (P, N * S) works without any
176 + need for an arithmetic overflow check. */
179 +xclone (void const *p, size_t s)
181 + return memcpy (xmalloc (s), p, s);
183 diff -Nur coreutils-5.0.orig/lib/xstrdup.c coreutils-5.0/lib/xstrdup.c
184 --- coreutils-5.0.orig/lib/xstrdup.c Fri Nov 30 15:32:22 2001
185 +++ coreutils-5.0/lib/xstrdup.c Mon Dec 1 16:46:22 2003
188 xstrdup (const char *string)
190 - return strcpy (xmalloc (strlen (string) + 1), string);
191 + return xclone (string, strlen (string) + 1);
193 diff -Nur coreutils-5.0.orig/src/ls.c coreutils-5.0/src/ls.c
194 --- coreutils-5.0.orig/src/ls.c Mon Dec 1 16:45:36 2003
195 +++ coreutils-5.0/src/ls.c Mon Dec 1 16:55:07 2003
200 - int len; /* Number of bytes */
201 + size_t len; /* Number of bytes */
202 const char *string; /* Pointer to the same */
205 @@ -265,15 +265,15 @@
206 static void print_color_indicator (const char *name, mode_t mode, int linkok);
207 static void put_indicator (const struct bin_str *ind);
208 static int put_indicator_direct (const struct bin_str *ind);
209 -static int length_of_file_name_and_frills (const struct fileinfo *f);
210 +static size_t length_of_file_name_and_frills (const struct fileinfo *f);
211 static void add_ignore_pattern (const char *pattern);
212 static void attach (char *dest, const char *dirname, const char *name);
213 static void clear_files (void);
214 static void extract_dirs_from_files (const char *dirname,
215 int ignore_dot_and_dot_dot);
216 static void get_link_name (const char *filename, struct fileinfo *f);
217 -static void indent (int from, int to);
218 -static void init_column_info (void);
219 +static void indent (size_t from, size_t to);
220 +static size_t calculate_columns (bool by_columns);
221 static void print_current_files (void);
222 static void print_dir (const char *name, const char *realname);
223 static void print_file_name_and_frills (const struct fileinfo *f);
224 @@ -319,10 +319,10 @@
225 static struct fileinfo *files; /* FIXME: rename this to e.g. cwd_file */
227 /* Length of block that `files' points to, measured in files. */
228 -static int nfiles; /* FIXME: rename this to e.g. cwd_n_alloc */
229 +static size_t nfiles; /* FIXME: rename this to e.g. cwd_n_alloc */
231 /* Index of first unused in `files'. */
232 -static int files_index; /* FIXME: rename this to e.g. cwd_n_used */
233 +static size_t files_index; /* FIXME: rename this to e.g. cwd_n_used */
235 /* When nonzero, in a color listing, color each symlink name according to the
236 type of file it points to. Otherwise, color them according to the `ln'
239 /* The number of chars per hardware tab stop. Setting this to zero
240 inhibits the use of TAB characters for separating columns. -T */
242 +static size_t tabsize;
244 /* Nonzero means we are listing the working directory because no
245 non-option arguments were given. */
247 /* The line length to use for breaking lines in many-per-line format.
248 Can be set with -w. */
250 -static int line_length;
251 +static size_t line_length;
253 /* If nonzero, the file listing format requires that stat be called on
255 @@ -799,16 +799,16 @@
256 /* Information about filling a column. */
267 /* Array with information about column filledness. */
268 static struct column_info *column_info;
270 /* Maximum number of columns ever possible for this display. */
272 +static size_t max_idx;
274 /* The minimum width of a colum is 3: 1 character for the name and 2
275 for the separating white space. */
276 @@ -904,18 +904,18 @@
278 dired_dump_obstack (const char *prefix, struct obstack *os)
283 n_pos = obstack_object_size (os) / sizeof (dired_pos);
290 pos = (size_t *) obstack_finish (os);
291 fputs (prefix, stdout);
292 for (i = 0; i < n_pos; i++)
293 - printf (" %lu", (unsigned long) pos[i]);
294 + printf (" %lu", (unsigned long int) pos[i]);
299 struct dev_ino *ent_from_table;
302 - ent = XMALLOC (struct dev_ino, 1);
303 + ent = xmalloc (sizeof *ent);
307 @@ -1134,7 +1134,7 @@
311 - files = XMALLOC (struct fileinfo, nfiles);
312 + files = xnmalloc (nfiles, sizeof *files);
316 @@ -1322,11 +1322,11 @@
317 char const *p = getenv ("COLUMNS");
321 - if (xstrtol (p, NULL, 0, &tmp_long, NULL) == LONGINT_OK
322 - && 0 < tmp_long && tmp_long <= INT_MAX)
323 + unsigned long int tmp_ulong;
324 + if (xstrtoul (p, NULL, 0, &tmp_ulong, NULL) == LONGINT_OK
325 + && 0 < tmp_ulong && tmp_ulong <= SIZE_MAX)
327 - line_length = (int) tmp_long;
328 + line_length = tmp_ulong;
332 @@ -1341,7 +1341,8 @@
336 - if (ioctl (STDOUT_FILENO, TIOCGWINSZ, &ws) != -1 && ws.ws_col != 0)
337 + if (ioctl (STDOUT_FILENO, TIOCGWINSZ, &ws) != -1
338 + && 0 < ws.ws_col && ws.ws_col <= SIZE_MAX)
339 line_length = ws.ws_col;
342 @@ -1353,11 +1354,11 @@
344 if (!getenv ("POSIXLY_CORRECT") && (p = getenv ("TABSIZE")))
347 - if (xstrtol (p, NULL, 0, &tmp_long, NULL) == LONGINT_OK
348 - && 0 <= tmp_long && tmp_long <= INT_MAX)
349 + unsigned long int tmp_ulong;
350 + if (xstrtoul (p, NULL, 0, &tmp_ulong, NULL) == LONGINT_OK
351 + && tmp_ulong <= SIZE_MAX)
353 - tabsize = (int) tmp_long;
354 + tabsize = tmp_ulong;
358 @@ -1476,12 +1477,12 @@
363 - if (xstrtol (optarg, NULL, 0, &tmp_long, NULL) != LONGINT_OK
364 - || tmp_long <= 0 || tmp_long > INT_MAX)
365 + unsigned long int tmp_ulong;
366 + if (xstrtoul (optarg, NULL, 0, &tmp_ulong, NULL) != LONGINT_OK
367 + || ! (0 < tmp_ulong && tmp_ulong <= SIZE_MAX))
368 error (EXIT_FAILURE, 0, _("invalid line width: %s"),
370 - line_length = (int) tmp_long;
371 + line_length = tmp_ulong;
375 @@ -1550,12 +1551,12 @@
380 - if (xstrtol (optarg, NULL, 0, &tmp_long, NULL) != LONGINT_OK
381 - || tmp_long < 0 || tmp_long > INT_MAX)
382 + unsigned long int tmp_ulong;
383 + if (xstrtoul (optarg, NULL, 0, &tmp_ulong, NULL) != LONGINT_OK
384 + || SIZE_MAX < tmp_ulong)
385 error (EXIT_FAILURE, 0, _("invalid tab size: %s"),
387 - tabsize = (int) tmp_long;
388 + tabsize = tmp_ulong;
392 @@ -1661,6 +1662,8 @@
396 + max_idx = MAX (1, line_length / MIN_COLUMN_WIDTH);
398 filename_quoting_options = clone_quoting_options (NULL);
399 if (get_quoting_style (filename_quoting_options) == escape_quoting_style)
400 set_char_quoting (filename_quoting_options, ' ', 1);
401 @@ -1762,7 +1765,8 @@
402 /* Parse a string as part of the LS_COLORS variable; this may involve
403 decoding all kinds of escape characters. If equals_end is set an
404 unescaped equal sign ends the string, otherwise only a : or \0
405 - does. Returns the number of characters output, or -1 on failure.
406 + does. Set *OUTPUT_COUNT to the number of bytes output. Return
407 + true if successful.
409 The resulting string is *not* null-terminated, but may contain
411 @@ -1771,11 +1775,12 @@
412 the first free byte after the array and the character that ended
413 the input string, respectively. */
416 -get_funky_string (char **dest, const char **src, int equals_end)
418 +get_funky_string (char **dest, const char **src, bool equals_end,
419 + size_t *output_count)
421 int num; /* For numerical codes */
422 - int count; /* Something to count with */
423 + size_t count; /* Something to count with */
425 ST_GND, ST_BACKSLASH, ST_OCTAL, ST_HEX, ST_CARET, ST_END, ST_ERROR
427 @@ -1960,8 +1965,9 @@
431 + *output_count = count;
433 - return state == ST_ERROR ? -1 : count;
434 + return state != ST_ERROR;
438 @@ -2004,15 +2010,15 @@
439 override an earlier one, which can be useful for
440 having terminal-specific defs override global). */
442 - ext = XMALLOC (struct color_ext_type, 1);
443 + ext = xmalloc (sizeof *ext);
444 ext->next = color_ext_list;
445 color_ext_list = ext;
448 ext->ext.string = buf;
450 - state = (ext->ext.len =
451 - get_funky_string (&buf, &p, 1)) < 0 ? -1 : 4;
452 + state = (get_funky_string (&buf, &p, true, &ext->ext.len)
457 @@ -2045,8 +2051,9 @@
458 if (STREQ (label, indicator_name[ind_no]))
460 color_indicator[ind_no].string = buf;
461 - state = ((color_indicator[ind_no].len =
462 - get_funky_string (&buf, &p, 0)) < 0 ? -1 : 1);
463 + state = (get_funky_string (&buf, &p, false,
464 + &color_indicator[ind_no].len)
469 @@ -2059,8 +2066,8 @@
472 ext->seq.string = buf;
473 - state = (ext->seq.len =
474 - get_funky_string (&buf, &p, 0)) < 0 ? -1 : 1;
475 + state = (get_funky_string (&buf, &p, false, &ext->seq.len)
480 @@ -2104,7 +2111,7 @@
484 - new = XMALLOC (struct pending, 1);
485 + new = xmalloc (sizeof *new);
486 new->realname = realname ? xstrdup (realname) : NULL;
487 new->name = name ? xstrdup (name) : NULL;
488 new->next = pending_dirs;
489 @@ -2259,7 +2266,7 @@
491 register struct ignore_pattern *ignore;
493 - ignore = XMALLOC (struct ignore_pattern, 1);
494 + ignore = xmalloc (sizeof *ignore);
495 ignore->pattern = pattern;
496 /* Add it to the head of the linked list. */
497 ignore->next = ignore_patterns;
498 @@ -2294,7 +2301,7 @@
505 for (i = 0; i < files_index; i++)
507 @@ -2320,8 +2327,8 @@
509 if (files_index == nfiles)
511 + files = xnrealloc (files, nfiles, 2 * sizeof *files);
513 - files = XREALLOC (files, struct fileinfo, nfiles);
516 files[files_index].linkname = 0;
517 @@ -2547,7 +2554,8 @@
519 extract_dirs_from_files (const char *dirname, int ignore_dot_and_dot_dot)
525 if (*dirname && LOOP_DETECT)
527 @@ -2559,7 +2567,7 @@
529 /* Queue the directories last one first, because queueing reverses the
531 - for (i = files_index - 1; i >= 0; i--)
532 + for (i = files_index; i-- != 0; )
533 if ((files[i].filetype == directory || files[i].filetype == arg_directory)
534 && (!ignore_dot_and_dot_dot
535 || !basename_is_dot_or_dotdot (files[i].name)))
536 @@ -2786,7 +2794,7 @@
538 print_current_files (void)
545 @@ -2799,12 +2807,10 @@
549 - init_column_info ();
550 print_many_per_line ();
554 - init_column_info ();
558 @@ -2907,7 +2913,7 @@
560 sprintf (buffer, "%-8s ", name);
562 - sprintf (buffer, "%-8lu ", (unsigned long) u);
563 + sprintf (buffer, "%-8lu ", (unsigned long int) u);
564 return strlen (buffer);
567 @@ -2981,7 +2987,7 @@
569 /* The last byte of the mode string is the POSIX
570 "optional alternate access method flag". */
571 - sprintf (p, "%s %3lu ", modebuf, (unsigned long) f->stat.st_nlink);
572 + sprintf (p, "%s %3lu ", modebuf, (unsigned long int) f->stat.st_nlink);
576 @@ -2993,7 +2999,7 @@
578 sprintf (p, "%-8s ", group_name);
580 - sprintf (p, "%-8lu ", (unsigned long) f->stat.st_gid);
581 + sprintf (p, "%-8lu ", (unsigned long int) f->stat.st_gid);
585 @@ -3002,8 +3008,8 @@
587 if (S_ISCHR (f->stat.st_mode) || S_ISBLK (f->stat.st_mode))
588 sprintf (p, "%3lu, %3lu ",
589 - (unsigned long) major (f->stat.st_rdev),
590 - (unsigned long) minor (f->stat.st_rdev));
591 + (unsigned long int) major (f->stat.st_rdev),
592 + (unsigned long int) minor (f->stat.st_rdev));
595 char hbuf[LONGEST_HUMAN_READABLE + 1];
596 @@ -3405,7 +3411,7 @@
597 name += len; /* Pointer to final \0. */
598 for (ext = color_ext_list; ext != NULL; ext = ext->next)
600 - if ((size_t) ext->ext.len <= len
601 + if (ext->ext.len <= len
602 && strncmp (name - ext->ext.len, ext->ext.string,
605 @@ -3422,12 +3428,12 @@
607 put_indicator (const struct bin_str *ind)
611 register const char *p;
615 - for (i = ind->len; i > 0; --i)
616 + for (i = ind->len; i != 0; --i)
620 @@ -3445,10 +3451,10 @@
621 return (full_write (STDOUT_FILENO, ind->string, len) != len);
626 length_of_file_name_and_frills (const struct fileinfo *f)
628 - register int len = 0;
629 + register size_t len = 0;
633 @@ -3485,70 +3491,25 @@
635 print_many_per_line (void)
637 - struct column_info *line_fmt;
638 - int filesno; /* Index into files. */
639 - int row; /* Current row. */
640 - int max_name_length; /* Length of longest file name + frills. */
641 - int name_length; /* Length of each file name + frills. */
642 - int pos; /* Current character column. */
643 - int cols; /* Number of files across. */
644 - int rows; /* Maximum number of files down. */
647 - /* Normally the maximum number of columns is determined by the
648 - screen width. But if few files are available this might limit it
650 - max_cols = max_idx > files_index ? files_index : max_idx;
652 - /* Compute the maximum number of possible columns. */
653 - for (filesno = 0; filesno < files_index; ++filesno)
657 - name_length = length_of_file_name_and_frills (files + filesno);
659 - for (i = 0; i < max_cols; ++i)
661 - if (column_info[i].valid_len)
663 - int idx = filesno / ((files_index + i) / (i + 1));
664 - int real_length = name_length + (idx == i ? 0 : 2);
666 - if (real_length > column_info[i].col_arr[idx])
668 - column_info[i].line_len += (real_length
669 - - column_info[i].col_arr[idx]);
670 - column_info[i].col_arr[idx] = real_length;
671 - column_info[i].valid_len = column_info[i].line_len < line_length;
677 - /* Find maximum allowed columns. */
678 - for (cols = max_cols; cols > 1; --cols)
680 - if (column_info[cols - 1].valid_len)
684 - line_fmt = &column_info[cols - 1];
685 + size_t row; /* Current row. */
686 + size_t cols = calculate_columns (true);
687 + struct column_info const *line_fmt = &column_info[cols - 1];
689 /* Calculate the number of rows that will be in each column except possibly
690 for a short column on the right. */
691 - rows = files_index / cols + (files_index % cols != 0);
692 + size_t rows = files_index / cols + (files_index % cols != 0);
694 for (row = 0; row < rows; row++)
700 + size_t filesno = row;
702 /* Print the next row. */
705 + size_t name_length = length_of_file_name_and_frills (files + filesno);
706 + size_t max_name_length = line_fmt->col_arr[col++];
707 print_file_name_and_frills (files + filesno);
708 - name_length = length_of_file_name_and_frills (files + filesno);
709 - max_name_length = line_fmt->col_arr[col++];
712 if (filesno >= files_index)
713 @@ -3564,65 +3525,20 @@
715 print_horizontal (void)
717 - struct column_info *line_fmt;
719 - int max_name_length;
725 - /* Normally the maximum number of columns is determined by the
726 - screen width. But if few files are available this might limit it
728 - max_cols = max_idx > files_index ? files_index : max_idx;
730 - /* Compute the maximum file name length. */
731 - max_name_length = 0;
732 - for (filesno = 0; filesno < files_index; ++filesno)
736 - name_length = length_of_file_name_and_frills (files + filesno);
738 - for (i = 0; i < max_cols; ++i)
740 - if (column_info[i].valid_len)
742 - int idx = filesno % (i + 1);
743 - int real_length = name_length + (idx == i ? 0 : 2);
745 - if (real_length > column_info[i].col_arr[idx])
747 - column_info[i].line_len += (real_length
748 - - column_info[i].col_arr[idx]);
749 - column_info[i].col_arr[idx] = real_length;
750 - column_info[i].valid_len = column_info[i].line_len < line_length;
756 - /* Find maximum allowed columns. */
757 - for (cols = max_cols; cols > 1; --cols)
759 - if (column_info[cols - 1].valid_len)
763 - line_fmt = &column_info[cols - 1];
768 + size_t cols = calculate_columns (false);
769 + struct column_info const *line_fmt = &column_info[cols - 1];
770 + size_t name_length = length_of_file_name_and_frills (files);
771 + size_t max_name_length = line_fmt->col_arr[0];
773 /* Print first entry. */
774 print_file_name_and_frills (files);
775 - name_length = length_of_file_name_and_frills (files);
776 - max_name_length = line_fmt->col_arr[0];
779 for (filesno = 1; filesno < files_index; ++filesno)
781 - int col = filesno % cols;
782 + size_t col = filesno % cols;
786 @@ -3646,8 +3562,9 @@
788 print_with_commas (void)
798 @@ -3679,11 +3596,11 @@
799 Use a TAB character instead of two or more spaces whenever possible. */
802 -indent (int from, int to)
803 +indent (size_t from, size_t to)
807 - if (tabsize > 0 && to / tabsize > (from + 1) / tabsize)
808 + if (tabsize != 0 && to / tabsize > (from + 1) / tabsize)
811 from += tabsize - from % tabsize;
812 @@ -3719,37 +3636,129 @@
816 +/* Allocate enough column info suitable for the current number of
817 + files and display columns, and initialize the info to represent the
818 + narrowest possible columns. */
821 init_column_info (void)
827 - max_idx = line_length / MIN_COLUMN_WIDTH;
830 + size_t max_cols = MIN (max_idx, files_index);
832 - if (column_info == NULL)
833 + /* Currently allocated columns in column_info. */
834 + static size_t column_info_alloc;
836 + if (column_info_alloc < max_cols)
838 - column_info = XMALLOC (struct column_info, max_idx);
840 + size_t new_column_info_alloc;
843 + if (max_cols < max_idx / 2)
845 + /* The number of columns is far less than the display width
846 + allows. Grow the allocation, but only so that it's
847 + double the current requirements. If the display is
848 + extremely wide, this avoids allocating a lot of memory
849 + that is never needed. */
850 + column_info = xnrealloc (column_info, max_cols,
851 + 2 * sizeof *column_info);
852 + new_column_info_alloc = 2 * max_cols;
856 + column_info = xnrealloc (column_info, max_idx, sizeof *column_info);
857 + new_column_info_alloc = max_idx;
860 + /* Allocate the new size_t objects by computing the triangle
861 + formula n * (n + 1) / 2, except that we don't need to
862 + allocate the part of the triangle that we've already
863 + allocated. Check for address arithmetic overflow. */
865 + size_t column_info_growth = new_column_info_alloc - column_info_alloc;
866 + size_t s = column_info_alloc + 1 + new_column_info_alloc;
867 + size_t t = s * column_info_growth;
868 + if (s < new_column_info_alloc || t / column_info_growth != s)
870 + p = xnmalloc (t / 2, sizeof *p);
873 + /* Grow the triangle by parceling out the cells just allocated. */
874 + for (i = column_info_alloc; i < new_column_info_alloc; i++)
876 + column_info[i].col_arr = p;
880 + column_info_alloc = new_column_info_alloc;
883 - for (i = 0; i < max_idx; ++i)
884 + for (i = 0; i < max_cols; ++i)
889 - column_info[i].valid_len = 1;
890 + column_info[i].valid_len = true;
891 column_info[i].line_len = (i + 1) * MIN_COLUMN_WIDTH;
894 - column_info[i].col_arr = XMALLOC (int, i + 1);
896 for (j = 0; j <= i; ++j)
897 column_info[i].col_arr[j] = MIN_COLUMN_WIDTH;
901 +/* Calculate the number of columns needed to represent the current set
902 + of files in the current display width. */
905 +calculate_columns (bool by_columns)
907 + size_t filesno; /* Index into files. */
908 + size_t cols; /* Number of files across. */
910 + /* Normally the maximum number of columns is determined by the
911 + screen width. But if few files are available this might limit it
913 + size_t max_cols = MIN (max_idx, files_index);
915 + init_column_info ();
917 + /* Compute the maximum number of possible columns. */
918 + for (filesno = 0; filesno < files_index; ++filesno)
920 + size_t name_length = length_of_file_name_and_frills (files + filesno);
923 + for (i = 0; i < max_cols; ++i)
925 + if (column_info[i].valid_len)
927 + size_t idx = (by_columns
928 + ? filesno / ((files_index + i) / (i + 1))
929 + : filesno % (i + 1));
930 + size_t real_length = name_length + (idx == i ? 0 : 2);
932 + if (column_info[i].col_arr[idx] < real_length)
934 + column_info[i].line_len += (real_length
935 + - column_info[i].col_arr[idx]);
936 + column_info[i].col_arr[idx] = real_length;
937 + column_info[i].valid_len = (column_info[i].line_len
944 + /* Find maximum allowed columns. */
945 + for (cols = max_cols; 1 < cols; --cols)
947 + if (column_info[cols - 1].valid_len)