]> git.ipfire.org Git - thirdparty/bash.git/blame - builtins/pushd.def
commit bash-20060307 snapshot
[thirdparty/bash.git] / builtins / pushd.def
CommitLineData
ccc6cda3
JA
1This file is pushd.def, from which is created pushd.c. It implements the
2builtins "pushd", "popd", and "dirs" in Bash.
3
d11b8b46 4Copyright (C) 1987-2004 Free Software Foundation, Inc.
ccc6cda3
JA
5
6This file is part of GNU Bash, the Bourne Again SHell.
7
8Bash is free software; you can redistribute it and/or modify it under
9the terms of the GNU General Public License as published by the Free
bb70624e 10Software Foundation; either version 2, or (at your option) any later
ccc6cda3
JA
11version.
12
13Bash is distributed in the hope that it will be useful, but WITHOUT ANY
14WARRANTY; without even the implied warranty of MERCHANTABILITY or
15FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16for more details.
17
18You should have received a copy of the GNU General Public License along
19with Bash; see the file COPYING. If not, write to the Free Software
bb70624e 20Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA.
ccc6cda3
JA
21
22$PRODUCES pushd.c
23
24$BUILTIN pushd
25$FUNCTION pushd_builtin
26$DEPENDS_ON PUSHD_AND_POPD
27$SHORT_DOC pushd [dir | +N | -N] [-n]
28Adds a directory to the top of the directory stack, or rotates
29the stack, making the new top of the stack the current working
30directory. With no arguments, exchanges the top two directories.
31
32+N Rotates the stack so that the Nth directory (counting
d166f048
JA
33 from the left of the list shown by `dirs', starting with
34 zero) is at the top.
ccc6cda3
JA
35
36-N Rotates the stack so that the Nth directory (counting
d166f048
JA
37 from the right of the list shown by `dirs', starting with
38 zero) is at the top.
ccc6cda3
JA
39
40-n suppress the normal change of directory when adding directories
41 to the stack, so only the stack is manipulated.
42
43dir adds DIR to the directory stack at the top, making it the
44 new current working directory.
45
46You can see the directory stack with the `dirs' command.
47$END
48
49$BUILTIN popd
50$FUNCTION popd_builtin
51$DEPENDS_ON PUSHD_AND_POPD
52$SHORT_DOC popd [+N | -N] [-n]
53Removes entries from the directory stack. With no arguments,
54removes the top directory from the stack, and cd's to the new
55top directory.
56
57+N removes the Nth entry counting from the left of the list
58 shown by `dirs', starting with zero. For example: `popd +0'
59 removes the first directory, `popd +1' the second.
60
61-N removes the Nth entry counting from the right of the list
62 shown by `dirs', starting with zero. For example: `popd -0'
63 removes the last directory, `popd -1' the next to last.
64
65-n suppress the normal change of directory when removing directories
66 from the stack, so only the stack is manipulated.
67
68You can see the directory stack with the `dirs' command.
69$END
70
71$BUILTIN dirs
72$FUNCTION dirs_builtin
73$DEPENDS_ON PUSHD_AND_POPD
74$SHORT_DOC dirs [-clpv] [+N] [-N]
75Display the list of currently remembered directories. Directories
76find their way onto the list with the `pushd' command; you can get
77back up through the list with the `popd' command.
78
79The -l flag specifies that `dirs' should not print shorthand versions
80of directories which are relative to your home directory. This means
81that `~/bin' might be displayed as `/homes/bfox/bin'. The -v flag
82causes `dirs' to print the directory stack with one entry per line,
83prepending the directory name with its position in the stack. The -p
84flag does the same thing, but the stack position is not prepended.
85The -c flag clears the directory stack by deleting all of the elements.
86
87+N displays the Nth entry counting from the left of the list shown by
88 dirs when invoked without options, starting with zero.
89
90-N displays the Nth entry counting from the right of the list shown by
91 dirs when invoked without options, starting with zero.
92$END
93
94#include <config.h>
95
96#if defined (PUSHD_AND_POPD)
97#include <stdio.h>
cce855bc
JA
98#ifndef _MINIX
99# include <sys/param.h>
100#endif
ccc6cda3
JA
101
102#if defined (HAVE_UNISTD_H)
cce855bc
JA
103# ifdef _MINIX
104# include <sys/types.h>
105# endif
ccc6cda3
JA
106# include <unistd.h>
107#endif
108
109#include "../bashansi.h"
5e13499c 110#include "../bashintl.h"
ccc6cda3
JA
111
112#include <errno.h>
113
114#include <tilde/tilde.h>
115
116#include "../shell.h"
bb70624e 117#include "maxpath.h"
ccc6cda3
JA
118#include "common.h"
119#include "builtext.h"
120
b72432fd
JA
121#ifdef LOADABLE_BUILTIN
122# include "builtins.h"
123#endif
124
ccc6cda3
JA
125#if !defined (errno)
126extern int errno;
127#endif /* !errno */
128
ccc6cda3
JA
129/* The list of remembered directories. */
130static char **pushd_directory_list = (char **)NULL;
131
132/* Number of existing slots in this list. */
133static int directory_list_size;
134
135/* Offset to the end of the list. */
136static int directory_list_offset;
137
f73dda09
JA
138static void pushd_error __P((int, char *));
139static void clear_directory_stack __P((void));
140static int cd_to_string __P((char *));
141static int change_to_temp __P((char *));
142static void add_dirstack_element __P((char *));
7117c2d2 143static int get_dirstack_index __P((intmax_t, int, int *));
ccc6cda3
JA
144
145#define NOCD 0x01
146#define ROTATE 0x02
147#define LONGFORM 0x04
148#define CLEARSTAK 0x08
149
150int
151pushd_builtin (list)
152 WORD_LIST *list;
153{
28089d04 154 WORD_LIST *orig_list;
ccc6cda3 155 char *temp, *current_directory, *top;
453f278a 156 int j, flags, skipopt;
7117c2d2 157 intmax_t num;
ccc6cda3
JA
158 char direction;
159
28089d04 160 orig_list = list;
7117c2d2 161 if (list && list->word && ISOPTION (list->word->word, '-'))
453f278a
CR
162 {
163 list = list->next;
164 skipopt = 1;
165 }
166 else
167 skipopt = 0;
7117c2d2 168
ccc6cda3
JA
169 /* If there is no argument list then switch current and
170 top of list. */
171 if (list == 0)
172 {
173 if (directory_list_offset == 0)
174 {
5e13499c 175 builtin_error (_("no other directory"));
ccc6cda3
JA
176 return (EXECUTION_FAILURE);
177 }
178
179 current_directory = get_working_directory ("pushd");
180 if (current_directory == 0)
181 return (EXECUTION_FAILURE);
182
183 j = directory_list_offset - 1;
184 temp = pushd_directory_list[j];
185 pushd_directory_list[j] = current_directory;
186 j = change_to_temp (temp);
187 free (temp);
188 return j;
189 }
190
453f278a 191 for (flags = 0; skipopt == 0 && list; list = list->next)
ccc6cda3
JA
192 {
193 if (ISOPTION (list->word->word, 'n'))
194 {
195 flags |= NOCD;
196 }
197 else if (ISOPTION (list->word->word, '-'))
28ef6c31
JA
198 {
199 list = list->next;
200 break;
201 }
ccc6cda3
JA
202 else if (list->word->word[0] == '-' && list->word->word[1] == '\0')
203 /* Let `pushd -' work like it used to. */
204 break;
205 else if (((direction = list->word->word[0]) == '+') || direction == '-')
206 {
207 if (legal_number (list->word->word + 1, &num) == 0)
208 {
7117c2d2 209 sh_invalidnum (list->word->word);
ccc6cda3
JA
210 builtin_usage ();
211 return (EXECUTION_FAILURE);
212 }
213
214 if (direction == '-')
215 num = directory_list_offset - num;
216
217 if (num > directory_list_offset || num < 0)
218 {
219 pushd_error (directory_list_offset, list->word->word);
220 return (EXECUTION_FAILURE);
221 }
222 flags |= ROTATE;
223 }
224 else if (*list->word->word == '-')
225 {
7117c2d2 226 sh_invalidopt (list->word->word);
ccc6cda3
JA
227 builtin_usage ();
228 return (EXECUTION_FAILURE);
229 }
230 else
231 break;
232 }
233
234 if (flags & ROTATE)
235 {
236 /* Rotate the stack num times. Remember, the current
237 directory acts like it is part of the stack. */
238 temp = get_working_directory ("pushd");
239
240 if (num == 0)
241 {
242 j = ((flags & NOCD) == 0) ? change_to_temp (temp) : EXECUTION_SUCCESS;
243 free (temp);
244 return j;
245 }
246
247 do
248 {
249 top = pushd_directory_list[directory_list_offset - 1];
250
251 for (j = directory_list_offset - 2; j > -1; j--)
252 pushd_directory_list[j + 1] = pushd_directory_list[j];
253
254 pushd_directory_list[j + 1] = temp;
255
256 temp = top;
257 num--;
258 }
259 while (num);
260
261 j = ((flags & NOCD) == 0) ? change_to_temp (temp) : EXECUTION_SUCCESS;
262 free (temp);
263 return j;
264 }
265
266 if (list == 0)
267 return (EXECUTION_SUCCESS);
268
269 /* Change to the directory in list->word->word. Save the current
270 directory on the top of the stack. */
271 current_directory = get_working_directory ("pushd");
272 if (current_directory == 0)
273 return (EXECUTION_FAILURE);
274
28089d04 275 j = ((flags & NOCD) == 0) ? cd_builtin (skipopt ? orig_list : list) : EXECUTION_SUCCESS;
ccc6cda3
JA
276 if (j == EXECUTION_SUCCESS)
277 {
278 add_dirstack_element ((flags & NOCD) ? savestring (list->word->word) : current_directory);
279 dirs_builtin ((WORD_LIST *)NULL);
d166f048
JA
280 if (flags & NOCD)
281 free (current_directory);
ccc6cda3
JA
282 return (EXECUTION_SUCCESS);
283 }
284 else
285 {
286 free (current_directory);
287 return (EXECUTION_FAILURE);
288 }
289}
290
291/* Pop the directory stack, and then change to the new top of the stack.
292 If LIST is non-null it should consist of a word +N or -N, which says
293 what element to delete from the stack. The default is the top one. */
294int
295popd_builtin (list)
296 WORD_LIST *list;
297{
298 register int i;
7117c2d2 299 intmax_t which;
ccc6cda3
JA
300 int flags;
301 char direction;
d166f048 302 char *which_word;
ccc6cda3 303
d166f048 304 which_word = (char *)NULL;
f73dda09 305 for (flags = 0, which = 0, direction = '+'; list; list = list->next)
ccc6cda3
JA
306 {
307 if (ISOPTION (list->word->word, 'n'))
28ef6c31
JA
308 {
309 flags |= NOCD;
310 }
ccc6cda3 311 else if (ISOPTION (list->word->word, '-'))
28ef6c31
JA
312 {
313 list = list->next;
314 break;
315 }
ccc6cda3
JA
316 else if (((direction = list->word->word[0]) == '+') || direction == '-')
317 {
318 if (legal_number (list->word->word + 1, &which) == 0)
319 {
7117c2d2 320 sh_invalidnum (list->word->word);
ccc6cda3
JA
321 builtin_usage ();
322 return (EXECUTION_FAILURE);
323 }
d166f048 324 which_word = list->word->word;
ccc6cda3
JA
325 }
326 else if (*list->word->word == '-')
327 {
7117c2d2 328 sh_invalidopt (list->word->word);
ccc6cda3
JA
329 builtin_usage ();
330 return (EXECUTION_FAILURE);
331 }
332 else
333 break;
334 }
335
336 if (which > directory_list_offset || (directory_list_offset == 0 && which == 0))
337 {
d166f048 338 pushd_error (directory_list_offset, which_word ? which_word : "");
ccc6cda3
JA
339 return (EXECUTION_FAILURE);
340 }
341
342 /* Handle case of no specification, or top of stack specification. */
343 if ((direction == '+' && which == 0) ||
344 (direction == '-' && which == directory_list_offset))
345 {
346 i = ((flags & NOCD) == 0) ? cd_to_string (pushd_directory_list[directory_list_offset - 1])
28ef6c31 347 : EXECUTION_SUCCESS;
ccc6cda3
JA
348 if (i != EXECUTION_SUCCESS)
349 return (i);
350 free (pushd_directory_list[--directory_list_offset]);
351 }
352 else
353 {
354 /* Since an offset other than the top directory was specified,
355 remove that directory from the list and shift the remainder
356 of the list into place. */
357 i = (direction == '+') ? directory_list_offset - which : which;
358 free (pushd_directory_list[i]);
359 directory_list_offset--;
360
361 /* Shift the remainder of the list into place. */
362 for (; i < directory_list_offset; i++)
363 pushd_directory_list[i] = pushd_directory_list[i + 1];
364 }
365
366 dirs_builtin ((WORD_LIST *)NULL);
367 return (EXECUTION_SUCCESS);
368}
369
370/* Print the current list of directories on the directory stack. */
371int
372dirs_builtin (list)
373 WORD_LIST *list;
374{
375 int flags, desired_index, index_flag, vflag;
7117c2d2 376 intmax_t i;
ccc6cda3
JA
377 char *temp, *w;
378
379 for (flags = vflag = index_flag = 0, desired_index = -1, w = ""; list; list = list->next)
380 {
381 if (ISOPTION (list->word->word, 'l'))
382 {
383 flags |= LONGFORM;
384 }
385 else if (ISOPTION (list->word->word, 'c'))
386 {
387 flags |= CLEARSTAK;
388 }
389 else if (ISOPTION (list->word->word, 'v'))
390 {
391 vflag |= 2;
392 }
393 else if (ISOPTION (list->word->word, 'p'))
394 {
395 vflag |= 1;
396 }
397 else if (ISOPTION (list->word->word, '-'))
28ef6c31
JA
398 {
399 list = list->next;
400 break;
401 }
ccc6cda3 402 else if (*list->word->word == '+' || *list->word->word == '-')
28ef6c31
JA
403 {
404 int sign;
405 if (legal_number (w = list->word->word + 1, &i) == 0)
ccc6cda3 406 {
7117c2d2 407 sh_invalidnum (list->word->word);
ccc6cda3
JA
408 builtin_usage ();
409 return (EXECUTION_FAILURE);
410 }
411 sign = (*list->word->word == '+') ? 1 : -1;
412 desired_index = get_dirstack_index (i, sign, &index_flag);
413 }
414 else
415 {
7117c2d2 416 sh_invalidopt (list->word->word);
ccc6cda3
JA
417 builtin_usage ();
418 return (EXECUTION_FAILURE);
419 }
420 }
421
422 if (flags & CLEARSTAK)
423 {
424 clear_directory_stack ();
425 return (EXECUTION_SUCCESS);
426 }
427
428 if (index_flag && (desired_index < 0 || desired_index > directory_list_offset))
429 {
430 pushd_error (directory_list_offset, w);
431 return (EXECUTION_FAILURE);
432 }
433
434#define DIRSTACK_FORMAT(temp) \
435 (flags & LONGFORM) ? temp : polite_directory_format (temp)
436
437 /* The first directory printed is always the current working directory. */
438 if (index_flag == 0 || (index_flag == 1 && desired_index == 0))
439 {
440 temp = get_working_directory ("dirs");
441 if (temp == 0)
5e13499c 442 temp = savestring (_("<no current directory>"));
ccc6cda3
JA
443 if (vflag & 2)
444 printf ("%2d %s", 0, DIRSTACK_FORMAT (temp));
445 else
446 printf ("%s", DIRSTACK_FORMAT (temp));
447 free (temp);
448 if (index_flag)
449 {
450 putchar ('\n');
451 return EXECUTION_SUCCESS;
452 }
453 }
454
455#define DIRSTACK_ENTRY(i) \
456 (flags & LONGFORM) ? pushd_directory_list[i] \
457 : polite_directory_format (pushd_directory_list[i])
458
459 /* Now print the requested directory stack entries. */
460 if (index_flag)
461 {
462 if (vflag & 2)
463 printf ("%2d %s", directory_list_offset - desired_index,
464 DIRSTACK_ENTRY (desired_index));
465 else
466 printf ("%s", DIRSTACK_ENTRY (desired_index));
467 }
468 else
469 for (i = directory_list_offset - 1; i >= 0; i--)
470 if (vflag >= 2)
471 printf ("\n%2d %s", directory_list_offset - (int)i, DIRSTACK_ENTRY (i));
472 else
473 printf ("%s%s", (vflag & 1) ? "\n" : " ", DIRSTACK_ENTRY (i));
474
475 putchar ('\n');
476 fflush (stdout);
477 return (EXECUTION_SUCCESS);
478}
479
480static void
481pushd_error (offset, arg)
482 int offset;
483 char *arg;
484{
485 if (offset == 0)
486 builtin_error ("directory stack empty");
ccc6cda3 487 else
7117c2d2 488 sh_erange (arg, "directory stack index");
ccc6cda3
JA
489}
490
491static void
492clear_directory_stack ()
493{
494 register int i;
495
496 for (i = 0; i < directory_list_offset; i++)
497 free (pushd_directory_list[i]);
498 directory_list_offset = 0;
499}
500
501/* Switch to the directory in NAME. This uses the cd_builtin to do the work,
502 so if the result is EXECUTION_FAILURE then an error message has already
503 been printed. */
504static int
505cd_to_string (name)
506 char *name;
507{
508 WORD_LIST *tlist;
28089d04 509 WORD_LIST *dir;
ccc6cda3
JA
510 int result;
511
28089d04
CR
512 dir = make_word_list (make_word (name), NULL);
513 tlist = make_word_list (make_word ("--"), dir);
ccc6cda3
JA
514 result = cd_builtin (tlist);
515 dispose_words (tlist);
516 return (result);
517}
518
519static int
520change_to_temp (temp)
521 char *temp;
522{
523 int tt;
524
525 tt = temp ? cd_to_string (temp) : EXECUTION_FAILURE;
526
527 if (tt == EXECUTION_SUCCESS)
528 dirs_builtin ((WORD_LIST *)NULL);
529
530 return (tt);
531}
532
533static void
534add_dirstack_element (dir)
535 char *dir;
536{
ccc6cda3 537 if (directory_list_offset == directory_list_size)
7117c2d2 538 pushd_directory_list = strvec_resize (pushd_directory_list, directory_list_size += 10);
ccc6cda3
JA
539 pushd_directory_list[directory_list_offset++] = dir;
540}
541
542static int
543get_dirstack_index (ind, sign, indexp)
7117c2d2 544 intmax_t ind;
f73dda09 545 int sign, *indexp;
ccc6cda3
JA
546{
547 if (indexp)
548 *indexp = sign > 0 ? 1 : 2;
549
550 /* dirs +0 prints the current working directory. */
551 /* dirs -0 prints last element in directory stack */
552 if (ind == 0 && sign > 0)
553 return 0;
554 else if (ind == directory_list_offset)
555 {
556 if (indexp)
557 *indexp = sign > 0 ? 2 : 1;
558 return 0;
559 }
f73dda09 560 else if (ind >= 0 && ind <= directory_list_offset)
ccc6cda3 561 return (sign > 0 ? directory_list_offset - ind : ind);
f73dda09
JA
562 else
563 return -1;
ccc6cda3
JA
564}
565
cce855bc
JA
566/* Used by the tilde expansion code. */
567char *
568get_dirstack_from_string (string)
569 char *string;
570{
571 int ind, sign, index_flag;
7117c2d2 572 intmax_t i;
cce855bc
JA
573
574 sign = 1;
575 if (*string == '-' || *string == '+')
576 {
577 sign = (*string == '-') ? -1 : 1;
578 string++;
579 }
580 if (legal_number (string, &i) == 0)
581 return ((char *)NULL);
582
583 index_flag = 0;
584 ind = get_dirstack_index (i, sign, &index_flag);
585 if (index_flag && (ind < 0 || ind > directory_list_offset))
586 return ((char *)NULL);
587 if (index_flag == 0 || (index_flag == 1 && ind == 0))
588 return (get_string_value ("PWD"));
589 else
590 return (pushd_directory_list[ind]);
591}
592
593#ifdef INCLUDE_UNUSED
ccc6cda3
JA
594char *
595get_dirstack_element (ind, sign)
7117c2d2 596 intmax_t ind;
f73dda09 597 int sign;
ccc6cda3
JA
598{
599 int i;
600
601 i = get_dirstack_index (ind, sign, (int *)NULL);
602 return (i < 0 || i > directory_list_offset) ? (char *)NULL
603 : pushd_directory_list[i];
604}
cce855bc 605#endif
ccc6cda3
JA
606
607void
608set_dirstack_element (ind, sign, value)
7117c2d2 609 intmax_t ind;
f73dda09 610 int sign;
ccc6cda3
JA
611 char *value;
612{
613 int i;
614
615 i = get_dirstack_index (ind, sign, (int *)NULL);
616 if (ind == 0 || i < 0 || i > directory_list_offset)
617 return;
618 free (pushd_directory_list[i]);
619 pushd_directory_list[i] = savestring (value);
620}
621
622WORD_LIST *
74d9692b
CR
623get_directory_stack (flags)
624 int flags;
ccc6cda3
JA
625{
626 register int i;
627 WORD_LIST *ret;
628 char *d, *t;
629
630 for (ret = (WORD_LIST *)NULL, i = 0; i < directory_list_offset; i++)
631 {
74d9692b
CR
632 d = (flags&1) ? polite_directory_format (pushd_directory_list[i])
633 : pushd_directory_list[i];
ccc6cda3
JA
634 ret = make_word_list (make_word (d), ret);
635 }
636 /* Now the current directory. */
637 d = get_working_directory ("dirstack");
638 i = 0; /* sentinel to decide whether or not to free d */
639 if (d == 0)
640 d = ".";
641 else
642 {
643 t = polite_directory_format (d);
644 /* polite_directory_format sometimes returns its argument unchanged.
645 If it does not, we can free d right away. If it does, we need to
646 mark d to be deleted later. */
647 if (t != d)
648 {
649 free (d);
650 d = t;
651 }
652 else /* t == d, so d is what we want */
653 i = 1;
654 }
655 ret = make_word_list (make_word (d), ret);
656 if (i)
657 free (d);
658 return ret; /* was (REVERSE_LIST (ret, (WORD_LIST *)); */
659}
b72432fd
JA
660
661#ifdef LOADABLE_BUILTIN
8d618825 662char * const dirs_doc[] = {
5e13499c
CR
663 N_("Display the list of currently remembered directories. Directories"),
664 N_("find their way onto the list with the `pushd' command; you can get"),
665 N_("back up through the list with the `popd' command."),
a2e7f358 666 N_(" "),
5e13499c
CR
667 N_("The -l flag specifies that `dirs' should not print shorthand versions"),
668 N_("of directories which are relative to your home directory. This means"),
669 N_("that `~/bin' might be displayed as `/homes/bfox/bin'. The -v flag"),
670 N_("causes `dirs' to print the directory stack with one entry per line,"),
671 N_("prepending the directory name with its position in the stack. The -p"),
672 N_("flag does the same thing, but the stack position is not prepended."),
673 N_("The -c flag clears the directory stack by deleting all of the elements."),
a2e7f358 674 N_(" "),
5e13499c
CR
675 N_("+N displays the Nth entry counting from the left of the list shown by"),
676 N_(" dirs when invoked without options, starting with zero."),
a2e7f358 677 N_(" "),
5e13499c
CR
678 N_("-N displays the Nth entry counting from the right of the list shown by"),
679 N_(" dirs when invoked without options, starting with zero."),
b72432fd
JA
680 (char *)NULL
681};
682
8d618825 683char * const pushd_doc[] = {
5e13499c
CR
684 N_("Adds a directory to the top of the directory stack, or rotates"),
685 N_("the stack, making the new top of the stack the current working"),
686 N_("directory. With no arguments, exchanges the top two directories."),
a2e7f358 687 N_(" "),
5e13499c
CR
688 N_("+N Rotates the stack so that the Nth directory (counting"),
689 N_(" from the left of the list shown by `dirs', starting with"),
690 N_(" zero) is at the top."),
a2e7f358 691 N_(" "),
5e13499c
CR
692 N_("-N Rotates the stack so that the Nth directory (counting"),
693 N_(" from the right of the list shown by `dirs', starting with"),
694 N_(" zero) is at the top."),
a2e7f358 695 N_(" "),
5e13499c
CR
696 N_("-n suppress the normal change of directory when adding directories"),
697 N_(" to the stack, so only the stack is manipulated."),
a2e7f358 698 N_(" "),
5e13499c
CR
699 N_("dir adds DIR to the directory stack at the top, making it the"),
700 N_(" new current working directory."),
a2e7f358 701 N_(" "),
5e13499c 702 N_("You can see the directory stack with the `dirs' command."),
b72432fd
JA
703 (char *)NULL
704};
705
8d618825 706char * const popd_doc[] = {
5e13499c
CR
707 N_("Removes entries from the directory stack. With no arguments,"),
708 N_("removes the top directory from the stack, and cd's to the new"),
709 N_("top directory."),
a2e7f358 710 N_(" "),
5e13499c
CR
711 N_("+N removes the Nth entry counting from the left of the list"),
712 N_(" shown by `dirs', starting with zero. For example: `popd +0'"),
713 N_(" removes the first directory, `popd +1' the second."),
a2e7f358 714 N_(" "),
5e13499c
CR
715 N_("-N removes the Nth entry counting from the right of the list"),
716 N_(" shown by `dirs', starting with zero. For example: `popd -0'"),
717 N_(" removes the last directory, `popd -1' the next to last."),
a2e7f358 718 N_(" "),
5e13499c
CR
719 N_("-n suppress the normal change of directory when removing directories"),
720 N_(" from the stack, so only the stack is manipulated."),
a2e7f358 721 N_(" "),
5e13499c 722 N_("You can see the directory stack with the `dirs' command."),
b72432fd
JA
723 (char *)NULL
724};
725
726struct builtin pushd_struct = {
727 "pushd",
728 pushd_builtin,
729 BUILTIN_ENABLED,
730 pushd_doc,
731 "pushd [+N | -N] [-n] [dir]",
732 0
733};
734
735struct builtin popd_struct = {
736 "popd",
737 popd_builtin,
738 BUILTIN_ENABLED,
739 popd_doc,
740 "popd [+N | -N] [-n]",
741 0
742};
743
744struct builtin dirs_struct = {
745 "dirs",
746 dirs_builtin,
747 BUILTIN_ENABLED,
748 dirs_doc,
749 "dirs [-clpv] [+N] [-N]",
750 0
751};
752#endif /* LOADABLE_BUILTIN */
753
ccc6cda3 754#endif /* PUSHD_AND_POPD */