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

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/intl/icu/source/tools/toolutil/udbgutil.cpp	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,777 @@
     1.4 +/********************************************************************
     1.5 + * COPYRIGHT:
     1.6 + * Copyright (c) 2007-2013, International Business Machines Corporation and
     1.7 + * others. All Rights Reserved.
     1.8 + ********************************************************************/
     1.9 +
    1.10 +#include "udbgutil.h"
    1.11 +#include <string.h>
    1.12 +#include "ustr_imp.h"
    1.13 +#include "cstring.h"
    1.14 +#include "putilimp.h"
    1.15 +#include "unicode/ulocdata.h"
    1.16 +#include "unicode/ucnv.h"
    1.17 +#include "unicode/unistr.h"
    1.18 +
    1.19 +/*
    1.20 +To add a new enum type
    1.21 +      (For example: UShoeSize  with values USHOE_WIDE=0, USHOE_REGULAR, USHOE_NARROW, USHOE_COUNT)
    1.22 +
    1.23 +    1. udbgutil.h:  add  UDBG_UShoeSize to the UDebugEnumType enum before UDBG_ENUM_COUNT
    1.24 +      ( The subsequent steps involve this file, udbgutil.cpp )
    1.25 +    2. Find the marker "Add new enum types above this line"
    1.26 +    3. Before that marker, add a #include of any header file you need.
    1.27 +    4. Each enum type has three things in this section:  a #define, a count_, and an array of Fields.
    1.28 +       It may help to copy and paste a previous definition.
    1.29 +    5. In the case of the USHOE_... strings above, "USHOE_" is common to all values- six characters
    1.30 +         " #define LEN_USHOE 6 "
    1.31 +       6 characters will strip off "USHOE_" leaving enum values of WIDE, REGULAR, and NARROW.
    1.32 +    6. Define the 'count_' variable, with the number of enum values. If the enum has a _MAX or _COUNT value,
    1.33 +        that can be helpful for automatically defining the count. Otherwise define it manually.
    1.34 +        " static const int32_t count_UShoeSize = USHOE_COUNT; "
    1.35 +    7. Define the field names, in order.
    1.36 +        " static const Field names_UShoeSize[] =  {
    1.37 +        "  FIELD_NAME_STR( LEN_USHOE, USHOE_WIDE ),
    1.38 +        "  FIELD_NAME_STR( LEN_USHOE, USHOE_REGULAR ),
    1.39 +        "  FIELD_NAME_STR( LEN_USHOE, USHOE_NARROW ),
    1.40 +        " };
    1.41 +      ( The following command  was usedfor converting ucol.h into partially correct entities )
    1.42 +      grep "^[  ]*UCOL" < unicode/ucol.h  |
    1.43 +         sed -e 's%^[  ]*\([A-Z]*\)_\([A-Z_]*\).*%   FIELD_NAME_STR( LEN_\1, \1_\2 ),%g'
    1.44 +    8. Now, a bit farther down, add the name of the enum itself to the end of names_UDebugEnumType
    1.45 +          ( UDebugEnumType is an enum, too!)
    1.46 +        names_UDebugEnumType[] { ...
    1.47 +            " FIELD_NAME_STR( LEN_UDBG, UDBG_UShoeSize ),   "
    1.48 +    9. Find the function _udbg_enumCount  and add the count macro:
    1.49 +            " COUNT_CASE(UShoeSize)
    1.50 +   10. Find the function _udbg_enumFields  and add the field macro:
    1.51 +            " FIELD_CASE(UShoeSize)
    1.52 +   11. verify that your test code, and Java data generation, works properly.
    1.53 +*/
    1.54 +
    1.55 +/**
    1.56 + * Structure representing an enum value
    1.57 + */
    1.58 +struct Field {
    1.59 +    int32_t prefix;   /**< how many characters to remove in the prefix - i.e. UCHAR_ = 5 */
    1.60 +	const char *str;  /**< The actual string value */
    1.61 +	int32_t num;      /**< The numeric value */
    1.62 +};
    1.63 +
    1.64 +/**
    1.65 + * Calculate the size of an array.
    1.66 + */
    1.67 +#define DBG_ARRAY_COUNT(x) (sizeof(x)/sizeof(x[0]))
    1.68 +
    1.69 +/**
    1.70 + * Define another field name. Used in an array of Field s
    1.71 + * @param y the common prefix length (i.e. 6 for "USHOE_" )
    1.72 + * @param x the actual enum value - it will be copied in both string and symbolic form.
    1.73 + * @see Field
    1.74 + */
    1.75 +#define FIELD_NAME_STR(y,x)  { y, #x, x }
    1.76 +
    1.77 +
    1.78 +// TODO: Currently, this whole functionality goes away with UCONFIG_NO_FORMATTING. Should be split up.
    1.79 +#if !UCONFIG_NO_FORMATTING
    1.80 +
    1.81 +// Calendar
    1.82 +#include "unicode/ucal.h"
    1.83 +
    1.84 +// 'UCAL_' = 5
    1.85 +#define LEN_UCAL 5 /* UCAL_ */
    1.86 +static const int32_t count_UCalendarDateFields = UCAL_FIELD_COUNT;
    1.87 +static const Field names_UCalendarDateFields[] =
    1.88 +{
    1.89 +    FIELD_NAME_STR( LEN_UCAL, UCAL_ERA ),
    1.90 +    FIELD_NAME_STR( LEN_UCAL, UCAL_YEAR ),
    1.91 +    FIELD_NAME_STR( LEN_UCAL, UCAL_MONTH ),
    1.92 +    FIELD_NAME_STR( LEN_UCAL, UCAL_WEEK_OF_YEAR ),
    1.93 +    FIELD_NAME_STR( LEN_UCAL, UCAL_WEEK_OF_MONTH ),
    1.94 +    FIELD_NAME_STR( LEN_UCAL, UCAL_DATE ),
    1.95 +    FIELD_NAME_STR( LEN_UCAL, UCAL_DAY_OF_YEAR ),
    1.96 +    FIELD_NAME_STR( LEN_UCAL, UCAL_DAY_OF_WEEK ),
    1.97 +    FIELD_NAME_STR( LEN_UCAL, UCAL_DAY_OF_WEEK_IN_MONTH ),
    1.98 +    FIELD_NAME_STR( LEN_UCAL, UCAL_AM_PM ),
    1.99 +    FIELD_NAME_STR( LEN_UCAL, UCAL_HOUR ),
   1.100 +    FIELD_NAME_STR( LEN_UCAL, UCAL_HOUR_OF_DAY ),
   1.101 +    FIELD_NAME_STR( LEN_UCAL, UCAL_MINUTE ),
   1.102 +    FIELD_NAME_STR( LEN_UCAL, UCAL_SECOND ),
   1.103 +    FIELD_NAME_STR( LEN_UCAL, UCAL_MILLISECOND ),
   1.104 +    FIELD_NAME_STR( LEN_UCAL, UCAL_ZONE_OFFSET ),
   1.105 +    FIELD_NAME_STR( LEN_UCAL, UCAL_DST_OFFSET ),
   1.106 +    FIELD_NAME_STR( LEN_UCAL, UCAL_YEAR_WOY ),
   1.107 +    FIELD_NAME_STR( LEN_UCAL, UCAL_DOW_LOCAL ),
   1.108 +    FIELD_NAME_STR( LEN_UCAL, UCAL_EXTENDED_YEAR ),
   1.109 +    FIELD_NAME_STR( LEN_UCAL, UCAL_JULIAN_DAY ),
   1.110 +    FIELD_NAME_STR( LEN_UCAL, UCAL_MILLISECONDS_IN_DAY ),
   1.111 +    FIELD_NAME_STR( LEN_UCAL, UCAL_IS_LEAP_MONTH ),
   1.112 +};
   1.113 +
   1.114 +
   1.115 +static const int32_t count_UCalendarMonths = UCAL_UNDECIMBER+1;
   1.116 +static const Field names_UCalendarMonths[] =
   1.117 +{
   1.118 +  FIELD_NAME_STR( LEN_UCAL, UCAL_JANUARY ),
   1.119 +  FIELD_NAME_STR( LEN_UCAL, UCAL_FEBRUARY ),
   1.120 +  FIELD_NAME_STR( LEN_UCAL, UCAL_MARCH ),
   1.121 +  FIELD_NAME_STR( LEN_UCAL, UCAL_APRIL ),
   1.122 +  FIELD_NAME_STR( LEN_UCAL, UCAL_MAY ),
   1.123 +  FIELD_NAME_STR( LEN_UCAL, UCAL_JUNE ),
   1.124 +  FIELD_NAME_STR( LEN_UCAL, UCAL_JULY ),
   1.125 +  FIELD_NAME_STR( LEN_UCAL, UCAL_AUGUST ),
   1.126 +  FIELD_NAME_STR( LEN_UCAL, UCAL_SEPTEMBER ),
   1.127 +  FIELD_NAME_STR( LEN_UCAL, UCAL_OCTOBER ),
   1.128 +  FIELD_NAME_STR( LEN_UCAL, UCAL_NOVEMBER ),
   1.129 +  FIELD_NAME_STR( LEN_UCAL, UCAL_DECEMBER ),
   1.130 +  FIELD_NAME_STR( LEN_UCAL, UCAL_UNDECIMBER)
   1.131 +};
   1.132 +
   1.133 +#include "unicode/udat.h"
   1.134 +
   1.135 +#define LEN_UDAT 5 /* "UDAT_" */
   1.136 +static const int32_t count_UDateFormatStyle = UDAT_SHORT+1;
   1.137 +static const Field names_UDateFormatStyle[] =
   1.138 +{
   1.139 +        FIELD_NAME_STR( LEN_UDAT, UDAT_FULL ),
   1.140 +        FIELD_NAME_STR( LEN_UDAT, UDAT_LONG ),
   1.141 +        FIELD_NAME_STR( LEN_UDAT, UDAT_MEDIUM ),
   1.142 +        FIELD_NAME_STR( LEN_UDAT, UDAT_SHORT ),
   1.143 +        /* end regular */
   1.144 +    /*
   1.145 +     *  negative enums.. leave out for now.
   1.146 +        FIELD_NAME_STR( LEN_UDAT, UDAT_NONE ),
   1.147 +        FIELD_NAME_STR( LEN_UDAT, UDAT_PATTERN ),
   1.148 +     */
   1.149 +};
   1.150 +
   1.151 +#endif
   1.152 +
   1.153 +#include "unicode/uloc.h"
   1.154 +
   1.155 +#define LEN_UAR 12 /* "ULOC_ACCEPT_" */
   1.156 +static const int32_t count_UAcceptResult = 3;
   1.157 +static const Field names_UAcceptResult[] =
   1.158 +{
   1.159 +        FIELD_NAME_STR( LEN_UAR, ULOC_ACCEPT_FAILED ),
   1.160 +        FIELD_NAME_STR( LEN_UAR, ULOC_ACCEPT_VALID ),
   1.161 +        FIELD_NAME_STR( LEN_UAR, ULOC_ACCEPT_FALLBACK ),
   1.162 +};
   1.163 +
   1.164 +#if !UCONFIG_NO_COLLATION
   1.165 +#include "unicode/ucol.h"
   1.166 +#define LEN_UCOL 5 /* UCOL_ */
   1.167 +static const int32_t count_UColAttributeValue = UCOL_ATTRIBUTE_VALUE_COUNT;
   1.168 +static const Field names_UColAttributeValue[]  = {
   1.169 +   FIELD_NAME_STR( LEN_UCOL, UCOL_PRIMARY ),
   1.170 +   FIELD_NAME_STR( LEN_UCOL, UCOL_SECONDARY ),
   1.171 +   FIELD_NAME_STR( LEN_UCOL, UCOL_TERTIARY ),
   1.172 +//   FIELD_NAME_STR( LEN_UCOL, UCOL_CE_STRENGTH_LIMIT ),
   1.173 +   FIELD_NAME_STR( LEN_UCOL, UCOL_QUATERNARY ),
   1.174 +   // gap
   1.175 +   FIELD_NAME_STR( LEN_UCOL, UCOL_IDENTICAL ),
   1.176 +//   FIELD_NAME_STR( LEN_UCOL, UCOL_STRENGTH_LIMIT ),
   1.177 +   FIELD_NAME_STR( LEN_UCOL, UCOL_OFF ),
   1.178 +   FIELD_NAME_STR( LEN_UCOL, UCOL_ON ),
   1.179 +   // gap
   1.180 +   FIELD_NAME_STR( LEN_UCOL, UCOL_SHIFTED ),
   1.181 +   FIELD_NAME_STR( LEN_UCOL, UCOL_NON_IGNORABLE ),
   1.182 +   // gap
   1.183 +   FIELD_NAME_STR( LEN_UCOL, UCOL_LOWER_FIRST ),
   1.184 +   FIELD_NAME_STR( LEN_UCOL, UCOL_UPPER_FIRST ),
   1.185 +};
   1.186 +
   1.187 +#endif
   1.188 +
   1.189 +
   1.190 +#include "unicode/icuplug.h"
   1.191 +
   1.192 +#define LEN_UPLUG_REASON 13 /* UPLUG_REASON_ */
   1.193 +static const int32_t count_UPlugReason = UPLUG_REASON_COUNT;
   1.194 +static const Field names_UPlugReason[]  = {
   1.195 +   FIELD_NAME_STR( LEN_UPLUG_REASON, UPLUG_REASON_QUERY ),
   1.196 +   FIELD_NAME_STR( LEN_UPLUG_REASON, UPLUG_REASON_LOAD ),
   1.197 +   FIELD_NAME_STR( LEN_UPLUG_REASON, UPLUG_REASON_UNLOAD ),
   1.198 +};
   1.199 +
   1.200 +#define LEN_UPLUG_LEVEL 12 /* UPLUG_LEVEL_ */
   1.201 +static const int32_t count_UPlugLevel = UPLUG_LEVEL_COUNT;
   1.202 +static const Field names_UPlugLevel[]  = {
   1.203 +   FIELD_NAME_STR( LEN_UPLUG_LEVEL, UPLUG_LEVEL_INVALID ),
   1.204 +   FIELD_NAME_STR( LEN_UPLUG_LEVEL, UPLUG_LEVEL_UNKNOWN ),
   1.205 +   FIELD_NAME_STR( LEN_UPLUG_LEVEL, UPLUG_LEVEL_LOW ),
   1.206 +   FIELD_NAME_STR( LEN_UPLUG_LEVEL, UPLUG_LEVEL_HIGH ),
   1.207 +};
   1.208 +
   1.209 +#define LEN_UDBG 5 /* "UDBG_" */
   1.210 +static const int32_t count_UDebugEnumType = UDBG_ENUM_COUNT;
   1.211 +static const Field names_UDebugEnumType[] =
   1.212 +{
   1.213 +    FIELD_NAME_STR( LEN_UDBG, UDBG_UDebugEnumType ),
   1.214 +#if !UCONFIG_NO_FORMATTING
   1.215 +    FIELD_NAME_STR( LEN_UDBG, UDBG_UCalendarDateFields ),
   1.216 +    FIELD_NAME_STR( LEN_UDBG, UDBG_UCalendarMonths ),
   1.217 +    FIELD_NAME_STR( LEN_UDBG, UDBG_UDateFormatStyle ),
   1.218 +#endif
   1.219 +    FIELD_NAME_STR( LEN_UDBG, UDBG_UPlugReason ),
   1.220 +    FIELD_NAME_STR( LEN_UDBG, UDBG_UPlugLevel ),
   1.221 +    FIELD_NAME_STR( LEN_UDBG, UDBG_UAcceptResult ),
   1.222 +#if !UCONFIG_NO_COLLATION
   1.223 +    FIELD_NAME_STR( LEN_UDBG, UDBG_UColAttributeValue ),
   1.224 +#endif
   1.225 +};
   1.226 +
   1.227 +
   1.228 +// --- Add new enum types above this line ---
   1.229 +
   1.230 +#define COUNT_CASE(x)  case UDBG_##x: return (actual?count_##x:DBG_ARRAY_COUNT(names_##x));
   1.231 +#define COUNT_FAIL_CASE(x) case UDBG_##x: return -1;
   1.232 +
   1.233 +#define FIELD_CASE(x)  case UDBG_##x: return names_##x;
   1.234 +#define FIELD_FAIL_CASE(x) case UDBG_##x: return NULL;
   1.235 +
   1.236 +// low level
   1.237 +
   1.238 +/**
   1.239 + * @param type type of item
   1.240 + * @param actual TRUE: for the actual enum's type (UCAL_FIELD_COUNT, etc), or FALSE for the string count
   1.241 + */
   1.242 +static int32_t _udbg_enumCount(UDebugEnumType type, UBool actual) {
   1.243 +	switch(type) {
   1.244 +		COUNT_CASE(UDebugEnumType)
   1.245 +#if !UCONFIG_NO_FORMATTING
   1.246 +		COUNT_CASE(UCalendarDateFields)
   1.247 +		COUNT_CASE(UCalendarMonths)
   1.248 +		COUNT_CASE(UDateFormatStyle)
   1.249 +#endif
   1.250 +        COUNT_CASE(UPlugReason)
   1.251 +        COUNT_CASE(UPlugLevel)
   1.252 +        COUNT_CASE(UAcceptResult)
   1.253 +#if !UCONFIG_NO_COLLATION
   1.254 +        COUNT_CASE(UColAttributeValue)
   1.255 +#endif
   1.256 +		// COUNT_FAIL_CASE(UNonExistentEnum)
   1.257 +	default:
   1.258 +		return -1;
   1.259 +	}
   1.260 +}
   1.261 +
   1.262 +static const Field* _udbg_enumFields(UDebugEnumType type) {
   1.263 +	switch(type) {
   1.264 +		FIELD_CASE(UDebugEnumType)
   1.265 +#if !UCONFIG_NO_FORMATTING
   1.266 +		FIELD_CASE(UCalendarDateFields)
   1.267 +		FIELD_CASE(UCalendarMonths)
   1.268 +		FIELD_CASE(UDateFormatStyle)
   1.269 +#endif
   1.270 +        FIELD_CASE(UPlugReason)
   1.271 +        FIELD_CASE(UPlugLevel)
   1.272 +        FIELD_CASE(UAcceptResult)
   1.273 +		// FIELD_FAIL_CASE(UNonExistentEnum)
   1.274 +#if !UCONFIG_NO_COLLATION
   1.275 +        FIELD_CASE(UColAttributeValue)
   1.276 +#endif
   1.277 +	default:
   1.278 +		return NULL;
   1.279 +	}
   1.280 +}
   1.281 +
   1.282 +// implementation
   1.283 +
   1.284 +int32_t  udbg_enumCount(UDebugEnumType type) {
   1.285 +	return _udbg_enumCount(type, FALSE);
   1.286 +}
   1.287 +
   1.288 +int32_t  udbg_enumExpectedCount(UDebugEnumType type) {
   1.289 +	return _udbg_enumCount(type, TRUE);
   1.290 +}
   1.291 +
   1.292 +const char *  udbg_enumName(UDebugEnumType type, int32_t field) {
   1.293 +	if(field<0 ||
   1.294 +				field>=_udbg_enumCount(type,FALSE)) { // also will catch unsupported items
   1.295 +		return NULL;
   1.296 +	} else {
   1.297 +		const Field *fields = _udbg_enumFields(type);
   1.298 +		if(fields == NULL) {
   1.299 +			return NULL;
   1.300 +		} else {
   1.301 +			return fields[field].str + fields[field].prefix;
   1.302 +		}
   1.303 +	}
   1.304 +}
   1.305 +
   1.306 +int32_t  udbg_enumArrayValue(UDebugEnumType type, int32_t field) {
   1.307 +	if(field<0 ||
   1.308 +				field>=_udbg_enumCount(type,FALSE)) { // also will catch unsupported items
   1.309 +		return -1;
   1.310 +	} else {
   1.311 +		const Field *fields = _udbg_enumFields(type);
   1.312 +		if(fields == NULL) {
   1.313 +			return -1;
   1.314 +		} else {
   1.315 +			return fields[field].num;
   1.316 +		}
   1.317 +	}
   1.318 +}
   1.319 +
   1.320 +int32_t udbg_enumByName(UDebugEnumType type, const char *value) {
   1.321 +    if(type<0||type>=_udbg_enumCount(UDBG_UDebugEnumType, TRUE)) {
   1.322 +        return -1; // type out of range
   1.323 +    }
   1.324 +	const Field *fields = _udbg_enumFields(type);
   1.325 +    for(int32_t field = 0;field<_udbg_enumCount(type, FALSE);field++) {
   1.326 +        if(!strcmp(value, fields[field].str + fields[field].prefix)) {
   1.327 +            return fields[field].num;
   1.328 +        }
   1.329 +    }
   1.330 +    // try with the prefix
   1.331 +    for(int32_t field = 0;field<_udbg_enumCount(type, FALSE);field++) {
   1.332 +        if(!strcmp(value, fields[field].str)) {
   1.333 +            return fields[field].num;
   1.334 +        }
   1.335 +    }
   1.336 +    // fail
   1.337 +    return -1;
   1.338 +}
   1.339 +
   1.340 +/* platform info */
   1.341 +/**
   1.342 + * Print the current platform
   1.343 + */
   1.344 +U_CAPI const char *udbg_getPlatform(void)
   1.345 +{
   1.346 +#if U_PLATFORM_HAS_WIN32_API
   1.347 +    return "Windows";
   1.348 +#elif U_PLATFORM == U_PF_UNKNOWN
   1.349 +    return "unknown";
   1.350 +#elif U_PLATFORM == U_PF_DARWIN
   1.351 +    return "Darwin";
   1.352 +#elif U_PLATFORM == U_PF_BSD
   1.353 +    return "BSD";
   1.354 +#elif U_PLATFORM == U_PF_QNX
   1.355 +    return "QNX";
   1.356 +#elif U_PLATFORM == U_PF_LINUX
   1.357 +    return "Linux";
   1.358 +#elif U_PLATFORM == U_PF_ANDROID
   1.359 +    return "Android";
   1.360 +#elif U_PLATFORM == U_PF_CLASSIC_MACOS
   1.361 +    return "MacOS (Classic)";
   1.362 +#elif U_PLATFORM == U_PF_OS390
   1.363 +    return "IBM z";
   1.364 +#elif U_PLATFORM == U_PF_OS400
   1.365 +    return "IBM i";
   1.366 +#else
   1.367 +    return "Other (POSIX-like)";
   1.368 +#endif
   1.369 +}
   1.370 +
   1.371 +struct USystemParams;
   1.372 +
   1.373 +typedef int32_t U_CALLCONV USystemParameterCallback(const USystemParams *param, char *target, int32_t targetCapacity, UErrorCode *status);
   1.374 +
   1.375 +struct USystemParams {
   1.376 +  const char *paramName;
   1.377 +  USystemParameterCallback *paramFunction;
   1.378 +  const char *paramStr;
   1.379 +  int32_t paramInt;
   1.380 +};
   1.381 +
   1.382 +/* parameter types */
   1.383 +U_CAPI  int32_t
   1.384 +paramEmpty(const USystemParams * /* param */, char *target, int32_t targetCapacity, UErrorCode *status) {
   1.385 +  if(U_FAILURE(*status))return 0;
   1.386 +  return u_terminateChars(target, targetCapacity, 0, status);
   1.387 +}
   1.388 +
   1.389 +U_CAPI  int32_t
   1.390 +paramStatic(const USystemParams *param, char *target, int32_t targetCapacity, UErrorCode *status) {
   1.391 +  if(param->paramStr==NULL) return paramEmpty(param,target,targetCapacity,status);
   1.392 +  if(U_FAILURE(*status))return 0;
   1.393 +  int32_t len = uprv_strlen(param->paramStr);
   1.394 +  if(target!=NULL) {
   1.395 +    uprv_strncpy(target,param->paramStr,uprv_min(len,targetCapacity));
   1.396 +  }
   1.397 +  return u_terminateChars(target, targetCapacity, len, status);
   1.398 +}
   1.399 +
   1.400 +static const char *nullString = "(null)";
   1.401 +
   1.402 +static int32_t stringToStringBuffer(char *target, int32_t targetCapacity, const char *str, UErrorCode *status) {
   1.403 +  if(str==NULL) str=nullString;
   1.404 +
   1.405 +  int32_t len = uprv_strlen(str);
   1.406 +  if (U_SUCCESS(*status)) {
   1.407 +    if(target!=NULL) {
   1.408 +      uprv_strncpy(target,str,uprv_min(len,targetCapacity));
   1.409 +    }
   1.410 +  } else {
   1.411 +    const char *s = u_errorName(*status);
   1.412 +    len = uprv_strlen(s);
   1.413 +    if(target!=NULL) {
   1.414 +      uprv_strncpy(target,s,uprv_min(len,targetCapacity));
   1.415 +    }
   1.416 +  }
   1.417 +  return u_terminateChars(target, targetCapacity, len, status);
   1.418 +}
   1.419 +
   1.420 +static int32_t integerToStringBuffer(char *target, int32_t targetCapacity, int32_t n, int32_t radix, UErrorCode *status) {
   1.421 +  if(U_FAILURE(*status)) return 0;
   1.422 +  char str[300];
   1.423 +  T_CString_integerToString(str,n,radix);
   1.424 +  return stringToStringBuffer(target,targetCapacity,str,status);
   1.425 +}
   1.426 +
   1.427 +U_CAPI  int32_t
   1.428 +paramInteger(const USystemParams *param, char *target, int32_t targetCapacity, UErrorCode *status) {
   1.429 +  if(U_FAILURE(*status))return 0;
   1.430 +  if(param->paramStr==NULL || param->paramStr[0]=='d') {
   1.431 +    return integerToStringBuffer(target,targetCapacity,param->paramInt, 10,status);
   1.432 +  } else if(param->paramStr[0]=='x') {
   1.433 +    return integerToStringBuffer(target,targetCapacity,param->paramInt, 16,status);
   1.434 +  } else if(param->paramStr[0]=='o') {
   1.435 +    return integerToStringBuffer(target,targetCapacity,param->paramInt, 8,status);
   1.436 +  } else if(param->paramStr[0]=='b') {
   1.437 +    return integerToStringBuffer(target,targetCapacity,param->paramInt, 2,status);
   1.438 +  } else {
   1.439 +    *status = U_INTERNAL_PROGRAM_ERROR;
   1.440 +    return 0;
   1.441 +  }
   1.442 +}
   1.443 +
   1.444 +
   1.445 +U_CAPI  int32_t
   1.446 +paramCldrVersion(const USystemParams * /* param */, char *target, int32_t targetCapacity, UErrorCode *status) {
   1.447 +  if(U_FAILURE(*status))return 0;
   1.448 +  char str[200]="";
   1.449 +  UVersionInfo icu;
   1.450 +
   1.451 +  ulocdata_getCLDRVersion(icu, status);
   1.452 +  if(U_SUCCESS(*status)) {
   1.453 +    u_versionToString(icu, str);
   1.454 +    return stringToStringBuffer(target,targetCapacity,str,status);
   1.455 +  } else {
   1.456 +    return 0;
   1.457 +  }
   1.458 +}
   1.459 +
   1.460 +
   1.461 +#if !UCONFIG_NO_FORMATTING
   1.462 +U_CAPI  int32_t
   1.463 +paramTimezoneDefault(const USystemParams * /* param */, char *target, int32_t targetCapacity, UErrorCode *status) {
   1.464 +  if(U_FAILURE(*status))return 0;
   1.465 +  UChar buf[100];
   1.466 +  char buf2[100];
   1.467 +  int32_t len;
   1.468 +
   1.469 +  len = ucal_getDefaultTimeZone(buf, 100, status);
   1.470 +  if(U_SUCCESS(*status)&&len>0) {
   1.471 +    u_UCharsToChars(buf, buf2, len+1);
   1.472 +    return stringToStringBuffer(target,targetCapacity, buf2,status);
   1.473 +  } else {
   1.474 +    return 0;
   1.475 +  }
   1.476 +}
   1.477 +#endif
   1.478 +
   1.479 +U_CAPI  int32_t
   1.480 +paramLocaleDefaultBcp47(const USystemParams * /* param */, char *target, int32_t targetCapacity, UErrorCode *status) {
   1.481 +  if(U_FAILURE(*status))return 0;
   1.482 +  const char *def = uloc_getDefault();
   1.483 +  return uloc_toLanguageTag(def,target,targetCapacity,FALSE,status);
   1.484 +}
   1.485 +
   1.486 +
   1.487 +/* simple 1-liner param functions */
   1.488 +#define STRING_PARAM(func, str) U_CAPI  int32_t \
   1.489 +  func(const USystemParams *, char *target, int32_t targetCapacity, UErrorCode *status) \
   1.490 +  {  return stringToStringBuffer(target,targetCapacity,(str),status); }
   1.491 +
   1.492 +STRING_PARAM(paramIcudataPath, u_getDataDirectory())
   1.493 +STRING_PARAM(paramPlatform, udbg_getPlatform())
   1.494 +STRING_PARAM(paramLocaleDefault, uloc_getDefault())
   1.495 +#if !UCONFIG_NO_CONVERSION
   1.496 +STRING_PARAM(paramConverterDefault, ucnv_getDefaultName())
   1.497 +#endif
   1.498 +
   1.499 +#if !UCONFIG_NO_FORMATTING
   1.500 +STRING_PARAM(paramTimezoneVersion, ucal_getTZDataVersion(status))
   1.501 +#endif
   1.502 +
   1.503 +static const USystemParams systemParams[] = {
   1.504 +  { "copyright",    paramStatic, U_COPYRIGHT_STRING,0 },
   1.505 +  { "product",      paramStatic, "icu4c",0 },
   1.506 +  { "product.full", paramStatic, "International Components for Unicode for C/C++",0 },
   1.507 +  { "version",      paramStatic, U_ICU_VERSION,0 },
   1.508 +  { "version.unicode", paramStatic, U_UNICODE_VERSION,0 },
   1.509 +  { "platform.number", paramInteger, "d",U_PLATFORM},
   1.510 +  { "platform.type", paramPlatform, NULL ,0},
   1.511 +  { "locale.default", paramLocaleDefault, NULL, 0},
   1.512 +  { "locale.default.bcp47", paramLocaleDefaultBcp47, NULL, 0},
   1.513 +#if !UCONFIG_NO_CONVERSION
   1.514 +  { "converter.default", paramConverterDefault, NULL, 0},
   1.515 +#endif
   1.516 +  { "icudata.name", paramStatic, U_ICUDATA_NAME, 0},
   1.517 +  { "icudata.path", paramIcudataPath, NULL, 0},
   1.518 +
   1.519 +  { "cldr.version", paramCldrVersion, NULL, 0},
   1.520 +
   1.521 +#if !UCONFIG_NO_FORMATTING
   1.522 +  { "tz.version", paramTimezoneVersion, NULL, 0},
   1.523 +  { "tz.default", paramTimezoneDefault, NULL, 0},
   1.524 +#endif
   1.525 +
   1.526 +  { "cpu.bits",       paramInteger, "d", (sizeof(void*))*8},
   1.527 +  { "cpu.big_endian", paramInteger, "b", U_IS_BIG_ENDIAN},
   1.528 +  { "os.wchar_width", paramInteger, "d", U_SIZEOF_WCHAR_T},
   1.529 +  { "os.charset_family", paramInteger, "d", U_CHARSET_FAMILY},
   1.530 +#if defined (U_HOST)
   1.531 +  { "os.host", paramStatic, U_HOST, 0},
   1.532 +#endif
   1.533 +#if defined (U_BUILD)
   1.534 +  { "build.build", paramStatic, U_BUILD, 0},
   1.535 +#endif
   1.536 +#if defined (U_CC)
   1.537 +  { "build.cc", paramStatic, U_CC, 0},
   1.538 +#endif
   1.539 +#if defined (U_CXX)
   1.540 +  { "build.cxx", paramStatic, U_CXX, 0},
   1.541 +#endif
   1.542 +#if defined (CYGWINMSVC)
   1.543 +  { "build.cygwinmsvc", paramInteger, "b", 1},
   1.544 +#endif
   1.545 +  { "uconfig.internal_digitlist", paramInteger, "b", 1}, /* always 1 */
   1.546 +  { "uconfig.have_parseallinput", paramInteger, "b", UCONFIG_HAVE_PARSEALLINPUT},
   1.547 +  { "uconfig.format_fastpaths_49",paramInteger, "b", UCONFIG_FORMAT_FASTPATHS_49},
   1.548 +
   1.549 +
   1.550 +};
   1.551 +
   1.552 +#define U_SYSPARAM_COUNT (sizeof(systemParams)/sizeof(systemParams[0]))
   1.553 +
   1.554 +U_CAPI const char *udbg_getSystemParameterNameByIndex(int32_t i) {
   1.555 +  if(i>=0 && i < (int32_t)U_SYSPARAM_COUNT) {
   1.556 +    return systemParams[i].paramName;
   1.557 +  } else {
   1.558 +    return NULL;
   1.559 +  }
   1.560 +}
   1.561 +
   1.562 +
   1.563 +U_CAPI int32_t udbg_getSystemParameterValueByIndex(int32_t i, char *buffer, int32_t bufferCapacity, UErrorCode *status) {
   1.564 +  if(i>=0 && i< (int32_t)U_SYSPARAM_COUNT) {
   1.565 +    return systemParams[i].paramFunction(&(systemParams[i]),buffer,bufferCapacity,status);
   1.566 +  } else {
   1.567 +    return 0;
   1.568 +  }
   1.569 +}
   1.570 +
   1.571 +U_CAPI void udbg_writeIcuInfo(FILE *out) {
   1.572 +  char str[2000];
   1.573 +  /* todo: API for writing DTD? */
   1.574 +  fprintf(out, " <icuSystemParams type=\"icu4c\">\n");
   1.575 +  const char *paramName;
   1.576 +  for(int32_t i=0;(paramName=udbg_getSystemParameterNameByIndex(i))!=NULL;i++) {
   1.577 +    UErrorCode status2 = U_ZERO_ERROR;
   1.578 +    udbg_getSystemParameterValueByIndex(i, str,2000,&status2);
   1.579 +    if(U_SUCCESS(status2)) {
   1.580 +      fprintf(out,"    <param name=\"%s\">%s</param>\n", paramName,str);
   1.581 +    } else {
   1.582 +      fprintf(out,"  <!-- n=\"%s\" ERROR: %s -->\n", paramName, u_errorName(status2));
   1.583 +    }
   1.584 +  }
   1.585 +  fprintf(out, " </icuSystemParams>\n");
   1.586 +}
   1.587 +
   1.588 +#define ICU_TRAC_URL "http://bugs.icu-project.org/trac/ticket/"
   1.589 +#define CLDR_TRAC_URL "http://unicode.org/cldr/trac/ticket/"
   1.590 +#define CLDR_TICKET_PREFIX "cldrbug:"
   1.591 +
   1.592 +U_CAPI char *udbg_knownIssueURLFrom(const char *ticket, char *buf) {
   1.593 +  if( ticket==NULL ) {
   1.594 +    return NULL;
   1.595 +  }
   1.596 +
   1.597 +  if( !strncmp(ticket, CLDR_TICKET_PREFIX, strlen(CLDR_TICKET_PREFIX)) ) {
   1.598 +    strcpy( buf, CLDR_TRAC_URL );
   1.599 +    strcat( buf, ticket+strlen(CLDR_TICKET_PREFIX) );
   1.600 +  } else {
   1.601 +    strcpy( buf, ICU_TRAC_URL );
   1.602 +    strcat( buf, ticket );
   1.603 +  }
   1.604 +  return buf;
   1.605 +}
   1.606 +
   1.607 +
   1.608 +#if !U_HAVE_STD_STRING
   1.609 +const char *warning = "WARNING: Don't have std::string (STL) - known issue logs will be deficient.";
   1.610 +
   1.611 +U_CAPI void *udbg_knownIssue_openU(void *ptr, const char *ticket, char *where, const UChar *msg, UBool *firstForTicket,
   1.612 +                                   UBool *firstForWhere) {
   1.613 +  if(ptr==NULL) {
   1.614 +    puts(warning);
   1.615 +  }
   1.616 +  printf("%s\tKnown Issue #%s\n", where, ticket);
   1.617 +
   1.618 +  return (void*)warning;
   1.619 +}
   1.620 +
   1.621 +U_CAPI void *udbg_knownIssue_open(void *ptr, const char *ticket, char *where, const char *msg, UBool *firstForTicket,
   1.622 +                                   UBool *firstForWhere) {
   1.623 +  if(ptr==NULL) {
   1.624 +    puts(warning);
   1.625 +  }
   1.626 +  if(msg==NULL) msg = "";
   1.627 +  printf("%s\tKnown Issue #%s  \"%s\n", where, ticket, msg);
   1.628 +
   1.629 +  return (void*)warning;
   1.630 +}
   1.631 +
   1.632 +U_CAPI UBool udbg_knownIssue_print(void *ptr) {
   1.633 +  puts(warning);
   1.634 +  return FALSE;
   1.635 +}
   1.636 +
   1.637 +U_CAPI void udbg_knownIssue_close(void *ptr) {
   1.638 +  // nothing to do
   1.639 +}
   1.640 +#else
   1.641 +
   1.642 +#include <set>
   1.643 +#include <map>
   1.644 +#include <string>
   1.645 +#include <ostream>
   1.646 +#include <iostream>
   1.647 +
   1.648 +class KnownIssues {
   1.649 +public:
   1.650 +  KnownIssues();
   1.651 +  ~KnownIssues();
   1.652 +  void add(const char *ticket, const char *where, const UChar *msg, UBool *firstForTicket, UBool *firstForWhere);
   1.653 +  void add(const char *ticket, const char *where, const char *msg, UBool *firstForTicket, UBool *firstForWhere);
   1.654 +  UBool print();
   1.655 +private:
   1.656 +  std::map< std::string,
   1.657 +            std::map < std::string, std::set < std::string > > > fTable;
   1.658 +};
   1.659 +
   1.660 +KnownIssues::KnownIssues()
   1.661 +  : fTable()
   1.662 +{
   1.663 +}
   1.664 +
   1.665 +KnownIssues::~KnownIssues()
   1.666 +{
   1.667 +}
   1.668 +
   1.669 +void KnownIssues::add(const char *ticket, const char *where, const UChar *msg, UBool *firstForTicket, UBool *firstForWhere)
   1.670 +{
   1.671 +  if(fTable.find(ticket) == fTable.end()) {
   1.672 +    if(firstForTicket!=NULL) *firstForTicket = TRUE;
   1.673 +    fTable[ticket] = std::map < std::string, std::set < std::string > >();
   1.674 +  } else {
   1.675 +    if(firstForTicket!=NULL) *firstForTicket = FALSE;
   1.676 +  }
   1.677 +  if(where==NULL) return;
   1.678 +
   1.679 +  if(fTable[ticket].find(where) == fTable[ticket].end()) {
   1.680 +    if(firstForWhere!=NULL) *firstForWhere = TRUE;
   1.681 +    fTable[ticket][where] = std::set < std::string >();
   1.682 +  } else {
   1.683 +    if(firstForWhere!=NULL) *firstForWhere = FALSE;
   1.684 +  }
   1.685 +  if(msg==NULL || !*msg) return;
   1.686 +
   1.687 +  std::string str;
   1.688 +  fTable[ticket][where].insert(icu::UnicodeString(msg).toUTF8String(str));
   1.689 +}
   1.690 +
   1.691 +void KnownIssues::add(const char *ticket, const char *where, const char *msg, UBool *firstForTicket, UBool *firstForWhere)
   1.692 +{
   1.693 +  if(fTable.find(ticket) == fTable.end()) {
   1.694 +    if(firstForTicket!=NULL) *firstForTicket = TRUE;
   1.695 +    fTable[ticket] = std::map < std::string, std::set < std::string > >();
   1.696 +  } else {
   1.697 +    if(firstForTicket!=NULL) *firstForTicket = FALSE;
   1.698 +  }
   1.699 +  if(where==NULL) return;
   1.700 +
   1.701 +  if(fTable[ticket].find(where) == fTable[ticket].end()) {
   1.702 +    if(firstForWhere!=NULL) *firstForWhere = TRUE;
   1.703 +    fTable[ticket][where] = std::set < std::string >();
   1.704 +  } else {
   1.705 +    if(firstForWhere!=NULL) *firstForWhere = FALSE;
   1.706 +  }
   1.707 +  if(msg==NULL || !*msg) return;
   1.708 +
   1.709 +  std::string str(msg);
   1.710 +  fTable[ticket][where].insert(str);
   1.711 +}
   1.712 +
   1.713 +UBool KnownIssues::print()
   1.714 +{
   1.715 +  if(fTable.empty()) {
   1.716 +    return FALSE;
   1.717 +  }
   1.718 +
   1.719 +  std::cout << "KNOWN ISSUES" << std::endl;
   1.720 +  for( std::map<  std::string,
   1.721 +          std::map <  std::string,  std::set <  std::string > > >::iterator i = fTable.begin();
   1.722 +       i != fTable.end();
   1.723 +       i++ ) {
   1.724 +    char URL[1024];
   1.725 +    std::cout << '#' << (*i).first << " <" << udbg_knownIssueURLFrom( (*i).first.c_str(), URL ) << ">" << std::endl;
   1.726 +
   1.727 +    for( std::map< std::string, std::set < std::string > >::iterator ii = (*i).second.begin();
   1.728 +         ii != (*i).second.end();
   1.729 +         ii++ ) {
   1.730 +      std::cout << "  " << (*ii).first << std::endl;
   1.731 +      for ( std::set < std::string >::iterator iii = (*ii).second.begin();
   1.732 +            iii != (*ii).second.end();
   1.733 +            iii++ ) {
   1.734 +        std::cout << "     " << '"' << (*iii) << '"' << std::endl;
   1.735 +      }
   1.736 +    }
   1.737 +  }
   1.738 +  return TRUE;
   1.739 +}
   1.740 +
   1.741 +U_CAPI void *udbg_knownIssue_openU(void *ptr, const char *ticket, char *where, const UChar *msg, UBool *firstForTicket,
   1.742 +                                   UBool *firstForWhere) {
   1.743 +  KnownIssues *t = static_cast<KnownIssues*>(ptr);
   1.744 +  if(t==NULL) {
   1.745 +    t = new KnownIssues();
   1.746 +  }
   1.747 +
   1.748 +  t->add(ticket, where, msg, firstForTicket, firstForWhere);
   1.749 +
   1.750 +  return static_cast<void*>(t);
   1.751 +}
   1.752 +
   1.753 +U_CAPI void *udbg_knownIssue_open(void *ptr, const char *ticket, char *where, const char *msg, UBool *firstForTicket,
   1.754 +                                   UBool *firstForWhere) {
   1.755 +  KnownIssues *t = static_cast<KnownIssues*>(ptr);
   1.756 +  if(t==NULL) {
   1.757 +    t = new KnownIssues();
   1.758 +  }
   1.759 +
   1.760 +  t->add(ticket, where, msg, firstForTicket, firstForWhere);
   1.761 +
   1.762 +  return static_cast<void*>(t);
   1.763 +}
   1.764 +
   1.765 +U_CAPI UBool udbg_knownIssue_print(void *ptr) {
   1.766 +  KnownIssues *t = static_cast<KnownIssues*>(ptr);
   1.767 +  if(t==NULL) {
   1.768 +    return FALSE;
   1.769 +  } else {
   1.770 +    t->print();
   1.771 +    return TRUE;
   1.772 +  }
   1.773 +}
   1.774 +
   1.775 +U_CAPI void udbg_knownIssue_close(void *ptr) {
   1.776 +  KnownIssues *t = static_cast<KnownIssues*>(ptr);
   1.777 +  delete t;
   1.778 +}
   1.779 +
   1.780 +#endif

mercurial