diff options
author | Jesse Morgan <jesse@jesterpm.net> | 2016-12-17 21:28:53 -0800 |
---|---|---|
committer | Jesse Morgan <jesse@jesterpm.net> | 2016-12-17 21:28:53 -0800 |
commit | 54df2afaa61c6a03cbb4a33c9b90fa572b6d07b8 (patch) | |
tree | 18147b92b969d25ffbe61935fb63035cac820dd0 /db-4.8.30/dist/api_flags.c |
Berkeley DB 4.8 with rust build script for linux.
Diffstat (limited to 'db-4.8.30/dist/api_flags.c')
-rw-r--r-- | db-4.8.30/dist/api_flags.c | 444 |
1 files changed, 444 insertions, 0 deletions
diff --git a/db-4.8.30/dist/api_flags.c b/db-4.8.30/dist/api_flags.c new file mode 100644 index 0000000..c0d3317 --- /dev/null +++ b/db-4.8.30/dist/api_flags.c @@ -0,0 +1,444 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1996-2009 Oracle. All rights reserved. + */ + +#include <sys/types.h> + +#include <ctype.h> +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +typedef struct { + char *name; /* API name */ + + u_int used_mask; /* Bits used. */ +} API; +API **api_list, **api_end; + +typedef struct { + char *name; /* Flag name */ + + int api_cnt; /* APIs that use this flag. */ + API **api, **api_end; + + u_int value; /* Bit value */ +} FLAG; +FLAG **flag_list, **flag_end; + +int verbose; +char *progname; + +int add_entry(char *, char *); +void define_print(char *, u_int); +void dump_api(void); +void dump_flags(void); +int flag_cmp_alpha(const void *, const void *); +int flag_cmp_api_cnt(const void *, const void *); +int generate_flags(void); +int parse(void); +void print_api_mask(void); +void print_api_remainder(void); +void print_flag_value(void); +int syserr(void); +int usage(void); + +int +main(int argc, char *argv[]) +{ + enum { API_MASK, API_REMAINDER, FLAG_VALUE } output; + int ch; + + if ((progname = strrchr(argv[0], '/')) == NULL) + progname = argv[0]; + else + ++progname; + + output = FLAG_VALUE; + while ((ch = getopt(argc, argv, "mrv")) != EOF) + switch (ch) { + case 'm': + output = API_MASK; + break; + case 'r': + output = API_REMAINDER; + break; + case 'v': + verbose = 1; + break; + case '?': + default: + return (usage()); + } + argc -= optind; + argv += optind; + + if (parse() || generate_flags()) + return (EXIT_FAILURE); + + switch (output) { + case API_MASK: + print_api_mask(); + break; + case API_REMAINDER: + print_api_remainder(); + break; + case FLAG_VALUE: + print_flag_value(); + break; + } + + if (verbose) { + dump_api(); + dump_flags(); + } + + return (EXIT_SUCCESS); +} + +int +parse() +{ + int lc; + char *p, *api, buf[256]; + + api = NULL; + + /* + * Read the method name/flag pairs. + */ + for (lc = 1; fgets(buf, sizeof(buf), stdin) != NULL; ++lc) { + if ((p = strchr(buf, '\n')) != NULL) + *p = '\0'; + else { + fprintf( + stderr, "%s: %d: line too long\n", progname, lc); + return (1); + } + + /* Ignore any empty line or hash mark. */ + if (buf[0] == '\0' || buf[0] == '#') + continue; + + /* + * A line without leading whitespace is an API name, a line + * with leading whitespace is a flag name. + */ + if (isspace(buf[0])) { + if ((p = strtok(buf, " \t")) == NULL || *p == '#') + continue; + + /* A flag without an API makes no sense. */ + if (api == NULL) + goto format; + + /* Enter the pair into the array. */ + if (add_entry(api, p)) + return (1); + } else { + if ((p = strtok(buf, " \t")) == NULL) + continue; + if (api != NULL) + free(api); + if ((api = strdup(p)) == NULL) + return (syserr()); + } + if ((p = strtok(NULL, " \t")) != NULL && *p != '#') + goto format; + } + + return (0); + +format: fprintf(stderr, "%s: format error: line %d\n", progname, lc); + return (1); +} + +int +add_entry(char *api_name, char *flag_name) +{ + FLAG **fpp, *fp; + API **app, *ap, **p; + u_int cnt; + + /* Search for this api's API structure. */ + for (app = api_list; + app != NULL && *app != NULL && app < api_end; ++app) + if (strcmp(api_name, (*app)->name) == 0) + break; + + /* Allocate new space in the API array if necessary. */ + if (app == NULL || app == api_end) { + cnt = app == NULL ? 100 : (u_int)(api_end - api_list) + 100; + if ((api_list = realloc(api_list, sizeof(API *) * cnt)) == NULL) + return (syserr()); + api_end = api_list + cnt; + app = api_list + (cnt - 100); + memset(app, 0, (u_int)(api_end - app) * sizeof(API *)); + } + + /* Allocate a new API structure and fill in the name if necessary. */ + if (*app == NULL && + ((*app = calloc(sizeof(API), 1)) == NULL || + ((*app)->name = strdup(api_name)) == NULL)) + return (syserr()); + + ap = *app; + + /* + * There's a special keyword, "__MASK=<value>" that sets the initial + * flags value for an API, and so prevents those flag bits from being + * chosen for that API's flags. + */ + if (strncmp(flag_name, "__MASK=", sizeof("__MASK=") - 1) == 0) { + ap->used_mask |= + strtoul(flag_name + sizeof("__MASK=") - 1, NULL, 0); + return (0); + } + + /* Search for this flag's FLAG structure. */ + for (fpp = flag_list; + fpp != NULL && *fpp != NULL && fpp < flag_end; ++fpp) + if (strcmp(flag_name, (*fpp)->name) == 0) + break; + + /* Realloc space in the FLAG array if necessary. */ + if (fpp == NULL || fpp == flag_end) { + cnt = fpp == NULL ? 100 : (u_int)(flag_end - flag_list) + 100; + if ((flag_list = + realloc(flag_list, sizeof(FLAG *) * cnt)) == NULL) + return (syserr()); + flag_end = flag_list + cnt; + fpp = flag_list + (cnt - 100); + memset(fpp, 0, (u_int)(flag_end - fpp) * sizeof(FLAG *)); + } + + /* Allocate a new FLAG structure and fill in the name if necessary. */ + if (*fpp == NULL && + ((*fpp = calloc(sizeof(FLAG), 1)) == NULL || + ((*fpp)->name = strdup(flag_name)) == NULL)) + return (syserr()); + + fp = *fpp; + ++fp->api_cnt; + + /* Check to see if this API is already listed for this flag. */ + for (p = fp->api; p != NULL && *p != NULL && p < fp->api_end; ++p) + if (strcmp(api_name, (*p)->name) == 0) { + fprintf(stderr, + "duplicate entry: %s / %s\n", api_name, flag_name); + return (1); + } + + /* Realloc space in the FLAG's API array if necessary. */ + if (p == NULL || p == fp->api_end) { + cnt = p == NULL ? 20 : (u_int)(fp->api_end - fp->api) + 20; + if ((fp->api = realloc(fp->api, sizeof(API *) * cnt)) == NULL) + return (syserr()); + fp->api_end = fp->api + cnt; + p = fp->api + (cnt - 20); + memset(p, 0, (u_int)(fp->api_end - fp->api) * sizeof(API *)); + } + *p = ap; + + return (0); +} + +void +dump_api() +{ + API **app; + + printf("=============================\nAPI:\n"); + for (app = api_list; *app != NULL; ++app) + printf("%s (%#x)\n", (*app)->name, (*app)->used_mask); +} + +void +dump_flags() +{ + FLAG **fpp; + API **api; + char *sep; + + printf("=============================\nFLAGS:\n"); + for (fpp = flag_list; *fpp != NULL; ++fpp) { + printf("%s (%#x, %d): ", + (*fpp)->name, (*fpp)->value, (*fpp)->api_cnt); + sep = ""; + for (api = (*fpp)->api; *api != NULL; ++api) { + printf("%s%s", sep, (*api)->name); + sep = ", "; + } + printf("\n"); + } +} + +int +flag_cmp_api_cnt(const void *a, const void *b) +{ + FLAG *af, *bf; + + af = *(FLAG **)a; + bf = *(FLAG **)b; + + if (af == NULL) { + if (bf == NULL) + return (0); + return (1); + } + if (bf == NULL) { + if (af == NULL) + return (0); + return (-1); + } + if (af->api_cnt > bf->api_cnt) + return (-1); + if (af->api_cnt < bf->api_cnt) + return (1); + return (strcmp(af->name, bf->name)); +} + +int +generate_flags() +{ + FLAG **fpp; + API **api; + u_int mask; + + /* Sort the FLAGS array by reference count, in reverse order. */ + qsort(flag_list, + (u_int)(flag_end - flag_list), sizeof(FLAG *), flag_cmp_api_cnt); + + /* + * Here's the plan: walk the list of flags, allocating bits. For + * each flag, we walk the list of APIs that use it and find a bit + * none of them are using. That bit becomes the flag's value. + */ + for (fpp = flag_list; *fpp != NULL; ++fpp) { + mask = 0xffffffff; /* Set to all 1's */ + for (api = (*fpp)->api; *api != NULL; ++api) + mask &= ~(*api)->used_mask; /* Clear API's bits */ + if (mask == 0) { + fprintf(stderr, "%s: ran out of bits at flag %s\n", + progname, (*fpp)->name); + return (1); + } + (*fpp)->value = mask = 1 << (ffs(mask) - 1); + for (api = (*fpp)->api; *api != NULL; ++api) + (*api)->used_mask |= mask; /* Set bit for API */ + } + + return (0); +} + +int +flag_cmp_alpha(const void *a, const void *b) +{ + FLAG *af, *bf; + + af = *(FLAG **)a; + bf = *(FLAG **)b; + + if (af == NULL) { + if (bf == NULL) + return (0); + return (1); + } + if (bf == NULL) { + if (af == NULL) + return (0); + return (-1); + } + return (strcmp(af->name, bf->name)); +} + +void +print_api_mask() +{ + API **app; + char *p, buf[256]; + + /* Output a mask for the API. */ + for (app = api_list; *app != NULL; ++app) { + (void)snprintf( + buf, sizeof(buf), "_%s_API_MASK", (*app)->name); + for (p = buf; *p != '\0'; ++p) + if (islower(*p)) + *p = toupper(*p); + else if (!isalpha(*p)) + *p = '_'; + define_print(buf, (*app)->used_mask); + } +} + +void +print_api_remainder() +{ + API **app; + int unused, i; + + /* Output the bits remaining for the API. */ + for (app = api_list; *app != NULL; ++app) { + for (i = unused = 0; i < 32; ++i) + if (!((*app)->used_mask & (1 << i))) + ++unused; + printf("%s: %d bits unused\n", (*app)->name, unused); + } +} + +void +print_flag_value() +{ + FLAG **fpp; + + /* Sort the FLAGS array in alphabetical order. */ + qsort(flag_list, + (u_int)(flag_end - flag_list), sizeof(FLAG *), flag_cmp_alpha); + + /* Output each flag's value. */ + for (fpp = flag_list; *fpp != NULL; ++fpp) + define_print((*fpp)->name, (*fpp)->value); +} + +void +define_print(char *name, u_int value) +{ + char *sep; + + switch (strlen(name) / 8) { + case 0: + sep = "\t\t\t\t\t"; + break; + case 1: + sep = "\t\t\t\t"; + break; + case 2: + sep = "\t\t\t"; + break; + case 3: + sep = "\t\t"; + break; + default: + sep = "\t"; + break; + } + printf("#define\t%s%s%#010x\n", name, sep, value); +} + +int +syserr(void) +{ + fprintf(stderr, "%s: %s\n", progname, strerror(errno)); + return (1); +} + +int +usage() +{ + (void)fprintf(stderr, "usage: %s [-mrv]\n", progname); + return (EXIT_FAILURE); +} |