Julius 4.2
libjulius/src/m_jconf.c
説明を見る。
00001 
00043 /*
00044  * Copyright (c) 1991-2011 Kawahara Lab., Kyoto University
00045  * Copyright (c) 2000-2005 Shikano Lab., Nara Institute of Science and Technology
00046  * Copyright (c) 2005-2011 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 #define BUFLEN 512
00058 
00086 /* added by H.Banno for Windows & Mac */
00087 static char *
00088 fgets_jconf(char *buf, int size, FILE *fp)
00089 {
00090   int c, prev_c;
00091   int pos;
00092 
00093   if (fp == NULL) return NULL;
00094     
00095   pos = 0;
00096   c = '\0';
00097   prev_c = '\0';
00098   while (1) {
00099     if (pos >= size) {
00100       pos--;
00101       break;
00102     }
00103 
00104     c = fgetc(fp);
00105     if (c == EOF) {
00106       buf[pos] = '\0';
00107       if (pos <= 0) {
00108         return NULL;
00109       } else {
00110         return buf;
00111       }
00112     } else if (c == '\n' || c == '\r') {
00113       if (c == '\r' && (c = fgetc(fp)) != '\n') { /* for Mac */
00114         ungetc(c, fp);
00115       }
00116       if (prev_c == '\\') {
00117         pos--;
00118       } else {
00119         break;
00120       }
00121     } else {
00122       buf[pos] = c;
00123       pos++;
00124 
00125 #if defined(_WIN32) && !defined(__CYGWIN32__)
00126       if (c == '\\' && (_ismbblead(prev_c) && _ismbbtrail(c))) {
00127       c = '\0';
00128       }
00129 #endif
00130     }
00131     prev_c = c;
00132   }
00133   buf[pos] = '\0';
00134 
00135   return buf;
00136 }
00137 
00154 void
00155 get_dirname(char *path)
00156 {
00157   char *p;
00158   /* /path/file -> /path/ */
00159   /* path/file  -> path/  */
00160   /* /file      -> / */
00161   /* file       ->  */
00162   /* ../file    -> ../ */
00163   p = path + strlen(path) - 1;
00164   while (*p != '/'
00165 #if defined(_WIN32) && !defined(__CYGWIN32__)
00166          && *p != '\\'
00167 #endif
00168          && p != path) p--;
00169   if (p == path && *p != '/') *p = '\0';
00170   else *(p+1) = '\0';
00171 }
00172 
00207 static char *
00208 expand_env(char *str)
00209 {
00210   char *p, *q;
00211   char *bgn;
00212   char eb;
00213   char *target;
00214   char *envval;
00215   int target_malloclen;
00216   int len, n;
00217   boolean inbrace;
00218   char env[256];
00219 
00220   /* check if string contains '$' and return immediately if not */
00221   /* '$' = 36, '\'' = 39 */
00222   p = str;
00223   inbrace = FALSE;
00224   while (*p != '\0') {
00225     if (*p == 39) {
00226       if (inbrace == FALSE) {
00227         inbrace = TRUE;
00228       } else {
00229         inbrace = FALSE;
00230       }
00231       p++;
00232       continue;
00233     }
00234     if (! inbrace) {
00235       if (*p == '\\') {
00236         p++;
00237         if (*p == '\0') break;
00238       } else {
00239         if (*p == 36) break;
00240       }
00241     }
00242     p++;
00243   }
00244   if (*p == '\0') return str;
00245 
00246   /* prepare result buffer */
00247   target_malloclen = strlen(str) * 2;
00248   target = (char *)mymalloc(target_malloclen);
00249 
00250   p = str;
00251   q = target;
00252 
00253   /* parsing */
00254   inbrace = FALSE;
00255   while (*p != '\0') {
00256 
00257     /* look for next '$' */
00258     while (*p != '\0') {
00259       if (*p == 39) {
00260         if (inbrace == FALSE) {
00261           inbrace = TRUE;
00262         } else {
00263           inbrace = FALSE;
00264         }
00265         p++;
00266         continue;
00267       }
00268       if (! inbrace) {
00269         if (*p == '\\') {
00270           p++;
00271           if (*p == '\0') break;
00272         } else {
00273           if (*p == 36) break;
00274         }
00275       }
00276       *q = *p;
00277       p++;
00278       q++;
00279       n = q - target;
00280       if (n >= target_malloclen) {
00281         target_malloclen *= 2;
00282         target = myrealloc(target, target_malloclen);
00283         q = target + n;
00284       }
00285     }
00286     if (*p == '\0') {           /* reached end of string */
00287       *q = '\0';
00288       break;
00289     }
00290 
00291     /* move to next */
00292     p++;
00293 
00294     /* check for brace */
00295     eb = 0;
00296     if (*p == '(') {
00297       eb = ')';
00298     } else if (*p == '{') {
00299       eb = '}';
00300     }
00301 
00302     /* proceed to find env end point and set the env string to env[] */
00303     if (eb != 0) {
00304       p++;
00305       bgn = p;
00306       while (*p != '\0' && *p != eb) p++;
00307       if (*p == '\0') {
00308         jlog("ERROR: failed to expand variable: no end brace: \"%s\"\n", str);
00309         free(target);
00310         return str;
00311       }
00312     } else {
00313       bgn = p;
00314       while (*p == '_'
00315              || (*p >= '0' && *p <= '9')
00316              || (*p >= 'a' && *p <= 'z')
00317              || (*p >= 'A' && *p <= 'Z')) p++;
00318     }
00319     len = p - bgn;
00320     if (len >= 256 - 1) {
00321       jlog("ERROR: failed to expand variable: too long env name: \"%s\"\n", str);
00322       free(target);
00323       return str;
00324     }
00325     strncpy(env, bgn, len);
00326     env[len] = '\0';
00327 
00328     /* get value */
00329     if ((envval = getenv(env)) == NULL) {
00330       jlog("ERROR: failed to expand variable: no such variable \"%s\"\n", env);
00331       free(target);
00332       return str;
00333     }
00334 
00335     if (debug2_flag) {          /* for debug */
00336       jlog("DEBUG: expand $%s to %s\n", env, envval);
00337     }
00338 
00339     /* paste value to target */
00340     while(*envval != '\0') {
00341       *q = *envval;
00342       q++;
00343       envval++;
00344       n = q - target;
00345       if (n >= target_malloclen) {
00346         target_malloclen *= 2;
00347         target = myrealloc(target, target_malloclen);
00348         q = target + n;
00349       }
00350     }
00351 
00352     /* go on to next */
00353     if (eb != 0) p++;
00354   }
00355 
00356   free(str);
00357   return target;
00358 }
00359 
00360 /* read-in and parse jconf file and process those using m_options */
00379 static void
00380 add_to_arglist(char *buf, char ***argv_ret, int *argc_ret, int *maxnum_ret)
00381 {
00382   char *p = buf;
00383   char cpy[BUFLEN];
00384   char *dst, *dst_from;
00385   char **argv = *argv_ret;
00386   int argc = *argc_ret;
00387   int maxnum = *maxnum_ret;
00388 
00389   dst = cpy;
00390   while (1) {
00391     while (*p != '\0' && ISTOKEN(*p)) p++;
00392     if (*p == '\0') break;
00393       
00394     dst_from = dst;
00395       
00396     while (*p != '\0' && (!ISTOKEN(*p))) {
00397       if (*p == '\\') {     /* escape by '\' */
00398         if (*(++p) == '\0') break;
00399         *(dst++) = *(p++);
00400       } else {
00401         if (*p == '"') { /* quote by "" */
00402           p++;
00403           while (*p != '\0' && *p != '"') *(dst++) = *(p++);
00404           if (*p == '\0') break;
00405           p++;
00406         } else if (*p == '\'') { /* quote by '' */
00407           p++;
00408           while (*p != '\0' && *p != '\'') *(dst++) = *(p++);
00409           if (*p == '\0') break;
00410           p++;
00411         } else if (*p == '#') { /* comment out by '#' */
00412           *p = '\0';
00413           break;
00414         } else {                /* other */
00415           *(dst++) = *(p++);
00416         }
00417       }
00418     }
00419     if (dst != dst_from) {
00420       *dst = '\0'; dst++;
00421       if ( argc >= maxnum) {
00422         maxnum += 20;
00423         argv = (char **)myrealloc(argv, sizeof(char *) * maxnum);
00424       }
00425       argv[argc++] = strcpy((char*)mymalloc(strlen(dst_from)+1), dst_from);
00426     }
00427   }
00428   *argv_ret = argv;
00429   *argc_ret = argc;
00430   *maxnum_ret = maxnum;
00431 }
00432 
00452 boolean
00453 config_string_parse(char *str, Jconf *jconf)
00454 {
00455   int c_argc;
00456   char **c_argv;
00457   int maxnum;
00458   char buf[BUFLEN];
00459   char *cdir;
00460   int i;
00461   boolean ret;
00462 
00463   jlog("STAT: parsing option string: \"%s\"\n", str);
00464   
00465   /* set the content of jconf file into argument list c_argv[1..c_argc-1] */
00466   maxnum = 20;
00467   c_argv = (char **)mymalloc(sizeof(char *) * maxnum);
00468   c_argv[0] = strcpy((char *)mymalloc(7), "string");
00469   c_argc = 1;
00470   add_to_arglist(str, &c_argv, &c_argc, &maxnum);
00471   /* env expansion */
00472   for (i=1;i<c_argc;i++) {
00473     c_argv[i] = expand_env(c_argv[i]);
00474   }
00475   /* now that options are in c_argv[][], call opt_parse() to process them */
00476   /* relative paths in string are relative to current */
00477   ret = opt_parse(c_argc, c_argv, NULL, jconf);
00478 
00479   /* free arguments */
00480   while (c_argc-- > 0) {
00481     free(c_argv[c_argc]);
00482   }
00483   free(c_argv);
00484 
00485   return(ret);
00486 }
00487 
00508 boolean
00509 config_file_parse(char *conffile, Jconf *jconf)
00510 {
00511   int c_argc;
00512   char **c_argv;
00513   FILE *fp;
00514   int maxnum;
00515   char buf[BUFLEN];
00516   char *cdir;
00517   int i;
00518   boolean ret;
00519 
00520   jlog("STAT: include config: %s\n", conffile);
00521   
00522   /* set the content of jconf file into argument list c_argv[1..c_argc-1] */
00523   /* c_argv[0] will be the original conffile name */
00524   /* inside jconf file, quoting by ", ' and escape by '\' is supported */
00525   if ((fp = fopen(conffile, "r")) == NULL) {
00526     jlog("ERROR: m_jconf: failed to open jconf file: %s\n", conffile);
00527     return FALSE;
00528   }
00529   maxnum = 20;
00530   c_argv = (char **)mymalloc(sizeof(char *) * maxnum);
00531   c_argv[0] = strcpy((char *)mymalloc(strlen(conffile)+1), conffile);
00532   c_argc = 1;
00533   while (fgets_jconf(buf, BUFLEN, fp) != NULL) {
00534     if (buf[0] == '\0') continue;
00535     add_to_arglist(buf, &c_argv, &c_argc, &maxnum);
00536   }
00537   if (fclose(fp) == -1) {
00538     jlog("ERROR: m_jconf: cannot close jconf file\n");
00539     return FALSE;
00540   }
00541 
00542   /* env expansion */
00543   for (i=1;i<c_argc;i++) {
00544     c_argv[i] = expand_env(c_argv[i]);
00545   }
00546 
00547   if (debug2_flag) {            /* for debug */
00548     jlog("DEBUG: args:");
00549     for (i=1;i<c_argc;i++) jlog(" %s",c_argv[i]);
00550     jlog("\n");
00551   }
00552 
00553   /* now that options are in c_argv[][], call opt_parse() to process them */
00554   /* relative paths in jconf file are relative to the jconf file (not current) */
00555   cdir = strcpy((char *)mymalloc(strlen(conffile)+1), conffile);
00556   get_dirname(cdir);
00557   ret = opt_parse(c_argc, c_argv, (cdir[0] == '\0') ? NULL : cdir, jconf);
00558   free(cdir);
00559 
00560   /* free arguments */
00561   while (c_argc-- > 0) {
00562     free(c_argv[c_argc]);
00563   }
00564   free(c_argv);
00565 
00566   return(ret);
00567 }
00568 
00569 /* end of file */