]> sjero.net Git - wget/blob - src/utils.c
371afd6dbd4553bca76d548742d0bb0bde0873ff
[wget] / src / utils.c
1 /* Various functions of utilitarian nature.
2    Copyright (C) 1995, 1996, 1997, 1998, 2000 Free Software Foundation, Inc.
3
4 This file is part of Wget.
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
19
20 #include <config.h>
21
22 #include <stdio.h>
23 #include <stdlib.h>
24 #ifdef HAVE_STRING_H
25 # include <string.h>
26 #else  /* not HAVE_STRING_H */
27 # include <strings.h>
28 #endif /* not HAVE_STRING_H */
29 #include <ctype.h>
30 #include <sys/types.h>
31 #ifdef HAVE_UNISTD_H
32 # include <unistd.h>
33 #endif
34 #ifdef HAVE_PWD_H
35 # include <pwd.h>
36 #endif
37 #include <limits.h>
38 #ifdef HAVE_UTIME_H
39 # include <utime.h>
40 #endif
41 #ifdef HAVE_SYS_UTIME_H
42 # include <sys/utime.h>
43 #endif
44 #include <errno.h>
45 #ifdef NeXT
46 # include <libc.h>              /* for access() */
47 #endif
48
49 #include "wget.h"
50 #include "utils.h"
51 #include "fnmatch.h"
52
53 #ifndef errno
54 extern int errno;
55 #endif
56
57
58 /* Croak the fatal memory error and bail out with non-zero exit
59    status.  */
60 static void
61 memfatal (const char *s)
62 {
63   /* HACK: expose save_log_p from log.c, so we can turn it off in
64      order to prevent saving the log.  Saving the log is dangerous
65      because logprintf() and logputs() can call malloc(), so this
66      could infloop.  When logging is turned off, infloop can no longer
67      happen.  */
68   extern int save_log_p;
69
70   save_log_p = 0;
71   logprintf (LOG_ALWAYS, _("%s: %s: Not enough memory.\n"), exec_name, s);
72   exit (1);
73 }
74
75 /* xmalloc, xrealloc and xstrdup exit the program if there is not
76    enough memory.  xstrdup also implements strdup on systems that do
77    not have it.  */
78 void *
79 xmalloc (size_t size)
80 {
81   void *res;
82
83   res = malloc (size);
84   if (!res)
85     memfatal ("malloc");
86   return res;
87 }
88
89 void *
90 xrealloc (void *obj, size_t size)
91 {
92   void *res;
93
94   /* Not all Un*xes have the feature of realloc() that calling it with
95      a NULL-pointer is the same as malloc(), but it is easy to
96      simulate.  */
97   if (obj)
98     res = realloc (obj, size);
99   else
100     res = malloc (size);
101   if (!res)
102     memfatal ("realloc");
103   return res;
104 }
105
106 char *
107 xstrdup (const char *s)
108 {
109 #ifndef HAVE_STRDUP
110   int l = strlen (s);
111   char *s1 = malloc (l + 1);
112   if (!s1)
113     memfatal ("strdup");
114   memcpy (s1, s, l + 1);
115   return s1;
116 #else  /* HAVE_STRDUP */
117   char *s1 = strdup (s);
118   if (!s1)
119     memfatal ("strdup");
120   return s1;
121 #endif /* HAVE_STRDUP */
122 }
123 \f
124 /* Copy the string formed by two pointers (one on the beginning, other
125    on the char after the last char) to a new, malloc-ed location.
126    0-terminate it.  */
127 char *
128 strdupdelim (const char *beg, const char *end)
129 {
130   char *res = (char *)xmalloc (end - beg + 1);
131   memcpy (res, beg, end - beg);
132   res[end - beg] = '\0';
133   return res;
134 }
135
136 /* Parse a string containing comma-separated elements, and return a
137    vector of char pointers with the elements.  Spaces following the
138    commas are ignored.  */
139 char **
140 sepstring (const char *s)
141 {
142   char **res;
143   const char *p;
144   int i = 0;
145
146   if (!s || !*s)
147     return NULL;
148   res = NULL;
149   p = s;
150   while (*s)
151     {
152       if (*s == ',')
153         {
154           res = (char **)xrealloc (res, (i + 2) * sizeof (char *));
155           res[i] = strdupdelim (p, s);
156           res[++i] = NULL;
157           ++s;
158           /* Skip the blanks following the ','.  */
159           while (ISSPACE (*s))
160             ++s;
161           p = s;
162         }
163       else
164         ++s;
165     }
166   res = (char **)xrealloc (res, (i + 2) * sizeof (char *));
167   res[i] = strdupdelim (p, s);
168   res[i + 1] = NULL;
169   return res;
170 }
171 \f
172 /* Return pointer to a static char[] buffer in which zero-terminated
173    string-representation of TM (in form hh:mm:ss) is printed.  It is
174    shamelessly non-reentrant, but it doesn't matter, really.
175
176    If TM is non-NULL, the time_t of the current time will be stored
177    there.  */
178 char *
179 time_str (time_t *tm)
180 {
181   static char tms[15];
182   struct tm *ptm;
183   time_t tim;
184
185   *tms = '\0';
186   tim = time (tm);
187   if (tim == -1)
188     return tms;
189   ptm = localtime (&tim);
190   sprintf (tms, "%02d:%02d:%02d", ptm->tm_hour, ptm->tm_min, ptm->tm_sec);
191   return tms;
192 }
193
194 /* Returns an error message for ERRNUM.  #### This requires more work.
195    This function, as well as the whole error system, is very
196    ill-conceived.  */
197 const char *
198 uerrmsg (uerr_t errnum)
199 {
200   switch (errnum)
201     {
202     case URLUNKNOWN:
203       return _("Unknown/unsupported protocol");
204       break;
205     case URLBADPORT:
206       return _("Invalid port specification");
207       break;
208     case URLBADHOST:
209       return _("Invalid host name");
210       break;
211     default:
212       abort ();
213       /* $@#@#$ compiler.  */
214       return NULL;
215     }
216 }
217 \f
218 /* The Windows versions of the following two functions are defined in
219    mswindows.c.  */
220
221 /* A cuserid() immitation using getpwuid(), to avoid hassling with
222    utmp.  Besides, not all systems have cuesrid().  Under Windows, it
223    is defined in mswindows.c.
224
225    If WHERE is non-NULL, the username will be stored there.
226    Otherwise, it will be returned as a static buffer (as returned by
227    getpwuid()).  In the latter case, the buffer should be copied
228    before calling getpwuid() or pwd_cuserid() again.  */
229 #ifndef WINDOWS
230 char *
231 pwd_cuserid (char *where)
232 {
233   struct passwd *pwd;
234
235   if (!(pwd = getpwuid (getuid ())) || !pwd->pw_name)
236     return NULL;
237   if (where)
238     {
239       strcpy (where, pwd->pw_name);
240       return where;
241     }
242   else
243     return pwd->pw_name;
244 }
245
246 void
247 fork_to_background (void)
248 {
249   pid_t pid;
250   /* Whether we arrange our own version of opt.lfilename here.  */
251   int changedp = 0;
252
253   if (!opt.lfilename)
254     {
255       opt.lfilename = unique_name (DEFAULT_LOGFILE);
256       changedp = 1;
257     }
258   pid = fork ();
259   if (pid < 0)
260     {
261       /* parent, error */
262       perror ("fork");
263       exit (1);
264     }
265   else if (pid != 0)
266     {
267       /* parent, no error */
268       printf (_("Continuing in background.\n"));
269       if (changedp)
270         printf (_("Output will be written to `%s'.\n"), opt.lfilename);
271       exit (0);
272     }
273   /* child: keep running */
274 }
275 #endif /* not WINDOWS */
276 \f
277 /* Canonicalize PATH, and return a new path.  The new path differs from PATH
278    in that:
279         Multple `/'s are collapsed to a single `/'.
280         Leading `./'s and trailing `/.'s are removed.
281         Trailing `/'s are removed.
282         Non-leading `../'s and trailing `..'s are handled by removing
283         portions of the path.
284
285    E.g. "a/b/c/./../d/.." will yield "a/b".  This function originates
286    from GNU Bash.
287
288    Changes for Wget:
289         Always use '/' as stub_char.
290         Don't check for local things using canon_stat.
291         Change the original string instead of strdup-ing.
292         React correctly when beginning with `./' and `../'.  */
293 void
294 path_simplify (char *path)
295 {
296   register int i, start, ddot;
297   char stub_char;
298
299   if (!*path)
300     return;
301
302   /*stub_char = (*path == '/') ? '/' : '.';*/
303   stub_char = '/';
304
305   /* Addition: Remove all `./'-s preceding the string.  If `../'-s
306      precede, put `/' in front and remove them too.  */
307   i = 0;
308   ddot = 0;
309   while (1)
310     {
311       if (path[i] == '.' && path[i + 1] == '/')
312         i += 2;
313       else if (path[i] == '.' && path[i + 1] == '.' && path[i + 2] == '/')
314         {
315           i += 3;
316           ddot = 1;
317         }
318       else
319         break;
320     }
321   if (i)
322     strcpy (path, path + i - ddot);
323
324   /* Replace single `.' or `..' with `/'.  */
325   if ((path[0] == '.' && path[1] == '\0')
326       || (path[0] == '.' && path[1] == '.' && path[2] == '\0'))
327     {
328       path[0] = stub_char;
329       path[1] = '\0';
330       return;
331     }
332   /* Walk along PATH looking for things to compact.  */
333   i = 0;
334   while (1)
335     {
336       if (!path[i])
337         break;
338
339       while (path[i] && path[i] != '/')
340         i++;
341
342       start = i++;
343
344       /* If we didn't find any slashes, then there is nothing left to do.  */
345       if (!path[start])
346         break;
347
348       /* Handle multiple `/'s in a row.  */
349       while (path[i] == '/')
350         i++;
351
352       if ((start + 1) != i)
353         {
354           strcpy (path + start + 1, path + i);
355           i = start + 1;
356         }
357
358       /* Check for trailing `/'.  */
359       if (start && !path[i])
360         {
361         zero_last:
362           path[--i] = '\0';
363           break;
364         }
365
366       /* Check for `../', `./' or trailing `.' by itself.  */
367       if (path[i] == '.')
368         {
369           /* Handle trailing `.' by itself.  */
370           if (!path[i + 1])
371             goto zero_last;
372
373           /* Handle `./'.  */
374           if (path[i + 1] == '/')
375             {
376               strcpy (path + i, path + i + 1);
377               i = (start < 0) ? 0 : start;
378               continue;
379             }
380
381           /* Handle `../' or trailing `..' by itself.  */
382           if (path[i + 1] == '.' &&
383               (path[i + 2] == '/' || !path[i + 2]))
384             {
385               while (--start > -1 && path[start] != '/');
386               strcpy (path + start + 1, path + i + 2);
387               i = (start < 0) ? 0 : start;
388               continue;
389             }
390         }       /* path == '.' */
391     } /* while */
392
393   if (!*path)
394     {
395       *path = stub_char;
396       path[1] = '\0';
397     }
398 }
399 \f
400 /* "Touch" FILE, i.e. make its atime and mtime equal to the time
401    specified with TM.  */
402 void
403 touch (const char *file, time_t tm)
404 {
405 #ifdef HAVE_STRUCT_UTIMBUF
406   struct utimbuf times;
407   times.actime = times.modtime = tm;
408 #else
409   time_t times[2];
410   times[0] = times[1] = tm;
411 #endif
412
413   if (utime (file, &times) == -1)
414     logprintf (LOG_NOTQUIET, "utime(%s): %s\n", file, strerror (errno));
415 }
416
417 /* Checks if FILE is a symbolic link, and removes it if it is.  Does
418    nothing under MS-Windows.  */
419 int
420 remove_link (const char *file)
421 {
422   int err = 0;
423   struct stat st;
424
425   if (lstat (file, &st) == 0 && S_ISLNK (st.st_mode))
426     {
427       DEBUGP (("Unlinking %s (symlink).\n", file));
428       err = unlink (file);
429       if (err != 0)
430         logprintf (LOG_VERBOSE, _("Failed to unlink symlink `%s': %s\n"),
431                    file, strerror (errno));
432     }
433   return err;
434 }
435
436 /* Does FILENAME exist?  This is quite a lousy implementation, since
437    it supplies no error codes -- only a yes-or-no answer.  Thus it
438    will return that a file does not exist if, e.g., the directory is
439    unreadable.  I don't mind it too much currently, though.  The
440    proper way should, of course, be to have a third, error state,
441    other than true/false, but that would introduce uncalled-for
442    additional complexity to the callers.  */
443 int
444 file_exists_p (const char *filename)
445 {
446 #ifdef HAVE_ACCESS
447   return access (filename, F_OK) >= 0;
448 #else
449   struct stat buf;
450   return stat (filename, &buf) >= 0;
451 #endif
452 }
453
454 /* Returns 0 if PATH is a directory, 1 otherwise (any kind of file).
455    Returns 0 on error.  */
456 int
457 file_non_directory_p (const char *path)
458 {
459   struct stat buf;
460   /* Use lstat() rather than stat() so that symbolic links pointing to
461      directories can be identified correctly.  */
462   if (lstat (path, &buf) != 0)
463     return 0;
464   return S_ISDIR (buf.st_mode) ? 0 : 1;
465 }
466
467 /* Return a unique filename, given a prefix and count */
468 static char *
469 unique_name_1 (const char *fileprefix, int count)
470 {
471   char *filename;
472
473   if (count)
474     {
475       filename = (char *)xmalloc (strlen (fileprefix) + numdigit (count) + 2);
476       sprintf (filename, "%s.%d", fileprefix, count);
477     }
478   else
479     filename = xstrdup (fileprefix);
480
481   if (!file_exists_p (filename))
482     return filename;
483   else
484     {
485       free (filename);
486       return NULL;
487     }
488 }
489
490 /* Return a unique file name, based on PREFIX.  */
491 char *
492 unique_name (const char *prefix)
493 {
494   char *file = NULL;
495   int count = 0;
496
497   while (!file)
498     file = unique_name_1 (prefix, count++);
499   return file;
500 }
501 \f
502 /* Create DIRECTORY.  If some of the pathname components of DIRECTORY
503    are missing, create them first.  In case any mkdir() call fails,
504    return its error status.  Returns 0 on successful completion.
505
506    The behaviour of this function should be identical to the behaviour
507    of `mkdir -p' on systems where mkdir supports the `-p' option.  */
508 int
509 make_directory (const char *directory)
510 {
511   int quit = 0;
512   int i;
513   char *dir;
514
515   /* Make a copy of dir, to be able to write to it.  Otherwise, the
516      function is unsafe if called with a read-only char *argument.  */
517   STRDUP_ALLOCA (dir, directory);
518
519   /* If the first character of dir is '/', skip it (and thus enable
520      creation of absolute-pathname directories.  */
521   for (i = (*dir == '/'); 1; ++i)
522     {
523       for (; dir[i] && dir[i] != '/'; i++)
524         ;
525       if (!dir[i])
526         quit = 1;
527       dir[i] = '\0';
528       /* Check whether the directory already exists.  */
529       if (!file_exists_p (dir))
530         {
531           if (mkdir (dir, 0777) < 0)
532             return -1;
533         }
534       if (quit)
535         break;
536       else
537         dir[i] = '/';
538     }
539   return 0;
540 }
541 \f
542 static int in_acclist PARAMS ((const char *const *, const char *, int));
543
544 /* Determine whether a file is acceptable to be followed, according to
545    lists of patterns to accept/reject.  */
546 int
547 acceptable (const char *s)
548 {
549   int l = strlen (s);
550
551   while (l && s[l] != '/')
552     --l;
553   if (s[l] == '/')
554     s += (l + 1);
555   if (opt.accepts)
556     {
557       if (opt.rejects)
558         return (in_acclist ((const char *const *)opt.accepts, s, 1)
559                 && !in_acclist ((const char *const *)opt.rejects, s, 1));
560       else
561         return in_acclist ((const char *const *)opt.accepts, s, 1);
562     }
563   else if (opt.rejects)
564     return !in_acclist ((const char *const *)opt.rejects, s, 1);
565   return 1;
566 }
567
568 /* Compare S1 and S2 frontally; S2 must begin with S1.  E.g. if S1 is
569    `/something', frontcmp() will return 1 only if S2 begins with
570    `/something'.  Otherwise, 0 is returned.  */
571 int
572 frontcmp (const char *s1, const char *s2)
573 {
574   for (; *s1 && *s2 && (*s1 == *s2); ++s1, ++s2);
575   return !*s1;
576 }
577
578 /* Iterate through STRLIST, and return the first element that matches
579    S, through wildcards or front comparison (as appropriate).  */
580 static char *
581 proclist (char **strlist, const char *s, enum accd flags)
582 {
583   char **x;
584
585   for (x = strlist; *x; x++)
586     if (has_wildcards_p (*x))
587       {
588         if (fnmatch (*x, s, FNM_PATHNAME) == 0)
589           break;
590       }
591     else
592       {
593         char *p = *x + ((flags & ALLABS) && (**x == '/')); /* Remove '/' */
594         if (frontcmp (p, s))
595           break;
596       }
597   return *x;
598 }
599
600 /* Returns whether DIRECTORY is acceptable for download, wrt the
601    include/exclude lists.
602
603    If FLAGS is ALLABS, the leading `/' is ignored in paths; relative
604    and absolute paths may be freely intermixed.  */
605 int
606 accdir (const char *directory, enum accd flags)
607 {
608   /* Remove starting '/'.  */
609   if (flags & ALLABS && *directory == '/')
610     ++directory;
611   if (opt.includes)
612     {
613       if (!proclist (opt.includes, directory, flags))
614         return 0;
615     }
616   if (opt.excludes)
617     {
618       if (proclist (opt.excludes, directory, flags))
619         return 0;
620     }
621   return 1;
622 }
623
624 /* Match the end of STRING against PATTERN.  For instance:
625
626    match_backwards ("abc", "bc") -> 1
627    match_backwards ("abc", "ab") -> 0
628    match_backwards ("abc", "abc") -> 1 */
629 static int
630 match_backwards (const char *string, const char *pattern)
631 {
632   int i, j;
633
634   for (i = strlen (string), j = strlen (pattern); i >= 0 && j >= 0; i--, j--)
635     if (string[i] != pattern[j])
636       break;
637   /* If the pattern was exhausted, the match was succesful.  */
638   if (j == -1)
639     return 1;
640   else
641     return 0;
642 }
643
644 /* Checks whether string S matches each element of ACCEPTS.  A list
645    element are matched either with fnmatch() or match_backwards(),
646    according to whether the element contains wildcards or not.
647
648    If the BACKWARD is 0, don't do backward comparison -- just compare
649    them normally.  */
650 static int
651 in_acclist (const char *const *accepts, const char *s, int backward)
652 {
653   for (; *accepts; accepts++)
654     {
655       if (has_wildcards_p (*accepts))
656         {
657           /* fnmatch returns 0 if the pattern *does* match the
658              string.  */
659           if (fnmatch (*accepts, s, 0) == 0)
660             return 1;
661         }
662       else
663         {
664           if (backward)
665             {
666               if (match_backwards (s, *accepts))
667                 return 1;
668             }
669           else
670             {
671               if (!strcmp (s, *accepts))
672                 return 1;
673             }
674         }
675     }
676   return 0;
677 }
678
679 /* Return the malloc-ed suffix of STR.  For instance:
680    suffix ("foo.bar")       -> "bar"
681    suffix ("foo.bar.baz")   -> "baz"
682    suffix ("/foo/bar")      -> NULL
683    suffix ("/foo.bar/baz")  -> NULL  */
684 char *
685 suffix (const char *str)
686 {
687   int i;
688
689   for (i = strlen (str); i && str[i] != '/' && str[i] != '.'; i--);
690   if (str[i++] == '.')
691     return xstrdup (str + i);
692   else
693     return NULL;
694 }
695
696 /* Read a line from FP.  The function reallocs the storage as needed
697    to accomodate for any length of the line.  Reallocs are done
698    storage exponentially, doubling the storage after each overflow to
699    minimize the number of calls to realloc().
700
701    It is not an exemplary of correctness, since it kills off the
702    newline (and no, there is no way to know if there was a newline at
703    EOF).  */
704 char *
705 read_whole_line (FILE *fp)
706 {
707   char *line;
708   int i, bufsize, c;
709
710   i = 0;
711   bufsize = 40;
712   line = (char *)xmalloc (bufsize);
713   /* Construct the line.  */
714   while ((c = getc (fp)) != EOF && c != '\n')
715     {
716       if (i > bufsize - 1)
717         line = (char *)xrealloc (line, (bufsize <<= 1));
718       line[i++] = c;
719     }
720   if (c == EOF && !i)
721     {
722       free (line);
723       return NULL;
724     }
725   /* Check for overflow at zero-termination (no need to double the
726      buffer in this case.  */
727   if (i == bufsize)
728     line = (char *)xrealloc (line, i + 1);
729   line[i] = '\0';
730   return line;
731 }
732
733 /* Load file pointed to by FP to memory and return the malloc-ed
734    buffer with the contents.  *NREAD will contain the number of read
735    bytes.  The file is loaded in chunks, allocated exponentially,
736    starting with FILE_BUFFER_SIZE bytes.  */
737 void
738 load_file (FILE *fp, char **buf, long *nread)
739 {
740   long bufsize;
741
742   bufsize = 512;
743   *nread = 0;
744   *buf = NULL;
745   while (!feof (fp) && !ferror (fp))
746     {
747       *buf = (char *)xrealloc (*buf, bufsize + *nread);
748       *nread += fread (*buf + *nread, sizeof (char), bufsize, fp);
749       bufsize <<= 1;
750     }
751   /* #### No indication of encountered error??  */
752 }
753
754 /* Free the pointers in a NULL-terminated vector of pointers, then
755    free the pointer itself.  */
756 void
757 free_vec (char **vec)
758 {
759   if (vec)
760     {
761       char **p = vec;
762       while (*p)
763         free (*p++);
764       free (vec);
765     }
766 }
767
768 /* Append vector V2 to vector V1.  The function frees V2 and
769    reallocates V1 (thus you may not use the contents of neither
770    pointer after the call).  If V1 is NULL, V2 is returned.  */
771 char **
772 merge_vecs (char **v1, char **v2)
773 {
774   int i, j;
775
776   if (!v1)
777     return v2;
778   if (!v2)
779     return v1;
780   if (!*v2)
781     {
782       /* To avoid j == 0 */
783       free (v2);
784       return v1;
785     }
786   /* Count v1.  */
787   for (i = 0; v1[i]; i++);
788   /* Count v2.  */
789   for (j = 0; v2[j]; j++);
790   /* Reallocate v1.  */
791   v1 = (char **)xrealloc (v1, (i + j + 1) * sizeof (char **));
792   memcpy (v1 + i, v2, (j + 1) * sizeof (char *));
793   free (v2);
794   return v1;
795 }
796
797 /* A set of simple-minded routines to store and search for strings in
798    a linked list.  You may add a string to the slist, and peek whether
799    it's still in there at any time later.  */
800
801 /* Add an element to the list.  If flags is NOSORT, the list will not
802    be sorted.  */
803 slist *
804 add_slist (slist *l, const char *s, int flags)
805 {
806   slist *t, *old, *beg;
807   int cmp;
808
809   if (flags & NOSORT)
810     {
811       if (!l)
812         {
813           t = (slist *)xmalloc (sizeof (slist));
814           t->string = xstrdup (s);
815           t->next = NULL;
816           return t;
817         }
818       beg = l;
819       /* Find the last element.  */
820       while (l->next)
821         l = l->next;
822       t = (slist *)xmalloc (sizeof (slist));
823       l->next = t;
824       t->string = xstrdup (s);
825       t->next = NULL;
826       return beg;
827     }
828   /* Empty list or changing the first element.  */
829   if (!l || (cmp = strcmp (l->string, s)) > 0)
830     {
831       t = (slist *)xmalloc (sizeof (slist));
832       t->string = xstrdup (s);
833       t->next = l;
834       return t;
835     }
836
837   beg = l;
838   if (cmp == 0)
839     return beg;
840
841   /* Second two one-before-the-last element.  */
842   while (l->next)
843     {
844       old = l;
845       l = l->next;
846       cmp = strcmp (s, l->string);
847       if (cmp == 0)             /* no repeating in the list */
848         return beg;
849       else if (cmp > 0)
850         continue;
851       /* If the next list element is greater than s, put s between the
852          current and the next list element.  */
853       t = (slist *)xmalloc (sizeof (slist));
854       old->next = t;
855       t->next = l;
856       t->string = xstrdup (s);
857       return beg;
858     }
859   t = (slist *)xmalloc (sizeof (slist));
860   t->string = xstrdup (s);
861   /* Insert the new element after the last element.  */
862   l->next = t;
863   t->next = NULL;
864   return beg;
865 }
866
867 /* Is there a specific entry in the list?  */
868 int
869 in_slist (slist *l, const char *s)
870 {
871   int cmp;
872
873   while (l)
874     {
875       cmp = strcmp (l->string, s);
876       if (cmp == 0)
877         return 1;
878       else if (cmp > 0)         /* the list is ordered!  */
879         return 0;
880       l = l->next;
881     }
882   return 0;
883 }
884
885 /* Free the whole slist.  */
886 void
887 free_slist (slist *l)
888 {
889   slist *n;
890
891   while (l)
892     {
893       n = l->next;
894       free (l->string);
895       free (l);
896       l = n;
897     }
898 }
899 \f
900 /* Engine for legible and legible_long_long; this function works on
901    strings.  */
902
903 static char *
904 legible_1 (const char *repr)
905 {
906   static char outbuf[128];
907   int i, i1, mod;
908   char *outptr;
909   const char *inptr;
910
911   /* Reset the pointers.  */
912   outptr = outbuf;
913   inptr = repr;
914   /* If the number is negative, shift the pointers.  */
915   if (*inptr == '-')
916     {
917       *outptr++ = '-';
918       ++inptr;
919     }
920   /* How many digits before the first separator?  */
921   mod = strlen (inptr) % 3;
922   /* Insert them.  */
923   for (i = 0; i < mod; i++)
924     *outptr++ = inptr[i];
925   /* Now insert the rest of them, putting separator before every
926      third digit.  */
927   for (i1 = i, i = 0; inptr[i1]; i++, i1++)
928     {
929       if (i % 3 == 0 && i1 != 0)
930         *outptr++ = ',';
931       *outptr++ = inptr[i1];
932     }
933   /* Zero-terminate the string.  */
934   *outptr = '\0';
935   return outbuf;
936 }
937
938 /* Legible -- return a static pointer to the legibly printed long.  */
939 char *
940 legible (long l)
941 {
942   char inbuf[24];
943   /* Print the number into the buffer.  */
944   long_to_string (inbuf, l);
945   return legible_1 (inbuf);
946 }
947
948 /* The same as legible(), but works on VERY_LONG_TYPE.  See sysdep.h.  */
949 char *
950 legible_very_long (VERY_LONG_TYPE l)
951 {
952   char inbuf[128];
953   /* Print the number into the buffer.  */
954   sprintf (inbuf, VERY_LONG_FORMAT, l);
955   return legible_1 (inbuf);
956 }
957
958 /* Count the digits in a (long) integer.  */
959 int
960 numdigit (long a)
961 {
962   int res = 1;
963   while ((a /= 10) != 0)
964     ++res;
965   return res;
966 }
967
968 /* Print NUMBER to BUFFER.  This is equivalent to sprintf(buffer,
969    "%ld", number), only much faster.
970
971    BUFFER should accept 24 bytes.  This should suffice for the longest
972    numbers on 64-bit machines, including the `-' sign and the trailing
973    \0.  */
974 void
975 long_to_string (char *buffer, long number)
976 {
977 #if (SIZEOF_LONG != 4) && (SIZEOF_LONG != 8)
978   /* Huh? */
979   sprintf (buffer, "%ld", number);
980 #else /* (SIZEOF_LONG == 4) || (SIZEOF_LONG == 8) */
981   char *p = buffer;
982   int force = 0;
983
984   if (number < 0)
985     {
986       *p++ = '-';
987       number = -number;
988     }
989
990 #define FROB(figure) do {                                               \
991     if (force || number >= figure)                                      \
992       *p++ = number / figure + '0', number %= figure, force = 1;        \
993     } while (0)
994 #if SIZEOF_LONG == 8
995   FROB (1000000000000000000L);
996   FROB (100000000000000000L);
997   FROB (10000000000000000L);
998   FROB (1000000000000000L);
999   FROB (100000000000000L);
1000   FROB (10000000000000L);
1001   FROB (1000000000000L);
1002   FROB (100000000000L);
1003   FROB (10000000000L);
1004 #endif /* SIZEOF_LONG == 8 */
1005   FROB (1000000000);
1006   FROB (100000000);
1007   FROB (10000000);
1008   FROB (1000000);
1009   FROB (100000);
1010   FROB (10000);
1011   FROB (1000);
1012   FROB (100);
1013   FROB (10);
1014 #undef FROB
1015   *p++ = number + '0';
1016   *p = '\0';
1017 #endif /* (SIZEOF_LONG == 4) || (SIZEOF_LONG == 8) */
1018 }