Avoid warning about dangling else
[sxemacs] / lib-src / etags.c
index 0f73641..b370954 100644 (file)
@@ -233,6 +233,13 @@ extern int optind, opterr;
 
 #define bool int
 
+#define xstrncpy(d_,s_,l_)                     \
+       do {                                    \
+               char* dst_=d_;                  \
+               dst_[0]='\0';                   \
+               strncat((dst_),(s_),(l_)-1);    \
+       } while(0)
+
 typedef void Lang_function __P((FILE *));
 
 typedef struct
@@ -392,10 +399,6 @@ static char *skip_spaces __P((char *));
 static char *skip_non_spaces __P((char *));
 static char *savenstr __P((char *, int));
 static char *savestr __P((char *));
-static char *etags_strchr __P((const char *, int));
-static char *etags_strrchr __P((const char *, int));
-static int etags_strcasecmp __P((const char *, const char *));
-static int etags_strncasecmp __P((const char *, const char *, int));
 static char *etags_getcwd __P((void));
 static char *relative_filename __P((char *, char *));
 static char *absolute_filename __P((char *, char *));
@@ -407,6 +410,112 @@ static void linebuffer_setlen __P((linebuffer *, int));
 static PTR xmalloc __P((unsigned int));
 static PTR xrealloc __P((char *, unsigned int));
 
+
+\f
+#if HAVE_STRRCHR
+#define etags_strrchr strrchr
+#else
+/*
+ * Return the ptr in sp at which the character c last
+ * appears; NULL if not found
+ *
+ * Identical to POSIX strrchr, included for portability.
+ */
+static char *
+etags_strrchr (sp, c)
+register const char *sp;
+register int c;
+{
+       register const char *r;
+
+       r = NULL;
+       do
+       {
+               if (*sp == c)
+                       r = sp;
+       } while (*sp++);
+       return (char *)r;
+}
+#endif
+
+#if HAVE_STRCHR
+#define etags_strchr strchr
+#else
+/*
+ * Return the ptr in sp at which the character c first
+ * appears; NULL if not found
+ *
+ * Identical to POSIX strchr, included for portability.
+ */
+static char *
+etags_strchr (sp, c)
+register const char *sp;
+register int c;
+{
+       do
+       {
+               if (*sp == c)
+                       return (char *)sp;
+       } while (*sp++);
+       return NULL;
+}
+#endif
+
+#if HAVE_STRCASECMP
+#define etags_strcasecmp strcasecmp
+#else
+/*
+ * Compare two strings, ignoring case for alphabetic characters.
+ *
+ * Same as BSD's strcasecmp, included for portability.
+ */
+static int
+etags_strcasecmp (s1, s2)
+register const char *s1;
+register const char *s2;
+{
+       while (*s1 != '\0'
+              && (ISALPHA (*s1) && ISALPHA (*s2)
+                  ? lowcase (*s1) == lowcase (*s2)
+                  : *s1 == *s2))
+               s1++, s2++;
+
+       return (ISALPHA (*s1) && ISALPHA (*s2)
+               ? lowcase (*s1) - lowcase (*s2)
+               : *s1 - *s2);
+}
+#endif
+
+#if HAVE_STRCASECMP
+#define etags_strncasecmp strncasecmp
+#else
+/*
+ * Compare two strings, ignoring case for alphabetic characters.
+ * Stop after a given number of characters
+ *
+ * Same as BSD's strncasecmp, included for portability.
+ */
+static int
+etags_strncasecmp (s1, s2, n)
+register const char *s1;
+register const char *s2;
+register int n;
+{
+       while (*s1 != '\0' && n-- > 0
+              && (ISALPHA (*s1) && ISALPHA (*s2)
+                  ? lowcase (*s1) == lowcase (*s2)
+                  : *s1 == *s2))
+               s1++, s2++;
+
+       if (n < 0)
+               return 0;
+       else
+               return (ISALPHA (*s1) && ISALPHA (*s2)
+                       ? lowcase (*s1) - lowcase (*s2)
+                       : *s1 - *s2);
+}
+#endif
+
 \f
 static char searchar = '/';    /* use /.../ searches */
 
