Julius 4.1.5
libjulius/src/m_jconf.c
説明を見る。
00001 
00043 /*
00044  * Copyright (c) 1991-2007 Kawahara Lab., Kyoto University
00045  * Copyright (c) 2000-2005 Shikano Lab., Nara Institute of Science and Technology
00046  * Copyright (c) 2005-2007 Julius project team, Nagoya Institute of Technology
00047  * All rights reserved
00048  */
00049 
00050 #include <julius/julius.h>
00051 
00052 #if defined(_WIN32) && !defined(__CYGWIN32__)
00053 #include <mbstring.h>
00054 #endif
00055 
00056 #define ISTOKEN(A) (A == ' ' || A == '\t' || A == '\n') ///< Determine token characters
00057 
00085 /* added by H.Banno for Windows & Mac */
00086 static char *
00087 fgets_jconf(char *buf, int size, FILE *fp)
00088 {
00089   int c, prev_c;
00090   int pos;
00091 
00092   if (fp == NULL) return NULL;
00093     
00094   pos = 0;
00095   c = '\0';
00096   prev_c = '\0';
00097   while (1) {
00098     if (pos >= size) {
00099       pos--;
00100       break;
00101     }
00102 
00103     c = fgetc(fp);
00104     if (c == EOF) {
00105       buf[pos] = '\0';
00106       if (pos <= 0) {
00107         return NULL;
00108       } else {
00109         return buf;
00110       }
00111     } else if (c == '\n' || c == '\r') {
00112       if (c == '\r' && (c = fgetc(fp)) != '\n') { /* for Mac */
00113         ungetc(c, fp);
00114       }
00115       if (prev_c == '\\') {
00116         pos--;
00117       } else {
00118         break;
00119       }
00120     } else {
00121       buf[pos] = c;
00122       pos++;
00123 
00124 #if defined(_WIN32) && !defined(__CYGWIN32__)
00125       if (c == '\\' && (_ismbblead(prev_c) && _ismbbtrail(c))) {
00126       c = '\0';
00127       }
00128 #endif
00129     }
00130     prev_c = c;
00131   }
00132   buf[pos] = '\0';
00133 
00134   return buf;
00135 }
00136 
00153 void
00154 get_dirname(char *path)
00155 {
00156   char *p;
00157   /* /path/file -> /path/ */
00158   /* path/file  -> path/  */
00159   /* /file      -> / */
00160   /* file       ->  */
00161   /* ../file    -> ../ */
00162   p = path + strlen(path) - 1;
00163   while (*p != '/'
00164 #if defined(_WIN32) && !defined(__CYGWIN32__)
00165          && *p != '\\'
00166 #endif
00167          && p != path) p--;
00168   if (p == path && *p != '/') *p = '\0';
00169   else *(p+1) = '\0';
00170 }
00171 
00206 static char *
00207 expand_env(char *str)
00208 {
00209   char *p, *q;
00210   char *bgn;
00211   char eb;
00212   char *target;
00213   char *envval;
00214   int target_malloclen;
00215   int len, n;
00216   boolean inbrace;
00217   char env[256];
00218 
00219   /* check if string contains '$' and return immediately if not */
00220   /* '$' = 36, '\'' = 39 */
00221   p = str;
00222   inbrace = FALSE;
00223   while (*p != '\0') {
00224     if (*p == 39) {
00225       if (inbrace == FALSE) {
00226         inbrace = TRUE;
00227       } else {
00228         inbrace = FALSE;
00229       }
00230       p++;
00231       continue;
00232     }
00233     if (! inbrace) {
00234       if (*p == '\\') {
00235         p++;
00236         if (*p == '\0') break;
00237       } else {
00238         if (*p == 36) break;
00239       }
00240     }
00241     p++;
00242   }
00243   if (*p == '\0') return str;
00244 
00245   /* prepare result buffer */
00246   target_malloclen = strlen(str) * 2;
00247   target = (char *)mymalloc(target_malloclen);
00248 
00249   p = str;
00250   q = target;
00251 
00252   /* parsing */
00253   inbrace = FALSE;
00254   while (*p != '\0') {
00255 
00256     /* look for next '$' */
00257     while (*p != '\0') {
00258       if (*p == 39) {
00259         if (inbrace == FALSE) {
00260           inbrace = TRUE;
00261         } else {
00262           inbrace = FALSE;
00263         }
00264         p++;
00265         continue;
00266       }
00267       if (! inbrace) {
00268         if (*p == '\\') {
00269           p++;
00270           if (*p == '\0') break;
00271         } else {
00272           if (*p == 36) break;
00273         }
00274       }
00275       *q = *p;
00276       p++;
00277       q++;
00278       n = q - target;
00279       if (n >= target_malloclen) {
00280         target_malloclen *= 2;
00281         target = myrealloc(target, target_malloclen);
00282         q = target + n;
00283       }
00284     }
00285     if (*p == '\0') {           /* reached end of string */
00286       *q = '\0';
00287       break;
00288     }
00289 
00290     /* move to next */
00291     p++;
00292 
00293     /* check for brace */
00294     eb = 0;
00295     if (*p == '(') {
00296       eb = ')';
00297     } else if (*p == '{') {
00298       eb = '}';
00299     }
00300 
00301     /* proceed to find env end point and set the env string to env[] */
00302     if (eb != 0) {
00303       p++;
00304       bgn = p;
00305       while (*p != '\0' && *p != eb) p++;
00306       if (*p == '\0') {
00307         jlog("ERROR: failed to expand variable: no end brace: \"%s\"\n", str);
00308         free(target);
00309         return str;
00310       }
00311     } else {
00312       bgn = p;
00313       while (*p == '_'
00314              || (*p >= '0' && *p <= '9')
00315              || (*p >= 'a' && *p <= 'z')
00316              || (*p >= 'A' && *p <= 'Z')) p++;
00317     }
00318     len = p - bgn;
00319     if (len >= 256 - 1) {
00320       jlog("ERROR: failed to expand variable: too long env name: \"%s\"\n", str);
00321       free(target);
00322       return str;
00323     }
00324     strncpy(env, bgn, len);
00325     env[len] = '\0';
00326 
00327     /* get value */
00328     if ((envval = getenv(env)) == NULL) {
00329       jlog("ERROR: failed to expand variable: no such variable \"%s\"\n", env);
00330       free(target);
00331       return str;
00332     }
00333 
00334     if (debug2_flag) {          /* for debug */
00335       jlog("DEBUG: expand $%s to %s\n", env, envval);
00336     }
00337 
00338     /* paste value to target */
00339     while(*envval != '\0') {
00340       *q = *envval;
00341       q++;
00342       envval++;
00343       n = q - target;
00344       if (n >= target_malloclen) {
00345         target_malloclen *= 2;
00346         target = myrealloc(target, target_malloclen);
00347         q = target + n;
00348       }
00349     }
00350 
00351     /* go on to next */
00352     if (eb != 0) p++;
00353   }
00354 
00355   free(str);
00356   return target;
00357 }
00358 
00359 /* read-in and parse jconf file and process those using m_options */
00377 boolean
00378 config_file_parse(char *conffile, Jconf *jconf)
00379 {
00380   int c_argc;
00381   char **c_argv;
00382   FILE *fp;
00383   int maxnum, step;
00384 #define BUFLEN 512
00385   char buf[BUFLEN], cpy[BUFLEN];
00386   char *p, *dst, *dst_from;
00387   char *cdir;
00388   int i;
00389   boolean ret;
00390 
00391   jlog("STAT: include config: %s\n", conffile);
00392   
00393   /* set the content of jconf file into argument list c_argv[1..c_argc-1] */
00394   /* c_argv[0] will be the original conffile name */
00395   /* inside jconf file, quoting by ", ' and escape by '\' is supported */
00396   if ((fp = fopen(conffile, "r")) == NULL) {
00397     jlog("ERROR: m_jconf: failed to open jconf file: %s\n", conffile);
00398     return FALSE;
00399   }
00400   step = 20;
00401   maxnum = step;
00402   c_argv = (char **)mymalloc(sizeof(char *) * maxnum);
00403   c_argv[0] = strcpy((char *)mymalloc(strlen(conffile)+1), conffile);
00404   c_argc = 1;
00405   while (fgets_jconf(buf, BUFLEN, fp) != NULL) {
00406     if (buf[0] == '\0') continue;
00407     p = buf; dst = cpy;
00408     while (1) {
00409       while (*p != '\0' && ISTOKEN(*p)) p++;
00410       if (*p == '\0') break;
00411       
00412       dst_from = dst;
00413       
00414       while (*p != '\0' && (!ISTOKEN(*p))) {
00415         if (*p == '\\') {     /* escape by '\' */
00416           if (*(++p) == '\0') break;
00417           *(dst++) = *(p++);
00418         } else {
00419           if (*p == '"') { /* quote by "" */
00420             p++;
00421             while (*p != '\0' && *p != '"') *(dst++) = *(p++);
00422             if (*p == '\0') break;
00423             p++;
00424           } else if (*p == '\'') { /* quote by '' */
00425             p++;
00426             while (*p != '\0' && *p != '\'') *(dst++) = *(p++);
00427             if (*p == '\0') break;
00428             p++;
00429           } else if (*p == '#') { /* comment out by '#' */
00430             *p = '\0';
00431             break;
00432           } else {              /* other */
00433             *(dst++) = *(p++);
00434           }
00435         }
00436       }
00437       if (dst != dst_from) {
00438         *dst = '\0'; dst++;
00439         if (c_argc >= maxnum) {
00440           maxnum += step;
00441           c_argv = (char **)myrealloc(c_argv, sizeof(char *) * maxnum);
00442         }
00443         c_argv[c_argc++] = strcpy((char*)mymalloc(strlen(dst_from)+1), dst_from);
00444       }
00445     }
00446   }
00447   if (fclose(fp) == -1) {
00448     jlog("ERROR: m_jconf: cannot close jconf file\n");
00449     return FALSE;
00450   }
00451 
00452   /* env expansion */
00453   for (i=1;i<c_argc;i++) {
00454     c_argv[i] = expand_env(c_argv[i]);
00455   }
00456 
00457   if (debug2_flag) {            /* for debug */
00458     jlog("DEBUG: args:");
00459     for (i=1;i<c_argc;i++) jlog(" %s",c_argv[i]);
00460     jlog("\n");
00461   }
00462 
00463   /* now that options are in c_argv[][], call opt_parse() to process them */
00464   /* relative paths in jconf file are relative to the jconf file (not current) */
00465   cdir = strcpy((char *)mymalloc(strlen(conffile)+1), conffile);
00466   get_dirname(cdir);
00467   ret = opt_parse(c_argc, c_argv, (cdir[0] == '\0') ? NULL : cdir, jconf);
00468   free(cdir);
00469 
00470   /* free arguments */
00471   while (c_argc-- > 0) {
00472     free(c_argv[c_argc]);
00473   }
00474   free(c_argv);
00475 
00476   return(ret);
00477 }
00478 
00479 /* end of file */