00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #ifdef HAVE_CONFIG_H
00024 #include "config.h"
00025 #endif
00026
00027 #include <stdarg.h>
00028 #include <stdlib.h>
00029 #include <string.h>
00030
00031 #ifdef HAVE_UNISTD_H
00032 #include <unistd.h>
00033 #endif
00034
00035 #ifdef WIN32
00036 #include <fcntl.h>
00037 #include <io.h>
00038 #include "compat.h"
00039 #endif
00040
00041 #ifdef HAVE_LIBZ
00042 #include <zlib.h>
00043 #endif
00044
00045 #include "logic.h"
00046 #include "const.h"
00047 #include "gvplugin_device.h"
00048 #include "gvcjob.h"
00049 #include "gvcint.h"
00050 #include "gvcproc.h"
00051
00052 static const int PAGE_ALIGN = 4095;
00053
00054 size_t gvdevice_write (GVJ_t * job, const unsigned char *s, unsigned int len)
00055 {
00056 if (job->gvc->write_fn && job->output_file == stdout)
00057 return (job->gvc->write_fn)((char*)s, len);
00058 if (job->flags & GVDEVICE_COMPRESSED_FORMAT) {
00059 #ifdef HAVE_LIBZ
00060 return gzwrite((gzFile *) (job->output_file), s, len);
00061 #endif
00062 }
00063 else if (job->output_data) {
00064 if (len > job->output_data_allocated - job->output_data_position) {
00065 job->output_data_allocated = (job->output_data_position + len + PAGE_ALIGN) & ~PAGE_ALIGN;
00066 job->output_data = realloc(job->output_data, job->output_data_allocated);
00067 if (!job->output_data) {
00068 fprintf(stderr, "failure realloc'ing for result string\n");
00069 return 0;
00070 }
00071 }
00072 memcpy(job->output_data + job->output_data_position, s, len);
00073 job->output_data_position += len;
00074 return len;
00075 }
00076 else
00077 return fwrite(s, sizeof(char), len, job->output_file);
00078 return 0;
00079 }
00080
00081 void gvdevice_fputs(GVJ_t * job, char *s)
00082 {
00083 gvdevice_write (job, (unsigned char*)s, strlen(s));
00084 }
00085
00086
00087
00088
00089
00090
00091
00092
00093 void gvdevice_printf(GVJ_t * job, const char *format, ...)
00094 {
00095 unsigned char buf[BUFSIZ];
00096 unsigned int len;
00097 va_list argp;
00098
00099 va_start(argp, format);
00100 #ifdef HAVE_VSNPRINTF
00101 len = vsnprintf((char *)buf, sizeof(buf), format, argp);
00102 #else
00103 len = vsprintf((char *)buf, format, argp);
00104 #endif
00105 va_end(argp);
00106
00107 gvdevice_write(job, buf, len);
00108 }
00109
00110
00111
00112
00113
00114
00115 #define DECPLACES 2
00116 #define DECPLACES_SCALE 100
00117
00118
00119 #define val_str(n, x) static double n = x; static unsigned char n##str[] = #x;
00120 val_str(maxnegnum, -999999999999999.99)
00121
00122
00123
00124
00125
00126 static unsigned char * gvprintnum (int *len, double number)
00127 {
00128 static unsigned char tmpbuf[sizeof(maxnegnumstr)];
00129 unsigned char *result = tmpbuf+sizeof(maxnegnumstr);
00130 long int N;
00131 bool showzeros, negative;
00132 int digit, i;
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142 if (number < maxnegnum) {
00143 *len = sizeof(maxnegnumstr)-1;
00144 return maxnegnumstr;;
00145 }
00146 if (number > -maxnegnum) {
00147 *len = sizeof(maxnegnumstr)-2;
00148 return maxnegnumstr+1;
00149 }
00150 number *= DECPLACES_SCALE;
00151 if (number < 0.0)
00152 N = number - 0.5;
00153 else
00154 N = number + 0.5;
00155 if (N == 0) {
00156 *len = 1;
00157 return (unsigned char *)"0";
00158 }
00159 if ((negative = (N < 0)))
00160 N = -N;
00161 #ifdef TERMINATED_NUMBER_STRING
00162 *--result = '\0';
00163 #endif
00164 showzeros = false;
00165 for (i = DECPLACES; N || i > 0; i--) {
00166
00167 digit = N % 10;
00168 N /= 10;
00169 if (digit || showzeros) {
00170
00171 *--result = digit | '0';
00172 showzeros = true;
00173 }
00174 if (i == 1) {
00175 if (showzeros)
00176 *--result = '.';
00177 showzeros = true;
00178 }
00179 }
00180 if (negative)
00181 *--result = '-';
00182 #ifdef TERMINATED_NUMBER_STRING
00183 *len = tmpbuf+sizeof(maxnegnumstr)-1 - result;
00184 #else
00185 *len = tmpbuf+sizeof(maxnegnumstr) - result;
00186 #endif
00187 return result;
00188 }
00189
00190
00191 #ifdef GVPRINTNUM_TEST
00192 int main (int argc, char *argv[])
00193 {
00194 unsigned char *buf;
00195 int len;
00196
00197 double test[] = {
00198 -maxnegnum*1.1, -maxnegnum*.9,
00199 1e8, 10.008, 10, 1, .1, .01,
00200 .006, .005, .004, .001, 1e-8,
00201 0, -0,
00202 -1e-8, -.001, -.004, -.005, -.006,
00203 -.01, -.1, -1, -10, -10.008, -1e8,
00204 maxnegnum*.9, maxnegnum*1.1
00205 };
00206 int i = sizeof(test) / sizeof(test[0]);
00207
00208 while (i--) {
00209 buf = gvprintnum(&len, test[i]);
00210 fprintf (stdout, "%g = %s %d\n", test[i], buf, len);
00211 }
00212
00213 return 0;
00214 }
00215 #endif
00216
00217 void gvdevice_printnum(GVJ_t * job, double num)
00218 {
00219 unsigned char *buf;
00220 int len;
00221
00222 buf = gvprintnum(&len, num);
00223 gvdevice_write(job, buf, len);
00224 }
00225
00226 void gvdevice_printpointf(GVJ_t * job, pointf p)
00227 {
00228 unsigned char *buf;
00229 int len;
00230
00231 buf = gvprintnum(&len, p.x);
00232 gvdevice_write(job, buf, len);
00233 gvdevice_write(job, (unsigned char*)" ", 1);
00234 buf = gvprintnum(&len, p.y);
00235 gvdevice_write(job, buf, len);
00236 }
00237
00238 void gvdevice_printpointflist(GVJ_t * job, pointf *p, int n)
00239 {
00240 int i = 0;
00241
00242 while (TRUE) {
00243 gvdevice_printpointf(job, p[i]);
00244 if (++i >= n) break;
00245 gvdevice_write(job, (unsigned char*)" ", 1);
00246 }
00247 }
00248
00249 static void auto_output_filename(GVJ_t *job)
00250 {
00251 static char *buf;
00252 static int bufsz;
00253 char gidx[100];
00254 char *fn, *p;
00255 int len;
00256
00257 if (job->graph_index)
00258 sprintf(gidx, ".%d", job->graph_index + 1);
00259 else
00260 gidx[0] = '\0';
00261 if (!(fn = job->input_filename))
00262 fn = "noname.dot";
00263 len = strlen(fn)
00264 + strlen(gidx)
00265 + 1
00266 + strlen(job->output_langname)
00267 + 1;
00268 if (bufsz < len) {
00269 bufsz = len + 10;
00270 buf = realloc(buf, bufsz * sizeof(char));
00271 }
00272 strcpy(buf, fn);
00273 strcat(buf, gidx);
00274 strcat(buf, ".");
00275 if ((p = strchr(job->output_langname, ':'))) {
00276 strcat(buf, p+1);
00277 strcat(buf, ".");
00278 strncat(buf, job->output_langname, (p - job->output_langname));
00279 }
00280 else {
00281 strcat(buf, job->output_langname);
00282 }
00283
00284 job->output_filename = buf;
00285 }
00286
00287 #ifdef WITH_CODEGENS
00288 extern FILE* Output_file;
00289 #endif
00290
00291 void gvdevice_initialize(GVJ_t * job)
00292 {
00293 gvdevice_engine_t *gvde = job->device.engine;
00294 GVC_t *gvc = job->gvc;
00295
00296 if (gvde && gvde->initialize) {
00297 gvde->initialize(job);
00298 }
00299 else if (job->output_data) {
00300 }
00301
00302 else if (!job->output_file) {
00303 if (gvc->common.auto_outfile_names)
00304 auto_output_filename(job);
00305 if (job->output_filename) {
00306 job->output_file = fopen(job->output_filename, "w");
00307 if (job->output_file == NULL) {
00308 perror(job->output_filename);
00309 exit(1);
00310 }
00311 }
00312 else
00313 job->output_file = stdout;
00314
00315 #ifdef WITH_CODEGENS
00316 Output_file = job->output_file;
00317 #endif
00318
00319 #ifdef HAVE_SETMODE
00320 #ifdef O_BINARY
00321 if (job->flags & GVDEVICE_BINARY_FORMAT)
00322 setmode(fileno(job->output_file), O_BINARY);
00323 #endif
00324 #endif
00325
00326 if (job->flags & GVDEVICE_COMPRESSED_FORMAT) {
00327 #if HAVE_LIBZ
00328 int fd;
00329
00330
00331 fd = dup(fileno(job->output_file));
00332 job->output_file = (FILE *) (gzdopen(fd, "wb"));
00333 if (!job->output_file) {
00334 (job->common->errorfn) ("Error initializing compression on output file\n");
00335 exit(1);
00336 }
00337 #else
00338 (job->common->errorfn) ("No libz support.\n");
00339 exit(1);
00340 #endif
00341 }
00342 }
00343 }
00344
00345 void gvdevice_format(GVJ_t * job)
00346 {
00347 gvdevice_engine_t *gvde = job->device.engine;
00348
00349 if (gvde && gvde->format)
00350 gvde->format(job);
00351 if (job->output_file
00352 && ! job->external_context
00353 && job->output_lang != TK
00354 && ! (job->flags & GVDEVICE_COMPRESSED_FORMAT))
00355 fflush(job->output_file);
00356 }
00357
00358 void gvdevice_finalize(GVJ_t * job)
00359 {
00360 gvdevice_engine_t *gvde = job->device.engine;
00361 boolean finalized_p = FALSE;
00362
00363 if (gvde) {
00364 if (gvde->finalize) {
00365 gvde->finalize(job);
00366 finalized_p = TRUE;
00367 }
00368 }
00369 #ifdef WITH_CODEGENS
00370 else {
00371 codegen_t *cg = job->codegen;
00372
00373 if (cg && cg->reset)
00374 cg->reset();
00375 }
00376 #endif
00377
00378 if (! finalized_p) {
00379
00380 if (job->flags & GVDEVICE_COMPRESSED_FORMAT) {
00381 #ifdef HAVE_LIBZ
00382 gzclose((gzFile *) (job->output_file));
00383 job->output_file = NULL;
00384 #else
00385 (job->common->errorfn) ("No libz support\n");
00386 exit(1);
00387 #endif
00388 }
00389 if (job->output_filename
00390 && job->output_file != stdout
00391 && ! job->external_context) {
00392 if (job->output_file) {
00393 fclose(job->output_file);
00394 job->output_file = NULL;
00395 }
00396 job->output_filename = NULL;
00397 }
00398 }
00399 }