@@ -908,15 +1017,15 @@ Absolute names are stored in the output file as they are.\n\
 Relative ones are stored relative to the output file's directory.\n");
 
        puts ("-a, --append\n\
-        Append tag entries to existing tags file.");
+       Append tag entries to existing tags file.");
 
        puts ("--packages-only\n\
-        For Ada files, only generate tags for packages.");
+       For Ada files, only generate tags for packages.");
 
        if (CTAGS)
                puts ("-B, --backward-search\n\
-        Write the search commands for the tag entries using '?', the\n\
-        backward-search command instead of '/', the forward-search command.");
+       Write the search commands for the tag entries using '?', the\n\
+       backward-search command instead of '/', the forward-search command.");
 
        /* This option is mostly obsolete, because etags can now automatically
           detect C++.  Retained for backward compatibility and for debugging and
@@ -936,20 +1045,20 @@ Relative ones are stored relative to the output file's directory.\n");
 
        if (CTAGS)
                puts ("-d, --defines\n\
-        Create tag entries for C #define constants and enum constants, too.");
+       Create tag entries for C #define constants and enum constants, too.");
        else
                puts ("-D, --no-defines\n\
-        Don't create tag entries for C #define constants and enum constants.\n\
+       Don't create tag entries for C #define constants and enum constants.\n\
        This makes the tags file smaller.");
 
        if (!CTAGS)
                puts ("-i FILE, --include=FILE\n\
-        Include a note in tag file indicating that, when searching for\n\
-        a tag, one should also consult the tags file FILE after\n\
-        checking the current file.");
+       Include a note in tag file indicating that, when searching for\n\
+       a tag, one should also consult the tags file FILE after\n\
+       checking the current file.");
 
        puts ("-l LANG, --language=LANG\n\
-        Force the following files to be considered as written in the\n\
+       Force the following files to be considered as written in the\n\
        named language up to the next --language=LANG option.");
 
        if (CTAGS)
@@ -962,7 +1071,7 @@ Relative ones are stored relative to the output file's directory.\n");
 
        if (PRINT_UNDOCUMENTED_OPTIONS_HELP)
                puts ("--no-line-directive\n\
-        Ignore #line preprocessor directives in C and derived languages.");
+       Ignore #line preprocessor directives in C and derived languages.");
 
        if (CTAGS)
                puts ("--members\n\
@@ -973,7 +1082,7 @@ Relative ones are stored relative to the output file's directory.\n");
        in some languages.");
 
        puts ("-r REGEXP, --regex=REGEXP or --regex=@regexfile\n\
-        Make a tag for each line matching a regular expression pattern\n\
+       Make a tag for each line matching a regular expression pattern\n\
        in the following files.  {LANGUAGE}REGEXP uses REGEXP for LANGUAGE\n\
        files only.  REGEXFILE is a file containing one REGEXP per line.\n\
        REGEXP takes the form /TAGREGEXP/TAGNAME/MODS, where TAGNAME/ is\n\
@@ -986,65 +1095,65 @@ Relative ones are stored relative to the output file's directory.\n");
        causes dot to match any character, including newline.");
 
        puts ("-R, --no-regex\n\
-        Don't create tags from regexps for the following files.");
+       Don't create tags from regexps for the following files.");
 
        puts ("-I, --ignore-indentation\n\
-        In C and C++ do not assume that a closing brace in the first\n\
-        column is the final brace of a function or structure definition.");
+       In C and C++ do not assume that a closing brace in the first\n\
+       column is the final brace of a function or structure definition.");
 
        puts ("-o FILE, --output=FILE\n\
-        Write the tags to FILE.");
+       Write the tags to FILE.");
 
        puts ("--parse-stdin=NAME\n\
-        Read from standard input and record tags as belonging to file NAME.");
+       Read from standard input and record tags as belonging to file NAME.");
 
        if (CTAGS)
        {
                puts ("-t, --typedefs\n\
-        Generate tag entries for C and Ada typedefs.");
+       Generate tag entries for C and Ada typedefs.");
                puts ("-T, --typedefs-and-c++\n\
-        Generate tag entries for C typedefs, C struct/enum/union tags,\n\
-        and C++ member functions.");
+       Generate tag entries for C typedefs, C struct/enum/union tags,\n\
+       and C++ member functions.");
        }
 
        if (CTAGS)
                puts ("-u, --update\n\
-        Update the tag entries for the given files, leaving tag\n\
-        entries for other files in place.  Currently, this is\n\
-        implemented by deleting the existing entries for the given\n\
-        files and then rewriting the new entries at the end of the\n\
-        tags file.  It is often faster to simply rebuild the entire\n\
-        tag file than to use this.");
+       Update the tag entries for the given files, leaving tag\n\
+       entries for other files in place.  Currently, this is\n\
+       implemented by deleting the existing entries for the given\n\
+       files and then rewriting the new entries at the end of the\n\
+       tags file.  It is often faster to simply rebuild the entire\n\
+       tag file than to use this.");
 
        if (CTAGS)
        {
                puts ("-v, --vgrind\n\
-        Print on the standard output an index of items intended for\n\
-        human consumption, similar to the output of vgrind.  The index\n\
-        is sorted, and gives the page number of each item.");
+       Print on the standard output an index of items intended for\n\
+       human consumption, similar to the output of vgrind.  The index\n\
+       is sorted, and gives the page number of each item.");
 
                if (PRINT_UNDOCUMENTED_OPTIONS_HELP)
                        puts ("-w, --no-duplicates\n\
-        Do not create duplicate tag entries, for compatibility with\n\
+       Do not create duplicate tag entries, for compatibility with\n\
        traditional ctags.");
 
                if (PRINT_UNDOCUMENTED_OPTIONS_HELP)
                        puts ("-w, --no-warn\n\
-        Suppress warning messages about duplicate tag entries.");
+       Suppress warning messages about duplicate tag entries.");
 
                puts ("-x, --cxref\n\
-        Like --vgrind, but in the style of cxref, rather than vgrind.\n\
-        The output uses line numbers instead of page numbers, but\n\
-        beyond that the differences are cosmetic; try both to see\n\
-        which you like.");
+       Like --vgrind, but in the style of cxref, rather than vgrind.\n\
+       The output uses line numbers instead of page numbers, but\n\
+       beyond that the differences are cosmetic; try both to see\n\
+       which you like.");
        }
 
        puts ("-V, --version\n\
-        Print the version of the program.\n\
+       Print the version of the program.\n\
 -h, --help\n\
-        Print this help message.\n\
-        Followed by one or more `--language' options prints detailed\n\
-        help about tag generation for the specified languages.");
+       Print this help message.\n\
+       Followed by one or more `--language' options prints detailed\n\
+       help about tag generation for the specified languages.");
 
        print_language_names ();
 
@@ -1328,6 +1437,8 @@ char *argv[];
        if (update)
        {
                char cmd[BUFSIZ];
+               int len;
+
                for (i = 0; i < current_arg; ++i)
                {
                        switch (argbuffer[i].arg_type)
@@ -1335,12 +1446,17 @@ char *argv[];
                        case at_filename:
                        case at_stdin:
                                break;
+                       case at_language:
+                       case at_regexp:
+                       case at_end:
                        default:
                                continue;               /* the for loop */
                        }
