Bash-4.3 distribution sources and documentation
[platform/upstream/bash.git] / builtins / help.def
index 8fb0e2b..1894f17 100644 (file)
@@ -1,7 +1,7 @@
 This file is help.def, from which is created help.c.
 It implements the builtin "help" in Bash.
 
 This file is help.def, from which is created help.c.
 It implements the builtin "help" in Bash.
 
-Copyright (C) 1987-2009 Free Software Foundation, Inc.
+Copyright (C) 1987-2013 Free Software Foundation, Inc.
 
 This file is part of GNU Bash, the Bourne Again SHell.
 
 
 This file is part of GNU Bash, the Bourne Again SHell.
 
@@ -92,7 +92,7 @@ help_builtin (list)
 {
   register int i;
   char *pattern, *name;
 {
   register int i;
   char *pattern, *name;
-  int plen, match_found, sflag, dflag, mflag;
+  int plen, match_found, sflag, dflag, mflag, m, pass, this_found;
 
   dflag = sflag = mflag = 0;
   reset_internal_getopt ();
 
   dflag = sflag = mflag = 0;
   reset_internal_getopt ();
@@ -137,29 +137,43 @@ help_builtin (list)
       pattern = list->word->word;
       plen = strlen (pattern);
 
       pattern = list->word->word;
       plen = strlen (pattern);
 
-      for (i = 0; name = shell_builtins[i].name; i++)
+      for (pass = 1, this_found = 0; pass < 3; pass++)
        {
        {
-         QUIT;
-         if ((strncmp (pattern, name, plen) == 0) ||
-             (strmatch (pattern, name, FNMATCH_EXTFLAG) != FNM_NOMATCH))
+         for (i = 0; name = shell_builtins[i].name; i++)
            {
            {
-             match_found++;
-             if (dflag)
-               {
-                 show_desc (name, i);
-                 continue;
-               }
-             else if (mflag)
-               {
-                 show_manpage (name, i);
-                 continue;
-               }
-
-             printf ("%s: %s\n", name, _(shell_builtins[i].short_doc));
-
-             if (sflag == 0)
-               show_longdoc (i);
+             QUIT;
+
+             /* First pass: look for exact string or pattern matches.
+                Second pass: look for prefix matches like bash-4.2 */
+             if (pass == 1)
+               m = (strcmp (pattern, name) == 0) ||
+                   (strmatch (pattern, name, FNMATCH_EXTFLAG) != FNM_NOMATCH);
+             else
+               m = strncmp (pattern, name, plen) == 0;
+
+             if (m)
+               {
+                 this_found = 1;
+                 match_found++;
+                 if (dflag)
+                   {
+                     show_desc (name, i);
+                     continue;
+                   }
+                 else if (mflag)
+                   {
+                     show_manpage (name, i);
+                     continue;
+                   }
+
+                 printf ("%s: %s\n", name, _(shell_builtins[i].short_doc));
+
+                 if (sflag == 0)
+                   show_longdoc (i);
+               }
            }
            }
+         if (pass == 1 && this_found == 1)
+           break;
        }
     }
 
        }
     }
 
@@ -209,7 +223,7 @@ show_longdoc (i)
       zcatfd (fd, 1, doc[0]);
       close (fd);
     }
       zcatfd (fd, 1, doc[0]);
       close (fd);
     }
-  else
+  else if (doc)
     for (j = 0; doc[j]; j++)
       printf ("%*s%s\n", BASE_INDENT, " ", _(doc[j]));
 }
     for (j = 0; doc[j]; j++)
       printf ("%*s%s\n", BASE_INDENT, " ", _(doc[j]));
 }
@@ -327,6 +341,140 @@ show_manpage (name, i)
 }
 
 static void
 }
 
 static void
