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

📄 refer.cc

📁 早期freebsd实现
💻 CC
📖 第 1 页 / 共 2 页
字号:
  int handle_pending(int c);public:  label_processing_state(reference **, int, FILE *);  ~label_processing_state();  void process(int c);};static void output_pending_line(){  if (label_in_text && !accumulate && ncitations > 0) {    label_processing_state state(citation, ncitations, outfp);    int len = pending_line.length();    for (int i = 0; i < len; i++)      state.process((unsigned char)(pending_line[i]));  }  else    put_string(pending_line, outfp);  pending_line.clear();  if (pending_lf_lines.length() > 0) {    put_string(pending_lf_lines, outfp);    pending_lf_lines.clear();  }  if (!accumulate)    immediately_output_references();  if (need_syncing) {    fprintf(outfp, ".lf %d %s\n", current_lineno, current_filename);    need_syncing = 0;  }}static void split_punct(string &line, string &punct){  const char *start = line.contents();  const char *end = start + line.length();  const char *ptr = start;  const char *last_token_start = 0;  for (;;) {    if (ptr >= end)      break;    last_token_start = ptr;    if (*ptr == PRE_LABEL_MARKER || *ptr == POST_LABEL_MARKER	|| (*ptr >= LABEL_MARKER && *ptr < LABEL_MARKER + N_LABEL_TYPES))      ptr++;    else if (!get_token(&ptr, end))      break;  }  if (last_token_start) {    const token_info *ti = lookup_token(last_token_start, end);    if (ti->is_punct()) {      punct.append(last_token_start, end - last_token_start);      line.set_length(last_token_start - start);    }  }}static void divert_to_temporary_file(){  outfp = xtmpfile();}static void store_citation(reference *ref){  if (ncitations >= citation_max) {    if (citation == 0)      citation = new reference*[citation_max = 100];    else {      reference **old_citation = citation;      citation_max *= 2;      citation = new reference *[citation_max];      memcpy(citation, old_citation, ncitations*sizeof(reference *));      a_delete old_citation;    }  }  citation[ncitations++] = ref;}static unsigned store_reference(const string &str){  if (reference_hash_table == 0) {    reference_hash_table = new reference *[17];    hash_table_size = 17;    for (int i = 0; i < hash_table_size; i++)      reference_hash_table[i] = 0;  }  unsigned flags;  reference *ref = make_reference(str, &flags);  ref->compute_hash_code();  unsigned h = ref->hash();  for (reference **ptr = reference_hash_table + (h % hash_table_size);       *ptr != 0;       ((ptr == reference_hash_table)	? (ptr = reference_hash_table + hash_table_size - 1)	: --ptr))    if (same_reference(**ptr, *ref))      break;  if (*ptr != 0) {    if (ref->is_merged())      warning("fields ignored because reference already used");    delete ref;    ref = *ptr;  }  else {    *ptr = ref;    ref->set_number(nreferences);    nreferences++;    ref->pre_compute_label();    ref->compute_sort_key();    if (nreferences*2 >= hash_table_size) {      // Rehash it.      reference **old_table = reference_hash_table;      int old_size = hash_table_size;      hash_table_size = next_size(hash_table_size);      reference_hash_table = new reference*[hash_table_size];      int i;      for (i = 0; i < hash_table_size; i++)	reference_hash_table[i] = 0;      for (i = 0; i < old_size; i++)	if (old_table[i]) {	  for (reference **p = (reference_hash_table				+ (old_table[i]->hash() % hash_table_size));	       *p;	       ((p == reference_hash_table)		? (p = reference_hash_table + hash_table_size - 1)		: --p))	    ;	  *p = old_table[i];	}      a_delete old_table;    }  }  if (label_in_text)    store_citation(ref);  return flags;}unsigned immediately_handle_reference(const string &str){  unsigned flags;  reference *ref = make_reference(str, &flags);  ref->set_number(nreferences);  if (label_in_text || label_in_reference) {    ref->pre_compute_label();    ref->immediate_compute_label();  }  nreferences++;  store_citation(ref);  return flags;}static void immediately_output_references(){  for (int i = 0; i < ncitations; i++) {    reference *ref = citation[i];    if (label_in_reference) {      fputs(".ds [F ", outfp);      const string &label = ref->get_label(NORMAL_LABEL);      if (label.length() > 0	  && (label[0] == ' ' || label[0] == '\\' || label[0] == '"'))	putc('"', outfp);      put_string(label, outfp);      putc('\n', outfp);    }    ref->output(outfp);    delete ref;  }  ncitations = 0;}static void output_citation_group(reference **v, int n, label_type type,				  FILE *fp){  if (sort_adjacent_labels) {    // Do an insertion sort.  Usually n will be very small.    for (int i = 1; i < n; i++) {      int num = v[i]->get_number();      reference *temp = v[i];      for (int j = i - 1; j >= 0 && v[j]->get_number() > num; j--)	v[j + 1] = v[j];      v[j + 1] = temp;    }  }  // This messes up if !accumulate.  if (accumulate && n > 1) {    // remove duplicates    int j = 1;    for (int i = 1; i < n; i++)      if (v[i]->get_label(type) != v[i - 1]->get_label(type))	v[j++] = v[i];    n = j;  }  string merged_label;  for (int i = 0; i < n; i++) {    int nmerged = v[i]->merge_labels(v + i + 1, n - i - 1, type, merged_label);    if (nmerged > 0) {      put_string(merged_label, fp);      i += nmerged;    }    else      put_string(v[i]->get_label(type), fp);    if (i < n - 1)      put_string(sep_label, fp);  }}label_processing_state::label_processing_state(reference **p, int n, FILE *f): state(NORMAL), count(0), rptr(p), rcount(n), fp(f){}label_processing_state::~label_processing_state(){  int handled = handle_pending(EOF);  assert(!handled);  assert(rcount == 0);}int label_processing_state::handle_pending(int c){  switch (state) {  case NORMAL:    break;  case PENDING_LABEL:    if (c == POST_LABEL_MARKER) {      state = PENDING_LABEL_POST;      return 1;    }    else {      output_citation_group(rptr, count, type, fp);      rptr += count ;      rcount -= count;      state = NORMAL;    }    break;  case PENDING_LABEL_POST:    if (c == PRE_LABEL_MARKER) {      state = PENDING_LABEL_POST_PRE;      return 1;    }    else {      output_citation_group(rptr, count, type, fp);      rptr += count;      rcount -= count;      put_string(post_label, fp);      state = NORMAL;    }    break;  case PENDING_LABEL_POST_PRE:    if (c >= LABEL_MARKER	&& c < LABEL_MARKER + N_LABEL_TYPES	&& c - LABEL_MARKER == type) {      count += 1;      state = PENDING_LABEL;      return 1;    }    else {      output_citation_group(rptr, count, type, fp);      rptr += count;      rcount -= count;      put_string(sep_label, fp);      state = NORMAL;    }    break;  case PENDING_POST:    if (c == PRE_LABEL_MARKER) {      put_string(sep_label, fp);      state = NORMAL;      return 1;    }    else {      put_string(post_label, fp);      state = NORMAL;    }    break;  }  return 0;}void label_processing_state::process(int c){  if (handle_pending(c))    return;  assert(state == NORMAL);  switch (c) {  case PRE_LABEL_MARKER:    put_string(pre_label, fp);    state = NORMAL;    break;  case POST_LABEL_MARKER:    state = PENDING_POST;    break;  case LABEL_MARKER:  case LABEL_MARKER + 1:    count = 1;    state = PENDING_LABEL;    type = label_type(c - LABEL_MARKER);    break;  default:    state = NORMAL;    putc(c, fp);    break;  }}extern "C" {static int rcompare(const void *p1, const void *p2){  return compare_reference(**(reference **)p1, **(reference **)p2);}}void output_references(){  assert(accumulate);  if (nreferences > 0) {    int j = 0;    int i;    for (i = 0; i < hash_table_size; i++)      if (reference_hash_table[i] != 0)	reference_hash_table[j++] = reference_hash_table[i];    assert(j == nreferences);    for (; j < hash_table_size; j++)      reference_hash_table[j] = 0;    qsort(reference_hash_table, nreferences, sizeof(reference*), rcompare);    for (i = 0; i < nreferences; i++)      reference_hash_table[i]->set_number(i);    compute_labels(reference_hash_table, nreferences);  }  if (outfp != stdout) {    rewind(outfp);    {      label_processing_state state(citation, ncitations, stdout);      int c;      while ((c = getc(outfp)) != EOF)	state.process(c);    }    ncitations = 0;    fclose(outfp);    outfp = stdout;  }  if (nreferences > 0) {    fputs(".]<\n", outfp);    for (int i = 0; i < nreferences; i++) {      if (sort_fields.length() > 0)	reference_hash_table[i]->print_sort_key_comment(outfp);      if (label_in_reference) {	fputs(".ds [F ", outfp);	const string &label = reference_hash_table[i]->get_label(NORMAL_LABEL);	if (label.length() > 0	    && (label[0] == ' ' || label[0] == '\\' || label[0] == '"'))	  putc('"', outfp);	put_string(label, outfp);	putc('\n', outfp);      }      reference_hash_table[i]->output(outfp);      delete reference_hash_table[i];      reference_hash_table[i] = 0;    }    fputs(".]>\n", outfp);    nreferences = 0;  }  clear_labels();}static reference *find_reference(const char *query, int query_len){  // This is so that error messages look better.  while (query_len > 0 && csspace(query[query_len - 1]))    query_len--;  string str;  for (int i = 0; i < query_len; i++)    str += query[i] == '\n' ? ' ' : query[i];  str += '\0';  possibly_load_default_database();  search_list_iterator iter(&database_list, str.contents());  reference_id rid;  const char *start;  int len;  if (!iter.next(&start, &len, &rid)) {    error("no matches for `%1'", str.contents());    return 0;  }  const char *end = start + len;  while (start < end) {    if (*start == '%')      break;    while (start < end && *start++ != '\n')      ;  }  if (start >= end) {    error("found a reference for `%1' but it didn't contain any fields",	  str.contents());    return 0;  }  reference *result = new reference(start, end - start, &rid);  if (iter.next(&start, &len, &rid))    warning("multiple matches for `%1'", str.contents());  return result;}static reference *make_reference(const string &str, unsigned *flagsp){  const char *start = str.contents();  const char *end = start + str.length();  const char *ptr = start;  while (ptr < end) {    if (*ptr == '%')      break;    while (ptr < end && *ptr++ != '\n')      ;  }  *flagsp = 0;  for (; start < ptr; start++) {    if (*start == '#')      *flagsp = (SHORT_LABEL | (*flagsp & (FORCE_RIGHT_BRACKET					   | FORCE_LEFT_BRACKET)));    else if (*start == '[')      *flagsp |= FORCE_LEFT_BRACKET;    else if (*start == ']')      *flagsp |= FORCE_RIGHT_BRACKET;    else if (!csspace(*start))      break;  }  if (start >= end) {    error("empty reference");    return new reference;  }  reference *database_ref = 0;  if (start < ptr)    database_ref = find_reference(start, ptr - start);  reference *inline_ref = 0;  if (ptr < end)    inline_ref = new reference(ptr, end - ptr);  if (inline_ref) {    if (database_ref) {      database_ref->merge(*inline_ref);      delete inline_ref;      return database_ref;    }    else      return inline_ref;  }  else if (database_ref)    return database_ref;  else    return new reference;}static void do_ref(const string &str){  if (accumulate)    (void)store_reference(str);  else {    (void)immediately_handle_reference(str);    immediately_output_references();  }}static void trim_blanks(string &str){  const char *start = str.contents();  const char *end = start + str.length();  while (end > start && end[-1] != '\n' && csspace(end[-1]))    --end;  str.set_length(end - start);}void do_bib(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;  }  enum {    START, MIDDLE, BODY, BODY_START, BODY_BLANK, BODY_DOT    } state = START;  string body;  for (;;) {    int c = getc(fp);    if (c == EOF)      break;    if (illegal_input_char(c)) {      error("illegal input character code %1", c);      continue;    }    switch (state) {    case START:      if (c == '%') {	body = c;	state = BODY;      }      else if (c != '\n')	state = MIDDLE;      break;    case MIDDLE:      if (c == '\n')	state = START;      break;    case BODY:      body += c;      if (c == '\n')	state = BODY_START;      break;    case BODY_START:      if (c == '\n') {	do_ref(body);	state = START;      }      else if (c == '.')	state = BODY_DOT;      else if (csspace(c)) {	state = BODY_BLANK;	body += c;      }      else {	body += c;	state = BODY;      }      break;    case BODY_BLANK:      if (c == '\n') {	trim_blanks(body);	do_ref(body);	state = START;      }      else if (csspace(c))	body += c;      else {	body += c;	state = BODY;      }      break;    case BODY_DOT:      if (c == ']') {	do_ref(body);	state = MIDDLE;      }      else {	body += '.';	body += c;	state = c == '\n' ? BODY_START : BODY;      }      break;    default:      assert(0);    }    if (c == '\n')      current_lineno++;  }  switch (state) {  case START:  case MIDDLE:    break;  case BODY:    body += '\n';    do_ref(body);    break;  case BODY_DOT:  case BODY_START:    do_ref(body);    break;  case BODY_BLANK:    trim_blanks(body);    do_ref(body);    break;  }  fclose(fp);}// from the Dragon Bookunsigned hash_string(const char *s, int len){  const char *end = s + len;  unsigned h = 0, g;  while (s < end) {    h <<= 4;    h += *s++;    if ((g = h & 0xf0000000) != 0) {      h ^= g >> 24;      h ^= g;    }  }  return h;}int next_size(int n){  static const int table_sizes[] = {     101, 503, 1009, 2003, 3001, 4001, 5003, 10007, 20011, 40009,    80021, 160001, 500009, 1000003, 2000003, 4000037, 8000009,    16000057, 32000011, 64000031, 128000003, 0   };  for (const int *p = table_sizes; *p <= n && *p != 0; p++)    ;  assert(*p != 0);  return *p;}

⌨️ 快捷键说明

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