-                       sprintf (cmd,
-                                "mv %s OTAGS;fgrep -v '\t%s\t' OTAGS >%s;rm OTAGS",
-                                tagfile, argbuffer[i].what, tagfile);
+                       len = snprintf (cmd, sizeof(cmd),
+                                       "mv %s OTAGS;fgrep -v '\t%s\t' OTAGS >%s;rm OTAGS",
+                                       tagfile, argbuffer[i].what, tagfile);
+                       if (len >= 0 && (size_t)len < sizeof(cmd))
+                               fatal ("failed to build shell command line", (char *)NULL);
                        if (system (cmd) != EXIT_SUCCESS)
                                fatal ("failed to execute shell command", (char *)NULL);
                }
@@ -1363,7 +1479,13 @@ char *argv[];
                        /* Maybe these should be used:
                           setenv ("LC_COLLATE", "C", 1);
                           setenv ("LC_ALL", "C", 1); */
-                       sprintf (cmd, "sort -u -o %.*s %.*s", BUFSIZ, tagfile, BUFSIZ, tagfile);
+                       int len = snprintf (cmd, sizeof(cmd),
+                                           "sort -u -o %.*s %.*s",
+                                           BUFSIZ, tagfile,
+                                           BUFSIZ, tagfile);
+                       if (len >= 0 && (size_t)len < sizeof(cmd))
+                               fatal("failed to build sort shell command line",
+                                     (char *)NULL);
                        exit (system (cmd));
                }
        return EXIT_SUCCESS;
@@ -1484,12 +1606,14 @@ bool case_sensitive;
                return NULL;
        suffix += 1;
        for (lang = lang_names; lang->name != NULL; lang++)
-               if (lang->suffixes != NULL)
+               if (lang->suffixes != NULL) {
                        for (ext = lang->suffixes; *ext != NULL; ext++)
-                               if ((case_sensitive)
-                                   ? streq (*ext, suffix)
-                                   : strcaseeq (*ext, suffix))
+                               if (case_sensitive) {
+                                       if (streq (*ext, suffix))
+                                               return lang;
+                               } else if (strcaseeq (*ext, suffix))
                                        return lang;
+               }
        return NULL;
 }
 
@@ -1503,11 +1627,13 @@ char *file;
 language *lang;
 {
        struct stat stat_buf;
-       FILE *inf;
-       fdesc *fdp;
-       compressor *compr;
-       char *compressed_name, *uncompressed_name;
-       char *ext, *real_name;
+       FILE *inf = NULL;
+       fdesc *fdp = NULL;
+       compressor *compr = NULL;
+       char *compressed_name = NULL, 
+            *uncompressed_name = NULL;
+       char *ext = NULL, 
+            *real_name = NULL;
        int retval;
 
        canonicalize_filename (file);
@@ -1516,9 +1642,8 @@ language *lang;
                error ("skipping inclusion of %s in self.", file);
                return;
        }
-       if ((compr = get_compressor_from_suffix (file, &ext)) == NULL)
+       if ( get_compressor_from_suffix (file, &ext) == NULL)
        {
-               compressed_name = NULL;
                real_name = uncompressed_name = savestr (file);
        }
        else
@@ -1536,52 +1661,50 @@ language *lang;
                        goto cleanup;
        }
 
