1b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/************************************************************************** 2b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* 350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho* Copyright (C) 2002-2010, International Business Machines 4b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* Corporation and others. All Rights Reserved. 5b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* 6b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*************************************************************************** 7b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*/ 8b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 9b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// 10b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// ugrep - an ICU sample program illustrating the use of ICU Regular Expressions. 11b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// 12b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// The use of the ICU Regex API all occurs within the main() 13b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// function. The rest of the code deals with with opening files, 14b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// encoding conversions, printing results, etc. 15b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// 16b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// This is not a full-featured grep program. The command line options 17b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// have been kept to a minimum to avoid complicating the sample code. 18b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// 19b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 20b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 21b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 22b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include <stdio.h> 23b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include <stdlib.h> 24b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include <string.h> 25b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 26b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/utypes.h" 27b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/ustring.h" 28b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/regex.h" 29b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/ucnv.h" 30b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/uclean.h" 31b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 32b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 33b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// 34b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// The following variables contain paramters that may be set from the command line. 35b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// 36b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruconst char *pattern = NULL; // The regular expression 37b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint firstFileNum; // argv index of the first file name 38b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUBool displayFileName = FALSE; 39b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUBool displayLineNum = FALSE; 40b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 41b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 42b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// 43b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// Info regarding the file currently being processed 44b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// 45b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruconst char *fileName; 46b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint fileLen; // Length, in UTF-16 Code Units. 47b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 48b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUChar *ucharBuf = 0; // Buffer, holds converted file. (Simple minded program, always reads 49b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // the whole file at once. 50b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 51b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruchar *charBuf = 0; // Buffer, for original, unconverted file data. 52b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 53b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 54b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// 55b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// Info regarding the line currently being processed 56b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// 57b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint lineStart; // Index of first char of the current line in the file buffer 58b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint lineEnd; // Index of char following the new line sequence for the current line 59b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint lineNum; 60b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 61b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// 62b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// Converter, used on output to convert Unicode data back to char * 63b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// so that it will display in non-Unicode terminal windows. 64b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// 65b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUConverter *outConverter = 0; 66b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 67b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// 68b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// Function forward declarations 69b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// 70b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid processOptions(int argc, const char **argv); 71b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid nextLine(int start); 72b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid printMatch(); 73b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid printUsage(); 74b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid readFile(const char *name); 75b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 76b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 77b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 78b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//------------------------------------------------------------------------------------------ 79b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// 80b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// main for ugrep 81b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// 82b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// Structurally, all use of the ICU Regular Expression API is in main(), 83b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// and all of the supporting stuff necessary to make a running program, but 84b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// not directly related to regular expressions, is factored out into these other 85b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// functions. 86b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// 87b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//------------------------------------------------------------------------------------------ 88b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint main(int argc, const char** argv) { 89b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UBool matchFound = FALSE; 90b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 91b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // 92b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Process the commmand line options. 93b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // 94b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru processOptions(argc, argv); 95b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 96b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // 97b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Create a RegexPattern object from the user supplied pattern string. 98b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // 99b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UErrorCode status = U_ZERO_ERROR; // All ICU operations report success or failure 100b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // in a status variable. 101b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 102b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UParseError parseErr; // In the event of a syntax error in the regex pattern, 103b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // this struct will contain the position of the 104b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // error. 105b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 106b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru RegexPattern *rePat = RegexPattern::compile(pattern, parseErr, status); 107b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Note that C++ is doing an automatic conversion 108b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // of the (char *) pattern to a temporary 109b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // UnicodeString object. 110b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (U_FAILURE(status)) { 111b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru fprintf(stderr, "ugrep: error in pattern: \"%s\" at position %d\n", 112b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru u_errorName(status), parseErr.offset); 113b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru exit(-1); 114b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 115b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 116b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // 117b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Create a RegexMatcher from the newly created pattern. 118b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // 119b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UnicodeString empty; 120b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru RegexMatcher *matcher = rePat->matcher(empty, status); 121b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (U_FAILURE(status)) { 122b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru fprintf(stderr, "ugrep: error in creating RegexMatcher: \"%s\"\n", 123b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru u_errorName(status)); 124b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru exit(-1); 125b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 126b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 127b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // 128b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Loop, processing each of the input files. 129b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // 130b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru for (int fileNum=firstFileNum; fileNum < argc; fileNum++) { 131b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru readFile(argv[fileNum]); 132b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 133b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // 134b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Loop through the lines of a file, trying to match the regex pattern on each. 135b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // 136b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru for (nextLine(0); lineStart<fileLen; nextLine(lineEnd)) { 137b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UnicodeString s(FALSE, ucharBuf+lineStart, lineEnd-lineStart); 138b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru matcher->reset(s); 139b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (matcher->find()) { 140b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru matchFound = TRUE; 141b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru printMatch(); 142b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 143b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 144b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 145b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 146b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // 147b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Clean up 148b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // 149b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru delete matcher; 150b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru delete rePat; 151b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru free(ucharBuf); 152b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru free(charBuf); 153b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ucnv_close(outConverter); 154b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 155b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru u_cleanup(); // shut down ICU, release any cached data it owns. 156b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 157b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return matchFound? 0: 1; 158b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 159b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 160b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 161b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 162b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//------------------------------------------------------------------------------------------ 163b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// 164b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// doOptions Run through the command line options, and set 165b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// the global variables accordingly. 166b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// 167b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// exit without returning if an error occured and 168b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// ugrep should not proceed further. 169b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// 170b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//------------------------------------------------------------------------------------------ 171b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid processOptions(int argc, const char **argv) { 172b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int optInd; 173b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UBool doUsage = FALSE; 174b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UBool doVersion = FALSE; 175b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru const char *arg; 176b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 177b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 178b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru for(optInd = 1; optInd < argc; ++optInd) { 179b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru arg = argv[optInd]; 180b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 181b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru /* version info */ 182b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if(strcmp(arg, "-V") == 0 || strcmp(arg, "--version") == 0) { 183b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru doVersion = TRUE; 184b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 185b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru /* usage info */ 186b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru else if(strcmp(arg, "--help") == 0) { 187b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru doUsage = TRUE; 188b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 189b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru else if(strcmp(arg, "-n") == 0 || strcmp(arg, "--line-number") == 0) { 190b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru displayLineNum = TRUE; 191b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 192b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru /* POSIX.1 says all arguments after -- are not options */ 193b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru else if(strcmp(arg, "--") == 0) { 194b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru /* skip the -- */ 195b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ++optInd; 196b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru break; 197b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 198b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru /* unrecognized option */ 199b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru else if(strncmp(arg, "-", strlen("-")) == 0) { 200b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru printf("ugrep: invalid option -- %s\n", arg+1); 201b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru doUsage = TRUE; 202b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 203b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru /* done with options */ 204b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru else { 205b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru break; 206b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 207b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 208b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 209b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (doUsage) { 210b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru printUsage(); 211b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru exit(0); 212b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 213b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 214b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (doVersion) { 215b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru printf("ugrep version 0.01\n"); 216b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (optInd == argc) { 217b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru exit(0); 218b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 219b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 220b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 221b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int remainingArgs = argc-optInd; // pattern file ... 222b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (remainingArgs < 2) { 223b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru fprintf(stderr, "ugrep: files or pattern are missing.\n"); 224b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru printUsage(); 225b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru exit(1); 226b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 227b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 228b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (remainingArgs > 2) { 229b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // More than one file to be processed. Display file names with match output. 230b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru displayFileName = TRUE; 231b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 232b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 233b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru pattern = argv[optInd]; 234b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru firstFileNum = optInd+1; 235b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 236b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 237b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//------------------------------------------------------------------------------------------ 238b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// 239b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// printUsage 240b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// 241b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//------------------------------------------------------------------------------------------ 242b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid printUsage() { 243b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru printf("ugrep [options] pattern file...\n" 244b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru " -V or --version display version information\n" 245b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru " --help display this help and exit\n" 246b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru " -- stop further option processing\n" 247b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru "-n, --line-number Prefix each line of output with the line number within its input file.\n" 248b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ); 249b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru exit(0); 250b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 251b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 252b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//------------------------------------------------------------------------------------------ 253b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// 254b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// readFile Read a file into memory, and convert it to Unicode. 255b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// 256b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// Since this is just a demo program, take the simple minded approach 257b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// of always reading the whole file at once. No intelligent buffering 258b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// is done. 259b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// 260b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//------------------------------------------------------------------------------------------ 261b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid readFile(const char *name) { 262b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 263b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // 264b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Initialize global file variables 265b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // 266b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru fileName = name; 267b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru fileLen = 0; // zero length prevents processing in case of errors. 268b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 269b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 270b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // 271b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Open the file and determine its size. 272b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // 273b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru FILE *file = fopen(name, "rb"); 274b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (file == 0 ) { 275b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru fprintf(stderr, "ugrep: Could not open file \"%s\"\n", fileName); 276b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return; 277b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 278b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru fseek(file, 0, SEEK_END); 279b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int rawFileLen = ftell(file); 280b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru fseek(file, 0, SEEK_SET); 281b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 282b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 283b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // 284b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Read in the file 285b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // 286b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru charBuf = (char *)realloc(charBuf, rawFileLen+1); // Need error checking... 287b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int t = fread(charBuf, 1, rawFileLen, file); 288b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (t != rawFileLen) { 289b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru fprintf(stderr, "Error reading file \"%s\"\n", fileName); 29050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho fclose(file); 291b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return; 292b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 293b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru charBuf[rawFileLen]=0; 294b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru fclose(file); 295b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 296b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // 297b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Look for a Unicode Signature (BOM) in the data 298b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // 299b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t signatureLength; 300b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru const char * charDataStart = charBuf; 301b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UErrorCode status = U_ZERO_ERROR; 302b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru const char* encoding = ucnv_detectUnicodeSignature( 303b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru charDataStart, rawFileLen, &signatureLength, &status); 304b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (U_FAILURE(status)) { 305b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru fprintf(stderr, "ugrep: ICU Error \"%s\" from ucnv_detectUnicodeSignature()\n", 306b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru u_errorName(status)); 307b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return; 308b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 309b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if(encoding!=NULL ){ 310b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru charDataStart += signatureLength; 311b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru rawFileLen -= signatureLength; 312b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 313b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 314b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // 315b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Open a converter to take the file to UTF-16 316b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // 317b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UConverter* conv; 318b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru conv = ucnv_open(encoding, &status); 319b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (U_FAILURE(status)) { 320b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru fprintf(stderr, "ugrep: ICU Error \"%s\" from ucnv_open()\n", u_errorName(status)); 321b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return; 322b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 323b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 324b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // 325b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Convert the file data to UChar. 326b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Preflight first to determine required buffer size. 327b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // 328b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru uint32_t destCap = ucnv_toUChars(conv, 329b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru NULL, // dest, 330b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 0, // destCapacity, 331b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru charDataStart, 332b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru rawFileLen, 333b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru &status); 334b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (status != U_BUFFER_OVERFLOW_ERROR) { 335b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru fprintf(stderr, "ugrep: ucnv_toUChars: ICU Error \"%s\"\n", u_errorName(status)); 336b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return; 337b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru }; 338b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 339b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru status = U_ZERO_ERROR; 340b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ucharBuf = (UChar *)realloc(ucharBuf, (destCap+1) * sizeof(UChar)); 341b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ucnv_toUChars(conv, 342b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ucharBuf, // dest, 343b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru destCap+1, 344b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru charDataStart, 345b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru rawFileLen, 346b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru &status); 347b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (U_FAILURE(status)) { 348b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru fprintf(stderr, "ugrep: ucnv_toUChars: ICU Error \"%s\"\n", u_errorName(status)); 349b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return; 350b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru }; 351b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ucnv_close(conv); 352b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 353b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // 354b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Successful conversion. Set the global size variables so that 355b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // the rest of the processing will proceed for this file. 356b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // 357b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru fileLen = destCap; 358b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 359b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 360b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 361b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 362b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 363b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 364b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//------------------------------------------------------------------------------------------ 365b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// 366b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// nextLine Advance the line index variables, starting at the 367b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// specified position in the input file buffer, by 368b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// scanning forwrd until the next end-of-line. 369b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// 370b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// Need to take into account all of the possible Unicode 371b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// line ending sequences. 372b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// 373b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//------------------------------------------------------------------------------------------ 374b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid nextLine(int startPos) { 375b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (startPos == 0) { 376b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru lineNum = 0; 377b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else { 378b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru lineNum++; 379b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 380b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru lineStart = lineEnd = startPos; 381b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 382b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru for (;;) { 383b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (lineEnd >= fileLen) { 384b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return; 385b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 386b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UChar c = ucharBuf[lineEnd]; 387b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru lineEnd++; 388b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (c == 0x0a || // Line Feed 389b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru c == 0x0c || // Form Feed 390b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru c == 0x0d || // Carriage Return 391b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru c == 0x85 || // Next Line 392b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru c == 0x2028 || // Line Separator 393b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru c == 0x2029) // Paragraph separator 394b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru { 395b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru break; 396b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 397b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 398b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 399b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Check for CR/LF sequence, and advance over the LF if we're in the middle of one. 400b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (lineEnd < fileLen && 401b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ucharBuf[lineEnd-1] == 0x0d && 402b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ucharBuf[lineEnd] == 0x0a) 403b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru { 404b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru lineEnd++; 405b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 406b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 407b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 408b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 409b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//------------------------------------------------------------------------------------------ 410b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// 411b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// printMatch Called when a matching line has been located. 412b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// Print out the line from the file with the match, after 413b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// converting it back to the default code page. 414b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// 415b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//------------------------------------------------------------------------------------------ 416b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid printMatch() { 417b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru char buf[2000]; 418b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UErrorCode status = U_ZERO_ERROR; 419b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 420b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // If we haven't already created a converter for output, do it now. 421b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (outConverter == 0) { 422b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru outConverter = ucnv_open(NULL, &status); 423b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (U_FAILURE(status)) { 424b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru fprintf(stderr, "ugrep: Error opening default converter: \"%s\"\n", 425b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru u_errorName(status)); 426b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru exit(-1); 427b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 428b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru }; 429b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 430b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Convert the line to be printed back to the default 8 bit code page. 431b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // If the line is too long for our buffer, just truncate it. 432b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ucnv_fromUChars(outConverter, 433b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru buf, // destination buffer for conversion 434b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru sizeof(buf), // capacity of destination buffer 435b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru &ucharBuf[lineStart], // Input to conversion 436b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru lineEnd-lineStart, // number of UChars to convert 437b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru &status); 438b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru buf[sizeof(buf)-1] = 0; // Add null for use in case of too long lines. 439b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // The converter null-terminates its output unless 440b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // the buffer completely fills. 441b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 442b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (displayFileName) { 443b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru printf("%s:", fileName); 444b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 445b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (displayLineNum) { 446b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru printf("%d:", lineNum); 447b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 448b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru printf("%s", buf); 449b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 450b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 451