1 /* 2 ******************************************************************************* 3 * 4 * Copyright (C) 2005-2012, International Business Machines 5 * Corporation and others. All Rights Reserved. 6 * 7 ******************************************************************************* 8 * file name: writesrc.c 9 * encoding: US-ASCII 10 * tab size: 8 (not used) 11 * indentation:4 12 * 13 * created on: 2005apr23 14 * created by: Markus W. Scherer 15 * 16 * Helper functions for writing source code for data. 17 */ 18 19 #include <stdio.h> 20 #include <time.h> 21 #include "unicode/utypes.h" 22 #include "unicode/putil.h" 23 #include "utrie2.h" 24 #include "cstring.h" 25 #include "writesrc.h" 26 27 static FILE * 28 usrc_createWithHeader(const char *path, const char *filename, 29 const char *generator, const char *header) { 30 char buffer[1024]; 31 const char *p; 32 char *q; 33 FILE *f; 34 char c; 35 36 if(path==NULL) { 37 p=filename; 38 } else { 39 /* concatenate path and filename, with U_FILE_SEP_CHAR in between if necessary */ 40 uprv_strcpy(buffer, path); 41 q=buffer+uprv_strlen(buffer); 42 if(q>buffer && (c=*(q-1))!=U_FILE_SEP_CHAR && c!=U_FILE_ALT_SEP_CHAR) { 43 *q++=U_FILE_SEP_CHAR; 44 } 45 uprv_strcpy(q, filename); 46 p=buffer; 47 } 48 49 f=fopen(p, "w"); 50 if(f!=NULL) { 51 char year[8]; 52 const struct tm *lt; 53 time_t t; 54 55 time(&t); 56 lt=localtime(&t); 57 strftime(year, sizeof(year), "%Y", lt); 58 if(generator==NULL) { 59 strftime(buffer, sizeof(buffer), "%Y-%m-%d", lt); 60 fprintf(f, header, year, filename, buffer); 61 } else { 62 fprintf(f, header, year, filename, generator); 63 } 64 } else { 65 fprintf( 66 stderr, 67 "usrc_create(%s, %s): unable to create file\n", 68 path!=NULL ? path : "", filename); 69 } 70 return f; 71 } 72 73 U_CAPI FILE * U_EXPORT2 74 usrc_create(const char *path, const char *filename, const char *generator) { 75 static const char *header= 76 "/*\n" 77 " * Copyright (C) 1999-%s, International Business Machines\n" 78 " * Corporation and others. All Rights Reserved.\n" 79 " *\n" 80 " * file name: %s\n" 81 " *\n" 82 " * machine-generated by: %s\n" 83 " */\n\n"; 84 return usrc_createWithHeader(path, filename, generator, header); 85 } 86 87 U_CAPI FILE * U_EXPORT2 88 usrc_createTextData(const char *path, const char *filename, const char *generator) { 89 static const char *header= 90 "# Copyright (C) 1999-%s, International Business Machines\n" 91 "# Corporation and others. All Rights Reserved.\n" 92 "#\n" 93 "# file name: %s\n" 94 "#\n" 95 "# machine-generated by: %s\n" 96 "#\n\n"; 97 return usrc_createWithHeader(path, filename, generator, header); 98 } 99 100 U_CAPI void U_EXPORT2 101 usrc_writeArray(FILE *f, 102 const char *prefix, 103 const void *p, int32_t width, int32_t length, 104 const char *postfix) { 105 const uint8_t *p8; 106 const uint16_t *p16; 107 const uint32_t *p32; 108 uint32_t value; 109 int32_t i, col; 110 111 p8=NULL; 112 p16=NULL; 113 p32=NULL; 114 switch(width) { 115 case 8: 116 p8=(const uint8_t *)p; 117 break; 118 case 16: 119 p16=(const uint16_t *)p; 120 break; 121 case 32: 122 p32=(const uint32_t *)p; 123 break; 124 default: 125 fprintf(stderr, "usrc_writeArray(width=%ld) unrecognized width\n", (long)width); 126 return; 127 } 128 if(prefix!=NULL) { 129 fprintf(f, prefix, (long)length); 130 } 131 for(i=col=0; i<length; ++i, ++col) { 132 if(i>0) { 133 if(col<16) { 134 fputc(',', f); 135 } else { 136 fputs(",\n", f); 137 col=0; 138 } 139 } 140 switch(width) { 141 case 8: 142 value=p8[i]; 143 break; 144 case 16: 145 value=p16[i]; 146 break; 147 case 32: 148 value=p32[i]; 149 break; 150 default: 151 value=0; /* unreachable */ 152 break; 153 } 154 fprintf(f, value<=9 ? "%lu" : "0x%lx", (unsigned long)value); 155 } 156 if(postfix!=NULL) { 157 fputs(postfix, f); 158 } 159 } 160 161 U_CAPI void U_EXPORT2 162 usrc_writeUTrie2Arrays(FILE *f, 163 const char *indexPrefix, const char *data32Prefix, 164 const UTrie2 *pTrie, 165 const char *postfix) { 166 if(pTrie->data32==NULL) { 167 /* 16-bit trie */ 168 usrc_writeArray(f, indexPrefix, pTrie->index, 16, pTrie->indexLength+pTrie->dataLength, postfix); 169 } else { 170 /* 32-bit trie */ 171 usrc_writeArray(f, indexPrefix, pTrie->index, 16, pTrie->indexLength, postfix); 172 usrc_writeArray(f, data32Prefix, pTrie->data32, 32, pTrie->dataLength, postfix); 173 } 174 } 175 176 U_CAPI void U_EXPORT2 177 usrc_writeUTrie2Struct(FILE *f, 178 const char *prefix, 179 const UTrie2 *pTrie, 180 const char *indexName, const char *data32Name, 181 const char *postfix) { 182 if(prefix!=NULL) { 183 fputs(prefix, f); 184 } 185 if(pTrie->data32==NULL) { 186 /* 16-bit trie */ 187 fprintf( 188 f, 189 " %s,\n" /* index */ 190 " %s+%ld,\n" /* data16 */ 191 " NULL,\n", /* data32 */ 192 indexName, 193 indexName, 194 (long)pTrie->indexLength); 195 } else { 196 /* 32-bit trie */ 197 fprintf( 198 f, 199 " %s,\n" /* index */ 200 " NULL,\n" /* data16 */ 201 " %s,\n", /* data32 */ 202 indexName, 203 data32Name); 204 } 205 fprintf( 206 f, 207 " %ld,\n" /* indexLength */ 208 " %ld,\n" /* dataLength */ 209 " 0x%hx,\n" /* index2NullOffset */ 210 " 0x%hx,\n" /* dataNullOffset */ 211 " 0x%lx,\n" /* initialValue */ 212 " 0x%lx,\n" /* errorValue */ 213 " 0x%lx,\n" /* highStart */ 214 " 0x%lx,\n" /* highValueIndex */ 215 " NULL, 0, FALSE, FALSE, 0, NULL\n", 216 (long)pTrie->indexLength, (long)pTrie->dataLength, 217 (short)pTrie->index2NullOffset, (short)pTrie->dataNullOffset, 218 (long)pTrie->initialValue, (long)pTrie->errorValue, 219 (long)pTrie->highStart, (long)pTrie->highValueIndex); 220 if(postfix!=NULL) { 221 fputs(postfix, f); 222 } 223 } 224 225 U_CAPI void U_EXPORT2 226 usrc_writeArrayOfMostlyInvChars(FILE *f, 227 const char *prefix, 228 const char *p, int32_t length, 229 const char *postfix) { 230 int32_t i, col; 231 int prev2, prev, c; 232 233 if(prefix!=NULL) { 234 fprintf(f, prefix, (long)length); 235 } 236 prev2=prev=-1; 237 for(i=col=0; i<length; ++i, ++col) { 238 c=(uint8_t)p[i]; 239 if(i>0) { 240 /* Break long lines. Try to break at interesting places, to minimize revision diffs. */ 241 if( 242 /* Very long line. */ 243 col>=32 || 244 /* Long line, break after terminating NUL. */ 245 (col>=24 && prev2>=0x20 && prev==0) || 246 /* Medium-long line, break before non-NUL, non-character byte. */ 247 (col>=16 && (prev==0 || prev>=0x20) && 0<c && c<0x20) 248 ) { 249 fputs(",\n", f); 250 col=0; 251 } else { 252 fputc(',', f); 253 } 254 } 255 fprintf(f, c<0x20 ? "%u" : "'%c'", c); 256 prev2=prev; 257 prev=c; 258 } 259 if(postfix!=NULL) { 260 fputs(postfix, f); 261 } 262 } 263