OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [tags/] [start/] [insight/] [readline/] [tilde.c] - Blame information for rev 1780

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 578 markom
/* tilde.c -- Tilde expansion code (~/foo := $HOME/foo). */
2
 
3
/* Copyright (C) 1988,1989 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 it
9
   under the terms of the GNU General Public License as published by the
10
   Free Software Foundation; either version 2, or (at your option) any
11
   later version.
12
 
13
   Readline is distributed in the hope that it will be useful, but
14
   WITHOUT ANY WARRANTY; without even the implied warranty of
15
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16
   General Public License for more details.
17
 
18
   You should have received a copy of the GNU General Public License
19
   along with Readline; see the file COPYING.  If not, write to the Free
20
   Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
21
 
22
#if defined (HAVE_CONFIG_H)
23
#  include <config.h>
24
#endif
25
 
26
#if defined (HAVE_UNISTD_H)
27
#  ifdef _MINIX
28
#    include <sys/types.h>
29
#  endif
30
#  include <unistd.h>
31
#endif
32
 
33
#if defined (HAVE_STRING_H)
34
#  include <string.h>
35
#else /* !HAVE_STRING_H */
36
#  include <strings.h>
37
#endif /* !HAVE_STRING_H */  
38
 
39
#if defined (HAVE_STDLIB_H)
40
#  include <stdlib.h>
41
#else
42
#  include "ansi_stdlib.h"
43
#endif /* HAVE_STDLIB_H */
44
 
45
#include <sys/types.h>
46
#include <pwd.h>
47
 
48
#include "tilde.h"
49
 
50
#if defined (TEST) || defined (STATIC_MALLOC)
51
static char *xmalloc (), *xrealloc ();
52
#else
53
#  if defined __STDC__
54
extern char *xmalloc (int);
55
extern char *xrealloc (void *, int);
56
#  else
57
extern char *xmalloc (), *xrealloc ();
58
#  endif /* !__STDC__ */
59
#endif /* TEST || STATIC_MALLOC */
60
 
61
#if !defined (HAVE_GETPW_DECLS)
62
extern struct passwd *getpwuid (), *getpwnam ();
63
#endif /* !HAVE_GETPW_DECLS */
64
 
65
#if !defined (savestring)
66
#  ifndef strcpy
67
extern char *strcpy ();
68
#  endif
69
#define savestring(x) strcpy (xmalloc (1 + strlen (x)), (x))
70
#endif /* !savestring */
71
 
72
#if !defined (NULL)
73
#  if defined (__STDC__)
74
#    define NULL ((void *) 0)
75
#  else
76
#    define NULL 0x0
77
#  endif /* !__STDC__ */
78
#endif /* !NULL */
79
 
80
/* If being compiled as part of bash, these will be satisfied from
81
   variables.o.  If being compiled as part of readline, they will
82
   be satisfied from shell.o. */
83
extern char *get_home_dir __P((void));
84
extern char *get_env_value __P((char *));
85
 
86
/* The default value of tilde_additional_prefixes.  This is set to
87
   whitespace preceding a tilde so that simple programs which do not
88
   perform any word separation get desired behaviour. */
89
static char *default_prefixes[] =
90
  { " ~", "\t~", (char *)NULL };
91
 
92
/* The default value of tilde_additional_suffixes.  This is set to
93
   whitespace or newline so that simple programs which do not
94
   perform any word separation get desired behaviour. */
95
static char *default_suffixes[] =
96
  { " ", "\n", (char *)NULL };
97
 
98
/* If non-null, this contains the address of a function that the application
99
   wants called before trying the standard tilde expansions.  The function
100
   is called with the text sans tilde, and returns a malloc()'ed string
101
   which is the expansion, or a NULL pointer if the expansion fails. */
102
CPFunction *tilde_expansion_preexpansion_hook = (CPFunction *)NULL;
103
 
104
/* If non-null, this contains the address of a function to call if the
105
   standard meaning for expanding a tilde fails.  The function is called
106
   with the text (sans tilde, as in "foo"), and returns a malloc()'ed string
107
   which is the expansion, or a NULL pointer if there is no expansion. */
108
CPFunction *tilde_expansion_failure_hook = (CPFunction *)NULL;
109
 
110
/* When non-null, this is a NULL terminated array of strings which
111
   are duplicates for a tilde prefix.  Bash uses this to expand
112
   `=~' and `:~'. */
113
char **tilde_additional_prefixes = default_prefixes;
114
 
115
/* When non-null, this is a NULL terminated array of strings which match
116
   the end of a username, instead of just "/".  Bash sets this to
117
   `:' and `=~'. */
118
char **tilde_additional_suffixes = default_suffixes;
119
 
120
/* Find the start of a tilde expansion in STRING, and return the index of
121
   the tilde which starts the expansion.  Place the length of the text
122
   which identified this tilde starter in LEN, excluding the tilde itself. */
123
static int
124
tilde_find_prefix (string, len)
125
     char *string;
126
     int *len;