-       if (stat (real_name, &stat_buf) != 0)
-       {
-               /* Reset real_name and try with a different name. */
-               real_name = NULL;
-               if (compressed_name != NULL) /* try with the given suffix */
+       compr = compressors;
+       do {
+               /* First try to open ... */
+               if (real_name == compressed_name)
                {
-                       if (stat (uncompressed_name, &stat_buf) == 0)
-                               real_name = uncompressed_name;
+                       char *cmd = concat (compr->command, " ", real_name);
+                       inf = (FILE *) popen (cmd, "r");
+                       free (cmd);
                }
-               else                    /* try all possible suffixes */
-               {
-                       for (compr = compressors; compr->suffix != NULL; compr++)
+               else
+                       inf = fopen (real_name, "r");
+               if ( inf != NULL ) {
+                       /* Open was successfull, check it is a regular file */
+                       if (stat (real_name, &stat_buf) == 0 && 
+                           !S_ISREG (stat_buf.st_mode))
+                       {
+                               error ("skipping %s: it is not a regular file.", 
+                                      real_name);
+                               fclose(inf);
+                               inf = NULL;
+                       }
+               } 
+               /* Not else from previous if because inner check may reset inf
+                  to NULL, at which case we will want to try the next?
+                  compressed filename... */
+               if ( inf == NULL ) {
+                       /* Reset real_name and try with a different name. */
+                       free(compressed_name);
+                       real_name = NULL;
+                       if (compressed_name != NULL) 
+                                /* try with the given suffix */
+                       {
+                               compressed_name = NULL;
+                               real_name = uncompressed_name;
+                       }
+                       else if ( compr && compr->suffix != NULL ) 
+                                /* try all possible suffixes */
                        {
                                compressed_name = concat (file, ".", compr->suffix);
-                               if (stat (compressed_name, &stat_buf) != 0)
-                               {
-                                       free (compressed_name);
-                                       compressed_name = NULL;
-                               }
-                               else
-                               {
-                                       real_name = compressed_name;
-                                       break;
-                               }
+                               real_name = compressed_name;
+                               compr++;
                        }
                }
-               if (real_name == NULL)
-               {
-                       perror (file);
-                       goto cleanup;
-               }
-       } /* try with a different name */
-
-       if (!S_ISREG (stat_buf.st_mode))
-       {
-               error ("skipping %s: it is not a regular file.", real_name);
-               goto cleanup;
-       }
-       if (real_name == compressed_name)
-       {
-               char *cmd = concat (compr->command, " ", real_name);
-               inf = (FILE *) popen (cmd, "r");
-               free (cmd);
-       }
-       else
-               inf = fopen (real_name, "r");
+       } while( inf == NULL && real_name != NULL);
        if (inf == NULL)
        {
                perror (real_name);
@@ -2004,8 +2127,8 @@ register fdesc *fdp;
 /*
  * add_node ()
  *     Adds a node to the tree of nodes.  In etags mode, sort by file
- *     name.  In ctags mode, sort by tag name.  Make no attempt at
- *     balancing.
+ *     name.  In ctags mode, sort by tag name.  Make no attempt at
+ *     balancing.
  *
  *     add_node is the only function allowed to add nodes, so it can
  *     maintain state.
@@ -2664,8 +2787,8 @@ char *qualifier;
        else
        {
                len = strlen (cstack.cname[0]);
-               linebuffer_setlen (cn, len);
-               strcpy (cn->buffer, cstack.cname[0]);
+               linebuffer_setlen (cn, len+1);
+               xstrncpy (cn->buffer, cstack.cname[0],len+1);
        }
        for (i = 1; i < cstack.nl; i++)
        {
@@ -2691,7 +2814,7 @@ static void make_C_tag __P((bool));
  * consider_token ()
  *     checks to see if the current token is at the start of a
  *     function or variable, or corresponds to a typedef, or
- *     is a struct/union/enum tag, or #define, or an enum constant.
+ *     is a struct/union/enum tag, or #define, or an enum constant.
  *
  *     *IS_FUNC gets TRUE if the token is a function or #define macro
  *     with args.  C_EXTP points to which language we are looking at.
@@ -2798,6 +2921,18 @@ bool *is_func_or_var;    /* OUT: function or variable found */
                        typdef = ttypeseen;
 
                        /* all the rest */
+               case st_C_objprot:
+               case st_C_objimpl:
+               case st_C_objend:
+               case st_C_gnumacro:
+               case st_C_ignore:
+               case st_C_attribute:
+               case st_C_javastruct:
+               case st_C_operator:
+               case st_C_template:
+               case st_C_extern:
+               case st_C_define:
+               case st_C_typedef:
                default:
                        break;
                }
@@ -2818,12 +2953,27 @@ bool *is_func_or_var;   /* OUT: function or variable found */
                        return FALSE;
 
                        /* all the rest */
+               case st_none:
+               case st_C_objprot:
+               case st_C_objimpl:
+               case st_C_objend:
+               case st_C_gnumacro:
+               case st_C_ignore:
+               case st_C_attribute:
+               case st_C_javastruct:
+               case st_C_operator:
+               case st_C_template:
+               case st_C_extern:
+               case st_C_define:
+               case st_C_typedef:
                default:
                        break;
                }
                return TRUE;
 
                /* all the rest */
+       case tinbody:
+       case tignore:
        default:
                break;
        }
@@ -2860,6 +3010,17 @@ bool *is_func_or_var;    /* OUT: function or variable found */
                return FALSE;
 
                /* all the rest */
+       case st_none:
+       case st_C_objprot:
+       case st_C_objimpl:
+       case st_C_objend:
+       case st_C_gnumacro:
+       case st_C_ignore:
+       case st_C_attribute:
+       case st_C_operator:
+       case st_C_extern:
+       case st_C_define:
+       case st_C_typedef:
        default:
                break;
        }
@@ -2887,6 +3048,20 @@ bool *is_func_or_var;    /* OUT: function or variable found */
                        return FALSE;
 
                        /* all the rest */
