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