127
{
128
  register int i, j, string_len;
129
  register char **prefixes;
130
 
131
  prefixes = tilde_additional_prefixes;
132
 
133
  string_len = strlen (string);
134
  *len = 0;
135
 
136
  if (*string == '\0' || *string == '~')
137
    return (0);
138
 
139
  if (prefixes)
140
    {
141
      for (i = 0; i < string_len; i++)
142
        {
143
          for (j = 0; prefixes[j]; j++)
144
            {
145
              if (strncmp (string + i, prefixes[j], strlen (prefixes[j])) == 0)
146
                {
147
                  *len = strlen (prefixes[j]) - 1;
148
                  return (i + *len);
149
                }
150
            }
151
        }
152
    }
153
  return (string_len);
154
}
155
 
156
/* Find the end of a tilde expansion in STRING, and return the index of
157
   the character which ends the tilde definition.  */
158
static int
159
tilde_find_suffix (string)
160
     char *string;
161
{
162
  register int i, j, string_len;
163
  register char **suffixes;
164
 
165
  suffixes = tilde_additional_suffixes;
166
  string_len = strlen (string);
167
 
168
  for (i = 0; i < string_len; i++)
169
    {
170
#if defined (__MSDOS__)
171
      if (string[i] == '/' || string[i] == '\\' /* || !string[i] */)
172
#else
173
      if (string[i] == '/' /* || !string[i] */)
174
#endif
175
        break;
176
 
177
      for (j = 0; suffixes && suffixes[j]; j++)
178
        {
179
          if (strncmp (string + i, suffixes[j], strlen (suffixes[j])) == 0)
180
            return (i);
181
        }
182
    }
183
  return (i);
184
}
185
 
186
/* Return a new string which is the result of tilde expanding STRING. */
187
char *
188
tilde_expand (string)
189
     char *string;
190
{
191
  char *result;
192
  int result_size, result_index;
193
 
194
  result_index = result_size = 0;
195
  if (result = strchr (string, '~'))
196
    result = xmalloc (result_size = (strlen (string) + 16));
197
  else
198
    result = xmalloc (result_size = (strlen (string) + 1));
199
 
200
  /* Scan through STRING expanding tildes as we come to them. */
201
  while (1)
202
    {
203
      register int start, end;
204
      char *tilde_word, *expansion;
205
      int len;
206
 
207
      /* Make START point to the tilde which starts the expansion. */
208
      start = tilde_find_prefix (string, &len);
209
 
210
      /* Copy the skipped text into the result. */
211
      if ((result_index + start + 1) > result_size)
212
        result = xrealloc (result, 1 + (result_size += (start + 20)));
213
 
214
      strncpy (result + result_index, string, start);
215
      result_index += start;
216
 
217
      /* Advance STRING to the starting tilde. */
218
      string += start;
219
 
220
      /* Make END be the index of one after the last character of the
221
         username. */
222
      end = tilde_find_suffix (string);
223
 
224
      /* If both START and END are zero, we are all done. */
225
      if (!start && !end)
226
        break;
227
 
228
      /* Expand the entire tilde word, and copy it into RESULT. */
229
      tilde_word = xmalloc (1 + end);
230
      strncpy (tilde_word, string, end);
231
      tilde_word[end] = '\0';
232
      string += end;
233
 
234
      expansion = tilde_expand_word (tilde_word);
235
      free (tilde_word);
236
 
237
      len = strlen (expansion);
238
#ifdef __CYGWIN32__
239
      /* Fix for Cygwin to prevent ~user/xxx from expanding to //xxx when
240
         $HOME for `user' is /.  On cygwin, // denotes a network drive. */
241
      if (len > 1 || *expansion != '/' || *string != '/')
242
#endif
243
        {
244
          if ((result_index + len + 1) > result_size)
245
            result = xrealloc (result, 1 + (result_size += (len + 20)));
246
 
247
          strcpy (result + result_index, expansion);
248
          result_index += len;
249
        }
250
      free (expansion);
251
    }
252
 
253
  result[result_index] = '\0';
254
 
255
  return (result);
256
}
257
 
258
/* Take FNAME and return the tilde prefix we want expanded.  If LENP is
259
   non-null, the index of the end of the prefix into FNAME is returned in
260
   the location it points to. */
261
static char *
262
isolate_tilde_prefix (fname, lenp)
263
     char *fname;
264
     int *lenp;
265
{
266
  char *ret;
267
  int i;
268
 
269
  ret = xmalloc (strlen (fname));
270
#if defined (__MSDOS__)
271
  for (i = 1; fname[i] && fname[i] != '/' && fname[i] != '\\'; i++)
272
#else
273
  for (i = 1; fname[i] && fname[i] != '/'; i++)
274
#endif
275
    ret[i - 1] = fname[i];
276
  ret[i - 1] = '\0';
277
  if (lenp)
278
    *lenp = i;
279
  return ret;
280
}
281
 
282
/* Return a string that is PREFIX concatenated with SUFFIX starting at
283
   SUFFIND. */
284
static char *
285
glue_prefix_and_suffix (prefix, suffix, suffind)
286
     char *prefix, *suffix;
287
     int suffind;