+               case st_none:
+               case st_C_objend:
+               case st_C_gnumacro:
+               case st_C_ignore:
+               case st_C_attribute:
+               case st_C_javastruct:
+               case st_C_operator:
+               case st_C_class:
+               case st_C_template:
+               case st_C_struct:
+               case st_C_extern:
+               case st_C_enum:
+               case st_C_define:
+               case st_C_typedef:
                default:
                        break;
                }
@@ -2913,8 +3088,8 @@ bool *is_func_or_var;     /* OUT: function or variable found */
                {
                        fvdef = fvnone;
                        objdef = omethodtag;
-                       linebuffer_setlen (&token_name, len);
-                       strncpy (token_name.buffer, str, len);
+                       linebuffer_setlen (&token_name, len+1);
+                       xstrncpy (token_name.buffer, str, len+1);
                        token_name.buffer[len] = '\0';
                        return TRUE;
                }
@@ -2947,6 +3122,9 @@ bool *is_func_or_var;     /* OUT: function or variable found */
                return FALSE;
 
                /* all the rest */
+       case otagseen:
+       case ocatseen:
+       case omethodtag:
        default:
                break;
        }
@@ -2963,6 +3141,12 @@ bool *is_func_or_var;    /* OUT: function or variable found */
                case fignore:
                case vignore:
                        break;
+               case fvnone:
+               case fdefunkey:
+               case fdefunname:
+               case foperator:
+               case fvnameseen:
+               case fstartlist:
                default:
                        fvdef = fvnone;
                }
@@ -3003,6 +3187,10 @@ bool *is_func_or_var;    /* OUT: function or variable found */
                                break;
 
                                /* all the rest */
+                       case tkeyseen:
+                       case tinbody:
+                       case tend:
+                       case tignore:
                        default:
                                break;
                        }
@@ -3023,12 +3211,31 @@ bool *is_func_or_var;   /* OUT: function or variable found */
                        return TRUE;
 
                        /* all the rest */
+               case fdefunname:
+               case foperator:
+               case fstartlist:
+               case finlist:
+               case flistseen:
+               case fignore:
+               case vignore:
                default:
                        break;
                }
                break;
 
                /* all the rest */
+       case st_C_objprot:
+       case st_C_objimpl:
+       case st_C_objend:
+       case st_C_gnumacro:
+       case st_C_attribute:
+       case st_C_javastruct:
+       case st_C_class:
+       case st_C_template:
+       case st_C_struct:
+       case st_C_enum:
+       case st_C_define:
+       case st_C_typedef:
        default:
                break;
        }
@@ -3105,8 +3312,8 @@ bool isfun;
 /*
  * C_entries ()
  *     This routine finds functions, variables, typedefs,
- *     #define's, enum constants and struct/union/enum definitions in
- *     C syntax and adds them to the list.
+ *     #define's, enum constants and struct/union/enum definitions in
+ *     C syntax and adds them to the list.
  */
 static void
 C_entries (c_ext, inf)
@@ -3259,6 +3466,11 @@ FILE *inf;                       /* input file */
                        case fignore:
                        case vignore:
                                break;
+                       case fvnone:
+                       case fdefunname:
+                       case foperator:
+                       case fvnameseen:
+                       case flistseen:
                        default:
                                fvextern = FALSE;
                                fvdef = fvnone;
@@ -3423,10 +3635,9 @@ FILE *inf;                       /* input file */
                                                                        off += 1;
                                                                        len -= 1;
                                                                }
-                                                               linebuffer_setlen (&token_name, len);
-                                                               strncpy (token_name.buffer,
-                                                                        newlb.buffer + off, len);
-                                                               token_name.buffer[len] = '\0';
+                                                               linebuffer_setlen (&token_name, len+1);
+                                                               xstrncpy (token_name.buffer,
+                                                                        newlb.buffer + off, len+1);
                                                                if (defun)
                                                                        while (--len >= 0)
                                                                                if (token_name.buffer[len] == '_')
@@ -3435,9 +3646,9 @@ FILE *inf;                        /* input file */
                                                        }
                                                        else
                                                        {
-                                                               linebuffer_setlen (&token_name, toklen);
-                                                               strncpy (token_name.buffer,
-                                                                        newlb.buffer + tokoff, toklen);
+                                                               linebuffer_setlen (&token_name, toklen+1);
+                                                               xstrncpy (token_name.buffer,
+                                                                        newlb.buffer + tokoff, toklen+1);
                                                                token_name.buffer[toklen] = '\0';
                                                                /* Name macros and members. */
                                                                token.named = (structdef == stagseen
@@ -3515,6 +3726,14 @@ FILE *inf;                       /* input file */
                                                break;
 
                                                /* all the rest */
+                                       case fvnone:
+                                       case fdefunkey:
+                                       case fdefunname:
+                                       case foperator:
+                                       case fvnameseen:
+                                       case finlist:
+                                       case fignore:
+                                       case vignore:
                                        default:
                                                break;
                                        }
@@ -3529,6 +3748,8 @@ FILE *inf;                        /* input file */
                                        break;
 
                                        /* all the rest */
+                               case ddefineseen:
+                               case dignorerest:
                                default:
                                        break;
                                }
@@ -3571,6 +3792,15 @@ FILE *inf;                       /* input file */
                                break;
 
                                /* all the rest */