+dispcolumn (i, buf, bufsize, width, height)
+     int i;
+     char *buf;
+     size_t bufsize;
+     int width, height;
+{
+  int j;
+  int displen;
+  char *helpdoc;
+
+  /* first column */
+  helpdoc = _(shell_builtins[i].short_doc);
+
+  buf[0] = (shell_builtins[i].flags & BUILTIN_ENABLED) ? ' ' : '*';
+  strncpy (buf + 1, helpdoc, width - 2);
+  buf[width - 2] = '>';                /* indicate truncation */
+  buf[width - 1] = '\0';
+  printf ("%s", buf);
+  if (((i << 1) >= num_shell_builtins) || (i+height >= num_shell_builtins))
+    {
+      printf ("\n");
+      return;
+    }
+
+  displen = strlen (buf);
+  /* two spaces */
+  for (j = displen; j < width; j++)
+    putc (' ', stdout);
+
+  /* second column */
+  helpdoc = _(shell_builtins[i+height].short_doc);
+
+  buf[0] = (shell_builtins[i+height].flags & BUILTIN_ENABLED) ? ' ' : '*';
+  strncpy (buf + 1, helpdoc, width - 3);
+  buf[width - 3] = '>';                /* indicate truncation */
+  buf[width - 2] = '\0';
+
+  printf ("%s\n", buf);
+}
+
+#if defined (HANDLE_MULTIBYTE)
+static void
+wdispcolumn (i, buf, bufsize, width, height)
+     int i;
+     char *buf;
+     size_t bufsize;
+     int width, height;
+{
+  int j;
+  int displen;
+  char *helpdoc;
+  wchar_t *wcstr;
+  size_t slen, n;
+  int wclen;
+
+  /* first column */
+  helpdoc = _(shell_builtins[i].short_doc);
+
+  wcstr = 0;
+  slen = mbstowcs ((wchar_t *)0, helpdoc, 0);
+  if (slen == -1)
+    {
+      dispcolumn (i, buf, bufsize, width, height);
+      return;
+    }
+
+  /* No bigger than the passed max width */
+  if (slen >= width)
+    slen = width - 2;
+  wcstr = (wchar_t *)xmalloc (sizeof (wchar_t) * (width + 2));
+  n = mbstowcs (wcstr+1, helpdoc, slen + 1);
+  wcstr[n+1] = L'\0';
+
+  /* Turn tabs and newlines into spaces for column display, since wcwidth
+     returns -1 for them */
+  for (j = 1; j < n; j++)
+    if (wcstr[j] == L'\n' || wcstr[j] == L'\t')
+      wcstr[j] = L' ';
+
+  displen = wcsnwidth (wcstr+1, slen, width - 2) + 1;  /* +1 for ' ' or '*' */
+  
+  wcstr[0] = (shell_builtins[i].flags & BUILTIN_ENABLED) ? L' ' : L'*';
+
+  /* This assumes each wide char takes up one column position when displayed */
+  wcstr[width - 2] = L'>';             /* indicate truncation */
+  wcstr[width - 1] = L'\0';
+
+  printf ("%ls", wcstr);
+  if (((i << 1) >= num_shell_builtins) || (i+height >= num_shell_builtins))
+    {
+      printf ("\n");
+      return;
+    }
+
+  /* at least one space */
+  for (j = displen; j < width; j++)
+    putc (' ', stdout);
+
+  /* second column */
+  helpdoc = _(shell_builtins[i+height].short_doc);
+  slen = mbstowcs ((wchar_t *)0, helpdoc, 0);
+  if (slen == -1)
+    {
+      /* for now */
+      printf ("%c%s\n", (shell_builtins[i+height].flags & BUILTIN_ENABLED) ? ' ' : '*', helpdoc);
+      return;
+    }
+
+  /* Reuse wcstr since it is already width wide chars long */
+  if (slen >= width)
+    slen = width - 2;
+  n = mbstowcs (wcstr+1, helpdoc, slen + 1);
+  wcstr[n+1] = L'\0';          /* make sure null-terminated */
+
+  /* Turn tabs and newlines into spaces for column display */
+  for (j = 1; j < n; j++)
+    if (wcstr[j] == L'\n' || wcstr[j] == L'\t')
+      wcstr[j] = L' ';
+
+  displen = wcsnwidth (wcstr+1, slen, width - 2);
+  
+  wcstr[0] = (shell_builtins[i+height].flags & BUILTIN_ENABLED) ? L' ' : L'*';
+
+  /* This assumes each wide char takes up one column position when displayed */
+  wcstr[width - 3] = L'>';             /* indicate truncation */
+  wcstr[width - 2] = L'\0';
+
+  printf ("%ls\n", wcstr);
+
+  free (wcstr);
+}
+#endif /* HANDLE_MULTIBYTE */
+
+static void
 show_builtin_command_help ()
 {
   int i, j;
 show_builtin_command_help ()
 {
   int i, j;
@@ -358,28 +506,12 @@ A star (*) next to a name means that the command is disabled.\n\
     {
       QUIT;
 
     {
       QUIT;
 
-      /* first column */
-      blurb[0] = (shell_builtins[i].flags & BUILTIN_ENABLED) ? ' ' : '*';
-      strncpy (blurb + 1, _(shell_builtins[i].short_doc), width - 2);
-      blurb[width - 2] = '>';          /* indicate truncation */
-      blurb[width - 1] = '\0';
-      printf ("%s", blurb);
-      if (((i << 1) >= num_shell_builtins) || (i+height >= num_shell_builtins))
-       {
-         printf ("\n");
-         break;
-       }
-
-      /* two spaces */
-      for (j = strlen (blurb); j < width; j++)
-        putc (' ', stdout);
-
-      /* second column */
-      blurb[0] = (shell_builtins[i+height].flags & BUILTIN_ENABLED) ? ' ' : '*';
-      strncpy (blurb + 1, _(shell_builtins[i+height].short_doc), width - 3);
-      blurb[width - 3] = '>';          /* indicate truncation */
-      blurb[width - 2] = '\0';
-      printf ("%s\n", blurb);
+#if defined (HANDLE_MULTIBYTE)
+      if (MB_CUR_MAX > 1)
+       wdispcolumn (i, blurb, sizeof (blurb), width, height);
+      else
+#endif
+       dispcolumn (i, blurb, sizeof (blurb), width, height);
     }
 }
 #endif /* HELP_BUILTIN */
     }
 }
 #endif /* HELP_BUILTIN */