]> git.saurik.com Git - apple/icu.git/blob - icuSources/tools/toolutil/toolutil.cpp
ICU-511.25.tar.gz
[apple/icu.git] / icuSources / tools / toolutil / toolutil.cpp
1 /*
2 *******************************************************************************
3 *
4 * Copyright (C) 1999-2011, International Business Machines
5 * Corporation and others. All Rights Reserved.
6 *
7 *******************************************************************************
8 * file name: toolutil.c
9 * encoding: US-ASCII
10 * tab size: 8 (not used)
11 * indentation:4
12 *
13 * created on: 1999nov19
14 * created by: Markus W. Scherer
15 *
16 * 6/25/08 - Added Cygwin specific code in uprv_mkdir - Brian Rower
17 *
18 * This file contains utility functions for ICU tools like genccode.
19 */
20
21 #include <stdio.h>
22 #include <sys/stat.h>
23 #include "unicode/utypes.h"
24
25 #ifndef U_TOOLUTIL_IMPLEMENTATION
26 #error U_TOOLUTIL_IMPLEMENTATION not set - must be set for all ICU source files in common/ - see http://userguide.icu-project.org/howtouseicu
27 #endif
28
29 #if U_PLATFORM_USES_ONLY_WIN32_API
30 # define VC_EXTRALEAN
31 # define WIN32_LEAN_AND_MEAN
32 # define NOUSER
33 # define NOSERVICE
34 # define NOIME
35 # define NOMCX
36 # include <windows.h>
37 # include <direct.h>
38 #else
39 # include <sys/stat.h>
40 # include <sys/types.h>
41 #endif
42
43 /* In MinGW environment, io.h needs to be included for _mkdir() */
44 #if U_PLATFORM == U_PF_MINGW
45 #include <io.h>
46 #endif
47
48 #include <errno.h>
49
50 #include "unicode/errorcode.h"
51 #include "unicode/putil.h"
52 #include "cmemory.h"
53 #include "cstring.h"
54 #include "toolutil.h"
55 #include "unicode/ucal.h"
56
57 U_NAMESPACE_BEGIN
58
59 IcuToolErrorCode::~IcuToolErrorCode() {
60 // Safe because our handleFailure() does not throw exceptions.
61 if(isFailure()) { handleFailure(); }
62 }
63
64 void IcuToolErrorCode::handleFailure() const {
65 fprintf(stderr, "error at %s: %s\n", location, errorName());
66 exit(errorCode);
67 }
68
69 U_NAMESPACE_END
70
71 static int32_t currentYear = -1;
72
73 U_CAPI int32_t U_EXPORT2 getCurrentYear() {
74 #if !UCONFIG_NO_FORMATTING
75 UErrorCode status=U_ZERO_ERROR;
76 UCalendar *cal = NULL;
77
78 if(currentYear == -1) {
79 cal = ucal_open(NULL, -1, NULL, UCAL_TRADITIONAL, &status);
80 ucal_setMillis(cal, ucal_getNow(), &status);
81 currentYear = ucal_get(cal, UCAL_YEAR, &status);
82 ucal_close(cal);
83 }
84 #else
85 /* No formatting- no way to set the current year. */
86 #endif
87 return currentYear;
88 }
89
90
91 U_CAPI const char * U_EXPORT2
92 getLongPathname(const char *pathname) {
93 #if U_PLATFORM_USES_ONLY_WIN32_API
94 /* anticipate problems with "short" pathnames */
95 static WIN32_FIND_DATAA info;
96 HANDLE file=FindFirstFileA(pathname, &info);
97 if(file!=INVALID_HANDLE_VALUE) {
98 if(info.cAlternateFileName[0]!=0) {
99 /* this file has a short name, get and use the long one */
100 const char *basename=findBasename(pathname);
101 if(basename!=pathname) {
102 /* prepend the long filename with the original path */
103 uprv_memmove(info.cFileName+(basename-pathname), info.cFileName, uprv_strlen(info.cFileName)+1);
104 uprv_memcpy(info.cFileName, pathname, basename-pathname);
105 }
106 pathname=info.cFileName;
107 }
108 FindClose(file);
109 }
110 #endif
111 return pathname;
112 }
113
114 U_CAPI const char * U_EXPORT2
115 findDirname(const char *path, char *buffer, int32_t bufLen, UErrorCode* status) {
116 if(U_FAILURE(*status)) return NULL;
117 const char *resultPtr = NULL;
118 int32_t resultLen = 0;
119
120 const char *basename=uprv_strrchr(path, U_FILE_SEP_CHAR);
121 #if U_FILE_ALT_SEP_CHAR!=U_FILE_SEP_CHAR
122 const char *basenameAlt=uprv_strrchr(path, U_FILE_ALT_SEP_CHAR);
123 if(basenameAlt && (!basename || basename<basenameAlt)) {
124 basename = basenameAlt;
125 }
126 #endif
127 if(!basename) {
128 /* no basename - return ''. */
129 resultPtr = "";
130 resultLen = 0;
131 } else {
132 resultPtr = path;
133 resultLen = basename - path;
134 if(resultLen<1) {
135 resultLen = 1; /* '/' or '/a' -> '/' */
136 }
137 }
138
139 if((resultLen+1) <= bufLen) {
140 uprv_strncpy(buffer, resultPtr, resultLen);
141 buffer[resultLen]=0;
142 return buffer;
143 } else {
144 *status = U_BUFFER_OVERFLOW_ERROR;
145 return NULL;
146 }
147 }
148
149 U_CAPI const char * U_EXPORT2
150 findBasename(const char *filename) {
151 const char *basename=uprv_strrchr(filename, U_FILE_SEP_CHAR);
152
153 #if U_FILE_ALT_SEP_CHAR!=U_FILE_SEP_CHAR
154 if(basename==NULL) {
155 /* Use lenient matching on Windows, which can accept either \ or /
156 This is useful for environments like Win32+CygWin which have both.
157 */
158 basename=uprv_strrchr(filename, U_FILE_ALT_SEP_CHAR);
159 }
160 #endif
161
162 if(basename!=NULL) {
163 return basename+1;
164 } else {
165 return filename;
166 }
167 }
168
169 U_CAPI void U_EXPORT2
170 uprv_mkdir(const char *pathname, UErrorCode *status) {
171
172 int retVal = 0;
173 #if U_PLATFORM_USES_ONLY_WIN32_API
174 retVal = _mkdir(pathname);
175 #else
176 retVal = mkdir(pathname, S_IRWXU | (S_IROTH | S_IXOTH) | (S_IROTH | S_IXOTH));
177 #endif
178 if (retVal && errno != EEXIST) {
179 #if U_PF_MINGW <= U_PLATFORM && U_PLATFORM <= U_PF_CYGWIN
180 /*if using Cygwin and the mkdir says it failed...check if the directory already exists..*/
181 /* if it does...don't give the error, if it does not...give the error - Brian Rower - 6/25/08 */
182 struct stat st;
183
184 if(stat(pathname,&st) != 0)
185 {
186 *status = U_FILE_ACCESS_ERROR;
187 }
188 #else
189 *status = U_FILE_ACCESS_ERROR;
190 #endif
191 }
192 }
193
194 /*U_CAPI UDate U_EXPORT2
195 uprv_getModificationDate(const char *pathname, UErrorCode *status)
196 {
197 if(U_FAILURE(*status)) {
198 return;
199 }
200 // TODO: handle case where stat is not available
201 struct stat st;
202
203 if(stat(pathname,&st) != 0)
204 {
205 *status = U_FILE_ACCESS_ERROR;
206 } else {
207 return st.st_mtime;
208 }
209 }
210 */
211
212 /* tool memory helper ------------------------------------------------------- */
213
214 struct UToolMemory {
215 char name[64];
216 int32_t capacity, maxCapacity, size, idx;
217 void *array;
218 UAlignedMemory staticArray[1];
219 };
220
221 U_CAPI UToolMemory * U_EXPORT2
222 utm_open(const char *name, int32_t initialCapacity, int32_t maxCapacity, int32_t size) {
223 UToolMemory *mem;
224
225 if(maxCapacity<initialCapacity) {
226 maxCapacity=initialCapacity;
227 }
228
229 mem=(UToolMemory *)uprv_malloc(sizeof(UToolMemory)+initialCapacity*size);
230 if(mem==NULL) {
231 fprintf(stderr, "error: %s - out of memory\n", name);
232 exit(U_MEMORY_ALLOCATION_ERROR);
233 }
234 mem->array=mem->staticArray;
235
236 uprv_strcpy(mem->name, name);
237 mem->capacity=initialCapacity;
238 mem->maxCapacity=maxCapacity;
239 mem->size=size;
240 mem->idx=0;
241 return mem;
242 }
243
244 U_CAPI void U_EXPORT2
245 utm_close(UToolMemory *mem) {
246 if(mem!=NULL) {
247 if(mem->array!=mem->staticArray) {
248 uprv_free(mem->array);
249 }
250 uprv_free(mem);
251 }
252 }
253
254
255 U_CAPI void * U_EXPORT2
256 utm_getStart(UToolMemory *mem) {
257 return (char *)mem->array;
258 }
259
260 U_CAPI int32_t U_EXPORT2
261 utm_countItems(UToolMemory *mem) {
262 return mem->idx;
263 }
264
265
266 static UBool
267 utm_hasCapacity(UToolMemory *mem, int32_t capacity) {
268 if(mem->capacity<capacity) {
269 int32_t newCapacity;
270
271 if(mem->maxCapacity<capacity) {
272 fprintf(stderr, "error: %s - trying to use more than maxCapacity=%ld units\n",
273 mem->name, (long)mem->maxCapacity);
274 exit(U_MEMORY_ALLOCATION_ERROR);
275 }
276
277 /* try to allocate a larger array */
278 if(capacity>=2*mem->capacity) {
279 newCapacity=capacity;
280 } else if(mem->capacity<=mem->maxCapacity/3) {
281 newCapacity=2*mem->capacity;
282 } else {
283 newCapacity=mem->maxCapacity;
284 }
285
286 if(mem->array==mem->staticArray) {
287 mem->array=uprv_malloc(newCapacity*mem->size);
288 if(mem->array!=NULL) {
289 uprv_memcpy(mem->array, mem->staticArray, mem->idx*mem->size);
290 }
291 } else {
292 mem->array=uprv_realloc(mem->array, newCapacity*mem->size);
293 }
294
295 if(mem->array==NULL) {
296 fprintf(stderr, "error: %s - out of memory\n", mem->name);
297 exit(U_MEMORY_ALLOCATION_ERROR);
298 }
299 mem->capacity=newCapacity;
300 }
301
302 return TRUE;
303 }
304
305 U_CAPI void * U_EXPORT2
306 utm_alloc(UToolMemory *mem) {
307 char *p=NULL;
308 int32_t oldIndex=mem->idx;
309 int32_t newIndex=oldIndex+1;
310 if(utm_hasCapacity(mem, newIndex)) {
311 p=(char *)mem->array+oldIndex*mem->size;
312 mem->idx=newIndex;
313 uprv_memset(p, 0, mem->size);
314 }
315 return p;
316 }
317
318 U_CAPI void * U_EXPORT2
319 utm_allocN(UToolMemory *mem, int32_t n) {
320 char *p=NULL;
321 int32_t oldIndex=mem->idx;
322 int32_t newIndex=oldIndex+n;
323 if(utm_hasCapacity(mem, newIndex)) {
324 p=(char *)mem->array+oldIndex*mem->size;
325 mem->idx=newIndex;
326 uprv_memset(p, 0, n*mem->size);
327 }
328 return p;
329 }