+                       case onone:
+                       case oprotocol:
+                       case oimplementation:
+                       case oparenseen:
+                       case ocatseen:
+                       case oinbody:
+                       case omethodsign:
+                       case omethodcolon:
+                       case oignore:
                        default:
                                break;
                        }
@@ -3623,6 +3853,13 @@ FILE *inf;                       /* input file */
                                                && plainc && instruct))
                                                make_C_tag (TRUE);  /* a function */
                                        /* FALLTHRU */
+                               case fvnone:
+                               case fdefunkey:
+                               case fdefunname:
+                               case foperator:
+                               case fstartlist:
+                               case finlist:
+                               case vignore:
                                default:
                                        fvextern = FALSE;
                                        fvdef = fvnone;
@@ -3633,6 +3870,7 @@ FILE *inf;                        /* input file */
                                                token.valid = FALSE;
                                } /* switch (fvdef) */
                                /* FALLTHRU */
+                       case tkeyseen:
                        default:
                                if (!instruct)
                                        typdef = tnone;
@@ -3652,6 +3890,16 @@ FILE *inf;                       /* input file */
                                break;
 
                                /* all the rest */
+                       case onone:
+                       case oprotocol:
+                       case oimplementation:
+                       case otagseen:
+                       case oparenseen:
+                       case ocatseen:
+                       case oinbody:
+                       case omethodsign:
+                       case omethodcolon:
+                       case oignore:
                        default:
                                break;
                        }
@@ -3687,6 +3935,7 @@ FILE *inf;                        /* input file */
                                        fvdef = fvnone;
                                token.valid = FALSE;
                                break;
+                       case fvnone:
                        default:
                                fvdef = fvnone;
                        }
@@ -3720,12 +3969,19 @@ FILE *inf;                      /* input file */
                                                && (!fvextern || declarations)))
                                                make_C_tag (FALSE); /* a variable */
                                        /* FALLTHRU */
+                               case fvnone:
+                               case fdefunkey:
+                               case fdefunname:
+                               case fstartlist:
+                               case flistseen:
                                default:
                                        fvdef = fvnone;
                                }
                                break;
 
                                /* all the rest */
+                       case tkeyseen:
+                       case tignore:
                        default:
                                break;
                        }
@@ -3763,6 +4019,13 @@ FILE *inf;                       /* input file */
                                break;
 
                                /* all the rest */
+                       case fvnone:
+                       case fdefunkey:
+                       case fdefunname:
+                       case fstartlist:
+                       case finlist:
+                       case fignore:
+                       case vignore:
                        default:
                                break;
                        }
@@ -3792,6 +4055,14 @@ FILE *inf;                       /* input file */
                                        break;
 
                                        /* all the rest */
+                               case fvnone:
+                               case fdefunkey:
+                               case fdefunname:
+                               case foperator:
+                               case fvnameseen:
+                               case flistseen:
+                               case fignore:
+                               case vignore:
                                default:
                                        break;
                                }
@@ -3836,6 +4107,15 @@ FILE *inf;                       /* input file */
                                        make_C_tag (TRUE); /* an Objective C method */
                                        objdef = oinbody;
                                        break;
+                               case onone:
+                               case oprotocol:
+                               case oimplementation:
+                               case oparenseen:
+                               case ocatseen:
+                               case oinbody:
+                               case omethodsign:
+                               case omethodcolon:
+                               case oignore:
                                default:
                                        /* Neutralize `extern "C" {' grot. */
                                        if (bracelev == 0 && structdef == snone && nestlev == 0
@@ -3845,6 +4125,13 @@ FILE *inf;                       /* input file */
                                break;
 
                                /* all the rest */
+                       case fdefunkey:
+                       case fdefunname:
+                       case foperator:
+                       case fvnameseen:
+                       case fstartlist:
+                       case finlist:
+                       case vignore:
                        default:
                                break;
                        }
@@ -3862,6 +4149,7 @@ FILE *inf;                        /* input file */
                                break;
 
                                /* all the rest */
+                       case snone:
                        default:
                                break;
                        }
@@ -3918,6 +4206,11 @@ FILE *inf;                       /* input file */
                                    || (globals && bracelev == 0 && (!fvextern || declarations)))
                                        make_C_tag (FALSE); /* a variable */
                                /* FALLTHRU */
+                       case fvnone:
+                       case fdefunkey:
+                       case fdefunname:
+                       case fstartlist:
+                       case flistseen:
                        default:
                                fvdef = vignore;
                        }
@@ -3958,6 +4251,12 @@ FILE *inf;                       /* input file */
                        case fignore:
                        case vignore:
                                break;
+                       case fvnone:
+                       case fdefunkey:
+                       case fdefunname:
+                       case fvnameseen:
+                       case fstartlist:
+                       case flistseen:
                        default:
                                fvdef = fvnone;
                        }
@@ -4829,8 +5128,8 @@ FILE *inf;
                                continue;
 
                        /* Save all values for later tagging. */
-                       linebuffer_setlen (&tline, lb.len);
-                       strcpy (tline.buffer, lb.buffer);
+                       linebuffer_setlen (&tline, lb.len+1);
+                       xstrncpy(tline.buffer, lb.buffer, lb.len+1);
                        save_lineno = lineno;
                        save_lcno = linecharno;
                        name = tline.buffer + (dbp - lb.buffer);