288
{
289
  char *ret;
290
  int plen, slen;
291
 
292
  plen = (prefix && *prefix) ? strlen (prefix) : 0;
293
  slen = strlen (suffix + suffind);
294
  ret = xmalloc (plen + slen + 1);
295
  if (plen)
296
    strcpy (ret, prefix);
297
  strcpy (ret + plen, suffix + suffind);
298
  return ret;
299
}
300
 
301
/* Do the work of tilde expansion on FILENAME.  FILENAME starts with a
302
   tilde.  If there is no expansion, call tilde_expansion_failure_hook.
303
   This always returns a newly-allocated string, never static storage. */
304
char *
305
tilde_expand_word (filename)
306
     char *filename;
307
{
308
  char *dirname, *expansion, *username;
309
  int user_len;
310
  struct passwd *user_entry;
311
 
312
  if (filename == 0)
313
    return ((char *)NULL);
314
 
315
  if (*filename != '~')
316
    return (savestring (filename));
317
 
318
  /* A leading `~/' or a bare `~' is *always* translated to the value of
319
     $HOME or the home directory of the current user, regardless of any
320
     preexpansion hook. */
321
  if (filename[1] == '\0' || filename[1] == '/')
322
    {
323
      /* Prefix $HOME to the rest of the string. */
324
      expansion = get_env_value ("HOME");
325
 
326
      /* If there is no HOME variable, look up the directory in
327
         the password database. */
328
      if (expansion == 0)
329
        expansion = get_home_dir ();
330
 
331
      return (glue_prefix_and_suffix (expansion, filename, 1));
332
    }
333
 
334
  username = isolate_tilde_prefix (filename, &user_len);
335
 
336
  if (tilde_expansion_preexpansion_hook)
337
    {
338
      expansion = (*tilde_expansion_preexpansion_hook) (username);
339
      if (expansion)
340
        {
341
          dirname = glue_prefix_and_suffix (expansion, filename, user_len);
342
          free (username);
343
          free (expansion);
344
          return (dirname);
345
        }
346
    }
347
 
348
  /* No preexpansion hook, or the preexpansion hook failed.  Look in the
349
     password database. */
350
  dirname = (char *)NULL;
351
  user_entry = getpwnam (username);
352
  if (user_entry == 0)
353
    {
354
      /* If the calling program has a special syntax for expanding tildes,
355
         and we couldn't find a standard expansion, then let them try. */
356
      if (tilde_expansion_failure_hook)
357
        {
358
          expansion = (*tilde_expansion_failure_hook) (username);
359
          if (expansion)
360
            {
361
              dirname = glue_prefix_and_suffix (expansion, filename, user_len);
362
              free (expansion);
363
            }
364
        }
365
      free (username);
366
      /* If we don't have a failure hook, or if the failure hook did not
367
         expand the tilde, return a copy of what we were passed. */
368
      if (dirname == 0)
369
        dirname = savestring (filename);
370
    }
371
  else
372
    {
373
      free (username);
374
      dirname = glue_prefix_and_suffix (user_entry->pw_dir, filename, user_len);
375
    }
376
 
377
  endpwent ();
378
  return (dirname);
379
}
380
 
381
 
382
#if defined (TEST)
383
#undef NULL
384
#include <stdio.h>
385
 
386
main (argc, argv)
387
     int argc;
388
     char **argv;
389
{
390
  char *result, line[512];
391
  int done = 0;
392
 
393
  while (!done)
394
    {
395
      printf ("~expand: ");
396
      fflush (stdout);
397
 
398
      if (!gets (line))
399
        strcpy (line, "done");
400
 
401
      if ((strcmp (line, "done") == 0) ||
402
          (strcmp (line, "quit") == 0) ||
403
          (strcmp (line, "exit") == 0))
404
        {
405
          done = 1;
406
          break;
407
        }
408
 
409
      result = tilde_expand (line);
410
      printf ("  --> %s\n", result);
411
      free (result);
412
    }
413
  exit (0);
414
}
415
 
416
static void memory_error_and_abort ();
417
 
418
static char *
419
xmalloc (bytes)
420
     int bytes;
421
{
422
  char *temp = (char *)malloc (bytes);
423
 
424
  if (!temp)
425
    memory_error_and_abort ();
426
  return (temp);
427
}
428
 
429
static char *
430
xrealloc (pointer, bytes)
431
     char *pointer;
432
     int bytes;
433
{
434
  char *temp;
435
 
436
  if (!pointer)
437
    temp = (char *)malloc (bytes);
438
  else
439
    temp = (char *)realloc (pointer, bytes);
440
 
441
  if (!temp)
442
    memory_error_and_abort ();
443
 
444
  return (temp);
445
}
446
 
447
static void
448
memory_error_and_abort ()
449
{
450
  fprintf (stderr, "readline: out of virtual memory\n");
451
  abort ();
452
}
453
 
454
/*
455
 * Local variables:
456
 * compile-command: "gcc -g -DTEST -o tilde tilde.c"
457
 * end:
458
 */
459
#endif /* TEST */

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.