[BACK]Return to lesskey.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / less

Diff for /src/usr.bin/less/lesskey.c between version 1.7 and 1.8

version 1.7, 2014/04/25 13:38:21 version 1.8, 2015/11/05 22:08:44
Line 6 
Line 6 
  *   *
  * For more information, see the README file.   * For more information, see the README file.
  */   */
   /*
    * Modified for use with illumos.
    * Copyright 2014 Garrett D'Amore <garrett@damore.org>
    */
   
   
 /*  /*
  *      lesskey [-o output] [input]   *      lesskey [-o output] [input]
  *   *
  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *   * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  *   *
  *      Make a .less file.   *      Make a .less file.
  *      If no input file is specified, standard input is used.   *      If no input file is specified, standard input is used.
Line 21 
Line 24 
  *      key bindings.  Basically any sequence of 1 to MAX_CMDLEN   *      key bindings.  Basically any sequence of 1 to MAX_CMDLEN
  *      keystrokes may be bound to an existing less function.   *      keystrokes may be bound to an existing less function.
  *   *
  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *   * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  *   *
  *      The input file is an ascii file consisting of a   *      The input file is an ascii file consisting of a
  *      sequence of lines of the form:   *      sequence of lines of the form:
  *              string <whitespace> action [chars] <newline>   *              string <whitespace> action [chars] <newline>
  *   *
Line 37 
Line 40 
  *                 to specify a character by its octal value.   *                 to specify a character by its octal value.
  *              4. A backslash followed by b, e, n, r or t   *              4. A backslash followed by b, e, n, r or t
  *                 to specify \b, ESC, \n, \r or \t, respectively.   *                 to specify \b, ESC, \n, \r or \t, respectively.
  *              5. Any character (other than those mentioned above) preceded   *              5. Any character (other than those mentioned above) preceded
  *                 by a \ to specify the character itself (characters which   *                 by a \ to specify the character itself (characters which
  *                 must be preceded by \ include ^, \, and whitespace.   *                 must be preceded by \ include ^, \, and whitespace.
  *      "action" is the name of a "less" action, from the table below.   *      "action" is the name of a "less" action, from the table below.
  *      "chars" is an optional sequence of characters which is treated   *      "chars" is an optional sequence of characters which is treated
  *              as keyboard input after the command is executed.   *              as keyboard input after the command is executed.
  *   *
  *      Blank lines and lines which start with # are ignored,   *      Blank lines and lines which start with # are ignored,
  *      except for the special control lines:   *      except for the special control lines:
  *              #command        Signals the beginning of the command   *              #command        Signals the beginning of the command
  *                              keys section.   *                              keys section.
Line 55 
Line 58 
  *              #stop           Stops command parsing in less;   *              #stop           Stops command parsing in less;
  *                              causes all default keys to be disabled.   *                              causes all default keys to be disabled.
  *   *
  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *   * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  *   *
  *      The output file is a non-ascii file, consisting of a header,   *      The output file is a non-ascii file, consisting of a header,
  *      one or more sections, and a trailer.   *      one or more sections, and a trailer.
Line 63 
Line 66 
  *      and the section data.  Normally there are three sections:   *      and the section data.  Normally there are three sections:
  *              CMD_SECTION     Definition of command keys.   *              CMD_SECTION     Definition of command keys.
  *              EDIT_SECTION    Definition of editing keys.   *              EDIT_SECTION    Definition of editing keys.
  *              END_SECTION     A special section header, with no   *              END_SECTION     A special section header, with no
  *                              length word or section data.   *                              length word or section data.
  *   *
  *      Section data consists of zero or more byte sequences of the form:   *      Section data consists of zero or more byte sequences of the form:
Line 77 
Line 80 
  *      If action is ORed with A_EXTRA, the action byte is followed   *      If action is ORed with A_EXTRA, the action byte is followed
  *              by the null-terminated "chars" string.   *              by the null-terminated "chars" string.
  *   *
  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *   * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  */   */
   
 #include "less.h"  #include "less.h"
