Fossil SCM
Completely rework the "fossil grep" command. Omit the -H option. Instead, print a header line that includes both the file hash and the check-in hash and the timestamp for every file that contains any match. Scan all files together, in reverse chronological order.
Commit
9c2080a360fc4a4e7496eadf0d49722bf7861bf515157bf632bab46c41ec58cb
Parent
1bf2f84843b063c…
1 file changed
+67
-49
+67
-49
| --- src/regexp.c | ||
| +++ src/regexp.c | ||
| @@ -738,15 +738,18 @@ | ||
| 738 | 738 | n = j - i; |
| 739 | 739 | ln++; |
| 740 | 740 | if( re_match(pRe, (const unsigned char*)(z+i), j-i) ){ |
| 741 | 741 | cnt++; |
| 742 | 742 | if( flags & GREP_EXISTS ){ |
| 743 | - if( (flags & GREP_QUIET)==0 ) fossil_print("%S\n", zName); | |
| 743 | + if( (flags & GREP_QUIET)==0 && zName ) fossil_print("%s\n", zName); | |
| 744 | 744 | break; |
| 745 | 745 | } |
| 746 | 746 | if( (flags & GREP_QUIET)==0 ){ |
| 747 | - fossil_print("%S:%d:%.*s\n", zName, ln, n, z+i); | |
| 747 | + if( cnt==1 && zName ){ | |
| 748 | + fossil_print("== %s\n", zName); | |
| 749 | + } | |
| 750 | + fossil_print("%d:%.*s\n", ln, n, z+i); | |
| 748 | 751 | } |
| 749 | 752 | } |
| 750 | 753 | } |
| 751 | 754 | return cnt; |
| 752 | 755 | } |
| @@ -793,19 +796,22 @@ | ||
| 793 | 796 | ** COMMAND: grep |
| 794 | 797 | ** |
| 795 | 798 | ** Usage: %fossil grep [OPTIONS] PATTERN FILENAME ... |
| 796 | 799 | ** |
| 797 | 800 | ** Attempt to match the given POSIX extended regular expression PATTERN |
| 798 | -** over all historic versions of FILENAME. For details of the supported | |
| 799 | -** RE dialect, see https://fossil-scm.org/fossil/doc/trunk/www/grep.md | |
| 801 | +** historic versions of FILENAME. The search begins with the most recent | |
| 802 | +** version of the file and moves backwards in time. Multiple FILENAMEs can | |
| 803 | +** be specified, in which case all named files are searched in reverse | |
| 804 | +** chronological order. | |
| 805 | +** | |
| 806 | +** For details of the supported regular expression dialect, see | |
| 807 | +** https://fossil-scm.org/fossil/doc/trunk/www/grep.md | |
| 800 | 808 | ** |
| 801 | 809 | ** Options: |
| 802 | 810 | ** |
| 803 | 811 | ** -c|--count Suppress normal output; instead print a count |
| 804 | 812 | ** of the number of matching files |
| 805 | -** -H|--checkin-hash Show the check-in hash rather than | |
| 806 | -** file artifact hash for each match | |
| 807 | 813 | ** -i|--ignore-case Ignore case |
| 808 | 814 | ** -l|--files-with-matches List only hash for each match |
| 809 | 815 | ** --once Stop searching after the first match |
| 810 | 816 | ** -s|--no-messages Suppress error messages about nonexistant |
| 811 | 817 | ** or unreadable files |
| @@ -818,23 +824,23 @@ | ||
| 818 | 824 | int bVerbose = 0; |
| 819 | 825 | ReCompiled *pRe; |
| 820 | 826 | const char *zErr; |
| 821 | 827 | int ignoreCase = 0; |
| 822 | 828 | Blob fullName; |
| 823 | - int ckinHash = 0; | |
| 824 | 829 | int ii; |
| 825 | 830 | int nMatch = 0; |
| 826 | 831 | int bNoMsg; |
| 827 | 832 | int cntFlag; |
| 828 | 833 | int bOnce; |
| 829 | 834 | int bInvert; |
| 830 | 835 | int nSearch = 0; |
| 836 | + Stmt q; | |
| 837 | + | |
| 831 | 838 | |
| 832 | 839 | if( find_option("ignore-case","i",0)!=0 ) ignoreCase = 1; |
| 833 | 840 | if( find_option("files-with-matches","l",0)!=0 ) flags |= GREP_EXISTS; |
| 834 | 841 | if( find_option("verbose",0,0)!=0 ) bVerbose = 1; |
| 835 | - ckinHash = find_option("checkin-hash","H",0)!=0; | |
| 836 | 842 | if( find_option("quiet","q",0) ) flags |= GREP_QUIET|GREP_EXISTS; |
| 837 | 843 | bNoMsg = find_option("no-messages","s",0)!=0; |
| 838 | 844 | bOnce = find_option("once",0,0)!=0; |
| 839 | 845 | bInvert = find_option("invert-match","v",0)!=0; |
| 840 | 846 | if( bInvert ){ |
| @@ -851,16 +857,13 @@ | ||
| 851 | 857 | } |
| 852 | 858 | zErr = re_compile(&pRe, g.argv[2], ignoreCase); |
| 853 | 859 | if( zErr ) fossil_fatal("%s", zErr); |
| 854 | 860 | |
| 855 | 861 | add_content_sql_commands(g.db); |
| 862 | + db_multi_exec("CREATE TEMP TABLE arglist(iname,fname,fnid);"); | |
| 856 | 863 | for(ii=3; ii<g.argc; ii++){ |
| 857 | 864 | const char *zTarget = g.argv[ii]; |
| 858 | - if( nMatch ){ | |
| 859 | - if( (flags & GREP_QUIET)!=0 ) break; | |
| 860 | - if( bOnce ) break; | |
| 861 | - } | |
| 862 | 865 | if( file_tree_name(zTarget, &fullName, 0, 1) ){ |
| 863 | 866 | int fnid = db_int(0, "SELECT fnid FROM filename WHERE name=%Q", |
| 864 | 867 | blob_str(&fullName)); |
| 865 | 868 | if( !fnid ){ |
| 866 | 869 | if( bNoMsg ) continue; |
| @@ -867,50 +870,65 @@ | ||
| 867 | 870 | if( file_size(zTarget, ExtFILE)<0 ){ |
| 868 | 871 | fossil_fatal("no such file: %s", zTarget); |
| 869 | 872 | } |
| 870 | 873 | fossil_fatal("not a managed file: %s", zTarget); |
| 871 | 874 | }else{ |
| 872 | - Stmt q; | |
| 873 | - db_prepare(&q, | |
| 874 | - "SELECT content(ux), %w FROM (" | |
| 875 | - " SELECT A.uuid AS ux, B.uuid AS ckin, min(event.mtime) AS mx" | |
| 876 | - " FROM mlink, blob A, blob B, event" | |
| 877 | - " WHERE mlink.mid=event.objid" | |
| 878 | - " AND mlink.fid=A.rid" | |
| 879 | - " AND mlink.mid=B.rid" | |
| 880 | - " AND mlink.fnid=%d" | |
| 881 | - " GROUP BY A.uuid" | |
| 882 | - ") ORDER BY mx DESC;", | |
| 883 | - ckinHash ? "ckin" : "ux", | |
| 884 | - fnid | |
| 885 | - ); | |
| 886 | - while( db_step(&q)==SQLITE_ROW ){ | |
| 887 | - const char *zHash = db_column_text(&q,1); | |
| 888 | - const char *zContent = db_column_text(&q,0); | |
| 889 | - if( bVerbose ) fossil_print("%S:\n", zHash); | |
| 890 | - nSearch++; | |
| 891 | - nMatch += grep_buffer(pRe, zHash, zContent, flags); | |
| 892 | - if( bInvert && cntFlag==0 ){ | |
| 893 | - if( nMatch==0 ){ | |
| 894 | - fossil_print("%S\n", zHash); | |
| 895 | - if( bOnce ) nMatch = 1; | |
| 896 | - }else{ | |
| 897 | - nMatch = 0; | |
| 898 | - } | |
| 899 | - } | |
| 900 | - if( nMatch ){ | |
| 901 | - if( (flags & GREP_QUIET)!=0 ) break; | |
| 902 | - if( bOnce ) break; | |
| 903 | - } | |
| 904 | - } | |
| 905 | - db_finalize(&q); | |
| 906 | - } | |
| 907 | - } | |
| 908 | - } | |
| 875 | + db_multi_exec( | |
| 876 | + "INSERT INTO arglist(iname,fname,fnid) VALUES(%Q,%Q,%d)", | |
| 877 | + zTarget, blob_str(&fullName), fnid); | |
| 878 | + } | |
| 879 | + } | |
| 880 | + blob_reset(&fullName); | |
| 881 | + } | |
| 882 | + db_prepare(&q, | |
| 883 | + " SELECT" | |
| 884 | + " A.uuid," /* file hash */ | |
| 885 | + " A.rid," /* file rid */ | |
| 886 | + " B.uuid," /* check-in hash */ | |
| 887 | + " datetime(min(event.mtime))," /* check-in time */ | |
| 888 | + " arglist.iname" /* file name */ | |
| 889 | + " FROM arglist, mlink, blob A, blob B, event" | |
| 890 | + " WHERE mlink.mid=event.objid" | |
| 891 | + " AND mlink.fid=A.rid" | |
| 892 | + " AND mlink.mid=B.rid" | |
| 893 | + " AND mlink.fnid=arglist.fnid" | |
| 894 | + " GROUP BY A.uuid" | |
| 895 | + " ORDER BY min(event.mtime) DESC;" | |
| 896 | + ); | |
| 897 | + while( db_step(&q)==SQLITE_ROW ){ | |
| 898 | + const char *zFileHash = db_column_text(&q,0); | |
| 899 | + int rid = db_column_int(&q,1); | |
| 900 | + const char *zCkinHash = db_column_text(&q,2); | |
| 901 | + const char *zDate = db_column_text(&q,3); | |
| 902 | + const char *zFN = db_column_text(&q,4); | |
| 903 | + char *zLabel; | |
| 904 | + Blob cx; | |
| 905 | + content_get(rid, &cx); | |
| 906 | + zLabel = mprintf("%.16s %s %S checkin %S", zDate, zFN,zFileHash,zCkinHash); | |
| 907 | + if( bVerbose ) fossil_print("Scanning: %s\n", zLabel); | |
| 908 | + nSearch++; | |
| 909 | + nMatch += grep_buffer(pRe, zLabel, blob_str(&cx), flags); | |
| 910 | + blob_reset(&cx); | |
| 911 | + if( bInvert && cntFlag==0 ){ | |
| 912 | + if( nMatch==0 ){ | |
| 913 | + fossil_print("== %s\n", zLabel); | |
| 914 | + if( bOnce ) nMatch = 1; | |
| 915 | + }else{ | |
| 916 | + nMatch = 0; | |
| 917 | + } | |
| 918 | + } | |
| 919 | + fossil_free(zLabel); | |
| 920 | + if( nMatch ){ | |
| 921 | + if( (flags & GREP_QUIET)!=0 ) break; | |
| 922 | + if( bOnce ) break; | |
| 923 | + } | |
| 924 | + } | |
| 925 | + db_finalize(&q); | |
| 926 | + re_free(pRe); | |
| 909 | 927 | if( cntFlag ){ |
| 910 | 928 | if( bInvert ){ |
| 911 | 929 | fossil_print("%d\n", nSearch-nMatch); |
| 912 | 930 | }else{ |
| 913 | 931 | fossil_print("%d\n", nMatch); |
| 914 | 932 | } |
| 915 | 933 | } |
| 916 | 934 | } |
| 917 | 935 |
| --- src/regexp.c | |
| +++ src/regexp.c | |
| @@ -738,15 +738,18 @@ | |
| 738 | n = j - i; |
| 739 | ln++; |
| 740 | if( re_match(pRe, (const unsigned char*)(z+i), j-i) ){ |
| 741 | cnt++; |
| 742 | if( flags & GREP_EXISTS ){ |
| 743 | if( (flags & GREP_QUIET)==0 ) fossil_print("%S\n", zName); |
| 744 | break; |
| 745 | } |
| 746 | if( (flags & GREP_QUIET)==0 ){ |
| 747 | fossil_print("%S:%d:%.*s\n", zName, ln, n, z+i); |
| 748 | } |
| 749 | } |
| 750 | } |
| 751 | return cnt; |
| 752 | } |
| @@ -793,19 +796,22 @@ | |
| 793 | ** COMMAND: grep |
| 794 | ** |
| 795 | ** Usage: %fossil grep [OPTIONS] PATTERN FILENAME ... |
| 796 | ** |
| 797 | ** Attempt to match the given POSIX extended regular expression PATTERN |
| 798 | ** over all historic versions of FILENAME. For details of the supported |
| 799 | ** RE dialect, see https://fossil-scm.org/fossil/doc/trunk/www/grep.md |
| 800 | ** |
| 801 | ** Options: |
| 802 | ** |
| 803 | ** -c|--count Suppress normal output; instead print a count |
| 804 | ** of the number of matching files |
| 805 | ** -H|--checkin-hash Show the check-in hash rather than |
| 806 | ** file artifact hash for each match |
| 807 | ** -i|--ignore-case Ignore case |
| 808 | ** -l|--files-with-matches List only hash for each match |
| 809 | ** --once Stop searching after the first match |
| 810 | ** -s|--no-messages Suppress error messages about nonexistant |
| 811 | ** or unreadable files |
| @@ -818,23 +824,23 @@ | |
| 818 | int bVerbose = 0; |
| 819 | ReCompiled *pRe; |
| 820 | const char *zErr; |
| 821 | int ignoreCase = 0; |
| 822 | Blob fullName; |
| 823 | int ckinHash = 0; |
| 824 | int ii; |
| 825 | int nMatch = 0; |
| 826 | int bNoMsg; |
| 827 | int cntFlag; |
| 828 | int bOnce; |
| 829 | int bInvert; |
| 830 | int nSearch = 0; |
| 831 | |
| 832 | if( find_option("ignore-case","i",0)!=0 ) ignoreCase = 1; |
| 833 | if( find_option("files-with-matches","l",0)!=0 ) flags |= GREP_EXISTS; |
| 834 | if( find_option("verbose",0,0)!=0 ) bVerbose = 1; |
| 835 | ckinHash = find_option("checkin-hash","H",0)!=0; |
| 836 | if( find_option("quiet","q",0) ) flags |= GREP_QUIET|GREP_EXISTS; |
| 837 | bNoMsg = find_option("no-messages","s",0)!=0; |
| 838 | bOnce = find_option("once",0,0)!=0; |
| 839 | bInvert = find_option("invert-match","v",0)!=0; |
| 840 | if( bInvert ){ |
| @@ -851,16 +857,13 @@ | |
| 851 | } |
| 852 | zErr = re_compile(&pRe, g.argv[2], ignoreCase); |
| 853 | if( zErr ) fossil_fatal("%s", zErr); |
| 854 | |
| 855 | add_content_sql_commands(g.db); |
| 856 | for(ii=3; ii<g.argc; ii++){ |
| 857 | const char *zTarget = g.argv[ii]; |
| 858 | if( nMatch ){ |
| 859 | if( (flags & GREP_QUIET)!=0 ) break; |
| 860 | if( bOnce ) break; |
| 861 | } |
| 862 | if( file_tree_name(zTarget, &fullName, 0, 1) ){ |
| 863 | int fnid = db_int(0, "SELECT fnid FROM filename WHERE name=%Q", |
| 864 | blob_str(&fullName)); |
| 865 | if( !fnid ){ |
| 866 | if( bNoMsg ) continue; |
| @@ -867,50 +870,65 @@ | |
| 867 | if( file_size(zTarget, ExtFILE)<0 ){ |
| 868 | fossil_fatal("no such file: %s", zTarget); |
| 869 | } |
| 870 | fossil_fatal("not a managed file: %s", zTarget); |
| 871 | }else{ |
| 872 | Stmt q; |
| 873 | db_prepare(&q, |
| 874 | "SELECT content(ux), %w FROM (" |
| 875 | " SELECT A.uuid AS ux, B.uuid AS ckin, min(event.mtime) AS mx" |
| 876 | " FROM mlink, blob A, blob B, event" |
| 877 | " WHERE mlink.mid=event.objid" |
| 878 | " AND mlink.fid=A.rid" |
| 879 | " AND mlink.mid=B.rid" |
| 880 | " AND mlink.fnid=%d" |
| 881 | " GROUP BY A.uuid" |
| 882 | ") ORDER BY mx DESC;", |
| 883 | ckinHash ? "ckin" : "ux", |
| 884 | fnid |
| 885 | ); |
| 886 | while( db_step(&q)==SQLITE_ROW ){ |
| 887 | const char *zHash = db_column_text(&q,1); |
| 888 | const char *zContent = db_column_text(&q,0); |
| 889 | if( bVerbose ) fossil_print("%S:\n", zHash); |
| 890 | nSearch++; |
| 891 | nMatch += grep_buffer(pRe, zHash, zContent, flags); |
| 892 | if( bInvert && cntFlag==0 ){ |
| 893 | if( nMatch==0 ){ |
| 894 | fossil_print("%S\n", zHash); |
| 895 | if( bOnce ) nMatch = 1; |
| 896 | }else{ |
| 897 | nMatch = 0; |
| 898 | } |
| 899 | } |
| 900 | if( nMatch ){ |
| 901 | if( (flags & GREP_QUIET)!=0 ) break; |
| 902 | if( bOnce ) break; |
| 903 | } |
| 904 | } |
| 905 | db_finalize(&q); |
| 906 | } |
| 907 | } |
| 908 | } |
| 909 | if( cntFlag ){ |
| 910 | if( bInvert ){ |
| 911 | fossil_print("%d\n", nSearch-nMatch); |
| 912 | }else{ |
| 913 | fossil_print("%d\n", nMatch); |
| 914 | } |
| 915 | } |
| 916 | } |
| 917 |
| --- src/regexp.c | |
| +++ src/regexp.c | |
| @@ -738,15 +738,18 @@ | |
| 738 | n = j - i; |
| 739 | ln++; |
| 740 | if( re_match(pRe, (const unsigned char*)(z+i), j-i) ){ |
| 741 | cnt++; |
| 742 | if( flags & GREP_EXISTS ){ |
| 743 | if( (flags & GREP_QUIET)==0 && zName ) fossil_print("%s\n", zName); |
| 744 | break; |
| 745 | } |
| 746 | if( (flags & GREP_QUIET)==0 ){ |
| 747 | if( cnt==1 && zName ){ |
| 748 | fossil_print("== %s\n", zName); |
| 749 | } |
| 750 | fossil_print("%d:%.*s\n", ln, n, z+i); |
| 751 | } |
| 752 | } |
| 753 | } |
| 754 | return cnt; |
| 755 | } |
| @@ -793,19 +796,22 @@ | |
| 796 | ** COMMAND: grep |
| 797 | ** |
| 798 | ** Usage: %fossil grep [OPTIONS] PATTERN FILENAME ... |
| 799 | ** |
| 800 | ** Attempt to match the given POSIX extended regular expression PATTERN |
| 801 | ** historic versions of FILENAME. The search begins with the most recent |
| 802 | ** version of the file and moves backwards in time. Multiple FILENAMEs can |
| 803 | ** be specified, in which case all named files are searched in reverse |
| 804 | ** chronological order. |
| 805 | ** |
| 806 | ** For details of the supported regular expression dialect, see |
| 807 | ** https://fossil-scm.org/fossil/doc/trunk/www/grep.md |
| 808 | ** |
| 809 | ** Options: |
| 810 | ** |
| 811 | ** -c|--count Suppress normal output; instead print a count |
| 812 | ** of the number of matching files |
| 813 | ** -i|--ignore-case Ignore case |
| 814 | ** -l|--files-with-matches List only hash for each match |
| 815 | ** --once Stop searching after the first match |
| 816 | ** -s|--no-messages Suppress error messages about nonexistant |
| 817 | ** or unreadable files |
| @@ -818,23 +824,23 @@ | |
| 824 | int bVerbose = 0; |
| 825 | ReCompiled *pRe; |
| 826 | const char *zErr; |
| 827 | int ignoreCase = 0; |
| 828 | Blob fullName; |
| 829 | int ii; |
| 830 | int nMatch = 0; |
| 831 | int bNoMsg; |
| 832 | int cntFlag; |
| 833 | int bOnce; |
| 834 | int bInvert; |
| 835 | int nSearch = 0; |
| 836 | Stmt q; |
| 837 | |
| 838 | |
| 839 | if( find_option("ignore-case","i",0)!=0 ) ignoreCase = 1; |
| 840 | if( find_option("files-with-matches","l",0)!=0 ) flags |= GREP_EXISTS; |
| 841 | if( find_option("verbose",0,0)!=0 ) bVerbose = 1; |
| 842 | if( find_option("quiet","q",0) ) flags |= GREP_QUIET|GREP_EXISTS; |
| 843 | bNoMsg = find_option("no-messages","s",0)!=0; |
| 844 | bOnce = find_option("once",0,0)!=0; |
| 845 | bInvert = find_option("invert-match","v",0)!=0; |
| 846 | if( bInvert ){ |
| @@ -851,16 +857,13 @@ | |
| 857 | } |
| 858 | zErr = re_compile(&pRe, g.argv[2], ignoreCase); |
| 859 | if( zErr ) fossil_fatal("%s", zErr); |
| 860 | |
| 861 | add_content_sql_commands(g.db); |
| 862 | db_multi_exec("CREATE TEMP TABLE arglist(iname,fname,fnid);"); |
| 863 | for(ii=3; ii<g.argc; ii++){ |
| 864 | const char *zTarget = g.argv[ii]; |
| 865 | if( file_tree_name(zTarget, &fullName, 0, 1) ){ |
| 866 | int fnid = db_int(0, "SELECT fnid FROM filename WHERE name=%Q", |
| 867 | blob_str(&fullName)); |
| 868 | if( !fnid ){ |
| 869 | if( bNoMsg ) continue; |
| @@ -867,50 +870,65 @@ | |
| 870 | if( file_size(zTarget, ExtFILE)<0 ){ |
| 871 | fossil_fatal("no such file: %s", zTarget); |
| 872 | } |
| 873 | fossil_fatal("not a managed file: %s", zTarget); |
| 874 | }else{ |
| 875 | db_multi_exec( |
| 876 | "INSERT INTO arglist(iname,fname,fnid) VALUES(%Q,%Q,%d)", |
| 877 | zTarget, blob_str(&fullName), fnid); |
| 878 | } |
| 879 | } |
| 880 | blob_reset(&fullName); |
| 881 | } |
| 882 | db_prepare(&q, |
| 883 | " SELECT" |
| 884 | " A.uuid," /* file hash */ |
| 885 | " A.rid," /* file rid */ |
| 886 | " B.uuid," /* check-in hash */ |
| 887 | " datetime(min(event.mtime))," /* check-in time */ |
| 888 | " arglist.iname" /* file name */ |
| 889 | " FROM arglist, mlink, blob A, blob B, event" |
| 890 | " WHERE mlink.mid=event.objid" |
| 891 | " AND mlink.fid=A.rid" |
| 892 | " AND mlink.mid=B.rid" |
| 893 | " AND mlink.fnid=arglist.fnid" |
| 894 | " GROUP BY A.uuid" |
| 895 | " ORDER BY min(event.mtime) DESC;" |
| 896 | ); |
| 897 | while( db_step(&q)==SQLITE_ROW ){ |
| 898 | const char *zFileHash = db_column_text(&q,0); |
| 899 | int rid = db_column_int(&q,1); |
| 900 | const char *zCkinHash = db_column_text(&q,2); |
| 901 | const char *zDate = db_column_text(&q,3); |
| 902 | const char *zFN = db_column_text(&q,4); |
| 903 | char *zLabel; |
| 904 | Blob cx; |
| 905 | content_get(rid, &cx); |
| 906 | zLabel = mprintf("%.16s %s %S checkin %S", zDate, zFN,zFileHash,zCkinHash); |
| 907 | if( bVerbose ) fossil_print("Scanning: %s\n", zLabel); |
| 908 | nSearch++; |
| 909 | nMatch += grep_buffer(pRe, zLabel, blob_str(&cx), flags); |
| 910 | blob_reset(&cx); |
| 911 | if( bInvert && cntFlag==0 ){ |
| 912 | if( nMatch==0 ){ |
| 913 | fossil_print("== %s\n", zLabel); |
| 914 | if( bOnce ) nMatch = 1; |
| 915 | }else{ |
| 916 | nMatch = 0; |
| 917 | } |
| 918 | } |
| 919 | fossil_free(zLabel); |
| 920 | if( nMatch ){ |
| 921 | if( (flags & GREP_QUIET)!=0 ) break; |
| 922 | if( bOnce ) break; |
| 923 | } |
| 924 | } |
| 925 | db_finalize(&q); |
| 926 | re_free(pRe); |
| 927 | if( cntFlag ){ |
| 928 | if( bInvert ){ |
| 929 | fossil_print("%d\n", nSearch-nMatch); |
| 930 | }else{ |
| 931 | fossil_print("%d\n", nMatch); |
| 932 | } |
| 933 | } |
| 934 | } |
| 935 |