4 /* Copyright (C) 1989-1992, 2000, 2001, 2002, 2003
5 Free Software Foundation, Inc.
6 Written by James Clark (jjc@jclark.com)
8 This file is part of groff.
10 groff is free software; you can redistribute it and/or modify it under
11 the terms of the GNU General Public License as published by the Free
12 Software Foundation; either version 2, or (at your option) any later
15 groff is distributed in the hope that it will be useful, but WITHOUT ANY
16 WARRANTY; without even the implied warranty of MERCHANTABILITY or
17 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
20 You should have received a copy of the GNU General Public License along
21 with groff; see the file COPYING. If not, write to the Free Software
22 Foundation, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. */
27 extern "C" const char *Version_string
;
30 char *graphname
; // the picture box name in TeX mode
33 int zero_length_line_flag
= 0;
34 // Non-zero means we're using a groff driver.
35 int driver_extension_flag
= 1;
36 int compatible_flag
= 0;
38 int command_char
= '.'; // the character that introduces lines
39 // that should be passed through tranparently
40 static int lf_flag
= 1; // non-zero if we should attempt to understand
41 // lines beginning with `.lf'
43 // Non-zero means a parse error was encountered.
44 static int had_parse_error
= 0;
46 void do_file(const char *filename
);
48 class top_input
: public input
{
58 int get_location(const char **, int *);
61 top_input::top_input(FILE *p
) : fp(p
), bol(1), eof(0)
63 push_back
[0] = push_back
[1] = push_back
[2] = EOF
;
64 start_lineno
= current_lineno
;
71 if (push_back
[2] != EOF
) {
76 else if (push_back
[1] != EOF
) {
81 else if (push_back
[0] != EOF
) {
87 while (invalid_input_char(c
)) {
88 error("invalid input character code %1", int(c
));
92 if (bol
&& c
== '.') {
96 if (c
== 'F' || c
== 'E') {
100 if (d
== EOF
|| d
== ' ' || d
== '\n' || compatible_flag
) {
102 flyback_flag
= c
== 'F';
113 if (c
== EOF
|| c
== ' ' || c
== '\n' || compatible_flag
) {
141 error("end of file before .PE or .PF");
142 error_with_file_and_line(current_filename
, start_lineno
- 1,
148 int top_input::peek()
152 if (push_back
[2] != EOF
)
154 if (push_back
[1] != EOF
)
156 if (push_back
[0] != EOF
)
159 while (invalid_input_char(c
)) {
160 error("invalid input character code %1", int(c
));
164 if (bol
&& c
== '.') {
168 if (c
== 'F' || c
== 'E') {
172 if (d
== EOF
|| d
== ' ' || d
== '\n' || compatible_flag
) {
174 flyback_flag
= c
== 'F';
186 if (c
== EOF
|| c
== ' ' || c
== '\n' || compatible_flag
) {
216 int top_input::get_location(const char **filenamep
, int *linenop
)
218 *filenamep
= current_filename
;
219 *linenop
= current_lineno
;
223 void do_picture(FILE *fp
)
228 graphname
= strsave("graph"); // default picture name in TeX mode
229 while ((c
= getc(fp
)) == ' ')
233 while ((c
= getc(fp
)) == ' ')
235 while (c
!= EOF
&& c
!= ' ' && c
!= '\n') {
242 } while (c
!= EOF
&& c
!= '\n');
246 if (filename
.length() == 0)
247 error("missing filename after `<'");
250 const char *old_filename
= current_filename
;
251 int old_lineno
= current_lineno
;
252 // filenames must be permanent
253 do_file(strsave(filename
.contents()));
254 current_filename
= old_filename
;
255 current_lineno
= old_lineno
;
257 out
->set_location(current_filename
, current_lineno
);
260 out
->set_location(current_filename
, current_lineno
);
274 switch (sscanf(&start_line
[0], "%lf %lf", &wid
, &ht
)) {
284 out
->set_desired_width_height(wid
, ht
);
285 out
->set_args(start_line
.contents());
286 lex_init(new top_input(fp
));
289 lex_error("giving up on this picture");
294 // skip the rest of the .PF/.PE line
295 while ((c
= getc(fp
)) != EOF
&& c
!= '\n')
299 out
->set_location(current_filename
, current_lineno
);
303 void do_file(const char *filename
)
306 if (strcmp(filename
, "-") == 0)
310 fp
= fopen(filename
, "r");
313 fatal("can't open `%1': %2", filename
, strerror(errno
));
316 out
->set_location(filename
, 1);
317 current_filename
= filename
;
319 enum { START
, MIDDLE
, HAD_DOT
, HAD_P
, HAD_PS
, HAD_l
, HAD_lf
} state
= START
;
348 else if (lf_flag
&& c
== 'l')
377 if (c
== ' ' || c
== '\n' || compatible_flag
) {
383 fputs(".PS", stdout
);
404 if (c
== ' ' || c
== '\n' || compatible_flag
) {
415 interpret_lf_args(line
.contents());
416 printf(".lf%s", line
.contents());
420 fputs(".lf", stdout
);
436 fputs(".\n", stdout
);
439 fputs(".P\n", stdout
);
442 fputs(".PS\n", stdout
);
445 fputs(".l\n", stdout
);
448 fputs(".lf\n", stdout
);
456 void do_whole_file(const char *filename
)
458 // Do not set current_filename.
460 if (strcmp(filename
, "-") == 0)
464 fp
= fopen(filename
, "r");
466 fatal("can't open `%1': %2", filename
, strerror(errno
));
468 lex_init(new file_input(fp
, filename
));
476 void usage(FILE *stream
)
478 fprintf(stream
, "usage: %s [ -nvC ] [ filename ... ]\n", program_name
);
480 fprintf(stream
, " %s -t [ -cvzC ] [ filename ... ]\n", program_name
);
483 fprintf(stream
, " %s -f [ -v ] [ filename ]\n", program_name
);
487 #if defined(__MSDOS__) || defined(__EMX__)
488 static char *fix_program_name(char *arg
, char *dflt
)
492 char *prog
= strchr(arg
, '\0');
497 if (strchr("\\/:", *prog
)) {
502 char *ext
= strchr(prog
, '.');
505 for (char *p
= prog
; *p
; p
++)
506 if ('A' <= *p
&& *p
<= 'Z')
507 *p
= 'a' + (*p
- 'A');
510 #endif /* __MSDOS__ || __EMX__ */
512 int main(int argc
, char **argv
)
514 setlocale(LC_NUMERIC
, "C");
515 #if defined(__MSDOS__) || defined(__EMX__)
516 argv
[0] = fix_program_name(argv
[0], "pic");
517 #endif /* __MSDOS__ || __EMX__ */
518 program_name
= argv
[0];
519 static char stderr_buf
[BUFSIZ
];
520 setbuf(stderr
, stderr_buf
);
527 int whole_file_flag
= 0;
530 static const struct option long_options
[] = {
531 { "help", no_argument
, 0, CHAR_MAX
+ 1 },
532 { "version", no_argument
, 0, 'v' },
535 while ((opt
= getopt_long(argc
, argv
, "T:CDSUtcvnxzpf", long_options
, NULL
))
555 fatal("fig support not included");
559 driver_extension_flag
= 0;
563 warning("-%1 option is obsolete", char(opt
));
569 fatal("TeX support not included");
576 fatal("TeX support not included");
581 printf("GNU pic (groff) version %s\n", Version_string
);
586 // zero length lines will be printed as dots
587 zero_length_line_flag
++;
589 case CHAR_MAX
+ 1: // --help
603 out
= make_tpic_output();
607 out
= make_tex_output();
615 out
= make_fig_output();
618 out
= make_troff_output();
620 if (whole_file_flag
) {
623 else if (argc
- optind
> 1) {
627 do_whole_file(argv
[optind
]);
634 for (int i
= optind
; i
< argc
; i
++)
640 if (ferror(stdout
) || fflush(stdout
) < 0)
641 fatal("output error");
642 return had_parse_error
;