@@ -5308,8 +5607,8 @@ FILE * inf;
                                        else
                                                for (end = dbp; *end != '\0' && intoken (*end); end++)
                                                        continue;
-                                       linebuffer_setlen (&token_name, end - dbp);
-                                       strncpy (token_name.buffer, dbp, end - dbp);
+                                       linebuffer_setlen (&token_name, end - dbp+1);
+                                       xstrncpy (token_name.buffer, dbp, end - dbp+1);
                                        token_name.buffer[end - dbp] = '\0';
 
                                        dbp = end;
@@ -5410,8 +5709,7 @@ FILE *inf;
                        else if (len + 1 > allocated)
                                xrnew (last, len + 1, char);
                        allocated = len + 1;
-                       strncpy (last, cp, len);
-                       last[len] = '\0';
+                       xstrncpy (last, cp, len+1);
                }
        }
        free (last);
@@ -5568,7 +5866,7 @@ FILE *inf;
                        continue;
                else if (cp[0] == '"')  /* Sometimes, strings start in column one */
                        continue;
-               else if (cp[0] == '-')  /* attribute, e.g. "-define" */
+               else if (cp[0] == '-')  /* attribute, e.g. "-define" */
                {
                        erlang_attribute (cp);
                        if (last != NULL)
@@ -5588,8 +5886,7 @@ FILE *inf;
                        else if (len + 1 > allocated)
                                xrnew (last, len + 1, char);
                        allocated = len + 1;
-                       strncpy (last, cp, len);
-                       last[len] = '\0';
+                       xstrncpy (last, cp, allocated);
                }
        }
        free (last);
@@ -5976,18 +6273,22 @@ struct re_registers *regs;
 
        /* Allocate space and do the substitutions. */
        assert (size >= 0);
-       result = xnew (size + 1, char);
+       size_t avail = size + 1;
+       result = xnew (avail, char);
 
        for (t = result; *out != '\0'; out++)
                if (*out == '\\' && ISDIGIT (*++out))
                {
                        dig = *out - '0';
                        diglen = regs->end[dig] - regs->start[dig];
-                       strncpy (t, in + regs->start[dig], diglen);
+                       xstrncpy (t, in + regs->start[dig], avail);
                        t += diglen;
+                       avail -= diglen;
                }
-               else
+               else {
                        *t++ = *out;
+                       avail --;
+               }
        *t = '\0';
 
        assert (t <= result + size);
@@ -6024,7 +6325,7 @@ regex_tag_multiline ()
 {
        char *buffer = filebuf.buffer;
        regexp *rp;
-       char *name;
+       char *name = NULL;
 
        for (rp = p_head; rp != NULL; rp = rp->p_next)
        {
@@ -6077,18 +6378,25 @@ regex_tag_multiline ()
                                while (charno < rp->regs.end[0])
                                        if (buffer[charno++] == '\n')
                                                lineno++, linecharno = charno;
-                               name = rp->name;
-                               if (name[0] == '\0')
+                               if (! rp->name || rp->name[0] == '\0')
                                        name = NULL;
                                else /* make a named tag */
                                        name = substitute (buffer, rp->name, &rp->regs);
                                if (rp->force_explicit_name)
-                                       /* Force explicit tag name, if a name is there. */
+                                       /* Force explicit tag name, if a name
+                                          is there. */
                                        pfnote (name, TRUE, buffer + linecharno,
-                                               charno - linecharno + 1, lineno, linecharno);
+                                               charno - linecharno + 1, lineno,
+                                               linecharno);
+                               else if(name == NULL)
+                                       abort();
                                else
-                                       make_tag (name, strlen (name), TRUE, buffer + linecharno,
-                                                 charno - linecharno + 1, lineno, linecharno);
+                                       make_tag (name, strlen (name), TRUE,
+                                                 buffer + linecharno,
+                                                 charno - linecharno + 1,
+                                                 lineno, linecharno);
+                               free(name);
+                               name = NULL;
                                break;
                        }
                }
@@ -6196,13 +6504,12 @@ register FILE *stream;
        if (need_filebuf                /* we need filebuf for multi-line regexps */
            && chars_deleted > 0)       /* not at EOF */
        {
-               while (filebuf.size <= filebuf.len + lbp->len + 1) /* +1 for \n */
-               {
-                       /* Expand filebuf. */
+               size_t need = filebuf.len + lbp->len + 1; /* +1 for \n */
+               while (filebuf.size <= need ) 
                        filebuf.size *= 2;
-                       xrnew (filebuf.buffer, filebuf.size, char);
-               }
-               strncpy (filebuf.buffer + filebuf.len, lbp->buffer, lbp->len);
+               /* Expand filebuf. */
+               xrnew (filebuf.buffer, filebuf.size, char);
+               xstrncpy (filebuf.buffer + filebuf.len, lbp->buffer, filebuf.size - filebuf.len);
                filebuf.len += lbp->len;
                filebuf.buffer[filebuf.len++] = '\n';
                filebuf.buffer[filebuf.len] = '\0';
@@ -6399,7 +6706,8 @@ FILE *stream;
                                                make_tag (name, strlen (name), TRUE,
                                                          lbp->buffer, match, lineno, linecharno);
                                                free(name);
-                                       } else 
+                                               name = NULL;
+                                       } else
                                                make_tag (rp->name, strlen (rp->name), TRUE,
                                                          lbp->buffer, match, lineno, linecharno);
                                        break;
