From 03b2b8652e3da962eebaa4acef67dc6e25a97fbd Mon Sep 17 00:00:00 2001 From: stefan schippers Date: Wed, 18 Jan 2023 00:24:28 +0100 Subject: [PATCH] fixed filter_data routine that was clobbering ps export file, now ps output is correct without the need to add fflush() functions, that are thus removed in psprint.c --- src/psprint.c | 27 +++++++--------------- src/save.c | 60 +++++++++++++++++++++++++++++++++++++------------ src/scheduler.c | 14 +++++++++++- src/xschem.h | 1 + 4 files changed, 68 insertions(+), 34 deletions(-) diff --git a/src/psprint.c b/src/psprint.c index 73a84363..8ac7f4fb 100644 --- a/src/psprint.c +++ b/src/psprint.c @@ -24,9 +24,6 @@ #define X_TO_PS(x) ( (x+xctx->xorigin)* xctx->mooz ) #define Y_TO_PS(y) ( (y+xctx->yorigin)* xctx->mooz ) -/* FIXME This must be investigated, without some fflushes the ps file is corrupted */ -#define FFLUSH_PS - #if 0 * /* FIXME: overflow check. Not used, BTW */ * static char *strreplace(char s[], char token[], char replace[]) @@ -129,24 +126,24 @@ unsigned char* bin2hex(const unsigned char* bin, size_t len) void ps_drawPNG(xRect* r, double x1, double y1, double x2, double y2, int rot, int flip) { int i; - size_t data_size; - png_to_byte_closure_t closure; + size_t data_size = 0; + png_to_byte_closure_t closure = {NULL, 0, 0}; char* filter = NULL; int png_size_x, png_size_y; - unsigned char *png_data, BG_r, BG_g, BG_b; + unsigned char *png_data = NULL, BG_r, BG_g, BG_b; int invertImage; /* static char str[PATH_MAX]; * FILE* fp; */ - unsigned char* hexEncodedJPG; + unsigned char* hexEncodedJPG = NULL; char* image_data64_ptr = NULL; - cairo_surface_t* surface; + cairo_surface_t* surface = NULL; unsigned char* jpgData = NULL; size_t fileSize = 0; my_strdup(59, &filter, get_tok_value(r->prop_ptr, "filter", 0)); - my_strdup2(1183, &image_data64_ptr, get_tok_value(r->prop_ptr, "image_data", 0)); + if (filter) { size_t filtersize = 0; char* filterdata = NULL; @@ -163,6 +160,7 @@ void ps_drawPNG(xRect* r, double x1, double y1, double x2, double y2, int rot, i closure.pos = 0; closure.size = data_size; /* should not be necessary */ surface = cairo_image_surface_create_from_png_stream(png_reader, &closure); + png_size_x = cairo_image_surface_get_width(surface); png_size_y = cairo_image_surface_get_height(surface); @@ -187,7 +185,7 @@ void ps_drawPNG(xRect* r, double x1, double y1, double x2, double y2, int rot, i png_data[i + 1] = (unsigned char)(0xFF-png_g) + (unsigned char)((double)BG_g * ainv); png_data[i + 2] = (unsigned char)(0xFF-png_b) + (unsigned char)((double)BG_b * ainv); png_data[i + 3] = 0xFF; - }else + } else { png_data[i + 0] = png_r + (unsigned char)((double)BG_r * ainv); png_data[i + 1] = png_g + (unsigned char)((double)BG_g * ainv); @@ -246,9 +244,6 @@ void ps_drawPNG(xRect* r, double x1, double y1, double x2, double y2, int rot, i fprintf(fd, "3\n"); fprintf(fd, "colorimage\n"); fprintf(fd, "grestore\n"); - #ifdef FFLUSH_PS /* FIXME: why is this needed? */ - fflush(fd); - #endif cairo_surface_destroy(surface); my_free(1663, &hexEncodedJPG); } @@ -359,9 +354,6 @@ void ps_embedded_graph(xRect* r, double rx1, double ry1, double rx2, double ry2) fprintf(fd, "3\n"); fprintf(fd, "colorimage\n"); fprintf(fd, "grestore\n"); - #ifdef FFLUSH_PS /* FIXME: why is this needed? */ - fflush(fd); - #endif my_free(1666, &hexEncodedJPG); #endif @@ -380,9 +372,6 @@ static void set_ps_colors(unsigned int pixel) if(color_ps) fprintf(fd, "%g %g %g RGB\n", (double)ps_colors[pixel].red/256.0, (double)ps_colors[pixel].green/256.0, (double)ps_colors[pixel].blue/256.0); - #ifdef FFLUSH_PS /* FIXME: why is this needed? */ - fflush(fd); - #endif } diff --git a/src/save.c b/src/save.c index 7c15b716..84482280 100644 --- a/src/save.c +++ b/src/save.c @@ -25,6 +25,35 @@ #include /* waitpid */ #endif + +/* splits a command string into argv-like arguments + * return # of args in *argc + * argv[*argc] is always set to NULL + * parse_cmd_string(NULL, NULL) to clear static allocated data */ +#define PARSE_SIZE 128 +char **parse_cmd_string(const char *cmd, int *argc) +{ + static char *cmd_copy = NULL; + static char *argv[PARSE_SIZE]; + char *cmd_ptr, *cmd_save; + if(!cmd || !cmd[0]) { + if(cmd_copy) my_free(1670, &cmd_copy); + return NULL; + } + *argc = 0; + my_strdup2(1669, &cmd_copy, cmd); + cmd_ptr = cmd_copy; + while( (argv[*argc] = my_strtok_r(cmd_ptr, " \t", "'\"", &cmd_save)) ) { + cmd_ptr = NULL; + dbg(1, "--> %s\n", argv[*argc]); + (*argc)++; + if(*argc >= PARSE_SIZE) break; + } + argv[*argc] = NULL; /*terminating pointer needed by execvp() */ + return argv; +} + + /* get an input databuffer (din[ilen]), and a shell command (cmd) that reads stdin * and writes stdout, return the result in dout[olen]. * Caller must free the returned buffer. @@ -50,29 +79,32 @@ int filter_data(const char *din, const size_t ilen, pipe(p1); pipe(p2); signal(SIGPIPE, SIG_IGN); /* so attempting write/read a broken pipe won't kill program */ +/* + * p2 + * ------------------- p2[0] <--------- p2[1] ------------------- + * | Parent program | | Child filter | + * ------------------- p1[1] ---------> p1[0] ------------------- + * p1 + */ if( (pid = fork()) == 0) { + char **av; + int ac; /* child */ close(p1[1]); /* only read from p1 */ close(p2[0]); /* only write to p2 */ - #if 0 - dup2(p1[0],0); /* some systems lack this function */ - #else close(0); /* dup2(p1[0],0); */ /* connect read side of read pipe to stdin */ dup(p1[0]); - #endif - #if 0 - dup2(p2[1],1); /* some systems lack this function */ - #else close(1); /* dup2(p2[1],1); */ /* connect write side of write pipe to stdout */ dup(p2[1]); - #endif - /* execlp("gm", "gm", "convert", "-", "-quality", "50", "jpg:-", NULL); */ - if(system(cmd)) { + + + av = parse_cmd_string(cmd, &ac); + if(execvp(av[0], av) == -1) { fprintf(stderr, "error: conversion failed\n"); + close(p1[0]); + close(p2[1]); ret = 1; } - close(p1[0]); - close(p2[1]); exit(ret); } /* parent */ @@ -85,7 +117,7 @@ int filter_data(const char *din, const size_t ilen, fsync(p1[1]); close(p1[1]); if(!ret) { - oalloc = bufsize + 1; /* add extra space for final '\0' */ + oalloc = bufsize + 10000000; /* add extra space for final '\0' */ *dout = my_malloc(1480, oalloc); *olen = 0; while( (n = read(p2[0], *dout + *olen, bufsize)) > 0) { @@ -100,7 +132,6 @@ int filter_data(const char *din, const size_t ilen, } if(*olen) (*dout)[*olen] = '\0'; /* so (if ascii) it can be used as a string */ } - close(p2[0]); if(n < 0 || !*olen) { if(oalloc) { my_free(1483, dout); @@ -110,6 +141,7 @@ int filter_data(const char *din, const size_t ilen, ret = 1; } waitpid(pid, NULL, 0); /* write for child process to finish and unzombie it */ + close(p2[0]); signal(SIGPIPE, SIG_DFL); /* restore default SIGPIPE signal action */ return ret; } diff --git a/src/scheduler.c b/src/scheduler.c index 7ec90de1..3839751d 100644 --- a/src/scheduler.c +++ b/src/scheduler.c @@ -1875,7 +1875,19 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg else { cmd_found = 0;} break; case 'p': /*----------------------------------------------*/ - if(!strcmp(argv[1], "parselabel")) + if(!strcmp(argv[1], "parse_cmd")) + { + if(argc > 2) { + int c, i; + char **av; + av = parse_cmd_string(argv[2], &c); + for(i = 0; i < c; i++) { + dbg(0, "--> %s\n", av[i]); + } + } + } + + else if(!strcmp(argv[1], "parselabel")) { if(argc > 2) { parse(argv[2]); diff --git a/src/xschem.h b/src/xschem.h index cdcb4519..f781d272 100644 --- a/src/xschem.h +++ b/src/xschem.h @@ -1361,6 +1361,7 @@ extern void my_strndup(int id, char **dest, const char *src, size_t n); extern size_t my_strdup2(int id, char **dest, const char *src); extern char *my_fgets(FILE *fd); extern char *my_strtok_r(char *str, const char *delim, const char *quote, char **saveptr); +extern char **parse_cmd_string(const char *cmd, int *argc); extern int my_strncpy(char *d, const char *s, size_t n); extern int my_strcasecmp(const char *s1, const char *s2); extern double mylog10(double x);