home *** CD-ROM | disk | FTP | other *** search
- /*
- config - read graphics device driver configuration file
-
- Config reads command line-like switches from a configuration file.
- Switches may have arguments, but not optional arguments. fname is
- the name of the configuration file. cpath is NULL, or a string
- containing a series of directories (optionally ending with '/' or
- '\\'), separated by semicolons. pp points to an array of
- structures, with one element per legal switch. The array is
- terminated by an element starting with a zero. buf is a work array
- of length bufsize.
-
- In the configuration file, parameters are represented by switches like
- those used on the command line. Switches introduced by '-' specify
- final values of the corresponding parameters. Use '+' rather than
- '-' if the given values are to be defaults only, and the driver is
- to ask the user for the final values. Tokens (switches and parameters)
- are separated by whitespace (spaces, tabs, or newlines). A semicolon
- denotes a comment which extends to the end of the line.
-
- If an illegal switch appears in the file, config prints an error
- message to stderr and exits with an error.
-
- The item pp[i]->ask points to an integer which is set to zero if the
- switch was introduced by '-'. Note that, as in the example below,
- more than one such item may point to the same integer. This can
- be used if two switches are mutually exclusive, and using either
- one should prevent a user query. Either pp[i]->ask or pp[i]->var
- may be NULL. (There would be no point to setting both to NULL,
- since config could then record no information about the switch.)
-
- EXAMPLE...
-
- Typical switches are...
- -p ; portrait orientation
- -l ; landscape orientation
- -o <xoffset> <yoffset> ; offset from top left corner
- -s <xsize> <ysize> ; plot size
- -v <num> ; pen velocity
-
- ...which would be represented by this structure:
-
- PARAM parmv[] = {{'o', REAL, &offset_ask, offsetv, 2},
- {'s', REAL, &size_ask, sizev, 2},
- {'v', REAL, &vel_ask, &vel, 1},
- {'p', BOOLEAN, &orientation_ask, &portrait, 0},
- {'l', BOOLEAN, &orientation_ask, &landscape, 0},
- {'L', STRING, NULL, &plabel, 1},
- {'\0'}};
-
- The configuration file might contain:
- -v 17 ; velocity
- +o 0 1 ; offset (default only)
- -p ; portrait orientation
-
- */
- #include <stdio.h>
- #include <math.h>
- #include <string.h>
- #include "config.h"
-
- static FILE *cfile = stdin;
-
- static char *gettok(char *buf, int bufsize)
- { static char separate[] = " \t\n";
- char *s;
- s = strtok(NULL, separate);
- while(s == NULL)
- {s = fgets(buf, bufsize, cfile);
- if(s == NULL) return NULL;
- s = strchr(buf, ';');
- if(s != NULL) *s = 0; /* zap the comment */
- s = strtok(buf, separate);
- }
- return s;
- }
-
- static cgripe(char *s, char *fname)
- { fprintf(stderr, "illegal parameter %s in configuration file %s\n",
- s, fname);
- exit(1);
- }
-
- config(char *fname, char *cpath, PARAM *pp, char *buf, int bufsize)
- { char c, *s;
- int ask, found, i;
- PARAM *np;
- int *ip;
- double *dp;
- char *cp;
- char **sp;
-
- if(fname == NULL) return;
- buf[0] = 0;
- while(1)
- {strncat(buf, fname, bufsize - strlen(fname) - 2);
- cfile = fopen(buf, "r");
- if(cfile != NULL) break; /* found configuration file */
- if(cpath == NULL || *cpath == 0)
- return; /* no configuration file */
- for (i = 0; *cpath && *cpath != ';'; i++)
- buf[i] = *cpath++;
- if(*cpath) cpath++; /* step past the ';' */
- if(i > 0)
- {c = buf[i-1];
- if(c != ':' && c != '\\' && c != '/')
- buf[i++] = '/'; /* append '/' to path */
- }
- buf[i] = 0;
- }
- strtok("", " "); /* force initial read from file */
-
- while((s = gettok(buf, bufsize)) != NULL)
- {switch(s[0])
- {case '-': ask = 0; break;
- case '+': ask = 1; break;
- default: cgripe(s, fname);
- }
- for (np = pp, found = 0; np->flag; np++)
- {if(s[1] != np->flag) continue;
- if(np->var == NULL) continue;
- found = 1;
- if(np->ask != NULL) *np->ask = ask;
- if((np->type == BOOLEAN) && (np->nvar == 0))
- {ip = (int *)np->var;
- *ip = (int)(s[2] != '-');
- }
- ip = (int *)np->var;
- dp = (double *)np->var;
- cp = (char *)np->var;
- sp = (char **)np->var;
- for (i = 0; i < np->nvar ; i++)
- {s = gettok(buf, bufsize);
- if(s == NULL) return;
-
- switch(np->type)
- {case BOOLEAN: ip[i] = atoi(s); break;
- case CHARACTER: cp[i] = s[0]; break;
- case STRING: sp[i] = strdup(s); break;
- case REAL: dp[i] = atof(s);
- }
- }
- break;
- }
- if(!found) cgripe(s, fname);
- }
- }
-
- #ifdef MAIN
-
- int offset_doubt = 1;
- int size_doubt = 1;
- int vel_doubt = 1;
- int orientation_doubt = 1;
- int do_doubt = 1;
-
- double offsetv[2] = {2.,1.}, sizev[2] = {6.,3.}, vel = 12.;
- int portrait = 0, landscape = 0;
- char *plabel = "default_string";
-
- PARAM parmv[] = {{'o', REAL, &offset_doubt, offsetv, 2},
- {'s', REAL, &size_doubt, sizev, 2},
- {'v', REAL, &vel_doubt, &vel, 1},
- {'p', BOOLEAN, &orientation_doubt, &portrait, 0},
- {'l', BOOLEAN, &orientation_doubt, &landscape, 0},
- {'L', STRING, NULL, &plabel, 1},
- {'\0'}};
-
- char buf[80];
- main()
- { PARAM *pp;
- int i;
-
- printf("about to read file...\n");
-
- config("TEST.CFG", ";d:\\bin/", parmv, buf, 80);
-
- printf("file read\n");
-
- for (pp = parmv; pp->flag; pp++)
- {printf("%c: %10s\n", pp->flag, pp->ask[0]?"asking":"not asking");
- for (i = 0; i < pp->nvar; i++)
- switch(pp->type)
- {case REAL: printf("\t\t%f\n", ((double *)pp->var)[i]); break;
- case BOOLEAN: printf("\t\t%d\n", ((int *)pp->var)[i]); break;
- case STRING: printf("\t\t%s\n", ((char **)pp->var)[i]); break;
- case CHARACTER: printf("\t\t%c\n", ((char *)pp->var)[i]); break;
- }
- }
- printf("structure printed\n");
- printf("portrait = %d\n", portrait);
- printf("landscape = %d\n", landscape);
- }
-
-
- #endif /* MAIN */
-