1 /* find.c */ 2 3 /* Copyright (C) 1994-2002, Jim Hall <jhall@freedos.org> */ 4 5 /* Adapted for ReactOS */ 6 7 /* 8 This program is free software; you can redistribute it and/or modify 9 it under the terms of the GNU General Public License as published by 10 the Free Software Foundation; either version 2 of the License, or 11 (at your option) any later version. 12 13 This program is distributed in the hope that it will be useful, 14 but WITHOUT ANY WARRANTY; without even the implied warranty of 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 GNU General Public License for more details. 17 18 You should have received a copy of the GNU General Public License along 19 with this program; if not, write to the Free Software Foundation, Inc., 20 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 21 */ 22 23 24 /* This program locates a string in a text file and prints those lines 25 * that contain the string. Multiple files are clearly separated. 26 */ 27 28 #include <stdio.h> 29 #include <stdlib.h> 30 //#include <string.h> 31 //#include <ctype.h> 32 33 #include <windef.h> 34 #include <winbase.h> 35 #include <winuser.h> 36 37 //#include <io.h> 38 #include <dos.h> 39 40 #include "resource.h" 41 42 /* Symbol definition */ 43 #define MAX_STR 1024 44 45 /* This function prints out all lines containing a substring. There are some 46 * conditions that may be passed to the function. 47 * 48 * RETURN: If the string was found at least once, returns 1. 49 * If the string was not found at all, returns 0. 50 */ 51 int 52 find_str (char *sz, FILE *p, int invert_search, 53 int count_lines, int number_output, int ignore_case) 54 { 55 int i, length; 56 long line_number = 0, total_lines = 0; 57 char *c, temp_str[MAX_STR], this_line[MAX_STR]; 58 59 /* Convert to upper if needed */ 60 if (ignore_case) 61 { 62 length = strlen (sz); 63 for (i = 0; i < length; i++) 64 sz[i] = toupper (sz[i]); 65 } 66 67 /* Scan the file until EOF */ 68 while (fgets (temp_str, MAX_STR, p) != NULL) 69 { 70 /* Remove the trailing newline */ 71 length = strlen (temp_str); 72 if (temp_str[length-1] == '\n') 73 { 74 temp_str[length-1] = '\0'; 75 } 76 77 /* Increment number of lines */ 78 line_number++; 79 strcpy (this_line, temp_str); 80 81 /* Convert to upper if needed */ 82 if (ignore_case) 83 { 84 for (i = 0; i < length; i++) 85 { 86 temp_str[i] = toupper (temp_str[i]); 87 } 88 } 89 90 /* Locate the substring */ 91 92 /* strstr() returns a pointer to the first occurrence in the 93 string of the substring */ 94 c = strstr (temp_str, sz); 95 96 if ( ((invert_search) ? (c == NULL) : (c != NULL)) ) 97 { 98 if (!count_lines) 99 { 100 if (number_output) 101 printf ("%ld:", line_number); 102 103 /* Print the line of text */ 104 puts (this_line); 105 } 106 107 total_lines++; 108 } /* long if */ 109 } /* while fgets */ 110 111 if (count_lines) 112 { 113 /* Just show num. lines that contain the string */ 114 printf ("%ld\n", total_lines); 115 } 116 117 118 /* RETURN: If the string was found at least once, returns 1. 119 * If the string was not found at all, returns 0. 120 */ 121 return (total_lines > 0 ? 1 : 0); 122 } 123 124 /* Show usage */ 125 void 126 usage (void) 127 { 128 WCHAR wszUsage[4096]; 129 char oemUsage[4096]; 130 131 LoadStringW (GetModuleHandleW (NULL), IDS_USAGE, wszUsage, sizeof(wszUsage) / sizeof(wszUsage[0])); 132 CharToOemW (wszUsage, oemUsage); 133 fputs (oemUsage, stdout); 134 } 135 136 137 /* Main program */ 138 int 139 main (int argc, char **argv) 140 { 141 char *opt, *needle = NULL; 142 int ret = 0; 143 WCHAR wszMessage[4096]; 144 char oemMessage[4096]; 145 146 int invert_search = 0; /* flag to invert the search */ 147 int count_lines = 0; /* flag to whether/not count lines */ 148 int number_output = 0; /* flag to print line numbers */ 149 int ignore_case = 0; /* flag to be case insensitive */ 150 151 FILE *pfile; /* file pointer */ 152 int hfind; /* search handle */ 153 struct _finddata_t finddata; /* _findfirst, filenext block */ 154 155 /* Scan the command line */ 156 while ((--argc) && (needle == NULL)) 157 { 158 if (*(opt = *++argv) == '/') 159 { 160 switch (opt[1]) 161 { 162 case 'c': 163 case 'C': /* Count */ 164 count_lines = 1; 165 break; 166 167 case 'i': 168 case 'I': /* Ignore */ 169 ignore_case = 1; 170 break; 171 172 case 'n': 173 case 'N': /* Number */ 174 number_output = 1; 175 break; 176 177 case 'v': 178 case 'V': /* Not with */ 179 invert_search = 1; 180 break; 181 182 default: 183 usage (); 184 exit (2); /* syntax error .. return error 2 */ 185 break; 186 } 187 } 188 else 189 { 190 /* Get the string */ 191 if (needle == NULL) 192 { 193 /* Assign the string to find */ 194 needle = *argv; 195 } 196 } 197 } 198 199 /* Check for search string */ 200 if (needle == NULL) 201 { 202 /* No string? */ 203 usage (); 204 exit (1); 205 } 206 207 /* Scan the files for the string */ 208 if (argc == 0) 209 { 210 ret = find_str (needle, stdin, invert_search, count_lines, 211 number_output, ignore_case); 212 } 213 214 while (--argc >= 0) 215 { 216 hfind = _findfirst (*++argv, &finddata); 217 if (hfind < 0) 218 { 219 /* We were not able to find a file. Display a message and 220 set the exit status. */ 221 LoadStringW (GetModuleHandleW (NULL), IDS_NO_SUCH_FILE, wszMessage, sizeof(wszMessage) / sizeof(wszMessage[0])); 222 CharToOemW (wszMessage, oemMessage); 223 fprintf (stderr, oemMessage, *argv); 224 } 225 else 226 { 227 /* repeat find next file to match the filemask */ 228 do 229 { 230 /* We have found a file, so try to open it */ 231 if ((pfile = fopen (finddata.name, "r")) != NULL) 232 { 233 printf ("---------------- %s\n", finddata.name); 234 ret = find_str (needle, pfile, invert_search, count_lines, 235 number_output, ignore_case); 236 fclose (pfile); 237 } 238 else 239 { 240 LoadStringW (GetModuleHandleW (NULL), IDS_CANNOT_OPEN, wszMessage, sizeof(wszMessage) / sizeof(wszMessage[0])); 241 CharToOemW (wszMessage, oemMessage); 242 fprintf (stderr, oemMessage, 243 finddata.name); 244 } 245 } 246 while (_findnext(hfind, &finddata) > 0); 247 } 248 _findclose(hfind); 249 } /* for each argv */ 250 251 /* RETURN: If the string was found at least once, returns 0. 252 * If the string was not found at all, returns 1. 253 * (Note that find_str.c returns the exact opposite values.) 254 */ 255 exit ( (ret ? 0 : 1) ); 256 } 257