Line 90 
Line 93 
         int cn_action;          int cn_action;
 };  };
   
 struct cmdname cmdnames[] =  static void lkerr(char *s);
   
   struct cmdname cmdnames[] =
 {  {
         { "back-bracket",         A_B_BRACKET },          { "back-bracket",               A_B_BRACKET },
         { "back-line",            A_B_LINE },          { "back-line",                  A_B_LINE },
         { "back-line-force",      A_BF_LINE },          { "back-line-force",            A_BF_LINE },
         { "back-screen",          A_B_SCREEN },          { "back-screen",                A_B_SCREEN },
         { "back-scroll",          A_B_SCROLL },          { "back-scroll",                A_B_SCROLL },
         { "back-search",          A_B_SEARCH },          { "back-search",                A_B_SEARCH },
         { "back-window",          A_B_WINDOW },          { "back-window",                A_B_WINDOW },
         { "debug",                A_DEBUG },          { "debug",                      A_DEBUG },
         { "digit",                A_DIGIT },          { "digit",                      A_DIGIT },
         { "display-flag",         A_DISP_OPTION },          { "display-flag",               A_DISP_OPTION },
         { "display-option",       A_DISP_OPTION },          { "display-option",             A_DISP_OPTION },
         { "end",                  A_GOEND },          { "end",                        A_GOEND },
         { "examine",              A_EXAMINE },          { "examine",                    A_EXAMINE },
         { "filter",               A_FILTER },          { "filter",                     A_FILTER },
         { "first-cmd",            A_FIRSTCMD },          { "first-cmd",                  A_FIRSTCMD },
         { "firstcmd",             A_FIRSTCMD },          { "firstcmd",                   A_FIRSTCMD },
         { "flush-repaint",        A_FREPAINT },          { "flush-repaint",              A_FREPAINT },
         { "forw-bracket",         A_F_BRACKET },          { "forw-bracket",               A_F_BRACKET },
         { "forw-forever",         A_F_FOREVER },          { "forw-forever",               A_F_FOREVER },
         { "forw-until-hilite",    A_F_UNTIL_HILITE },          { "forw-until-hilite",          A_F_UNTIL_HILITE },
         { "forw-line",            A_F_LINE },          { "forw-line",                  A_F_LINE },
         { "forw-line-force",      A_FF_LINE },          { "forw-line-force",            A_FF_LINE },
         { "forw-screen",          A_F_SCREEN },          { "forw-screen",                A_F_SCREEN },
         { "forw-screen-force",    A_FF_SCREEN },          { "forw-screen-force",          A_FF_SCREEN },
         { "forw-scroll",          A_F_SCROLL },          { "forw-scroll",                A_F_SCROLL },
         { "forw-search",          A_F_SEARCH },          { "forw-search",                A_F_SEARCH },
         { "forw-window",          A_F_WINDOW },          { "forw-skip",                  A_F_SKIP },
         { "goto-end",             A_GOEND },          { "forw-window",                A_F_WINDOW },
         { "goto-line",            A_GOLINE },          { "goto-end",                   A_GOEND },
         { "goto-mark",            A_GOMARK },          { "goto-line",                  A_GOLINE },
         { "help",                 A_HELP },          { "goto-mark",                  A_GOMARK },
         { "index-file",           A_INDEX_FILE },          { "help",                       A_HELP },
         { "invalid",              A_UINVALID },          { "index-file",                 A_INDEX_FILE },
         { "left-scroll",          A_LSHIFT },          { "invalid",                    A_UINVALID },
         { "next-file",            A_NEXT_FILE },          { "left-scroll",                A_LSHIFT },
         { "next-tag",             A_NEXT_TAG },          { "next-file",                  A_NEXT_FILE },
         { "noaction",             A_NOACTION },          { "next-tag",                   A_NEXT_TAG },
         { "percent",              A_PERCENT },          { "noaction",                   A_NOACTION },
         { "pipe",                 A_PIPE },          { "percent",                    A_PERCENT },
         { "prev-file",            A_PREV_FILE },          { "pipe",                       A_PIPE },
         { "prev-tag",             A_PREV_TAG },          { "prev-file",                  A_PREV_FILE },
         { "quit",                 A_QUIT },          { "prev-tag",                   A_PREV_TAG },
         { "remove-file",          A_REMOVE_FILE },          { "quit",                       A_QUIT },
         { "repaint",              A_REPAINT },          { "remove-file",                A_REMOVE_FILE },
         { "repaint-flush",        A_FREPAINT },          { "repaint",                    A_REPAINT },
         { "repeat-search",        A_AGAIN_SEARCH },          { "repaint-flush",              A_FREPAINT },
         { "repeat-search-all",    A_T_AGAIN_SEARCH },          { "repeat-search",              A_AGAIN_SEARCH },
         { "reverse-search",       A_REVERSE_SEARCH },          { "repeat-search-all",          A_T_AGAIN_SEARCH },
         { "reverse-search-all",   A_T_REVERSE_SEARCH },          { "reverse-search",             A_REVERSE_SEARCH },
         { "right-scroll",         A_RSHIFT },          { "reverse-search-all",         A_T_REVERSE_SEARCH },
         { "set-mark",             A_SETMARK },          { "right-scroll",               A_RSHIFT },
         { "shell",                A_SHELL },          { "set-mark",                   A_SETMARK },
         { "status",               A_STAT },          { "shell",                      A_SHELL },
         { "toggle-flag",          A_OPT_TOGGLE },          { "status",                     A_STAT },
         { "toggle-option",        A_OPT_TOGGLE },          { "toggle-flag",                A_OPT_TOGGLE },
         { "undo-hilite",          A_UNDO_SEARCH },          { "toggle-option",              A_OPT_TOGGLE },
         { "version",              A_VERSION },          { "undo-hilite",                A_UNDO_SEARCH },
         { "visual",               A_VISUAL },          { "version",                    A_VERSION },
         { NULL,   0 }          { "visual",                     A_VISUAL },
           { NULL,                         0 }
 };  };
   
 struct cmdname editnames[] =  struct cmdname editnames[] = {
 {  
         { "back-complete",      EC_B_COMPLETE },          { "back-complete",      EC_B_COMPLETE },
         { "backspace",          EC_BACKSPACE },          { "backspace",          EC_BACKSPACE },
         { "delete",             EC_DELETE },          { "delete",             EC_DELETE },
Line 191 
Line 196 
 struct table *currtable = &cmdtable;  struct table *currtable = &cmdtable;
   
 char fileheader[] = {  char fileheader[] = {
         C0_LESSKEY_MAGIC,          C0_LESSKEY_MAGIC,
         C1_LESSKEY_MAGIC,          C1_LESSKEY_MAGIC,
         C2_LESSKEY_MAGIC,          C2_LESSKEY_MAGIC,
         C3_LESSKEY_MAGIC          C3_LESSKEY_MAGIC
 };  };
 char filetrailer[] = {  char filetrailer[] = {
         C0_END_LESSKEY_MAGIC,          C0_END_LESSKEY_MAGIC,
         C1_END_LESSKEY_MAGIC,          C1_END_LESSKEY_MAGIC,
         C2_END_LESSKEY_MAGIC          C2_END_LESSKEY_MAGIC
 };  };
 char cmdsection[1] =    { CMD_SECTION };  char cmdsection[1] =    { CMD_SECTION };
Line 207 
Line 212 
 char endsection[1] =    { END_SECTION };  char endsection[1] =    { END_SECTION };
   
 char *infile = NULL;  char *infile = NULL;
 char *outfile = NULL ;  char *outfile = NULL;
   
 int linenum;  int linenum;
 int errors;  int errors;
   
 extern char version[];  extern char version[];
   
         void  void
 usage()  usage(void)
 {  {
         fprintf(stderr, "usage: lesskey [-o output] [input]\n");          (void) fprintf(stderr, "usage: lesskey [-o output] [input]\n");
         exit(1);          exit(1);
 }  }
   
         char *  char *
 mkpathname(dirname, filename)  mkpathname(char *dirname, char *filename)
         char *dirname;  
         char *filename;  
 {  {
         char *pathname;          char *pathname;
         size_t len;          size_t len;
   
         len = strlen(dirname) + strlen(filename) + 2;          len = strlen(dirname) + strlen(filename) + 2;
         pathname = calloc(len, sizeof(char));          pathname = calloc(1, len);
         strlcpy(pathname, dirname, len);          if (pathname == NULL) {
         strlcat(pathname, PATHNAME_SEP, len);                  fprintf(stderr, "mkpathname: out of memory\n");
         strlcat(pathname, filename, len);                  exit(1);
           }
           (void) snprintf(pathname, len, "%s/%s", dirname, filename);
         return (pathname);          return (pathname);
 }  }
   
 /*  /*
  * Figure out the name of a default file (in the user's HOME directory).   * Figure out the name of a default file (in the user's HOME directory).
  */   */
         char *  char *
 homefile(filename)  homefile(char *filename)
         char *filename;  
 {  {
         char *p;          char *p;
         char *pathname;          char *pathname;
   
         if ((p = getenv("HOME")) != NULL && *p != '\0')          if ((p = getenv("HOME")) != NULL && *p != '\0') {
                 pathname = mkpathname(p, filename);                  pathname = mkpathname(p, filename);
 #if OS2          } else {
         else if ((p = getenv("INIT")) != NULL && *p != '\0')                  (void) fprintf(stderr, "cannot find $HOME - "
                 pathname = mkpathname(p, filename);                      "using current directory\n");
 #endif  
         else  
         {  
                 fprintf(stderr, "cannot find $HOME - using current directory\n");  
                 pathname = mkpathname(".", filename);                  pathname = mkpathname(".", filename);
         }          }
         return (pathname);          return (pathname);
Line 264 
Line 264 
 /*  /*
  * Parse command line arguments.   * Parse command line arguments.
  */   */
         void  void
 parse_args(argc, argv)  parse_args(int argc, char **argv)
         int argc;  
         char **argv;  
 {  {
         char *arg;          char *arg;
   
         outfile = NULL;          outfile = NULL;
         while (--argc > 0)          while (--argc > 0) {
         {  
                 arg = *++argv;                  arg = *++argv;
                 if (arg[0] != '-')                  if (arg[0] != '-')
                         /* Arg does not start with "-"; it's not an option. */                          /* Arg does not start with "-"; it's not an option. */
Line 281 
Line 278 
                 if (arg[1] == '\0')                  if (arg[1] == '\0')
                         /* "-" means standard input. */                          /* "-" means standard input. */
                         break;                          break;
                 if (arg[1] == '-' && arg[2] == '\0')                  if (arg[1] == '-' && arg[2] == '\0') {
                 {  
                         /* "--" means end of options. */                          /* "--" means end of options. */
                         argc--;                          argc--;
                         argv++;                          argv++;
                         break;                          break;
                 }                  }
                 switch (arg[1])                  switch (arg[1]) {
                 {  
                 case '-':                  case '-':
                         if (strncmp(arg, "--output", 8) == 0)                          if (strncmp(arg, "--output", 8) == 0) {
                         {  
                                 if (arg[8] == '\0')                                  if (arg[8] == '\0')
                                         outfile = &arg[8];                                          outfile = &arg[8];
                                 else if (arg[8] == '=')                                  else if (arg[8] == '=')
Line 301 
Line 295 
                                         usage();                                          usage();
                                 goto opt_o;                                  goto opt_o;
                         }                          }
                         if (strcmp(arg, "--version") == 0)                          if (strcmp(arg, "--version") == 0) {
                         {  
                                 goto opt_V;                                  goto opt_V;
                         }                          }
                         usage();                          usage();
Line 310 
Line 303 
                 case 'o':                  case 'o':
                         outfile = &argv[0][2];                          outfile = &argv[0][2];
                 opt_o:                  opt_o:
                         if (*outfile == '\0')                          if (*outfile == '\0') {
                         {  
                                 if (--argc <= 0)                                  if (--argc <= 0)
                                         usage();                                          usage();
                                 outfile = *(++argv);                                  outfile = *(++argv);
Line 319 
Line 311 
                         break;                          break;
                 case 'V':                  case 'V':
                 opt_V:                  opt_V:
                         printf("lesskey  version %s\n", version);                          (void) printf("lesskey  version %s\n", version);
                         exit(0);                          exit(0);
                 default:                  default:
                         usage();                          usage();
Line 339 
Line 331 
 /*  /*
  * Initialize data structures.   * Initialize data structures.
  */   */
         void  void
 init_tables()  init_tables(void)
 {  {
         cmdtable.names = cmdnames;          cmdtable.names = cmdnames;
         cmdtable.pbuffer = cmdtable.buffer;          cmdtable.pbuffer = cmdtable.buffer;
Line 355 
Line 347 
 /*  /*
  * Parse one character of a string.   * Parse one character of a string.
  */   */
         char *  char *
 tstr(pp, xlate)  tstr(char **pp, int xlate)
         char **pp;  
         int xlate;  
 {  {
         register char *p;          char *p;
         register char ch;          char ch;
         register int i;          int i;
         static char buf[10];          static char buf[10];
         static char tstr_control_k[] =          static char tstr_control_k[] =
                 { SK_SPECIAL_KEY, SK_CONTROL_K, 6, 1, 1, 1, '\0' };                  { SK_SPECIAL_KEY, SK_CONTROL_K, 6, 1, 1, 1, '\0' };
   
         p = *pp;          p = *pp;
         switch (*p)          switch (*p) {
         {  
         case '\\':          case '\\':
                 ++p;                  ++p;
                 switch (*p)                  switch (*p) {
                 {  
                 case '0': case '1': case '2': case '3':                  case '0': case '1': case '2': case '3':
                 case '4': case '5': case '6': case '7':                  case '4': case '5': case '6': case '7':
                         /*                          /*
Line 383 
Line 371 
                         i = 0;                          i = 0;
                         do                          do
                                 ch = 8*ch + (*p - '0');                                  ch = 8*ch + (*p - '0');
                         while (*++p >= '0' && *p <= '7' && ++i < 3);                          while (*++p >= '0' && *p <= '7' && ++i < 3)
                                   ;
                         *pp = p;                          *pp = p;
                         if (xlate && ch == CONTROL('K'))                          if (xlate && ch == CONTROL('K'))
                                 return tstr_control_k;                                  return (tstr_control_k);
                         buf[0] = ch;                          buf[0] = ch;
                         buf[1] = '\0';                          buf[1] = '\0';
                         return (buf);                          return (buf);
Line 408 
Line 397 
                         *pp = p+1;                          *pp = p+1;
                         return ("\t");                          return ("\t");
                 case 'k':                  case 'k':
                         if (xlate)                          if (xlate) {
                         {                                  switch (*++p) {
                                 switch (*++p)  
                                 {  
                                 case 'u': ch = SK_UP_ARROW; break;                                  case 'u': ch = SK_UP_ARROW; break;
                                 case 'd': ch = SK_DOWN_ARROW; break;                                  case 'd': ch = SK_DOWN_ARROW; break;
                                 case 'r': ch = SK_RIGHT_ARROW; break;                                  case 'r': ch = SK_RIGHT_ARROW; break;
Line 422 
Line 409 
                                 case 'e': ch = SK_END; break;                                  case 'e': ch = SK_END; break;
                                 case 'x': ch = SK_DELETE; break;                                  case 'x': ch = SK_DELETE; break;
                                 default:                                  default:
                                         error("illegal char after \\k");                                          lkerr("illegal char after \\k");
                                         *pp = p+1;                                          *pp = p+1;
                                         return ("");                                          return ("");
                                 }                                  }
Line 439 
Line 426 
                         /* FALLTHRU */                          /* FALLTHRU */
                 default:                  default:
                         /*                          /*
                          * Backslash followed by any other char                           * Backslash followed by any other char
                          * just means that char.                           * just means that char.
                          */                           */
                         *pp = p+1;                          *pp = p+1;
                         buf[0] = *p;                          buf[0] = *p;
                         buf[1] = '\0';                          buf[1] = '\0';
                         if (xlate && buf[0] == CONTROL('K'))                          if (xlate && buf[0] == CONTROL('K'))
                                 return tstr_control_k;                                  return (tstr_control_k);
                         return (buf);                          return (buf);
                 }                  }
         case '^':          case '^':
Line 457 
Line 444 
                 buf[0] = CONTROL(p[1]);                  buf[0] = CONTROL(p[1]);
                 buf[1] = '\0';                  buf[1] = '\0';
                 if (buf[0] == CONTROL('K'))                  if (buf[0] == CONTROL('K'))
                         return tstr_control_k;                          return (tstr_control_k);
                 return (buf);                  return (buf);
         }          }
         *pp = p+1;          *pp = p+1;
         buf[0] = *p;          buf[0] = *p;
         buf[1] = '\0';          buf[1] = '\0';
         if (xlate && buf[0] == CONTROL('K'))          if (xlate && buf[0] == CONTROL('K'))
                 return tstr_control_k;                  return (tstr_control_k);
         return (buf);          return (buf);
 }  }
   
 /*  /*
  * Skip leading spaces in a string.   * Skip leading spaces in a string.
  */   */
         public char *  char *
 skipsp(s)  skipsp(char *s)
         register char *s;  
 {  {
         while (*s == ' ' || *s == '\t')          while (*s == ' ' || *s == '\t')
                 s++;                  s++;
         return (s);          return (s);
 }  }
Line 483 
Line 469 
 /*  /*
  * Skip non-space characters in a string.   * Skip non-space characters in a string.
  */   */
         public char *  char *
 skipnsp(s)  skipnsp(char *s)
         register char *s;  
 {  {
         while (*s != '\0' && *s != ' ' && *s != '\t')          while (*s != '\0' && *s != ' ' && *s != '\t')
                 s++;                  s++;
Line 496 
Line 481 
  * Clean up an input line:   * Clean up an input line:
  * strip off the trailing newline & any trailing # comment.   * strip off the trailing newline & any trailing # comment.
  */   */
         char *  char *
 clean_line(s)  clean_line(char *s)
         char *s;  
 {  {
         register int i;          int i;
   
         s = skipsp(s);          s = skipsp(s);
         for (i = 0;  s[i] != '\n' && s[i] != '\r' && s[i] != '\0';  i++)          for (i = 0;  s[i] != '\n' && s[i] != '\r' && s[i] != '\0';  i++)
Line 513 
Line 497 
 /*  /*
  * Add a byte to the output command table.   * Add a byte to the output command table.
  */   */
         void  void
 add_cmd_char(c)  add_cmd_char(int c)
         int c;  
 {  {
         if (currtable->pbuffer >= currtable->buffer + MAX_USERCMD)          if (currtable->pbuffer >= currtable->buffer + MAX_USERCMD) {
         {                  lkerr("too many commands");
                 error("too many commands");  
                 exit(1);                  exit(1);
         }          }
         *(currtable->pbuffer)++ = c;          *(currtable->pbuffer)++ = (char)c;
 }  }
   
 /*  /*
  * Add a string to the output command table.   * Add a string to the output command table.
  */   */
         void  void
 add_cmd_str(s)  add_cmd_str(char *s)
         char *s;  
 {  {
         for ( ;  *s != '\0';  s++)          for (; *s != '\0'; s++)
                 add_cmd_char(*s);                  add_cmd_char(*s);
 }  }
   
 /*  /*
  * See if we have a special "control" line.   * See if we have a special "control" line.
  */   */
         int  int
 control_line(s)  control_line(char *s)
         char *s;  
 {  {
 #define PREFIX(str,pat) (strncmp(str,pat,strlen(pat)) == 0)  #define PREFIX(str, pat)        (strncmp(str, pat, strlen(pat)) == 0)
   
         if (PREFIX(s, "#line-edit"))          if (PREFIX(s, "#line-edit")) {
         {  
                 currtable = &edittable;                  currtable = &edittable;
                 return (1);                  return (1);
         }          }
         if (PREFIX(s, "#command"))          if (PREFIX(s, "#command")) {
         {  
                 currtable = &cmdtable;                  currtable = &cmdtable;
                 return (1);                  return (1);
         }          }
         if (PREFIX(s, "#env"))          if (PREFIX(s, "#env")) {
         {  
                 currtable = &vartable;                  currtable = &vartable;
                 return (1);                  return (1);
         }          }
         if (PREFIX(s, "#stop"))          if (PREFIX(s, "#stop")) {
         {  
                 add_cmd_char('\0');                  add_cmd_char('\0');
                 add_cmd_char(A_END_LIST);                  add_cmd_char(A_END_LIST);
                 return (1);                  return (1);
Line 572 
Line 548 
 /*  /*
  * Output some bytes.   * Output some bytes.
  */   */
         void  void
 fputbytes(fd, buf, len)  fputbytes(FILE *fd, char *buf, int len)
         FILE *fd;  
         char *buf;  
         int len;  
 {  {
         while (len-- > 0)          while (len-- > 0) {
         {                  (void) fwrite(buf, sizeof (char), 1, fd);
                 fwrite(buf, sizeof(char), 1, fd);  
                 buf++;                  buf++;
         }          }
 }  }
Line 588 
Line 560 
 /*  /*
  * Output an integer, in special KRADIX form.   * Output an integer, in special KRADIX form.
  */   */
         void  void
 fputint(fd, val)  fputint(FILE *fd, unsigned int val)
         FILE *fd;  
         unsigned int val;  
 {  {
         char c;          char c;
   
         if (val >= KRADIX*KRADIX)          if (val >= KRADIX*KRADIX) {
         {                  (void) fprintf(stderr, "error: integer too big (%d > %d)\n",
                 fprintf(stderr, "error: integer too big (%d > %d)\n",                      val, KRADIX*KRADIX);
                         val, KRADIX*KRADIX);  
                 exit(1);                  exit(1);
         }          }
         c = val % KRADIX;          c = val % KRADIX;
         fwrite(&c, sizeof(char), 1, fd);          (void) fwrite(&c, sizeof (char), 1, fd);
         c = val / KRADIX;          c = val / KRADIX;
         fwrite(&c, sizeof(char), 1, fd);          (void) fwrite(&c, sizeof (char), 1, fd);
 }  }
   
 /*  /*
  * Find an action, given the name of the action.   * Find an action, given the name of the action.
  */   */
         int  int
 findaction(actname)  findaction(char *actname)
         char *actname;  
 {  {
         int i;          int i;
   
         for (i = 0;  currtable->names[i].cn_name != NULL;  i++)          for (i = 0;  currtable->names[i].cn_name != NULL;  i++)
                 if (strcmp(currtable->names[i].cn_name, actname) == 0)                  if (strcmp(currtable->names[i].cn_name, actname) == 0)
                         return (currtable->names[i].cn_action);                          return (currtable->names[i].cn_action);
         error("unknown action");          lkerr("unknown action");
         return (A_INVALID);          return (A_INVALID);
 }  }
   
         void  void
 error(s)  lkerr(char *s)
         char *s;  
 {  {
         fprintf(stderr, "line %d: %s\n", linenum, s);          (void) fprintf(stderr, "line %d: %s\n", linenum, s);
         errors++;          errors++;
 }  }
   
   
         void  void
 parse_cmdline(p)  parse_cmdline(char *p)
         char *p;  
 {  {
         int cmdlen;          int cmdlen;
         char *actname;          char *actname;
Line 646 
Line 612 
          * Parse the command string and store it in the current table.           * Parse the command string and store it in the current table.
          */           */
         cmdlen = 0;          cmdlen = 0;
         do          do {
         {  
                 s = tstr(&p, 1);                  s = tstr(&p, 1);
                 cmdlen += strlen(s);                  cmdlen += strlen(s);
                 if (cmdlen > MAX_CMDLEN)                  if (cmdlen > MAX_CMDLEN)
                         error("command too long");                          lkerr("command too long");
                 else                  else
                         add_cmd_str(s);                          add_cmd_str(s);
         } while (*p != ' ' && *p != '\t' && *p != '\0');          } while (*p != ' ' && *p != '\t' && *p != '\0');
Line 666 
Line 631 
          * Terminate the action name with a null byte.           * Terminate the action name with a null byte.
          */           */
         p = skipsp(p);          p = skipsp(p);
         if (*p == '\0')          if (*p == '\0') {
         {                  lkerr("missing action");
                 error("missing action");  
                 return;                  return;
         }          }
         actname = p;          actname = p;
Line 686 
Line 650 
          */           */
         *p = c;          *p = c;
         p = skipsp(p);          p = skipsp(p);
         if (*p == '\0')          if (*p == '\0') {
         {  
                 add_cmd_char(action);                  add_cmd_char(action);
         } else          } else {
         {  
                 /*                  /*
                  * OR the special value A_EXTRA into the action byte.                   * OR the special value A_EXTRA into the action byte.
                  * Put the extra string after the action byte.                   * Put the extra string after the action byte.
Line 702 
Line 664 
         }          }
 }  }
   
         void  void
 parse_varline(p)  parse_varline(char *p)
         char *p;  
 {  {
         char *s;          char *s;
   
         do          do {
         {  
                 s = tstr(&p, 0);                  s = tstr(&p, 0);
                 add_cmd_str(s);                  add_cmd_str(s);
         } while (*p != ' ' && *p != '\t' && *p != '=' && *p != '\0');          } while (*p != ' ' && *p != '\t' && *p != '=' && *p != '\0');
Line 719 
Line 679 
         add_cmd_char('\0');          add_cmd_char('\0');
   
         p = skipsp(p);          p = skipsp(p);
         if (*p++ != '=')          if (*p++ != '=') {
         {                  lkerr("missing =");
                 error("missing =");  
                 return;                  return;
         }          }
   
         add_cmd_char(EV_OK|A_EXTRA);          add_cmd_char(EV_OK|A_EXTRA);
   
         p = skipsp(p);          p = skipsp(p);
         while (*p != '\0')          while (*p != '\0') {
         {  
                 s = tstr(&p, 0);                  s = tstr(&p, 0);
                 add_cmd_str(s);                  add_cmd_str(s);
         }          }
Line 739 
Line 697 
 /*  /*
  * Parse a line from the lesskey file.   * Parse a line from the lesskey file.
  */   */
         void  void
 parse_line(line)  parse_line(char *line)
         char *line;  
 {  {
         char *p;          char *p;
   
Line 765 
Line 722 
                 parse_cmdline(p);                  parse_cmdline(p);
 }  }
   
         int  int
 main(argc, argv)  main(int argc, char **argv)
         int argc;  
         char *argv[];  
 {  {
         FILE *desc;          FILE *desc;
         FILE *out;          FILE *out;
         char line[1024];          char line[1024];
   
 #ifdef WIN32  
         if (getenv("HOME") == NULL)  
         {  
                 /*  
                  * If there is no HOME environment variable,  
                  * try the concatenation of HOMEDRIVE + HOMEPATH.  
                  */  
                 char *drive = getenv("HOMEDRIVE");  
                 char *path  = getenv("HOMEPATH");  
                 if (drive != NULL && path != NULL)  
                 {  
                         size_t len = strlen(drive) + strlen(path) + 6;  
                         char *env = (char *) calloc(len, sizeof(char));  
                         strlcpy(env, "HOME=", len);  
                         strlcat(env, drive, len);  
                         strlcat(env, path, len);  
                         putenv(env);  
                 }  
         }  
 #endif /* WIN32 */  
   
         /*          /*
          * Process command line arguments.           * Process command line arguments.
          */           */
Line 806 
Line 740 
          */           */
         if (strcmp(infile, "-") == 0)          if (strcmp(infile, "-") == 0)
                 desc = stdin;                  desc = stdin;
         else if ((desc = fopen(infile, "r")) == NULL)          else if ((desc = fopen(infile, "r")) == NULL) {
         {  
 #if HAVE_PERROR  
                 perror(infile);                  perror(infile);
 #else  
                 fprintf(stderr, "Cannot open %s\n", infile);  
 #endif  
                 usage();                  usage();
         }          }
   
Line 821 
Line 750 
          */           */
         errors = 0;          errors = 0;
         linenum = 0;          linenum = 0;
         while (fgets(line, sizeof(line), desc) != NULL)          while (fgets(line, sizeof (line), desc) != NULL) {
         {  
                 ++linenum;                  ++linenum;
                 parse_line(line);                  parse_line(line);
         }          }
Line 831 
Line 759 
          * Write the output file.           * Write the output file.
          * If no output file was specified, use "$HOME/.less"           * If no output file was specified, use "$HOME/.less"
          */           */
         if (errors > 0)          if (errors > 0) {
         {                  (void) fprintf(stderr, "%d errors; no output produced\n",
                 fprintf(stderr, "%d errors; no output produced\n", errors);                      errors);
                 exit(1);                  exit(1);
         }          }
   
Line 841 
Line 769 
                 outfile = getenv("LESSKEY");                  outfile = getenv("LESSKEY");
         if (outfile == NULL)          if (outfile == NULL)
                 outfile = homefile(LESSKEYFILE);                  outfile = homefile(LESSKEYFILE);
         if ((out = fopen(outfile, "wb")) == NULL)          if ((out = fopen(outfile, "wb")) == NULL) {
         {  
 #if HAVE_PERROR  
                 perror(outfile);                  perror(outfile);
 #else  
                 fprintf(stderr, "Cannot open %s\n", outfile);  
 #endif  
                 exit(1);                  exit(1);
         }          }
   
         /* File header */          /* File header */
         fputbytes(out, fileheader, sizeof(fileheader));          fputbytes(out, fileheader, sizeof (fileheader));
   
         /* Command key section */          /* Command key section */
         fputbytes(out, cmdsection, sizeof(cmdsection));          fputbytes(out, cmdsection, sizeof (cmdsection));
         fputint(out, cmdtable.pbuffer - cmdtable.buffer);          fputint(out, cmdtable.pbuffer - cmdtable.buffer);
         fputbytes(out, (char *)cmdtable.buffer, cmdtable.pbuffer-cmdtable.buffer);          fputbytes(out, (char *)cmdtable.buffer,
               cmdtable.pbuffer-cmdtable.buffer);
   
         /* Edit key section */          /* Edit key section */
         fputbytes(out, editsection, sizeof(editsection));          fputbytes(out, editsection, sizeof (editsection));
         fputint(out, edittable.pbuffer - edittable.buffer);          fputint(out, edittable.pbuffer - edittable.buffer);
         fputbytes(out, (char *)edittable.buffer, edittable.pbuffer-edittable.buffer);          fputbytes(out, (char *)edittable.buffer,
               edittable.pbuffer-edittable.buffer);
   
         /* Environment variable section */          /* Environment variable section */
         fputbytes(out, varsection, sizeof(varsection));          fputbytes(out, varsection, sizeof (varsection));
         fputint(out, vartable.pbuffer - vartable.buffer);          fputint(out, vartable.pbuffer - vartable.buffer);
         fputbytes(out, (char *)vartable.buffer, vartable.pbuffer-vartable.buffer);          fputbytes(out, (char *)vartable.buffer,
               vartable.pbuffer-vartable.buffer);
   
         /* File trailer */          /* File trailer */
         fputbytes(out, endsection, sizeof(endsection));          fputbytes(out, endsection, sizeof (endsection));
         fputbytes(out, filetrailer, sizeof(filetrailer));          fputbytes(out, filetrailer, sizeof (filetrailer));
         return (0);          return (0);
 }  }

Legend:
Removed from v.1.7  
changed lines
  Added in v.1.8