/* This file is in the public domain. */ #include #include #include #include #include "util.h" #include "repo.h" #include "ctype.h" #include "config.h" #include "structs.h" #include "timeint.h" typedef struct sect_repo_priv SECT_REPO_PRIV; struct sect_repo_priv { unsigned int have; /* no HAVE_NAME; the name is on the repo line. */ #define SRP_HAVE_FILENAME 0x00000001 #define SRP_HAVE_TYPE 0x00000002 #define SRP_HAVE_GAP 0x00000004 REPO *r; CONFIG *cfg; } ; static void *sect_repo_start(const char *line, CONFIG *cfg) { int i; SECT_REPO_PRIV *p; int j; int k; i = 0; while (line[i] && UCisspace(line[i])) i ++; if (strncmp(line+i,"repo",4) || (line[i+4] && !UCisspace(line[i+4]))) return(0); i += 4; while (line[i] && UCisspace(line[i])) i ++; if (! line[i]) config_err(cfg,"missing repo name"); j = i; while (line[i] && !UCisspace(line[i])) i ++; k = i; while (line[i] && UCisspace(line[i])) i ++; if (line[i]) config_err(cfg,"space in repo name"); p = malloc(sizeof(SECT_REPO_PRIV)); p->have = 0; p->r = malloc(sizeof(REPO)); p->r->name = blk_to_nulterm(line+j,k-j); p->r->filename = 0; p->r->f = 0; p->cfg = cfg; return(p); } static SPRV sect_repo_parse(void *pv, const char *line) { int i; int j; int k; SECT_REPO_PRIV *p; p = pv; i = 0; while (line[i] && UCisspace(line[i])) i ++; j = i; while (line[i] && !UCisspace(line[i])) i ++; k = i; while (line[i] && UCisspace(line[i])) i ++; if ((k-j == 4) && !bcmp(line+j,"file",4)) { if (p->have & SRP_HAVE_FILENAME) config_err(p->cfg,"extra `file' line in repo"); if (! line[i]) config_err(p->cfg,"missing filename on repo `file' line"); p->r->filename = strdup(line+i); p->have |= SRP_HAVE_FILENAME; return(SPRV_GOOD); } else if ((k-j == 4) && !bcmp(line+j,"type",4)) { if (p->have & SRP_HAVE_TYPE) config_err(p->cfg,"extra `type' line in repo"); if (! line[i]) config_err(p->cfg,"missing type on repo `type' line"); if (!strcmp(line+i,"int")) { p->r->type = DT_INT; } else if (!strcmp(line+i,"float")) { p->r->type = DT_FLOAT; } else { config_err(p->cfg,"bad type on repo `type' line"); } p->have |= SRP_HAVE_TYPE; return(SPRV_GOOD); } else if ((k-j == 3) && !bcmp(line+j,"gap",3)) { auto void err(const char *, ...) __attribute__((__format__(__printf__,1,2))); auto void err(const char *fmt, ...) { char *s; va_list ap; void free_s(void) { free(s); } va_start(ap,fmt); vasprintf(&s,fmt,ap); va_end(ap); config_err_post(&free_s,p->cfg,"%s",s); } if (p->have & SRP_HAVE_GAP) config_err(p->cfg,"extra `gap' line in repo"); if (! line[i]) config_err(p->cfg,"missing time interval on repo `gap' line"); p->r->maxgap = parse_time_interval(line+i,&err); p->have |= SRP_HAVE_GAP; return(SPRV_GOOD); } else { return(SPRV_UNKNOWN); } } static void sect_repo_done(void *pv) { SECT_REPO_PRIV *p; const char *msg; p = pv; switch (p->have & (SRP_HAVE_FILENAME|SRP_HAVE_TYPE|SRP_HAVE_GAP)) { case 0: msg = "incomplete repo spec (no file, type, or gap lines)"; break; case SRP_HAVE_GAP: msg = "incomplete repo spec: no file or type lines)"; break; case SRP_HAVE_TYPE : msg = "incomplete repo spec (no file or gap lines)"; break; case SRP_HAVE_TYPE | SRP_HAVE_GAP: msg = "incomplete repo spec (no file line)"; break; case SRP_HAVE_FILENAME : msg = "incomplete repo spec (no type or gap lines)"; break; case SRP_HAVE_FILENAME | SRP_HAVE_GAP: msg = "incomplete repo spec (no type line)"; break; case SRP_HAVE_FILENAME | SRP_HAVE_TYPE : msg = "incomplete repo spec (no gap line)"; break; case SRP_HAVE_FILENAME | SRP_HAVE_TYPE | SRP_HAVE_GAP: msg = 0; break; } if (msg) { repo_free(p->r); } else { p->r->link = p->cfg->repos; p->cfg->repos = p->r; } free(p); if (msg) config_err(p->cfg,"%s",msg); } const SECT_OPS sectops_repo = SECT_OPS_INIT(repo);