/* * FILE: cfg.c * PURPOSE: handling of MTPK.CFG configuration file * VERSION: 1.0 (Nov. 1995) * AUTHOR: Piet Tutelaers */ #include /* isspace(), isalpha() */ #include /* fgets(), sprintf() */ #include /* getenv() */ #include /* strcmp(), strlen(), strchr(), strncpy() */ #include "basics.h" /* fatal(), (*pfopen)() */ #include "psearch.h" /* search_file() */ /* string space */ #define MAXPOOLLEN 1024 static char pool[MAXPOOLLEN]; static char *pfree = pool; static int left = MAXPOOLLEN; /* where we store variable names and there values (expressions) */ #define MAXITEMS 32 static int items = 0; static char *var[MAXITEMS], *expr[MAXITEMS]; /* determine expression via simple linear search */ static char *value(char *name, int start) { int i; char *xres = NULL; for (i = items -1; i >= start; i--) { if (strcmp(var[i], name) == 0) return expr[i]; if (strcmp(var[i], "xres") == 0) xres = expr[i]; } if (xres && strcmp(name, "res") == 0) return xres; return NULL; } /* line buffer */ static char line[MAXSTRLEN]; static char *pline; static int count = 0; static char *nextname() { char *dest; dest = pfree; while (isspace(*pline)) pline++; while (isalpha(*pline)) { *pfree++ = *pline++; left--; if (left == 0) fatal("Out of pool space\n"); } if (dest == pfree) fatal("Invalid name in line %d\n", count); *pfree++ = '\0'; left--; return dest; } static char *nextexpression(char *expr) { char *dest, name[MAXSTRLEN], *pexpr; int i, n; dest = pfree; while (isspace(*expr)) expr++; while (*expr != '\0' && *expr != '\n') { if (*expr == '$') { /* UNIX style expressions */ expr++; if (*expr == '(' || *expr == '{') expr++; for (i = 0; isalpha(*expr); ) name[i++] = *expr++; name[i] = '\0'; pexpr = getenv(name); if (pexpr == NULL) pexpr = value(name, 0); if (pexpr == NULL) { /* filled in later */ n = strlen(name)+3; if (n > left) fatal("Out of pool space\n"); sprintf(pfree, "${%s}", name); left-=n; pfree+=n; if (*expr == ')' || *expr == '}') expr++; continue; } else { n = strlen(pexpr); if (n > left) fatal("Out of pool space\n"); strncpy(pfree, pexpr, n); left-=n; pfree+=n; if (*expr == ')' || *expr == '}') expr++; continue; } } if (*expr == '%') { /* MSDOS style expressions */ char *p = expr; expr++; for (i = 0; isalpha(*expr); i++) name[i] = *expr++; name[i] = '\0'; pexpr = getenv(name); if (pexpr == NULL) pexpr = value(name, 0); if (*expr == '%' && pexpr == NULL) { /* filled in later */ n = strlen(name)+2; if (n > left) fatal("Out of pool space\n"); sprintf(pfree, "%%%s%%", name); left-=n; pfree+=n; expr++; continue; } else if (pexpr == NULL && strcmp(name, "b")==0) { n = 6; if (n > left) fatal("Out of pool space\n"); sprintf(pfree, "${res}"); left-=n; pfree+=n; continue; } else if (pexpr == NULL && strcmp(name, "m")==0) { n = 7; if (n > left) fatal("Out of pool space\n"); sprintf(pfree, "${mode}"); left-=n; pfree+=n; continue; } else if (pexpr == NULL) expr = p; else { n = strlen(pexpr); if (n > left) fatal("Out of pool space\n"); strncpy(pfree, pexpr, n); left-=n; pfree+=n; expr++; continue; } } *pfree++ = *expr++; if (left == 0) fatal("Out of pool space\n"); } /* get rid of spaces at the end */ while (isspace(*(pfree-1))) { pfree--; left++; } if (*(pfree-1) == '\0') fatal("empty expression in line %d\n", count); *pfree++ = '\0'; left--; return dest; } /* Determine mtpk.cfg values for and . Return zero * if the requested values are found otherwise non-zero. */ int read_cfg(char *res, char *mode) { char *p, *r, *m, mtpkcfg[80]; FILE *CFG; int i; char *section_free; int section_count, section_start, section_left; p = MTPKCFG; for (i=0; i < 80 && *(p+i) != '@' && *(p+i) != '\0'; i++) { mtpkcfg[i] = *(p+i); } mtpkcfg[i] = '\0'; CFG = pfopen(mtpkcfg, "r"); if (CFG == NULL) fatal("%s: can not open\n", mtpkcfg); while (fgets(line, MAXSTRLEN, CFG)) { pline = line; count++; if (*pline == '#' || *pline == '\n') continue; if (p = strchr(pline, '#')) *p = '\n'; if (*pline == '[') { /* Check if we are finished */ r = value("res", 0); m = value("mode", 0); if (r != NULL && m != NULL) { if (res == NULL && mode == NULL) return 0; if (mode == NULL && strcmp(res, r) == 0) return 0; if (res == NULL && strcmp(mode, m) == 0) return 0; if (res && mode && strcmp(res, r)==0 && strcmp(mode, m)==0) return 0; } /* Not yet */ section_count = count; section_start = items; section_free = pfree; section_left = left; pline++; while (*pline != '\n' && isspace(*pline)) pline++; if (*pline == '\n') continue; } else if (*pline == ']') { if ((r = value("res", section_start)) == NULL) fatal("no definition of res between lines %d and %d\n", section_count, count); if ((m = value("mode", section_start)) == NULL) fatal("no definition of mode between lines %d and %d\n", section_count, count); /* Check if we are finished */ if (res == NULL && mode == NULL) return 0; if (mode == NULL && strcmp(res, r) == 0) return 0; if (res == NULL && strcmp(mode, m) == 0) return 0; if (res && mode && strcmp(res, r)==0 && strcmp(mode, m)== 0) return 0; items = section_start; pfree = section_free; left = section_left; continue; } /* process variable = expression */ var[items] = nextname(); while (isspace(*pline)) pline++; if (*pline != '=') fatal("Expected '=' in line %d\n", count); pline++; if (items == MAXITEMS) fatal("Table overflow (MAXITEMS = %d)\n", MAXITEMS); expr[items] = nextexpression(pline); items++; } fclose(CFG); return 1; } /* provide a function to query names */ char *cfg_value(char *variable) { char *v; v = value(variable, 0); if (v == NULL) return NULL; if (strchr(v, '$')) { /* evaluate */ v = nextexpression(v); if (strchr(v, '$')) fatal("%s = %s: can not evaluate\n", variable, v); return v; } else return v; }