diff options
Diffstat (limited to 'contrib/groff/refer/command.cc')
-rw-r--r-- | contrib/groff/refer/command.cc | 807 |
1 files changed, 0 insertions, 807 deletions
diff --git a/contrib/groff/refer/command.cc b/contrib/groff/refer/command.cc deleted file mode 100644 index 004189e..0000000 --- a/contrib/groff/refer/command.cc +++ /dev/null @@ -1,807 +0,0 @@ -// -*- C++ -*- -/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc. - Written by James Clark (jjc@jclark.com) - -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 2, 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 COPYING. If not, write to the Free Software -Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ - -#include "refer.h" -#include "refid.h" -#include "search.h" -#include "command.h" - -cset cs_field_name = csalpha; - -class input_item { - input_item *next; - char *filename; - int first_lineno; - string buffer; - const char *ptr; - const char *end; -public: - input_item(string &, const char *, int = 1); - ~input_item(); - int get_char(); - int peek_char(); - void skip_char(); - int get_location(const char **, int *); - - friend class input_stack; -}; - -input_item::input_item(string &s, const char *fn, int ln) -: filename(strsave(fn)), first_lineno(ln) -{ - buffer.move(s); - ptr = buffer.contents(); - end = ptr + buffer.length(); -} - -input_item::~input_item() -{ - a_delete filename; -} - -inline int input_item::peek_char() -{ - if (ptr >= end) - return EOF; - else - return (unsigned char)*ptr; -} - -inline int input_item::get_char() -{ - if (ptr >= end) - return EOF; - else - return (unsigned char)*ptr++; -} - -inline void input_item::skip_char() -{ - ptr++; -} - -int input_item::get_location(const char **filenamep, int *linenop) -{ - *filenamep = filename; - if (ptr == buffer.contents()) - *linenop = first_lineno; - else { - int ln = first_lineno; - const char *e = ptr - 1; - for (const char *p = buffer.contents(); p < e; p++) - if (*p == '\n') - ln++; - *linenop = ln; - } - return 1; -} - -class input_stack { - static input_item *top; -public: - static void init(); - static int get_char(); - static int peek_char(); - static void skip_char() { top->skip_char(); } - static void push_file(const char *); - static void push_string(string &, const char *, int); - static void error(const char *format, - const errarg &arg1 = empty_errarg, - const errarg &arg2 = empty_errarg, - const errarg &arg3 = empty_errarg); -}; - -input_item *input_stack::top = 0; - -void input_stack::init() -{ - while (top) { - input_item *tem = top; - top = top->next; - delete tem; - } -} - -int input_stack::get_char() -{ - while (top) { - int c = top->get_char(); - if (c >= 0) - return c; - input_item *tem = top; - top = top->next; - delete tem; - } - return -1; -} - -int input_stack::peek_char() -{ - while (top) { - int c = top->peek_char(); - if (c >= 0) - return c; - input_item *tem = top; - top = top->next; - delete tem; - } - return -1; -} - -void input_stack::push_file(const char *fn) -{ - FILE *fp; - if (strcmp(fn, "-") == 0) { - fp = stdin; - fn = "<standard input>"; - } - else { - errno = 0; - fp = fopen(fn, "r"); - if (fp == 0) { - error("can't open `%1': %2", fn, strerror(errno)); - return; - } - } - string buf; - int bol = 1; - int lineno = 1; - for (;;) { - int c = getc(fp); - if (bol && c == '.') { - // replace lines beginning with .R1 or .R2 with a blank line - c = getc(fp); - if (c == 'R') { - c = getc(fp); - if (c == '1' || c == '2') { - int cc = c; - c = getc(fp); - if (compatible_flag || c == ' ' || c == '\n' || c == EOF) { - while (c != '\n' && c != EOF) - c = getc(fp); - } - else { - buf += '.'; - buf += 'R'; - buf += cc; - } - } - else { - buf += '.'; - buf += 'R'; - } - } - else - buf += '.'; - } - if (c == EOF) - break; - if (illegal_input_char(c)) - error_with_file_and_line(fn, lineno, - "illegal input character code %1", int(c)); - else { - buf += c; - if (c == '\n') { - bol = 1; - lineno++; - } - else - bol = 0; - } - } - if (fp != stdin) - fclose(fp); - if (buf.length() > 0 && buf[buf.length() - 1] != '\n') - buf += '\n'; - input_item *it = new input_item(buf, fn); - it->next = top; - top = it; -} - -void input_stack::push_string(string &s, const char *filename, int lineno) -{ - input_item *it = new input_item(s, filename, lineno); - it->next = top; - top = it; -} - -void input_stack::error(const char *format, const errarg &arg1, - const errarg &arg2, const errarg &arg3) -{ - const char *filename; - int lineno; - for (input_item *it = top; it; it = it->next) - if (it->get_location(&filename, &lineno)) { - error_with_file_and_line(filename, lineno, format, arg1, arg2, arg3); - return; - } - ::error(format, arg1, arg2, arg3); -} - -void command_error(const char *format, const errarg &arg1, - const errarg &arg2, const errarg &arg3) -{ - input_stack::error(format, arg1, arg2, arg3); -} - -// # not recognized in "" -// \<newline> is recognized in "" -// # does not conceal newline -// if missing closing quote, word extends to end of line -// no special treatment of \ other than before newline -// \<newline> not recognized after # -// ; allowed as alternative to newline -// ; not recognized in "" -// don't clear word_buffer; just append on -// return -1 for EOF, 0 for newline, 1 for word - -int get_word(string &word_buffer) -{ - int c = input_stack::get_char(); - for (;;) { - if (c == '#') { - do { - c = input_stack::get_char(); - } while (c != '\n' && c != EOF); - break; - } - if (c == '\\' && input_stack::peek_char() == '\n') - input_stack::skip_char(); - else if (c != ' ' && c != '\t') - break; - c = input_stack::get_char(); - } - if (c == EOF) - return -1; - if (c == '\n' || c == ';') - return 0; - if (c == '"') { - for (;;) { - c = input_stack::peek_char(); - if (c == EOF || c == '\n') - break; - input_stack::skip_char(); - if (c == '"') { - int d = input_stack::peek_char(); - if (d == '"') - input_stack::skip_char(); - else - break; - } - else if (c == '\\') { - int d = input_stack::peek_char(); - if (d == '\n') - input_stack::skip_char(); - else - word_buffer += '\\'; - } - else - word_buffer += c; - } - return 1; - } - word_buffer += c; - for (;;) { - c = input_stack::peek_char(); - if (c == ' ' || c == '\t' || c == '\n' || c == '#' || c == ';') - break; - input_stack::skip_char(); - if (c == '\\') { - int d = input_stack::peek_char(); - if (d == '\n') - input_stack::skip_char(); - else - word_buffer += '\\'; - } - else - word_buffer += c; - } - return 1; -} - -union argument { - const char *s; - int n; -}; - -// This is for debugging. - -static void echo_command(int argc, argument *argv) -{ - for (int i = 0; i < argc; i++) - fprintf(stderr, "%s\n", argv[i].s); -} - -static void include_command(int argc, argument *argv) -{ - assert(argc == 1); - input_stack::push_file(argv[0].s); -} - -static void capitalize_command(int argc, argument *argv) -{ - if (argc > 0) - capitalize_fields = argv[0].s; - else - capitalize_fields.clear(); -} - -static void accumulate_command(int, argument *) -{ - accumulate = 1; -} - -static void no_accumulate_command(int, argument *) -{ - accumulate = 0; -} - -static void move_punctuation_command(int, argument *) -{ - move_punctuation = 1; -} - -static void no_move_punctuation_command(int, argument *) -{ - move_punctuation = 0; -} - -static void sort_command(int argc, argument *argv) -{ - if (argc == 0) - sort_fields = "AD"; - else - sort_fields = argv[0].s; - accumulate = 1; -} - -static void no_sort_command(int, argument *) -{ - sort_fields.clear(); -} - -static void articles_command(int argc, argument *argv) -{ - articles.clear(); - int i; - for (i = 0; i < argc; i++) { - articles += argv[i].s; - articles += '\0'; - } - int len = articles.length(); - for (i = 0; i < len; i++) - articles[i] = cmlower(articles[i]); -} - -static void database_command(int argc, argument *argv) -{ - for (int i = 0; i < argc; i++) - database_list.add_file(argv[i].s); -} - -static void default_database_command(int, argument *) -{ - search_default = 1; -} - -static void no_default_database_command(int, argument *) -{ - search_default = 0; -} - -static void bibliography_command(int argc, argument *argv) -{ - const char *saved_filename = current_filename; - int saved_lineno = current_lineno; - int saved_label_in_text = label_in_text; - label_in_text = 0; - if (!accumulate) - fputs(".]<\n", stdout); - for (int i = 0; i < argc; i++) - do_bib(argv[i].s); - if (accumulate) - output_references(); - else - fputs(".]>\n", stdout); - current_filename = saved_filename; - current_lineno = saved_lineno; - label_in_text = saved_label_in_text; -} - -static void annotate_command(int argc, argument *argv) -{ - if (argc > 0) - annotation_field = argv[0].s[0]; - else - annotation_field = 'X'; - if (argc == 2) - annotation_macro = argv[1].s; - else - annotation_macro = "AP"; -} - -static void no_annotate_command(int, argument *) -{ - annotation_macro.clear(); - annotation_field = -1; -} - -static void reverse_command(int, argument *argv) -{ - reverse_fields = argv[0].s; -} - -static void no_reverse_command(int, argument *) -{ - reverse_fields.clear(); -} - -static void abbreviate_command(int argc, argument *argv) -{ - abbreviate_fields = argv[0].s; - period_before_initial = argc > 1 ? argv[1].s : ". "; - period_before_last_name = argc > 2 ? argv[2].s : ". "; - period_before_other = argc > 3 ? argv[3].s : ". "; - period_before_hyphen = argc > 4 ? argv[4].s : "."; -} - -static void no_abbreviate_command(int, argument *) -{ - abbreviate_fields.clear(); -} - -string search_ignore_fields; - -static void search_ignore_command(int argc, argument *argv) -{ - if (argc > 0) - search_ignore_fields = argv[0].s; - else - search_ignore_fields = "XYZ"; - search_ignore_fields += '\0'; - linear_ignore_fields = search_ignore_fields.contents(); -} - -static void no_search_ignore_command(int, argument *) -{ - linear_ignore_fields = ""; -} - -static void search_truncate_command(int argc, argument *argv) -{ - if (argc > 0) - linear_truncate_len = argv[0].n; - else - linear_truncate_len = 6; -} - -static void no_search_truncate_command(int, argument *) -{ - linear_truncate_len = -1; -} - -static void discard_command(int argc, argument *argv) -{ - if (argc == 0) - discard_fields = "XYZ"; - else - discard_fields = argv[0].s; - accumulate = 1; -} - -static void no_discard_command(int, argument *) -{ - discard_fields.clear(); -} - -static void label_command(int, argument *argv) -{ - set_label_spec(argv[0].s); -} - -static void abbreviate_label_ranges_command(int argc, argument *argv) -{ - abbreviate_label_ranges = 1; - label_range_indicator = argc > 0 ? argv[0].s : "-"; -} - -static void no_abbreviate_label_ranges_command(int, argument *) -{ - abbreviate_label_ranges = 0; -} - -static void label_in_reference_command(int, argument *) -{ - label_in_reference = 1; -} - -static void no_label_in_reference_command(int, argument *) -{ - label_in_reference = 0; -} - -static void label_in_text_command(int, argument *) -{ - label_in_text = 1; -} - -static void no_label_in_text_command(int, argument *) -{ - label_in_text = 0; -} - -static void sort_adjacent_labels_command(int, argument *) -{ - sort_adjacent_labels = 1; -} - -static void no_sort_adjacent_labels_command(int, argument *) -{ - sort_adjacent_labels = 0; -} - -static void date_as_label_command(int argc, argument *argv) -{ - if (set_date_label_spec(argc > 0 ? argv[0].s : "D%a*")) - date_as_label = 1; -} - -static void no_date_as_label_command(int, argument *) -{ - date_as_label = 0; -} - -static void short_label_command(int, argument *argv) -{ - if (set_short_label_spec(argv[0].s)) - short_label_flag = 1; -} - -static void no_short_label_command(int, argument *) -{ - short_label_flag = 0; -} - -static void compatible_command(int, argument *) -{ - compatible_flag = 1; -} - -static void no_compatible_command(int, argument *) -{ - compatible_flag = 0; -} - -static void join_authors_command(int argc, argument *argv) -{ - join_authors_exactly_two = argv[0].s; - join_authors_default = argc > 1 ? argv[1].s : argv[0].s; - join_authors_last_two = argc == 3 ? argv[2].s : argv[0].s; -} - -static void bracket_label_command(int, argument *argv) -{ - pre_label = argv[0].s; - post_label = argv[1].s; - sep_label = argv[2].s; -} - -static void separate_label_second_parts_command(int, argument *argv) -{ - separate_label_second_parts = argv[0].s; -} - -static void et_al_command(int argc, argument *argv) -{ - et_al = argv[0].s; - et_al_min_elide = argv[1].n; - if (et_al_min_elide < 1) - et_al_min_elide = 1; - et_al_min_total = argc >= 3 ? argv[2].n : 0; -} - -static void no_et_al_command(int, argument *) -{ - et_al.clear(); - et_al_min_elide = 0; -} - -typedef void (*command_t)(int, argument *); - -/* arg_types is a string describing the numbers and types of arguments. -s means a string, i means an integer, f is a list of fields, F is -a single field, -? means that the previous argument is optional, * means that the -previous argument can occur any number of times. */ - -struct { - const char *name; - command_t func; - const char *arg_types; -} command_table[] = { - { "include", include_command, "s" }, - { "echo", echo_command, "s*" }, - { "capitalize", capitalize_command, "f?" }, - { "accumulate", accumulate_command, "" }, - { "no-accumulate", no_accumulate_command, "" }, - { "move-punctuation", move_punctuation_command, "" }, - { "no-move-punctuation", no_move_punctuation_command, "" }, - { "sort", sort_command, "s?" }, - { "no-sort", no_sort_command, "" }, - { "articles", articles_command, "s*" }, - { "database", database_command, "ss*" }, - { "default-database", default_database_command, "" }, - { "no-default-database", no_default_database_command, "" }, - { "bibliography", bibliography_command, "ss*" }, - { "annotate", annotate_command, "F?s?" }, - { "no-annotate", no_annotate_command, "" }, - { "reverse", reverse_command, "s" }, - { "no-reverse", no_reverse_command, "" }, - { "abbreviate", abbreviate_command, "ss?s?s?s?" }, - { "no-abbreviate", no_abbreviate_command, "" }, - { "search-ignore", search_ignore_command, "f?" }, - { "no-search-ignore", no_search_ignore_command, "" }, - { "search-truncate", search_truncate_command, "i?" }, - { "no-search-truncate", no_search_truncate_command, "" }, - { "discard", discard_command, "f?" }, - { "no-discard", no_discard_command, "" }, - { "label", label_command, "s" }, - { "abbreviate-label-ranges", abbreviate_label_ranges_command, "s?" }, - { "no-abbreviate-label-ranges", no_abbreviate_label_ranges_command, "" }, - { "label-in-reference", label_in_reference_command, "" }, - { "no-label-in-reference", no_label_in_reference_command, "" }, - { "label-in-text", label_in_text_command, "" }, - { "no-label-in-text", no_label_in_text_command, "" }, - { "sort-adjacent-labels", sort_adjacent_labels_command, "" }, - { "no-sort-adjacent-labels", no_sort_adjacent_labels_command, "" }, - { "date-as-label", date_as_label_command, "s?" }, - { "no-date-as-label", no_date_as_label_command, "" }, - { "short-label", short_label_command, "s" }, - { "no-short-label", no_short_label_command, "" }, - { "compatible", compatible_command, "" }, - { "no-compatible", no_compatible_command, "" }, - { "join-authors", join_authors_command, "sss?" }, - { "bracket-label", bracket_label_command, "sss" }, - { "separate-label-second-parts", separate_label_second_parts_command, "s" }, - { "et-al", et_al_command, "sii?" }, - { "no-et-al", no_et_al_command, "" }, -}; - -static int check_args(const char *types, const char *name, - int argc, argument *argv) -{ - int argno = 0; - while (*types) { - if (argc == 0) { - if (types[1] == '?') - break; - else if (types[1] == '*') { - assert(types[2] == '\0'); - break; - } - else { - input_stack::error("missing argument for command `%1'", name); - return 0; - } - } - switch (*types) { - case 's': - break; - case 'i': - { - char *ptr; - long n = strtol(argv->s, &ptr, 10); - if ((n == 0 && ptr == argv->s) - || *ptr != '\0') { - input_stack::error("argument %1 for command `%2' must be an integer", - argno + 1, name); - return 0; - } - argv->n = (int)n; - break; - } - case 'f': - { - for (const char *ptr = argv->s; *ptr != '\0'; ptr++) - if (!cs_field_name(*ptr)) { - input_stack::error("argument %1 for command `%2' must be a list of fields", - argno + 1, name); - return 0; - } - break; - } - case 'F': - if (argv->s[0] == '\0' || argv->s[1] != '\0' - || !cs_field_name(argv->s[0])) { - input_stack::error("argument %1 for command `%2' must be a field name", - argno + 1, name); - return 0; - } - break; - default: - assert(0); - } - if (types[1] == '?') - types += 2; - else if (types[1] != '*') - types += 1; - --argc; - ++argv; - ++argno; - } - if (argc > 0) { - input_stack::error("too many arguments for command `%1'", name); - return 0; - } - return 1; -} - -static void execute_command(const char *name, int argc, argument *argv) -{ - for (int i = 0; i < sizeof(command_table)/sizeof(command_table[0]); i++) - if (strcmp(name, command_table[i].name) == 0) { - if (check_args(command_table[i].arg_types, name, argc, argv)) - (*command_table[i].func)(argc, argv); - return; - } - input_stack::error("unknown command `%1'", name); -} - -static void command_loop() -{ - string command; - for (;;) { - command.clear(); - int res = get_word(command); - if (res != 1) { - if (res == 0) - continue; - break; - } - int argc = 0; - command += '\0'; - while ((res = get_word(command)) == 1) { - argc++; - command += '\0'; - } - argument *argv = new argument[argc]; - const char *ptr = command.contents(); - for (int i = 0; i < argc; i++) - argv[i].s = ptr = strchr(ptr, '\0') + 1; - execute_command(command.contents(), argc, argv); - a_delete argv; - if (res == -1) - break; - } -} - -void process_commands(const char *file) -{ - input_stack::init(); - input_stack::push_file(file); - command_loop(); -} - -void process_commands(string &s, const char *file, int lineno) -{ - input_stack::init(); - input_stack::push_string(s, file, lineno); - command_loop(); -} |