diff --git a/TODO b/TODO index ba3e087..5e83c87 100644 --- a/TODO +++ b/TODO @@ -2,3 +2,11 @@ - Documentation (Sergey) - Configure - Utilities +- Restrict node names to an XML-compatible subset (in waff-mkdir). +- Add node name checks into lhpc-aff check. +- lhpc-aff operations +--- extract +--- join +--- xml +--- spectrum +--- 3point diff --git a/utils/Makefile b/utils/Makefile index b3912bf..b2ce17d 100644 --- a/utils/Makefile +++ b/utils/Makefile @@ -6,8 +6,10 @@ CFLAGS = -Wall -g program = lhpc-aff headers = util.h \ procs.def + sources = lhpc-aff.c \ - check.c + check.c \ + ls.c all: $(program) diff --git a/utils/check.c b/utils/check.c index 42d858f..eb48fcf 100644 --- a/utils/check.c +++ b/utils/check.c @@ -1,7 +1,174 @@ #include +#include +#include #include #include "util.h" +struct arg { + struct AffReader_s *r; + const char *name; + int result; +}; + +static int verbose = 0; + +static void +check_node(struct AffNode_s *node, void *ptr) +{ + struct arg *arg = ptr; + const struct AffSymbol_s *sym; + enum AffNodeType_e type; + uint32_t size; + + if (node == 0 || arg->result) { + fprintf(stderr, "lhpc-aff: error processing %s: %s\n", + arg->name, aff_reader_errstr(arg->r)); + arg->result = 1; + return; + } + if (aff_node_parent(node) == NULL) { + fprintf(stderr, "lhpc-aff: error processing %s: missing parent\n", + arg->name); + arg->result = 1; + return; + } + if (aff_node_id(node) == (uint64_t)-1) { + fprintf(stderr, "lhpc-aff: error processing %s: unexpected node id\n", + arg->name); + arg->result = 1; + return; + } + sym = aff_node_name(node); + if (sym == 0) { + fprintf(stderr, "lhpc-aff: error processing %s: NULL node name\n", + arg->name); + arg->result = 1; + return; + } + if (aff_symbol_id(sym) == (uint32_t)-1) { + fprintf(stderr, "lhpc-aff: error processing %s: missing symbol ID\n", + arg->name); + arg->result = 1; + return; + } + if (aff_symbol_name(sym) == 0) { + fprintf(stderr, "lhpc-aff: error processing %s: missing symbol name\n", + arg->name); + arg->result = 1; + return; + } + type = aff_node_type(node); + size = aff_node_size(node); + switch (type) { + case affNodeVoid: + break; + case affNodeChar: { + char *ptr = malloc(sizeof (char) * size); + if (ptr == 0) { + fprintf(stderr, "lhpc-aff: not enough memory to check %s\n", + arg->name); + arg->result = 2; + return; + } + if (aff_node_get_char(arg->r, node, ptr, size)) { + fprintf(stderr, "lhpc-aff: error processing %s:" + " char[%d] data access failed\n", + arg->name, size); + arg->result = 1; + } + free(ptr); + break; + } + case affNodeInt: { + uint32_t *ptr = malloc(sizeof (uint32_t) * size); + if (ptr == 0) { + fprintf(stderr, "lhpc-aff: not enough memory to check %s\n", + arg->name); + arg->result = 2; + return; + } + if (aff_node_get_int(arg->r, node, ptr, size)) { + fprintf(stderr, "lhpc-aff: error processing %s:" + " int[%d] data access failed\n", + arg->name, size); + arg->result = 1; + } + free(ptr); + break; + } + case affNodeDouble: { + double *ptr = malloc(sizeof (double) * size); + if (ptr == 0) { + fprintf(stderr, "lhpc-aff: not enough memory to check %s\n", + arg->name); + arg->result = 2; + return; + } + if (aff_node_get_double(arg->r, node, ptr, size)) { + fprintf(stderr, "lhpc-aff: error processing %s:" + " double[%d] data access failed\n", + arg->name, size); + arg->result = 1; + } + free(ptr); + break; + } + case affNodeComplex: { + double _Complex *ptr = malloc(sizeof (double _Complex) * size); + if (ptr == 0) { + fprintf(stderr, "lhpc-aff: not enough memory to check %s\n", + arg->name); + arg->result = 2; + return; + } + if (aff_node_get_complex(arg->r, node, ptr, size)) { + fprintf(stderr, "lhpc-aff: error processing %s:" + " complex[%d] data access failed\n", + arg->name, size); + arg->result = 1; + } + free(ptr); + break; + } + default: + fprintf(stderr, "lhpc-aff: processing %s: unknown node type %d\n", + arg->name, (int)type); + } + aff_node_foreach(node, check_node, arg); +} + +static int +check_file(const char *name) +{ + struct arg arg; + struct AffReader_s *r = aff_reader(name); + const char *status = aff_reader_errstr(r); + int ret = 1; + + if (status != 0) { + fprintf(stderr, "lhpc-aff: failed on %s: %s\n", name, status); + goto end; + } + if (verbose) { + printf("lhpc-aff: file %s opened\n", name); + } + if (aff_reader_check(r)) { + fprintf(stderr, "lhpc-aff: data checksum failed on %s\n", name); + goto end; + } + arg.r = r; + arg.name = name; + arg.result = 0; + check_node(aff_reader_root(r), &arg); + ret = arg.result; + if (verbose && ret == 0) { + printf("lhpc-aff: done processing %s\n", name); + } +end: + aff_reader_close(r); + return ret; +} + void h_check(void) { @@ -15,9 +182,22 @@ int x_check(int argc, char *argv[]) { if (argc < 1) { + error: fprintf(stderr, "usage: lhpc-aff check [-v] file...\n"); return 1; } - printf("WRITE ME XXX\n"); - return 1; /* this is an error code */ + if (strcmp(argv[0], "-v") == 0) { + verbose = 1; + if (argc == 1) + goto error; + argc--; + argv++; + } + for (; argc; argc--, argv++) { + if (check_file(argv[0])) { + fprintf(stderr, "lhpc-aff: checking file %s failed\n", argv[0]); + return 1; + } + } + return 0; } diff --git a/utils/ls.c b/utils/ls.c new file mode 100644 index 0000000..d04f787 --- /dev/null +++ b/utils/ls.c @@ -0,0 +1,264 @@ +#include +#include +#include +#include +#include +#include "util.h" + +static int long_format = 0; +static int recursive = 0; + +struct arg { + struct AffReader_s *r; + const char *fname; + const char *kpath; + struct AffNode_s *root; +}; + +static char * +xstrdup(const char *n) +{ + char *p = malloc(strlen(n) + 1); + if (p == 0) { + fprintf(stderr, "lhpc-aff: non enough memory\n"); + exit(1); + } + strcpy(p, n); + return p; +} + +static void +print_path(const char *fname, + const char *kpath, + struct AffNode_s *root, + struct AffNode_s *node) +{ + const struct AffSymbol_s *sym; + const char *name; + + if (node == root) + return; + sym = aff_node_name(node); + name = aff_symbol_name(sym); + if (node == 0 || sym == 0 || name == 0) { + fprintf(stderr, "lhpc-aff: internal error in print_path()\n"); + exit(1); + } + print_path(fname, kpath, root, aff_node_parent(node)); + printf("/%s", name); +} + +static char * +type_name(enum AffNodeType_e type) +{ + switch (type) { + case affNodeVoid: return "void"; + case affNodeChar: return "char"; + case affNodeInt: return "int"; + case affNodeDouble: return "double"; + case affNodeComplex: return "complex"; + default: + fprintf(stderr, "lhpc-aff: Unknown node type %d\n", type); + exit(1); + } +} + +static void +short_list(struct AffNode_s *node, void *ptr) +{ + const char *name = aff_symbol_name(aff_node_name(node)); + uint32_t size = aff_node_size(node); + enum AffNodeType_e type = aff_node_type(node); + char buffer[128]; + + sprintf(buffer, "%s[%d]", type_name(type), size); + printf(" %-15s %s\n", buffer, name); +} + +static void +do_node(struct AffNode_s *node, void *ptr) +{ + struct arg *arg = ptr; + enum AffNodeType_e type = aff_node_type(node); + uint32_t size = aff_node_size(node); + + if (node == arg->root) + printf("/"); + else { + print_path(arg->fname, arg->kpath, arg->root, node); + } + printf(": %s[%d]\n", type_name(type), size); + if (long_format) { + switch (type) { + case affNodeVoid: + break; + case affNodeChar: { + char *ptr = malloc(sizeof (char) * size); + int i; + if (ptr == 0) { + fprintf(stderr, "lhpc-aff: not enough memory\n"); + exit(1); + } + if (aff_node_get_char(arg->r, node, ptr, size)) { + fprintf(stderr, "lhpc-aff: error getting data\n"); + exit(1); + } + printf(" \""); + for (i = 0; i < size; i++) { + unsigned char p = ptr[i]; + if (p < 32 || p >= 127 || p == '\"' || p == '\\') + printf("\\x%02x", p); + else + printf("%c", p); + } + printf("\"\n"); + free(ptr); + } break; + case affNodeInt: { + uint32_t *ptr = malloc(sizeof (uint32_t) * size); + int i; + if (ptr == 0) { + fprintf(stderr, "lhpc-aff: not enough memory\n"); + exit(1); + } + if (aff_node_get_int(arg->r, node, ptr, size)) { + fprintf(stderr, "lhpc-aff: error getting data\n"); + exit(1); + } + for (i = 0; i < size; i++) + printf(" %5d %11d\n", i, ptr[i]); + free(ptr); + break; + } + case affNodeDouble: { + double *ptr = malloc(sizeof (double) * size); + int i; + if (ptr == 0) { + fprintf(stderr, "lhpc-aff: not enough memory\n"); + exit(1); + } + if (aff_node_get_double(arg->r, node, ptr, size)) { + fprintf(stderr, "lhpc-aff: error getting data\n"); + exit(1); + } + for (i = 0; i < size; i++) + printf(" %5d %24.16e\n", i, ptr[i]); + free(ptr); + break; + } + case affNodeComplex: { + double _Complex *ptr = malloc(sizeof (double _Complex) * size); + int i; + if (ptr == 0) { + fprintf(stderr, "lhpc-aff: not enough memory\n"); + exit(1); + } + if (aff_node_get_complex(arg->r, node, ptr, size)) { + fprintf(stderr, "lhpc-aff: error getting data\n"); + exit(1); + } + for (i = 0; i < size; i++) + printf(" %5d %24.16e %24.16e\n", i, creal(ptr[i]), cimag(ptr[i])); + free(ptr); + break; + } + default: + fprintf(stderr, "lhpc-aff: Internal error: uknown node type %d\n", + type); + exit(1); + } + } + aff_node_foreach(node, short_list, arg); + if (recursive) + aff_node_foreach(node, do_node, arg); +} + +/* We are single threaded now, hence it's ok to use strtok() */ +static int +do_ls(struct AffReader_s *r, const char *name, const char *kp) +{ + char *p = xstrdup(kp); + struct AffNode_s *root = aff_reader_root(r); + struct AffNode_s *node; + struct arg arg; + + /* XXX */ + printf("do_ls(%s)\n", p); + for (node = root, p = strtok(p, "/"); p; p = strtok(NULL, "/")) { + node = aff_reader_chdir(r, node, p); + if (node == 0) { + fprintf(stderr, "lhpc-aff: error accesing %s:%s at %s\n", + name, kp, p); + return 1; + } + } + free(p); + arg.r = r; + arg.fname = name; + arg.kpath = kp; + arg.root = root; + do_node(node, &arg); + return (aff_reader_errstr(r) != 0); +} + +void +h_ls(void) +{ + printf("lphc-aff ls [-lR] aff-file key-path ...\n" + "\tlist the contents of AFF file starting at each key-path.\n" + "\tKey path components are separated by /, as in UNIX paths.\n" + "\tIf -l is given, show data in each component\n" + "\tIf -R is given, descent recursively\n"); +} + +int +x_ls(int argc, char *argv[]) +{ + const char *fname; + struct AffReader_s *r; + const char *status; + int res = 1; + + if (argc < 1) { + error: + fprintf(stderr, "usage: lhpc-aff ls [-lR] aff-file key-path ...\n"); + return 1; + } + for (;argc; argc--, argv++) { + char *p; + if (argv[0][0] != '-') + break; + for (p = &argv[0][1]; *p; p++) { + switch (*p) { + case 'l': long_format = 1; break; + case 'R': recursive = 1; break; + default: goto error; + } + } + } + + if (argc < 1) + goto error; + fname = argv[0]; + r = aff_reader(fname); + if (aff_reader_errstr(r) != 0) + goto end; + if (argc == 1) { + do_ls(r, fname, ""); + } else { + for ( argv++; --argc; argv++) { + if (do_ls(r, fname, argv[0])) + break; + } + } + +end: + status = aff_reader_errstr(r); + aff_reader_close(r); + if (status != 0) { + fprintf(stderr, "lhpc-aff: error opening %s\n", argv[0]); + } else { + res = 0; + } + return res; +} diff --git a/utils/procs.def b/utils/procs.def index b6db3f6..ec127d9 100644 --- a/utils/procs.def +++ b/utils/procs.def @@ -1,3 +1,11 @@ -PROC("help", x_help, h_help, "print this help") -PROC("version", x_version, h_version, "print the version of LHPC AFF") -PROC("check", x_check, h_check, "check aff files integrity") +PROC("help", x_help, h_help, "print this help") +PROC("version", x_version, h_version, "print the version of LHPC AFF") +PROC("check", x_check, h_check, "check aff files integrity") +PROC("ls", x_ls, h_ls, "list the content of the AFF file") +/* +PROC("extract", x_get, h_get, "extract one section from the AFF file") +PROC("join", x_join, h_join, "join input files together") +PROC("xml", x_xml, h_xml, "convert AFF to XML") +PROC("spectrum", x_2point, h_2point, "convert spectrum data into AFF") +PROC("3point", x_3point, h_3point, "convert 3-point data into AFF") +*/