]> mj.ucw.cz Git - libucw.git/commitdiff
written parsing config files and command line parameters, untested yet
authorRobert Spalek <robert@ucw.cz>
Sun, 7 Jan 2001 21:21:53 +0000 (21:21 +0000)
committerRobert Spalek <robert@ucw.cz>
Sun, 7 Jan 2001 21:21:53 +0000 (21:21 +0000)
lib/Makefile
lib/conf.c [new file with mode: 0644]
lib/conf.h [new file with mode: 0644]

index fc2dd56e930a5dd0498420096fbf3b69c93193c9..e5ac2881a20bb3238101c1409e9d4b554293d347 100644 (file)
@@ -6,7 +6,7 @@ PROGS+=obj/lib/db-test obj/lib/db-rebuild obj/lib/buckettool
 SHLIB_OBJS=alloc.o alloc_str.o ctmatch.o db.o fastbuf.o fb-file.o fb-mem.o lists.o \
        log.o log2.o md5.o md5hex.o mmap.o pagecache.o patimatch.o patmatch.o pool.o \
        prime.o random.o realloc.o regex.o temp.o timer.o url.o wildmatch.o \
-       wordsplit.o str_ctype.o str_upper.o bucket.o
+       wordsplit.o str_ctype.o str_upper.o bucket.o conf.o
 
 obj/lib/libsh.a: $(addprefix obj/lib/,$(SHLIB_OBJS))
 
