home *** CD-ROM | disk | FTP | other *** search
/ PC-Online 1996 May / PCOnline_05_1996.bin / linux / source / a / hdsetup / dialog-0.4-1 / dialog-0 / dialog-0.4-slackware / src / rc.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-03-22  |  10.9 KB  |  376 lines

  1. /*
  2.  *  rc.c -- routines for processing the configuration file
  3.  *
  4.  *  AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
  5.  *
  6.  *  This program is free software; you can redistribute it and/or
  7.  *  modify it under the terms of the GNU General Public License
  8.  *  as published by the Free Software Foundation; either version 2
  9.  *  of the License, or (at your option) any later version.
  10.  *
  11.  *  This program is distributed in the hope that it will be useful,
  12.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.  *  GNU General Public License for more details.
  15.  *
  16.  *  You should have received a copy of the GNU General Public License
  17.  *  along with this program; if not, write to the Free Software
  18.  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19.  */
  20.  
  21.  
  22. #include "dialog.h"
  23. #include "colors.h"
  24. #include "rc.h"
  25.  
  26.  
  27. static unsigned char *attr_to_str(int fg, int bg, int hl);
  28. static int str_to_attr(unsigned char *str, int *fg, int *bg, int *hl);
  29. static int parse_line(unsigned char *line, unsigned char **var, unsigned char **value);
  30.  
  31.  
  32. /*
  33.  * Create the configuration file
  34.  */
  35. void create_rc(unsigned char *filename)
  36. {
  37.   int i;
  38.   FILE *rc_file;
  39.  
  40.   if ((rc_file = fopen(filename, "wt")) == NULL) {
  41.     fprintf(stderr, "\nError opening file for writing in create_rc().\n");
  42.     exit(-1);
  43.   }
  44.  
  45.   fprintf(rc_file, "#\
  46. \n# Run-time configuration file for dialog\
  47. \n#\
  48. \n# Automatically generated by \"dialog --create-rc <file>\"\
  49. \n#\
  50. \n#\
  51. \n# Types of values:\
  52. \n#\
  53. \n# Number     -  <number>\
  54. \n# String     -  \"string\"\
  55. \n# Boolean    -  <ON|OFF>\
  56. \n# Attribute  -  (foreground,background,highlight?)\
  57. \n#\n\n");
  58.  
  59.   /* Print an entry for each configuration variable */
  60.   for (i = 0; i < VAR_COUNT; i++) {
  61.     fprintf(rc_file, "\n# %s\n", vars[i].comment);    /* print comment */
  62.     switch (vars[i].type) {
  63.       case VAL_INT:
  64.         fprintf(rc_file, "%s = %d\n", vars[i].name, *((int *) vars[i].var));
  65.         break;
  66.       case VAL_STR:
  67.         fprintf(rc_file, "%s = \"%s\"\n", vars[i].name, (unsigned char *) vars[i].var);
  68.         break;
  69.       case VAL_BOOL:
  70.         fprintf(rc_file, "%s = %s\n", vars[i].name, *((bool *) vars[i].var) ? "ON" : "OFF");
  71.         break;
  72.       case VAL_ATTR:
  73.         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]));
  74.         break;
  75.     }
  76.   }
  77.  
  78.   fclose(rc_file);
  79. }
  80. /* End of create_rc() */
  81.  
  82.  
  83. /*
  84.  * Parse the configuration file and set up variables
  85.  */
  86. int parse_rc(void)
  87. {
  88.   int i, l = 1, parse, fg, bg, hl;
  89.   unsigned char str[MAX_LEN+1], *var, *value, *tempptr;
  90.   FILE *rc_file;
  91.  
  92.   /*
  93.    *
  94.    *  At start, 'dialog' determines the settings to use as follows:
  95.    *
  96.    *  a) if environment variable DIALOGRC is set, it's value determines the
  97.    *     name of the configuration file.
  98.    *
  99.    *  b) if the file in (a) can't be found, use the file $HOME/.dialogrc
  100.    *     as the configuration file.
  101.    *
  102.    *  c) if the file in (b) can't be found, use compiled in defaults.
  103.    *
  104.    */
  105.  
  106.   if ((tempptr = getenv("DIALOGRC")) != NULL)
  107.     rc_file = fopen(tempptr, "rt");
  108.  
  109.   if (tempptr == NULL || rc_file == NULL) {    /* step (a) failed? */
  110.     /* try step (b) */
  111.     if ((tempptr = getenv("HOME")) == NULL)
  112.       return 0;    /* step (b) failed, use default values */
  113.  
  114.     if (tempptr[0] == '\0' || lastch(tempptr) == '/')
  115.       sprintf(str, "%s%s", tempptr, DIALOGRC);
  116.     else
  117.       sprintf(str, "%s/%s", tempptr, DIALOGRC);
  118.  
  119.     if ((rc_file = fopen(str, "rt")) == NULL)
  120.       return 0;    /* step (b) failed, use default values */
  121.   }
  122.  
  123.   /* Scan each line and set variables */
  124.   while (fgets(str, MAX_LEN, rc_file) != NULL) {
  125.     if (lastch(str) != '\n') {    /* ignore rest of file if line too long */
  126.       fprintf(stderr, "\nParse error: line %d of configuration file too long.\n", l);
  127.       fclose(rc_file);
  128.       return -1;    /* parse aborted */
  129.     }
  130.     else {
  131.       lastch(str) = '\0';
  132.       parse = parse_line(str, &var, &value);    /* parse current line */
  133.  
  134.       switch (parse) {
  135.     case LINE_BLANK:    /* ignore blank lines and comments */
  136.         case LINE_COMMENT:
  137.           break;
  138.         case LINE_OK:
  139.           /* search table for matching config variable name */
  140.           for (i = 0; i < VAR_COUNT && strcmp(vars[i].name, var); i++);
  141.  
  142.           if (i == VAR_COUNT) {    /* no match */
  143.             fprintf(stderr, "\nParse error: unknown variable at line %d of configuration file.\n", l);
  144.             return -1;    /* parse aborted */
  145.           }
  146.           else {    /* variable found in table, set run time variables */
  147.             switch (vars[i].type) {
  148.               case VAL_INT:
  149.                 *((int *) vars[i].var) = atoi(value);
  150.                 break;
  151.               case VAL_STR:
  152.                 if (!isquote(value[0]) || !isquote(lastch(value)) || strlen(value) < 2) {
  153.                   fprintf(stderr, "\nParse error: string value expected at line %d of configuration file.\n", l);
  154.                   return -1;    /* parse aborted */
  155.                 }
  156.                 else {
  157.                   /* remove the (") quotes */
  158.                   value++;
  159.                   lastch(value) = '\0';
  160.                   strcpy((unsigned char *) vars[i].var, value);
  161.         }
  162.                 break;
  163.               case VAL_BOOL:
  164.                 if (!strcasecmp(value, "ON"))
  165.                   *((bool *) vars[i].var) = TRUE;
  166.                 else if (!strcasecmp(value, "OFF"))
  167.                   *((bool *) vars[i].var) = FALSE;
  168.                 else {
  169.                   fprintf(stderr, "\nParse error: boolean value expected at line %d of configuration file.\n", l);
  170.                   return -1;    /* parse aborted */
  171.                 }
  172.                 break;
  173.               case VAL_ATTR:
  174.                 if (str_to_attr(value, &fg, &bg, &hl) == -1) {
  175.                   fprintf(stderr, "\nParse error: attribute value expected at line %d of configuration file.\n", l);
  176.                   return -1;    /* parse aborted */
  177.                 }
  178.                 ((int *) vars[i].var)[0] = fg;
  179.                 ((int *) vars[i].var)[1] = bg;
  180.                 ((int *) vars[i].var)[2] = hl;
  181.                 break;
  182.             }
  183.           }
  184.           break;
  185.         case LINE_ERROR:
  186.           fprintf(stderr, "\nParse error: syntax error at line %d of configuration file.\n", l);
  187.           return -1;    /* parse aborted */
  188.       }
  189.     }
  190.  
  191.     l++;    /* next line */
  192.   }
  193.  
  194.   fclose(rc_file);
  195.   return 0;    /* parse successful */
  196. }
  197. /* End of parse_rc() */
  198.  
  199.  
  200. /*
  201.  * Convert an attribute to a string representation like this:
  202.  *
  203.  * "(foreground,background,highlight)"
  204.  */
  205. static unsigned char *attr_to_str(int fg, int bg, int hl)
  206. {
  207.   int i;
  208.   static unsigned char str[MAX_LEN+1];
  209.  
  210.   strcpy(str, "(");
  211.   /* foreground */
  212.   for (i = 0; fg != color_names[i].value; i++);
  213.   strcat(str, color_names[i].name);
  214.   strcat(str, ",");
  215.  
  216.   /* background */
  217.   for (i = 0; bg != color_names[i].value; i++);
  218.   strcat(str, color_names[i].name);
  219.  
  220.   /* highlight */
  221.   strcat(str, hl ? ",ON)" : ",OFF)");
  222.  
  223.   return str;
  224. }
  225. /* End of attr_to_str() */
  226.  
  227.  
  228. /*
  229.  * Extract the foreground, background and highlight values from an attribute
  230.  * represented as a string in this form:
  231.  *
  232.  * "(foreground,background,highlight)"
  233.  */
  234. static int str_to_attr(unsigned char *str, int *fg, int *bg, int *hl)
  235. {
  236.   int i = 0, j, get_fg = 1;
  237.   unsigned char tempstr[MAX_LEN+1], *part;
  238.  
  239.   if (str[0] != '(' || lastch(str) != ')')
  240.     return -1;    /* invalid representation */
  241.  
  242.   /* remove the parenthesis */
  243.   strcpy(tempstr, str + 1);
  244.   lastch(tempstr) = '\0';
  245.  
  246.  
  247.   /* get foreground and background */
  248.  
  249.   while (1) {
  250.     /* skip white space before fg/bg string */
  251.     while (whitespace(tempstr[i]) && tempstr[i] != '\0') i++;
  252.     if (tempstr[i] == '\0')
  253.       return -1;    /* invalid representation */
  254.     part = tempstr + i;    /* set 'part' to start of fg/bg string */
  255.  
  256.     /* find end of fg/bg string */
  257.     while(!whitespace(tempstr[i]) && tempstr[i] != ',' && tempstr[i] != '\0') i++;
  258.  
  259.     if (tempstr[i] == '\0')
  260.       return -1;    /* invalid representation */
  261.     else if (whitespace(tempstr[i])) {   /* not yet ',' */
  262.       tempstr[i++] = '\0';
  263.  
  264.       /* skip white space before ',' */
  265.       while(whitespace(tempstr[i]) && tempstr[i] != '\0') i++;
  266.  
  267.       if (tempstr[i] != ',')
  268.         return -1;    /* invalid representation */
  269.     }
  270.  
  271.     tempstr[i++] = '\0';    /* skip the ',' */
  272.     for (j = 0; j < COLOR_COUNT && strcasecmp(part, color_names[j].name); j++);
  273.     if (j == COLOR_COUNT)    /* invalid color name */
  274.       return -1;
  275.     if (get_fg) {
  276.       *fg = color_names[j].value;
  277.       get_fg = 0;    /* next we have to get the background */
  278.     }
  279.     else {
  280.       *bg = color_names[j].value;
  281.       break;
  282.     }
  283.   }   /* got foreground and background */
  284.  
  285.  
  286.   /* get highlight */
  287.  
  288.   /* skip white space before highlight string */
  289.   while (whitespace(tempstr[i]) && tempstr[i] != '\0') i++;
  290.   if (tempstr[i] == '\0')
  291.     return -1;    /* invalid representation */
  292.   part = tempstr + i;    /* set 'part' to start of highlight string */
  293.  
  294.   /* trim trailing white space from highlight string */
  295.   i = strlen(part) - 1;
  296.   while(whitespace(part[i])) i--;
  297.   part[i+1] = '\0';
  298.  
  299.   if (!strcasecmp(part, "ON"))
  300.     *hl = TRUE;
  301.   else if (!strcasecmp(part, "OFF"))
  302.     *hl = FALSE;
  303.   else
  304.     return -1;    /* invalid highlight value */
  305.  
  306.   return 0;
  307. }
  308. /* End of str_to_attr() */
  309.  
  310.  
  311. /*
  312.  * Parse a line in the configuration file
  313.  *
  314.  * Each line is of the form:  "variable = value". On exit, 'var' will contain
  315.  * the variable name, and 'value' will contain the value string.
  316.  *
  317.  * Return values:
  318.  *
  319.  * LINE_BLANK   - line is blank
  320.  * LINE_COMMENT - line is comment
  321.  * LINE_OK      - line is ok
  322.  * LINE_ERROR   - syntax error in line
  323.  */
  324. static int parse_line(unsigned char *line, unsigned char **var, unsigned char **value)
  325. {
  326.   int i = 0;
  327.  
  328.   /* ignore white space at beginning of line */
  329.   while(whitespace(line[i]) && line[i] != '\0') i++;
  330.  
  331.   if (line[i] == '\0')    /* line is blank */
  332.     return LINE_BLANK;
  333.   else if (line[i] == '#')    /* line is comment */
  334.     return LINE_COMMENT;
  335.   else if (line[i] == '=')    /* variables names can't strart with a '=' */
  336.     return LINE_ERROR;
  337.  
  338.   /* set 'var' to variable name */
  339.   *var = line + i++;    /* skip to next character */
  340.  
  341.   /* find end of variable name */
  342.   while(!whitespace(line[i]) && line[i] != '=' && line[i] != '\0') i++;
  343.  
  344.   if (line[i] == '\0')    /* syntax error */
  345.     return LINE_ERROR;
  346.   else if (line[i] == '=')
  347.     line[i++] = '\0';
  348.   else {
  349.     line[i++] = '\0';
  350.  
  351.     /* skip white space before '=' */
  352.     while(whitespace(line[i]) && line[i] != '\0') i++;
  353.  
  354.     if (line[i] != '=')    /* syntax error */
  355.       return LINE_ERROR;
  356.     else
  357.       i++;    /* skip the '=' */
  358.   }
  359.  
  360.   /* skip white space after '=' */
  361.   while(whitespace(line[i]) && line[i] != '\0') i++;
  362.  
  363.   if (line[i] == '\0')
  364.     return LINE_ERROR;
  365.   else
  366.     *value = line + i;    /* set 'value' to value string */
  367.  
  368.   /* trim trailing white space from 'value' */
  369.   i = strlen(*value) - 1;
  370.   while(whitespace((*value)[i])) i--;
  371.   (*value)[i+1] = '\0';
  372.  
  373.   return LINE_OK;    /* no syntax error in line */
  374. }
  375. /* End of parse_line() */
  376.