summaryrefslogtreecommitdiff
path: root/db-4.8.30/dist/api_flags.c
diff options
context:
space:
mode:
authorJesse Morgan <jesse@jesterpm.net>2016-12-17 21:28:53 -0800
committerJesse Morgan <jesse@jesterpm.net>2016-12-17 21:28:53 -0800
commit54df2afaa61c6a03cbb4a33c9b90fa572b6d07b8 (patch)
tree18147b92b969d25ffbe61935fb63035cac820dd0 /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.c444
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);
+}