#include <stdio.h>
#include <libmawk.h>
#include "vio_hash.h"
/*
Purpose: register "/dev/foo" to a custion vio that does calculates some
sort of hash from all data written to it.
The hash files are set up in a dynamic manner: a hash is created
when the script opens it. It is possible to have at most 16 hashes.
Run: ./app -f test.awk
*/
/* any hash ever existed will get into this array and won't be freed until
the end of the app. This means if the script writes /dev/hash/3, the value
is preserved even after close("/dev/hash/3"), to allow multiple reads.
The hash value/seed is reset when the file is open for writing. */
mawk_vio_t *vf_hash[16];
mawk_vio_t *dispatch_open(mawk_state_t *MAWK, const char *name, mawk_vio_open_mode_t mode)
{
/* hijack /dev/hash/* for the hash vio */
if (strncmp(name, "/dev/hash/", 10) == 0) {
int idx;
char *end;
idx = strtol(name+10, &end, 10);
if (*end != '\0') {
fprintf(stderr, "Warning: invalid hash %s: hash id not an integer\n", name);
return NULL;
}
if ((idx < 0) || (idx >= 16)) {
fprintf(stderr, "Warning: invalid hash %s: hash id out of range\n", name);
return NULL;
}
/* allocate non-existing hashes or reopen existing ones */
if (vf_hash[idx] == NULL)
vf_hash[idx] = mawk_vio_hash_open(MAWK, name, mode);
else
mawk_vio_hash_reopen(MAWK, vf_hash[idx], mode);
return vf_hash[idx];
}
/* call the original open function for any other name */
return mawk_vio_orig_init.vopen(MAWK, name, mode);
}
void print_all_hashes(mawk_state_t *m, char *banner)
{
int n;
printf("app: %s\n", banner);
for(n = 0; n < 16; n++) {
if (vf_hash[n] != NULL)
printf(" /dev/hash/%d=%d\n", n, mawk_vio_hash_val(m, vf_hash[n]));
}
}
int main(int argc, char **argv)
{
mawk_state_t *m;
/* init a context in stages */
m = libmawk_initialize_stage1(); /* alloc context */
m->vio_init.vopen = dispatch_open;
/* set up all pipes */
mawk_vio_orig_setup_stdio(m, 0, 1, 1); /* whether bind to the app's stdio: 0,1,1=stdin,stdout,stderr */
m = libmawk_initialize_stage2(m, argc, argv); /* set up with CLI arguments */
m = libmawk_initialize_stage3(m); /* execute BEGIN */
if (m == NULL) {
fprintf(stderr, "libmawk_initialize failed, exiting\n");
return 1;
}
print_all_hashes(m, "hash after begin");
/* run END */
libmawk_uninitialize_stage1(m);
print_all_hashes(m, "hash after end");
/* free things */
libmawk_uninitialize_stage2(m);
/* no need to free vf_hash[]:
- uninitialize_stage2 will close all existing files
- final destruction of m will free any allocation left
*/
return 0;
}