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

Diff for /src/usr.bin/less/tags.c between version 1.11 and 1.12

version 1.11, 2014/04/25 13:38:21 version 1.12, 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>
    */
   
   
 #include "less.h"  #include "less.h"
   
 #define WHITESP(c)      ((c)==' ' || (c)=='\t')  #define WHITESP(c)      ((c) == ' ' || (c) == '\t')
   
 #if TAGS  char *tags = "tags";
   
 public char *tags = "tags";  
   
 static int total;  static int total;
 static int curseq;  static int curseq;
   
Line 46 
Line 47 
 static enum tag_result findgtag();  static enum tag_result findgtag();
 static char *nextgtag();  static char *nextgtag();
 static char *prevgtag();  static char *prevgtag();
 static POSITION ctagsearch();  static off_t ctagsearch();
 static POSITION gtagsearch();  static off_t gtagsearch();
 static int getentry();  static int getentry();
   
 /*  /*
Line 62 
Line 63 
         struct tag *tl_first;          struct tag *tl_first;
         struct tag *tl_last;          struct tag *tl_last;
 };  };
 #define TAG_END  ((struct tag *) &taglist)  #define TAG_END  ((struct tag *)&taglist)
 static struct taglist taglist = { TAG_END, TAG_END };  static struct taglist taglist = { TAG_END, TAG_END };
 struct tag {  struct tag {
         struct tag *next, *prev; /* List links */          struct tag *next, *prev; /* List links */
         char *tag_file;         /* Source file containing the tag */          char *tag_file;         /* Source file containing the tag */
         LINENUM tag_linenum;    /* Appropriate line number in source file */          LINENUM tag_linenum;    /* Appropriate line number in source file */
         char *tag_pattern;      /* Pattern used to find the tag */          char *tag_pattern;      /* Pattern used to find the tag */
         char tag_endline;       /* True if the pattern includes '$' */          int tag_endline;        /* True if the pattern includes '$' */
 };  };
 static struct tag *curtag;  static struct tag *curtag;
   
 #define TAG_INS(tp) \  #define TAG_INS(tp) \
         (tp)->next = TAG_END; \          (tp)->next = TAG_END; \
         (tp)->prev = taglist.tl_last; \          (tp)->prev = taglist.tl_last; \
         taglist.tl_last->next = (tp); \          taglist.tl_last->next = (tp); \
         taglist.tl_last = (tp);          taglist.tl_last = (tp);
   
 #define TAG_RM(tp) \  #define TAG_RM(tp) \
         (tp)->next->prev = (tp)->prev; \          (tp)->next->prev = (tp)->prev; \
         (tp)->prev->next = (tp)->next;          (tp)->prev->next = (tp)->next;
   
 /*  /*
  * Delete tag structures.   * Delete tag structures.
  */   */
         public void  void
 cleantags()  cleantags(void)
 {  {
         register struct tag *tp;          struct tag *tp;
   
         /*          /*
          * Delete any existing tag list.           * Delete any existing tag list.
          * {{ Ideally, we wouldn't do this until after we know that we           * {{ Ideally, we wouldn't do this until after we know that we
          *    can load some other tag information. }}           *    can load some other tag information. }}
          */           */
         while ((tp = taglist.tl_first) != TAG_END)          while ((tp = taglist.tl_first) != TAG_END) {
         {  
                 TAG_RM(tp);                  TAG_RM(tp);
                 free(tp);                  free(tp);
         }          }
Line 108 
Line 108 
 /*  /*
  * Create a new tag entry.   * Create a new tag entry.
  */   */
         static struct tag *  static struct tag *
 maketagent(name, file, linenum, pattern, endline)  maketagent(char *file, LINENUM linenum, char *pattern, int endline)
         char *name;  
         char *file;  
         LINENUM linenum;  
         char *pattern;  
         int endline;  
 {  {
         register struct tag *tp;          struct tag *tp;
   
         tp = (struct tag *) ecalloc(sizeof(struct tag), 1);          tp = ecalloc(sizeof (struct tag), 1);
         tp->tag_file = save(file);          tp->tag_file = save(file);
         tp->tag_linenum = linenum;          tp->tag_linenum = linenum;
         tp->tag_endline = endline;          tp->tag_endline = endline;
Line 132 
Line 127 
 /*  /*
  * Get tag mode.   * Get tag mode.
  */   */
         public int  static int
 gettagtype()  gettagtype(void)
 {  {
         int f;          int f;
   
         if (strcmp(tags, "GTAGS") == 0)          if (strcmp(tags, "GTAGS") == 0)
                 return T_GTAGS;                  return (T_GTAGS);
         if (strcmp(tags, "GRTAGS") == 0)          if (strcmp(tags, "GRTAGS") == 0)
                 return T_GRTAGS;                  return (T_GRTAGS);
         if (strcmp(tags, "GSYMS") == 0)          if (strcmp(tags, "GSYMS") == 0)
                 return T_GSYMS;                  return (T_GSYMS);
         if (strcmp(tags, "GPATH") == 0)          if (strcmp(tags, "GPATH") == 0)
                 return T_GPATH;                  return (T_GPATH);
         if (strcmp(tags, "-") == 0)          if (strcmp(tags, "-") == 0)
                 return T_CTAGS_X;                  return (T_CTAGS_X);
         f = open(tags, OPEN_READ);          f = open(tags, OPEN_READ);
         if (f >= 0)          if (f >= 0) {
         {                  (void) close(f);
                 close(f);                  return (T_CTAGS);
                 return T_CTAGS;  
         }          }
         return T_GTAGS;          return (T_GTAGS);
 }  }
   
 /*  /*
Line 163 
Line 157 
  * and "tagpattern" to the search pattern which should be used   * and "tagpattern" to the search pattern which should be used
  * to find the tag.   * to find the tag.
  */   */
         public void  void
 findtag(tag)  findtag(char *tag)
         register char *tag;  
 {  {
         int type = gettagtype();          int type = gettagtype();
         enum tag_result result;          enum tag_result result;
Line 174 
Line 167 
                 result = findctag(tag);                  result = findctag(tag);
         else          else
                 result = findgtag(tag, type);                  result = findgtag(tag, type);
         switch (result)          switch (result) {
         {  
         case TAG_FOUND:          case TAG_FOUND:
         case TAG_INTR:          case TAG_INTR:
                 break;                  break;
Line 194 
Line 186 
 /*  /*
  * Search for a tag.   * Search for a tag.
  */   */
         public POSITION  off_t
 tagsearch()  tagsearch(void)
 {  {
         if (curtag == NULL)          if (curtag == NULL)
                 return (NULL_POSITION);  /* No gtags loaded! */                  return (-1);  /* No gtags loaded! */
         if (curtag->tag_linenum != 0)          if (curtag->tag_linenum != 0)
                 return gtagsearch();                  return (gtagsearch());
         else          else
                 return ctagsearch();                  return (ctagsearch());
 }  }
   
 /*  /*
  * Go to the next tag.   * Go to the next tag.
  */   */
         public char *  char *
 nexttag(n)  nexttag(int n)
         int n;  
 {  {
         char *tagfile = (char *) NULL;          char *tagfile = NULL;
   
         while (n-- > 0)          while (n-- > 0)
                 tagfile = nextgtag();                  tagfile = nextgtag();
         return tagfile;          return (tagfile);
 }  }
   
 /*  /*
  * Go to the previous tag.   * Go to the previous tag.
  */   */
         public char *  char *
 prevtag(n)  prevtag(int n)
         int n;  
 {  {
         char *tagfile = (char *) NULL;          char *tagfile = NULL;
   
         while (n-- > 0)          while (n-- > 0)
                 tagfile = prevgtag();                  tagfile = prevgtag();
         return tagfile;          return (tagfile);
 }  }
   
 /*  /*
  * Return the total number of tags.   * Return the total number of tags.
  */   */
         public int  int
 ntags()  ntags(void)
 {  {
         return total;          return (total);
 }  }
   
 /*  /*
  * Return the sequence number of current tag.   * Return the sequence number of current tag.
  */   */
         public int  int
 curr_tag()  curr_tag(void)
 {  {
         return curseq;          return (curseq);
 }  }
   
 /*****************************************************************************  /*
  * ctags   * ctags
  */   */
   
Line 259 
Line 249 
  * Find tags in the "tags" file.   * Find tags in the "tags" file.
  * Sets curtag to the first tag entry.   * Sets curtag to the first tag entry.
  */   */
         static enum tag_result  static enum tag_result
 findctag(tag)  findctag(char *tag)
         register char *tag;  
 {  {
         char *p;          char *p;
         register FILE *f;          FILE *f;
         register int taglen;          int taglen;
         LINENUM taglinenum;          LINENUM taglinenum;
         char *tagfile;          char *tagfile;
         char *tagpattern;          char *tagpattern;
Line 279 
Line 268 
         f = fopen(p, "r");          f = fopen(p, "r");
         free(p);          free(p);
         if (f == NULL)          if (f == NULL)
                 return TAG_NOFILE;                  return (TAG_NOFILE);
   
         cleantags();          cleantags();
         total = 0;          total = 0;
Line 288 
Line 277 
         /*          /*
          * Search the tags file for the desired tag.           * Search the tags file for the desired tag.
          */           */
         while (fgets(tline, sizeof(tline), f) != NULL)          while (fgets(tline, sizeof (tline), f) != NULL) {
         {  
                 if (tline[0] == '!')                  if (tline[0] == '!')
                         /* Skip header of extended format. */                          /* Skip header of extended format. */
                         continue;                          continue;
Line 300 
Line 288 
                  * Found it.                   * Found it.
                  * The line contains the tag, the filename and the                   * The line contains the tag, the filename and the
                  * location in the file, separated by white space.                   * location in the file, separated by white space.
                  * The location is either a decimal line number,                   * The location is either a decimal line number,
                  * or a search pattern surrounded by a pair of delimiters.                   * or a search pattern surrounded by a pair of delimiters.
                  * Parse the line and extract these parts.                   * Parse the line and extract these parts.
                  */                   */
Line 328 
Line 316 
                         continue;                          continue;
   
                 /*                  /*
                  * First see if it is a line number.                   * First see if it is a line number.
                  */                   */
                 tagendline = 0;                  tagendline = 0;
                 taglinenum = getnum(&p, 0, &err);                  taglinenum = getnum(&p, 0, &err);
                 if (err)                  if (err) {
                 {  
                         /*                          /*
                          * No, it must be a pattern.                           * No, it must be a pattern.
                          * Delete the initial "^" (if present) and                           * Delete the initial "^" (if present) and
                          * the final "$" from the pattern.                           * the final "$" from the pattern.
                          * Delete any backslash in the pattern.                           * Delete any backslash in the pattern.
                          */                           */
Line 345 
Line 332 
                         if (*p == '^')                          if (*p == '^')
                                 p++;                                  p++;
                         tagpattern = p;                          tagpattern = p;
                         while (*p != search_char && *p != '\0')                          while (*p != search_char && *p != '\0') {
                         {  
                                 if (*p == '\\')                                  if (*p == '\\')
                                         p++;                                          p++;
                                 p++;                                  p++;
Line 356 
Line 342 
                                 p--;                                  p--;
                         *p = '\0';                          *p = '\0';
                 }                  }
                 tp = maketagent(tag, tagfile, taglinenum, tagpattern, tagendline);                  tp = maketagent(tagfile, taglinenum, tagpattern, tagendline);
                 TAG_INS(tp);                  TAG_INS(tp);
                 total++;                  total++;
         }          }
         fclose(f);          fclose(f);
         if (total == 0)          if (total == 0)
                 return TAG_NOTAG;                  return (TAG_NOTAG);
         curtag = taglist.tl_first;          curtag = taglist.tl_first;
         curseq = 1;          curseq = 1;
         return TAG_FOUND;          return (TAG_FOUND);
 }  }
   
 /*  /*
  * Edit current tagged file.   * Edit current tagged file.
  */   */
         public int  int
 edit_tagfile()  edit_tagfile(void)
 {  {
         if (curtag == NULL)          if (curtag == NULL)
                 return (1);                  return (1);
Line 385 
Line 371 
  * We don't use search() for several reasons:   * We don't use search() for several reasons:
  *   -  We don't want to blow away any search string we may have saved.   *   -  We don't want to blow away any search string we may have saved.
  *   -  The various regular-expression functions (from different systems:   *   -  The various regular-expression functions (from different systems:
  *      regcmp vs. re_comp) behave differently in the presence of   *      regcmp vs. re_comp) behave differently in the presence of
  *      parentheses (which are almost always found in a tag).   *      parentheses (which are almost always found in a tag).
  */   */
         static POSITION  static off_t
 ctagsearch()  ctagsearch(void)
 {  {
         POSITION pos, linepos;          off_t pos, linepos;
         LINENUM linenum;          LINENUM linenum;
         int len;          int len;
         char *line;          char *line;
Line 399 
Line 385 
         pos = ch_zero();          pos = ch_zero();
         linenum = find_linenum(pos);          linenum = find_linenum(pos);
   
         for (;;)          for (;;) {
         {  
                 /*                  /*
                  * Get lines until we find a matching one or                   * Get lines until we find a matching one or
                  * until we hit end-of-file.                   * until we hit end-of-file.
                  */                   */
                 if (ABORT_SIGS())                  if (ABORT_SIGS())
                         return (NULL_POSITION);                          return (-1);
   
                 /*                  /*
                  * Read the next line, and save the                   * Read the next line, and save the
                  * starting position of that line in linepos.                   * starting position of that line in linepos.
                  */                   */
                 linepos = pos;                  linepos = pos;
Line 417 
Line 402 
                 if (linenum != 0)                  if (linenum != 0)
                         linenum++;                          linenum++;
   
                 if (pos == NULL_POSITION)                  if (pos == -1) {
                 {  
                         /*                          /*
                          * We hit EOF without a match.                           * We hit EOF without a match.
                          */                           */
                         error("Tag not found", NULL_PARG);                          error("Tag not found", NULL_PARG);
                         return (NULL_POSITION);                          return (-1);
                 }                  }
   
                 /*                  /*
Line 443 
Line 427 
                  */                   */
                 len = strlen(curtag->tag_pattern);                  len = strlen(curtag->tag_pattern);
                 if (strncmp(curtag->tag_pattern, line, len) == 0 &&                  if (strncmp(curtag->tag_pattern, line, len) == 0 &&
                     (!curtag->tag_endline || line[len] == '\0' || line[len] == '\r'))                      (!curtag->tag_endline || line[len] == '\0' ||
                 {                      line[len] == '\r')) {
                         curtag->tag_linenum = find_linenum(linepos);                          curtag->tag_linenum = find_linenum(linepos);
                         break;                          break;
                 }                  }
Line 453 
Line 437 
         return (linepos);          return (linepos);
 }  }
   
 /*******************************************************************************  /*
  * gtags   * gtags
  */   */
   
Line 464 
Line 448 
  * for future use by gtagsearch().   * for future use by gtagsearch().
  * Sets curtag to the first tag entry.   * Sets curtag to the first tag entry.
  */   */
         static enum tag_result  static enum tag_result
 findgtag(tag, type)  findgtag(char *tag, int type)
         char *tag;              /* tag to load */  
         int type;               /* tags type */  
 {  {
         char buf[256];          char buf[256];
         FILE *fp;          FILE *fp;
         struct tag *tp;          struct tag *tp;
         size_t len;  
   
         if (type != T_CTAGS_X && tag == NULL)          if (type != T_CTAGS_X && tag == NULL)
                 return TAG_NOFILE;                  return (TAG_NOFILE);
   
         cleantags();          cleantags();
         total = 0;          total = 0;
Line 484 
Line 465 
          * If type == T_CTAGS_X then read ctags's -x format from stdin           * If type == T_CTAGS_X then read ctags's -x format from stdin
          * else execute global(1) and read from it.           * else execute global(1) and read from it.
          */           */
         if (type == T_CTAGS_X)          if (type == T_CTAGS_X) {
         {  
                 fp = stdin;                  fp = stdin;
                 /* Set tag default because we cannot read stdin again. */                  /* Set tag default because we cannot read stdin again. */
                 tags = "tags";                  tags = "tags";
         } else          } else {
         {  
 #if !HAVE_POPEN  
                 return TAG_NOFILE;  
 #else  
                 char *command;                  char *command;
                 char *flag;                  char *flag;
                 char *qtag;                  char *qtag;
                 char *cmd = lgetenv("LESSGLOBALTAGS");                  char *cmd = lgetenv("LESSGLOBALTAGS");
   
                 if (cmd == NULL || *cmd == '\0')                  if (cmd == NULL || *cmd == '\0')
                         return TAG_NOFILE;                          return (TAG_NOFILE);
                 /* Get suitable flag value for global(1). */                  /* Get suitable flag value for global(1). */
                 switch (type)                  switch (type) {
                 {  
                 case T_GTAGS:                  case T_GTAGS:
                         flag = "" ;                          flag = "";
                         break;                          break;
                 case T_GRTAGS:                  case T_GRTAGS:
                         flag = "r";                          flag = "r";
Line 517 
Line 492 
                         flag = "P";                          flag = "P";
                         break;                          break;
                 default:                  default:
                         return TAG_NOTYPE;                          return (TAG_NOTYPE);
                 }                  }
   
                 /* Get our data from global(1). */                  /* Get our data from global(1). */
                 qtag = shell_quote(tag);                  qtag = shell_quote(tag);
                 if (qtag == NULL)                  if (qtag == NULL)
                         qtag = tag;                          qtag = tag;
                 len = strlen(cmd) + strlen(flag) + strlen(qtag) + 5;                  command = easprintf("%s -x%s %s", cmd, flag, qtag);
                 command = (char *) ecalloc(len, sizeof(char));  
                 snprintf(command, len, "%s -x%s %s", cmd, flag, qtag);  
                 if (qtag != tag)                  if (qtag != tag)
                         free(qtag);                          free(qtag);
                 fp = popen(command, "r");                  fp = popen(command, "r");
                 free(command);                  free(command);
 #endif  
         }          }
         if (fp != NULL)          if (fp != NULL) {
         {                  while (fgets(buf, sizeof (buf), fp)) {
                 while (fgets(buf, sizeof(buf), fp))  
                 {  
                         char *name, *file, *line;                          char *name, *file, *line;
                           int len;
   
                         if (sigs)                          if (sigs) {
                         {  
 #if HAVE_POPEN  
                                 if (fp != stdin)                                  if (fp != stdin)
                                         pclose(fp);                                          pclose(fp);
 #endif                                  return (TAG_INTR);
                                 return TAG_INTR;  
                         }                          }
                         len = strlen(buf);                          len = strlen(buf);
                         if (len > 0 && buf[len-1] == '\n')                          if (len > 0 && buf[len-1] == '\n') {
                                 buf[len-1] = '\0';                                  buf[len-1] = '\0';
                         else                          } else {
                         {  
                                 int c;                                  int c;
                                 do {                                  do {
                                         c = fgetc(fp);                                          c = fgetc(fp);
                                 } while (c != '\n' && c != EOF);                                  } while (c != '\n' && c != EOF);
                         }                          }
   
                         if (getentry(buf, &name, &file, &line))                          if (getentry(buf, &name, &file, &line)) {
                         {  
                                 /*                                  /*
                                  * Couldn't parse this line for some reason.                                   * Couldn't parse this line for some reason.
                                  * We'll just pretend it never happened.                                   * We'll just pretend it never happened.
Line 568 
Line 534 
                         }                          }
   
                         /* Make new entry and add to list. */                          /* Make new entry and add to list. */
                         tp = maketagent(name, file, (LINENUM) atoi(line), NULL, 0);                          tp = maketagent(file, (LINENUM) atoi(line), NULL, 0);
                         TAG_INS(tp);                          TAG_INS(tp);
                         total++;                          total++;
                 }                  }
                 if (fp != stdin)                  if (fp != stdin) {
                 {                          if (pclose(fp)) {
                         if (pclose(fp))  
                         {  
                                 curtag = NULL;                                  curtag = NULL;
                                 total = curseq = 0;                                  total = curseq = 0;
                                 return TAG_NOFILE;                                  return (TAG_NOFILE);
                         }                          }
                 }                  }
         }          }
Line 586 
Line 550 
         /* Check to see if we found anything. */          /* Check to see if we found anything. */
         tp = taglist.tl_first;          tp = taglist.tl_first;
         if (tp == TAG_END)          if (tp == TAG_END)
                 return TAG_NOTAG;                  return (TAG_NOTAG);
         curtag = tp;          curtag = tp;
         curseq = 1;          curseq = 1;
         return TAG_FOUND;          return (TAG_FOUND);
 }  }
   
 static int circular = 0;        /* 1: circular tag structure */  static int circular = 0;        /* 1: circular tag structure */
Line 599 
Line 563 
  * by findgtag().  The next call to gtagsearch() will try to position at the   * by findgtag().  The next call to gtagsearch() will try to position at the
  * appropriate tag.   * appropriate tag.
  */   */
         static char *  static char *
 nextgtag()  nextgtag(void)
 {  {
         struct tag *tp;          struct tag *tp;
   
         if (curtag == NULL)          if (curtag == NULL)
                 /* No tag loaded */                  /* No tag loaded */
                 return NULL;                  return (NULL);
   
         tp = curtag->next;          tp = curtag->next;
         if (tp == TAG_END)          if (tp == TAG_END) {
         {  
                 if (!circular)                  if (!circular)
                         return NULL;                          return (NULL);
                 /* Wrapped around to the head of the queue */                  /* Wrapped around to the head of the queue */
                 curtag = taglist.tl_first;                  curtag = taglist.tl_first;
                 curseq = 1;                  curseq = 1;
         } else          } else {
         {  
                 curtag = tp;                  curtag = tp;
                 curseq++;                  curseq++;
         }          }
Line 629 
Line 591 
  * setup by findgtat().  The next call to gtagsearch() will try to position   * setup by findgtat().  The next call to gtagsearch() will try to position
  * at the appropriate tag.   * at the appropriate tag.
  */   */
         static char *  static char *
 prevgtag()  prevgtag(void)
 {  {
         struct tag *tp;          struct tag *tp;
   
         if (curtag == NULL)          if (curtag == NULL)
                 /* No tag loaded */                  /* No tag loaded */
                 return NULL;                  return (NULL);
   
         tp = curtag->prev;          tp = curtag->prev;
         if (tp == TAG_END)          if (tp == TAG_END) {
         {  
                 if (!circular)                  if (!circular)
                         return NULL;                          return (NULL);
                 /* Wrapped around to the tail of the queue */                  /* Wrapped around to the tail of the queue */
                 curtag = taglist.tl_last;                  curtag = taglist.tl_last;
                 curseq = total;                  curseq = total;
         } else          } else {
         {  
                 curtag = tp;                  curtag = tp;
                 curseq--;                  curseq--;
         }          }
Line 659 
Line 619 
  * using either findtag() or one of nextgtag() and prevgtag().  Returns -1   * using either findtag() or one of nextgtag() and prevgtag().  Returns -1
  * if it was unable to position at the tag, 0 if successful.   * if it was unable to position at the tag, 0 if successful.
  */   */
         static POSITION  static off_t
 gtagsearch()  gtagsearch(void)
 {  {
         if (curtag == NULL)          if (curtag == NULL)
                 return (NULL_POSITION);  /* No gtags loaded! */                  return (-1);  /* No gtags loaded! */
         return (find_pos(curtag->tag_linenum));          return (find_pos(curtag->tag_linenum));
 }  }
   
Line 695 
Line 655 
  * The tag, file, and line will each be NUL-terminated pointers   * The tag, file, and line will each be NUL-terminated pointers
  * into buf.   * into buf.
  */   */
         static int  static int
 getentry(buf, tag, file, line)  getentry(char *buf, char **tag, char **file, char **line)
         char *buf;      /* standard or extended ctags -x format data */  
         char **tag;     /* name of the tag we actually found */  
         char **file;    /* file in which to find this tag */  
         char **line;    /* line number of file where this tag is found */  
 {  {
         char *p = buf;          char *p = buf;
   
         for (*tag = p;  *p && !IS_SPACE(*p);  p++)      /* tag name */          for (*tag = p; *p && !isspace(*p); p++)         /* tag name */
                 ;                  ;
         if (*p == 0)          if (*p == 0)
                 return (-1);                  return (-1);
         *p++ = 0;          *p++ = 0;
         for ( ;  *p && IS_SPACE(*p);  p++)              /* (skip blanks) */          for (; *p && isspace(*p); p++)                  /* (skip blanks) */
                 ;                  ;
         if (*p == 0)          if (*p == 0)
                 return (-1);                  return (-1);
Line 717 
Line 673 
          * If the second part begin with other than digit,           * If the second part begin with other than digit,
          * it is assumed tag type. Skip it.           * it is assumed tag type. Skip it.
          */           */
         if (!IS_DIGIT(*p))          if (!isdigit(*p)) {
         {                  for (; *p && !isspace(*p); p++)         /* (skip tag type) */
                 for ( ;  *p && !IS_SPACE(*p);  p++)     /* (skip tag type) */  
                         ;                          ;
                 for (;  *p && IS_SPACE(*p);  p++)       /* (skip blanks) */                  for (; *p && isspace(*p); p++)          /* (skip blanks) */
                         ;                          ;
         }          }
         if (!IS_DIGIT(*p))          if (!isdigit(*p))
                 return (-1);                  return (-1);
         *line = p;                                      /* line number */          *line = p;                                      /* line number */
         for (*line = p;  *p && !IS_SPACE(*p);  p++)          for (*line = p;  *p && !isspace(*p);  p++)
                 ;                  ;
         if (*p == 0)          if (*p == 0)
                 return (-1);                  return (-1);
         *p++ = 0;          *p++ = 0;
         for ( ; *p && IS_SPACE(*p);  p++)               /* (skip blanks) */          for (; *p && isspace(*p); p++)          /* (skip blanks) */
                 ;                  ;
         if (*p == 0)          if (*p == 0)
                 return (-1);                  return (-1);
         *file = p;                                      /* file name */          *file = p;                                      /* file name */
         for (*file = p;  *p && !IS_SPACE(*p);  p++)          for (*file = p;  *p && !isspace(*p);  p++)
                 ;                  ;
         if (*p == 0)          if (*p == 0)
                 return (-1);                  return (-1);
Line 748 
Line 703 
                 return (0);                  return (0);
         return (-1);          return (-1);
 }  }
   
 #endif  

Legend:
Removed from v.1.11  
changed lines
  Added in v.1.12