Back to index

tetex-bin  3.0
rc.c
Go to the documentation of this file.
00001 /*
00002  *  rc.c -- routines for processing the configuration file
00003  *
00004  *  AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
00005  *
00006  *  This program is free software; you can redistribute it and/or
00007  *  modify it under the terms of the GNU General Public License
00008  *  as published by the Free Software Foundation; either version 2
00009  *  of the License, or (at your option) any later version.
00010  *
00011  *  This program is distributed in the hope that it will be useful,
00012  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  *  GNU General Public License for more details.
00015  *
00016  *  You should have received a copy of the GNU General Public License
00017  *  along with this program; if not, write to the Free Software
00018  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00019  */
00020 
00021 #ifdef HAVE_NCURSES
00022 
00023 #include "dialog.h"
00024 #include "colors.h"
00025 #include "rc.h"
00026 
00027 
00028 static char *attr_to_str(int fg, int bg, int hl);
00029 static int str_to_attr(char *str, int *fg, int *bg, int *hl);
00030 static int parse_line(char *line, char **var, char **value);
00031 
00032 
00033 /*
00034  * Create the configuration file
00035  */
00036 void create_rc(char *filename)
00037 {
00038   int i;
00039   FILE *rc_file;
00040 
00041   if ((rc_file = fopen(filename, "wt")) == NULL) {
00042     fprintf(stderr, "\nError opening file for writing in create_rc().\n");
00043     exit(-1);
00044   }
00045 
00046   fprintf(rc_file, "#\
00047 \n# Run-time configuration file for dialog\
00048 \n#\
00049 \n# Automatically generated by \"dialog --create-rc <file>\"\
00050 \n#\
00051 \n#\
00052 \n# Types of values:\
00053 \n#\
00054 \n# Number     -  <number>\
00055 \n# String     -  \"string\"\
00056 \n# Boolean    -  <ON|OFF>\
00057 \n# Attribute  -  (foreground,background,highlight?)\
00058 \n#\n\n");
00059 
00060   /* Print an entry for each configuration variable */
00061   for (i = 0; i < VAR_COUNT; i++) {
00062     fprintf(rc_file, "\n# %s\n", vars[i].comment);    /* print comment */
00063     switch (vars[i].type) {
00064       case VAL_INT:
00065         fprintf(rc_file, "%s = %d\n", vars[i].name, *((int *) vars[i].var));
00066         break;
00067       case VAL_STR:
00068         fprintf(rc_file, "%s = \"%s\"\n", vars[i].name, (char *) vars[i].var);
00069         break;
00070       case VAL_BOOL:
00071         fprintf(rc_file, "%s = %s\n", vars[i].name, *((bool *) vars[i].var) ? "ON" : "OFF");
00072         break;
00073       case VAL_ATTR:
00074         fprintf(rc_file, "%s = %s\n", vars[i].name, attr_to_str(((int *) vars[i].var)[0], ((int *) vars[i].var)[1], ((int *) vars[i].var)[2]));
00075         break;
00076     }
00077   }
00078 
00079   fclose(rc_file);
00080 }
00081 /* End of create_rc() */
00082 
00083 
00084 /*
00085  * Parse the configuration file and set up variables
00086  */
00087 int parse_rc(void)
00088 {
00089   int i, l = 1, parse, fg, bg, hl;
00090   char str[MAX_LEN+1], *var, *value, *tempptr;
00091   FILE *rc_file;
00092 
00093   /*
00094    *
00095    *  At start, 'dialog' determines the settings to use as follows:
00096    *
00097    *  a) if environment variable DIALOGRC is set, it's value determines the
00098    *     name of the configuration file.
00099    *
00100    *  b) if the file in (a) can't be found, use the file $HOME/.dialogrc
00101    *     as the configuration file.
00102    *
00103    *  c) if the file in (b) can't be found, use compiled in defaults.
00104    *
00105    */
00106 
00107   if ((tempptr = getenv("DIALOGRC")) != NULL)
00108     rc_file = fopen(tempptr, "rt");
00109 
00110   if (tempptr == NULL || rc_file == NULL) {    /* step (a) failed? */
00111     /* try step (b) */
00112     if ((tempptr = getenv("HOME")) == NULL)
00113       return 0;    /* step (b) failed, use default values */
00114 
00115     if (tempptr[0] == '\0' || lastch(tempptr) == '/')
00116       sprintf(str, "%s%s", tempptr, DIALOGRC);
00117     else
00118       sprintf(str, "%s/%s", tempptr, DIALOGRC);
00119 
00120     if ((rc_file = fopen(str, "rt")) == NULL)
00121       return 0;    /* step (b) failed, use default values */
00122   }
00123 
00124   /* Scan each line and set variables */
00125   while (fgets(str, MAX_LEN, rc_file) != NULL) {
00126     if (lastch(str) != '\n') {    /* ignore rest of file if line too long */
00127       fprintf(stderr, "\nParse error: line %d of configuration file too long.\n", l);
00128       fclose(rc_file);
00129       return -1;    /* parse aborted */
00130     }
00131     else {
00132       lastch(str) = '\0';
00133       parse = parse_line(str, &var, &value);    /* parse current line */
00134 
00135       switch (parse) {
00136        case LINE_BLANK:    /* ignore blank lines and comments */
00137         case LINE_COMMENT:
00138           break;
00139         case LINE_OK:
00140           /* search table for matching config variable name */
00141           for (i = 0; i < VAR_COUNT && strcmp(vars[i].name, var); i++);
00142 
00143           if (i == VAR_COUNT) {    /* no match */
00144             fprintf(stderr, "\nParse error: unknown variable at line %d of configuration file.\n", l);
00145             return -1;    /* parse aborted */
00146           }
00147           else {    /* variable found in table, set run time variables */
00148             switch (vars[i].type) {
00149               case VAL_INT:
00150                 *((int *) vars[i].var) = atoi(value);
00151                 break;
00152               case VAL_STR:
00153                 if (!isquote(value[0]) || !isquote(lastch(value)) || strlen(value) < 2) {
00154                   fprintf(stderr, "\nParse error: string value expected at line %d of configuration file.\n", l);
00155                   return -1;    /* parse aborted */
00156                 }
00157                 else {
00158                   /* remove the (") quotes */
00159                   value++;
00160                   lastch(value) = '\0';
00161                   strcpy((char *) vars[i].var, value);
00162               }
00163                 break;
00164               case VAL_BOOL:
00165                 if (!strcasecmp(value, "ON"))
00166                   *((bool *) vars[i].var) = TRUE;
00167                 else if (!strcasecmp(value, "OFF"))
00168                   *((bool *) vars[i].var) = FALSE;
00169                 else {
00170                   fprintf(stderr, "\nParse error: boolean value expected at line %d of configuration file.\n", l);
00171                   return -1;    /* parse aborted */
00172                 }
00173                 break;
00174               case VAL_ATTR:
00175                 if (str_to_attr(value, &fg, &bg, &hl) == -1) {
00176                   fprintf(stderr, "\nParse error: attribute value expected at line %d of configuration file.\n", l);
00177                   return -1;    /* parse aborted */
00178                 }
00179                 ((int *) vars[i].var)[0] = fg;
00180                 ((int *) vars[i].var)[1] = bg;
00181                 ((int *) vars[i].var)[2] = hl;
00182                 break;
00183             }
00184           }
00185           break;
00186         case LINE_ERROR:
00187           fprintf(stderr, "\nParse error: syntax error at line %d of configuration file.\n", l);
00188           return -1;    /* parse aborted */
00189       }
00190     }
00191 
00192     l++;    /* next line */
00193   }
00194 
00195   fclose(rc_file);
00196   return 0;    /* parse successful */
00197 }
00198 /* End of parse_rc() */
00199 
00200 
00201 /*
00202  * Convert an attribute to a string representation like this:
00203  *
00204  * "(foreground,background,highlight)"
00205  */
00206 static char *attr_to_str(int fg, int bg, int hl)
00207 {
00208   int i;
00209   static char str[MAX_LEN+1];
00210 
00211   strcpy(str, "(");
00212   /* foreground */
00213   for (i = 0; fg != color_names[i].value; i++);
00214   strcat(str, color_names[i].name);
00215   strcat(str, ",");
00216 
00217   /* background */
00218   for (i = 0; bg != color_names[i].value; i++);
00219   strcat(str, color_names[i].name);
00220 
00221   /* highlight */
00222   strcat(str, hl ? ",ON)" : ",OFF)");
00223 
00224   return str;
00225 }
00226 /* End of attr_to_str() */
00227 
00228 
00229 /*
00230  * Extract the foreground, background and highlight values from an attribute
00231  * represented as a string in this form:
00232  *
00233  * "(foreground,background,highlight)"
00234  */
00235 static int str_to_attr(char *str, int *fg, int *bg, int *hl)
00236 {
00237   int i = 0, j, get_fg = 1;
00238   char tempstr[MAX_LEN+1], *part;
00239 
00240   if (str[0] != '(' || lastch(str) != ')')
00241     return -1;    /* invalid representation */
00242 
00243   /* remove the parenthesis */
00244   strcpy(tempstr, str + 1);
00245   lastch(tempstr) = '\0';
00246 
00247 
00248   /* get foreground and background */
00249 
00250   while (1) {
00251     /* skip white space before fg/bg string */
00252     while (whitespace(tempstr[i]) && tempstr[i] != '\0') i++;
00253     if (tempstr[i] == '\0')
00254       return -1;    /* invalid representation */
00255     part = tempstr + i;    /* set 'part' to start of fg/bg string */
00256 
00257     /* find end of fg/bg string */
00258     while(!whitespace(tempstr[i]) && tempstr[i] != ',' && tempstr[i] != '\0') i++;
00259 
00260     if (tempstr[i] == '\0')
00261       return -1;    /* invalid representation */
00262     else if (whitespace(tempstr[i])) {   /* not yet ',' */
00263       tempstr[i++] = '\0';
00264 
00265       /* skip white space before ',' */
00266       while(whitespace(tempstr[i]) && tempstr[i] != '\0') i++;
00267 
00268       if (tempstr[i] != ',')
00269         return -1;    /* invalid representation */
00270     }
00271 
00272     tempstr[i++] = '\0';    /* skip the ',' */
00273     for (j = 0; j < COLOR_COUNT && strcasecmp(part, color_names[j].name); j++);
00274     if (j == COLOR_COUNT)    /* invalid color name */
00275       return -1;
00276     if (get_fg) {
00277       *fg = color_names[j].value;
00278       get_fg = 0;    /* next we have to get the background */
00279     }
00280     else {
00281       *bg = color_names[j].value;
00282       break;
00283     }
00284   }   /* got foreground and background */
00285 
00286 
00287   /* get highlight */
00288 
00289   /* skip white space before highlight string */
00290   while (whitespace(tempstr[i]) && tempstr[i] != '\0') i++;
00291   if (tempstr[i] == '\0')
00292     return -1;    /* invalid representation */
00293   part = tempstr + i;    /* set 'part' to start of highlight string */
00294 
00295   /* trim trailing white space from highlight string */
00296   i = strlen(part) - 1;
00297   while(whitespace(part[i])) i--;
00298   part[i+1] = '\0';
00299 
00300   if (!strcasecmp(part, "ON"))
00301     *hl = TRUE;
00302   else if (!strcasecmp(part, "OFF"))
00303     *hl = FALSE;
00304   else
00305     return -1;    /* invalid highlight value */
00306 
00307   return 0;
00308 }
00309 /* End of str_to_attr() */
00310 
00311 
00312 /*
00313  * Parse a line in the configuration file
00314  *
00315  * Each line is of the form:  "variable = value". On exit, 'var' will contain
00316  * the variable name, and 'value' will contain the value string.
00317  *
00318  * Return values:
00319  *
00320  * LINE_BLANK   - line is blank
00321  * LINE_COMMENT - line is comment
00322  * LINE_OK      - line is ok
00323  * LINE_ERROR   - syntax error in line
00324  */
00325 static int parse_line(char *line, char **var, char **value)
00326 {
00327   int i = 0;
00328 
00329   /* ignore white space at beginning of line */
00330   while(whitespace(line[i]) && line[i] != '\0') i++;
00331 
00332   if (line[i] == '\0')    /* line is blank */
00333     return LINE_BLANK;
00334   else if (line[i] == '#')    /* line is comment */
00335     return LINE_COMMENT;
00336   else if (line[i] == '=')    /* variables names can't strart with a '=' */
00337     return LINE_ERROR;
00338 
00339   /* set 'var' to variable name */
00340   *var = line + i++;    /* skip to next character */
00341 
00342   /* find end of variable name */
00343   while(!whitespace(line[i]) && line[i] != '=' && line[i] != '\0') i++;
00344 
00345   if (line[i] == '\0')    /* syntax error */
00346     return LINE_ERROR;
00347   else if (line[i] == '=')
00348     line[i++] = '\0';
00349   else {
00350     line[i++] = '\0';
00351 
00352     /* skip white space before '=' */
00353     while(whitespace(line[i]) && line[i] != '\0') i++;
00354 
00355     if (line[i] != '=')    /* syntax error */
00356       return LINE_ERROR;
00357     else
00358       i++;    /* skip the '=' */
00359   }
00360 
00361   /* skip white space after '=' */
00362   while(whitespace(line[i]) && line[i] != '\0') i++;
00363 
00364   if (line[i] == '\0')
00365     return LINE_ERROR;
00366   else
00367     *value = line + i;    /* set 'value' to value string */
00368 
00369   /* trim trailing white space from 'value' */
00370   i = strlen(*value) - 1;
00371   while(whitespace((*value)[i])) i--;
00372   (*value)[i+1] = '\0';
00373 
00374   return LINE_OK;    /* no syntax error in line */
00375 }
00376 /* End of parse_line() */
00377 #endif