Mercurial > vim
comparison src/quickfix.c @ 9568:ccbd2e604e59 v7.4.2061
commit https://github.com/vim/vim/commit/e87e6dddc2b2a99572ec0db0833c052214c4fbd3
Author: Bram Moolenaar <Bram@vim.org>
Date: Sun Jul 17 19:25:04 2016 +0200
patch 7.4.2061
Problem: qf_init_ext() is too big.
Solution: Move code to qf_parse_line() (Yegappan Lakshmanan)
author | Christian Brabandt <cb@256bit.org> |
---|---|
date | Sun, 17 Jul 2016 19:30:05 +0200 |
parents | 64a791c53418 |
children | 9946c4c33598 |
comparison
equal
deleted
inserted
replaced
9567:c4d5ba8214d1 | 9568:ccbd2e604e59 |
---|---|
409 errmsg = alloc_id(errmsglen, aid_qf_errmsg); | 409 errmsg = alloc_id(errmsglen, aid_qf_errmsg); |
410 if (errmsg == NULL) | 410 if (errmsg == NULL) |
411 goto parse_efm_end; | 411 goto parse_efm_end; |
412 | 412 |
413 /* | 413 /* |
414 * Each part of the format string is copied and modified from errorformat | |
415 * to regex prog. Only a few % characters are allowed. | |
416 */ | |
417 | |
418 /* | |
414 * Get some space to modify the format string into. | 419 * Get some space to modify the format string into. |
415 */ | 420 */ |
416 i = (FMT_PATTERNS * 3) + ((int)STRLEN(efm) << 2); | 421 i = (FMT_PATTERNS * 3) + ((int)STRLEN(efm) << 2); |
417 for (round = FMT_PATTERNS; round > 0; ) | 422 for (round = FMT_PATTERNS; round > 0; ) |
418 i += (int)STRLEN(fmt_pat[--round].pattern); | 423 i += (int)STRLEN(fmt_pat[--round].pattern); |
472 | 477 |
473 enum { | 478 enum { |
474 QF_FAIL = 0, | 479 QF_FAIL = 0, |
475 QF_OK = 1, | 480 QF_OK = 1, |
476 QF_END_OF_INPUT = 2, | 481 QF_END_OF_INPUT = 2, |
477 QF_NOMEM = 3 | 482 QF_NOMEM = 3, |
483 QF_IGNORE_LINE = 4 | |
478 }; | 484 }; |
479 | 485 |
480 typedef struct { | 486 typedef struct { |
481 char_u *linebuf; | 487 char_u *linebuf; |
482 int linelen; | 488 int linelen; |
762 #endif | 768 #endif |
763 | 769 |
764 return QF_OK; | 770 return QF_OK; |
765 } | 771 } |
766 | 772 |
773 typedef struct { | |
774 char_u *namebuf; | |
775 char_u *errmsg; | |
776 int errmsglen; | |
777 long lnum; | |
778 int col; | |
779 char_u use_viscol; | |
780 char_u *pattern; | |
781 int enr; | |
782 int type; | |
783 int valid; | |
784 } qffields_T; | |
785 | |
786 /* | |
787 * Parse a line and get the quickfix fields. | |
788 * Return the QF_ status. | |
789 */ | |
790 static int | |
791 qf_parse_line( | |
792 qf_info_T *qi, | |
793 char_u *linebuf, | |
794 int linelen, | |
795 efm_T *fmt_first, | |
796 qffields_T *fields) | |
797 { | |
798 efm_T *fmt_ptr; | |
799 static efm_T *fmt_start = NULL; /* cached across calls */ | |
800 char_u *ptr; | |
801 int len; | |
802 int i; | |
803 int idx = 0; | |
804 char_u *tail = NULL; | |
805 regmatch_T regmatch; | |
806 | |
807 /* Always ignore case when looking for a matching error. */ | |
808 regmatch.rm_ic = TRUE; | |
809 | |
810 /* If there was no %> item start at the first pattern */ | |
811 if (fmt_start == NULL) | |
812 fmt_ptr = fmt_first; | |
813 else | |
814 { | |
815 fmt_ptr = fmt_start; | |
816 fmt_start = NULL; | |
817 } | |
818 | |
819 /* | |
820 * Try to match each part of 'errorformat' until we find a complete | |
821 * match or no match. | |
822 */ | |
823 fields->valid = TRUE; | |
824 restofline: | |
825 for ( ; fmt_ptr != NULL; fmt_ptr = fmt_ptr->next) | |
826 { | |
827 int r; | |
828 | |
829 idx = fmt_ptr->prefix; | |
830 if (qi->qf_multiscan && vim_strchr((char_u *)"OPQ", idx) == NULL) | |
831 continue; | |
832 fields->namebuf[0] = NUL; | |
833 fields->pattern[0] = NUL; | |
834 if (!qi->qf_multiscan) | |
835 fields->errmsg[0] = NUL; | |
836 fields->lnum = 0; | |
837 fields->col = 0; | |
838 fields->use_viscol = FALSE; | |
839 fields->enr = -1; | |
840 fields->type = 0; | |
841 tail = NULL; | |
842 | |
843 regmatch.regprog = fmt_ptr->prog; | |
844 r = vim_regexec(®match, linebuf, (colnr_T)0); | |
845 fmt_ptr->prog = regmatch.regprog; | |
846 if (r) | |
847 { | |
848 if ((idx == 'C' || idx == 'Z') && !qi->qf_multiline) | |
849 continue; | |
850 if (vim_strchr((char_u *)"EWI", idx) != NULL) | |
851 fields->type = idx; | |
852 else | |
853 fields->type = 0; | |
854 /* | |
855 * Extract error message data from matched line. | |
856 * We check for an actual submatch, because "\[" and "\]" in | |
857 * the 'errorformat' may cause the wrong submatch to be used. | |
858 */ | |
859 if ((i = (int)fmt_ptr->addr[0]) > 0) /* %f */ | |
860 { | |
861 int c; | |
862 | |
863 if (regmatch.startp[i] == NULL || regmatch.endp[i] == NULL) | |
864 continue; | |
865 | |
866 /* Expand ~/file and $HOME/file to full path. */ | |
867 c = *regmatch.endp[i]; | |
868 *regmatch.endp[i] = NUL; | |
869 expand_env(regmatch.startp[i], fields->namebuf, CMDBUFFSIZE); | |
870 *regmatch.endp[i] = c; | |
871 | |
872 if (vim_strchr((char_u *)"OPQ", idx) != NULL | |
873 && mch_getperm(fields->namebuf) == -1) | |
874 continue; | |
875 } | |
876 if ((i = (int)fmt_ptr->addr[1]) > 0) /* %n */ | |
877 { | |
878 if (regmatch.startp[i] == NULL) | |
879 continue; | |
880 fields->enr = (int)atol((char *)regmatch.startp[i]); | |
881 } | |
882 if ((i = (int)fmt_ptr->addr[2]) > 0) /* %l */ | |
883 { | |
884 if (regmatch.startp[i] == NULL) | |
885 continue; | |
886 fields->lnum = atol((char *)regmatch.startp[i]); | |
887 } | |
888 if ((i = (int)fmt_ptr->addr[3]) > 0) /* %c */ | |
889 { | |
890 if (regmatch.startp[i] == NULL) | |
891 continue; | |
892 fields->col = (int)atol((char *)regmatch.startp[i]); | |
893 } | |
894 if ((i = (int)fmt_ptr->addr[4]) > 0) /* %t */ | |
895 { | |
896 if (regmatch.startp[i] == NULL) | |
897 continue; | |
898 fields->type = *regmatch.startp[i]; | |
899 } | |
900 if (fmt_ptr->flags == '+' && !qi->qf_multiscan) /* %+ */ | |
901 { | |
902 if (linelen > fields->errmsglen) { | |
903 /* linelen + null terminator */ | |
904 if ((fields->errmsg = vim_realloc(fields->errmsg, | |
905 linelen + 1)) == NULL) | |
906 return QF_NOMEM; | |
907 fields->errmsglen = linelen + 1; | |
908 } | |
909 vim_strncpy(fields->errmsg, linebuf, linelen); | |
910 } | |
911 else if ((i = (int)fmt_ptr->addr[5]) > 0) /* %m */ | |
912 { | |
913 if (regmatch.startp[i] == NULL || regmatch.endp[i] == NULL) | |
914 continue; | |
915 len = (int)(regmatch.endp[i] - regmatch.startp[i]); | |
916 if (len > fields->errmsglen) { | |
917 /* len + null terminator */ | |
918 if ((fields->errmsg = vim_realloc(fields->errmsg, len + 1)) | |
919 == NULL) | |
920 return QF_NOMEM; | |
921 fields->errmsglen = len + 1; | |
922 } | |
923 vim_strncpy(fields->errmsg, regmatch.startp[i], len); | |
924 } | |
925 if ((i = (int)fmt_ptr->addr[6]) > 0) /* %r */ | |
926 { | |
927 if (regmatch.startp[i] == NULL) | |
928 continue; | |
929 tail = regmatch.startp[i]; | |
930 } | |
931 if ((i = (int)fmt_ptr->addr[7]) > 0) /* %p */ | |
932 { | |
933 char_u *match_ptr; | |
934 | |
935 if (regmatch.startp[i] == NULL || regmatch.endp[i] == NULL) | |
936 continue; | |
937 fields->col = 0; | |
938 for (match_ptr = regmatch.startp[i]; | |
939 match_ptr != regmatch.endp[i]; ++match_ptr) | |
940 { | |
941 ++fields->col; | |
942 if (*match_ptr == TAB) | |
943 { | |
944 fields->col += 7; | |
945 fields->col -= fields->col % 8; | |
946 } | |
947 } | |
948 ++fields->col; | |
949 fields->use_viscol = TRUE; | |
950 } | |
951 if ((i = (int)fmt_ptr->addr[8]) > 0) /* %v */ | |
952 { | |
953 if (regmatch.startp[i] == NULL) | |
954 continue; | |
955 fields->col = (int)atol((char *)regmatch.startp[i]); | |
956 fields->use_viscol = TRUE; | |
957 } | |
958 if ((i = (int)fmt_ptr->addr[9]) > 0) /* %s */ | |
959 { | |
960 if (regmatch.startp[i] == NULL || regmatch.endp[i] == NULL) | |
961 continue; | |
962 len = (int)(regmatch.endp[i] - regmatch.startp[i]); | |
963 if (len > CMDBUFFSIZE - 5) | |
964 len = CMDBUFFSIZE - 5; | |
965 STRCPY(fields->pattern, "^\\V"); | |
966 STRNCAT(fields->pattern, regmatch.startp[i], len); | |
967 fields->pattern[len + 3] = '\\'; | |
968 fields->pattern[len + 4] = '$'; | |
969 fields->pattern[len + 5] = NUL; | |
970 } | |
971 break; | |
972 } | |
973 } | |
974 qi->qf_multiscan = FALSE; | |
975 | |
976 if (fmt_ptr == NULL || idx == 'D' || idx == 'X') | |
977 { | |
978 if (fmt_ptr != NULL) | |
979 { | |
980 if (idx == 'D') /* enter directory */ | |
981 { | |
982 if (*fields->namebuf == NUL) | |
983 { | |
984 EMSG(_("E379: Missing or empty directory name")); | |
985 return QF_FAIL; | |
986 } | |
987 qi->qf_directory = | |
988 qf_push_dir(fields->namebuf, &qi->qf_dir_stack, FALSE); | |
989 if (qi->qf_directory == NULL) | |
990 return QF_FAIL; | |
991 } | |
992 else if (idx == 'X') /* leave directory */ | |
993 qi->qf_directory = qf_pop_dir(&qi->qf_dir_stack); | |
994 } | |
995 fields->namebuf[0] = NUL; /* no match found, remove file name */ | |
996 fields->lnum = 0; /* don't jump to this line */ | |
997 fields->valid = FALSE; | |
998 if (linelen > fields->errmsglen) { | |
999 /* linelen + null terminator */ | |
1000 if ((fields->errmsg = vim_realloc(fields->errmsg, | |
1001 linelen + 1)) == NULL) | |
1002 return QF_NOMEM; | |
1003 fields->errmsglen = linelen + 1; | |
1004 } | |
1005 /* copy whole line to error message */ | |
1006 vim_strncpy(fields->errmsg, linebuf, linelen); | |
1007 if (fmt_ptr == NULL) | |
1008 qi->qf_multiline = qi->qf_multiignore = FALSE; | |
1009 } | |
1010 else if (fmt_ptr != NULL) | |
1011 { | |
1012 /* honor %> item */ | |
1013 if (fmt_ptr->conthere) | |
1014 fmt_start = fmt_ptr; | |
1015 | |
1016 if (vim_strchr((char_u *)"AEWI", idx) != NULL) | |
1017 { | |
1018 qi->qf_multiline = TRUE; /* start of a multi-line message */ | |
1019 qi->qf_multiignore = FALSE; /* reset continuation */ | |
1020 } | |
1021 else if (vim_strchr((char_u *)"CZ", idx) != NULL) | |
1022 { /* continuation of multi-line msg */ | |
1023 qfline_T *qfprev = qi->qf_lists[qi->qf_curlist].qf_last; | |
1024 | |
1025 if (qfprev == NULL) | |
1026 return QF_FAIL; | |
1027 if (*fields->errmsg && !qi->qf_multiignore) | |
1028 { | |
1029 len = (int)STRLEN(qfprev->qf_text); | |
1030 if ((ptr = alloc((unsigned)(len + STRLEN(fields->errmsg) + 2))) | |
1031 == NULL) | |
1032 return QF_FAIL; | |
1033 STRCPY(ptr, qfprev->qf_text); | |
1034 vim_free(qfprev->qf_text); | |
1035 qfprev->qf_text = ptr; | |
1036 *(ptr += len) = '\n'; | |
1037 STRCPY(++ptr, fields->errmsg); | |
1038 } | |
1039 if (qfprev->qf_nr == -1) | |
1040 qfprev->qf_nr = fields->enr; | |
1041 if (vim_isprintc(fields->type) && !qfprev->qf_type) | |
1042 /* only printable chars allowed */ | |
1043 qfprev->qf_type = fields->type; | |
1044 | |
1045 if (!qfprev->qf_lnum) | |
1046 qfprev->qf_lnum = fields->lnum; | |
1047 if (!qfprev->qf_col) | |
1048 qfprev->qf_col = fields->col; | |
1049 qfprev->qf_viscol = fields->use_viscol; | |
1050 if (!qfprev->qf_fnum) | |
1051 qfprev->qf_fnum = qf_get_fnum(qi, qi->qf_directory, | |
1052 *fields->namebuf || qi->qf_directory != NULL | |
1053 ? fields->namebuf | |
1054 : qi->qf_currfile != NULL && fields->valid | |
1055 ? qi->qf_currfile : 0); | |
1056 if (idx == 'Z') | |
1057 qi->qf_multiline = qi->qf_multiignore = FALSE; | |
1058 line_breakcheck(); | |
1059 return QF_IGNORE_LINE; | |
1060 } | |
1061 else if (vim_strchr((char_u *)"OPQ", idx) != NULL) | |
1062 { | |
1063 /* global file names */ | |
1064 fields->valid = FALSE; | |
1065 if (*fields->namebuf == NUL || mch_getperm(fields->namebuf) >= 0) | |
1066 { | |
1067 if (*fields->namebuf && idx == 'P') | |
1068 qi->qf_currfile = | |
1069 qf_push_dir(fields->namebuf, &qi->qf_file_stack, TRUE); | |
1070 else if (idx == 'Q') | |
1071 qi->qf_currfile = qf_pop_dir(&qi->qf_file_stack); | |
1072 *fields->namebuf = NUL; | |
1073 if (tail && *tail) | |
1074 { | |
1075 STRMOVE(IObuff, skipwhite(tail)); | |
1076 qi->qf_multiscan = TRUE; | |
1077 goto restofline; | |
1078 } | |
1079 } | |
1080 } | |
1081 if (fmt_ptr->flags == '-') /* generally exclude this line */ | |
1082 { | |
1083 if (qi->qf_multiline) | |
1084 /* also exclude continuation lines */ | |
1085 qi->qf_multiignore = TRUE; | |
1086 return QF_IGNORE_LINE; | |
1087 } | |
1088 } | |
1089 | |
1090 return QF_OK; | |
1091 } | |
1092 | |
767 /* | 1093 /* |
768 * Read the errorfile "efile" into memory, line by line, building the error | 1094 * Read the errorfile "efile" into memory, line by line, building the error |
769 * list. | 1095 * list. |
770 * Alternative: when "efile" is NULL read errors from buffer "buf". | 1096 * Alternative: when "efile" is NULL read errors from buffer "buf". |
771 * Alternative: when "tv" is not NULL get errors from the string or list. | 1097 * Alternative: when "tv" is not NULL get errors from the string or list. |
784 int newlist, /* TRUE: start a new error list */ | 1110 int newlist, /* TRUE: start a new error list */ |
785 linenr_T lnumfirst, /* first line number to use */ | 1111 linenr_T lnumfirst, /* first line number to use */ |
786 linenr_T lnumlast, /* last line number to use */ | 1112 linenr_T lnumlast, /* last line number to use */ |
787 char_u *qf_title) | 1113 char_u *qf_title) |
788 { | 1114 { |
789 char_u *namebuf; | |
790 char_u *errmsg; | |
791 int errmsglen; | |
792 char_u *pattern; | |
793 qfstate_T state = {NULL, 0, NULL, 0, NULL, NULL, NULL, NULL, | 1115 qfstate_T state = {NULL, 0, NULL, 0, NULL, NULL, NULL, NULL, |
794 NULL, 0, 0}; | 1116 NULL, 0, 0}; |
795 int col = 0; | 1117 qffields_T fields = {NULL, NULL, 0, 0L, 0, FALSE, NULL, 0, 0, 0}; |
796 char_u use_viscol = FALSE; | |
797 int type = 0; | |
798 int valid; | |
799 long lnum = 0L; | |
800 int enr = 0; | |
801 #ifdef FEAT_WINDOWS | 1118 #ifdef FEAT_WINDOWS |
802 qfline_T *old_last = NULL; | 1119 qfline_T *old_last = NULL; |
803 #endif | 1120 #endif |
804 static efm_T *fmt_first = NULL; | 1121 static efm_T *fmt_first = NULL; |
805 efm_T *fmt_ptr; | |
806 efm_T *fmt_start = NULL; | |
807 char_u *efm; | 1122 char_u *efm; |
808 static char_u *last_efm = NULL; | 1123 static char_u *last_efm = NULL; |
809 char_u *ptr; | |
810 int len; | |
811 int i; | |
812 int idx = 0; | |
813 int retval = -1; /* default: return error flag */ | 1124 int retval = -1; /* default: return error flag */ |
814 int status; | 1125 int status; |
815 char_u *tail = NULL; | 1126 |
816 regmatch_T regmatch; | 1127 fields.namebuf = alloc_id(CMDBUFFSIZE + 1, aid_qf_namebuf); |
817 | 1128 fields.errmsglen = CMDBUFFSIZE + 1; |
818 namebuf = alloc_id(CMDBUFFSIZE + 1, aid_qf_namebuf); | 1129 fields.errmsg = alloc_id(fields.errmsglen, aid_qf_errmsg); |
819 errmsglen = CMDBUFFSIZE + 1; | 1130 fields.pattern = alloc_id(CMDBUFFSIZE + 1, aid_qf_pattern); |
820 errmsg = alloc_id(errmsglen, aid_qf_errmsg); | 1131 if (fields.namebuf == NULL || fields.errmsg == NULL || |
821 pattern = alloc_id(CMDBUFFSIZE + 1, aid_qf_pattern); | 1132 fields.pattern == NULL) |
822 if (namebuf == NULL || errmsg == NULL || pattern == NULL) | |
823 goto qf_init_end; | 1133 goto qf_init_end; |
824 | 1134 |
825 if (efile != NULL && (state.fd = mch_fopen((char *)efile, "r")) == NULL) | 1135 if (efile != NULL && (state.fd = mch_fopen((char *)efile, "r")) == NULL) |
826 { | 1136 { |
827 EMSG2(_(e_openerrf), efile); | 1137 EMSG2(_(e_openerrf), efile); |
837 /* Adding to existing list, use last entry. */ | 1147 /* Adding to existing list, use last entry. */ |
838 old_last = qi->qf_lists[qi->qf_curlist].qf_last; | 1148 old_last = qi->qf_lists[qi->qf_curlist].qf_last; |
839 } | 1149 } |
840 #endif | 1150 #endif |
841 | 1151 |
842 /* | |
843 * Each part of the format string is copied and modified from errorformat to | |
844 * regex prog. Only a few % characters are allowed. | |
845 */ | |
846 /* Use the local value of 'errorformat' if it's set. */ | 1152 /* Use the local value of 'errorformat' if it's set. */ |
847 if (errorformat == p_efm && tv == NULL && *buf->b_p_efm != NUL) | 1153 if (errorformat == p_efm && tv == NULL && *buf->b_p_efm != NUL) |
848 efm = buf->b_p_efm; | 1154 efm = buf->b_p_efm; |
849 else | 1155 else |
850 efm = errorformat; | 1156 efm = errorformat; |
888 * got_int is reset here, because it was probably set when killing the | 1194 * got_int is reset here, because it was probably set when killing the |
889 * ":make" command, but we still want to read the errorfile then. | 1195 * ":make" command, but we still want to read the errorfile then. |
890 */ | 1196 */ |
891 got_int = FALSE; | 1197 got_int = FALSE; |
892 | 1198 |
893 /* Always ignore case when looking for a matching error. */ | |
894 regmatch.rm_ic = TRUE; | |
895 | |
896 if (tv != NULL) | 1199 if (tv != NULL) |
897 { | 1200 { |
898 if (tv->v_type == VAR_STRING) | 1201 if (tv->v_type == VAR_STRING) |
899 state.p_str = tv->vval.v_string; | 1202 state.p_str = tv->vval.v_string; |
900 else if (tv->v_type == VAR_LIST) | 1203 else if (tv->v_type == VAR_LIST) |
916 if (status == QF_NOMEM) /* memory alloc failure */ | 1219 if (status == QF_NOMEM) /* memory alloc failure */ |
917 goto qf_init_end; | 1220 goto qf_init_end; |
918 if (status == QF_END_OF_INPUT) /* end of input */ | 1221 if (status == QF_END_OF_INPUT) /* end of input */ |
919 break; | 1222 break; |
920 | 1223 |
921 /* If there was no %> item start at the first pattern */ | 1224 status = qf_parse_line(qi, state.linebuf, state.linelen, fmt_first, |
922 if (fmt_start == NULL) | 1225 &fields); |
923 fmt_ptr = fmt_first; | 1226 if (status == QF_FAIL) |
924 else | 1227 goto error2; |
925 { | 1228 if (status == QF_NOMEM) |
926 fmt_ptr = fmt_start; | 1229 goto qf_init_end; |
927 fmt_start = NULL; | 1230 if (status == QF_IGNORE_LINE) |
928 } | 1231 continue; |
929 | |
930 /* | |
931 * Try to match each part of 'errorformat' until we find a complete | |
932 * match or no match. | |
933 */ | |
934 valid = TRUE; | |
935 restofline: | |
936 for ( ; fmt_ptr != NULL; fmt_ptr = fmt_ptr->next) | |
937 { | |
938 int r; | |
939 | |
940 idx = fmt_ptr->prefix; | |
941 if (qi->qf_multiscan && vim_strchr((char_u *)"OPQ", idx) == NULL) | |
942 continue; | |
943 namebuf[0] = NUL; | |
944 pattern[0] = NUL; | |
945 if (!qi->qf_multiscan) | |
946 errmsg[0] = NUL; | |
947 lnum = 0; | |
948 col = 0; | |
949 use_viscol = FALSE; | |
950 enr = -1; | |
951 type = 0; | |
952 tail = NULL; | |
953 | |
954 regmatch.regprog = fmt_ptr->prog; | |
955 r = vim_regexec(®match, state.linebuf, (colnr_T)0); | |
956 fmt_ptr->prog = regmatch.regprog; | |
957 if (r) | |
958 { | |
959 if ((idx == 'C' || idx == 'Z') && !qi->qf_multiline) | |
960 continue; | |
961 if (vim_strchr((char_u *)"EWI", idx) != NULL) | |
962 type = idx; | |
963 else | |
964 type = 0; | |
965 /* | |
966 * Extract error message data from matched line. | |
967 * We check for an actual submatch, because "\[" and "\]" in | |
968 * the 'errorformat' may cause the wrong submatch to be used. | |
969 */ | |
970 if ((i = (int)fmt_ptr->addr[0]) > 0) /* %f */ | |
971 { | |
972 int c; | |
973 | |
974 if (regmatch.startp[i] == NULL || regmatch.endp[i] == NULL) | |
975 continue; | |
976 | |
977 /* Expand ~/file and $HOME/file to full path. */ | |
978 c = *regmatch.endp[i]; | |
979 *regmatch.endp[i] = NUL; | |
980 expand_env(regmatch.startp[i], namebuf, CMDBUFFSIZE); | |
981 *regmatch.endp[i] = c; | |
982 | |
983 if (vim_strchr((char_u *)"OPQ", idx) != NULL | |
984 && mch_getperm(namebuf) == -1) | |
985 continue; | |
986 } | |
987 if ((i = (int)fmt_ptr->addr[1]) > 0) /* %n */ | |
988 { | |
989 if (regmatch.startp[i] == NULL) | |
990 continue; | |
991 enr = (int)atol((char *)regmatch.startp[i]); | |
992 } | |
993 if ((i = (int)fmt_ptr->addr[2]) > 0) /* %l */ | |
994 { | |
995 if (regmatch.startp[i] == NULL) | |
996 continue; | |
997 lnum = atol((char *)regmatch.startp[i]); | |
998 } | |
999 if ((i = (int)fmt_ptr->addr[3]) > 0) /* %c */ | |
1000 { | |
1001 if (regmatch.startp[i] == NULL) | |
1002 continue; | |
1003 col = (int)atol((char *)regmatch.startp[i]); | |
1004 } | |
1005 if ((i = (int)fmt_ptr->addr[4]) > 0) /* %t */ | |
1006 { | |
1007 if (regmatch.startp[i] == NULL) | |
1008 continue; | |
1009 type = *regmatch.startp[i]; | |
1010 } | |
1011 if (fmt_ptr->flags == '+' && !qi->qf_multiscan) /* %+ */ | |
1012 { | |
1013 if (state.linelen > errmsglen) { | |
1014 /* linelen + null terminator */ | |
1015 if ((errmsg = vim_realloc(errmsg, | |
1016 state.linelen + 1)) == NULL) | |
1017 goto qf_init_end; | |
1018 errmsglen = state.linelen + 1; | |
1019 } | |
1020 vim_strncpy(errmsg, state.linebuf, state.linelen); | |
1021 } | |
1022 else if ((i = (int)fmt_ptr->addr[5]) > 0) /* %m */ | |
1023 { | |
1024 if (regmatch.startp[i] == NULL || regmatch.endp[i] == NULL) | |
1025 continue; | |
1026 len = (int)(regmatch.endp[i] - regmatch.startp[i]); | |
1027 if (len > errmsglen) { | |
1028 /* len + null terminator */ | |
1029 if ((errmsg = vim_realloc(errmsg, len + 1)) | |
1030 == NULL) | |
1031 goto qf_init_end; | |
1032 errmsglen = len + 1; | |
1033 } | |
1034 vim_strncpy(errmsg, regmatch.startp[i], len); | |
1035 } | |
1036 if ((i = (int)fmt_ptr->addr[6]) > 0) /* %r */ | |
1037 { | |
1038 if (regmatch.startp[i] == NULL) | |
1039 continue; | |
1040 tail = regmatch.startp[i]; | |
1041 } | |
1042 if ((i = (int)fmt_ptr->addr[7]) > 0) /* %p */ | |
1043 { | |
1044 char_u *match_ptr; | |
1045 | |
1046 if (regmatch.startp[i] == NULL || regmatch.endp[i] == NULL) | |
1047 continue; | |
1048 col = 0; | |
1049 for (match_ptr = regmatch.startp[i]; | |
1050 match_ptr != regmatch.endp[i]; ++match_ptr) | |
1051 { | |
1052 ++col; | |
1053 if (*match_ptr == TAB) | |
1054 { | |
1055 col += 7; | |
1056 col -= col % 8; | |
1057 } | |
1058 } | |
1059 ++col; | |
1060 use_viscol = TRUE; | |
1061 } | |
1062 if ((i = (int)fmt_ptr->addr[8]) > 0) /* %v */ | |
1063 { | |
1064 if (regmatch.startp[i] == NULL) | |
1065 continue; | |
1066 col = (int)atol((char *)regmatch.startp[i]); | |
1067 use_viscol = TRUE; | |
1068 } | |
1069 if ((i = (int)fmt_ptr->addr[9]) > 0) /* %s */ | |
1070 { | |
1071 if (regmatch.startp[i] == NULL || regmatch.endp[i] == NULL) | |
1072 continue; | |
1073 len = (int)(regmatch.endp[i] - regmatch.startp[i]); | |
1074 if (len > CMDBUFFSIZE - 5) | |
1075 len = CMDBUFFSIZE - 5; | |
1076 STRCPY(pattern, "^\\V"); | |
1077 STRNCAT(pattern, regmatch.startp[i], len); | |
1078 pattern[len + 3] = '\\'; | |
1079 pattern[len + 4] = '$'; | |
1080 pattern[len + 5] = NUL; | |
1081 } | |
1082 break; | |
1083 } | |
1084 } | |
1085 qi->qf_multiscan = FALSE; | |
1086 | |
1087 if (fmt_ptr == NULL || idx == 'D' || idx == 'X') | |
1088 { | |
1089 if (fmt_ptr != NULL) | |
1090 { | |
1091 if (idx == 'D') /* enter directory */ | |
1092 { | |
1093 if (*namebuf == NUL) | |
1094 { | |
1095 EMSG(_("E379: Missing or empty directory name")); | |
1096 goto error2; | |
1097 } | |
1098 qi->qf_directory = | |
1099 qf_push_dir(namebuf, &qi->qf_dir_stack, FALSE); | |
1100 if (qi->qf_directory == NULL) | |
1101 goto error2; | |
1102 } | |
1103 else if (idx == 'X') /* leave directory */ | |
1104 qi->qf_directory = qf_pop_dir(&qi->qf_dir_stack); | |
1105 } | |
1106 namebuf[0] = NUL; /* no match found, remove file name */ | |
1107 lnum = 0; /* don't jump to this line */ | |
1108 valid = FALSE; | |
1109 if (state.linelen > errmsglen) { | |
1110 /* linelen + null terminator */ | |
1111 if ((errmsg = vim_realloc(errmsg, state.linelen + 1)) == NULL) | |
1112 goto qf_init_end; | |
1113 errmsglen = state.linelen + 1; | |
1114 } | |
1115 /* copy whole line to error message */ | |
1116 vim_strncpy(errmsg, state.linebuf, state.linelen); | |
1117 if (fmt_ptr == NULL) | |
1118 qi->qf_multiline = qi->qf_multiignore = FALSE; | |
1119 } | |
1120 else if (fmt_ptr != NULL) | |
1121 { | |
1122 /* honor %> item */ | |
1123 if (fmt_ptr->conthere) | |
1124 fmt_start = fmt_ptr; | |
1125 | |
1126 if (vim_strchr((char_u *)"AEWI", idx) != NULL) | |
1127 { | |
1128 qi->qf_multiline = TRUE; /* start of a multi-line message */ | |
1129 qi->qf_multiignore = FALSE; /* reset continuation */ | |
1130 } | |
1131 else if (vim_strchr((char_u *)"CZ", idx) != NULL) | |
1132 { /* continuation of multi-line msg */ | |
1133 qfline_T *qfprev = qi->qf_lists[qi->qf_curlist].qf_last; | |
1134 | |
1135 if (qfprev == NULL) | |
1136 goto error2; | |
1137 if (*errmsg && !qi->qf_multiignore) | |
1138 { | |
1139 len = (int)STRLEN(qfprev->qf_text); | |
1140 if ((ptr = alloc((unsigned)(len + STRLEN(errmsg) + 2))) | |
1141 == NULL) | |
1142 goto error2; | |
1143 STRCPY(ptr, qfprev->qf_text); | |
1144 vim_free(qfprev->qf_text); | |
1145 qfprev->qf_text = ptr; | |
1146 *(ptr += len) = '\n'; | |
1147 STRCPY(++ptr, errmsg); | |
1148 } | |
1149 if (qfprev->qf_nr == -1) | |
1150 qfprev->qf_nr = enr; | |
1151 if (vim_isprintc(type) && !qfprev->qf_type) | |
1152 qfprev->qf_type = type; /* only printable chars allowed */ | |
1153 if (!qfprev->qf_lnum) | |
1154 qfprev->qf_lnum = lnum; | |
1155 if (!qfprev->qf_col) | |
1156 qfprev->qf_col = col; | |
1157 qfprev->qf_viscol = use_viscol; | |
1158 if (!qfprev->qf_fnum) | |
1159 qfprev->qf_fnum = qf_get_fnum(qi, qi->qf_directory, | |
1160 *namebuf || qi->qf_directory != NULL | |
1161 ? namebuf | |
1162 : qi->qf_currfile != NULL && valid | |
1163 ? qi->qf_currfile : 0); | |
1164 if (idx == 'Z') | |
1165 qi->qf_multiline = qi->qf_multiignore = FALSE; | |
1166 line_breakcheck(); | |
1167 continue; | |
1168 } | |
1169 else if (vim_strchr((char_u *)"OPQ", idx) != NULL) | |
1170 { | |
1171 /* global file names */ | |
1172 valid = FALSE; | |
1173 if (*namebuf == NUL || mch_getperm(namebuf) >= 0) | |
1174 { | |
1175 if (*namebuf && idx == 'P') | |
1176 qi->qf_currfile = | |
1177 qf_push_dir(namebuf, &qi->qf_file_stack, TRUE); | |
1178 else if (idx == 'Q') | |
1179 qi->qf_currfile = qf_pop_dir(&qi->qf_file_stack); | |
1180 *namebuf = NUL; | |
1181 if (tail && *tail) | |
1182 { | |
1183 STRMOVE(IObuff, skipwhite(tail)); | |
1184 qi->qf_multiscan = TRUE; | |
1185 goto restofline; | |
1186 } | |
1187 } | |
1188 } | |
1189 if (fmt_ptr->flags == '-') /* generally exclude this line */ | |
1190 { | |
1191 if (qi->qf_multiline) | |
1192 /* also exclude continuation lines */ | |
1193 qi->qf_multiignore = TRUE; | |
1194 continue; | |
1195 } | |
1196 } | |
1197 | 1232 |
1198 if (qf_add_entry(qi, | 1233 if (qf_add_entry(qi, |
1199 qi->qf_directory, | 1234 qi->qf_directory, |
1200 (*namebuf || qi->qf_directory != NULL) | 1235 (*fields.namebuf || qi->qf_directory != NULL) |
1201 ? namebuf | 1236 ? fields.namebuf |
1202 : ((qi->qf_currfile != NULL && valid) | 1237 : ((qi->qf_currfile != NULL && fields.valid) |
1203 ? qi->qf_currfile : (char_u *)NULL), | 1238 ? qi->qf_currfile : (char_u *)NULL), |
1204 0, | 1239 0, |
1205 errmsg, | 1240 fields.errmsg, |
1206 lnum, | 1241 fields.lnum, |
1207 col, | 1242 fields.col, |
1208 use_viscol, | 1243 fields.use_viscol, |
1209 pattern, | 1244 fields.pattern, |
1210 enr, | 1245 fields.enr, |
1211 type, | 1246 fields.type, |
1212 valid) == FAIL) | 1247 fields.valid) == FAIL) |
1213 goto error2; | 1248 goto error2; |
1214 line_breakcheck(); | 1249 line_breakcheck(); |
1215 } | 1250 } |
1216 if (state.fd == NULL || !ferror(state.fd)) | 1251 if (state.fd == NULL || !ferror(state.fd)) |
1217 { | 1252 { |
1241 if (qi->qf_curlist > 0) | 1276 if (qi->qf_curlist > 0) |
1242 --qi->qf_curlist; | 1277 --qi->qf_curlist; |
1243 qf_init_end: | 1278 qf_init_end: |
1244 if (state.fd != NULL) | 1279 if (state.fd != NULL) |
1245 fclose(state.fd); | 1280 fclose(state.fd); |
1246 vim_free(namebuf); | 1281 vim_free(fields.namebuf); |
1247 vim_free(errmsg); | 1282 vim_free(fields.errmsg); |
1248 vim_free(pattern); | 1283 vim_free(fields.pattern); |
1249 vim_free(state.growbuf); | 1284 vim_free(state.growbuf); |
1250 | 1285 |
1251 #ifdef FEAT_WINDOWS | 1286 #ifdef FEAT_WINDOWS |
1252 qf_update_buffer(qi, old_last); | 1287 qf_update_buffer(qi, old_last); |
1253 #endif | 1288 #endif |