Annotation of GNUtools/debug/gdb/glob/tilde.c, revision 1.1.1.1

1.1       root        1: /* tilde.c -- Tilde expansion code (~/foo := $HOME/foo). */
                      2: 
                      3: /* Copyright (C) 1988,1989, 1991 Free Software Foundation, Inc.
                      4: 
                      5:    This file is part of GNU Readline, a library for reading lines
                      6:    of text with interactive input and history editing.
                      7: 
                      8:    Readline is free software; you can redistribute it and/or modify
                      9:    it under the terms of the GNU General Public License as published by
                     10:    the Free Software Foundation; either version 2 of the License, or
                     11:    (at your option) any later version.
                     12: 
                     13:    Readline is distributed in the hope that it will be useful,
                     14:    but WITHOUT ANY WARRANTY; without even the implied warranty of
                     15:    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     16:    GNU General Public License for more details.
                     17: 
                     18:    You should have received a copy of the GNU General Public License
                     19:    along with this program; if not, write to the Free Software
                     20:    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
                     21: 
                     22: #include "sysdep.h"
                     23: 
                     24: #ifndef __MSDOS__
                     25: #include <pwd.h>
                     26: #endif
                     27: 
                     28: #ifdef __GNUC__
                     29: #undef alloca
                     30: #define alloca(x) __builtin_alloca(x)
                     31: #endif
                     32: 
                     33: #ifndef savestring
                     34: #ifdef xmalloc
                     35: #define savestring(x) (char *)strcpy ((char *)malloc (1 + strlen (x)), (x))
                     36: #else
                     37: #define savestring(x) (char *)strcpy (xmalloc (1 + strlen (x)), (x))
                     38: #endif /* xmalloc */
                     39: #endif
                     40: 
                     41: typedef int Function ();
                     42: #if !defined (NULL)
                     43: #  define NULL 0x0
                     44: #endif
                     45: 
                     46: #ifndef xmalloc
                     47: #if defined (TEST)
                     48: static char *xmalloc (), *xrealloc ();
                     49: #else
                     50: extern char *xmalloc (), *xrealloc ();
                     51: #endif /* TEST */
                     52: #endif /* !xmalloc */
                     53: 
                     54: /* The default value of tilde_additional_prefixes.  This is set to
                     55:    whitespace preceding a tilde so that simple programs which do not
                     56:    perform any word separation get desired behaviour. */
                     57: static char *default_prefixes[] =
                     58:   { " ~", "\t~", (char *)NULL };
                     59: 
                     60: /* The default value of tilde_additional_suffixes.  This is set to
                     61:    whitespace or newline so that simple programs which do not
                     62:    perform any word separation get desired behaviour. */
                     63: static char *default_suffixes[] =
                     64:   { " ", "\n", (char *)NULL };
                     65: 
                     66: /* If non-null, this contains the address of a function to call if the
                     67:    standard meaning for expanding a tilde fails.  The function is called
                     68:    with the text (sans tilde, as in "foo"), and returns a malloc()'ed string
                     69:    which is the expansion, or a NULL pointer if there is no expansion. */
                     70: Function *tilde_expansion_failure_hook = (Function *)NULL;
                     71: 
                     72: /* When non-null, this is a NULL terminated array of strings which
                     73:    are duplicates for a tilde prefix.  Bash uses this to expand
                     74:    `=~' and `:~'. */
                     75: char **tilde_additional_prefixes = default_prefixes;
                     76: 
                     77: /* When non-null, this is a NULL terminated array of strings which match
                     78:    the end of a username, instead of just "/".  Bash sets this to
                     79:    `:' and `=~'. */
                     80: char **tilde_additional_suffixes = default_suffixes;
                     81: 
                     82: /* Find the start of a tilde expansion in STRING, and return the index of
                     83:    the tilde which starts the expansion.  Place the length of the text
                     84:    which identified this tilde starter in LEN, excluding the tilde itself. */
                     85: static int
                     86: tilde_find_prefix (string, len)
                     87:      char *string;
                     88:      int *len;
                     89: {
                     90:   register int i, j, string_len;
                     91:   register char **prefixes = tilde_additional_prefixes;
                     92: 
                     93:   string_len = strlen (string);
                     94:   *len = 0;
                     95: 
                     96:   if (!*string || *string == '~')
                     97:     return (0);
                     98: 
                     99:   if (prefixes)
                    100:     {
                    101:       for (i = 0; i < string_len; i++)
                    102:        {
                    103:          for (j = 0; prefixes[j]; j++)
                    104:            {
                    105:              if (strncmp (string + i, prefixes[j], strlen (prefixes[j])) == 0)
                    106:                {
                    107:                  *len = strlen (prefixes[j]) - 1;
                    108:                  return (i + *len);
                    109:                }
                    110:            }
                    111:        }
                    112:     }
                    113:   return (string_len);
                    114: }
                    115: 
                    116: /* Find the end of a tilde expansion in STRING, and return the index of
                    117:    the character which ends the tilde definition.  */
                    118: static int
                    119: tilde_find_suffix (string)
                    120:      char *string;
                    121: {
                    122:   register int i, j, string_len;
                    123:   register char **suffixes = tilde_additional_suffixes;
                    124: 
                    125:   string_len = strlen (string);
                    126: 
                    127:   for (i = 0; i < string_len; i++)
                    128:     {
                    129:       if (string[i] == '/' || !string[i])
                    130:        break;
                    131: 
                    132:       for (j = 0; suffixes && suffixes[j]; j++)
                    133:        {
                    134:          if (strncmp (string + i, suffixes[j], strlen (suffixes[j])) == 0)
                    135:            return (i);
                    136:        }
                    137:     }
                    138:   return (i);
                    139: }
                    140: 
                    141: /* Return a new string which is the result of tilde expanding FILENAME. */
                    142: char *
                    143: tilde_expand (filename)
                    144:      char *filename;
                    145: {
                    146:   char *result, *tilde_expand_word ();
                    147:   int result_size, result_index;
                    148: 
                    149:   result_size = result_index = 0;
                    150:   result = (char *)NULL;
                    151: 
                    152:   /* Scan through FILENAME expanding tildes as we come to them. */
                    153:   while (1)
                    154:     {
                    155:       register int start, end;
                    156:       char *tilde_word, *expansion;
                    157:       int len;
                    158: 
                    159:       /* Make START point to the tilde which starts the expansion. */
                    160:       start = tilde_find_prefix (filename, &len);
                    161: 
                    162:       /* Copy the skipped text into the result. */
                    163:       /* This test is always true the first time, since result_index
                    164:         is 0, result_size is 0, and start is >= 0.  So we malloc here.  */
                    165:       if ((result_index + start + 1) > result_size) {
                    166:        result_size += (start + 20);
                    167:        if (result == NULL)
                    168:          result = (char *)xmalloc  (        1 + result_size);
                    169:        else
                    170:          result = (char *)xrealloc (result, 1 + result_size);
                    171:       }
                    172: 
                    173:       strncpy (result + result_index, filename, start);
                    174:       result_index += start;
                    175: 
                    176:       /* Advance FILENAME upto the starting tilde. */
                    177:       filename += start;
                    178: 
                    179:       /* Make END be the index of one after the last character of the
                    180:         username. */
                    181:       end = tilde_find_suffix (filename);
                    182: 
                    183:       /* If both START and END are zero, we are all done. */
                    184:       if (!start && !end)
                    185:        break;
                    186: 
                    187:       /* Expand the entire tilde word, and copy it into RESULT. */
                    188:       tilde_word = (char *)xmalloc (1 + end);
                    189:       strncpy (tilde_word, filename, end);
                    190:       tilde_word[end] = '\0';
                    191:       filename += end;
                    192: 
                    193:       expansion = tilde_expand_word (tilde_word);
                    194:       free (tilde_word);
                    195: 
                    196:       len = strlen (expansion);
                    197:       if ((result_index + len + 1) > result_size)
                    198:        result = (char *)xrealloc (result, 1 + (result_size += (len + 20)));
                    199: 
                    200:       strcpy (result + result_index, expansion);
                    201:       result_index += len;
                    202:       free (expansion);
                    203:     }
                    204: 
                    205:   result[result_index] = '\0';
                    206: 
                    207:   return (result);
                    208: }
                    209: 
                    210: /* Do the work of tilde expansion on FILENAME.  FILENAME starts with a
                    211:    tilde.  If there is no expansion, call tilde_expansion_failure_hook. */
                    212: char *
                    213: tilde_expand_word (filename)
                    214:      char *filename;
                    215: {
                    216:   char *dirname = filename ? savestring (filename) : (char *)NULL;
                    217: 
                    218:   if (dirname && *dirname == '~')
                    219:     {
                    220:       char *temp_name;
                    221:       if (!dirname[1] || dirname[1] == '/')
                    222:        {
                    223:          /* Prepend $HOME to the rest of the string. */
                    224:          char *temp_home = (char *)getenv ("HOME");
                    225: 
                    226:          temp_name = (char *)alloca (1 + strlen (&dirname[1])
                    227:                                      + (temp_home? strlen (temp_home) : 0));
                    228:          temp_name[0] = '\0';
                    229:          if (temp_home)
                    230:            strcpy (temp_name, temp_home);
                    231:          strcat (temp_name, &dirname[1]);
                    232:          free (dirname);
                    233:          dirname = savestring (temp_name);
                    234:        }
                    235:       else
                    236:        {
                    237: #ifndef __MSDOS__
                    238:          struct passwd *getpwnam (), *user_entry;
                    239: #endif
                    240:          char *username = (char *)alloca (257);
                    241:          int i, c;
                    242: 
                    243:          for (i = 1; c = dirname[i]; i++)
                    244:            {
                    245:              if (c == '/')
                    246:                break;
                    247:              else
                    248:                username[i - 1] = c;
                    249:            }
                    250:          username[i - 1] = '\0';
                    251: 
                    252: #ifndef __MSDOS__
                    253:          if (!(user_entry = getpwnam (username)))
                    254:            {
                    255:              /* If the calling program has a special syntax for
                    256:                 expanding tildes, and we couldn't find a standard
                    257:                 expansion, then let them try. */
                    258: #endif
                    259:              if (tilde_expansion_failure_hook)
                    260:                {
                    261:                  char *expansion;
                    262: 
                    263:                  expansion =
                    264:                    (char *)(*tilde_expansion_failure_hook) (username);
                    265: 
                    266:                  if (expansion)
                    267:                    {
                    268:                      temp_name = (char *)alloca (1 + strlen (expansion)
                    269:                                                  + strlen (&dirname[i]));
                    270:                      strcpy (temp_name, expansion);
                    271:                      strcat (temp_name, &dirname[i]);
                    272:                      free (expansion);
                    273:                      goto return_name;
                    274:                    }
                    275:                }
                    276:              /* We shouldn't report errors. */
                    277: #ifndef __MSDOS__
                    278:            }
                    279:          else
                    280:            {
                    281:              temp_name = (char *)alloca (1 + strlen (user_entry->pw_dir)
                    282:                                          + strlen (&dirname[i]));
                    283:              strcpy (temp_name, user_entry->pw_dir);
                    284:              strcat (temp_name, &dirname[i]);
                    285: #endif
                    286:            return_name:
                    287:              free (dirname);
                    288:              dirname = savestring (temp_name);
                    289: #ifndef __MSDOS__
                    290:            }
                    291:            endpwent ();
                    292: #endif
                    293:        }
                    294:     }
                    295:   return (dirname);
                    296: }
                    297: 
                    298: #if defined (TEST)
                    299: #undef NULL
                    300: #include <stdio.h>
                    301: 
                    302: main (argc, argv)
                    303:      int argc;
                    304:      char **argv;
                    305: {
                    306:   char *result, line[512];
                    307:   int done = 0;
                    308: 
                    309:   while (!done)
                    310:     {
                    311:       printf ("~expand: ");
                    312:       fflush (stdout);
                    313: 
                    314:       if (!gets (line))
                    315:        strcpy (line, "done");
                    316: 
                    317:       if ((strcmp (line, "done") == 0) ||
                    318:          (strcmp (line, "quit") == 0) ||
                    319:          (strcmp (line, "exit") == 0))
                    320:        {
                    321:          done = 1;
                    322:          break;
                    323:        }
                    324: 
                    325:       result = tilde_expand (line);
                    326:       printf ("  --> %s\n", result);
                    327:       free (result);
                    328:     }
                    329:   exit (0);
                    330: }
                    331: 
                    332: static void memory_error_and_abort ();
                    333: 
                    334: static char *
                    335: xmalloc (bytes)
                    336:      int bytes;
                    337: {
                    338:   char *temp = (char *)malloc (bytes);
                    339: 
                    340:   if (!temp)
                    341:     memory_error_and_abort ();
                    342:   return (temp);
                    343: }
                    344: 
                    345: static char *
                    346: xrealloc (pointer, bytes)
                    347:      char *pointer;
                    348:      int bytes;
                    349: {
                    350:   char *temp;
                    351: 
                    352:   if (!pointer)
                    353:     temp = (char *)malloc (bytes);
                    354:   else
                    355:     temp = (char *)realloc (pointer, bytes);
                    356: 
                    357:   if (!temp)
                    358:     memory_error_and_abort ();
                    359: 
                    360:   return (temp);
                    361: }
                    362: 
                    363: static void
                    364: memory_error_and_abort ()
                    365: {
                    366:   fprintf (stderr, "readline: Out of virtual memory!\n");
                    367:   abort ();
                    368: }
                    369: 
                    370: /*
                    371:  * Local variables:
                    372:  * compile-command: "gcc -g -DTEST -o tilde tilde.c"
                    373:  * end:
                    374:  */
                    375: #endif /* TEST */
                    376: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.