diff --git a/lib/conf.c b/lib/conf.c
new file mode 100644 (file)
index 0000000..aa67451
--- /dev/null
@@ -0,0 +1,245 @@
+/* Reading conf files
+ * Robert Spalek, (c) 2001, robert@ucw.cz
+ * $Id: conf.c,v 1.1 2001/01/07 21:21:53 robert Exp $
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <fcntl.h>
+#include <getopt.h>
+
+#include "lib/lib.h"
+#include "lib/fastbuf.h"
+
+#include "lib/conf.h"
+
+#define        BUFFER          1024
+#define        MAX_LEVEL       8
+
+#define        MAX_SECTIONS    64
+
+static struct {
+       byte *section;
+       struct cfitem *items;
+} cfsection[MAX_SECTIONS];
+static int cfsections;
+
+#define        MAX_SHORT_OPTS  128
+#define        MAX_LONG_OPTS   64
+
+static byte shortopts[MAX_SHORT_OPTS] = "S:C:";
+static int shortlen=4;
+
+static struct option longopts[MAX_LONG_OPTS] =
+{
+       {"set",         1, 0, 'S'},
+       {"config",      1, 0, 'C'}
+};
+static int longlen=2;
+
+void cf_register(byte *section,struct cfitem *items)
+{
+       if(cfsections>=MAX_SECTIONS)
+               die("too many modules %d",cfsections);
+       cfsection[cfsections].section=section;
+       cfsection[cfsections].items=items;
+       cfsections++;
+}
+
+static byte *cf_set_item(byte *sect, byte *name, byte *value)
+{
+       int idsect;
+       struct cfitem *item;
+       byte *msg=NULL;
+
+       idsect=0;
+       while(idsect<cfsections && strcasecmp(sect,cfsection[idsect].section))
+               idsect++;
+       if(idsect>=cfsections)  /* ignore unknown section */
+               return NULL;
+
+       item=cfsection[idsect].items;
+       while(item->type && strcasecmp(name,item->name))
+               item++;
+       switch(item->type){
+               case ct_int:
+                       {
+                               char *end;
+                               *((uns *) item->var) = strtoul(value, &end, 0);
+                               if (end && *end)
+                                       msg = "Invalid number";
+                               break;
+                       }
+               case ct_string:
+                       *((byte **) item->var) = stralloc(value);
+                       break;
+               case ct_function:
+                       msg = ((ci_func) item->var)(item, value);
+                       break;
+               default:
+                       msg = "Unknown keyword";
+                       break;
+       }
+
+       return msg;
+}
+
+static int cf_subread(byte *filename,int level)
+{
+       struct fastbuf *b;
+       byte def_section[BUFFER];
+       int line;
+       byte *msg=NULL;
+
+       if(level>=MAX_LEVEL){
+               log("Too many nested files %d",level);
+               return 0;
+       }
+               
+       b=bopen(filename,O_RDONLY,4096);
+       if(!b){
+               log("Cannot open file %s",filename);
+               return 0;
+       }
+
+       def_section[0]=0;
+       line=0;
+       while(1){
+               byte buf[BUFFER];
+               byte *c;
+
+               if(!bgets(b,buf,BUFFER))
+                       break;
+
+               c=buf;
+               while(*c && isspace(*c))
+                       c++;
+               if(!*c || *c=='#')
+                       continue;
+
+               if(*c=='['){
+                       strcpy(def_section,c+1);
+                       c=strchr(def_section,']');
+                       if(c)
+                               *c=0;
+                       else{
+                               msg="Missing ]";
+                               break;
+                       }
+
+               }else if(*c='<'){
+                       if(!cf_subread(c+1,level+1)){
+                               msg="";
+                               break;
+                       }
+               
+               }else{
+                       byte *sect,*name,*value;
+
+                       name=c;
+                       c=strpbrk(c," \t");
+                       while(c && *c && isspace(*c))
+                               c++;
+                       if(!c || !*c){
+                               msg="Missing argument";
+                               break;
+                       }
+                       value=c;
+
+                       c=strchr(name,'.');
+                       if(!c)
+                               sect=def_section;
+                       else{
+                               sect=name;
+                               *c++=0;
+                               name=c;
+                       }
+
+                       msg=cf_set_item(sect,name,value);
+                       if(msg)
+                               break;
+               }
+
+       }       /* for every line */
+
+       if(msg)
+               log("%s, line %d: %s",msg);
+       bclose(b);
+       return !msg;
+}
+
+int cf_read(byte *filename)
+{
+       return cf_subread(filename,0);
+}
+
+void cf_read_err(byte *filename)
+{
+       if(!cf_read(filename))
+               die("Reading config file %s failed",filename);
+}
+
+void cf_register_opts(byte *so,struct option *lo)
+{
+       int l;
+
+       l=strlen(so);
+       if(shortlen+l>=MAX_SHORT_OPTS)
+               die("Too many short options %d",shortlen+l);
+       strcat(shortopts,so);
+
+       l=longlen;
+       while(lo->name){
+               if(l>=MAX_LONG_OPTS)
+                       die("Too many long options %d",l);
+               longopts[l++]=*lo++;
+       }
+}
+
+int cf_getopt(int argc,char * const argv[], int *longindex)
+{
+       int res;
+
+       do{
+               res=getopt_long(argc,argv,shortopts,longopts,longindex);
+               if(res=='S'){
+                       byte *sect,*name,*value;
+                       byte *c;
+                       byte *msg=NULL;
+
+
+                       name=optarg;
+                       c=strchr(name,'=');
+                       if(!c){
+                               msg="Missing argument";
+                               sect=value="";
+                       }else{
+                               *c++=0;
+                               value=c;
+
+                               c=strchr(name,'.');
+                               if(!c)
+                                       sect="";
+                               else{
+                                       sect=name;
+                                       *c++=0;
+                                       name=c;
+                               }
+
+                               msg=cf_set_item(sect,name,value);
+                       }
+                       if(msg)
+                               die("Invalid command line argument %s.%s=%s: %s",sect,name,value,msg);
+
+               }else if(res=='C'){
+                       cf_read_err(optarg);
+
+               }else{  /* unhandled option */
+                       return res;
+               }
+
+       }while(1);
+}
+
diff --git a/lib/conf.h b/lib/conf.h
new file mode 100644 (file)
index 0000000..015ff0c
--- /dev/null
@@ -0,0 +1,22 @@
+/* Reading conf files
+ * Robert Spalek, (c) 2001, robert@ucw.cz
+ * $Id: conf.h,v 1.1 2001/01/07 21:21:53 robert Exp $
+ */
+
+enum cftype { ct_stop, ct_int, ct_string, ct_function };
+
+struct cfitem {
+       byte *name;
+       enum cftype type;
+       void *var;
+};
+
+typedef byte *(*ci_func)(struct cfitem *, byte *);
+
+void cf_register(byte *section,struct cfitem *items);
+void cf_register_opts(byte *so,struct option *lo);
+
+int cf_read(byte *filename);
+void cf_read_err(byte *filename);
+int cf_getopt(int argc,char * const argv[], int *longindex);
+