home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / prgtools / mint / shells / bashsrc.zoo / general.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-06-05  |  10.8 KB  |  500 lines

  1. /* general.c -- Stuff that is used by all files. */
  2.  
  3. /* Copyright (C) 1987,1989 Free Software Foundation, Inc.
  4.  
  5. This file is part of GNU Bash, the Bourne Again SHell.
  6.  
  7. Bash is free software; you can redistribute it and/or modify it under
  8. the terms of the GNU General Public License as published by the Free
  9. Software Foundation; either version 1, or (at your option) any later
  10. version.
  11.  
  12. Bash is distributed in the hope that it will be useful, but WITHOUT ANY
  13. WARRANTY; without even the implied warranty of MERCHANTABILITY or
  14. FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  15. for more details.
  16.  
  17. You should have received a copy of the GNU General Public License along
  18. with Bash; see the file COPYING.  If not, write to the Free Software
  19. Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
  20.  
  21. #include <stdio.h>
  22. #include <errno.h>
  23.  
  24. #include "shell.h"
  25. #ifdef SYSV
  26. #include <string.h>
  27. #else
  28. #include <strings.h>
  29. #endif  /* SYSV */
  30.  
  31. #ifndef NULL
  32. #define NULL 0x0
  33. #endif
  34.  
  35.  
  36. #if !defined (rindex)
  37. extern char *rindex ();
  38. #endif
  39.  
  40. /* **************************************************************** */
  41. /*                                    */
  42. /*           Memory Allocation and Deallocation.            */
  43. /*                                    */
  44. /* **************************************************************** */
  45.  
  46. char *
  47. xmalloc (size)
  48.      int size;
  49. {
  50.   register char *temp = (char *)malloc (size);
  51.   if (!temp)
  52.     fatal_error ("Out of virtual memory!");
  53.   return (temp);
  54. }
  55.  
  56. char *
  57. xrealloc (pointer, size)
  58.      register char *pointer;
  59.      int size;
  60. {
  61.   pointer = (char *)realloc (pointer, size);
  62.   if (!pointer)
  63.     fatal_error ("Out of virtual memory!");
  64.   return (pointer);
  65. }
  66.  
  67.  
  68. /* **************************************************************** */
  69. /*                                    */
  70. /*            Generic List Functions                */
  71. /*                                    */
  72. /* **************************************************************** */
  73.  
  74. /* Call FUNCTION on every member of LIST, a generic list. */
  75. map_over_list (list, function)
  76.      GENERIC_LIST *list;
  77.      Function *function;
  78. {
  79.   while (list) {
  80.     (*function) (list);
  81.     list = list->next;
  82.   }
  83. }
  84.  
  85. /* Call FUNCTION on every string in WORDS. */
  86. map_over_words (words, function)
  87.      WORD_LIST *words;
  88.      Function *function;
  89. {
  90.   while (words) {
  91.     (*function)(words->word->word);
  92.     words = words->next;
  93.   }
  94. }
  95.  
  96. /* Reverse the chain of structures in LIST.  Output the new head
  97.    of the chain.  You should always assign the output value of this
  98.    function to something, or you will lose the chain. */
  99. GENERIC_LIST *
  100. reverse_list (list)
  101.      register GENERIC_LIST *list;
  102. {
  103.   register GENERIC_LIST *next, *prev = (GENERIC_LIST *)NULL;
  104.  
  105.   while (list) {
  106.     next = list->next;
  107.     list->next = prev;
  108.     prev = list;
  109.     list = next;
  110.   }
  111.   return (prev);
  112. }
  113.  
  114. /* Return the number of elements in LIST, a generic list. */
  115. list_length (list)
  116.      register GENERIC_LIST *list;
  117. {
  118.   register int i;
  119.  
  120.   for (i = 0; list; list = list->next, i++);
  121.   return (i);
  122. }
  123.  
  124. /* Delete the element of LIST which satisfies the predicate function COMPARER.
  125.    Returns the element that was deleted, so you can dispose of it, or -1 if
  126.    the element wasn't found.  COMPARER is called with the list element and
  127.    then ARG.  Note that LIST contains the address of a variable which points
  128.    to the list.  You might call this function like this:
  129.    
  130.    SHELL_VAR *elt = delete_element (&variable_list, check_var_has_name, "foo");
  131.    dispose_variable (elt);
  132. */
  133. GENERIC_LIST *
  134. delete_element (list, comparer, arg)
  135.      GENERIC_LIST **list;
  136.      Function *comparer;
  137. {
  138.   register GENERIC_LIST *prev = (GENERIC_LIST *)NULL;
  139.   register GENERIC_LIST *temp = *list;
  140.  
  141.   while (temp) {
  142.     if ((*comparer) (temp, arg)) {
  143.       if (prev) prev->next = temp->next;
  144.       else *list = temp->next;
  145.       return (temp);
  146.     }
  147.     prev = temp;
  148.     temp = temp->next;
  149.   }
  150.   return ((GENERIC_LIST *)-1);
  151. }
  152.  
  153. /* Find NAME in ARRAY.  Return the index of NAME, or -1 if not present.
  154.    ARRAY shoudl be NULL terminated. */
  155. find_name_in_list (name, array)
  156.      char *name, *array[];
  157. {
  158.   int i;
  159.  
  160.   for (i=0; array[i]; i++)
  161.     if (strcmp (name, array[i]) == 0)
  162.       return (i);
  163.  
  164.   return (-1);
  165. }
  166.  
  167. /* Return the length of ARRAY, a NULL terminated array of char *. */
  168. array_len (array)
  169.      register char **array;
  170. {
  171.   register int i;
  172.   for (i=0; array[i]; i++);
  173.   return (i);
  174. }
  175.  
  176. /* Free the contents of ARRAY, a NULL terminated array of char *. */
  177. free_array (array)
  178.      register char **array;
  179. {
  180.   register int i = 0;
  181.  
  182.   if (!array) return;
  183.  
  184.   while (array[i]) free (array[i++]);
  185.   free (array);
  186. }
  187.  
  188. /* Append LIST2 to LIST1.  Return the header of the list. */
  189. GENERIC_LIST *
  190. list_append (head, tail)
  191.      GENERIC_LIST *head, *tail;
  192. {
  193.   register GENERIC_LIST *t_head = head;
  194.  
  195.   if (!t_head)
  196.     return (tail);
  197.  
  198.   while (t_head->next) t_head = t_head->next;
  199.   t_head->next = tail;
  200.   return (head);
  201. }
  202.  
  203. /* Some random string stuff. */
  204.  
  205. /* Remove all leading whitespace from STRING.  This includes
  206.    newlines.  STRING should be terminated with a zero. */
  207. strip_leading (string)
  208.      char *string;
  209. {
  210.   char *start = string;
  211.  
  212.   while (*string && (whitespace (*string) || *string == '\n')) string++;
  213.  
  214.   if (string != start) {
  215.     int len = strlen (string);
  216.     bcopy (string, start, len);
  217.     start[len] = '\0';
  218.   }
  219. }
  220.  
  221. /* Remove all trailing whitespace from STRING.  This includes
  222.    newlines.  STRING should be terminated with a zero. */
  223. strip_trailing (string)
  224.      char *string;
  225. {
  226.   int len = strlen (string);
  227.  
  228.   while (len--)
  229.     if (!whitespace (string[len]) && string[len] != '\n') {
  230.       string[len + 1] = '\0';
  231.       return;
  232.     }
  233. }
  234.  
  235. /* Turn STRING (a pathname) into an absolute pathname, assuming that
  236.    DOT_PATH contains the symbolic location of '.'.  This always
  237.    returns a new string, even if STRING was an absolute pathname to
  238.    begin with. */
  239.  
  240. #ifndef MAXPATHLEN
  241. #define MAXPATHLEN 1024
  242. #endif
  243.  
  244. static char current_path[MAXPATHLEN];
  245.  
  246. char *
  247. make_absolute (string, dot_path)
  248.      char *string, *dot_path;
  249. {
  250.   register char *cp;
  251.  
  252.   if (!dot_path || *string == '/')
  253.     return (savestring (string));
  254.  
  255.   strcpy (current_path, dot_path);
  256.  
  257.   if (!current_path[0])
  258.     strcpy (current_path, "./");
  259.  
  260.   cp = current_path + (strlen (current_path) - 1);
  261.  
  262.   if (*cp++ != '/')
  263.     *cp++ = '/';
  264.  
  265.   *cp = '\0';
  266.  
  267.   while (*string)
  268.     {
  269.       if (*string == '.')
  270.     {
  271.       if (!string[1])
  272.         return (savestring (current_path));
  273.  
  274.       if (string[1] == '/')
  275.         {
  276.           string += 2;
  277.           continue;
  278.         }
  279.  
  280.       if (string[1] == '.' && (string[2] == '/' || !string[2]))
  281.         {
  282.           string += 2;
  283.  
  284.           if (*string)
  285.         string++;
  286.  
  287.           pathname_backup (current_path, 1);
  288.           cp = current_path + strlen (current_path);
  289.           continue;
  290.         }
  291.     }
  292.  
  293.       while (*string && *string != '/')
  294.     *cp++ = *string++;
  295.  
  296.       if (*string)
  297.     *cp++ = *string++;
  298.  
  299.       *cp = '\0';
  300.     }
  301.   return (savestring (current_path));
  302. }
  303.  
  304. /* Remove the last N directories from PATH.  Do not leave a blank path.
  305.    PATH must contain enough space for MAXPATHLEN characters. */
  306. pathname_backup (path, n)
  307.      char *path;
  308.      int n;
  309. {
  310.   register char *p = path + strlen (path);
  311.  
  312.   if (*path)
  313.     p--;
  314.  
  315.   while (n--)
  316.     {
  317.       while (*p == '/')
  318.     p--;
  319.  
  320.       while (*p != '/')
  321.     p--;
  322.  
  323.       *++p = '\0';
  324.     }
  325. }
  326.  
  327. /* Return 1 if STRING contains an absolute pathname, else 0. */
  328. absolute_pathname (string)
  329.      char *string;
  330. {
  331.   if (!string || !strlen (string))
  332.     return (0);
  333.  
  334.   if (*string == '/')
  335.     return (1);
  336.  
  337.   if (*string++ == '.')
  338.     {
  339.       if ((!*string) || *string == '/')
  340.     return (1);
  341.  
  342.       if (*string++ == '.')
  343.     if (!*string || *string == '/')
  344.       return (1);
  345.     }
  346.   return (0);
  347. }
  348.  
  349. /* Return the `basename' of the pathname in STRING (the stuff after the
  350.    last '/').  If STRING is not a full pathname, simply return it. */
  351. char *
  352. base_pathname (string)
  353.      char *string;
  354. {
  355.   char *p = rindex (string, '/');
  356.  
  357.   if (*string != '/')
  358.     return (string);
  359.  
  360.   if (p)
  361.     return (++p);
  362.   else
  363.     return (string);
  364. }
  365.  
  366. /* Determine if s2 occurs in s1.  If so, return a pointer to the
  367.    match in s1.  The compare is case insensitive. */
  368. char *
  369. strindex (s1, s2)
  370.      register char *s1, *s2;
  371. {
  372.   register int i, l = strlen (s2);
  373.   register int len = strlen (s1);
  374.  
  375.   for (i = 0; (len - i) >= l; i++)
  376.     if (strnicmp (&s1[i], s2, l) == 0)
  377.       return (s1 + i);
  378.   return ((char *)NULL);
  379. }
  380.  
  381.  
  382. #ifndef to_upper
  383. #define lowercase_p(c) (((c) > ('a' - 1) && (c) < ('z' + 1)))
  384. #define uppercase_p(c) (((c) > ('A' - 1) && (c) < ('Z' + 1)))
  385. #define pure_alphabetic(c) (lowercase_p(c) || uppercase_p(c))
  386. #define to_upper(c) (lowercase_p(c) ? ((c) - 32) : (c))
  387. #define to_lower(c) (uppercase_p(c) ? ((c) + 32) : (c))
  388. #endif
  389.  
  390. /* Compare at most COUNT characters from string1 to string2.  Case
  391.    doesn't matter. */
  392. int
  393. strnicmp (string1, string2, count)
  394.      char *string1, *string2;
  395. {
  396.   register char ch1, ch2;
  397.  
  398.   while (count) {
  399.     ch1 = *string1++;
  400.     ch2 = *string2++;
  401.     if (to_upper(ch1) == to_upper(ch2))
  402.       count--;
  403.     else break;
  404.   }
  405.   return (count);
  406. }
  407.  
  408. /* strcmp (), but caseless. */
  409. int
  410. stricmp (string1, string2)
  411.      char *string1, *string2;
  412. {
  413.   register char ch1, ch2;
  414.  
  415.   while (*string1 && *string2) {
  416.     ch1 = *string1++;
  417.     ch2 = *string2++;
  418.     if (to_upper(ch1) != to_upper(ch2))
  419.       return (1);
  420.   }
  421.   return (*string1 | *string2);
  422. }
  423.  
  424. #if defined (SONY)
  425.  
  426. char *
  427. strchr (s, c)
  428.      char *s;
  429.      int c;
  430. {
  431.   char *index ();
  432.   return (index (s, c));
  433. }
  434.  
  435. #endif /* SONY */
  436.  
  437. extern int errno;
  438. #include <errno.h>
  439. #include <fcntl.h>
  440.  
  441. #ifdef NO_DUP2
  442. dup2 (fd1, fd2)
  443.      int fd1, fd2;
  444. {
  445.   if (fcntl (fd1, F_GETFL, 0) == -1)    /* fd1 is an invalid fd */
  446.     return (-1);
  447.   if (fd2 < 0 || fd2 >= NOFILE)
  448.     {
  449.       errno = EBADF;
  450.       return (-1);
  451.     }
  452.   if (fd1 == fd2)
  453.     return (0);
  454.   (void) close (fd2);
  455.   return (fcntl (fd1, F_DUPFD, fd2));
  456. }
  457. #endif /* NO_DUP */
  458.  
  459. #ifdef SYSV
  460. #include <sys/utsname.h>
  461. bcopy(s,d,n) char *d,*s; { while(n--) *d++ = *s++; }
  462. char *getwd(s) char *s; { getcwd(s,MAXPATHLEN); return s; }
  463. char *index(s,c) char *s; { char *strchr(); return strchr(s,c); }
  464. char *rindex(s,c) char *s; { char *strrchr(); return strrchr(s,c); }
  465.      
  466. gethostname (name, namelen) 
  467.      char *name;
  468.      int namelen;
  469. {
  470.   int i;
  471.   struct utsname uts;
  472.  
  473.   --namelen;
  474.  
  475.   uname (&uts);
  476.   i = strlen (uts.nodename) + 1;
  477.   strncpy (name, uts.nodename, i < namelen ? i : namelen);
  478.   name[namelen] = '\0';
  479.   return (0);
  480. }
  481.  
  482. int
  483. sysv_getc (stream)
  484.      FILE *stream;
  485. {
  486.   int result;
  487.   char c;
  488.  
  489.   while (1)
  490.     {
  491.       result = read (fileno (stream), &c, sizeof (char));
  492.       if (result == sizeof (char))
  493.     return (c);
  494.  
  495.       if (errno != EINTR)
  496.     return (EOF);
  497.     }
  498. }
  499. #endif  /* SYSV */
  500.