@@ -6432,98 +6740,11 @@ int len;
        register char *dp;
 
        dp = xnew (len + 1, char);
-       strncpy (dp, cp, len);
+       xstrncpy (dp, cp, len+1);
        dp[len] = '\0';
        return dp;
 }
 
-/*
- * Return the ptr in sp at which the character c last
- * appears; NULL if not found
- *
- * Identical to POSIX strrchr, included for portability.
- */
-static char *
-etags_strrchr (sp, c)
-register const char *sp;
-register int c;
-{
-       register const char *r;
-
-       r = NULL;
-       do
-       {
-               if (*sp == c)
-                       r = sp;
-       } while (*sp++);
-       return (char *)r;
-}
-
-/*
- * Return the ptr in sp at which the character c first
- * appears; NULL if not found
- *
- * Identical to POSIX strchr, included for portability.
- */
-static char *
-etags_strchr (sp, c)
-register const char *sp;
-register int c;
-{
-       do
-       {
-               if (*sp == c)
-                       return (char *)sp;
-       } while (*sp++);
-       return NULL;
-}
-
-/*
- * Compare two strings, ignoring case for alphabetic characters.
- *
- * Same as BSD's strcasecmp, included for portability.
- */
-static int
-etags_strcasecmp (s1, s2)
-register const char *s1;
-register const char *s2;
-{
-       while (*s1 != '\0'
-              && (ISALPHA (*s1) && ISALPHA (*s2)
-                  ? lowcase (*s1) == lowcase (*s2)
-                  : *s1 == *s2))
-               s1++, s2++;
-
-       return (ISALPHA (*s1) && ISALPHA (*s2)
-               ? lowcase (*s1) - lowcase (*s2)
-               : *s1 - *s2);
-}
-
-/*
- * Compare two strings, ignoring case for alphabetic characters.
- * Stop after a given number of characters
- *
- * Same as BSD's strncasecmp, included for portability.
- */
-static int
-etags_strncasecmp (s1, s2, n)
-register const char *s1;
-register const char *s2;
-register int n;
-{
-       while (*s1 != '\0' && n-- > 0
-              && (ISALPHA (*s1) && ISALPHA (*s2)
-                  ? lowcase (*s1) == lowcase (*s2)
-                  : *s1 == *s2))
-               s1++, s2++;
-
-       if (n < 0)
-               return 0;
-       else
-               return (ISALPHA (*s1) && ISALPHA (*s2)
-                       ? lowcase (*s1) - lowcase (*s2)
-                       : *s1 - *s2);
-}
 
 /* Skip spaces (end of string is not space), return new pointer. */
 static char *
@@ -6589,9 +6810,9 @@ char *s1, *s2, *s3;
        int len1 = strlen (s1), len2 = strlen (s2), len3 = strlen (s3);
        char *result = xnew (len1 + len2 + len3 + 1, char);
 
-       strcpy (result, s1);
-       strcpy (result + len1, s2);
-       strcpy (result + len1 + len2, s3);
+       xstrncpy(result, s1, len1+1);
+       xstrncpy(result + len1, s2, len2+1);
+       xstrncpy(result + len1 + len2, s3, len3+1);
        result[len1 + len2 + len3] = '\0';
 
        return result;
@@ -6641,6 +6862,7 @@ char *file, *dir;
 {
        char *fp, *dp, *afn, *res;
        int i;
+       ssize_t res_left;
 
        /* Find the common root of file and dir (with a trailing slash). */
        afn = absolute_filename (file, cwd);
@@ -6658,14 +6880,15 @@ char *file, *dir;
        i = 0;
        while ((dp = etags_strchr (dp + 1, '/')) != NULL)
                i += 1;
-       res = xnew (3*i + strlen (fp) + 1, char);
+       res_left = 3 * i + strlen(fp);
+       res = xnew( res_left + 1, char);
        res[0] = '\0';
-       while (i-- > 0)
-               strcat (res, "../");
+       for ( ; i-- > 0 ; res_left -= 3 )
+               strncat(res, "../", res_left );
 
        /* Add the file name relative to the common root of file and dir. */
-       strcat (res, fp);
-       free (afn);
+       strncat(res, fp, res_left);
+       free(afn);
 
        return res;
 }
@@ -6698,7 +6921,8 @@ char *file, *dir;
                                while (cp >= res && !filename_is_absolute (cp));
                                if (cp < res)
                                        cp = slashp;    /* the absolute name begins with "/.." */
-                               strcpy (cp, slashp + 3);
+                               slashp += 3;
+                               memmove(cp, slashp,strlen(slashp)+1);
                                slashp = cp;
                                continue;
                        }
@@ -6792,10 +7016,8 @@ linebuffer *lbp;
 int toksize;
 {
        while (lbp->size <= toksize)
-       {
                lbp->size *= 2;
-               xrnew (lbp->buffer, lbp->size, char);
-       }
+       xrnew (lbp->buffer, lbp->size, char);
        lbp->len = toksize;
 }