// Copyright status: this file is in the public domain. #include #include #include #include #include #include "lx.h" extern const char *__progname; typedef struct bqv BQV; typedef struct qv QV; struct bqv { LX_BOUNDQUARK *v; int a; } ; struct qv { LX_QUARK *v; int a; } ; static LX_DB *db; #define Cisspace(x) isspace((unsigned char)(x)) static void dump_value(const void *data, int len, FILE *to, int dq) { const unsigned char *dp; unsigned char c; int i; dp = data; for (i=0;i 126) && (c < 160))) { if ((i+1 < len) && (dp[i+1] >= '0') && (dp[i+1] <= '9')) { fprintf(to,"\\%03o",c); } else { fprintf(to,"\\%o",c); } } else { putc(c,to); } break; } } } static void print_value(const void *data, int len) { putchar('"'); dump_value(data,len,stdout,1); putchar('"'); } static int dump_db_1(void *cookie __attribute__((__unused__)), const LX_BOUNDQUARK *bqv, int nbq, const LX_DBVAL *val) { int i; for (i=0;is,val->l,stdout,0); putchar('\n'); return(0); } static void dump_db(LX_DB *db) { lx_db_map(db,&dump_db_1,0); } #if 0 static void load_sample_file(void) { char *home; char *path; int fd; struct stat stb; void *mmrv; int len; #if 0 home = getenv("HOME"); if (! home) { fprintf(stderr,"%s: no $HOME\n",__progname); return; } asprintf(&path,"%s/.Xdefaults",home); #else home = 0; (void)home; asprintf(&path,"test-defaults"); #endif do { fd = open(path,O_RDONLY,0); if (fd < 0) { fprintf(stderr,"%s: open %s: %s\n",__progname,path,strerror(errno)); break; } do { if (fstat(fd,&stb) < 0) { fprintf(stderr,"%s: fstat %s: %s\n",__progname,path,strerror(errno)); break; } len = stb.st_size; if (len != stb.st_size) { fprintf(stderr,"%s: %s: too large\n",__progname,path); break; } mmrv = mmap(0,len,PROT_READ,MAP_FILE|MAP_SHARED,fd,0); if (mmrv == MAP_FAILED) { fprintf(stderr,"%s: mmap %s: %s\n",__progname,path,strerror(errno)); break; } db = lx_db_from_string(mmrv,len,0); printf("--------\n"); dump_db(db); munmap(mmrv,len); } while (0); close(fd); } while (0); free(path); } #endif static void cmd_add(const char *arg, int arglen) { LX_DB *db2; int err; err = -1; db2 = lx_db_from_string(arg,arglen,LX_DB_ERR_COUNT,&err); if (! db2) { printf("add: error parsing string\n"); return; } lx_db_merge(db,db2); lx_db_done(db2); } static int arg_to_bqv(const char *arg, int arglen, BQV *v) { int e; int n; n = lx_rm_bq_string(arg,arglen,v->v,v->a); if (n < 1) return(-1); if (n+1 > v->a) { free(v->v); v->a = n + 1; v->v = malloc(v->a*sizeof(LX_BOUNDQUARK)); e = lx_rm_bq_string(arg,arglen,v->v,v->a); if (e != n) abort(); } return(n); } static int arg_to_qv(const char *arg, int arglen, QV *v) { int e; int n; n = lx_rm_q_string(arg,arglen,v->v,v->a); if (n < 1) return(-1); if (n+1 > v->a) { free(v->v); v->a = n + 1; v->v = malloc(v->a*sizeof(LX_QUARK)); e = lx_rm_q_string(arg,arglen,v->v,v->a); if (e != n) abort(); } return(n); } static void cmd_del(const char *arg, int arglen) { int n; int e; static BQV bq; n = arg_to_bqv(arg,arglen,&bq); if (n < 1) { printf("del: invalid name\n"); return; } e = lx_db_putq(db,bq.v,n,0,0,LX_DB_PUTQ_DELETE); switch (e) { case -1: printf("Impossible error from lx_db_putq(LX_DB_PUTQ_DELETE)\n"); break; case 0: printf("Not found\n"); break; case 1: printf("Deleted\n"); break; default: printf("Impossible return %d from lx_db_putq(LX_DB_PUTQ_DELETE)\n",e); break; } } static void cmd_dump(const char *arg __attribute__((__unused__)), int arglen) { if (arglen) { printf("dump: takes no args\n"); return; } dump_db(db); } static void cmd_file(const char *arg, int arglen __attribute__((__unused__))) { LX_DB *db2; int ec; ec = -1; db2 = lx_db_from_file(arg,LX_DB_IGNORE_ERR|LX_DB_ERR_COUNT,&ec); if (! db2) { printf("file: %s: error reading file\n",arg); return; } if (ec > 0) { printf("file: warning: %s: error count %d\n",arg,ec); } lx_db_merge(db,db2); lx_db_done(db2); } static void cmd_find(const char *arg, int arglen) { int n; static BQV bq; LX_DBVAL v; n = arg_to_bqv(arg,arglen,&bq); if (n < 1) { printf("find: invalid name\n"); return; } v = lx_db_getq(db,bq.v,n); if (v.l < 0) { printf("Not found\n"); } else { printf("Found, value = "); print_value(v.s,v.l); printf("\n"); } } static void cmd_clear(const char *arg __attribute__((__unused__)), int arglen) { if (arglen) { printf("clear: takes no args\n"); return; } lx_db_done(db); db = lx_db_new(); } static void cmd_query(const char *arg, int arglen) { int x; int n0; int nl; int c0; int cl; int nn; int cn; static QV name; static QV class; LX_DBVAL v; for (x=0;(x 0) && (line[0] == '?')) { printf("\ ?\n\ Print this help\n\ add \n\ Add a single resource line\n\ del \n\ Delete a resource entry\n\ dump\n\ Dump out all database entries\n\ file \n\ Load from , adding each resource line.\n\ find \n\ Look for a resource entry\n\ query \n\ Query for a resource\n\ clear\n\ Empty out the db\n\ `find' looks up exact matches; `query' does resource-manager matching.\n\ "); return; } for (i=0;(i (1) { es_clear(&iline); printf("> "); while (1) { c = getchar(); if (c == EOF) { es_done(&iline); exit(0); } if (c == '\n') { es_append_1(&iline,'\0'); command_line(es_buf(&iline),es_len(&iline)-1); es_clear(&iline); continue <"cmds">; } es_append_1(&iline,c); } } }