intl/icu/source/tools/toolutil/toolutil.cpp

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/intl/icu/source/tools/toolutil/toolutil.cpp	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,351 @@
     1.4 +/*
     1.5 +*******************************************************************************
     1.6 +*
     1.7 +*   Copyright (C) 1999-2013, International Business Machines
     1.8 +*   Corporation and others.  All Rights Reserved.
     1.9 +*
    1.10 +*******************************************************************************
    1.11 +*   file name:  toolutil.c
    1.12 +*   encoding:   US-ASCII
    1.13 +*   tab size:   8 (not used)
    1.14 +*   indentation:4
    1.15 +*
    1.16 +*   created on: 1999nov19
    1.17 +*   created by: Markus W. Scherer
    1.18 +*
    1.19 +*	6/25/08 - Added Cygwin specific code in uprv_mkdir - Brian Rower
    1.20 +*	
    1.21 +*   This file contains utility functions for ICU tools like genccode.
    1.22 +*/
    1.23 +
    1.24 +#if U_PLATFORM == U_PF_MINGW
    1.25 +// *cough* - for struct stat
    1.26 +#ifdef __STRICT_ANSI__
    1.27 +#undef __STRICT_ANSI__
    1.28 +#endif
    1.29 +#endif
    1.30 +
    1.31 +#include <stdio.h>
    1.32 +#include <sys/stat.h>
    1.33 +#include "unicode/utypes.h"
    1.34 +
    1.35 +#ifndef U_TOOLUTIL_IMPLEMENTATION
    1.36 +#error U_TOOLUTIL_IMPLEMENTATION not set - must be set for all ICU source files in common/ - see http://userguide.icu-project.org/howtouseicu
    1.37 +#endif
    1.38 +
    1.39 +#if U_PLATFORM_USES_ONLY_WIN32_API
    1.40 +#   define VC_EXTRALEAN
    1.41 +#   define WIN32_LEAN_AND_MEAN
    1.42 +#   define NOUSER
    1.43 +#   define NOSERVICE
    1.44 +#   define NOIME
    1.45 +#   define NOMCX
    1.46 +#   if U_PLATFORM == U_PF_MINGW
    1.47 +#     define __NO_MINGW_LFS /* gets around missing 'off64_t' */
    1.48 +#   endif
    1.49 +#   include <windows.h>
    1.50 +#   include <direct.h>
    1.51 +#else
    1.52 +#   include <sys/stat.h>
    1.53 +#   include <sys/types.h>
    1.54 +#endif
    1.55 +
    1.56 +/* In MinGW environment, io.h needs to be included for _mkdir() */
    1.57 +#if U_PLATFORM == U_PF_MINGW
    1.58 +#include <io.h>
    1.59 +#endif
    1.60 +
    1.61 +#include <errno.h>
    1.62 +
    1.63 +#include "unicode/errorcode.h"
    1.64 +#include "unicode/putil.h"
    1.65 +#include "cmemory.h"
    1.66 +#include "cstring.h"
    1.67 +#include "toolutil.h"
    1.68 +#include "unicode/ucal.h"
    1.69 +
    1.70 +U_NAMESPACE_BEGIN
    1.71 +
    1.72 +IcuToolErrorCode::~IcuToolErrorCode() {
    1.73 +    // Safe because our handleFailure() does not throw exceptions.
    1.74 +    if(isFailure()) { handleFailure(); }
    1.75 +}
    1.76 +
    1.77 +void IcuToolErrorCode::handleFailure() const {
    1.78 +    fprintf(stderr, "error at %s: %s\n", location, errorName());
    1.79 +    exit(errorCode);
    1.80 +}
    1.81 +
    1.82 +U_NAMESPACE_END
    1.83 +
    1.84 +static int32_t currentYear = -1;
    1.85 +
    1.86 +U_CAPI int32_t U_EXPORT2 getCurrentYear() {
    1.87 +#if !UCONFIG_NO_FORMATTING
    1.88 +    UErrorCode status=U_ZERO_ERROR;    
    1.89 +    UCalendar *cal = NULL;
    1.90 +
    1.91 +    if(currentYear == -1) {
    1.92 +        cal = ucal_open(NULL, -1, NULL, UCAL_TRADITIONAL, &status);
    1.93 +        ucal_setMillis(cal, ucal_getNow(), &status);
    1.94 +        currentYear = ucal_get(cal, UCAL_YEAR, &status);
    1.95 +        ucal_close(cal);
    1.96 +    }
    1.97 +#else
    1.98 +    /* No formatting- no way to set the current year. */
    1.99 +#endif
   1.100 +    return currentYear;
   1.101 +}
   1.102 +
   1.103 +
   1.104 +U_CAPI const char * U_EXPORT2
   1.105 +getLongPathname(const char *pathname) {
   1.106 +#if U_PLATFORM_USES_ONLY_WIN32_API
   1.107 +    /* anticipate problems with "short" pathnames */
   1.108 +    static WIN32_FIND_DATAA info;
   1.109 +    HANDLE file=FindFirstFileA(pathname, &info);
   1.110 +    if(file!=INVALID_HANDLE_VALUE) {
   1.111 +        if(info.cAlternateFileName[0]!=0) {
   1.112 +            /* this file has a short name, get and use the long one */
   1.113 +            const char *basename=findBasename(pathname);
   1.114 +            if(basename!=pathname) {
   1.115 +                /* prepend the long filename with the original path */
   1.116 +                uprv_memmove(info.cFileName+(basename-pathname), info.cFileName, uprv_strlen(info.cFileName)+1);
   1.117 +                uprv_memcpy(info.cFileName, pathname, basename-pathname);
   1.118 +            }
   1.119 +            pathname=info.cFileName;
   1.120 +        }
   1.121 +        FindClose(file);
   1.122 +    }
   1.123 +#endif
   1.124 +    return pathname;
   1.125 +}
   1.126 +
   1.127 +U_CAPI const char * U_EXPORT2
   1.128 +findDirname(const char *path, char *buffer, int32_t bufLen, UErrorCode* status) {
   1.129 +  if(U_FAILURE(*status)) return NULL;
   1.130 +  const char *resultPtr = NULL;
   1.131 +  int32_t resultLen = 0;
   1.132 +
   1.133 +  const char *basename=uprv_strrchr(path, U_FILE_SEP_CHAR);
   1.134 +#if U_FILE_ALT_SEP_CHAR!=U_FILE_SEP_CHAR
   1.135 +  const char *basenameAlt=uprv_strrchr(path, U_FILE_ALT_SEP_CHAR);
   1.136 +  if(basenameAlt && (!basename || basename<basenameAlt)) {
   1.137 +    basename = basenameAlt;
   1.138 +  }
   1.139 +#endif
   1.140 +  if(!basename) {
   1.141 +    /* no basename - return ''. */
   1.142 +    resultPtr = "";
   1.143 +    resultLen = 0;
   1.144 +  } else {
   1.145 +    resultPtr = path;
   1.146 +    resultLen = basename - path;
   1.147 +    if(resultLen<1) {
   1.148 +      resultLen = 1; /* '/' or '/a' -> '/' */
   1.149 +    }
   1.150 +  }
   1.151 +
   1.152 +  if((resultLen+1) <= bufLen) {
   1.153 +    uprv_strncpy(buffer, resultPtr, resultLen);
   1.154 +    buffer[resultLen]=0;
   1.155 +    return buffer;
   1.156 +  } else {
   1.157 +    *status = U_BUFFER_OVERFLOW_ERROR;
   1.158 +    return NULL;
   1.159 +  }
   1.160 +}
   1.161 +
   1.162 +U_CAPI const char * U_EXPORT2
   1.163 +findBasename(const char *filename) {
   1.164 +    const char *basename=uprv_strrchr(filename, U_FILE_SEP_CHAR);
   1.165 +
   1.166 +#if U_FILE_ALT_SEP_CHAR!=U_FILE_SEP_CHAR
   1.167 +    if(basename==NULL) {
   1.168 +        /* Use lenient matching on Windows, which can accept either \ or /
   1.169 +           This is useful for environments like Win32+CygWin which have both.
   1.170 +        */
   1.171 +        basename=uprv_strrchr(filename, U_FILE_ALT_SEP_CHAR);
   1.172 +    }
   1.173 +#endif
   1.174 +
   1.175 +    if(basename!=NULL) {
   1.176 +        return basename+1;
   1.177 +    } else {
   1.178 +        return filename;
   1.179 +    }
   1.180 +}
   1.181 +
   1.182 +U_CAPI void U_EXPORT2
   1.183 +uprv_mkdir(const char *pathname, UErrorCode *status) {
   1.184 +
   1.185 +    int retVal = 0;
   1.186 +#if U_PLATFORM_USES_ONLY_WIN32_API
   1.187 +    retVal = _mkdir(pathname);
   1.188 +#else
   1.189 +    retVal = mkdir(pathname, S_IRWXU | (S_IROTH | S_IXOTH) | (S_IROTH | S_IXOTH));
   1.190 +#endif
   1.191 +    if (retVal && errno != EEXIST) {
   1.192 +#if U_PF_MINGW <= U_PLATFORM && U_PLATFORM <= U_PF_CYGWIN
   1.193 +        /*if using Cygwin and the mkdir says it failed...check if the directory already exists..*/
   1.194 +        /* if it does...don't give the error, if it does not...give the error - Brian Rower - 6/25/08 */
   1.195 +        struct stat st;
   1.196 +
   1.197 +        if(stat(pathname,&st) != 0)
   1.198 +        {
   1.199 +            *status = U_FILE_ACCESS_ERROR;
   1.200 +        }
   1.201 +#else
   1.202 +        *status = U_FILE_ACCESS_ERROR;
   1.203 +#endif
   1.204 +    }
   1.205 +}
   1.206 +
   1.207 +#if !UCONFIG_NO_FILE_IO
   1.208 +U_CAPI UBool U_EXPORT2
   1.209 +uprv_fileExists(const char *file) {
   1.210 +  struct stat stat_buf;
   1.211 +  if (stat(file, &stat_buf) == 0) {
   1.212 +    return TRUE;
   1.213 +  } else {
   1.214 +    return FALSE;
   1.215 +  }
   1.216 +}
   1.217 +#endif
   1.218 +
   1.219 +/*U_CAPI UDate U_EXPORT2
   1.220 +uprv_getModificationDate(const char *pathname, UErrorCode *status)
   1.221 +{
   1.222 +    if(U_FAILURE(*status)) {
   1.223 +        return;
   1.224 +    }
   1.225 +    //  TODO: handle case where stat is not available
   1.226 +    struct stat st;
   1.227 +    
   1.228 +    if(stat(pathname,&st) != 0)
   1.229 +    {
   1.230 +        *status = U_FILE_ACCESS_ERROR;
   1.231 +    } else {
   1.232 +        return st.st_mtime;
   1.233 +    }
   1.234 +}
   1.235 +*/
   1.236 +
   1.237 +/* tool memory helper ------------------------------------------------------- */
   1.238 +
   1.239 +struct UToolMemory {
   1.240 +    char name[64];
   1.241 +    int32_t capacity, maxCapacity, size, idx;
   1.242 +    void *array;
   1.243 +    UAlignedMemory staticArray[1];
   1.244 +};
   1.245 +
   1.246 +U_CAPI UToolMemory * U_EXPORT2
   1.247 +utm_open(const char *name, int32_t initialCapacity, int32_t maxCapacity, int32_t size) {
   1.248 +    UToolMemory *mem;
   1.249 +
   1.250 +    if(maxCapacity<initialCapacity) {
   1.251 +        maxCapacity=initialCapacity;
   1.252 +    }
   1.253 +
   1.254 +    mem=(UToolMemory *)uprv_malloc(sizeof(UToolMemory)+initialCapacity*size);
   1.255 +    if(mem==NULL) {
   1.256 +        fprintf(stderr, "error: %s - out of memory\n", name);
   1.257 +        exit(U_MEMORY_ALLOCATION_ERROR);
   1.258 +    }
   1.259 +    mem->array=mem->staticArray;
   1.260 +
   1.261 +    uprv_strcpy(mem->name, name);
   1.262 +    mem->capacity=initialCapacity;
   1.263 +    mem->maxCapacity=maxCapacity;
   1.264 +    mem->size=size;
   1.265 +    mem->idx=0;
   1.266 +    return mem;
   1.267 +}
   1.268 +
   1.269 +U_CAPI void U_EXPORT2
   1.270 +utm_close(UToolMemory *mem) {
   1.271 +    if(mem!=NULL) {
   1.272 +        if(mem->array!=mem->staticArray) {
   1.273 +            uprv_free(mem->array);
   1.274 +        }
   1.275 +        uprv_free(mem);
   1.276 +    }
   1.277 +}
   1.278 +
   1.279 +
   1.280 +U_CAPI void * U_EXPORT2
   1.281 +utm_getStart(UToolMemory *mem) {
   1.282 +    return (char *)mem->array;
   1.283 +}
   1.284 +
   1.285 +U_CAPI int32_t U_EXPORT2
   1.286 +utm_countItems(UToolMemory *mem) {
   1.287 +    return mem->idx;
   1.288 +}
   1.289 +
   1.290 +
   1.291 +static UBool
   1.292 +utm_hasCapacity(UToolMemory *mem, int32_t capacity) {
   1.293 +    if(mem->capacity<capacity) {
   1.294 +        int32_t newCapacity;
   1.295 +
   1.296 +        if(mem->maxCapacity<capacity) {
   1.297 +            fprintf(stderr, "error: %s - trying to use more than maxCapacity=%ld units\n",
   1.298 +                    mem->name, (long)mem->maxCapacity);
   1.299 +            exit(U_MEMORY_ALLOCATION_ERROR);
   1.300 +        }
   1.301 +
   1.302 +        /* try to allocate a larger array */
   1.303 +        if(capacity>=2*mem->capacity) {
   1.304 +            newCapacity=capacity;
   1.305 +        } else if(mem->capacity<=mem->maxCapacity/3) {
   1.306 +            newCapacity=2*mem->capacity;
   1.307 +        } else {
   1.308 +            newCapacity=mem->maxCapacity;
   1.309 +        }
   1.310 +
   1.311 +        if(mem->array==mem->staticArray) {
   1.312 +            mem->array=uprv_malloc(newCapacity*mem->size);
   1.313 +            if(mem->array!=NULL) {
   1.314 +                uprv_memcpy(mem->array, mem->staticArray, mem->idx*mem->size);
   1.315 +            }
   1.316 +        } else {
   1.317 +            mem->array=uprv_realloc(mem->array, newCapacity*mem->size);
   1.318 +        }
   1.319 +
   1.320 +        if(mem->array==NULL) {
   1.321 +            fprintf(stderr, "error: %s - out of memory\n", mem->name);
   1.322 +            exit(U_MEMORY_ALLOCATION_ERROR);
   1.323 +        }
   1.324 +        mem->capacity=newCapacity;
   1.325 +    }
   1.326 +
   1.327 +    return TRUE;
   1.328 +}
   1.329 +
   1.330 +U_CAPI void * U_EXPORT2
   1.331 +utm_alloc(UToolMemory *mem) {
   1.332 +    char *p=NULL;
   1.333 +    int32_t oldIndex=mem->idx;
   1.334 +    int32_t newIndex=oldIndex+1;
   1.335 +    if(utm_hasCapacity(mem, newIndex)) {
   1.336 +        p=(char *)mem->array+oldIndex*mem->size;
   1.337 +        mem->idx=newIndex;
   1.338 +        uprv_memset(p, 0, mem->size);
   1.339 +    }
   1.340 +    return p;
   1.341 +}
   1.342 +
   1.343 +U_CAPI void * U_EXPORT2
   1.344 +utm_allocN(UToolMemory *mem, int32_t n) {
   1.345 +    char *p=NULL;
   1.346 +    int32_t oldIndex=mem->idx;
   1.347 +    int32_t newIndex=oldIndex+n;
   1.348 +    if(utm_hasCapacity(mem, newIndex)) {
   1.349 +        p=(char *)mem->array+oldIndex*mem->size;
   1.350 +        mem->idx=newIndex;
   1.351 +        uprv_memset(p, 0, n*mem->size);
   1.352 +    }
   1.353 +    return p;
   1.354 +}

mercurial