image_t *grid_to_image(grid_t *grid) { if (grid == NULL) return NULL; double max; int i, j; int w = grid->pw; int h = grid->ph; image_t *img = make_image(grid->width, grid->height, 3 * w); ERR_NOMEM(img); /* convert double values to char */ grid_max(grid, &max); int interval = get_color_interval((float) max); float interval_inv = get_color_interval_inv((float) max); for (j = 0; j < h; j++) { png_byte *row = img->rows[j]; for (i = 0; i < w; i++) { int index = IX2(i,j,w); int offset = i * 3; struct rgb c; value_color(&c, grid->dbl[index], interval, interval_inv); row[offset + 0] = c.r; row[offset + 1] = c.g; row[offset + 2] = c.b; } } error: return img; }
static struct fa *regexp_to_fa(struct regexp *r) { const char *p = r->pattern->str; int ret; struct fa *fa = NULL; ret = fa_compile(p, strlen(p), &fa); ERR_NOMEM(ret == REG_ESPACE, r->info); BUG_ON(ret != REG_NOERROR, r->info, NULL); if (r->nocase) { ret = fa_nocase(fa); ERR_NOMEM(ret < 0, r->info); } return fa; error: fa_free(fa); return NULL; }
int save_grid_png(grid_t *grid, char *output) { if (grid == NULL || output == NULL) goto error; image_t *img = grid_to_image(grid); ERR_NOMEM(img); return save_image_png(img, output); error: return -1; }
struct regexp * regexp_union_n(struct info *info, int n, struct regexp **r) { size_t len = 0; char *pat = NULL, *p, *expanded = NULL; int nnocase = 0, npresent = 0; int ret; for (int i=0; i < n; i++) if (r[i] != NULL) { len += strlen(r[i]->pattern->str) + strlen("()|"); npresent += 1; if (r[i]->nocase) nnocase += 1; } bool mixedcase = nnocase > 0 && nnocase < npresent; if (len == 0) return NULL; if (ALLOC_N(pat, len) < 0) return NULL; p = pat; int added = 0; for (int i=0; i < n; i++) { if (r[i] == NULL) continue; if (added > 0) *p++ = '|'; *p++ = '('; if (mixedcase && r[i]->nocase) { expanded = regexp_expand_nocase(r[i]); ERR_BAIL(r[i]->info); len += strlen(expanded) - strlen(r[i]->pattern->str); ret = REALLOC_N(pat, len); ERR_NOMEM(ret < 0, info); p = pat + strlen(pat); p = stpcpy(p, expanded); FREE(expanded); } else { p = stpcpy(p, r[i]->pattern->str); } *p++ = ')'; added += 1; } *p = '\0'; return make_regexp(info, pat, nnocase == npresent); error: FREE(expanded); FREE(pat); return NULL; }
char *regexp_expand_nocase(struct regexp *r) { const char *p = r->pattern->str, *t; char *s = NULL; size_t len; int ret; int psub = 0, rsub = 0; if (! r->nocase) return strdup(p); ret = fa_expand_nocase(p, strlen(p), &s, &len); ERR_NOMEM(ret == REG_ESPACE, r->info); BUG_ON(ret != REG_NOERROR, r->info, NULL); /* Make sure that r->pattern->str and ret have the same number * of parentheses/groups, since our parser critically depends * on the fact that the regexp for a union/concat and those * of its children have groups that are in direct relation */ for (t = p; *t; t++) if (*t == '(') psub += 1; for (t = s; *t; t++) if (*t == '(') rsub += 1; BUG_ON(psub < rsub, r->info, NULL); psub -= rsub; if (psub > 0) { char *adjusted = NULL, *a; if (ALLOC_N(adjusted, strlen(s) + 2*psub + 1) < 0) ERR_NOMEM(true, r->info); a = adjusted; for (int i=0; i < psub; i++) *a++ = '('; a = stpcpy(a, s); for (int i=0; i < psub; i++) *a++ = ')'; free(s); s = adjusted; } error: return s; }
char *regexp_expand_nocase(struct regexp *r) { const char *p = r->pattern->str; char *s = NULL; size_t len; int ret; if (! r->nocase) return strdup(p); ret = fa_expand_nocase(p, strlen(p), &s, &len); ERR_NOMEM(ret == REG_ESPACE, r->info); BUG_ON(ret != REG_NOERROR, r->info, NULL); error: return s; }
static char *append_expanded(struct regexp *r, char **pat, char *p, size_t *len) { char *expanded = NULL; size_t ofs = p - *pat; int ret; expanded = regexp_expand_nocase(r); ERR_BAIL(r->info); *len += strlen(expanded) - strlen(r->pattern->str); ret = REALLOC_N(*pat, *len); ERR_NOMEM(ret < 0, r->info); p = stpcpy(*pat + ofs, expanded); error: FREE(expanded); return p; }
/** * Run a command without using the shell. * * return 0 if the command run and exited with 0 status; Otherwise * return -1 * */ int run_program(struct netcf *ncf, const char *const *argv, char **output) { pid_t childpid = -1; int exitstatus, waitret; char *argv_str; int ret = -1; char errbuf[128]; char *outtext = NULL; int outfd = -1; FILE *outfile = NULL; size_t outlen; if (!output) output = &outtext; argv_str = argv_to_string(argv); ERR_NOMEM(argv_str == NULL, ncf); exec_program(ncf, argv, argv_str, &childpid, &outfd); ERR_BAIL(ncf); printf("Attempting to execute %s\n", argv_str); outfile = fdopen(outfd, "r"); ERR_THROW_STRERROR(outfile == NULL,ncf, EEXEC, "Failed to create file stream for output while executing '%s': %s", argv_str, errbuf); *output = fread_file(outfile, &outlen); ERR_THROW_STRERROR(*output == NULL, ncf, EEXEC, "Error while reading output from execution of '%s': %s", argv_str, errbuf); /* finished with the stream. Close it so the child can exit. */ fclose(outfile); outfile = NULL; while ((waitret = waitpid(childpid, &exitstatus, 0) == -1) && errno == EINTR) { /* empty loop */ } ERR_THROW_STRERROR(waitret == -1, ncf, EEXEC, "Failed waiting for completion of '%s': %s", argv_str, errbuf); ERR_THROW(!WIFEXITED(exitstatus) && WIFSIGNALED(exitstatus), ncf, EEXEC, "'%s' terminated by signal: %d", argv_str, WTERMSIG(exitstatus)); ERR_THROW(!WIFEXITED(exitstatus), ncf, EEXEC, "'%s' terminated improperly", argv_str); ERR_THROW(WEXITSTATUS(exitstatus) == EXIT_ENOENT, ncf, EEXEC, "Running '%s' program not found", argv_str); ERR_THROW(WEXITSTATUS(exitstatus) == EXIT_CANNOT_INVOKE, ncf, EEXEC, "Running '%s' program located but not usable", argv_str); ERR_THROW(WEXITSTATUS(exitstatus) == EXIT_SIGMASK, ncf, EEXEC, "Running '%s' failed to reset child process signal mask", argv_str); ERR_THROW(WEXITSTATUS(exitstatus) == EXIT_DUP2, ncf, EEXEC, "Running '%s' failed to dup2 child process stdout/stderr", argv_str); ERR_THROW(WEXITSTATUS(exitstatus) == EXIT_INVALID_IN_THIS_STATE, ncf, EINVALIDOP, "Running '%s' operation is invalid in this state", argv_str); ERR_THROW(WEXITSTATUS(exitstatus) != 0, ncf, EEXEC, "Running '%s' failed with exit code %d: %s", argv_str, WEXITSTATUS(exitstatus), *output); ret = 0; error: if (outfile) fclose(outfile); else if (outfd >= 0) close(outfd); FREE(outtext); FREE(argv_str); return ret; }