2 /* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
3 Written by James Clark (jjc@jclark.com)
5 This file is part of groff.
7 groff is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 2, or (at your option) any later
12 groff is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 You should have received a copy of the GNU General Public License along
18 with groff; see the file COPYING. If not, write to the Free Software
19 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
28 int zero_length_line_flag
= 0;
29 // Non-zero means we're using a groff driver.
30 int driver_extension_flag
= 1;
31 int compatible_flag
= 0;
33 int command_char
= '.'; // the character that introduces lines
34 // that should be passed through tranparently
35 static int lf_flag
= 1; // non-zero if we should attempt to understand
36 // lines beginning with `.lf'
38 // Non-zero means a parse error was encountered.
39 static int had_parse_error
= 0;
41 void do_file(const char *filename
);
43 class top_input
: public input
{
53 int get_location(const char **, int *);
56 top_input::top_input(FILE *p
) : fp(p
), bol(1), eof(0)
58 push_back
[0] = push_back
[1] = push_back
[2] = EOF
;
59 start_lineno
= current_lineno
;
66 if (push_back
[2] != EOF
) {
71 else if (push_back
[1] != EOF
) {
76 else if (push_back
[0] != EOF
) {
82 while (illegal_input_char(c
)) {
83 error("illegal input character code %1", int(c
));
87 if (bol
&& c
== '.') {
91 if (c
== 'F' || c
== 'E') {
95 if (d
== EOF
|| d
== ' ' || d
== '\n' || compatible_flag
) {
97 flyback_flag
= c
== 'F';
108 if (c
== EOF
|| c
== ' ' || c
== '\n' || compatible_flag
) {
136 error("end of file before .PE or .PF");
137 error_with_file_and_line(current_filename
, start_lineno
- 1,
143 int top_input::peek()
147 if (push_back
[2] != EOF
)
149 if (push_back
[1] != EOF
)
151 if (push_back
[0] != EOF
)
154 while (illegal_input_char(c
)) {
155 error("illegal input character code %1", int(c
));
159 if (bol
&& c
== '.') {
163 if (c
== 'F' || c
== 'E') {
167 if (d
== EOF
|| d
== ' ' || d
== '\n' || compatible_flag
) {
169 flyback_flag
= c
== 'F';
181 if (c
== EOF
|| c
== ' ' || c
== '\n' || compatible_flag
) {
211 int top_input::get_location(const char **filenamep
, int *linenop
)
213 *filenamep
= current_filename
;
214 *linenop
= current_lineno
;
218 void do_picture(FILE *fp
)
222 while ((c
= getc(fp
)) == ' ')
226 while ((c
= getc(fp
)) == ' ')
228 while (c
!= EOF
&& c
!= ' ' && c
!= '\n') {
235 } while (c
!= EOF
&& c
!= '\n');
239 if (filename
.length() == 0)
240 error("missing filename after `<'");
243 const char *old_filename
= current_filename
;
244 int old_lineno
= current_lineno
;
245 // filenames must be permanent
246 do_file(strsave(filename
.contents()));
247 current_filename
= old_filename
;
248 current_lineno
= old_lineno
;
250 out
->set_location(current_filename
, current_lineno
);
253 out
->set_location(current_filename
, current_lineno
);
267 switch (sscanf(&start_line
[0], "%lf %lf", &wid
, &ht
)) {
277 out
->set_desired_width_height(wid
, ht
);
278 out
->set_args(start_line
.contents());
279 lex_init(new top_input(fp
));
282 lex_error("giving up on this picture");
287 // skip the rest of the .PF/.PE line
288 while ((c
= getc(fp
)) != EOF
&& c
!= '\n')
292 out
->set_location(current_filename
, current_lineno
);
296 void do_file(const char *filename
)
299 if (strcmp(filename
, "-") == 0)
303 fp
= fopen(filename
, "r");
305 fatal("can't open `%1': %2", filename
, strerror(errno
));
307 out
->set_location(filename
, 1);
308 current_filename
= filename
;
310 enum { START
, MIDDLE
, HAD_DOT
, HAD_P
, HAD_PS
, HAD_l
, HAD_lf
} state
= START
;
339 else if (lf_flag
&& c
== 'l')
368 if (c
== ' ' || c
== '\n' || compatible_flag
) {
374 fputs(".PS", stdout
);
395 if (c
== ' ' || c
== '\n' || compatible_flag
) {
406 interpret_lf_args(line
.contents());
407 printf(".lf%s", line
.contents());
411 fputs(".lf", stdout
);
427 fputs(".\n", stdout
);
430 fputs(".P\n", stdout
);
433 fputs(".PS\n", stdout
);
436 fputs(".l\n", stdout
);
439 fputs(".lf\n", stdout
);
447 void do_whole_file(const char *filename
)
449 // Do not set current_filename.
451 if (strcmp(filename
, "-") == 0)
455 fp
= fopen(filename
, "r");
457 fatal("can't open `%1': %2", filename
, strerror(errno
));
459 lex_init(new file_input(fp
, filename
));
469 fprintf(stderr
, "usage: %s [ -nvC ] [ filename ... ]\n", program_name
);
471 fprintf(stderr
, " %s -t [ -cvzC ] [ filename ... ]\n", program_name
);
474 fprintf(stderr
, " %s -f [ -v ] [ filename ]\n", program_name
);
480 static char *fix_program_name(char *arg
, char *dflt
)
484 char *prog
= strchr(arg
, '\0');
489 if (strchr("\\/:", *prog
)) {
494 char *ext
= strchr(prog
, '.');
497 for (char *p
= prog
; *p
; p
++)
498 if ('A' <= *p
&& *p
<= 'Z')
499 *p
= 'a' + (*p
- 'A');
502 #endif /* __MSDOS__ */
504 int main(int argc
, char **argv
)
507 argv
[0] = fix_program_name(argv
[0], "pic");
508 #endif /* __MSDOS__ */
509 program_name
= argv
[0];
510 static char stderr_buf
[BUFSIZ
];
511 setbuf(stderr
, stderr_buf
);
518 int whole_file_flag
= 0;
521 while ((opt
= getopt(argc
, argv
, "T:CDStcvnxzpf")) != EOF
)
537 fatal("fig support not included");
541 driver_extension_flag
= 0;
545 warning("-%1 option is obsolete", char(opt
));
551 fatal("TeX support not included");
558 fatal("TeX support not included");
563 extern const char *version_string
;
564 fprintf(stderr
, "GNU pic version %s\n", version_string
);
569 // zero length lines will be printed as dots
570 zero_length_line_flag
++;
581 out
= make_tpic_output();
585 out
= make_tex_output();
593 out
= make_fig_output();
596 out
= make_troff_output();
598 if (whole_file_flag
) {
601 else if (argc
- optind
> 1)
604 do_whole_file(argv
[optind
]);
611 for (int i
= optind
; i
< argc
; i
++)
617 if (ferror(stdout
) || fflush(stdout
) < 0)
618 fatal("output error");
619 return had_parse_error
;