// -*- C++ -*- /* Copyright (C) 1989, 1990, 1991 Free Software Foundation, Inc. Written by James Clark (jjc@jclark.uucp) This file is part of groff. groff is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 1, or (at your option) any later version. groff is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with groff; see the file LICENSE. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "eqn.h" #include "stringclass.h" #ifndef DEVICE #define DEVICE "ps" #endif extern int yyparse(); char start_delim = '\0'; char end_delim = '\0'; int non_empty_flag; int inline_flag; int draw_flag = 0; int one_size_reduction_flag = 0; int compatible_flag = 0; int no_newline_in_delim_flag = 0; int read_line(FILE *fp, string *p) { p->clear(); int c = -1; while ((c = getc(fp)) != EOF) { if (!illegal_input_char(c)) *p += char(c); else error("illegal input character code `%1'", c); if (c == '\n') break; } current_lineno++; return p->length() > 0; } void do_file(const char *filename) { string linebuf; string str; FILE *fp; if (strcmp(filename, "-") == 0) fp = stdin; else { fp = fopen(filename, "r"); if (fp == 0) fatal("can't open `%1': %2", filename, strerror(errno)); } printf(".lf 1 %s\n", filename); current_filename = filename; current_lineno = 0; while (read_line(fp, &linebuf)) { int i; if (linebuf.length() >= 4 && linebuf[0] == '.' && linebuf[1] == 'l' && linebuf[2] == 'f' && (linebuf[3] == ' ' || linebuf[3] == '\n' || compatible_flag)) { put_string(linebuf, stdout); linebuf += '\0'; if (interpret_lf_args(linebuf.contents() + 3)) current_lineno--; } else if (linebuf.length() >= 4 && linebuf[0] == '.' && linebuf[1] == 'E' && linebuf[2] == 'Q' && (linebuf[3] == ' ' || linebuf[3] == '\n' || compatible_flag)) { put_string(linebuf, stdout); int start_lineno = current_lineno + 1; str.clear(); for (;;) { if (!read_line(fp, &linebuf)) fatal("end of file before .EN"); if (linebuf.length() >= 3 && linebuf[0] == '.' && linebuf[1] == 'E') { if (linebuf[2] == 'N' && (linebuf.length() == 3 || linebuf[3] == ' ' || linebuf[3] == '\n' || compatible_flag)) break; else if (linebuf[2] == 'Q' && linebuf.length() > 3 && (linebuf[3] == ' ' || linebuf[3] == '\n' || compatible_flag)) fatal("nested .EQ"); } str += linebuf; } str += '\0'; start_string(); init_lex(str.contents(), current_filename, start_lineno); non_empty_flag = 0; inline_flag = 0; yyparse(); if (non_empty_flag) { printf(".lf %d\n", current_lineno - 1); output_string(); } restore_compatibility(); printf(".lf %d\n", current_lineno); put_string(linebuf, stdout); } else if (start_delim != '\0' && (i = linebuf.search(start_delim)) >= 0 && (i == 0 || linebuf[i - 1] != '\\')) { start_string(); linebuf += '\0'; char *ptr = &linebuf[0]; inline_flag = 1; for (;;) { char *start = strchr(ptr, start_delim); if (start == 0) { char *nl = strchr(ptr, '\n'); if (nl != 0) *nl = '\0'; do_text(ptr); break; } if (no_newline_in_delim_flag && strchr(start + 1, end_delim) == 0) { error("missing `%1'", end_delim); char *nl = strchr(start + 1, '\n'); if (nl != 0) *nl = '\0'; do_text(ptr); break; } int start_lineno = current_lineno; *start = '\0'; do_text(ptr); ptr = start + 1; str.clear(); for (;;) { char *end = strchr(ptr, end_delim); if (end != 0) { *end = '\0'; str += ptr; ptr = end + 1; break; } str += ptr; if (!read_line(fp, &linebuf)) fatal("end of file before `%1'", end_delim); linebuf += '\0'; ptr = &linebuf[0]; } str += '\0'; init_lex(str.contents(), current_filename, start_lineno); yyparse(); } printf(".lf %d\n", current_lineno); output_string(); restore_compatibility(); printf(".lf %d\n", current_lineno + 1); } else { put_string(linebuf, stdout); } } if (fp != stdin) fclose(fp); current_filename = 0; current_lineno = 0; } void usage() { fprintf(stderr, "usage: %s [ -vrDCN ] -dxx -fn -sn -pn -mn -Ts [ files ... ]\n", program_name); exit(1); } int main(int argc, char **argv) { program_name = argv[0]; static char stderr_buf[BUFSIZ]; setbuf(stderr, stderr_buf); int opt; const char *device = DEVICE; const char *tem = getenv("GROFF_TYPESETTER"); if (tem) device = tem; while ((opt = getopt(argc, argv, "DCvd:f:p:s:m:T:rN")) != EOF) switch (opt) { case 'C': compatible_flag = 1; break; case 'v': { extern const char *version_string; fprintf(stderr, "GNU eqn version %s\n", version_string); fflush(stderr); break; } case 'd': if (optarg[0] == '\0' || optarg[1] == '\0') error("-d requires two character argument"); else if (illegal_input_char(optarg[0])) error("bad delimiter `%1'", optarg[0]); else if (illegal_input_char(optarg[1])) error("bad delimiter `%1'", optarg[1]); else { start_delim = optarg[0]; end_delim = optarg[1]; } break; case 'f': set_gfont(optarg); break; case 'T': device = optarg; break; case 's': { int n; if (sscanf(optarg, "%d", &n) == 1) set_gsize(n); else error("bad size `%1'", optarg); } break; case 'p': { int n; if (sscanf(optarg, "%d", &n) == 1) set_script_reduction(n); else error("bad size `%1'", optarg); } break; case 'm': { int n; if (sscanf(optarg, "%d", &n) == 1) set_minimum_size(n); else error("bad size `%1'", optarg); } break; case 'r': one_size_reduction_flag = 1; break; case 'D': draw_flag = 1; break; case 'N': no_newline_in_delim_flag = 1; break; case '?': usage(); break; default: assert(0); } init_table(device); init_char_table(); if (optind >= argc) do_file("-"); else for (int i = optind; i < argc; i++) do_file(argv[i]); if (ferror(stdout) || fflush(stdout) < 0) fatal("output error"); exit(0); }