main.cc 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760
  1. /* This file is part of the GNU plotutils package. Copyright (C) 1995,
  2. 1996, 1997, 1998, 1999, 2000, 2005, 2008, 2009, Free Software
  3. 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. #include "pic.h"
  17. #include "output.h"
  18. #include "common.h"
  19. #include "libcommon.h"
  20. #include "getopt.h"
  21. #include "fontlist.h"
  22. #include "plot.h" // libplot header file
  23. const char *progname = "pic2plot"; // name of this program
  24. const char *written = "Written by Robert S. Maier.";
  25. const char *copyright = "Copyright (C) 2009 Free Software Foundation, Inc.";
  26. const char *usage_appendage = " FILE...\n";
  27. // A global; we have only one of these. Its member function are what do
  28. // the output of objects of various kinds (they're invoked by the
  29. // objects' `print' operations).
  30. output *out; // declared in output.h
  31. // `out' is a pointer to an instance of the plot_output class, which
  32. // is derived from the output class. Any instance of the plot_output
  33. // class looks at the following global variables, which the user
  34. // can set on the command line.
  35. char *output_format = (char *)"meta"; // libplot output format
  36. char *font_name = NULL; // initial font name (if set)
  37. char *pen_color_name = NULL; // initial pen color (if set)
  38. double font_size = 10.0/(8.0*72.); // font size as width of graphics display
  39. double line_width = -0.5/(8.0*72.); // line width as width of graphics display,
  40. // negative means use libplot default
  41. // any plot_output instance contains a plPlotter object; the following
  42. // PlotterParams object contains the parameters used when creating it
  43. plPlotterParams *plotter_params;
  44. // flags (used by lexer)
  45. int command_char = '.'; // char that introduces pass-thru lines
  46. int compatible_flag = 0; // recog. PS/PE even if not foll. by ' ', '\n'?
  47. // flags (used by parser)
  48. int safer_flag = 0; // forbid shell escapes?
  49. // flag (could be used by driver)
  50. int flyback_flag;
  51. int no_centering_flag = 0; // turn off auto-centering?
  52. int precision_dashing = 0; // position dashes/dots individually?
  53. // static variables
  54. static int had_parse_error = 0; // parse error?
  55. static int lf_flag = 1; // non-zero -> try to parse `.lf' lines
  56. // options
  57. #define ARG_NONE 0
  58. #define ARG_REQUIRED 1
  59. #define ARG_OPTIONAL 2
  60. const char *optstring = "T:OndF:f:W:";
  61. struct option long_options[] =
  62. {
  63. /* The most important option ("--display-type" is an obsolete variant) */
  64. { "output-format", ARG_REQUIRED, NULL, 'T'},
  65. { "display-type", ARG_REQUIRED, NULL, 'T' << 8 }, /* hidden */
  66. /* Long options, most with no equivalent short option alias */
  67. { "bg-color", ARG_REQUIRED, NULL, 'q' << 8 },
  68. { "bitmap-size", ARG_REQUIRED, NULL, 'B' << 8 },
  69. { "emulate-color", ARG_REQUIRED, NULL, 'e' << 8 },
  70. { "font-name", ARG_REQUIRED, NULL, 'F' },
  71. { "font-size", ARG_REQUIRED, NULL, 'f' },
  72. { "line-width", ARG_REQUIRED, NULL, 'W' },
  73. { "max-line-length", ARG_REQUIRED, NULL, 'M' << 8 },
  74. { "no-centering", ARG_NONE, NULL, 'n' },
  75. { "page-size", ARG_REQUIRED, NULL, 'P' << 8 },
  76. { "pen-color", ARG_REQUIRED, NULL, 'C' << 8 },
  77. { "precision-dashing",ARG_NONE, NULL, 'd' },
  78. { "rotation", ARG_REQUIRED, NULL, 'r' << 8},
  79. /* Options relevant only to raw pic2plot (refers to metafile output) */
  80. { "portable-output", ARG_NONE, NULL, 'O' },
  81. /* Documentation options */
  82. { "help-fonts", ARG_NONE, NULL, 'f' << 8 },
  83. { "list-fonts", ARG_NONE, NULL, 'l' << 8 },
  84. { "version", ARG_NONE, NULL, 'V' << 8 },
  85. { "help", ARG_NONE, NULL, 'h' << 8 },
  86. { NULL, 0, NULL, 0}
  87. };
  88. /* null-terminated list of options, such as obsolete-but-still-maintained
  89. options or undocumented options, which we don't show to the user */
  90. const int hidden_options[] = { (int)('T' << 8), 0 };
  91. // forward references
  92. void do_file (const char *filename);
  93. void do_picture (FILE *fp);
  94. //////////////////////////////////////////////////////////////////////
  95. // TOP_INPUT class.
  96. //////////////////////////////////////////////////////////////////////
  97. class top_input : public input
  98. {
  99. public:
  100. // ctor
  101. top_input (FILE *);
  102. // public functions
  103. int get (void);
  104. int peek (void);
  105. int get_location (const char **filenamep, int *linenop);
  106. private:
  107. FILE *fp;
  108. int bol;
  109. int eof;
  110. int push_back[3];
  111. int start_lineno;
  112. };
  113. top_input::top_input(FILE *p) : fp(p), bol(1), eof(0)
  114. {
  115. push_back[0] = push_back[1] = push_back[2] = EOF;
  116. start_lineno = current_lineno;
  117. }
  118. int
  119. top_input::get(void)
  120. {
  121. if (eof)
  122. return EOF;
  123. if (push_back[2] != EOF)
  124. {
  125. int c = push_back[2];
  126. push_back[2] = EOF;
  127. return c;
  128. }
  129. else if (push_back[1] != EOF)
  130. {
  131. int c = push_back[1];
  132. push_back[1] = EOF;
  133. return c;
  134. }
  135. else if (push_back[0] != EOF)
  136. {
  137. int c = push_back[0];
  138. push_back[0] = EOF;
  139. return c;
  140. }
  141. int c = getc(fp);
  142. while (illegal_input_char(c))
  143. {
  144. error("illegal input character code %1", int(c));
  145. c = getc(fp);
  146. bol = 0;
  147. }
  148. if (bol && c == '.')
  149. {
  150. c = getc(fp);
  151. if (c == 'P')
  152. {
  153. c = getc(fp);
  154. if (c == 'F' || c == 'E')
  155. {
  156. int d = getc(fp);
  157. if (d != EOF)
  158. ungetc(d, fp);
  159. if (d == EOF || d == ' ' || d == '\n' || compatible_flag)
  160. {
  161. eof = 1;
  162. flyback_flag = (c == 'F');
  163. return EOF;
  164. }
  165. push_back[0] = c;
  166. push_back[1] = 'P';
  167. return '.';
  168. }
  169. if (c == 'S')
  170. {
  171. c = getc(fp);
  172. if (c != EOF)
  173. ungetc(c, fp);
  174. if (c == EOF || c == ' ' || c == '\n' || compatible_flag)
  175. {
  176. error("nested .PS");
  177. eof = 1;
  178. return EOF;
  179. }
  180. push_back[0] = 'S';
  181. push_back[1] = 'P';
  182. return '.';
  183. }
  184. if (c != EOF)
  185. ungetc(c, fp);
  186. push_back[0] = 'P';
  187. return '.';
  188. }
  189. else
  190. {
  191. if (c != EOF)
  192. ungetc(c, fp);
  193. return '.';
  194. }
  195. }
  196. if (c == '\n')
  197. {
  198. bol = 1;
  199. current_lineno++;
  200. return '\n';
  201. }
  202. bol = 0;
  203. if (c == EOF)
  204. {
  205. eof = 1;
  206. error("end of file before .PE or .PF");
  207. error_with_file_and_line(current_filename, start_lineno - 1,
  208. ".PS was here");
  209. }
  210. return c;
  211. }
  212. int
  213. top_input::peek(void)
  214. {
  215. if (eof)
  216. return EOF;
  217. if (push_back[2] != EOF)
  218. return push_back[2];
  219. if (push_back[1] != EOF)
  220. return push_back[1];
  221. if (push_back[0] != EOF)
  222. return push_back[0];
  223. int c = getc(fp);
  224. while (illegal_input_char(c))
  225. {
  226. error("illegal input character code %1", int(c));
  227. c = getc(fp);
  228. bol = 0;
  229. }
  230. if (bol && c == '.')
  231. {
  232. c = getc(fp);
  233. if (c == 'P')
  234. {
  235. c = getc(fp);
  236. if (c == 'F' || c == 'E')
  237. {
  238. int d = getc(fp);
  239. if (d != EOF)
  240. ungetc(d, fp);
  241. if (d == EOF || d == ' ' || d == '\n' || compatible_flag)
  242. {
  243. eof = 1;
  244. flyback_flag = (c == 'F');
  245. return EOF;
  246. }
  247. push_back[0] = c;
  248. push_back[1] = 'P';
  249. push_back[2] = '.';
  250. return '.';
  251. }
  252. if (c == 'S')
  253. {
  254. c = getc(fp);
  255. if (c != EOF)
  256. ungetc(c, fp);
  257. if (c == EOF || c == ' ' || c == '\n' || compatible_flag)
  258. {
  259. error("nested .PS");
  260. eof = 1;
  261. return EOF;
  262. }
  263. push_back[0] = 'S';
  264. push_back[1] = 'P';
  265. push_back[2] = '.';
  266. return '.';
  267. }
  268. if (c != EOF)
  269. ungetc(c, fp);
  270. push_back[0] = 'P';
  271. push_back[1] = '.';
  272. return '.';
  273. }
  274. else
  275. {
  276. if (c != EOF)
  277. ungetc(c, fp);
  278. push_back[0] = '.';
  279. return '.';
  280. }
  281. }
  282. if (c != EOF)
  283. ungetc(c, fp);
  284. if (c == '\n')
  285. return '\n';
  286. return c;
  287. }
  288. int
  289. top_input::get_location(const char **filenamep, int *linenop)
  290. {
  291. *filenamep = current_filename;
  292. *linenop = current_lineno;
  293. return 1;
  294. }
  295. //////////////////////////////////////////////////////////////////////
  296. // End of TOP_INPUT class, beginning of main().
  297. //////////////////////////////////////////////////////////////////////
  298. int
  299. main (int argc, char **argv)
  300. {
  301. bool do_list_fonts = false; /* show a list of fonts? */
  302. bool show_fonts = false; /* supply help on fonts? */
  303. bool show_usage = false; /* show usage message? */
  304. bool show_version = false; /* show version message? */
  305. int errcnt = 0; /* errors encountered */
  306. int opt_index; /* long option index */
  307. int option; /* option character */
  308. static char stderr_buf[BUFSIZ];
  309. setbuf(stderr, stderr_buf);
  310. /* set global */
  311. program_name = progname;
  312. #if 0
  313. /* could add -C, -S options to set these */
  314. compatible_flag = 1; // allow non-' ', non-'\n' after .PS ?
  315. safer_flag = 1; // forbid shell escapes
  316. #endif
  317. plotter_params = pl_newplparams ();
  318. while ((option = getopt_long (argc, argv, optstring, long_options, &opt_index)) != EOF)
  319. {
  320. if (option == 0)
  321. option = long_options[opt_index].val;
  322. switch (option)
  323. {
  324. case 'T': /* Output format, ARG REQUIRED */
  325. case 'T' << 8:
  326. output_format = (char *)xmalloc (strlen (optarg) + 1);
  327. strcpy (output_format, optarg);
  328. break;
  329. case 'O': /* Ascii output */
  330. pl_setplparam (plotter_params, "META_PORTABLE", (void *)"yes");
  331. break;
  332. case 'n': /* No centering */
  333. no_centering_flag = 1;
  334. break;
  335. case 'd': /* Draw dots/dashes individually */
  336. precision_dashing = 1;
  337. break;
  338. case 'F': /* set the initial font */
  339. font_name = (char *)xmalloc (strlen (optarg) + 1);
  340. strcpy (font_name, optarg);
  341. break;
  342. case 'f': /* Font size, ARG REQUIRED */
  343. {
  344. double local_font_size;
  345. char s[4];
  346. if (sscanf (optarg, "%lf %3s", &local_font_size, s) == 2
  347. && strcmp (s, "pt") == 0)
  348. local_font_size /= (8.0 * 72.0); // express as width of display
  349. else if (sscanf (optarg, "%lf", &local_font_size) <= 0)
  350. {
  351. fprintf (stderr,
  352. "%s: error: font size must be a number, e.g. `0.01736' or `10pt', was `%s'\n",
  353. progname, optarg);
  354. errcnt++;
  355. break;
  356. }
  357. if (local_font_size >= 1.0)
  358. fprintf (stderr, "%s: ignoring too-large font size\n",
  359. progname);
  360. else if (local_font_size < 0.0)
  361. fprintf (stderr, "%s: ignoring negative font size\n",
  362. progname);
  363. else
  364. font_size = local_font_size;
  365. break;
  366. }
  367. case 'W': /* Line width, ARG REQUIRED */
  368. {
  369. double local_line_width;
  370. char s[4];
  371. if (sscanf (optarg, "%lf %3s", &local_line_width, s) == 2
  372. && strcmp (s, "pt") == 0)
  373. local_line_width /= (8.0 * 72.0); // express as width of display
  374. else if (sscanf (optarg, "%lf", &local_line_width) <= 0)
  375. {
  376. fprintf (stderr,
  377. "%s: error: line thickness must be a number, e.g. `0.00868' or `0.5pt', was `%s'\n",
  378. progname, optarg);
  379. errcnt++;
  380. break;
  381. }
  382. if (local_line_width >= 1.0)
  383. fprintf (stderr, "%s: ignoring too-large line thickness\n",
  384. progname);
  385. /* N.B. We don't rule out negative line thickness, because it's
  386. interpreted as a request to use libplot's default line
  387. thickness. (Which depends on output format; for example,
  388. with the `-T X' option it'll yield a zero-thickness X11
  389. line, which means a Bresenham line.) */
  390. else
  391. line_width = local_line_width;
  392. break;
  393. }
  394. case 'e' << 8: /* Emulate color via grayscale */
  395. pl_setplparam (plotter_params, "EMULATE_COLOR", (void *)optarg);
  396. break;
  397. case 'C' << 8: /* set the initial pen color */
  398. pen_color_name = (char *)xmalloc (strlen (optarg) + 1);
  399. strcpy (pen_color_name, optarg);
  400. break;
  401. case 'q' << 8: /* set the initial background color */
  402. pl_setplparam (plotter_params, "BG_COLOR", (void *)optarg);
  403. break;
  404. case 'B' << 8: /* Bitmap size */
  405. pl_setplparam (plotter_params, "BITMAPSIZE", (void *)optarg);
  406. break;
  407. case 'M' << 8: /* Max line length */
  408. pl_setplparam (plotter_params, "MAX_LINE_LENGTH", (void *)optarg);
  409. break;
  410. case 'P' << 8: /* Page size */
  411. pl_setplparam (plotter_params, "PAGESIZE", (void *)optarg);
  412. break;
  413. case 'r' << 8: /* Rotation angle */
  414. pl_setplparam (plotter_params, "ROTATION", (void *)optarg);
  415. break;
  416. case 'V' << 8: /* Version */
  417. show_version = true;
  418. break;
  419. case 'f' << 8: /* Fonts */
  420. show_fonts = true;
  421. break;
  422. case 'l' << 8: /* Fonts */
  423. do_list_fonts = true;
  424. break;
  425. case 'h' << 8: /* Help */
  426. show_usage = true;
  427. break;
  428. default:
  429. errcnt++;
  430. break;
  431. }
  432. }
  433. if (errcnt > 0)
  434. {
  435. fprintf (stderr, "Try `%s --help' for more information\n",
  436. progname);
  437. return EXIT_FAILURE;
  438. }
  439. if (show_version)
  440. {
  441. display_version (progname, written, copyright);
  442. return EXIT_SUCCESS;
  443. }
  444. if (do_list_fonts)
  445. {
  446. int success = true;
  447. success = list_fonts (output_format, progname);
  448. if (success)
  449. return EXIT_SUCCESS;
  450. else
  451. return EXIT_FAILURE;
  452. }
  453. if (show_fonts)
  454. {
  455. int success = true;
  456. success = display_fonts (output_format, progname);
  457. if (success)
  458. return EXIT_SUCCESS;
  459. else
  460. return EXIT_FAILURE;
  461. }
  462. if (show_usage)
  463. {
  464. display_usage (progname, hidden_options, usage_appendage, true);
  465. return EXIT_SUCCESS;
  466. }
  467. /* at most, only file names remain, so initialize parser */
  468. parse_init();
  469. out = make_plot_output();
  470. command_char = 014; // bogus to avoid seeing `commands'
  471. lf_flag = 0;
  472. /* invoke do_file() on stdin or on each remaining file */
  473. if (optind >= argc)
  474. do_file ("-");
  475. else
  476. for (int i = optind; i < argc; i++)
  477. do_file (argv[i]);
  478. delete out;
  479. if (ferror(stdout) || fflush(stdout) < 0)
  480. fatal ("output error");
  481. /* clean up */
  482. pl_deleteplparams (plotter_params);
  483. return had_parse_error ? EXIT_FAILURE : EXIT_SUCCESS;
  484. }
  485. void
  486. do_file (const char *filename)
  487. {
  488. FILE *fp;
  489. if (strcmp(filename, "-") == 0)
  490. fp = stdin;
  491. else
  492. {
  493. errno = 0;
  494. fp = fopen(filename, "r");
  495. if (fp == 0)
  496. fatal ("can't open `%1': %2", filename, strerror(errno));
  497. }
  498. out->set_location (filename, 1);
  499. current_filename = filename;
  500. current_lineno = 1;
  501. enum { START, MIDDLE, HAD_DOT, HAD_P, HAD_PS, HAD_l, HAD_lf } state = START;
  502. for (;;)
  503. {
  504. int c = getc(fp);
  505. if (c == EOF) // break out of for loop on EOF, only
  506. break;
  507. switch (state)
  508. {
  509. case START:
  510. if (c == '.')
  511. state = HAD_DOT;
  512. else
  513. {
  514. if (c == '\n')
  515. {
  516. current_lineno++;
  517. state = START;
  518. }
  519. else // dnl
  520. state = MIDDLE;
  521. }
  522. break;
  523. case MIDDLE:
  524. // discard chars until newline seen; switch back to START
  525. if (c == '\n')
  526. {
  527. current_lineno++;
  528. state = START;
  529. }
  530. break;
  531. case HAD_DOT:
  532. if (c == 'P')
  533. state = HAD_P;
  534. else if (lf_flag && c == 'l')
  535. state = HAD_l;
  536. else
  537. {
  538. if (c == '\n')
  539. {
  540. current_lineno++;
  541. state = START;
  542. }
  543. else // dnl
  544. state = MIDDLE;
  545. }
  546. break;
  547. case HAD_P:
  548. if (c == 'S')
  549. state = HAD_PS;
  550. else
  551. {
  552. if (c == '\n')
  553. {
  554. current_lineno++;
  555. state = START;
  556. }
  557. else // dnl
  558. state = MIDDLE;
  559. }
  560. break;
  561. case HAD_PS:
  562. if (c == ' ' || c == '\n' || compatible_flag)
  563. {
  564. ungetc(c, fp);
  565. do_picture(fp); // do the picture, incl. args of .PS if any
  566. state = START;
  567. }
  568. else // dnl
  569. state = MIDDLE;
  570. break;
  571. case HAD_l:
  572. if (c == 'f')
  573. state = HAD_lf;
  574. else
  575. {
  576. if (c == '\n')
  577. {
  578. current_lineno++;
  579. state = START;
  580. }
  581. else // dnl
  582. state = MIDDLE;
  583. }
  584. break;
  585. case HAD_lf:
  586. if (c == ' ' || c == '\n' || compatible_flag)
  587. {
  588. string line;
  589. while (c != EOF)
  590. {
  591. line += c;
  592. if (c == '\n')
  593. {
  594. current_lineno++;
  595. break;
  596. }
  597. c = getc(fp);
  598. }
  599. line += '\0';
  600. interpret_lf_args(line.contents());
  601. state = START;
  602. }
  603. else // dnl
  604. state = MIDDLE;
  605. break;
  606. default:
  607. assert(0);
  608. }
  609. }
  610. // exit gracefully when EOF seen
  611. if (fp != stdin)
  612. fclose(fp);
  613. }
  614. void
  615. do_picture(FILE *fp)
  616. {
  617. flyback_flag = 0;
  618. int c;
  619. while ((c = getc(fp)) == ' ')
  620. ;
  621. if (c == '<')
  622. /* first nonblank character after .PS is '<' */
  623. {
  624. string filename;
  625. while ((c = getc(fp)) == ' ')
  626. ;
  627. while (c != EOF && c != ' ' && c != '\n')
  628. {
  629. filename += char(c);
  630. c = getc(fp);
  631. }
  632. if (c == ' ')
  633. {
  634. do
  635. {
  636. c = getc(fp);
  637. } while (c != EOF && c != '\n');
  638. }
  639. if (c == '\n')
  640. current_lineno++;
  641. if (filename.length() == 0)
  642. error("missing filename after `<'");
  643. else
  644. {
  645. filename += '\0';
  646. const char *old_filename = current_filename;
  647. int old_lineno = current_lineno;
  648. // filenames must be permanent
  649. do_file (strsave(filename.contents())); // recursive call
  650. current_filename = old_filename;
  651. current_lineno = old_lineno;
  652. }
  653. out->set_location (current_filename, current_lineno);
  654. }
  655. else
  656. /* first nonblank character after .PS is not '<' */
  657. {
  658. out->set_location (current_filename, current_lineno);
  659. /* get the starting line */
  660. string start_line;
  661. while (c != EOF)
  662. {
  663. if (c == '\n')
  664. {
  665. current_lineno++;
  666. break;
  667. }
  668. start_line += c;
  669. c = getc(fp);
  670. }
  671. if (c == EOF)
  672. return;
  673. start_line += '\0';
  674. /* parse starting line for height and width */
  675. double wid, ht;
  676. switch (sscanf(&start_line[0], "%lf %lf", &wid, &ht))
  677. {
  678. case 1:
  679. ht = 0.0;
  680. break;
  681. case 2:
  682. break;
  683. default:
  684. ht = wid = 0.0;
  685. break;
  686. }
  687. out->set_desired_width_height (wid, ht);
  688. out->set_args (start_line.contents());
  689. // do the parse
  690. lex_init (new top_input(fp));
  691. if (yyparse())
  692. {
  693. had_parse_error = 1;
  694. lex_error ("giving up on this picture");
  695. }
  696. parse_cleanup();
  697. lex_cleanup();
  698. // skip the rest of the .PF/.PE line
  699. while ((c = getc(fp)) != EOF && c != '\n')
  700. ;
  701. if (c == '\n')
  702. current_lineno++;
  703. out->set_location (current_filename, current_lineno);
  704. }
  705. }