⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 refer.cc

📁 早期freebsd实现
💻 CC
📖 第 1 页 / 共 2 页
字号:
// -*- 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 underthe terms of the GNU General Public License as published by the FreeSoftware Foundation; either version 2, or (at your option) any laterversion.groff is distributed in the hope that it will be useful, but WITHOUT ANYWARRANTY; without even the implied warranty of MERCHANTABILITY orFITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public Licensefor more details.You should have received a copy of the GNU General Public License alongwith groff; see the file COPYING.  If not, write to the Free SoftwareFoundation, 675 Mass Ave, Cambridge, MA 02139, USA. */#include "refer.h"#include "refid.h"#include "ref.h"#include "token.h"#include "search.h"#include "command.h"const char PRE_LABEL_MARKER = '\013';const char POST_LABEL_MARKER = '\014';const char LABEL_MARKER = '\015'; // label_type is added on#define FORCE_LEFT_BRACKET 04#define FORCE_RIGHT_BRACKET 010static FILE *outfp = stdout;string capitalize_fields;string reverse_fields;string abbreviate_fields;string period_before_last_name = ". ";string period_before_initial = ".";string period_before_hyphen = "";string period_before_other = ". ";string sort_fields;int annotation_field = -1;string annotation_macro;string discard_fields = "XYZ";string pre_label = "\\*([.";string post_label = "\\*(.]";string sep_label = ", ";int accumulate = 0;int move_punctuation = 0;int abbreviate_label_ranges = 0;string label_range_indicator;int label_in_text = 1;int label_in_reference = 1;int date_as_label = 0;int sort_adjacent_labels = 0;// Join exactly two authors with this.string join_authors_exactly_two = " and ";// When there are more than two authors join the last two with this.string join_authors_last_two = ", and ";// Otherwise join authors with this.string join_authors_default = ", ";string separate_label_second_parts = ", ";// Use this string to represent that there are other authors.string et_al = " et al";// Use et al only if it can replace at least this many authors.int et_al_min_elide = 2;// Use et al only if the total number of authors is at least this.int et_al_min_total = 3;int compatible_flag = 0;int short_label_flag = 0;static int recognize_R1_R2 = 1;search_list database_list;int search_default = 1;static int default_database_loaded = 0;static reference **citation = 0;static int ncitations = 0;static int citation_max = 0;static reference **reference_hash_table = 0;static int hash_table_size;static int nreferences = 0;static int need_syncing = 0;string pending_line;string pending_lf_lines;static void output_pending_line();static unsigned immediately_handle_reference(const string &);static void immediately_output_references();static unsigned store_reference(const string &);static void divert_to_temporary_file();static reference *make_reference(const string &, unsigned *);static void usage();static void do_file(const char *);static void split_punct(string &line, string &punct);static void output_citation_group(reference **v, int n, label_type, FILE *fp);static void possibly_load_default_database();int main(int argc, char **argv){  program_name = argv[0];  static char stderr_buf[BUFSIZ];  setbuf(stderr, stderr_buf);  outfp = stdout;  int finished_options = 0;  int bib_flag = 0;  int done_spec = 0;  for (--argc, ++argv;       !finished_options && argc > 0 && argv[0][0] == '-'       && argv[0][1] != '\0';       argv++, argc--) {    const char *opt = argv[0] + 1;     while (opt != 0 && *opt != '\0') {      switch (*opt) {      case 'C':	compatible_flag = 1;	opt++;	break;      case 'B':	bib_flag = 1;	label_in_reference = 0;	label_in_text = 0;	++opt;	if (*opt == '\0') {	  annotation_field = 'X';	  annotation_macro = "AP";	}	else if (csalnum(opt[0]) && opt[1] == '.' && opt[2] != '\0') {	  annotation_field = opt[0];	  annotation_macro = opt + 2;	}	opt = 0;	break;      case 'P':	move_punctuation = 1;	opt++;	break;      case 'R':	recognize_R1_R2 = 0;	opt++;	break;      case 'S':	// Not a very useful spec.	set_label_spec("(A.n|Q)', '(D.y|D)");	done_spec = 1;	pre_label = " (";	post_label = ")";	sep_label = "; ";	opt++;	break;      case 'V':	verify_flag = 1;	opt++;	break;      case 'f':	{	  const char *num = 0;	  if (*++opt == '\0') {	    if (argc > 1) {	      num = *++argv;	      --argc;	    }	    else {	      error("option `f' requires an argument");	      usage();	    }	  }	  else {	    num = opt;	    opt = 0;	  }	  for (const char *ptr = num; *ptr; ptr++)	    if (!csdigit(*ptr)) {	      error("bad character `%1' in argument to -f option", *ptr);	      break;	    }	  if (*ptr == '\0') {	    string spec;	    spec = '%';	    spec += num;	    spec += '\0';	    set_label_spec(spec.contents());	    done_spec = 1;	  }	  break;	}      case 'b':	label_in_text = 0;	label_in_reference = 0;	opt++;	break;      case 'e':	accumulate = 1;	opt++;	break;      case 'c':	capitalize_fields = ++opt;	opt = 0;	break;      case 'k':	{	  char buf[5];	  if (csalpha(*++opt))	    buf[0] = *opt++;	  else {	    if (*opt != '\0')	      error("bad field name `%1'", *opt++);	    buf[0] = 'L';	  }	  buf[1] = '~';	  buf[2] = '%';	  buf[3] = 'a';	  buf[4] = '\0';	  set_label_spec(buf);	  done_spec = 1;	}	break;      case 'a':	{	  for (const char *ptr = ++opt; *ptr; ptr++)	    if (!csdigit(*ptr)) {	      error("argument to `a' option not a number");	      break;	    }	  if (*ptr == '\0') {	    reverse_fields = 'A';	    reverse_fields += opt;	  }	  opt = 0;	}	break;      case 'i':	linear_ignore_fields = ++opt;	opt = 0;	break;      case 'l':	{	  char buf[INT_DIGITS*2 + 11]; // A.n+2D.y-3%a	  strcpy(buf, "A.n");	  if (*++opt != '\0' && *opt != ',') {	    char *ptr;	    long n = strtol(opt, &ptr, 10);	    if (n == 0 && ptr == opt) {	      error("bad integer `%1' in `l' option", opt);	      opt = 0;	      break;	    }	    if (n < 0)	      n = 0;	    opt = ptr;	    sprintf(strchr(buf, '\0'), "+%d", n);	  }	  strcat(buf, "D.y");	  if (*opt == ',')	    opt++;	  if (*opt != '\0') {	    char *ptr;	    long n = strtol(opt, &ptr, 10);	    if (n == 0 && ptr == opt) {	      error("bad integer `%1' in `l' option", opt);	      opt = 0;	      break;	    }	    if (n < 0)	      n = 0;	    sprintf(strchr(buf, '\0'), "-%d", n);	    opt = ptr;	    if (*opt != '\0')	      error("argument to `l' option not of form `m,n'");	  }	  strcat(buf, "%a");	  if (!set_label_spec(buf))	    assert(0);	  done_spec = 1;	}	break;      case 'n':	search_default = 0;	opt++;	break;      case 'p':	{	  const char *filename = 0;	  if (*++opt == '\0') {	    if (argc > 1) {	      filename = *++argv;	      argc--;	    }	    else {	      error("option `p' requires an argument");	      usage();	    }	  }	  else {	    filename = opt;	    opt = 0;	  }	  database_list.add_file(filename);	}	break;      case 's':	if (*++opt == '\0')	  sort_fields = "AD";	else {	  sort_fields = opt;	  opt = 0;	}	accumulate = 1;	break;      case 't':	{	  char *ptr;	  long n = strtol(opt, &ptr, 10);	  if (n == 0 && ptr == opt) {	    error("bad integer `%1' in `t' option", opt);	    opt = 0;	    break;	  }	  if (n < 1)	    n = 1;	  linear_truncate_len = int(n);	  opt = ptr;	  break;	}      case 'v':	{	  extern const char *version_string;	  fprintf(stderr, "GNU refer version %s\n", version_string);	  fflush(stderr);	  opt++;	  break;	}      case '-':	if (opt[1] == '\0') {	  finished_options = 1;	  opt++;	  break;	}	// fall through      default:	error("unrecognized option `%1'", *opt);	usage();	break;      }    }  }  if (!done_spec)    set_label_spec("%1");  if (argc <= 0) {    if (bib_flag)      do_bib("-");    else      do_file("-");  }  else {    for (int i = 0; i < argc; i++) {      if (bib_flag)	do_bib(argv[i]);      else	do_file(argv[i]);    }  }  if (accumulate)    output_references();  if (fflush(stdout) < 0)    fatal("output error");  exit(0);}static void usage(){  fprintf(stderr,"usage: %s [-benvCPRS] [-aN] [-cXYZ] [-fN] [-iXYZ] [-kX] [-lM,N] [-p file]\n""       [-sXYZ] [-tN] [-BL.M] [files ...]\n",	  program_name);  exit(1);}static void possibly_load_default_database(){  if (search_default && !default_database_loaded) {    char *filename = getenv("REFER");    if (filename)      database_list.add_file(filename);    else      database_list.add_file(DEFAULT_INDEX, 1);    default_database_loaded = 1;  }}static int is_list(const string &str){  const char *start = str.contents();  const char *end = start + str.length();  while (end > start && csspace(end[-1]))    end--;  while (start < end && csspace(*start))    start++;  return end - start == 6 && memcmp(start, "$LIST$", 6) == 0;}static void do_file(const char *filename){  FILE *fp;  if (strcmp(filename, "-") == 0) {    fp = stdin;  }  else {    errno = 0;    fp = fopen(filename, "r");    if (fp == 0) {      error("can't open `%1': %2", filename, strerror(errno));      return;    }    current_filename = filename;  }  fprintf(outfp, ".lf 1 %s\n", filename);  string line;  current_lineno = 0;  for (;;) {    line.clear();    for (;;) {      int c = getc(fp);      if (c == EOF) {	if (line.length() > 0)	  line += '\n';	break;      }      if (illegal_input_char(c))	error("illegal input character code %1", c);      else {	line += c;	if (c == '\n')	  break;      }    }    int len = line.length();    if (len == 0)      break;    current_lineno++;    if (len >= 2 && line[0] == '.' && line[1] == '[') {      int start_lineno = current_lineno;      int start_of_line = 1;      string str;      string post;      string pre(line.contents() + 2, line.length() - 3);      for (;;) {	int c = getc(fp);	if (c == EOF) {	  error_with_file_and_line(current_filename, start_lineno,				   "missing `.]' line");	  break;	}	if (start_of_line)	  current_lineno++;	if (start_of_line && c == '.') {	  int d = getc(fp);	  if (d == ']') {	    while ((d = getc(fp)) != '\n' && d != EOF) {	      if (illegal_input_char(d))		error("illegal input character code %1", d);	      else		post += d;	    }	    break;	  }	  if (d != EOF)	    ungetc(d, fp);	}	if (illegal_input_char(c))	  error("illegal input character code %1", c);	else	  str += c;	start_of_line = (c == '\n');      }      if (is_list(str)) {	output_pending_line();	if (accumulate)	  output_references();	else	  error("found `$LIST$' but not accumulating references");      }      else {	unsigned flags = (accumulate			  ? store_reference(str)			  : immediately_handle_reference(str));	if (label_in_text) {	  if (accumulate && outfp == stdout)	    divert_to_temporary_file();	  if (pending_line.length() == 0) {	    warning("can't attach citation to previous line");	  }	  else	    pending_line.set_length(pending_line.length() - 1);	  string punct;	  if (move_punctuation)	    split_punct(pending_line, punct);	  int have_text = pre.length() > 0 || post.length() > 0;	  label_type lt = label_type(flags & ~(FORCE_LEFT_BRACKET					       |FORCE_RIGHT_BRACKET));	  if ((flags & FORCE_LEFT_BRACKET) || !have_text)	    pending_line += PRE_LABEL_MARKER;	  pending_line += pre;	  pending_line += LABEL_MARKER + lt;	  pending_line += post;	  if ((flags & FORCE_RIGHT_BRACKET) || !have_text)	    pending_line += POST_LABEL_MARKER;	  pending_line += punct;	  pending_line += '\n';	}      }      need_syncing = 1;    }    else if (len >= 4	     && line[0] == '.' && line[1] == 'l' && line[2] == 'f'	     && (compatible_flag || line[3] == '\n' || line[3] == ' ')) {      pending_lf_lines += line;      line += '\0';      if (interpret_lf_args(line.contents() + 3))	current_lineno--;    }    else if (recognize_R1_R2	     && len >= 4	     && line[0] == '.' && line[1] == 'R' && line[2] == '1'	     && (compatible_flag || line[3] == '\n' || line[3] == ' ')) {      line.clear();      int start_of_line = 1;      int start_lineno = current_lineno;      for (;;) {	int c = getc(fp);	if (c != EOF && start_of_line)	  current_lineno++;	if (start_of_line && c == '.') {	  c = getc(fp);	  if (c == 'R') {	    c = getc(fp);	    if (c == '2') {	      c = getc(fp);	      if (compatible_flag || c == ' ' || c == '\n' || c == EOF) {		while (c != EOF && c != '\n')		  c = getc(fp);		break;	      }	      else {		line += '.';		line += 'R';		line += '2';	      }	    }	    else {	      line += '.';	      line += 'R';	    }	  }	  else	    line += '.';	}	if (c == EOF) {	  error_with_file_and_line(current_filename, start_lineno,				   "missing `.R2' line");	  break;	}	if (illegal_input_char(c))	  error("illegal input character code %1", int(c));	else {	  line += c;	  start_of_line = c == '\n';	}      }      output_pending_line();      if (accumulate)	output_references();      else	nreferences = 0;      process_commands(line, current_filename, start_lineno + 1);      need_syncing = 1;    }    else {      output_pending_line();      pending_line = line;    }  }  need_syncing = 0;  output_pending_line();  if (fp != stdin)    fclose(fp);}class label_processing_state {  enum {    NORMAL,    PENDING_LABEL,    PENDING_LABEL_POST,    PENDING_LABEL_POST_PRE,    PENDING_POST    } state;  label_type type;		// type of pending labels  int count;			// number of pending labels  reference **rptr;		// pointer to next reference  int rcount;			// number of references left  FILE *fp;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -