libjulius/src/m_jconf.c

Go to the documentation of this file.
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') 
00057 
00058 
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   }
00131   buf[pos] = '\0';
00132 
00133   return buf;
00134 }
00135 
00152 void
00153 get_dirname(char *path)
00154 {
00155   char *p;
00156   /* /path/file -> /path/ */
00157   /* path/file  -> path/  */
00158   /* /file      -> / */
00159   /* file       ->  */
00160   /* ../file    -> ../ */
00161   p = path + strlen(path) - 1;
00162   while (*p != '/'
00163 #if defined(_WIN32) && !defined(__CYGWIN32__)
00164          && *p != '\\'
00165 #endif
00166          && p != path) p--;
00167   if (p == path && *p != '/') *p = '\0';
00168   else *(p+1) = '\0';
00169 }
00170 
00205 static char *
00206 expand_env(char *str)
00207 {
00208   char *p, *q;
00209   char *bgn;
00210   char eb;
00211   char *target;
00212   char *envval;
00213   int target_malloclen;
00214   int len, n;
00215   boolean inbrace;
00216   static char env[256];
00217 
00218   /* check if string contains '$' and return immediately if not */
00219   /* '$' = 36, '\'' = 39 */
00220   p = str;
00221   inbrace = FALSE;
00222   while (*p != '\0') {
00223     if (*p == 39) {
00224       if (inbrace == FALSE) {
00225         inbrace = TRUE;
00226       } else {
00227         inbrace = FALSE;
00228       }
00229       p++;
00230       continue;
00231     }
00232     if (! inbrace) {
00233       if (*p == '\\') {
00234         p++;
00235         if (*p == '\0') break;
00236       } else {
00237         if (*p == 36) break;
00238       }
00239     }
00240     p++;
00241   }
00242   if (*p == '\0') return str;
00243 
00244   /* prepare result buffer */
00245   target_malloclen = strlen(str) * 2;
00246   target = (char *)mymalloc(target_malloclen);
00247 
00248   p = str;
00249   q = target;
00250 
00251   /* parsing */
00252   inbrace = FALSE;
00253   while (*p != '\0') {
00254 
00255     /* look for next '$' */
00256     while (*p != '\0') {
00257       if (*p == 39) {
00258         if (inbrace == FALSE) {
00259           inbrace = TRUE;
00260         } else {
00261           inbrace = FALSE;
00262         }
00263         p++;
00264         continue;
00265       }
00266       if (! inbrace) {
00267         if (*p == '\\') {
00268           p++;
00269           if (*p == '\0') break;
00270         } else {
00271           if (*p == 36) break;
00272         }
00273       }
00274       *q = *p;
00275       p++;
00276       q++;
00277       n = q - target;
00278       if (n >= target_malloclen) {
00279         target_malloclen *= 2;
00280         target = myrealloc(target, target_malloclen);
00281         q = target + n;
00282       }
00283     }
00284     if (*p == '\0') {           /* reached end of string */
00285       *q = '\0';
00286       break;
00287     }
00288 
00289     /* move to next */
00290     p++;
00291 
00292     /* check for brace */
00293     eb = 0;
00294     if (*p == '(') {
00295       eb = ')';
00296     } else if (*p == '{') {
00297       eb = '}';
00298     }
00299 
00300     /* proceed to find env end point and set the env string to env[] */
00301     if (eb != 0) {
00302       p++;
00303       bgn = p;
00304       while (*p != '\0' && *p != eb) p++;
00305       if (*p == '\0') {
00306         jlog("ERROR: failed to expand variable: no end brace: \"%s\"\n", str);
00307         free(target);
00308         return str;
00309       }
00310     } else {
00311       bgn = p;
00312       while (*p == '_'
00313              || (*p >= '0' && *p <= '9')
00314              || (*p >= 'a' && *p <= 'z')
00315              || (*p >= 'A' && *p <= 'Z')) p++;
00316     }
00317     len = p - bgn;
00318     if (len >= 256 - 1) {
00319       jlog("ERROR: failed to expand variable: too long env name: \"%s\"\n", str);
00320       free(target);
00321       return str;
00322     }
00323     strncpy(env, bgn, len);
00324     env[len+1] = '\0';
00325     
00326     /* get value */
00327     if ((envval = getenv(env)) == NULL) {
00328       jlog("ERROR: failed to expand variable: no such variable \"%s\"\n", env);
00329       free(target);
00330       return str;
00331     }
00332 
00333     if (debug2_flag) {          /* for debug */
00334       jlog("DEBUG: expand $%s to %s\n", env, envval);
00335     }
00336 
00337     /* paste value to target */
00338     while(*envval != '\0') {
00339       *q = *envval;
00340       q++;
00341       envval++;
00342       n = q - target;
00343       if (n >= target_malloclen) {
00344         target_malloclen *= 2;
00345         target = myrealloc(target, target_malloclen);
00346         q = target + n;
00347       }
00348     }
00349 
00350     /* go on to next */
00351   }
00352 
00353   free(str);
00354   return target;
00355 }
00356 
00357 /* read-in and parse jconf file and process those using m_options */
00375 boolean
00376 config_file_parse(char *conffile, Jconf *jconf)
00377 {
00378   int c_argc;
00379   char **c_argv;
00380   FILE *fp;
00381   int maxnum, step;
00382   static const int len = 512;
00383   char buf[len], cpy[len];
00384   char *p, *dst, *dst_from;
00385   char *cdir;
00386   int i;
00387   boolean ret;
00388 
00389   jlog("STAT: include config: %s\n", conffile);
00390   
00391   /* set the content of jconf file into argument list c_argv[1..c_argc-1] */
00392   /* c_argv[0] will be the original conffile name */
00393   /* inside jconf file, quoting by ", ' and escape by '\' is supported */
00394   if ((fp = fopen(conffile, "r")) == NULL) {
00395     jlog("ERROR: m_jconf: failed to open jconf file: %s\n", conffile);
00396     return FALSE;
00397   }
00398   step = 20;
00399   maxnum = step;
00400   c_argv = (char **)mymalloc(sizeof(char *) * maxnum);
00401   c_argv[0] = strcpy((char *)mymalloc(strlen(conffile)+1), conffile);
00402   c_argc = 1;
00403   while (fgets_jconf(buf, len, fp) != NULL) {
00404     if (buf[0] == '\0') continue;
00405     p = buf; dst = cpy;
00406     while (1) {
00407       while (*p != '\0' && ISTOKEN(*p)) p++;
00408       if (*p == '\0') break;
00409       
00410       dst_from = dst;
00411       
00412       while (*p != '\0' && (!ISTOKEN(*p))) {
00413         if (0 &&/* '\' is removed by fgets_jconf */ *p == '\\') {     /* escape by '\' */
00414           if (*(++p) == '\0') break;
00415           *(dst++) = *(p++);
00416         } else {
00417           if (*p == '"') { /* quote by "" */
00418             p++;
00419             while (*p != '\0' && *p != '"') *(dst++) = *(p++);
00420             if (*p == '\0') break;
00421             p++;
00422           } else if (*p == '\'') { /* quote by '' */
00423             p++;
00424             while (*p != '\0' && *p != '\'') *(dst++) = *(p++);
00425             if (*p == '\0') break;
00426             p++;
00427           } else if (*p == '#') { /* comment out by '#' */
00428             *p = '\0';
00429             break;
00430           } else {              /* other */
00431             *(dst++) = *(p++);
00432           }
00433         }
00434       }
00435       if (dst != dst_from) {
00436         *dst = '\0'; dst++;
00437         if (c_argc >= maxnum) {
00438           maxnum += step;
00439           c_argv = (char **)myrealloc(c_argv, sizeof(char *) * maxnum);
00440         }
00441         c_argv[c_argc++] = strcpy((char*)mymalloc(strlen(dst_from)+1), dst_from);
00442       }
00443     }
00444   }
00445   if (fclose(fp) == -1) {
00446     jlog("ERROR: m_jconf: cannot close jconf file\n");
00447     return FALSE;
00448   }
00449 
00450   /* env expansion */
00451   for (i=1;i<c_argc;i++) {
00452     c_argv[i] = expand_env(c_argv[i]);
00453   }
00454 
00455   if (debug2_flag) {            /* for debug */
00456     jlog("DEBUG: args:");
00457     for (i=1;i<c_argc;i++) jlog(" %s",c_argv[i]);
00458     jlog("\n");
00459   }
00460 
00461   /* now that options are in c_argv[][], call opt_parse() to process them */
00462   /* relative paths in jconf file are relative to the jconf file (not current) */
00463   cdir = strcpy((char *)mymalloc(strlen(conffile)+1), conffile);
00464   get_dirname(cdir);
00465   ret = opt_parse(c_argc, c_argv, (cdir[0] == '\0') ? NULL : cdir, jconf);
00466   free(cdir);
00467 
00468   /* free arguments */
00469   while (c_argc-- > 0) {
00470     free(c_argv[c_argc]);
00471   }
00472   free(c_argv);
00473 
00474   return(ret);
00475 }
00476 
00477 /* end of file */

Generated on Tue Dec 18 15:59:52 2007 for Julius by  doxygen 1.5.4