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, 675 Mass Ave, Cambridge, MA 02139, 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;
32 int command_char
= '.'; // the character that introduces lines
33 // that should be passed through tranparently
34 static int lf_flag
= 1; // non-zero if we should attempt to understand
35 // lines beginning with `.lf'
37 void do_file(const char *filename
);
39 class top_input
: public input
{
49 int get_location(const char **, int *);
52 top_input::top_input(FILE *p
) : fp(p
), bol(1), eof(0)
54 push_back
[0] = push_back
[1] = push_back
[2] = EOF
;
55 start_lineno
= current_lineno
;
62 if (push_back
[2] != EOF
) {
67 else if (push_back
[1] != EOF
) {
72 else if (push_back
[0] != EOF
) {
78 while (illegal_input_char(c
)) {
79 error("illegal input character code %1", int(c
));
83 if (bol
&& c
== '.') {
87 if (c
== 'F' || c
== 'E') {
91 if (d
== EOF
|| d
== ' ' || d
== '\n' || compatible_flag
) {
93 flyback_flag
= c
== 'F';
104 if (c
== EOF
|| c
== ' ' || c
== '\n' || compatible_flag
) {
132 error("end of file before .PE or .PF");
133 error_with_file_and_line(current_filename
, start_lineno
- 1,
139 int top_input::peek()
143 if (push_back
[2] != EOF
)
145 if (push_back
[1] != EOF
)
147 if (push_back
[0] != EOF
)
150 while (illegal_input_char(c
)) {
151 error("illegal input character code %1", int(c
));
155 if (bol
&& c
== '.') {
159 if (c
== 'F' || c
== 'E') {
163 if (d
== EOF
|| d
== ' ' || d
== '\n' || compatible_flag
) {
165 flyback_flag
= c
== 'F';
177 if (c
== EOF
|| c
== ' ' || c
== '\n' || compatible_flag
) {
207 int top_input::get_location(const char **filenamep
, int *linenop
)
209 *filenamep
= current_filename
;
210 *linenop
= current_lineno
;
214 void do_picture(FILE *fp
)
218 while ((c
= getc(fp
)) == ' ')
222 while ((c
= getc(fp
)) == ' ')
224 while (c
!= EOF
&& c
!= ' ' && c
!= '\n') {
231 } while (c
!= EOF
&& c
!= '\n');
235 if (filename
.length() == 0)
236 error("missing filename after `<'");
239 const char *old_filename
= current_filename
;
240 int old_lineno
= current_lineno
;
241 // filenames must be permanent
242 do_file(strsave(filename
.contents()));
243 current_filename
= old_filename
;
244 current_lineno
= old_lineno
;
246 out
->set_location(current_filename
, current_lineno
);
249 out
->set_location(current_filename
, current_lineno
);
263 switch (sscanf(&start_line
[0], "%lf %lf", &wid
, &ht
)) {
273 out
->set_desired_width_height(wid
, ht
);
274 out
->set_args(start_line
.contents());
275 lex_init(new top_input(fp
));
277 lex_error("giving up on this picture");
281 // skip the rest of the .PF/.PE line
282 while ((c
= getc(fp
)) != EOF
&& c
!= '\n')
286 out
->set_location(current_filename
, current_lineno
);
290 void do_file(const char *filename
)
293 if (strcmp(filename
, "-") == 0)
297 fp
= fopen(filename
, "r");
299 fatal("can't open `%1': %2", filename
, strerror(errno
));
301 out
->set_location(filename
, 1);
302 current_filename
= filename
;
304 enum { START
, MIDDLE
, HAD_DOT
, HAD_P
, HAD_PS
, HAD_l
, HAD_lf
} state
= START
;
333 else if (lf_flag
&& c
== 'l')
362 if (c
== ' ' || c
== '\n' || compatible_flag
) {
368 fputs(".PS", stdout
);
389 if (c
== ' ' || c
== '\n' || compatible_flag
) {
400 interpret_lf_args(line
.contents());
401 printf(".lf%s", line
.contents());
405 fputs(".lf", stdout
);
421 fputs(".\n", stdout
);
424 fputs(".P\n", stdout
);
427 fputs(".PS\n", stdout
);
430 fputs(".l\n", stdout
);
433 fputs(".lf\n", stdout
);
441 void do_whole_file(const char *filename
)
443 // Do not set current_filename.
445 if (strcmp(filename
, "-") == 0)
449 fp
= fopen(filename
, "r");
451 fatal("can't open `%1': %2", filename
, strerror(errno
));
453 lex_init(new file_input(fp
, filename
));
462 fprintf(stderr
, "usage: %s [ -nvC ] [ filename ... ]\n", program_name
);
464 fprintf(stderr
, " %s -t [ -cvzC ] [ filename ... ]\n", program_name
);
467 fprintf(stderr
, " %s -f [ -v ] [ filename ]\n", program_name
);
473 static char *fix_program_name(char *arg
, char *dflt
)
477 char *prog
= strchr(arg
, '\0');
482 if (strchr("\\/:", *prog
)) {
487 char *ext
= strchr(prog
, '.');
490 for (char *p
= prog
; *p
; p
++)
491 if ('A' <= *p
&& *p
<= 'Z')
492 *p
= 'a' + (*p
- 'A');
495 #endif /* __MSDOS__ */
497 int main(int argc
, char **argv
)
500 argv
[0] = fix_program_name(argv
[0], "pic");
501 #endif /* __MSDOS__ */
502 program_name
= argv
[0];
503 static char stderr_buf
[BUFSIZ
];
504 setbuf(stderr
, stderr_buf
);
511 int whole_file_flag
= 0;
514 while ((opt
= getopt(argc
, argv
, "T:CDtcvnxzpf")) != EOF
)
527 fatal("fig support not included");
531 driver_extension_flag
= 0;
535 warning("-%1 option is obsolete", char(opt
));
541 fatal("TeX support not included");
548 fatal("TeX support not included");
553 extern const char *version_string
;
554 fprintf(stderr
, "GNU pic version %s\n", version_string
);
559 // zero length lines will be printed as dots
560 zero_length_line_flag
++;
571 out
= make_tpic_output();
575 out
= make_tex_output();
583 out
= make_fig_output();
586 out
= make_troff_output();
588 if (whole_file_flag
) {
591 else if (argc
- optind
> 1)
594 do_whole_file(argv
[optind
]);
601 for (int i
= optind
; i
< argc
; i
++)
607 if (ferror(stdout
) || fflush(stdout
) < 0)
608 fatal("output error");