Home | History | Annotate | Download | only in toolutil
      1 /******************************************************************************
      2  *   Copyright (C) 2008-2009, International Business Machines
      3  *   Corporation and others.  All Rights Reserved.
      4  *******************************************************************************
      5  */
      6 #include "unicode/utypes.h"
      7 #include "unicode/putil.h"
      8 #include "cstring.h"
      9 #include "toolutil.h"
     10 #include "uoptions.h"
     11 #include "uparse.h"
     12 #include "package.h"
     13 #include "pkg_icu.h"
     14 
     15 #include <stdio.h>
     16 #include <stdlib.h>
     17 #include <string.h>
     18 
     19 
     20 #define LENGTHOF(array) (int32_t)(sizeof(array)/sizeof((array)[0]))
     21 
     22 // read a file list -------------------------------------------------------- ***
     23 
     24 static const struct {
     25     const char *suffix;
     26     int32_t length;
     27 } listFileSuffixes[]={
     28     { ".txt", 4 },
     29     { ".lst", 4 },
     30     { ".tmp", 4 }
     31 };
     32 
     33 /* check for multiple text file suffixes to see if this list name is a text file name */
     34 static UBool
     35 isListTextFile(const char *listname) {
     36     const char *listNameEnd=strchr(listname, 0);
     37     const char *suffix;
     38     int32_t i, length;
     39     for(i=0; i<LENGTHOF(listFileSuffixes); ++i) {
     40         suffix=listFileSuffixes[i].suffix;
     41         length=listFileSuffixes[i].length;
     42         if((listNameEnd-listname)>length && 0==memcmp(listNameEnd-length, suffix, length)) {
     43             return TRUE;
     44         }
     45     }
     46     return FALSE;
     47 }
     48 
     49 /*
     50  * Read a file list.
     51  * If the listname ends with ".txt", then read the list file
     52  * (in the system/ invariant charset).
     53  * If the listname ends with ".dat", then read the ICU .dat package file.
     54  * Otherwise, read the file itself as a single-item list.
     55  */
     56 U_CAPI Package * U_EXPORT2
     57 readList(const char *filesPath, const char *listname, UBool readContents) {
     58     Package *listPkg;
     59     FILE *file;
     60     const char *listNameEnd;
     61 
     62     if(listname==NULL || listname[0]==0) {
     63         fprintf(stderr, "missing list file\n");
     64         return NULL;
     65     }
     66 
     67     listPkg=new Package();
     68     if(listPkg==NULL) {
     69         fprintf(stderr, "icupkg: not enough memory\n");
     70         exit(U_MEMORY_ALLOCATION_ERROR);
     71     }
     72 
     73     listNameEnd=strchr(listname, 0);
     74     if(isListTextFile(listname)) {
     75         // read the list file
     76         char line[1024];
     77         char *end;
     78         const char *start;
     79 
     80         file=fopen(listname, "r");
     81         if(file==NULL) {
     82             fprintf(stderr, "icupkg: unable to open list file \"%s\"\n", listname);
     83             delete listPkg;
     84             exit(U_FILE_ACCESS_ERROR);
     85         }
     86 
     87         while(fgets(line, sizeof(line), file)) {
     88             // remove comments
     89             end=strchr(line, '#');
     90             if(end!=NULL) {
     91                 *end=0;
     92             } else {
     93                 // remove trailing CR LF
     94                 end=strchr(line, 0);
     95                 while(line<end && (*(end-1)=='\r' || *(end-1)=='\n')) {
     96                     *--end=0;
     97                 }
     98             }
     99 
    100             // check first non-whitespace character and
    101             // skip empty lines and
    102             // skip lines starting with reserved characters
    103             start=u_skipWhitespace(line);
    104             if(*start==0 || NULL!=strchr(U_PKG_RESERVED_CHARS, *start)) {
    105                 continue;
    106             }
    107 
    108             // take whitespace-separated items from the line
    109             for(;;) {
    110                 // find whitespace after the item or the end of the line
    111                 for(end=(char *)start; *end!=0 && *end!=' ' && *end!='\t'; ++end) {}
    112                 if(*end==0) {
    113                     // this item is the last one on the line
    114                     end=NULL;
    115                 } else {
    116                     // the item is terminated by whitespace, terminate it with NUL
    117                     *end=0;
    118                 }
    119                 if(readContents) {
    120                     listPkg->addFile(filesPath, start);
    121                 } else {
    122                     listPkg->addItem(start);
    123                 }
    124 
    125                 // find the start of the next item or exit the loop
    126                 if(end==NULL || *(start=u_skipWhitespace(end+1))==0) {
    127                     break;
    128                 }
    129             }
    130         }
    131         fclose(file);
    132     } else if((listNameEnd-listname)>4 && 0==memcmp(listNameEnd-4, ".dat", 4)) {
    133         // read the ICU .dat package
    134         listPkg->readPackage(listname);
    135     } else {
    136         // list the single file itself
    137         if(readContents) {
    138             listPkg->addFile(filesPath, listname);
    139         } else {
    140             listPkg->addItem(listname);
    141         }
    142     }
    143 
    144     return listPkg;
    145 }
    146 
    147 U_CAPI int U_EXPORT2
    148 writePackageDatFile(const char *outFilename, const char *outComment, const char *sourcePath, const char *addList, Package *pkg, char outType) {
    149     Package *addListPkg = NULL;
    150     UBool pkgDelete = FALSE;
    151 
    152     if (pkg == NULL) {
    153         pkg = new Package;
    154         if(pkg == NULL) {
    155             fprintf(stderr, "icupkg: not enough memory\n");
    156             return U_MEMORY_ALLOCATION_ERROR;
    157         }
    158 
    159         addListPkg = readList(sourcePath, addList, TRUE);
    160         if(addListPkg != NULL) {
    161             pkg->addItems(*addListPkg);
    162         } else {
    163             return U_ILLEGAL_ARGUMENT_ERROR;
    164         }
    165 
    166         pkgDelete = TRUE;
    167     }
    168 
    169     pkg->writePackage(outFilename, outType, outComment);
    170 
    171     if (pkgDelete) {
    172         delete pkg;
    173         delete addListPkg;
    174     }
    175 
    176     return 0;
    177 }
    178 
    179