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(&regmatch, 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(&regmatch, 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