comparison src/tag.c @ 28037:12a256140887 v8.2.4543

patch 8.2.4543: Coverity warning for refactored tag search code Commit: https://github.com/vim/vim/commit/20fb28b1dcc092787e1a7b22dcfcfe1e46e29813 Author: Yegappan Lakshmanan <yegappan@yahoo.com> Date: Fri Mar 11 12:05:18 2022 +0000 patch 8.2.4543: Coverity warning for refactored tag search code Problem: Coverity warning for refactored tag search code. Solution: Avoid the warnings. Update comments. Add one more test case. (Yegappan Lakshmanan, closes #9928)
author Bram Moolenaar <Bram@vim.org>
date Fri, 11 Mar 2022 13:15:04 +0100
parents d59552ad3f36
children 0362ab7c1a02
comparison
equal deleted inserted replaced
28036:3167a59d5fc2 28037:12a256140887
1661 // other: minimal number of matches 1661 // other: minimal number of matches
1662 int linear; // do a linear search 1662 int linear; // do a linear search
1663 char_u *lbuf; // line buffer 1663 char_u *lbuf; // line buffer
1664 int lbuf_size; // length of lbuf 1664 int lbuf_size; // length of lbuf
1665 #ifdef FEAT_EMACS_TAGS 1665 #ifdef FEAT_EMACS_TAGS
1666 int is_etag; // current file is emaces style 1666 int is_etag; // current file is emacs style
1667 char_u *ebuf; // additional buffer for etag fname 1667 char_u *ebuf; // additional buffer for etag fname
1668 #endif 1668 #endif
1669 int match_count; // number of matches found 1669 int match_count; // number of matches found
1670 garray_T ga_match[MT_COUNT]; // stores matches in sequence 1670 garray_T ga_match[MT_COUNT]; // stores matches in sequence
1671 hashtab_T ht_match[MT_COUNT]; // stores matches by key 1671 hashtab_T ht_match[MT_COUNT]; // stores matches by key
1672 int stop_searching; // stop when match found or error 1672 int stop_searching; // stop when match found or error
1673 } findtags_state_T; 1673 } findtags_state_T;
1674 1674
1675 /* 1675 /*
1676 * Initialize the state used by find_tags() 1676 * Initialize the state used by find_tags().
1677 * Returns OK on success and FAIL on memory allocation failure.
1677 */ 1678 */
1678 static int 1679 static int
1679 findtags_state_init( 1680 findtags_state_init(
1680 findtags_state_T *st, 1681 findtags_state_T *st,
1681 char_u *pat, 1682 char_u *pat,
1743 1744
1744 #ifdef FEAT_MULTI_LANG 1745 #ifdef FEAT_MULTI_LANG
1745 /* 1746 /*
1746 * Initialize the language and priority used for searching tags in a Vim help 1747 * Initialize the language and priority used for searching tags in a Vim help
1747 * file. 1748 * file.
1748 * Returns TRUE to process the help file and FALSE to skip the file. 1749 * Returns TRUE to process the help file for tags and FALSE to skip the file.
1749 */ 1750 */
1750 static int 1751 static int
1751 findtags_in_help_init(findtags_state_T *st) 1752 findtags_in_help_init(findtags_state_T *st)
1752 { 1753 {
1753 int i; 1754 int i;
1760 { 1761 {
1761 // Prefer help tags according to 'helplang'. Put the two-letter 1762 // Prefer help tags according to 'helplang'. Put the two-letter
1762 // language name in help_lang[]. 1763 // language name in help_lang[].
1763 i = (int)STRLEN(st->tag_fname); 1764 i = (int)STRLEN(st->tag_fname);
1764 if (i > 3 && st->tag_fname[i - 3] == '-') 1765 if (i > 3 && st->tag_fname[i - 3] == '-')
1765 STRCPY(st->help_lang, st->tag_fname + i - 2); 1766 vim_strncpy(st->help_lang, st->tag_fname + i - 2, 2);
1766 else 1767 else
1767 STRCPY(st->help_lang, "en"); 1768 STRCPY(st->help_lang, "en");
1768 } 1769 }
1769 // When searching for a specific language skip tags files for other 1770 // When searching for a specific language skip tags files for other
1770 // languages. 1771 // languages.
1844 char_u *etag_fname; 1845 char_u *etag_fname;
1845 } incstack[INCSTACK_SIZE]; 1846 } incstack[INCSTACK_SIZE];
1846 static int incstack_idx = 0; // index in incstack 1847 static int incstack_idx = 0; // index in incstack
1847 1848
1848 /* 1849 /*
1849 * Free the include tags file stack. 1850 * Free the emacs include tags file stack.
1850 */ 1851 */
1851 static void 1852 static void
1852 emacs_tags_incstack_free(void) 1853 emacs_tags_incstack_free(void)
1853 { 1854 {
1854 while (incstack_idx) 1855 while (incstack_idx)
1861 } 1862 }
1862 1863
1863 /* 1864 /*
1864 * Emacs tags line with CTRL-L: New file name on next line. 1865 * Emacs tags line with CTRL-L: New file name on next line.
1865 * The file name is followed by a ','. Remember etag file name in ebuf. 1866 * The file name is followed by a ','. Remember etag file name in ebuf.
1866 * Returns a FILE pointer to the tags file. If another tags file is included, 1867 * The FILE pointer to the tags file is stored in 'st->fp'. If another tags
1867 * then returns a pointer to the new tags file. The old file pointer is saved 1868 * file is included, then the FILE pointer to the new tags file is stored in
1868 * in incstack. 1869 * 'st->fp'. The old file pointer is saved in incstack.
1869 */ 1870 */
1870 static void 1871 static void
1871 emacs_tags_new_filename(findtags_state_T *st) 1872 emacs_tags_new_filename(findtags_state_T *st)
1872 { 1873 {
1873 char_u *p; 1874 char_u *p;
1916 // Can't open the included file, skip it and 1917 // Can't open the included file, skip it and
1917 // restore old value of "fp". 1918 // restore old value of "fp".
1918 st->fp = incstack[incstack_idx].fp; 1919 st->fp = incstack[incstack_idx].fp;
1919 vim_free(incstack[incstack_idx].etag_fname); 1920 vim_free(incstack[incstack_idx].etag_fname);
1920 } 1921 }
1921
1922 return;
1923 } 1922 }
1924 1923
1925 /* 1924 /*
1926 * Reached the end of an emacs-style tags file. If this is an included tags 1925 * Reached the end of an emacs-style tags file. If this is an included tags
1927 * file, then pop it from the incstack and continue processing the parent tags 1926 * file, then pop it from the incstack and continue processing the parent tags
1928 * file. Otherwise, processed all the tags. 1927 * file. Otherwise, processed all the tags.
1929 * Returns TRUE if an included tags file is popped and processing should 1928 * Returns TRUE if an included tags file is popped and processing should
1930 * continue with the parent tags file. Otherwise returns FALSE. 1929 * continue with the parent tags file. Returns FALSE to stop processing tags.
1931 */ 1930 */
1932 static int 1931 static int
1933 emacs_tags_file_eof(findtags_state_T *st) 1932 emacs_tags_file_eof(findtags_state_T *st)
1934 { 1933 {
1935 if (!incstack_idx) // reached end of file. stop processing. 1934 if (!incstack_idx) // reached end of file. stop processing.
1945 return TRUE; 1944 return TRUE;
1946 } 1945 }
1947 1946
1948 /* 1947 /*
1949 * Parse a line from an emacs-style tags file. 1948 * Parse a line from an emacs-style tags file.
1950 * Returns OK is the line is parsed successfully, otherwise FALSE. 1949 * Returns OK if the line is parsed successfully, returns FAIL if the line is
1950 * not terminated by a newline.
1951 */ 1951 */
1952 static int 1952 static int
1953 emacs_tags_parse_line(char_u *lbuf, tagptrs_T *tagp) 1953 emacs_tags_parse_line(char_u *lbuf, tagptrs_T *tagp)
1954 { 1954 {
1955 char_u *p_7f; 1955 char_u *p_7f;
2165 int use_cscope = (st->flags & TAG_CSCOPE); 2165 int use_cscope = (st->flags & TAG_CSCOPE);
2166 #endif 2166 #endif
2167 int noic = (st->flags & TAG_NOIC); 2167 int noic = (st->flags & TAG_NOIC);
2168 off_T filesize; 2168 off_T filesize;
2169 2169
2170 // The header ends when the line sorts below "!_TAG_". When 2170 // The header ends when the line sorts below "!_TAG_". When case is
2171 // case is folded lower case letters sort before "_". 2171 // folded lower case letters sort before "_".
2172 if (STRNCMP(st->lbuf, "!_TAG_", 6) <= 0 2172 if (STRNCMP(st->lbuf, "!_TAG_", 6) <= 0
2173 || (st->lbuf[0] == '!' && ASCII_ISLOWER(st->lbuf[1]))) 2173 || (st->lbuf[0] == '!' && ASCII_ISLOWER(st->lbuf[1])))
2174 return findtags_hdr_parse(st); 2174 return findtags_hdr_parse(st);
2175 2175
2176 // Headers ends. 2176 // Headers ends.
2239 } 2239 }
2240 2240
2241 /* 2241 /*
2242 * Parse a tag line read from a tags file. 2242 * Parse a tag line read from a tags file.
2243 * Returns OK if a tags line is successfully parsed. 2243 * Returns OK if a tags line is successfully parsed.
2244 * Returns FAIL if an error is encountered. 2244 * Returns FAIL if a format error is encountered.
2245 */ 2245 */
2246 static int 2246 static int
2247 findtags_parse_line(findtags_state_T *st, tagptrs_T *tagpp) 2247 findtags_parse_line(findtags_state_T *st, tagptrs_T *tagpp)
2248 { 2248 {
2249 int status; 2249 int status;
2745 return OK; 2745 return OK;
2746 } 2746 }
2747 2747
2748 /* 2748 /*
2749 * Read and get all the tags from file st->tag_fname. 2749 * Read and get all the tags from file st->tag_fname.
2750 * Returns OK if all the tags are processed successfully and FAIL is a tag 2750 * Sets 'st->stop_searching' to TRUE to stop searching for additional tags.
2751 * format error is encountered. 2751 */
2752 */ 2752 static void
2753 static int
2754 findtags_get_all_tags( 2753 findtags_get_all_tags(
2755 findtags_state_T *st, 2754 findtags_state_T *st,
2756 findtags_match_args_T *margs, 2755 findtags_match_args_T *margs,
2757 char_u *buf_ffname) 2756 char_u *buf_ffname)
2758 { 2757 {
2844 st->lbuf = alloc(st->lbuf_size); 2843 st->lbuf = alloc(st->lbuf_size);
2845 if (st->lbuf == NULL) 2844 if (st->lbuf == NULL)
2846 { 2845 {
2847 if (st->fp != NULL) 2846 if (st->fp != NULL)
2848 fclose(st->fp); 2847 fclose(st->fp);
2849 break; 2848 st->fp = NULL;
2849 st->stop_searching = TRUE;
2850 return;
2850 } 2851 }
2851 2852
2852 if (st->state == TS_STEP_FORWARD) 2853 if (st->state == TS_STEP_FORWARD)
2853 // Seek to the same position to read the same line again 2854 // Seek to the same position to read the same line again
2854 vim_fseek(st->fp, search_info.curr_offset, SEEK_SET); 2855 vim_fseek(st->fp, search_info.curr_offset, SEEK_SET);
2857 search_info.curr_offset = 0; 2858 search_info.curr_offset = 0;
2858 continue; 2859 continue;
2859 } 2860 }
2860 2861
2861 if (findtags_parse_line(st, &tagp) == FAIL) 2862 if (findtags_parse_line(st, &tagp) == FAIL)
2862 return FAIL; 2863 {
2864 semsg(_(e_format_error_in_tags_file_str), st->tag_fname);
2865 #ifdef FEAT_CSCOPE
2866 if (!use_cscope)
2867 #endif
2868 semsg(_("Before byte %ld"), (long)vim_ftell(st->fp));
2869 st->stop_searching = TRUE;
2870 return;
2871 }
2863 2872
2864 retval = findtags_match_tag(st, &tagp, margs, &search_info); 2873 retval = findtags_match_tag(st, &tagp, margs, &search_info);
2865 if (retval == TAG_MATCH_NEXT) 2874 if (retval == TAG_MATCH_NEXT)
2866 continue; 2875 continue;
2867 if (retval == TAG_MATCH_STOP) 2876 if (retval == TAG_MATCH_STOP)
2873 if (findtags_add_match(st, &tagp, margs, buf_ffname, &hash) 2882 if (findtags_add_match(st, &tagp, margs, buf_ffname, &hash)
2874 == FAIL) 2883 == FAIL)
2875 break; 2884 break;
2876 } 2885 }
2877 } // forever 2886 } // forever
2878
2879 return OK;
2880 } 2887 }
2881 2888
2882 /* 2889 /*
2883 * Search for tags matching 'st->orgpat.pat' in the 'st->tag_fname' tags file. 2890 * Search for tags matching 'st->orgpat.pat' in the 'st->tag_fname' tags file.
2884 * Information needed to search for the tags is in the 'st' state structure. 2891 * Information needed to search for the tags is in the 'st' state structure.
2885 * The matching tags are returned in 'st'. 2892 * The matching tags are returned in 'st'. If an error is encountered, then
2886 * Returns OK if successfully processed the file and FAIL on memory allocation 2893 * 'st->stop_searching' is set to TRUE.
2887 * failure. 2894 */
2888 */ 2895 static void
2889 static int
2890 findtags_in_file(findtags_state_T *st, char_u *buf_ffname) 2896 findtags_in_file(findtags_state_T *st, char_u *buf_ffname)
2891 { 2897 {
2892 findtags_match_args_T margs; 2898 findtags_match_args_T margs;
2893 int line_error = FALSE; // syntax error
2894 #ifdef FEAT_CSCOPE 2899 #ifdef FEAT_CSCOPE
2895 int use_cscope = FALSE; 2900 int use_cscope = FALSE;
2896 #endif 2901 #endif
2897 2902
2898 st->vimconv.vc_type = CONV_NONE; 2903 st->vimconv.vc_type = CONV_NONE;
2911 { 2916 {
2912 #ifdef FEAT_MULTI_LANG 2917 #ifdef FEAT_MULTI_LANG
2913 if (curbuf->b_help) 2918 if (curbuf->b_help)
2914 { 2919 {
2915 if (!findtags_in_help_init(st)) 2920 if (!findtags_in_help_init(st))
2916 return OK; 2921 return;
2917 } 2922 }
2918 #endif 2923 #endif
2919 2924
2920 st->fp = mch_fopen((char *)st->tag_fname, "r"); 2925 st->fp = mch_fopen((char *)st->tag_fname, "r");
2921 if (st->fp == NULL) 2926 if (st->fp == NULL)
2922 return OK; 2927 return;
2923 2928
2924 if (p_verbose >= 5) 2929 if (p_verbose >= 5)
2925 { 2930 {
2926 verbose_enter(); 2931 verbose_enter();
2927 smsg(_("Searching tags file %s"), st->tag_fname); 2932 smsg(_("Searching tags file %s"), st->tag_fname);
2934 #ifdef FEAT_EMACS_TAGS 2939 #ifdef FEAT_EMACS_TAGS
2935 st->is_etag = FALSE; // default is: not emacs style 2940 st->is_etag = FALSE; // default is: not emacs style
2936 #endif 2941 #endif
2937 2942
2938 // Read and parse the lines in the file one by one 2943 // Read and parse the lines in the file one by one
2939 if (findtags_get_all_tags(st, &margs, buf_ffname) == FAIL) 2944 findtags_get_all_tags(st, &margs, buf_ffname);
2940 line_error = TRUE;
2941
2942 if (line_error)
2943 {
2944 semsg(_(e_format_error_in_tags_file_str), st->tag_fname);
2945 #ifdef FEAT_CSCOPE
2946 if (!use_cscope)
2947 #endif
2948 semsg(_("Before byte %ld"), (long)vim_ftell(st->fp));
2949 st->stop_searching = TRUE;
2950 line_error = FALSE;
2951 }
2952 2945
2953 if (st->fp != NULL) 2946 if (st->fp != NULL)
2954 fclose(st->fp); 2947 fclose(st->fp);
2948 st->fp = NULL;
2955 #ifdef FEAT_EMACS_TAGS 2949 #ifdef FEAT_EMACS_TAGS
2956 emacs_tags_incstack_free(); 2950 emacs_tags_incstack_free();
2957 #endif 2951 #endif
2958 if (st->vimconv.vc_type != CONV_NONE) 2952 if (st->vimconv.vc_type != CONV_NONE)
2959 convert_setup(&st->vimconv, NULL, NULL); 2953 convert_setup(&st->vimconv, NULL, NULL);
2962 semsg(_(e_tags_file_not_sorted_str), st->tag_fname); 2956 semsg(_(e_tags_file_not_sorted_str), st->tag_fname);
2963 2957
2964 // Stop searching if sufficient tags have been found. 2958 // Stop searching if sufficient tags have been found.
2965 if (st->match_count >= st->mincount) 2959 if (st->match_count >= st->mincount)
2966 st->stop_searching = TRUE; 2960 st->stop_searching = TRUE;
2967
2968 return OK;
2969 } 2961 }
2970 2962
2971 /* 2963 /*
2972 * Copy the tags found by find_tags() to 'matchesp'. 2964 * Copy the tags found by find_tags() to 'matchesp'.
2973 * Returns the number of matches copied. 2965 * Returns the number of matches copied.
3186 use_cscope || 3178 use_cscope ||
3187 #endif 3179 #endif
3188 get_tagfname(&tn, first_file, st.tag_fname) == OK; 3180 get_tagfname(&tn, first_file, st.tag_fname) == OK;
3189 first_file = FALSE) 3181 first_file = FALSE)
3190 { 3182 {
3191 if (findtags_in_file(&st, buf_ffname) == FAIL) 3183 findtags_in_file(&st, buf_ffname);
3192 goto findtag_end;
3193 if (st.stop_searching 3184 if (st.stop_searching
3194 #ifdef FEAT_CSCOPE 3185 #ifdef FEAT_CSCOPE
3195 || use_cscope 3186 || use_cscope
3196 #endif 3187 #endif
3197 ) 3188 )