PUBLIC DBnamescheme * DBMakeNamescheme(char const *fmt, ...) { va_list ap; int i, j, k, n, pass, ncspecs, done, saved_narrefs; DBnamescheme *rv = 0; DBfile *dbfile = 0; char const *relpath = 0; /* We have nothing to do for a null or empty format string */ if (fmt == 0 || *fmt == '\0') return 0; /* Start by allocating an empty name scheme */ rv = DBAllocNamescheme(); // set the delimeter character n = 0; while (fmt[n] != '\0') { if (fmt[n] == '%' && fmt[n+1] != '%') break; n++; } if (fmt[n] == '%') // have at least one conversion spec rv->delim = fmt[0]; else rv->delim = '\0'; /* compute length up to max of 4096 of initial segment of fmt representing the printf-style format string. */ n = 1; while (n < 4096 && fmt[n] != '\0' && fmt[n] != rv->delim) n++; if (n == 4096) /* we pick arb. upper bound in length of 4096 */ { DBFreeNamescheme(rv); return 0; } /* grab just the part of fmt that is the printf-style format string */ rv->fmt = STRNDUP(&fmt[1],n-1); rv->fmtlen = n-1; /* In 2 passes, count conversion specs. and then setup pointers to each */ for (pass = 0; pass < 2; pass++) { if (pass == 1) { rv->fmtptrs = (const char **) calloc(rv->ncspecs+1, sizeof(char*)); rv->ncspecs = 0; } for (i = 0; i < rv->fmtlen-1; i++) { if (rv->fmt[i] == '%' && rv->fmt[i+1] != '%') { if (pass == 1) rv->fmtptrs[rv->ncspecs] = &(rv->fmt[i]); rv->ncspecs++; } } } rv->fmtptrs[rv->ncspecs] = &(rv->fmt[n+1]); /* If there are no conversion specs., we have nothing to do */ /* However, in this case, assume the first char is a real char. */ if (rv->ncspecs == 0) { free(rv->fmt); rv->fmt = STRNDUP(&fmt[0],n); rv->fmtlen = n; return rv; } /* Make a pass through rest of fmt string to count array refs in the expression substrings. */ i = n+1; while (i < 4096 && fmt[i] != '\0') { if (fmt[i] == '$' || fmt[i] == '#') rv->narrefs++; i++; } if (i == 4096) { DBFreeNamescheme(rv); return 0; } /* allocate various arrays needed by the naming scheme */ rv->exprstrs = (char **) calloc(rv->ncspecs, sizeof(char*)); if (rv->narrefs > 0) { void *dummy; rv->arrnames = (char **) calloc(rv->narrefs, sizeof(char*)); rv->arrvals = (void **) calloc(rv->narrefs, sizeof(void*)); rv->arrsizes = (int *) calloc(rv->narrefs, sizeof(int)); /* If we have non-zero ext. array references, then we may have the case of '0, DBfile*'. So, check for that now */ va_start(ap, fmt); dummy = va_arg(ap, void *); if (dummy == 0) { dbfile = va_arg(ap, DBfile *); relpath = va_arg(ap, char const *); rv->arralloc = 1; }
PUBLIC DBnamescheme * DBMakeNamescheme(const char *fmt, ...) { va_list ap; int i, j, k, n, pass, ncspecs, done; DBnamescheme *rv = 0; /* We have nothing to do for a null or empty format string */ if (fmt == 0 || *fmt == '\0') return 0; /* Start by allocating an empty name scheme */ rv = DBAllocNamescheme(); /* set the delimeter character */ rv->delim = fmt[0]; /* compute length up to max of 4096 of initial segment of fmt representing the printf-style format string. */ n = 1; while (n < 4096 && fmt[n] != '\0' && fmt[n] != rv->delim) n++; if (n == 4096) /* we pick arb. upper bound in length of 4096 */ { DBFreeNamescheme(rv); return 0; } /* grab just the part of fmt that is the printf-style format string */ rv->fmt = STRNDUP(&fmt[1],n-1); rv->fmtlen = n-1; /* In 2 passes, count conversion specs. and then setup pointers to each */ for (pass = 0; pass < 2; pass++) { if (pass == 1) { rv->fmtptrs = (const char **) calloc(rv->ncspecs+1, sizeof(char*)); rv->ncspecs = 0; } for (i = 0; i < rv->fmtlen-1; i++) { if (rv->fmt[i] == '%' && rv->fmt[i+1] != '%') { if (pass == 1) rv->fmtptrs[rv->ncspecs] = &(rv->fmt[i]); rv->ncspecs++; } } } rv->fmtptrs[rv->ncspecs] = &(rv->fmt[n+1]); /* If there are no conversion specs., we have nothing to do */ if (rv->ncspecs == 0) return rv; /* Make a pass through rest of fmt string to count array refs in the expression substrings. */ i = n+1; while (i < 4096 && fmt[i] != '\0') { if (fmt[i] == '$' || fmt[i] == '#') rv->narrefs++; i++; } if (i == 4096) { DBFreeNamescheme(rv); return 0; } /* allocate various arrays needed by the naming scheme */ rv->exprstrs = (char **) calloc(rv->ncspecs, sizeof(char*)); if (rv->narrefs > 0) { rv->arrnames = (char **) calloc(rv->narrefs, sizeof(char*)); rv->arrvals = (const int **) calloc(rv->narrefs, sizeof(int*)); } /* Ok, now go through rest of fmt string a second time and grab each expression that goes with each conversion spec. Also, handle array refs */ i = n+1; rv->narrefs = 0; ncspecs = 0; va_start(ap, fmt); done = 0; while (!done) { if (fmt[i] == '$' || fmt[i] == '#') { for (j = 1; fmt[i+j] != '['; j++) ; for (k = 0; k < rv->narrefs; k++) { if (strncmp(&fmt[i+1],rv->arrnames[k],j-1) == 0) break; } if (k == rv->narrefs) { rv->arrnames[k] = STRNDUP(&fmt[i+1], j-1); rv->arrvals[k] = va_arg(ap, const int *); rv->narrefs++; } } else if (fmt[i] == rv->delim || fmt[i] == '\0')