plot.c 57 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831
  1. /* This file is part of the GNU plotutils package. Copyright (C) 1989,
  2. 1990, 1991, 1995, 1996, 1997, 1998, 1999, 2000, 2005, 2008, 2009, Free
  3. Software Foundation, Inc.
  4. The GNU plotutils package is free software. You may redistribute it
  5. and/or modify it under the terms of the GNU General Public License as
  6. published by the Free Software foundation; either version 2, or (at your
  7. option) any later version.
  8. The GNU plotutils package is distributed in the hope that it will be
  9. useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. General Public License for more details.
  12. You should have received a copy of the GNU General Public License along
  13. with the GNU plotutils package; see the file COPYING. If not, write to
  14. the Free Software Foundation, Inc., 51 Franklin St., Fifth Floor,
  15. Boston, MA 02110-1301, USA. */
  16. /* This file is the driving routine for the GNU `plot' program. It
  17. includes code to read a stream of commands, in GNU metafile format, and
  18. call libplot functions to draw the graphics. */
  19. #include "sys-defines.h"
  20. #include "libcommon.h"
  21. #include "getopt.h"
  22. #include "fontlist.h"
  23. #include "plot.h"
  24. /* Obsolete op codes (no longer listed in plot.h) */
  25. #define O_COLOR 'C'
  26. #define O_FROTATE 'V'
  27. #define O_FSCALE 'X'
  28. #define O_FTRANSLATE 'Q'
  29. /* The six input formats we recognize */
  30. typedef enum
  31. {
  32. /* There are two GNU metafile formats: binary and portable (ascii). */
  33. GNU_BINARY, GNU_PORTABLE,
  34. /* PLOT5_HIGH and PLOT5_LOW are the two distinct versions of Unix plot(5)
  35. format (high/low byte first), which we also support. They are
  36. requested by the -h and -l options respectively. The user may not
  37. need to specify either of those options explicitly, since if
  38. sizeof(short int)=2 then plot(5) input format is subsumed by
  39. GNU_OLD_BINARY format (see below). */
  40. PLOT5_HIGH, PLOT5_LOW,
  41. /* GNU_OLD_BINARY [obsolete] is the binary format used in pre-2.0
  42. releases, with no initial magic string, short ints instead of ints,
  43. and no OPENPL or CLOSEPL directives. By default, we assume that the
  44. input format is GNU_OLD_BINARY, and we switch to GNU_BINARY or
  45. GNU_PORTABLE if we see the appropriate magic header string.
  46. GNU_OLD_PORTABLE [obsolete] is the ascii format used in pre-2.0
  47. releases, with no initial magic string, and no OPENPL or CLOSEPL
  48. directives. It subsumes the ascii version of plot(5) format, found on
  49. some Unix systems. If the user wishes to parse GNU_OLD_PORTABLE
  50. format, he/she should use the -A option. */
  51. GNU_OLD_BINARY, GNU_OLD_PORTABLE
  52. } plot_format;
  53. const char *progname = "plot"; /* name of this program */
  54. const char *written = "Written by Robert S. Maier.";
  55. const char *copyright = "Copyright (C) 2009 Free Software Foundation, Inc.";
  56. const char *usage_appendage = " [FILE]...\n\
  57. With no FILE, or when FILE is -, read standard input.\n";
  58. bool single_page_is_requested = false; /* set if user uses -p option */
  59. char *bg_color = NULL; /* initial bg color, can be spec'd by user */
  60. char *font_name = NULL; /* initial font name, can be spec'd by user */
  61. char *pen_color = NULL; /* initial pen color, can be spec'd by user */
  62. double font_size = -1.0; /* initial fractional size, <0 means default */
  63. double line_width = -1.0; /* initial line width, <0 means default */
  64. int requested_page = 0; /* user sets this via -p option */
  65. /* Default input file format (see list of supported formats above). Don't
  66. change this (GNU_OLD_BINARY is an obsolete format, but it subsumes
  67. plot(5) format on many operating systems). We'll switch to the
  68. appropriate modern format by peeking at the first line of the input file. */
  69. plot_format user_specified_input_format = GNU_OLD_BINARY;
  70. plot_format input_format = GNU_OLD_BINARY;
  71. /* Whether to remove all page breaks and frame breaks (i.e. invocations
  72. of erase()) from the output */
  73. bool merge_pages = false;
  74. /* options */
  75. #define ARG_NONE 0
  76. #define ARG_REQUIRED 1
  77. #define ARG_OPTIONAL 2
  78. const char *optstring = "shlAIOp:F:f:W:T:";
  79. struct option long_options[] =
  80. {
  81. /* The most important option ("--display-type" is an obsolete variant) */
  82. { "output-format", ARG_REQUIRED, NULL, 'T'},
  83. { "display-type", ARG_REQUIRED, NULL, 'T' << 8 }, /* hidden */
  84. /* Other frequently used options */
  85. { "font-name", ARG_REQUIRED, NULL, 'F' },
  86. { "font-size", ARG_REQUIRED, NULL, 'f' },
  87. { "line-width", ARG_REQUIRED, NULL, 'W' },
  88. /* Long options with (mostly) no equivalent short option alias */
  89. { "bg-color", ARG_REQUIRED, NULL, 'q' << 8 },
  90. { "bitmap-size", ARG_REQUIRED, NULL, 'B' << 8 },
  91. { "emulate-color", ARG_REQUIRED, NULL, 'e' << 8},
  92. { "max-line-length", ARG_REQUIRED, NULL, 'M' << 8 },
  93. { "merge-pages", ARG_NONE, NULL, 's' },
  94. { "page-number", ARG_REQUIRED, NULL, 'p' },
  95. { "page-size", ARG_REQUIRED, NULL, 'P' << 8 },
  96. { "pen-color", ARG_REQUIRED, NULL, 'C' << 8 },
  97. { "rotation", ARG_REQUIRED, NULL, 'r' << 8},
  98. /* Options relevant only to raw plot (refers to metafile output) */
  99. { "portable-output", ARG_NONE, NULL, 'O' },
  100. /* Old input formats, for backward compatibility */
  101. { "high-byte-first-input", ARG_NONE, NULL, 'h' },
  102. { "low-byte-first-input", ARG_NONE, NULL, 'l' },
  103. { "ascii-input", ARG_NONE, NULL, 'A' },
  104. /* obsolete hidden option [same as 'A'] */
  105. { "ascii-input", ARG_NONE, NULL, 'I' },
  106. /* Documentation options */
  107. { "help-fonts", ARG_NONE, NULL, 'f' << 8 },
  108. { "list-fonts", ARG_NONE, NULL, 'l' << 8 },
  109. { "version", ARG_NONE, NULL, 'V' << 8 },
  110. { "help", ARG_NONE, NULL, 'h' << 8 },
  111. { NULL, 0, NULL, 0}
  112. };
  113. /* null-terminated list of options, such as obsolete-but-still-maintained
  114. options or undocumented options, which we don't show to the user */
  115. const int hidden_options[] = { (int)'I', (int)('T' << 8), 0 };
  116. /* forward references */
  117. bool read_plot (plPlotter *plotter, FILE *in_stream);
  118. char *read_string (FILE *input, bool *badstatus);
  119. double read_float (FILE *input, bool *badstatus);
  120. double read_int (FILE *input, bool *badstatus);
  121. int maybe_closepl (plPlotter *plotter);
  122. int maybe_openpl (plPlotter *plotter);
  123. int read_true_int (FILE *input, bool *badstatus);
  124. unsigned char read_byte_as_unsigned_char (FILE *input, bool *badstatus);
  125. unsigned int read_byte_as_unsigned_int (FILE *input, bool *badstatus);
  126. int
  127. main (int argc, char *argv[])
  128. {
  129. plPlotter *plotter;
  130. plPlotterParams *plotter_params;
  131. bool do_list_fonts = false; /* show a list of fonts? */
  132. bool show_fonts = false; /* supply help on fonts? */
  133. bool show_usage = false; /* show usage message? */
  134. bool show_version = false; /* show version message? */
  135. char *output_format = (char *)"meta"; /* default libplot output format */
  136. int errcnt = 0; /* errors encountered */
  137. int local_page_number; /* temporary storage */
  138. int opt_index; /* long option index */
  139. int option; /* option character */
  140. int retval; /* return value */
  141. plotter_params = pl_newplparams ();
  142. while ((option = getopt_long (argc, argv, optstring, long_options, &opt_index)) != EOF)
  143. {
  144. if (option == 0)
  145. option = long_options[opt_index].val;
  146. switch (option)
  147. {
  148. case 'T': /* Output format, ARG REQUIRED */
  149. case 'T' << 8:
  150. output_format = (char *)xmalloc (strlen (optarg) + 1);
  151. strcpy (output_format, optarg);
  152. break;
  153. case 'O': /* Ascii output */
  154. pl_setplparam (plotter_params, "META_PORTABLE", (void *)"yes");
  155. break;
  156. case 'F': /* set the initial font */
  157. font_name = (char *)xmalloc (strlen (optarg) + 1);
  158. strcpy (font_name, optarg);
  159. break;
  160. case 'e' << 8: /* emulate color by grayscale */
  161. pl_setplparam (plotter_params, "EMULATE_COLOR", (void *)optarg);
  162. break;
  163. case 'C' << 8: /* set the initial pen color */
  164. pen_color = (char *)xmalloc (strlen (optarg) + 1);
  165. strcpy (pen_color, optarg);
  166. break;
  167. case 'q' << 8: /* set the initial background color */
  168. bg_color = (char *)xmalloc (strlen (optarg) + 1);
  169. strcpy (bg_color, optarg);
  170. break;
  171. case 'B' << 8: /* Bitmap size */
  172. pl_setplparam (plotter_params, "BITMAPSIZE", (void *)optarg);
  173. break;
  174. case 'P' << 8: /* Page size */
  175. pl_setplparam (plotter_params, "PAGESIZE", (void *)optarg);
  176. break;
  177. case 'f': /* set the initial fontsize */
  178. {
  179. double local_font_size;
  180. if (sscanf (optarg, "%lf", &local_font_size) <= 0)
  181. {
  182. fprintf (stderr,
  183. "%s: error: the initial font size `%s' is bad (it should be a number)\n",
  184. progname, optarg);
  185. errcnt++;
  186. break;
  187. }
  188. if (local_font_size > 1.0)
  189. fprintf (stderr, "%s: the too-large initial font size `%f' is disregarded (it should be less than 1.0)\n",
  190. progname, local_font_size);
  191. else if (local_font_size < 0.0)
  192. fprintf (stderr, "%s: the negative initial font size `%f' is disregarded\n",
  193. progname, local_font_size);
  194. else
  195. font_size = local_font_size;
  196. break;
  197. }
  198. case 'p': /* page number */
  199. if (sscanf (optarg, "%d", &local_page_number) <= 0
  200. || local_page_number < 1)
  201. {
  202. fprintf (stderr,
  203. "%s: error: the page number `%s' is bad (it should be a positive integer)\n",
  204. progname, optarg);
  205. errcnt++;
  206. }
  207. else
  208. {
  209. requested_page = local_page_number;
  210. single_page_is_requested = true;
  211. }
  212. break;
  213. case 'W': /* set the initial line width */
  214. {
  215. double local_line_width;
  216. if (sscanf (optarg, "%lf", &local_line_width) <= 0)
  217. {
  218. fprintf (stderr,
  219. "%s: error: the initial line thickness `%s' is bad (it should be a number)\n",
  220. progname, optarg);
  221. errcnt++;
  222. break;
  223. }
  224. if (local_line_width < 0.0)
  225. fprintf (stderr, "%s: the negative initial line thickness `%f' is ignored\n",
  226. progname, local_line_width);
  227. else
  228. line_width = local_line_width;
  229. break;
  230. }
  231. case 'h': /* High-byte-first plot(5) metafile(s) */
  232. user_specified_input_format = PLOT5_HIGH;
  233. break;
  234. case 'l': /* Low-byte-first plot(5) metafile(s) */
  235. user_specified_input_format = PLOT5_LOW;
  236. break;
  237. case 'A': /* Old ascii metafile(s) */
  238. case 'I':
  239. user_specified_input_format = GNU_OLD_PORTABLE;
  240. break;
  241. case 'r' << 8: /* Plot rotation angle, ARG REQUIRED */
  242. pl_setplparam (plotter_params, "ROTATION", (void *)optarg);
  243. break;
  244. case 'M' << 8: /* Max line length */
  245. pl_setplparam (plotter_params, "MAX_LINE_LENGTH", (void *)optarg);
  246. break;
  247. case 's': /* Merge pages */
  248. merge_pages = true;
  249. break;
  250. case 'V' << 8: /* Version */
  251. show_version = true;
  252. break;
  253. case 'f' << 8: /* Fonts */
  254. show_fonts = true;
  255. break;
  256. case 'h' << 8: /* Help */
  257. show_usage = true;
  258. break;
  259. case 'l' << 8: /* Fonts */
  260. do_list_fonts = true;
  261. break;
  262. default:
  263. errcnt++;
  264. break;
  265. }
  266. }
  267. if (errcnt > 0)
  268. {
  269. fprintf (stderr, "Try `%s --help' for more information\n", progname);
  270. return EXIT_FAILURE;
  271. }
  272. if (show_version)
  273. {
  274. display_version (progname, written, copyright);
  275. return EXIT_SUCCESS;
  276. }
  277. if (do_list_fonts)
  278. {
  279. int success;
  280. success = list_fonts (output_format, progname);
  281. if (success)
  282. return EXIT_SUCCESS;
  283. else
  284. return EXIT_FAILURE;
  285. }
  286. if (show_fonts)
  287. {
  288. int success;
  289. success = display_fonts (output_format, progname);
  290. if (success)
  291. return EXIT_SUCCESS;
  292. else
  293. return EXIT_FAILURE;
  294. }
  295. if (show_usage)
  296. {
  297. display_usage (progname, hidden_options, usage_appendage, 2);
  298. return EXIT_SUCCESS;
  299. }
  300. if (bg_color)
  301. /* select user-specified background color */
  302. pl_setplparam (plotter_params, "BG_COLOR", (void *)bg_color);
  303. if ((plotter = pl_newpl_r (output_format, NULL, stdout, stderr,
  304. plotter_params)) == NULL)
  305. {
  306. fprintf (stderr, "%s: error: the plot device could not be created\n", progname);
  307. return EXIT_FAILURE;
  308. }
  309. if (merge_pages)
  310. /* we do just one openpl..closepl, wrapped around everything */
  311. if (pl_openpl_r (plotter) < 0)
  312. {
  313. fprintf (stderr, "%s: error: the plot device could not be opened\n",
  314. progname);
  315. return EXIT_FAILURE;
  316. }
  317. retval = EXIT_SUCCESS;
  318. if (optind < argc)
  319. /* input files (or stdin) named explicitly on the command line */
  320. {
  321. for (; optind < argc; optind++)
  322. {
  323. FILE *data_file;
  324. if (strcmp (argv[optind], "-") == 0)
  325. data_file = stdin;
  326. else
  327. {
  328. data_file = fopen (argv[optind], "r");
  329. if (data_file == NULL)
  330. {
  331. fprintf (stderr, "%s: %s: %s\n", progname, argv[optind], strerror(errno));
  332. fprintf (stderr, "%s: ignoring this file\n", progname);
  333. errno = 0; /* not quite fatal */
  334. retval = EXIT_FAILURE;
  335. continue; /* back to top of for loop */
  336. }
  337. }
  338. if (read_plot (plotter, data_file) == false)
  339. {
  340. fprintf (stderr, "%s: the input file `%s' could not be parsed\n",
  341. progname, argv[optind]);
  342. retval = EXIT_FAILURE;
  343. break; /* break out of for loop */
  344. }
  345. if (data_file != stdin) /* Don't close stdin */
  346. if (fclose (data_file) < 0)
  347. {
  348. fprintf (stderr,
  349. "%s: the input file `%s' could not be closed\n",
  350. progname, argv[optind]);
  351. retval = EXIT_FAILURE;
  352. continue; /* back to top of for loop */
  353. }
  354. } /* endfor */
  355. }
  356. else
  357. /* no files/streams spec'd on the command line, just read stdin */
  358. {
  359. if (read_plot (plotter, stdin) == false)
  360. {
  361. fprintf (stderr, "%s: the input could not be parsed\n", progname);
  362. retval = EXIT_FAILURE;
  363. }
  364. }
  365. if (merge_pages)
  366. /* we do just one openpl..closepl, wrapped around everything */
  367. if (pl_closepl_r (plotter) < 0)
  368. {
  369. fprintf (stderr, "%s: error: the plot device could not be closed\n",
  370. progname);
  371. return EXIT_FAILURE;
  372. }
  373. if (pl_deletepl_r (plotter) < 0)
  374. {
  375. fprintf (stderr, "%s: error: the plot device could not be deleted\n", progname);
  376. retval = EXIT_FAILURE;
  377. }
  378. pl_deleteplparams (plotter_params);
  379. return retval;
  380. }
  381. /* read_plot() reads a file in GNU metafile format or plot(5) format from a
  382. stream, and calls a plot function according to each instruction found in
  383. the file. Return value indicates whether stream was parsed
  384. successfully. */
  385. bool
  386. read_plot (plPlotter *plotter, FILE *in_stream)
  387. {
  388. bool argerr = false; /* error occurred while reading argument? */
  389. bool display_open = false; /* display device open? */
  390. bool first_command = true; /* first command of file? */
  391. bool in_page = false; /* within an openpl..closepl? */
  392. bool parameters_initted = false; /* user-specified parameters initted? */
  393. bool unrec = false; /* unrecognized command seen? */
  394. char *s;
  395. double x0, y0, x1, y1, x2, y2, x3, y3;
  396. int i0, i1, i2;
  397. int instruction;
  398. static int current_page = 1; /* page count is continued from file to file */
  399. /* User may specify one of the formats PLOT5_HIGH, PLOT5_LOW, and
  400. GNU_OLD_PORTABLE on the command line. If user doesn't specify a
  401. format, this is by default set to GNU_OLD_BINARY [obsolete], and we'll
  402. figure out whether the file is in a modern format, and if so,
  403. which one. */
  404. input_format = user_specified_input_format;
  405. /* peek at first instruction in file */
  406. instruction = getc (in_stream);
  407. /* Switch away from GNU_OLD_BINARY to GNU_BINARY if a GNU metafile magic
  408. string, interpreted here as a comment, is seen at top of file. See
  409. also parsing of the COMMENT instruction below (we further switch to
  410. GNU_PORTABLE if the header line indicates we should). */
  411. if (input_format == GNU_OLD_BINARY && instruction == (int)O_COMMENT)
  412. input_format = GNU_BINARY;
  413. /* Note: we use `input_format' as a way of working around a problem:
  414. absurdly large font size requests, which can crash X servers. (You used
  415. to be able to crash an X server by piping any EPS file to `plot -TX',
  416. since the `S' on the first line was interepreted as an op code for a
  417. font size request!) We no longer process the `S' op code unless we've
  418. seen a modern GNU metafile magic string at the beginning of the file.
  419. This is a kludge but adds a little safety. */
  420. while (instruction != EOF)
  421. {
  422. /* If a pre-modern format, OPENPL directive is not supported. So
  423. open display device if it hasn't already been opened, and
  424. we're on the right page. */
  425. if (input_format != GNU_BINARY && input_format != GNU_PORTABLE)
  426. if ((!single_page_is_requested || current_page == requested_page)
  427. && instruction != (int)O_COMMENT && display_open == false)
  428. {
  429. if (maybe_openpl (plotter) < 0)
  430. {
  431. fprintf (stderr, "%s: error: the plot device could not be opened\n",
  432. progname);
  433. exit (EXIT_FAILURE);
  434. }
  435. else
  436. display_open = true;
  437. }
  438. switch (instruction)
  439. {
  440. case (int)O_ALABEL:
  441. {
  442. char x_adjust, y_adjust;
  443. x_adjust = (char)read_byte_as_unsigned_char (in_stream, &argerr);
  444. y_adjust = (char)read_byte_as_unsigned_char (in_stream, &argerr);
  445. s = read_string (in_stream, &argerr);
  446. if (!argerr)
  447. {
  448. if (!single_page_is_requested || current_page == requested_page)
  449. pl_alabel_r (plotter, x_adjust, y_adjust, s);
  450. free (s);
  451. }
  452. }
  453. break;
  454. case (int)O_ARC:
  455. x0 = read_int (in_stream, &argerr);
  456. y0 = read_int (in_stream, &argerr);
  457. x1 = read_int (in_stream, &argerr);
  458. y1 = read_int (in_stream, &argerr);
  459. x2 = read_int (in_stream, &argerr);
  460. y2 = read_int (in_stream, &argerr);
  461. if (!argerr)
  462. if (!single_page_is_requested || current_page == requested_page)
  463. pl_farc_r (plotter, x0, y0, x1, y1, x2, y2);
  464. break;
  465. case (int)O_ARCREL:
  466. x0 = read_int (in_stream, &argerr);
  467. y0 = read_int (in_stream, &argerr);
  468. x1 = read_int (in_stream, &argerr);
  469. y1 = read_int (in_stream, &argerr);
  470. x2 = read_int (in_stream, &argerr);
  471. y2 = read_int (in_stream, &argerr);
  472. if (!argerr)
  473. if (!single_page_is_requested || current_page == requested_page)
  474. pl_farcrel_r (plotter, x0, y0, x1, y1, x2, y2);
  475. break;
  476. case (int)O_BEZIER2:
  477. x0 = read_int (in_stream, &argerr);
  478. y0 = read_int (in_stream, &argerr);
  479. x1 = read_int (in_stream, &argerr);
  480. y1 = read_int (in_stream, &argerr);
  481. x2 = read_int (in_stream, &argerr);
  482. y2 = read_int (in_stream, &argerr);
  483. if (!argerr)
  484. if (!single_page_is_requested || current_page == requested_page)
  485. pl_fbezier2_r (plotter, x0, y0, x1, y1, x2, y2);
  486. break;
  487. case (int)O_BEZIER2REL:
  488. x0 = read_int (in_stream, &argerr);
  489. y0 = read_int (in_stream, &argerr);
  490. x1 = read_int (in_stream, &argerr);
  491. y1 = read_int (in_stream, &argerr);
  492. x2 = read_int (in_stream, &argerr);
  493. y2 = read_int (in_stream, &argerr);
  494. if (!argerr)
  495. if (!single_page_is_requested || current_page == requested_page)
  496. pl_fbezier2rel_r (plotter, x0, y0, x1, y1, x2, y2);
  497. break;
  498. case (int)O_BEZIER3:
  499. x0 = read_int (in_stream, &argerr);
  500. y0 = read_int (in_stream, &argerr);
  501. x1 = read_int (in_stream, &argerr);
  502. y1 = read_int (in_stream, &argerr);
  503. x2 = read_int (in_stream, &argerr);
  504. y2 = read_int (in_stream, &argerr);
  505. x3 = read_int (in_stream, &argerr);
  506. y3 = read_int (in_stream, &argerr);
  507. if (!argerr)
  508. if (!single_page_is_requested || current_page == requested_page)
  509. pl_fbezier3_r (plotter, x0, y0, x1, y1, x2, y2, x3, y3);
  510. break;
  511. case (int)O_BEZIER3REL:
  512. x0 = read_int (in_stream, &argerr);
  513. y0 = read_int (in_stream, &argerr);
  514. x1 = read_int (in_stream, &argerr);
  515. y1 = read_int (in_stream, &argerr);
  516. x2 = read_int (in_stream, &argerr);
  517. y2 = read_int (in_stream, &argerr);
  518. x3 = read_int (in_stream, &argerr);
  519. y3 = read_int (in_stream, &argerr);
  520. if (!argerr)
  521. if (!single_page_is_requested || current_page == requested_page)
  522. pl_fbezier3rel_r (plotter, x0, y0, x1, y1, x2, y2, x3, y3);
  523. break;
  524. case (int)O_BGCOLOR:
  525. /* parse args as unsigned ints rather than ints */
  526. i0 = read_true_int (in_stream, &argerr)&0xFFFF;
  527. i1 = read_true_int (in_stream, &argerr)&0xFFFF;
  528. i2 = read_true_int (in_stream, &argerr)&0xFFFF;
  529. if (!argerr)
  530. if (!single_page_is_requested || current_page == requested_page)
  531. pl_bgcolor_r (plotter, i0, i1, i2);
  532. break;
  533. case (int)O_BOX:
  534. x0 = read_int (in_stream, &argerr);
  535. y0 = read_int (in_stream, &argerr);
  536. x1 = read_int (in_stream, &argerr);
  537. y1 = read_int (in_stream, &argerr);
  538. if (!argerr)
  539. if (!single_page_is_requested || current_page == requested_page)
  540. pl_fbox_r (plotter, x0, y0, x1, y1);
  541. break;
  542. case (int)O_BOXREL:
  543. x0 = read_int (in_stream, &argerr);
  544. y0 = read_int (in_stream, &argerr);
  545. x1 = read_int (in_stream, &argerr);
  546. y1 = read_int (in_stream, &argerr);
  547. if (!argerr)
  548. if (!single_page_is_requested || current_page == requested_page)
  549. pl_fboxrel_r (plotter, x0, y0, x1, y1);
  550. break;
  551. case (int)O_CAPMOD:
  552. s = read_string (in_stream, &argerr);
  553. if (!argerr)
  554. {
  555. if (!single_page_is_requested || current_page == requested_page)
  556. pl_capmod_r (plotter, s);
  557. free (s);
  558. }
  559. break;
  560. case (int)O_CIRCLE:
  561. x0 = read_int (in_stream, &argerr);
  562. y0 = read_int (in_stream, &argerr);
  563. x1 = read_int (in_stream, &argerr);
  564. if (!argerr)
  565. if (!single_page_is_requested || current_page == requested_page)
  566. pl_fcircle_r (plotter, x0, y0, x1);
  567. break;
  568. case (int)O_CIRCLEREL:
  569. x0 = read_int (in_stream, &argerr);
  570. y0 = read_int (in_stream, &argerr);
  571. x1 = read_int (in_stream, &argerr);
  572. if (!argerr)
  573. if (!single_page_is_requested || current_page == requested_page)
  574. pl_fcirclerel_r (plotter, x0, y0, x1);
  575. break;
  576. case (int)O_COLOR: /* obsolete op code, to be removed */
  577. i0 = read_true_int (in_stream, &argerr)&0xFFFF;
  578. i1 = read_true_int (in_stream, &argerr)&0xFFFF;
  579. i2 = read_true_int (in_stream, &argerr)&0xFFFF;
  580. if (!argerr)
  581. if (!single_page_is_requested || current_page == requested_page)
  582. pl_color_r (plotter, i0, i1, i2);
  583. break;
  584. case (int)O_CLOSEPATH:
  585. if (!single_page_is_requested || current_page == requested_page)
  586. pl_closepath_r (plotter);
  587. break;
  588. case (int)O_CLOSEPL:
  589. if (input_format != GNU_BINARY && input_format != GNU_PORTABLE)
  590. /* shouldn't be seeing a CLOSEPL */
  591. {
  592. if (display_open && maybe_closepl (plotter) < 0)
  593. {
  594. fprintf (stderr, "%s: error: the plot device could not be closed\n",
  595. progname);
  596. exit (EXIT_FAILURE);
  597. }
  598. current_page++;
  599. return false; /* signal a parse error */
  600. }
  601. else
  602. /* GNU_BINARY or GNU_PORTABLE format, so this may be legitimate */
  603. {
  604. if (in_page == false)
  605. /* shouldn't be seeing a CLOSEPL */
  606. {
  607. current_page++;
  608. return false; /* signal a parse error */
  609. }
  610. else
  611. /* the CLOSEPL is legitimate */
  612. {
  613. if (!single_page_is_requested
  614. || current_page == requested_page)
  615. {
  616. if (maybe_closepl (plotter) < 0)
  617. {
  618. fprintf (stderr,
  619. "%s: error: the plot device could not be closed\n",
  620. progname);
  621. exit (EXIT_FAILURE);
  622. }
  623. display_open = false;
  624. }
  625. in_page = false;
  626. current_page++; /* `page' is an OPENPL..CLOSEPL */
  627. }
  628. }
  629. break;
  630. case (int)O_COMMENT:
  631. s = read_string (in_stream, &argerr);
  632. if (!argerr)
  633. {
  634. /* if a header line, switch to appropriate modern format */
  635. if (first_command
  636. && input_format != PLOT5_HIGH
  637. && input_format != PLOT5_LOW
  638. && (strlen (s) >= 6)
  639. /* check magic number */
  640. && strncmp (s, "PLOT ", 5) == 0)
  641. switch (s[5])
  642. {
  643. case '1':
  644. input_format = GNU_BINARY;
  645. break;
  646. case '2':
  647. input_format = GNU_PORTABLE;
  648. break;
  649. default:
  650. fprintf (stderr,
  651. "%s: the input file is of an unrecognized metafile type\n",
  652. progname);
  653. break;
  654. }
  655. free (s);
  656. }
  657. break;
  658. case (int)O_CONT:
  659. x0 = read_int (in_stream, &argerr);
  660. y0 = read_int (in_stream, &argerr);
  661. if (!argerr)
  662. if (!single_page_is_requested || current_page == requested_page)
  663. pl_fcont_r (plotter, x0, y0);
  664. break;
  665. case (int)O_CONTREL:
  666. x0 = read_int (in_stream, &argerr);
  667. y0 = read_int (in_stream, &argerr);
  668. if (!argerr)
  669. if (!single_page_is_requested || current_page == requested_page)
  670. pl_fcontrel_r (plotter, x0, y0);
  671. break;
  672. case (int)O_ELLARC:
  673. x0 = read_int (in_stream, &argerr);
  674. y0 = read_int (in_stream, &argerr);
  675. x1 = read_int (in_stream, &argerr);
  676. y1 = read_int (in_stream, &argerr);
  677. x2 = read_int (in_stream, &argerr);
  678. y2 = read_int (in_stream, &argerr);
  679. if (!argerr)
  680. if (!single_page_is_requested || current_page == requested_page)
  681. pl_fellarc_r (plotter, x0, y0, x1, y1, x2, y2);
  682. break;
  683. case (int)O_ELLARCREL:
  684. x0 = read_int (in_stream, &argerr);
  685. y0 = read_int (in_stream, &argerr);
  686. x1 = read_int (in_stream, &argerr);
  687. y1 = read_int (in_stream, &argerr);
  688. x2 = read_int (in_stream, &argerr);
  689. y2 = read_int (in_stream, &argerr);
  690. if (!argerr)
  691. if (!single_page_is_requested || current_page == requested_page)
  692. pl_fellarcrel_r (plotter, x0, y0, x1, y1, x2, y2);
  693. break;
  694. case (int)O_ELLIPSE:
  695. x0 = read_int (in_stream, &argerr);
  696. y0 = read_int (in_stream, &argerr);
  697. x1 = read_int (in_stream, &argerr);
  698. y1 = read_int (in_stream, &argerr);
  699. x2 = read_int (in_stream, &argerr);
  700. if (!argerr)
  701. if (!single_page_is_requested || current_page == requested_page)
  702. pl_fellipse_r (plotter, x0, y0, x1, y1, x2);
  703. break;
  704. case (int)O_ELLIPSEREL:
  705. x0 = read_int (in_stream, &argerr);
  706. y0 = read_int (in_stream, &argerr);
  707. x1 = read_int (in_stream, &argerr);
  708. y1 = read_int (in_stream, &argerr);
  709. x2 = read_int (in_stream, &argerr);
  710. if (!argerr)
  711. if (!single_page_is_requested || current_page == requested_page)
  712. pl_fellipserel_r (plotter, x0, y0, x1, y1, x2);
  713. break;
  714. case (int)O_ENDPATH:
  715. if (!single_page_is_requested || current_page == requested_page)
  716. pl_endpath_r (plotter);
  717. break;
  718. case (int)O_ENDSUBPATH:
  719. if (!single_page_is_requested || current_page == requested_page)
  720. pl_endsubpath_r (plotter);
  721. break;
  722. case (int)O_ERASE:
  723. if (!single_page_is_requested || current_page == requested_page)
  724. if (merge_pages == false) /* i.e. not merging frames */
  725. pl_erase_r (plotter);
  726. break;
  727. case (int)O_FILLCOLOR:
  728. /* parse args as unsigned ints rather than ints */
  729. i0 = read_true_int (in_stream, &argerr)&0xFFFF;
  730. i1 = read_true_int (in_stream, &argerr)&0xFFFF;
  731. i2 = read_true_int (in_stream, &argerr)&0xFFFF;
  732. if (!argerr)
  733. if (!single_page_is_requested || current_page == requested_page)
  734. pl_fillcolor_r (plotter, i0, i1, i2);
  735. break;
  736. case (int)O_FILLMOD:
  737. s = read_string (in_stream, &argerr);
  738. if (!argerr)
  739. {
  740. if (!single_page_is_requested || current_page == requested_page)
  741. pl_fillmod_r (plotter, s);
  742. free (s);
  743. }
  744. break;
  745. case (int)O_FILLTYPE:
  746. /* parse args as unsigned ints rather than ints */
  747. i0 = read_true_int (in_stream, &argerr)&0xFFFF;
  748. if (!argerr)
  749. if (!single_page_is_requested || current_page == requested_page)
  750. pl_filltype_r (plotter, i0);
  751. break;
  752. case (int)O_FONTNAME:
  753. s = read_string (in_stream, &argerr);
  754. if (!argerr)
  755. {
  756. if (!single_page_is_requested || current_page == requested_page)
  757. pl_fontname_r (plotter, s);
  758. free (s);
  759. }
  760. break;
  761. case (int)O_FONTSIZE:
  762. x0 = read_int (in_stream, &argerr);
  763. if (input_format == GNU_BINARY || input_format == GNU_PORTABLE)
  764. /* workaround, see comment above */
  765. {
  766. if (!argerr)
  767. if (!single_page_is_requested
  768. || current_page == requested_page)
  769. pl_ffontsize_r (plotter, x0);
  770. }
  771. break;
  772. case (int)O_JOINMOD:
  773. s = read_string (in_stream, &argerr);
  774. if (!argerr)
  775. {
  776. if (!single_page_is_requested || current_page == requested_page)
  777. pl_joinmod_r (plotter, s);
  778. free (s);
  779. }
  780. break;
  781. case (int)O_LABEL:
  782. s = read_string (in_stream, &argerr);
  783. if (!argerr)
  784. {
  785. if (!single_page_is_requested || current_page == requested_page)
  786. pl_label_r (plotter, s);
  787. free (s);
  788. }
  789. break;
  790. case (int)O_LINE:
  791. x0 = read_int (in_stream, &argerr);
  792. y0 = read_int (in_stream, &argerr);
  793. x1 = read_int (in_stream, &argerr);
  794. y1 = read_int (in_stream, &argerr);
  795. if (!argerr)
  796. if (!single_page_is_requested || current_page == requested_page)
  797. pl_fline_r (plotter, x0, y0, x1, y1);
  798. break;
  799. case (int)O_LINEDASH:
  800. {
  801. int n, i;
  802. double *dash_array, phase;
  803. n = read_true_int (in_stream, &argerr);
  804. if (n > 0)
  805. dash_array = (double *)xmalloc((unsigned int)n * sizeof(double));
  806. else
  807. dash_array = NULL;
  808. for (i = 0; i < n; i++)
  809. dash_array[i] = read_int (in_stream, &argerr);
  810. phase = read_int (in_stream, &argerr);
  811. if (!argerr)
  812. if (!single_page_is_requested || current_page == requested_page)
  813. pl_flinedash_r (plotter, n, dash_array, phase);
  814. free (dash_array);
  815. break;
  816. }
  817. case (int)O_LINEREL:
  818. x0 = read_int (in_stream, &argerr);
  819. y0 = read_int (in_stream, &argerr);
  820. x1 = read_int (in_stream, &argerr);
  821. y1 = read_int (in_stream, &argerr);
  822. if (!argerr)
  823. if (!single_page_is_requested || current_page == requested_page)
  824. pl_flinerel_r (plotter, x0, y0, x1, y1);
  825. break;
  826. case (int)O_LINEMOD:
  827. s = read_string (in_stream, &argerr);
  828. if (!argerr)
  829. {
  830. if (!single_page_is_requested || current_page == requested_page)
  831. pl_linemod_r (plotter, s);
  832. free (s);
  833. }
  834. break;
  835. case (int)O_LINEWIDTH:
  836. x0 = read_int (in_stream, &argerr);
  837. if (!argerr)
  838. if (!single_page_is_requested || current_page == requested_page)
  839. pl_flinewidth_r (plotter, x0);
  840. break;
  841. case (int)O_MARKER:
  842. x0 = read_int (in_stream, &argerr);
  843. y0 = read_int (in_stream, &argerr);
  844. i0 = read_true_int (in_stream, &argerr);
  845. y1 = read_int (in_stream, &argerr);
  846. if (!argerr)
  847. if (!single_page_is_requested || current_page == requested_page)
  848. pl_fmarker_r (plotter, x0, y0, i0, y1);
  849. break;
  850. case (int)O_MARKERREL:
  851. x0 = read_int (in_stream, &argerr);
  852. y0 = read_int (in_stream, &argerr);
  853. i0 = read_true_int (in_stream, &argerr);
  854. y1 = read_int (in_stream, &argerr);
  855. if (!argerr)
  856. if (!single_page_is_requested || current_page == requested_page)
  857. pl_fmarkerrel_r (plotter, x0, y0, i0, y1);
  858. break;
  859. case (int)O_MOVE:
  860. x0 = read_int (in_stream, &argerr);
  861. y0 = read_int (in_stream, &argerr);
  862. if (!argerr)
  863. if (!single_page_is_requested || current_page == requested_page)
  864. pl_fmove_r (plotter, x0, y0);
  865. break;
  866. case (int)O_MOVEREL:
  867. x0 = read_int (in_stream, &argerr);
  868. y0 = read_int (in_stream, &argerr);
  869. if (!argerr)
  870. if (!single_page_is_requested || current_page == requested_page)
  871. pl_fmoverel_r (plotter, x0, y0);
  872. break;
  873. case (int)O_OPENPL:
  874. if (input_format != GNU_BINARY && input_format != GNU_PORTABLE)
  875. /* shouldn't be seeing an OPENPL */
  876. {
  877. if (display_open && maybe_closepl (plotter) < 0)
  878. {
  879. fprintf (stderr, "%s: error: the plot device could not be closed\n",
  880. progname);
  881. exit (EXIT_FAILURE);
  882. }
  883. current_page++;
  884. return false; /* signal a parse error */
  885. }
  886. else
  887. /* GNU_BINARY or GNU_PORTABLE format, so may be legitimate */
  888. {
  889. if (in_page)
  890. /* shouldn't be seeing another OPENPL */
  891. {
  892. if (display_open && maybe_closepl (plotter) < 0)
  893. {
  894. fprintf (stderr,
  895. "%s: error: the plot device could not be closed\n",
  896. progname);
  897. exit (EXIT_FAILURE);
  898. }
  899. current_page++;
  900. return false; /* signal a parse error */
  901. }
  902. /* this OPENPL is legitimate */
  903. if (!single_page_is_requested || current_page == requested_page)
  904. {
  905. if (maybe_openpl (plotter) < 0)
  906. {
  907. fprintf (stderr,
  908. "%s: error: the plot device could not be opened\n",
  909. progname);
  910. exit (EXIT_FAILURE);
  911. }
  912. else
  913. display_open = true;
  914. }
  915. /* we're now in an openpl..closepl pair */
  916. in_page = true;
  917. }
  918. break;
  919. case (int)O_ORIENTATION:
  920. i0 = read_true_int (in_stream, &argerr);
  921. if (!argerr)
  922. if (!single_page_is_requested || current_page == requested_page)
  923. pl_orientation_r (plotter, i0);
  924. break;
  925. case (int)O_PENCOLOR:
  926. /* parse args as unsigned ints rather than ints */
  927. i0 = read_true_int (in_stream, &argerr)&0xFFFF;
  928. i1 = read_true_int (in_stream, &argerr)&0xFFFF;
  929. i2 = read_true_int (in_stream, &argerr)&0xFFFF;
  930. if (!argerr)
  931. if (!single_page_is_requested || current_page == requested_page)
  932. pl_pencolor_r (plotter, i0, i1, i2);
  933. break;
  934. case (int)O_PENTYPE:
  935. /* parse args as unsigned ints rather than ints */
  936. i0 = read_true_int (in_stream, &argerr)&0xFFFF;
  937. if (!argerr)
  938. if (!single_page_is_requested || current_page == requested_page)
  939. pl_pentype_r (plotter, i0);
  940. break;
  941. case (int)O_POINT:
  942. x0 = read_int (in_stream, &argerr);
  943. y0 = read_int (in_stream, &argerr);
  944. if (!argerr)
  945. if (!single_page_is_requested || current_page == requested_page)
  946. pl_fpoint_r (plotter, x0, y0);
  947. break;
  948. case (int)O_POINTREL:
  949. x0 = read_int (in_stream, &argerr);
  950. y0 = read_int (in_stream, &argerr);
  951. if (!argerr)
  952. if (!single_page_is_requested || current_page == requested_page)
  953. pl_fpointrel_r (plotter, x0, y0);
  954. break;
  955. case (int)O_RESTORESTATE:
  956. if (!single_page_is_requested || current_page == requested_page)
  957. pl_restorestate_r (plotter);
  958. break;
  959. case (int)O_SAVESTATE:
  960. if (!single_page_is_requested || current_page == requested_page)
  961. pl_savestate_r (plotter);
  962. break;
  963. case (int)O_SPACE:
  964. x0 = read_int (in_stream, &argerr);
  965. y0 = read_int (in_stream, &argerr);
  966. x1 = read_int (in_stream, &argerr);
  967. y1 = read_int (in_stream, &argerr);
  968. if (argerr)
  969. break;
  970. if (!single_page_is_requested || current_page == requested_page)
  971. pl_fspace_r (plotter, x0, y0, x1, y1);
  972. if (parameters_initted == false &&
  973. ((!single_page_is_requested && current_page == 1)
  974. || (single_page_is_requested && current_page == requested_page)))
  975. /* insert these after the call to space(), if user insists on
  976. including them (should estimate sizes better) */
  977. {
  978. if (pen_color)
  979. pl_pencolorname_r (plotter, pen_color);
  980. if (font_name)
  981. pl_fontname_r (plotter, font_name);
  982. if (font_size >= 0.0)
  983. pl_ffontsize_r (plotter, font_size * fabs (x1 - x0));
  984. if (line_width >= 0.0)
  985. pl_flinewidth_r (plotter, line_width * fabs (x1 - x0));
  986. parameters_initted = true;
  987. }
  988. break;
  989. case (int)O_SPACE2:
  990. x0 = read_int (in_stream, &argerr);
  991. y0 = read_int (in_stream, &argerr);
  992. x1 = read_int (in_stream, &argerr);
  993. y1 = read_int (in_stream, &argerr);
  994. x2 = read_int (in_stream, &argerr);
  995. y2 = read_int (in_stream, &argerr);
  996. if (argerr)
  997. break;
  998. if (!single_page_is_requested || current_page == requested_page)
  999. pl_fspace2_r (plotter, x0, y0, x1, y1, x2, y2);
  1000. if (parameters_initted == false &&
  1001. ((!single_page_is_requested && current_page == 1)
  1002. || (single_page_is_requested && current_page == requested_page)))
  1003. /* insert these after the call to space2(), if user insists on
  1004. including them (should estimate sizes better) */
  1005. {
  1006. if (bg_color)
  1007. {
  1008. pl_bgcolorname_r (plotter, bg_color);
  1009. pl_erase_r (plotter);
  1010. }
  1011. if (pen_color)
  1012. pl_pencolorname_r (plotter, pen_color);
  1013. if (font_name)
  1014. pl_fontname_r (plotter, font_name);
  1015. if (font_size >= 0.0)
  1016. pl_ffontsize_r (plotter, font_size * fabs (x1 - x0));
  1017. if (line_width >= 0.0)
  1018. pl_flinewidth_r (plotter, line_width * fabs (x1 - x0));
  1019. parameters_initted = true;
  1020. }
  1021. break;
  1022. case (int)O_TEXTANGLE:
  1023. x0 = read_int (in_stream, &argerr);
  1024. if (!argerr)
  1025. if (!single_page_is_requested || current_page == requested_page)
  1026. pl_ftextangle_r (plotter, x0);
  1027. break;
  1028. /* floating point counterparts to some of the above */
  1029. case (int)O_FARC:
  1030. x0 = read_float (in_stream, &argerr);
  1031. y0 = read_float (in_stream, &argerr);
  1032. x1 = read_float (in_stream, &argerr);
  1033. y1 = read_float (in_stream, &argerr);
  1034. x2 = read_float (in_stream, &argerr);
  1035. y2 = read_float (in_stream, &argerr);
  1036. if (!argerr)
  1037. if (!single_page_is_requested || current_page == requested_page)
  1038. pl_farc_r (plotter, x0, y0, x1, y1, x2, y2);
  1039. break;
  1040. case (int)O_FARCREL:
  1041. x0 = read_float (in_stream, &argerr);
  1042. y0 = read_float (in_stream, &argerr);
  1043. x1 = read_float (in_stream, &argerr);
  1044. y1 = read_float (in_stream, &argerr);
  1045. x2 = read_float (in_stream, &argerr);
  1046. y2 = read_float (in_stream, &argerr);
  1047. if (!argerr)
  1048. if (!single_page_is_requested || current_page == requested_page)
  1049. pl_farcrel_r (plotter, x0, y0, x1, y1, x2, y2);
  1050. break;
  1051. case (int)O_FBEZIER2:
  1052. x0 = read_float (in_stream, &argerr);
  1053. y0 = read_float (in_stream, &argerr);
  1054. x1 = read_float (in_stream, &argerr);
  1055. y1 = read_float (in_stream, &argerr);
  1056. x2 = read_float (in_stream, &argerr);
  1057. y2 = read_float (in_stream, &argerr);
  1058. if (!argerr)
  1059. if (!single_page_is_requested || current_page == requested_page)
  1060. pl_fbezier2_r (plotter, x0, y0, x1, y1, x2, y2);
  1061. break;
  1062. case (int)O_FBEZIER2REL:
  1063. x0 = read_float (in_stream, &argerr);
  1064. y0 = read_float (in_stream, &argerr);
  1065. x1 = read_float (in_stream, &argerr);
  1066. y1 = read_float (in_stream, &argerr);
  1067. x2 = read_float (in_stream, &argerr);
  1068. y2 = read_float (in_stream, &argerr);
  1069. if (!argerr)
  1070. if (!single_page_is_requested || current_page == requested_page)
  1071. pl_fbezier2rel_r (plotter, x0, y0, x1, y1, x2, y2);
  1072. break;
  1073. case (int)O_FBEZIER3:
  1074. x0 = read_float (in_stream, &argerr);
  1075. y0 = read_float (in_stream, &argerr);
  1076. x1 = read_float (in_stream, &argerr);
  1077. y1 = read_float (in_stream, &argerr);
  1078. x2 = read_float (in_stream, &argerr);
  1079. y2 = read_float (in_stream, &argerr);
  1080. x3 = read_float (in_stream, &argerr);
  1081. y3 = read_float (in_stream, &argerr);
  1082. if (!argerr)
  1083. if (!single_page_is_requested || current_page == requested_page)
  1084. pl_fbezier3_r (plotter, x0, y0, x1, y1, x2, y2, x3, y3);
  1085. break;
  1086. case (int)O_FBEZIER3REL:
  1087. x0 = read_float (in_stream, &argerr);
  1088. y0 = read_float (in_stream, &argerr);
  1089. x1 = read_float (in_stream, &argerr);
  1090. y1 = read_float (in_stream, &argerr);
  1091. x2 = read_float (in_stream, &argerr);
  1092. y2 = read_float (in_stream, &argerr);
  1093. x3 = read_float (in_stream, &argerr);
  1094. y3 = read_float (in_stream, &argerr);
  1095. if (!argerr)
  1096. if (!single_page_is_requested || current_page == requested_page)
  1097. pl_fbezier3rel_r (plotter, x0, y0, x1, y1, x2, y2, x3, y3);
  1098. break;
  1099. case (int)O_FBOX:
  1100. x0 = read_float (in_stream, &argerr);
  1101. y0 = read_float (in_stream, &argerr);
  1102. x1 = read_float (in_stream, &argerr);
  1103. y1 = read_float (in_stream, &argerr);
  1104. if (!argerr)
  1105. if (!single_page_is_requested || current_page == requested_page)
  1106. pl_fbox_r (plotter, x0, y0, x1, y1);
  1107. break;
  1108. case (int)O_FBOXREL:
  1109. x0 = read_float (in_stream, &argerr);
  1110. y0 = read_float (in_stream, &argerr);
  1111. x1 = read_float (in_stream, &argerr);
  1112. y1 = read_float (in_stream, &argerr);
  1113. if (!argerr)
  1114. if (!single_page_is_requested || current_page == requested_page)
  1115. pl_fboxrel_r (plotter, x0, y0, x1, y1);
  1116. break;
  1117. case (int)O_FCIRCLE:
  1118. x0 = read_float (in_stream, &argerr);
  1119. y0 = read_float (in_stream, &argerr);
  1120. x1 = read_float (in_stream, &argerr);
  1121. if (!argerr)
  1122. if (!single_page_is_requested || current_page == requested_page)
  1123. pl_fcircle_r (plotter, x0, y0, x1);
  1124. break;
  1125. case (int)O_FCIRCLEREL:
  1126. x0 = read_float (in_stream, &argerr);
  1127. y0 = read_float (in_stream, &argerr);
  1128. x1 = read_float (in_stream, &argerr);
  1129. if (!argerr)
  1130. if (!single_page_is_requested || current_page == requested_page)
  1131. pl_fcirclerel_r (plotter, x0, y0, x1);
  1132. break;
  1133. case (int)O_FCONT:
  1134. x0 = read_float (in_stream, &argerr);
  1135. y0 = read_float (in_stream, &argerr);
  1136. if (!argerr)
  1137. if (!single_page_is_requested || current_page == requested_page)
  1138. pl_fcont_r (plotter, x0, y0);
  1139. break;
  1140. case (int)O_FCONTREL:
  1141. x0 = read_float (in_stream, &argerr);
  1142. y0 = read_float (in_stream, &argerr);
  1143. if (!argerr)
  1144. if (!single_page_is_requested || current_page == requested_page)
  1145. pl_fcontrel_r (plotter, x0, y0);
  1146. break;
  1147. case (int)O_FELLARC:
  1148. x0 = read_float (in_stream, &argerr);
  1149. y0 = read_float (in_stream, &argerr);
  1150. x1 = read_float (in_stream, &argerr);
  1151. y1 = read_float (in_stream, &argerr);
  1152. x2 = read_float (in_stream, &argerr);
  1153. y2 = read_float (in_stream, &argerr);
  1154. if (!argerr)
  1155. if (!single_page_is_requested || current_page == requested_page)
  1156. pl_fellarc_r (plotter, x0, y0, x1, y1, x2, y2);
  1157. break;
  1158. case (int)O_FELLARCREL:
  1159. x0 = read_float (in_stream, &argerr);
  1160. y0 = read_float (in_stream, &argerr);
  1161. x1 = read_float (in_stream, &argerr);
  1162. y1 = read_float (in_stream, &argerr);
  1163. x2 = read_float (in_stream, &argerr);
  1164. y2 = read_float (in_stream, &argerr);
  1165. if (!argerr)
  1166. if (!single_page_is_requested || current_page == requested_page)
  1167. pl_fellarcrel_r (plotter, x0, y0, x1, y1, x2, y2);
  1168. break;
  1169. case (int)O_FELLIPSE:
  1170. x0 = read_float (in_stream, &argerr);
  1171. y0 = read_float (in_stream, &argerr);
  1172. x1 = read_float (in_stream, &argerr);
  1173. y1 = read_float (in_stream, &argerr);
  1174. x2 = read_float (in_stream, &argerr);
  1175. if (!argerr)
  1176. if (!single_page_is_requested || current_page == requested_page)
  1177. pl_fellipse_r (plotter, x0, y0, x1, y1, x2);
  1178. break;
  1179. case (int)O_FELLIPSEREL:
  1180. x0 = read_float (in_stream, &argerr);
  1181. y0 = read_float (in_stream, &argerr);
  1182. x1 = read_float (in_stream, &argerr);
  1183. y1 = read_float (in_stream, &argerr);
  1184. x2 = read_float (in_stream, &argerr);
  1185. if (!argerr)
  1186. if (!single_page_is_requested || current_page == requested_page)
  1187. pl_fellipserel_r (plotter, x0, y0, x1, y1, x2);
  1188. break;
  1189. case (int)O_FFONTSIZE:
  1190. x0 = read_float (in_stream, &argerr);
  1191. if (input_format == GNU_BINARY || input_format == GNU_PORTABLE)
  1192. /* workaround, see comment above */
  1193. {
  1194. if (!argerr)
  1195. if (!single_page_is_requested || current_page == requested_page)
  1196. pl_ffontsize_r (plotter, x0);
  1197. }
  1198. break;
  1199. case (int)O_FLINE:
  1200. x0 = read_float (in_stream, &argerr);
  1201. y0 = read_float (in_stream, &argerr);
  1202. x1 = read_float (in_stream, &argerr);
  1203. y1 = read_float (in_stream, &argerr);
  1204. if (!argerr)
  1205. if (!single_page_is_requested || current_page == requested_page)
  1206. pl_fline_r (plotter, x0, y0, x1, y1);
  1207. break;
  1208. case (int)O_FLINEDASH:
  1209. {
  1210. int n, i;
  1211. double *dash_array, phase;
  1212. n = read_true_int (in_stream, &argerr);
  1213. if (n > 0)
  1214. dash_array = (double *)xmalloc((unsigned int)n * sizeof(double));
  1215. else
  1216. dash_array = NULL;
  1217. for (i = 0; i < n; i++)
  1218. dash_array[i] = read_float (in_stream, &argerr);
  1219. phase = read_float (in_stream, &argerr);
  1220. if (!argerr)
  1221. if (!single_page_is_requested || current_page == requested_page)
  1222. pl_flinedash_r (plotter, n, dash_array, phase);
  1223. free (dash_array);
  1224. break;
  1225. }
  1226. case (int)O_FLINEREL:
  1227. x0 = read_float (in_stream, &argerr);
  1228. y0 = read_float (in_stream, &argerr);
  1229. x1 = read_float (in_stream, &argerr);
  1230. y1 = read_float (in_stream, &argerr);
  1231. if (!argerr)
  1232. if (!single_page_is_requested || current_page == requested_page)
  1233. pl_flinerel_r (plotter, x0, y0, x1, y1);
  1234. break;
  1235. case (int)O_FLINEWIDTH:
  1236. x0 = read_float (in_stream, &argerr);
  1237. if (!argerr)
  1238. if (!single_page_is_requested || current_page == requested_page)
  1239. pl_flinewidth_r (plotter, x0);
  1240. break;
  1241. case (int)O_FMARKER:
  1242. x0 = read_float (in_stream, &argerr);
  1243. y0 = read_float (in_stream, &argerr);
  1244. i0 = read_true_int (in_stream, &argerr);
  1245. y1 = read_float (in_stream, &argerr);
  1246. if (!argerr)
  1247. if (!single_page_is_requested || current_page == requested_page)
  1248. pl_fmarker_r (plotter, x0, y0, i0, y1);
  1249. break;
  1250. case (int)O_FMARKERREL:
  1251. x0 = read_float (in_stream, &argerr);
  1252. y0 = read_float (in_stream, &argerr);
  1253. i0 = read_true_int (in_stream, &argerr);
  1254. y1 = read_float (in_stream, &argerr);
  1255. if (!argerr)
  1256. if (!single_page_is_requested || current_page == requested_page)
  1257. pl_fmarkerrel_r (plotter, x0, y0, i0, y1);
  1258. break;
  1259. case (int)O_FMOVE:
  1260. x0 = read_float (in_stream, &argerr);
  1261. y0 = read_float (in_stream, &argerr);
  1262. if (!argerr)
  1263. if (!single_page_is_requested || current_page == requested_page)
  1264. pl_fmove_r (plotter, x0, y0);
  1265. break;
  1266. case (int)O_FMOVEREL:
  1267. x0 = read_float (in_stream, &argerr);
  1268. y0 = read_float (in_stream, &argerr);
  1269. if (!argerr)
  1270. if (!single_page_is_requested || current_page == requested_page)
  1271. pl_fmoverel_r (plotter, x0, y0);
  1272. break;
  1273. case (int)O_FPOINT:
  1274. x0 = read_float (in_stream, &argerr);
  1275. y0 = read_float (in_stream, &argerr);
  1276. if (!argerr)
  1277. if (!single_page_is_requested || current_page == requested_page)
  1278. pl_fpoint_r (plotter, x0, y0);
  1279. break;
  1280. case (int)O_FPOINTREL:
  1281. x0 = read_float (in_stream, &argerr);
  1282. y0 = read_float (in_stream, &argerr);
  1283. if (!single_page_is_requested || current_page == requested_page)
  1284. pl_fpointrel_r (plotter, x0, y0);
  1285. break;
  1286. case (int)O_FSPACE:
  1287. x0 = read_float (in_stream, &argerr);
  1288. y0 = read_float (in_stream, &argerr);
  1289. x1 = read_float (in_stream, &argerr);
  1290. y1 = read_float (in_stream, &argerr);
  1291. if (argerr)
  1292. break;
  1293. if (!single_page_is_requested || current_page == requested_page)
  1294. pl_fspace_r (plotter, x0, y0, x1, y1);
  1295. if (parameters_initted == false &&
  1296. ((!single_page_is_requested && current_page == 1)
  1297. || (single_page_is_requested && current_page == requested_page)))
  1298. /* insert these after the call to fspace(), if user insists on
  1299. including them (should estimate sizes better) */
  1300. {
  1301. if (bg_color)
  1302. {
  1303. pl_bgcolorname_r (plotter, bg_color);
  1304. pl_erase_r (plotter);
  1305. }
  1306. if (pen_color)
  1307. pl_pencolorname_r (plotter, pen_color);
  1308. if (font_name)
  1309. pl_fontname_r (plotter, font_name);
  1310. if (font_size >= 0.0)
  1311. pl_ffontsize_r (plotter, font_size * fabs (x1 - x0));
  1312. if (line_width >= 0.0)
  1313. pl_flinewidth_r (plotter, line_width * fabs (x1 - x0));
  1314. parameters_initted = true;
  1315. }
  1316. break;
  1317. case (int)O_FSPACE2:
  1318. x0 = read_float (in_stream, &argerr);
  1319. y0 = read_float (in_stream, &argerr);
  1320. x1 = read_float (in_stream, &argerr);
  1321. y1 = read_float (in_stream, &argerr);
  1322. x2 = read_float (in_stream, &argerr);
  1323. y2 = read_float (in_stream, &argerr);
  1324. if (argerr)
  1325. break;
  1326. if (!single_page_is_requested || current_page == requested_page)
  1327. pl_fspace2_r (plotter, x0, y0, x1, y1, x2, y2);
  1328. if (parameters_initted == false &&
  1329. ((!single_page_is_requested && current_page == 1)
  1330. || (single_page_is_requested && current_page == requested_page)))
  1331. /* insert these after the call to fspace2(), if user insists on
  1332. including them (should estimate sizes better) */
  1333. {
  1334. if (bg_color)
  1335. {
  1336. pl_bgcolorname_r (plotter, bg_color);
  1337. pl_erase_r (plotter);
  1338. }
  1339. if (pen_color)
  1340. pl_pencolorname_r (plotter, pen_color);
  1341. if (font_name)
  1342. pl_fontname_r (plotter, font_name);
  1343. if (font_size >= 0.0)
  1344. pl_ffontsize_r (plotter, font_size * fabs (x1 - x0));
  1345. if (line_width >= 0.0)
  1346. pl_flinewidth_r (plotter, line_width * fabs (x1 - x0));
  1347. parameters_initted = true;
  1348. }
  1349. break;
  1350. case (int)O_FTEXTANGLE:
  1351. x0 = read_float (in_stream, &argerr);
  1352. if (!argerr)
  1353. if (!single_page_is_requested || current_page == requested_page)
  1354. pl_ftextangle_r (plotter, x0);
  1355. break;
  1356. /* floating point routines with no integer counterpart */
  1357. case (int)O_FCONCAT:
  1358. x0 = read_float (in_stream, &argerr);
  1359. y0 = read_float (in_stream, &argerr);
  1360. x1 = read_float (in_stream, &argerr);
  1361. y1 = read_float (in_stream, &argerr);
  1362. x2 = read_float (in_stream, &argerr);
  1363. y2 = read_float (in_stream, &argerr);
  1364. if (!argerr)
  1365. if (!single_page_is_requested || current_page == requested_page)
  1366. pl_fconcat_r (plotter, x0, y0, x1, y1, x2, y2);
  1367. break;
  1368. case (int)O_FMITERLIMIT:
  1369. x0 = read_float (in_stream, &argerr);
  1370. if (!argerr)
  1371. if (!single_page_is_requested || current_page == requested_page)
  1372. pl_fmiterlimit_r (plotter, x0);
  1373. break;
  1374. case (int)O_FSETMATRIX:
  1375. x0 = read_float (in_stream, &argerr);
  1376. y0 = read_float (in_stream, &argerr);
  1377. x1 = read_float (in_stream, &argerr);
  1378. y1 = read_float (in_stream, &argerr);
  1379. x2 = read_float (in_stream, &argerr);
  1380. y2 = read_float (in_stream, &argerr);
  1381. if (!argerr)
  1382. if (!single_page_is_requested || current_page == requested_page)
  1383. pl_fsetmatrix_r (plotter, x0, y0, x1, y1, x2, y2);
  1384. if (parameters_initted == false &&
  1385. ((!single_page_is_requested && current_page == 1)
  1386. || (single_page_is_requested && current_page == requested_page)))
  1387. /* insert these after the call to fsetmatrix(), if user insists
  1388. on including them (should estimate sizes better) */
  1389. {
  1390. if (pen_color)
  1391. pl_pencolorname_r (plotter, pen_color);
  1392. if (font_name)
  1393. pl_fontname_r (plotter, font_name);
  1394. if (x0 != 0.0)
  1395. {
  1396. if (font_size >= 0.0)
  1397. pl_ffontsize_r (plotter, font_size / fabs (x0));
  1398. if (line_width >= 0.0)
  1399. pl_flinewidth_r (plotter, line_width / fabs (x0));
  1400. }
  1401. parameters_initted = true;
  1402. }
  1403. break;
  1404. case (int)O_FROTATE: /* obsolete op code, to be removed */
  1405. x0 = read_float (in_stream, &argerr);
  1406. if (!argerr)
  1407. if (!single_page_is_requested || current_page == requested_page)
  1408. pl_frotate_r (plotter, x0);
  1409. break;
  1410. case (int)O_FSCALE: /* obsolete op code, to be removed */
  1411. x0 = read_float (in_stream, &argerr);
  1412. y0 = read_float (in_stream, &argerr);
  1413. if (!argerr)
  1414. if (!single_page_is_requested || current_page == requested_page)
  1415. pl_fscale_r (plotter, x0, y0);
  1416. break;
  1417. case (int)O_FTRANSLATE: /* obsolete op code, to be removed */
  1418. x0 = read_float (in_stream, &argerr);
  1419. y0 = read_float (in_stream, &argerr);
  1420. if (!argerr)
  1421. if (!single_page_is_requested || current_page == requested_page)
  1422. pl_ftranslate_r (plotter, x0, y0);
  1423. break;
  1424. case ' ':
  1425. case '\n':
  1426. case '\r':
  1427. case '\t':
  1428. case '\v':
  1429. case '\f':
  1430. /* extra whitespace is all right in portable formats */
  1431. if (input_format == GNU_PORTABLE
  1432. || input_format == GNU_OLD_PORTABLE)
  1433. break;
  1434. else /* not harmless */
  1435. unrec = true;
  1436. break;
  1437. default:
  1438. unrec = true;
  1439. break;
  1440. } /* end of switch() */
  1441. first_command = false;
  1442. if (unrec)
  1443. {
  1444. fprintf (stderr, "%s: an unrecognized command `0x%x' was encountered in the input\n",
  1445. progname, instruction);
  1446. break; /* break out of while loop */
  1447. }
  1448. if (argerr)
  1449. {
  1450. int eof = feof (in_stream);
  1451. if (eof)
  1452. fprintf (stderr, "%s: the input terminated prematurely\n",
  1453. progname);
  1454. else
  1455. fprintf (stderr, "%s: the argument of the command `0x%x' in the input could not be parsed\n",
  1456. progname, instruction);
  1457. break; /* break out of while loop */
  1458. }
  1459. instruction = getc (in_stream); /* get next instruction */
  1460. } /* end of while loop, EOF reached */
  1461. if (input_format != GNU_BINARY && input_format != GNU_PORTABLE)
  1462. /* if a premodern format, this file contains only one page */
  1463. {
  1464. /* close display device at EOF, if it was ever opened */
  1465. if (display_open && maybe_closepl (plotter) < 0)
  1466. {
  1467. fprintf (stderr, "%s: error: the plot device could not be closed\n",
  1468. progname);
  1469. exit (EXIT_FAILURE);
  1470. }
  1471. current_page++; /* bump page count at EOF */
  1472. }
  1473. else
  1474. /* file is in a modern format, should have closed display device (if it
  1475. was ever opened) */
  1476. {
  1477. if (in_page)
  1478. /* shouldn't be the case; parse error */
  1479. {
  1480. if (display_open && maybe_closepl (plotter) < 0)
  1481. {
  1482. fprintf (stderr, "%s: error: the plot device could not be closed\n",
  1483. progname);
  1484. exit (EXIT_FAILURE);
  1485. }
  1486. current_page++;
  1487. return false; /* signal parse error */
  1488. }
  1489. }
  1490. return ((argerr || unrec) ? false : true); /* file parsed successfully? */
  1491. }
  1492. int
  1493. maybe_openpl (plPlotter *plotter)
  1494. {
  1495. if (merge_pages)
  1496. return 0;
  1497. else
  1498. return (pl_openpl_r (plotter));
  1499. }
  1500. int
  1501. maybe_closepl (plPlotter *plotter)
  1502. {
  1503. if (merge_pages)
  1504. return 0;
  1505. else
  1506. return (pl_closepl_r (plotter));
  1507. }
  1508. /* read a single byte from input stream, return as unsigned char (0..255) */
  1509. unsigned char
  1510. read_byte_as_unsigned_char (FILE *input, bool *badstatus)
  1511. {
  1512. int newint;
  1513. if (*badstatus == true)
  1514. return 0;
  1515. newint = getc (input);
  1516. /* have an unsigned char cast to an int, in range 0..255 */
  1517. if (newint == EOF)
  1518. {
  1519. *badstatus = true;
  1520. return 0;
  1521. }
  1522. else
  1523. return (unsigned char)newint;
  1524. }
  1525. /* read a single byte from input stream, return as unsigned int (0..255) */
  1526. unsigned int
  1527. read_byte_as_unsigned_int (FILE *input, bool *badstatus)
  1528. {
  1529. int newint;
  1530. if (*badstatus == true)
  1531. return 0;
  1532. newint = getc (input);
  1533. /* have an unsigned char cast to an int, in range 0..255 */
  1534. if (newint == EOF)
  1535. {
  1536. *badstatus = true;
  1537. return 0;
  1538. }
  1539. else
  1540. return (unsigned int)newint;
  1541. }
  1542. /* read an integer from input stream (can be in ascii format, system binary
  1543. format for integers or short integers, or perhaps in crufty old 2-byte
  1544. format) */
  1545. int
  1546. read_true_int (FILE *input, bool *badstatus)
  1547. {
  1548. int x, zi, returnval;
  1549. short zs;
  1550. unsigned int u;
  1551. if (*badstatus == true)
  1552. return 0;
  1553. switch (input_format)
  1554. {
  1555. case GNU_PORTABLE:
  1556. case GNU_OLD_PORTABLE:
  1557. returnval = fscanf (input, " %d", &x);
  1558. if (returnval != 1)
  1559. {
  1560. x = 0;
  1561. *badstatus = true;
  1562. }
  1563. break;
  1564. case GNU_BINARY: /* system format for integers */
  1565. default:
  1566. returnval = fread (&zi, sizeof(zi), 1, input);
  1567. if (returnval == 1)
  1568. x = zi;
  1569. else
  1570. {
  1571. x = 0;
  1572. *badstatus = true;
  1573. }
  1574. break;
  1575. case GNU_OLD_BINARY: /* system format for short integers */
  1576. returnval = fread (&zs, sizeof(zs), 1, input);
  1577. if (returnval == 1)
  1578. x = (int)zs;
  1579. else
  1580. {
  1581. x = 0;
  1582. *badstatus = true;
  1583. }
  1584. break;
  1585. case PLOT5_HIGH: /* two-byte format, high byte first */
  1586. u = ((read_byte_as_unsigned_int (input, badstatus)) << 8);
  1587. u |= read_byte_as_unsigned_int (input, badstatus);
  1588. if (u > 0x7fff)
  1589. x = - (int)(0x10000 - u);
  1590. else
  1591. x = (int)u;
  1592. break;
  1593. case PLOT5_LOW: /* two-byte format, low byte first */
  1594. u = read_byte_as_unsigned_int (input, badstatus);
  1595. u |= (read_byte_as_unsigned_int (input, badstatus) << 8);
  1596. if (u > 0x7fff)
  1597. x = - (int)(0x10000 - u);
  1598. else
  1599. x = (int)u;
  1600. break;
  1601. }
  1602. return x;
  1603. }
  1604. /* a relaxed version of the preceding routine: if a portable
  1605. (human-readable) format is used, a floating point number may substitute
  1606. for the integer */
  1607. double
  1608. read_int (FILE *input, bool *badstatus)
  1609. {
  1610. int x, zi, returnval;
  1611. short zs;
  1612. unsigned int u;
  1613. if (*badstatus == true)
  1614. return 0.0;
  1615. switch (input_format)
  1616. {
  1617. case GNU_PORTABLE:
  1618. case GNU_OLD_PORTABLE:
  1619. {
  1620. double r;
  1621. returnval = fscanf (input, " %lf", &r);
  1622. if (returnval != 1)
  1623. {
  1624. *badstatus = true;
  1625. r = 0.0;
  1626. }
  1627. return r;
  1628. }
  1629. case GNU_BINARY: /* system format for integers */
  1630. default:
  1631. returnval = fread (&zi, sizeof(zi), 1, input);
  1632. if (returnval == 1)
  1633. x = (int)zi;
  1634. else
  1635. {
  1636. x = 0;
  1637. *badstatus = true;
  1638. }
  1639. break;
  1640. case GNU_OLD_BINARY: /* system format for short integers */
  1641. returnval = fread (&zs, sizeof(zs), 1, input);
  1642. if (returnval == 1)
  1643. x = (int)zs;
  1644. else
  1645. {
  1646. x = 0;
  1647. *badstatus = true;
  1648. }
  1649. break;
  1650. case PLOT5_HIGH: /* two-byte format, high byte first */
  1651. u = ((read_byte_as_unsigned_int (input, badstatus)) << 8);
  1652. u |= read_byte_as_unsigned_int (input, badstatus);
  1653. if (u > 0x7fff)
  1654. x = - (int)(0x10000 - u);
  1655. else
  1656. x = (int)u;
  1657. break;
  1658. case PLOT5_LOW: /* two-byte format, low byte first */
  1659. u = read_byte_as_unsigned_int (input, badstatus);
  1660. u |= (read_byte_as_unsigned_int (input, badstatus) << 8);
  1661. if (u > 0x7fff)
  1662. x = - (int)(0x10000 - u);
  1663. else
  1664. x = (int)u;
  1665. break;
  1666. }
  1667. return (double)x;
  1668. }
  1669. /* read a floating point quantity from input stream (may be in ascii format
  1670. or system single-precision format) */
  1671. double
  1672. read_float (FILE *input, bool *badstatus)
  1673. {
  1674. float f;
  1675. int returnval;
  1676. if (*badstatus == true)
  1677. return 0;
  1678. switch (input_format)
  1679. {
  1680. case GNU_PORTABLE:
  1681. case GNU_OLD_PORTABLE:
  1682. /* human-readable format */
  1683. returnval = fscanf (input, " %f", &f);
  1684. break;
  1685. case GNU_BINARY:
  1686. case GNU_OLD_BINARY:
  1687. default:
  1688. /* system single-precision format */
  1689. returnval = fread (&f, sizeof(f), 1, input);
  1690. break;
  1691. case PLOT5_HIGH:
  1692. case PLOT5_LOW:
  1693. /* plot(5) didn't support floats */
  1694. returnval = 0;
  1695. break;
  1696. }
  1697. if (returnval != 1 || f != f)
  1698. /* failure, or NaN */
  1699. {
  1700. *badstatus = true;
  1701. return 0.0;
  1702. }
  1703. else
  1704. return (double)f;
  1705. }
  1706. /* Read a newline-terminated string from input stream. As returned, the
  1707. string, with \0 replacing \n, is allocated on the heap and may be
  1708. freed. */
  1709. char *
  1710. read_string (FILE *input, bool *badstatus)
  1711. {
  1712. int length = 0, buffer_length = 16; /* initial length */
  1713. char *buffer;
  1714. char c;
  1715. if (*badstatus == true)
  1716. return 0;
  1717. buffer = (char *)xmalloc (buffer_length * sizeof(char));
  1718. for ( ; ; )
  1719. {
  1720. if (length >= buffer_length)
  1721. {
  1722. buffer_length *= 2;
  1723. buffer = (char *)xrealloc (buffer, (unsigned int)(buffer_length));
  1724. }
  1725. c = (char)read_byte_as_unsigned_char (input, badstatus);
  1726. if ((*badstatus == true) || (c == '\n'))
  1727. break;
  1728. buffer [length++] = c;
  1729. }
  1730. if (*badstatus)
  1731. {
  1732. free (buffer);
  1733. return NULL;
  1734. }
  1735. else
  1736. {
  1737. buffer [length] = '\0'; /* null-terminate string */
  1738. return buffer;
  1739. }
  1740. }