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