/*-
******************************************************************************
******************************************************************************
**
**  MODULE
**
**      $RCSfile: bibtex-3.c,v $
**      $Revision: 3.71 $
**      $Date: 1996/08/18 20:37:06 $
**
**  DESCRIPTION
**
**      A 32-bit implementation of BibTeX v0.99c for MS-DOS, OS/2 2.x, 
**      Unix and VMS.  This C language implementation is based on the 
**      original WEB source but it has been enhanced to support 8-bit input
**      characters and a very large processing capacity.
**
**      For documentation describing how to use and build this program, 
**      see the 00README.TXT file that accompanies this distribution.
**
**  MODULE CONTENTS
**
**      This is the third of 4 source modules for BibTeX.  The source has 
**      been split into 4 parts so that some of the more primitive editors
**      can cope.  This code mimics the BibTeX WEB source as closely as
**      possible and there should be NO system dependent code in any of the 
**      bibtex-#.c modules.
**
**      The functions defined in this module are:
**
**          pre_def_certain_strings
**          pre_define
**          print_lit
**          print_missing_entry
**          print_overflow
**          print_recursion_illegal
**          print_skipping_whatever_remains
**          print_stk_lit
**          print_wrong_stk_lit
**          push_lit_stk
**          quick_sort
**          sam_too_long_file_name_print
**          sam_wrong_file_name_print
**          scan1
**          scan1_white
**          scan2
**          scan2_white
**          scan3
**          scan_a_field_token_and_eat_whit
**          scan_alpha
**          scan_and_store_the_field_value
**          scan_balanced_braces
**          str_eq_buf
**          str_eq_str
**          str_lookup
**          swap
**          trace_and_stat_printing
**          trace_pr_fn_class
**          unknwn_function_class_confusion
**          unknwn_literal_confusion
**          upper_case
**          von_name_ends_and_last_name_sta
**          von_token_found
**          x_add_period
**
**  AUTHORS
**
**      Original WEB translation to C, conversion to "big" (32-bit) capacity,
**      addition of run-time selectable capacity and 8-bit support extensions
**      by:
**
**          Niel Kempson
**          Snowy Owl Systems Limited, Cheltenham, England
**          E-mail: kempson@snowyowl.co.uk
**      
**      8-bit support extensions also by:
**
**          Alejandro Aguilar-Sierra
**          Centro de Ciencias de la Atm\'osfera, 
**          Universidad Nacional Aut\'onoma de M\'exico, M\'exico
**          E-mail: asierra@servidor.unam.mx
**
**  COPYRIGHT
**
**      This implementation copyright (c) 1991-1995 by Niel Kempson
**           and copyright (c) 1995 by Alejandro Aguilar-Sierra.
**
**      This program 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.
**
**      This program 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 this program; if not, write to the Free Software
**      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
**
**      In other words, you are welcome to use, share and improve this
**      program.  You are forbidden to forbid anyone else to use, share
**      and improve what you give them.  Help stamp out software-hoarding!
**
**  ACKNOWLEDGEMENT
**      
**      The original BibTeX was written by Oren Patashnik using Donald 
**      Knuth's WEB system.  This format produces a PASCAL program for 
**      execution and a TeX documented version of the source code. This 
**      program started as a (manual) translation of the WEB source into C.
**  
**  CHANGE LOG
**
**      $Log: bibtex-3.c,v $
**      Revision 3.71  1996/08/18  20:37:06  kempson
**      Official release 3.71 (see HISTORY file for details).
**
**      Revision 3.70  1996/04/08  10:08:40  kempson
**      Final documentation & cosmetic changes for official release 3.70.
**
**      Revision 3.6  1995/10/21  22:19:33  kempson
**      Removed previous WEB-imposed limit on the maximum value of Hash_Prime.
**
**      Revision 3.5  1995/09/24  20:44:37  kempson
**      Many changes for final beta test version.
**
**      Revision 3.4  1995/04/09  22:15:40  kempson
**      Placed under RCS control
**
******************************************************************************
******************************************************************************
*/
static char *rcsid = "$Id: bibtex-3.c,v 3.71 1996/08/18 20:37:06 kempson Exp $";

#include "sysdep.h"
#include "bibtex.h"
#include "datatype.h"
#include "gblprocs.h"
#include "gblvars.h"
#include "utils.h"
#include "version.h"


/***************************************************************************
 * WEB section number:	 336
 * ~~~~~~~~~~~~~~~~~~~
 * This is a procedure so that |initialize| is smaller.
 ***************************************************************************/
void          pre_def_certain_strings (void)
BEGIN

/***************************************************************************
 * WEB section number:	75
 * ~~~~~~~~~~~~~~~~~~~
 * It's time to insert some of the pre-defined strings into |str_pool|
 * (and thus the hash table).  These system-dependent strings should
 * contain no upper-case letters, and they must all be exactly
 * |longest_pds| characters long (even if fewer characters are actually
 * stored).  The |pre_define| routine appears shortly.
 *
 * Important notes: These pre-definitions must not have any glitches or
 * the program may bomb because the |log_file| hasn't been opened yet,
 * and |text_ilk|s should be pre-defined later, for
 * .bst-function-execution purposes.
 ***************************************************************************/
  pre_define (".aux        ", 4, FILE_EXT_ILK);
  s_aux_extension = hash_text[pre_def_loc];
  pre_define (".bbl        ", 4, FILE_EXT_ILK);
  s_bbl_extension = hash_text[pre_def_loc];
  pre_define (".blg        ", 4, FILE_EXT_ILK);
  s_log_extension = hash_text[pre_def_loc];
  pre_define (".bst        ", 4, FILE_EXT_ILK);
  s_bst_extension = hash_text[pre_def_loc];
  pre_define (".bib        ", 4, FILE_EXT_ILK);
  s_bib_extension = hash_text[pre_def_loc];
  pre_define ("            ", 0, FILE_AREA_ILK);
  s_bst_area = hash_text[pre_def_loc];
  pre_define ("            ", 0, FILE_AREA_ILK);
  s_bib_area = hash_text[pre_def_loc];

/***************************************************************************
 * WEB section number:	79
 * ~~~~~~~~~~~~~~~~~~~
 * Now we pre-define the command strings; they must all be exactly
 * |longest_pds| characters long.
 *
 * Important note: These pre-definitions must not have any glitches or
 * the program may bomb because the |log_file| hasn't been opened yet.
 ***************************************************************************/
  pre_define ("\\citation  ", 9, AUX_COMMAND_ILK);
  ilk_info[pre_def_loc] = N_AUX_CITATION;
  pre_define ("\\bibdata   ", 8, AUX_COMMAND_ILK);
  ilk_info[pre_def_loc] = N_AUX_BIBDATA;
  pre_define ("\\bibstyle  ", 9, AUX_COMMAND_ILK);
  ilk_info[pre_def_loc] = N_AUX_BIBSTYLE;
  pre_define ("\\@input    ", 7, AUX_COMMAND_ILK);
  ilk_info[pre_def_loc] = N_AUX_INPUT;
  pre_define ("entry       ", 5, BST_COMMAND_ILK);
  ilk_info[pre_def_loc] = N_BST_ENTRY;
  pre_define ("execute     ", 7, BST_COMMAND_ILK);
  ilk_info[pre_def_loc] = N_BST_EXECUTE;
  pre_define ("function    ", 8, BST_COMMAND_ILK);
  ilk_info[pre_def_loc] = N_BST_FUNCTION;
  pre_define ("integers    ", 8, BST_COMMAND_ILK);
  ilk_info[pre_def_loc] = N_BST_INTEGERS;
  pre_define ("iterate     ", 7, BST_COMMAND_ILK);
  ilk_info[pre_def_loc] = N_BST_ITERATE;
  pre_define ("macro       ", 5, BST_COMMAND_ILK);
  ilk_info[pre_def_loc] = N_BST_MACRO;
  pre_define ("read        ", 4, BST_COMMAND_ILK);
  ilk_info[pre_def_loc] = N_BST_READ;
  pre_define ("reverse     ", 7, BST_COMMAND_ILK);
  ilk_info[pre_def_loc] = N_BST_REVERSE;
  pre_define ("sort        ", 4, BST_COMMAND_ILK);
  ilk_info[pre_def_loc] = N_BST_SORT;
  pre_define ("strings     ", 7, BST_COMMAND_ILK);
  ilk_info[pre_def_loc] = N_BST_STRINGS;
  pre_define ("comment     ", 7, BIB_COMMAND_ILK);
  ilk_info[pre_def_loc] = N_BIB_COMMENT;
  pre_define ("preamble    ", 8, BIB_COMMAND_ILK);
  ilk_info[pre_def_loc] = N_BIB_PREAMBLE;
  pre_define ("string      ", 6, BIB_COMMAND_ILK);
  ilk_info[pre_def_loc] = N_BIB_STRING;
/*^^^^^^^^^^^^^^^^^^^^^^^^^^ END OF SECTION 79 ^^^^^^^^^^^^^^^^^^^^^^^^^^^*/

/***************************************************************************
 * WEB section number:	334
 * ~~~~~~~~~~~~~~~~~~~
 * It's time for us to insert more pre-defined strings into |str_pool|
 * (and thus the hash table) and to insert the |built_in| functions into
 * the hash table.  The strings corresponding to these functions should
 * contain no upper-case letters, and they must all be exactly
 * |longest_pds| characters long.  The |build_in| routine (to appear
 * shortly) does the work.
 *
 * Important note: These pre-definitions must not have any glitches or the
 * program may bomb because the |log_file| hasn't been opened yet.
 ***************************************************************************/
  build_in ("=           ", 1, &b_equals, N_EQUALS);
  build_in (">           ", 1, &b_greater_than, N_GREATER_THAN);
  build_in ("<           ", 1, &b_less_than, N_LESS_THAN);
  build_in ("+           ", 1, &b_plus, N_PLUS);
  build_in ("-           ", 1, &b_minus, N_MINUS);
  build_in ("*           ", 1, &b_concatenate, N_CONCATENATE);
  build_in (":=          ", 2, &b_gets, N_GETS);
  build_in ("add.period$ ", 11, &b_add_period, N_ADD_PERIOD);
  build_in ("call.type$  ", 10, &b_call_type, N_CALL_TYPE);
  build_in ("change.case$", 12, &b_change_case, N_CHANGE_CASE);
  build_in ("chr.to.int$ ", 11, &b_chr_to_int, N_CHR_TO_INT);
  build_in ("cite$       ", 5, &b_cite, N_CITE);
  build_in ("duplicate$  ", 10, &b_duplicate, N_DUPLICATE);
  build_in ("empty$      ", 6, &b_empty, N_EMPTY);
  build_in ("format.name$", 12, &b_format_name, N_FORMAT_NAME);
  build_in ("if$         ", 3, &b_if, N_IF);
  build_in ("int.to.chr$ ", 11, &b_int_to_chr, N_INT_TO_CHR);
  build_in ("int.to.str$ ", 11, &b_int_to_str, N_INT_TO_STR);
  build_in ("missing$    ", 8, &b_missing, N_MISSING);
  build_in ("newline$    ", 8, &b_newline, N_NEWLINE);
  build_in ("num.names$  ", 10, &b_num_names, N_NUM_NAMES);
  build_in ("pop$        ", 4, &b_pop, N_POP);
  build_in ("preamble$   ", 9, &b_preamble, N_PREAMBLE);
  build_in ("purify$     ", 7, &b_purify, N_PURIFY);
  build_in ("quote$      ", 6, &b_quote, N_QUOTE);
  build_in ("skip$       ", 5, &b_skip, N_SKIP);
  build_in ("stack$      ", 6, &b_stack, N_STACK);
  build_in ("substring$  ", 10, &b_substring, N_SUBSTRING);
  build_in ("swap$       ", 5, &b_swap, N_SWAP);
  build_in ("text.length$", 12, &b_text_length, N_TEXT_LENGTH);
  build_in ("text.prefix$", 12, &b_text_prefix, N_TEXT_PREFIX);
  build_in ("top$        ", 4, &b_top_stack, N_TOP_STACK);
  build_in ("type$       ", 5, &b_type, N_TYPE);
  build_in ("warning$    ", 8, &b_warning, N_WARNING);
  build_in ("width$      ", 6, &b_width, N_WIDTH);
  build_in ("while$      ", 6, &b_while, N_WHILE);
  build_in ("width$      ", 6, &b_width, N_WIDTH);
  build_in ("write$      ", 6, &b_write, N_WRITE);
/*^^^^^^^^^^^^^^^^^^^^^^^^^^ END OF SECTION 334 ^^^^^^^^^^^^^^^^^^^^^^^^^^^*/

/***************************************************************************
 * WEB section number:	339
 * ~~~~~~~~~~~~~~~~~~~
 * Here we pre-define a few strings used in executing the .bst file:
 * the null string, which is sometimes pushed onto the stack; a string
 * used for default entry types; and some control sequences used to spot
 * foreign characters.  We also initialize the |s_preamble| array to
 * empty.  These pre-defined strings must all be exactly |longest_pds|
 * characters long.
 *
 * Important note: These pre-definitions must not have any glitches or
 * the program may bomb because the |log_file| hasn't been opened yet,
 * and |text_ilk|s should be pre-defined here, not earlier, for
 * .bst-function-execution purposes.
 ***************************************************************************/
  pre_define ("            ", 0, TEXT_ILK);
  s_null = hash_text[pre_def_loc];
  fn_type[pre_def_loc] = STR_LITERAL;
  pre_define ("default.type", 12, TEXT_ILK);
  s_default = hash_text[pre_def_loc];
  fn_type[pre_def_loc] = STR_LITERAL;
  b_default = b_skip;
  preamble_ptr = 0;
  pre_define ("i           ", 1, CONTROL_SEQ_ILK);
  ilk_info[pre_def_loc] = N_I;
  pre_define ("j           ", 1, CONTROL_SEQ_ILK);
  ilk_info[pre_def_loc] = N_J;
  pre_define ("oe          ", 2, CONTROL_SEQ_ILK);
  ilk_info[pre_def_loc] = N_OE;
  pre_define ("OE          ", 2, CONTROL_SEQ_ILK);
  ilk_info[pre_def_loc] = N_OE_UPPER;
  pre_define ("ae          ", 2, CONTROL_SEQ_ILK);
  ilk_info[pre_def_loc] = N_AE;
  pre_define ("AE          ", 2, CONTROL_SEQ_ILK);
  ilk_info[pre_def_loc] = N_AE_UPPER;
  pre_define ("aa          ", 2, CONTROL_SEQ_ILK);
  ilk_info[pre_def_loc] = N_AA;
  pre_define ("AA          ", 2, CONTROL_SEQ_ILK);
  ilk_info[pre_def_loc] = N_AA_UPPER;
  pre_define ("o           ", 1, CONTROL_SEQ_ILK);
  ilk_info[pre_def_loc] = N_O;
  pre_define ("O           ", 1, CONTROL_SEQ_ILK);
  ilk_info[pre_def_loc] = N_O_UPPER;
  pre_define ("l           ", 1, CONTROL_SEQ_ILK);
  ilk_info[pre_def_loc] = N_L;
  pre_define ("L           ", 1, CONTROL_SEQ_ILK);
  ilk_info[pre_def_loc] = N_L_UPPER;
  pre_define ("ss          ", 2, CONTROL_SEQ_ILK);
  ilk_info[pre_def_loc] = N_SS;
/*^^^^^^^^^^^^^^^^^^^^^^^^^^ END OF SECTION 339 ^^^^^^^^^^^^^^^^^^^^^^^^^^^*/

/***************************************************************************
 * WEB section number:	340
 * ~~~~~~~~~~~~~~~~~~~
 * Now we pre-define any built-in |field|s, |str_entry_var|s, and
 * |int_global_var|s; these strings must all be exactly |longest_pds|
 * characters long.  Note that although these are built-in functions, we
 * classify them (in the |fn_type| array) otherwise.
 *
 * Important note: These pre-definitions must not have any glitches or
 * the program may bomb because the |log_file| hasn't been opened yet.
 ***************************************************************************/
  pre_define ("crossref    ", 8, BST_FN_ILK);
  fn_type[pre_def_loc] = FIELD;
  FN_INFO[pre_def_loc] = num_fields;
  crossref_num = num_fields;
  INCR (num_fields);
  num_pre_defined_fields = num_fields;
  pre_define ("sort.key$   ", 9, BST_FN_ILK);
  fn_type[pre_def_loc] = STR_ENTRY_VAR;
  FN_INFO[pre_def_loc] = num_ent_strs;
  sort_key_num = num_ent_strs;
  INCR (num_ent_strs);
  pre_define ("entry.max$  ", 10, BST_FN_ILK);
  fn_type[pre_def_loc] = INT_GLOBAL_VAR;
  FN_INFO[pre_def_loc] = ENT_STR_SIZE;
  pre_define ("global.max$ ", 11, BST_FN_ILK);
  fn_type[pre_def_loc] = INT_GLOBAL_VAR;
  FN_INFO[pre_def_loc] = GLOB_STR_SIZE;
/*^^^^^^^^^^^^^^^^^^^^^^^^^^ END OF SECTION 340 ^^^^^^^^^^^^^^^^^^^^^^^^^^^*/

END
/*^^^^^^^^^^^^^^^^^^^^^^^^^^ END OF SECTION 336 ^^^^^^^^^^^^^^^^^^^^^^^^^^^*/




/***************************************************************************
 * WEB section number:	 77
 * ~~~~~~~~~~~~~~~~~~~
 * This procedure initializes a pre-defined string of length at most
 * |longest_pds|.
 ***************************************************************************/
void          pre_define (PdsType_T pds, PdsLen_T len, StrIlk_T ilk)
BEGIN
  PdsLen_T        i;

  for (i=1; i<=len; i++)
  BEGIN

    /*----------------------------------------------------------------------
     * Unlike the WEB, the string in `pds' will occupy the positions
     * pds[0] ... pds[len-1], rather than pds[1] ... pds[len].
     *----------------------------------------------------------------------*/
    buffer[i] = xord[pds[i-1]];
  END
  pre_def_loc = str_lookup (buffer, 1, len, ilk, DO_INSERT);
END
/*^^^^^^^^^^^^^^^^^^^^^^^^^^ END OF SECTION  77 ^^^^^^^^^^^^^^^^^^^^^^^^^^^*/




/***************************************************************************
 * WEB section number:	 3
 * ~~~~~~~~~~~~~~~~~~~
 ***************************************************************************/
void          print_a_newline (void)
BEGIN
  if (log_file != NULL)
    FPUTC ('\n', log_file);
  FPUTC ('\n', TERM_OUT);
END
/*^^^^^^^^^^^^^^^^^^^^^^^^^^ END OF SECTION   3 ^^^^^^^^^^^^^^^^^^^^^^^^^^^*/




/***************************************************************************
 * WEB section number:	 51
 * ~~~~~~~~~~~~~~~~~~~
 * And here are the associated procedures. Note the |term_out| file is
 * system dependent.
 ***************************************************************************/
void          print_a_pool_str (StrNumber_T s)
BEGIN
  out_pool_str (TERM_OUT, s);
  out_pool_str (log_file, s);
END
/*^^^^^^^^^^^^^^^^^^^^^^^^^^ END OF SECTION  51 ^^^^^^^^^^^^^^^^^^^^^^^^^^^*/




/***************************************************************************
 * WEB section number:	 82
 * ~~~~~~~~~~~~~~~~~~~
 * And here are the associated procedures. Note the |term_out| file is
 * system dependent.
 ***************************************************************************/
void          print_a_token (void)
BEGIN
  out_token (TERM_OUT);
  out_token (log_file);
END
/*^^^^^^^^^^^^^^^^^^^^^^^^^^ END OF SECTION  82 ^^^^^^^^^^^^^^^^^^^^^^^^^^^*/




/***************************************************************************
 * WEB section number:	 108
 * ~~~~~~~~~~~~~~~~~~~
 * Print the name of the current .aux file, followed by a |newline|.
 ***************************************************************************/
void          print_aux_name (void)
BEGIN
  PRINT_POOL_STR (CUR_AUX_STR);
  PRINT_NEWLINE;
END
/*^^^^^^^^^^^^^^^^^^^^^^^^^^ END OF SECTION 108 ^^^^^^^^^^^^^^^^^^^^^^^^^^^*/




/***************************************************************************
 * WEB section number:	 95
 * ~~~~~~~~~~~~~~~~~~~
 * The |print_bad_input_line| procedure prints the current input line,
 * splitting it at the character being scanned: It prints |buffer[0]|,
 * |buffer[1]|, \dots, |buffer[buf_ptr2-1]| on one line and
 * |SCAN_CHAR|, \dots, |buffer[last-1]| on the next (and both
 * lines start with a colon between two |space|s).  Each |white_space|
 * character is printed as a |space|.
 ***************************************************************************/
void          print_bad_input_line (void)
BEGIN
  BufPointer_T      bf_ptr;

  PRINT (" : ");
  bf_ptr = 0;
  while (bf_ptr < buf_ptr2)
  BEGIN
    if (lex_class[buffer[bf_ptr]] == WHITE_SPACE)
    BEGIN
      PRINT2 ("%c", xchr[SPACE]);
    END
    else
    BEGIN
      PRINT2 ("%c", xchr[buffer[bf_ptr]]);
    END
    INCR (bf_ptr);
  END
  PRINT_NEWLINE;
  PRINT (" : ");
  bf_ptr = 0;
  while (bf_ptr < buf_ptr2)
  BEGIN
    PRINT2 ("%c", xchr[SPACE]);
    INCR (bf_ptr);
  END
  bf_ptr = buf_ptr2;
  while (bf_ptr < last)
  BEGIN
    if (lex_class[buffer[bf_ptr]] == WHITE_SPACE)
    BEGIN
      PRINT2 ("%c", xchr[SPACE]);
    END
    else
    BEGIN
      PRINT2 ("%c", xchr[buffer[bf_ptr]]);
    END
    INCR (bf_ptr);
  END
  PRINT_NEWLINE;
  bf_ptr = 0;
  while ((bf_ptr < buf_ptr2) && (lex_class[buffer[bf_ptr]] == WHITE_SPACE))
  BEGIN
    INCR (bf_ptr);
  END
  if (bf_ptr == buf_ptr2)
  BEGIN
    PRINT_LN ("(Error may have been on previous line)");
  END
  mark_error ();
END
/*^^^^^^^^^^^^^^^^^^^^^^^^^^ END OF SECTION  95 ^^^^^^^^^^^^^^^^^^^^^^^^^^^*/




/***************************************************************************
 * WEB section number:	 121
 * ~~~~~~~~~~~~~~~~~~~
 * Here's a procedure we'll need shortly.  It prints the name of the
 * current .bib file, followed by a |newline|.
 ***************************************************************************/
void          print_bib_name (void)
BEGIN
  PRINT_POOL_STR (CUR_BIB_STR);
  PRINT_POOL_STR (s_bib_extension);
  PRINT_NEWLINE;
END
/*^^^^^^^^^^^^^^^^^^^^^^^^^^ END OF SECTION 121 ^^^^^^^^^^^^^^^^^^^^^^^^^^^*/




/***************************************************************************
 * WEB section number:	 128
 * ~~~~~~~~~~~~~~~~~~~
 * Print the name of the .bst file, followed by a |newline|.
 ***************************************************************************/
void          print_bst_name (void)
BEGIN
  PRINT_POOL_STR (bst_str);
  PRINT_POOL_STR (s_bst_extension);
  PRINT_NEWLINE;
END
/*^^^^^^^^^^^^^^^^^^^^^^^^^^ END OF SECTION 128 ^^^^^^^^^^^^^^^^^^^^^^^^^^^*/




/***************************************************************************
 * WEB section number:	 45
 * ~~~~~~~~~~~~~~~~~~~
 * When something happens that the program thinks is impossible,
 * call the maintainer.
 ***************************************************************************/
void          print_confusion (void)
BEGIN
  PRINT_LN ("---this can't happen");
  PRINT_LN ("*Please notify the BibTeX maintainer*");
  mark_fatal ();
END
/*^^^^^^^^^^^^^^^^^^^^^^^^^^ END OF SECTION 45 ^^^^^^^^^^^^^^^^^^^^^^^^^^^*/




/***************************************************************************
 * WEB section number:	 158
 * ~~~~~~~~~~~~~~~~~~~
 * Occasionally we'll want to |print| the name of one of these function
 * classes.
 ***************************************************************************/
void          print_fn_class (HashLoc_T fn_loc)
BEGIN
  switch (fn_type[fn_loc])
  BEGIN
    case BUILT_IN:
      PRINT ("built-in");
      break;
    case WIZ_DEFINED:
      PRINT ("wizard-defined");
      break;
    case INT_LITERAL:
      PRINT ("integer-literal");
      break;
    case STR_LITERAL:
      PRINT ("string-literal");
      break;
    case FIELD:
      PRINT ("field");
      break;
    case INT_ENTRY_VAR:
      PRINT ("integer-entry-variable");
      break;
    case STR_ENTRY_VAR:
      PRINT ("string-entry-variable");
      break;
    case INT_GLOBAL_VAR:
      PRINT ("integer-global-variable");
      break;
    case STR_GLOBAL_VAR:
      PRINT ("string-global-variable");
      break;
    default:
      unknwn_function_class_confusion ();
      break;
  END
END
/*^^^^^^^^^^^^^^^^^^^^^^^^^^ END OF SECTION 158 ^^^^^^^^^^^^^^^^^^^^^^^^^^^*/




/***************************************************************************
 * WEB section number:	 313
 * ~~~~~~~~~~~~~~~~~~~
 * This is similar to |print_stk_lit|, but here we don't give the
 * literal's type, and here we end with a new line.  This procedure
 * should never be called after popping an empty stack.
 ***************************************************************************/
void          print_lit (Integer_T stk_lt, StkType_T stk_tp)
BEGIN
  switch (stk_tp)
  BEGIN
    case STK_INT:
      PRINT_LN2 ("%ld", (long) stk_lt);
      break;
    case STK_STR:
      PRINT_POOL_STR (stk_lt);
      PRINT_NEWLINE;
      break;
    case STK_FN:
      PRINT_POOL_STR (hash_text[stk_lt]);
      PRINT_NEWLINE;
      break;
    case STK_FIELD_MISSING:
      PRINT_POOL_STR (stk_lt);
      PRINT_NEWLINE;
      break;
    case STK_EMPTY:
      illegl_literal_confusion ();
      break;
    default:
      unknwn_literal_confusion ();
      break;
  END
END
/*^^^^^^^^^^^^^^^^^^^^^^^^^^ END OF SECTION 313 ^^^^^^^^^^^^^^^^^^^^^^^^^^^*/




/**************************************************************************
 * WEB section number:	 284
 * ~~~~~~~~~~~~~~~~~~~
 * When a cite key on the original |cite_list| (or added to |cite_list|
 * because of cross~referencing) didn't appear in the database, complain.
 ***************************************************************************/
void          print_missing_entry (StrNumber_T s)
BEGIN
  PRINT ("Warning--I didn't find a database entry for \"");
  PRINT_POOL_STR (s);
  PRINT_LN ("\"");
  mark_warning ();
END
/*^^^^^^^^^^^^^^^^^^^^^^^^^^ END OF SECTION 284 ^^^^^^^^^^^^^^^^^^^^^^^^^^^*/



/***************************************************************************
 * WEB section number:	 44
 * ~~~~~~~~~~~~~~~~~~~
 * When something in the program wants to be bigger or something out
 * there wants to be smaller, it's time to call it a run.  Here's the
 * first of several macros that have associated procedures so that they
 * produce less inline code.
 ***************************************************************************/
void          print_overflow (void)
BEGIN
  PRINT ("Sorry---you've exceeded BibTeX's ");
  mark_fatal ();
END
/*^^^^^^^^^^^^^^^^^^^^^^^^^^ END OF SECTION  44 ^^^^^^^^^^^^^^^^^^^^^^^^^^^*/



/***************************************************************************
 * WEB section number:	 184
 * ~~~~~~~~~~~~~~~~~~~
 * This macro is similar to the last one but is specifically for
 * recursion in a |wiz_defined| function, which is illegal; it helps save
 * space.
 ***************************************************************************/
void          print_recursion_illegal (void)
BEGIN

#ifdef TRACE
  if (Flag_trace)
    TRACE_PR_NEWLINE;
#endif                      			/* TRACE */

  PRINT_LN ("Curse you, wizard, before you recurse me:");
  PRINT ("function ");
  PRINT_TOKEN;
  PRINT_LN (" is illegal in its own definition");

  /*------------------------------------------------------------------------
   * print_recursion_illegal();
   *----------------------------------------------------------------------*/
  skip_token_print ();
END
/*^^^^^^^^^^^^^^^^^^^^^^^^^^ END OF SECTION 184 ^^^^^^^^^^^^^^^^^^^^^^^^^^^*/



/***************************************************************************
 * WEB section number:	 96
 * ~~~~~~~~~~~~~~~~~~~
 * This little procedure exists because it's used by at least two other
 * procedures and thus saves some space.
 ***************************************************************************/
void          print_skipping_whatever_remains (void)
BEGIN
  PRINT ("I'm skipping whatever remains of this ");
END
/*^^^^^^^^^^^^^^^^^^^^^^^^^^ END OF SECTION  96 ^^^^^^^^^^^^^^^^^^^^^^^^^^^*/



/***************************************************************************
 * WEB section number:	 311
 * ~~~~~~~~~~~~~~~~~~~
 * Occasionally we'll want to know what's on the literal stack.  Here we
 * print out a stack literal, giving its type.  This procedure should
 * never be called after popping an empty stack.
 ***************************************************************************/
void          print_stk_lit (Integer_T stk_lt, StkType_T stk_tp)
BEGIN
  switch (stk_tp)
  BEGIN
    case STK_INT:
      PRINT2 ("%ld is an integer literal", (long) stk_lt);
      break;
    case STK_STR:
      PRINT ("\"");
      PRINT_POOL_STR (stk_lt);
      PRINT ("\" is a string literal");
      break;
    case STK_FN:
      PRINT ("`");
      PRINT_POOL_STR (hash_text[stk_lt]);
      PRINT ("' is a function literal");
      break;
    case STK_FIELD_MISSING:
      PRINT ("`");
      PRINT_POOL_STR (stk_lt);
      PRINT ("' is a missing field");
      break;
    case STK_EMPTY:
      illegl_literal_confusion ();
      break;
    default:
      unknwn_literal_confusion ();
      break;
  END
END
/*^^^^^^^^^^^^^^^^^^^^^^^^^^ END OF SECTION 311 ^^^^^^^^^^^^^^^^^^^^^^^^^^^*/



/***************************************************************************
 * WEB section number:	 312
 * ~~~~~~~~~~~~~~~~~~~
 * This procedure appropriately chastises the style designer; however, if
 * the wrong literal came from popping an empty stack, the procedure
 * |pop_lit_stack| will have already done the chastising (because this
 * procedure is called only after popping the stack) so there's no need
 * for more.
 ***************************************************************************/
void          print_wrong_stk_lit (Integer_T stk_lt, StkType_T stk_tp1,
				   StkType_T stk_tp2)
BEGIN
  if (stk_tp1 != STK_EMPTY)
  BEGIN
    print_stk_lit (stk_lt, stk_tp1);
    switch (stk_tp2)
    BEGIN
      case STK_INT:
        PRINT (", not an integer,");
        break;
      case STK_STR:
        PRINT (", not a string,");
        break;
      case STK_FN:
        PRINT (", not a function,");
        break;
      case STK_FIELD_MISSING:
      case STK_EMPTY:
        illegl_literal_confusion ();
        break;
      default:
        unknwn_literal_confusion ();
        break;
    END
    bst_ex_warn_print ();
  END
END
/*^^^^^^^^^^^^^^^^^^^^^^^^^^ END OF SECTION 312 ^^^^^^^^^^^^^^^^^^^^^^^^^^^*/



/***************************************************************************
 * WEB section number:	 307
 * ~~~~~~~~~~~~~~~~~~~
 * Ok, that's it for sorting; now we'll play with the literal stack.
 * This procedure pushes a literal onto the stack, checking for stack
 * overflow.
 ***************************************************************************/
void          push_lit_stk (Integer_T push_lt, StkType_T push_type)
BEGIN

#ifdef TRACE
  LitStkLoc_T       dum_ptr;
#endif                      			/* TRACE */

  lit_stack[lit_stk_ptr] = push_lt;
  lit_stk_type[lit_stk_ptr] = push_type;

#ifdef TRACE
  if (Flag_trace) {
    for (dum_ptr=0; dum_ptr <= lit_stk_ptr; dum_ptr++)
    BEGIN
      TRACE_PR ("  ");
    END
    TRACE_PR ("Pushing ");

    switch (lit_stk_type[lit_stk_ptr])
    BEGIN
      case STK_INT:
        TRACE_PR_LN2 ("%ld", (long) lit_stack[lit_stk_ptr]);
        break;
      case STK_STR:
        TRACE_PR ("\"");
        TRACE_PR_POOL_STR (lit_stack[lit_stk_ptr]);
        TRACE_PR_LN ("\"");
        break;
      case STK_FN:
        TRACE_PR ("`");
        TRACE_PR_POOL_STR (hash_text[lit_stack[lit_stk_ptr]]);
        TRACE_PR_LN ("'");
        break;
      case STK_FIELD_MISSING:
        TRACE_PR ("missing field `");
        out_pool_str (log_file, lit_stack[lit_stk_ptr]);
        TRACE_PR_LN ("'");
        break;
      case STK_EMPTY:
        TRACE_PR_LN ("a bad literal--popped from an empty stack");
        break;
      default:
        unknwn_literal_confusion ();
        break;
    END
  }                             /* end if (Flag_trace) */
#endif                      			/* TRACE */

  if (lit_stk_ptr == LIT_STK_SIZE)
  BEGIN
    BIBTEX_OVERFLOW ("literal-stack size ", LIT_STK_SIZE);
  END
  INCR (lit_stk_ptr);
END
/*^^^^^^^^^^^^^^^^^^^^^^^^^^ END OF SECTION 307 ^^^^^^^^^^^^^^^^^^^^^^^^^^^*/


/***************************************************************************
 * WEB section number:	 303
 * ~~~~~~~~~~~~~~~~~~~
 * These next two procedures (actually, one procedures and one function,
 * but who's counting) are subroutines for |quick_sort|, which follows.
 * The |swap| procedure exchanges the two elements its arguments point
 * to.
 ***************************************************************************/
void          quick_sort (CiteNumber_T left_end, CiteNumber_T right_end)
BEGIN
  CiteNumber_T      left,
		    right;
  CiteNumber_T      insert_ptr;
  CiteNumber_T      middle;
  CiteNumber_T      partition;

#ifdef TRACE
  if (Flag_trace)
    TRACE_PR_LN3 ("Sorting %ld through %ld", (long) left_end,
		  (long) right_end);
#endif                      			/* TRACE */

  if ((right_end - left_end) < SHORT_LIST)
  BEGIN

/***************************************************************************
 * WEB section number:	304
 * ~~~~~~~~~~~~~~~~~~~
 * This code sorts the entries between |left_end| and |right_end| when
 * the difference is less than |short_list|.  Each iteration of the outer
 * loop inserts the element indicated by |insert_ptr| into its proper
 * place among the (sorted) elements from |left_end| through
 * |insert_ptr-1|.
 ***************************************************************************/
    for (insert_ptr=(left_end+1); insert_ptr<=right_end; insert_ptr++)
    BEGIN
      for (right=insert_ptr; right >= (left_end+1); right--)
      BEGIN
        if (less_than (SORTED_CITES[right-1], SORTED_CITES[right]))
        BEGIN
          goto Next_Insert_Label;
        END
        swap (right - 1, right);
      END
Next_Insert_Label: DO_NOTHING;
    END
/*^^^^^^^^^^^^^^^^^^^^^^^^^^ END OF SECTION 304 ^^^^^^^^^^^^^^^^^^^^^^^^^^^*/

  END
  else
  BEGIN

/***************************************************************************
 * WEB section number:	305
 * ~~~~~~~~~~~~~~~~~~~
 * Now we find the median of the three sort.key$s to which the three
 * elements |sorted_cites[left_end+end_offset]|,
 * |sorted_cites[right_end]-end_offset|, and
 * |sorted_cites[(left_end+right_end) div 2]| point (a nonzero
 * |end_offset| avoids using as the leftmost of the three elements the
 * one that was swapped there when the old partition element was swapped
 * into its final spot; this turns out to avoid $n^2$ behavior when the
 * list is nearly sorted to start with).  This code determines which of
 * the six possible permutations we're dealing with and moves the median
 * element to |left_end|.  The comments next to the |swap| actions give
 * the known orderings of the corresponding elements of |sorted_cites|
 * before the action.
 ***************************************************************************/
    left = left_end + END_OFFSET;
    middle = (left_end + right_end) / 2;
    right = right_end - END_OFFSET;
    if (less_than (SORTED_CITES[left], SORTED_CITES[middle]))
    BEGIN
      if (less_than (SORTED_CITES[middle], SORTED_CITES[right]))
      BEGIN
        swap (left_end, middle);
      END
      else if (less_than (SORTED_CITES[left], SORTED_CITES[right]))
      BEGIN
        swap (left_end, right);
      END
      else
      BEGIN
        swap (left_end, left);
      END
    END
    else if (less_than (SORTED_CITES[right], SORTED_CITES[middle]))
    BEGIN
      swap (left_end, middle);
    END
    else if (less_than (SORTED_CITES[right], SORTED_CITES[left]))
    BEGIN
      swap (left_end, right);
    END
    else
    BEGIN
      swap (left_end, left);
    END
/*^^^^^^^^^^^^^^^^^^^^^^^^^^ END OF SECTION 305 ^^^^^^^^^^^^^^^^^^^^^^^^^^^*/

/***************************************************************************
 * WEB section number:	306
 * ~~~~~~~~~~~~~~~~~~~
 * This module uses the median-of-three computed above to partition the
 * elements into those less than and those greater than the median.
 * Equal sort.key$s are sorted by order of occurrence (in
 * |cite_list|).
 ***************************************************************************/
    partition = SORTED_CITES[left_end];
    left = left_end + 1;
    right = right_end;
    do
    BEGIN
      while (less_than (SORTED_CITES[left], partition))
      BEGIN
        INCR (left);
      END
      while (less_than (partition, SORTED_CITES[right]))
      BEGIN
        DECR (right);
      END
      if (left < right)
      BEGIN
        swap (left, right);
        INCR (left);
        DECR (right);
      END
    END while ( ! (left == (right + 1)));
    swap (left_end, right);
    quick_sort (left_end, right - 1);
    quick_sort (left, right_end);
  END
/*^^^^^^^^^^^^^^^^^^^^^^^^^^ END OF SECTION 306 ^^^^^^^^^^^^^^^^^^^^^^^^^^^*/

END
/*^^^^^^^^^^^^^^^^^^^^^^^^^^ END OF SECTION 303 ^^^^^^^^^^^^^^^^^^^^^^^^^^^*/




/***************************************************************************
 * WEB section number:	 98
 * ~~~~~~~~~~~~~~~~~~~
 * I mean, this is truly disgraceful.  A user has to type something in to
 * the terminal just once during the entire run.  And it's not some
 * complicated string where you have to get every last punctuation mark
 * just right, and it's not some fancy list where you get nervous because
 * if you forget one item you have to type the whole thing again; it's
 * just a simple, ordinary, file name.  Now you'd think a five-year-old
 * could do it; you'd think it's so simple a user should be able to do it
 * in his sleep.  But noooooooooo.  He had to sit there droning on and on
 * about who knows what until he exceeded the bounds of common sense, and
 * he probably didn't even realize it.  Just pitiful.  What's this world
 * coming to?  We should probably just delete all his files and be done
 * with him.  Note: The |TERM_OUT| file is system dependent.
 *
 * NOTE: because C arrays start at index 0, not 1, the subscripts of array
 *	 |name_of_file| are generally 1 less than those in the WEB source.
 ***************************************************************************/
void          sam_too_long_file_name_print (void)
BEGIN
  FPRINTF (TERM_OUT, "File name `");
  name_ptr = 0;
  while (name_ptr < aux_name_length)
  BEGIN
    FPUTC (name_of_file[name_ptr], TERM_OUT);
    INCR (name_ptr);
  END
  FPRINTF (TERM_OUT, "' is too long\n");
END
/*^^^^^^^^^^^^^^^^^^^^^^^^^^ END OF SECTION  98 ^^^^^^^^^^^^^^^^^^^^^^^^^^^*/



/***************************************************************************
 * WEB section number:	 99
 * ~~~~~~~~~~~~~~~~~~~
 * We've abused the user enough for one section; suffice it to
 * say here that most of what we said last module still applies.
 * Note: The |TERM_OUT| file is system dependent.
 *
 * NOTE: because C arrays start at index 0, not 1, the subscripts of array
 *	 |name_of_file| are generally 1 less than those in the WEB source.
 ***************************************************************************/
void          sam_wrong_file_name_print (void)
BEGIN
  FPRINTF (TERM_OUT, "I couldn't open file name `");
  name_ptr = 0;
  while (name_ptr < name_length)
  BEGIN
    FPUTC (name_of_file[name_ptr], TERM_OUT);
    INCR (name_ptr);
  END
  FPRINTF (TERM_OUT, "'\n");
END
/*^^^^^^^^^^^^^^^^^^^^^^^^^^ END OF SECTION  99 ^^^^^^^^^^^^^^^^^^^^^^^^^^^*/



/***************************************************************************
 * WEB section number:	 83
 * ~~~~~~~~~~~~~~~~~~~
 * This function scans the |buffer| for the next token, starting at the
 * global variable |buf_ptr2| and ending just before either the single
 * specified stop-character or the end of the current line, whichever
 * comes first, respectively returning |true| or |false|; afterward,
 * |scan_char| is the first character following this token.
 ***************************************************************************/
Boolean_T         scan1 (ASCIICode_T char1)
BEGIN
  Boolean_T	  scan1;

  buf_ptr1 = buf_ptr2;
  while ((SCAN_CHAR != char1) && (buf_ptr2 < last))
  BEGIN
    INCR (buf_ptr2);
  END
  if (buf_ptr2 < last)
  BEGIN
    scan1 = TRUE;
  END
  else
  BEGIN
    scan1 = FALSE;
  END
  return (scan1);
END
/*^^^^^^^^^^^^^^^^^^^^^^^^^^ END OF SECTION  83 ^^^^^^^^^^^^^^^^^^^^^^^^^^^*/



/***************************************************************************
 * WEB section number:	 84
 * ~~~~~~~~~~~~~~~~~~~
 * This function is the same but stops at |white_space| characters as well.
 ***************************************************************************/
Boolean_T         scan1_white (ASCIICode_T char1)
BEGIN
  Boolean_T       scan1_white;

  buf_ptr1 = buf_ptr2;
  while ((lex_class[SCAN_CHAR] != WHITE_SPACE)
	    && (SCAN_CHAR != char1) && (buf_ptr2 < last))
  BEGIN
    INCR (buf_ptr2);
  END
  if (buf_ptr2 < last)
  BEGIN
    scan1_white = TRUE;
  END
  else
  BEGIN
    scan1_white = FALSE;
  END
  return (scan1_white);
END
/*^^^^^^^^^^^^^^^^^^^^^^^^^^ END OF SECTION  84 ^^^^^^^^^^^^^^^^^^^^^^^^^^^*/




/***************************************************************************
 * WEB section number:	 85
 * ~~~~~~~~~~~~~~~~~~~
 * This function is similar to |scan1|, but stops at either of two
 * stop-characters as well as the end of the current line.
 ***************************************************************************/
Boolean_T         scan2 (ASCIICode_T char1, ASCIICode_T char2)
BEGIN
  Boolean_T	  scan2;

  buf_ptr1 = buf_ptr2;
  while ((SCAN_CHAR != char1) && (SCAN_CHAR != char2)
	    && (buf_ptr2 < last))
  BEGIN
    INCR (buf_ptr2);
  END
  if (buf_ptr2 < last)
  BEGIN
    scan2 = TRUE;
  END
  else
  BEGIN
    scan2 = FALSE;
  END
  return (scan2);
END
/*^^^^^^^^^^^^^^^^^^^^^^^^^^ END OF SECTION  85 ^^^^^^^^^^^^^^^^^^^^^^^^^^^*/



/***************************************************************************
 * WEB section number:	 86
 * ~~~~~~~~~~~~~~~~~~~
 * This function is the same but stops at |white_space| characters as well.
 ***************************************************************************/
Boolean_T         scan2_white (ASCIICode_T char1, ASCIICode_T char2)
BEGIN
  Boolean_T	  scan2_white;

  buf_ptr1 = buf_ptr2;
  while ((SCAN_CHAR != char1) && (SCAN_CHAR != char2)
	    && (lex_class[SCAN_CHAR] != WHITE_SPACE) && (buf_ptr2 < last))
  BEGIN
    INCR (buf_ptr2);
  END
  if (buf_ptr2 < last)
  BEGIN
    scan2_white = TRUE;
  END
  else
  BEGIN
    scan2_white = FALSE;
  END
  return (scan2_white);
END
/*^^^^^^^^^^^^^^^^^^^^^^^^^^ END OF SECTION  86 ^^^^^^^^^^^^^^^^^^^^^^^^^^^*/




/***************************************************************************
 * WEB section number:	 87
 * ~~~~~~~~~~~~~~~~~~~
 * This function is similar to |scan2|, but stops at either of three
 * stop-characters as well as the end of the current line.
 ***************************************************************************/
Boolean_T         scan3 (ASCIICode_T char1, ASCIICode_T char2,
			 ASCIICode_T char3)
BEGIN
  Boolean_T	  scan3;

  buf_ptr1 = buf_ptr2;
  while ((SCAN_CHAR != char1) && (SCAN_CHAR != char2)
	    && (SCAN_CHAR != char3) && (buf_ptr2 < last))
  BEGIN
    INCR (buf_ptr2);
  END
  if (buf_ptr2 < last)
  BEGIN
    scan3 = TRUE;
  END
  else
  BEGIN
    scan3 = FALSE;
  END
  return (scan3);
END
/*^^^^^^^^^^^^^^^^^^^^^^^^^^ END OF SECTION  87 ^^^^^^^^^^^^^^^^^^^^^^^^^^^*/




/***************************************************************************
 * WEB section number:	 250
 * ~~~~~~~~~~~~~~~~~~~
 * Each field token is either a nonnegative number, a macro name (like
 * `jan'), or a brace-balanced string delimited by either |double_quote|s
 * or braces.  Thus there are four possibilities for the first character
 * of the field token: If it's a |left_brace| or a |double_quote|, the
 * token (with balanced braces, up to the matching |right_str_delim|) is
 * a string; if it's |numeric|, the token is a number; if it's anything
 * else, the token is a macro name (and should thus have been defined by
 * either the .bst-file's macro command or the .bib-file's
 * string command).  This function returns |false| if there was a
 * serious syntax error.
 ***************************************************************************/
Boolean_T         scan_a_field_token_and_eat_whit (void)
BEGIN
  Boolean_T scan_a_field_token_And_eat_whit;

  scan_a_field_token_And_eat_whit = FALSE;
  switch (SCAN_CHAR)
  BEGIN
    case LEFT_BRACE:
      right_str_delim = RIGHT_BRACE;
      if ( ! scan_balanced_braces ())
        goto Exit_Label;
      break;
    case DOUBLE_QUOTE:
      right_str_delim = DOUBLE_QUOTE;
      if ( ! scan_balanced_braces ())
        goto Exit_Label;
      break;
    case '0':
    case '1':
    case '2':
    case '3':
    case '4':
    case '5':
    case '6':
    case '7':
    case '8':
    case '9':

/***************************************************************************
 * WEB section number:	258
 * ~~~~~~~~~~~~~~~~~~~
 * This module scans a nonnegative number and copies it to |field_vl_str|
 * if it's to store the field.
 ***************************************************************************/
      if ( ! scan_nonneg_integer ())
      BEGIN
        CONFUSION ("A digit disappeared");
      END
      if (store_field)
      BEGIN
        tmp_ptr = buf_ptr1;
        while (tmp_ptr < buf_ptr2)
        BEGIN
	  COPY_CHAR (buffer[tmp_ptr]);
          INCR (tmp_ptr);
        END
      END
/*^^^^^^^^^^^^^^^^^^^^^^^^^^ END OF SECTION 258 ^^^^^^^^^^^^^^^^^^^^^^^^^^^*/

      break;
    default:

/***************************************************************************
 * WEB section number:	259
 * ~~~~~~~~~~~~~~~~~~~
 * This module scans a macro name and copies its string to |field_vl_str|
 * if it's to store the field, complaining if the macro is recursive or
 * undefined.
 ***************************************************************************/
      scan_identifier (COMMA, right_outer_delim, CONCAT_CHAR);
      BIB_IDENTIFIER_SCAN_CHECK ("a field part");
      if (store_field)
      BEGIN
        lower_case (buffer, buf_ptr1, TOKEN_LEN);
        macro_name_loc = str_lookup (buffer, buf_ptr1, TOKEN_LEN, MACRO_ILK,
					DONT_INSERT);
        store_token = TRUE;
        if (at_bib_command)
        BEGIN
          if (command_num == N_BIB_STRING)
          BEGIN
            if (macro_name_loc == cur_macro_loc)
            BEGIN
              store_token = FALSE;
              MACRO_NAME_WARNING ("used in its own definition");
            END
          END
        END
        if ( ! hash_found)
        BEGIN
          store_token = FALSE;
	  MACRO_NAME_WARNING ("undefined");
        END
        if (store_token)
        BEGIN

/***************************************************************************
 * WEB section number:	260
 * ~~~~~~~~~~~~~~~~~~~
 * The macro definition may have |white_space| that needs compressing,
 * because it may have been defined in the .bst file.
 ***************************************************************************/
          tmp_ptr = str_start[ilk_info[macro_name_loc]];
          tmp_end_ptr = str_start[ilk_info[macro_name_loc] + 1];
          if (FIELD_END == 0)
          BEGIN
            if ((lex_class[str_pool[tmp_ptr]] == WHITE_SPACE)
		    && (tmp_ptr < tmp_end_ptr))
            BEGIN
	      COPY_CHAR (SPACE);
              INCR (tmp_ptr);
              while ((lex_class[str_pool[tmp_ptr]] == WHITE_SPACE)
			&& (tmp_ptr < tmp_end_ptr))
              BEGIN
                INCR (tmp_ptr);
              END
            END
          END
          while (tmp_ptr < tmp_end_ptr)
          BEGIN
            if (lex_class[str_pool[tmp_ptr]] != WHITE_SPACE)
            BEGIN
              COPY_CHAR (str_pool[tmp_ptr]);
            END
            else if (FIELD_VL_STR[FIELD_END - 1] != SPACE)
            BEGIN
	      COPY_CHAR (SPACE);
            END
            INCR (tmp_ptr);
          END
        END
/*^^^^^^^^^^^^^^^^^^^^^^^^^^ END OF SECTION 260 ^^^^^^^^^^^^^^^^^^^^^^^^^^^*/

      END
/*^^^^^^^^^^^^^^^^^^^^^^^^^^ END OF SECTION 259 ^^^^^^^^^^^^^^^^^^^^^^^^^^^*/

      break;
  END
  EAT_BIB_WHITE_AND_EOF_CHECK;
  scan_a_field_token_And_eat_whit = TRUE;
Exit_Label: DO_NOTHING;
  return (scan_a_field_token_And_eat_whit);
END
/*^^^^^^^^^^^^^^^^^^^^^^^^^^ END OF SECTION 250 ^^^^^^^^^^^^^^^^^^^^^^^^^^^*/



/***************************************************************************
 * WEB section number:	 88
 * ~~~~~~~~~~~~~~~~~~~
 * This function scans for letters, stopping at the first nonletter; it
 * returns |true| if there is at least one letter.
 ***************************************************************************/
Boolean_T         scan_alpha (void)
BEGIN
  Boolean_T	  scan_alpha;

  buf_ptr1 = buf_ptr2;
  while ((lex_class[SCAN_CHAR] == ALPHA) && (buf_ptr2 < last))
  BEGIN
    INCR (buf_ptr2);
  END
  if (TOKEN_LEN == 0)
  BEGIN
    scan_alpha = FALSE;
  END
  else
  BEGIN
    scan_alpha = TRUE;
  END
  return (scan_alpha);
END
/*^^^^^^^^^^^^^^^^^^^^^^^^^^ END OF SECTION 88 ^^^^^^^^^^^^^^^^^^^^^^^^^^^*/



/***************************************************************************
 * WEB section number:	 249
 * ~~~~~~~~~~~~~~~~~~~
 * This function scans the list of field tokens that define the field
 * value string.  If |store_field| is |true| it accumulates (indirectly)
 * in |field_vl_str| the concatenation of all the field tokens,
 * compressing nonnull |white_space| to a single |space| and, if the
 * field value is for a field (rather than a string definition), removing
 * any leading or trailing |white_space|; when it's finished it puts the
 * string into the hash table.  It returns |false| if there was a serious
 * syntax error.
 ***************************************************************************/
Boolean_T         scan_and_store_the_field_value (void)
BEGIN
  Boolean_T    scan_and_store_the_field_value;

  scan_and_store_the_field_value = FALSE;
  FIELD_END = 0;
  if ( ! scan_a_field_token_and_eat_whit ())
  BEGIN
    goto Exit_Label;
  END
  while (SCAN_CHAR == CONCAT_CHAR)
  BEGIN
    INCR (buf_ptr2);
    EAT_BIB_WHITE_AND_EOF_CHECK;
    if ( ! scan_a_field_token_and_eat_whit ())
    BEGIN
      goto Exit_Label;
    END
  END
  if (store_field)
  BEGIN

/***************************************************************************
 * WEB section number:	261
 * ~~~~~~~~~~~~~~~~~~~
 * Now it's time to store the field value in the hash table, and store an
 * appropriate pointer to it (depending on whether it's for a database
 * entry or command).  But first, if necessary, we remove a trailing
 * |space| and a leading |space| if these exist.  (Hey, if we had some
 * ham we could make ham-and-eggs if we had some eggs.)
 ***************************************************************************/
    if ( ! at_bib_command)
    BEGIN
      if (FIELD_END > 0)
      BEGIN
        if (FIELD_VL_STR[FIELD_END - 1] == SPACE)
        BEGIN
          DECR (FIELD_END);
        END
      END
    END
    if (( ! at_bib_command) && (FIELD_VL_STR[0] == SPACE) && (FIELD_END > 0))
    BEGIN
      FIELD_START = 1;
    END
    else
    BEGIN
      FIELD_START = 0;
    END
    field_val_loc = str_lookup (FIELD_VL_STR, FIELD_START,
				FIELD_END - FIELD_START, TEXT_ILK,
				DO_INSERT);
    fn_type[field_val_loc] = STR_LITERAL;

#ifdef TRACE
    if (Flag_trace) {
      TRACE_PR ("\"");
      TRACE_PR_POOL_STR (hash_text[field_val_loc]);
      TRACE_PR_LN ("\" is a field value");
    }
#endif                      			/* TRACE */

    if (at_bib_command)
    BEGIN

/***************************************************************************
 * WEB section number:	262
 * ~~~~~~~~~~~~~~~~~~~
 * Here's where we store the goods when we're dealing with a command
 * rather than an entry.
 ***************************************************************************/
      switch (command_num)
      BEGIN
        case N_BIB_PREAMBLE:
          s_preamble[preamble_ptr] = hash_text[field_val_loc];
          INCR (preamble_ptr);
          break;
        case N_BIB_STRING:
          ilk_info[cur_macro_loc] = hash_text[field_val_loc];
          break;
        default:
          bib_cmd_confusion ();
          break;
      END
/*^^^^^^^^^^^^^^^^^^^^^^^^^^ END OF SECTION 262 ^^^^^^^^^^^^^^^^^^^^^^^^^^^*/

    END
    else
    BEGIN

/***************************************************************************
 * WEB section number:	263
 * ~~~~~~~~~~~~~~~~~~~
 * And here, an entry.
 ***************************************************************************/
      field_ptr = (entry_cite_ptr * num_fields) + FN_INFO[field_name_loc];
      if (field_info[field_ptr] != MISSING)
      BEGIN
        PRINT ("Warning--I'm ignoring ");
        PRINT_POOL_STR (cite_list[entry_cite_ptr]);
        PRINT ("'s extra \"");
        PRINT_POOL_STR (hash_text[field_name_loc]);
        BIB_WARN_NEWLINE ("\" field");
      END
      else
      BEGIN
        field_info[field_ptr] = hash_text[field_val_loc];
        if ((ilk_info[field_name_loc] == crossref_num)
		&& ( ! all_entries))
        BEGIN

/***************************************************************************
 * WEB section number:	264
 * ~~~~~~~~~~~~~~~~~~~
 * If the cross-referenced entry isn't already on |cite_list| we add it
 * (at least temporarily); if it is already on |cite_list| we update the
 * cross-reference count, if necessary.  Note that |all_entries| is
 * |false| here.  The alias kludge helps make the stack space not
 * overflow on some machines.
 ***************************************************************************/
          tmp_ptr = FIELD_START;
          while (tmp_ptr < FIELD_END)
          BEGIN
            EXTRA_BUF[tmp_ptr] = FIELD_VL_STR[tmp_ptr];
            INCR (tmp_ptr);
          END
          lower_case (EXTRA_BUF, FIELD_START, FIELD_END - FIELD_START);
          lc_cite_loc = str_lookup (EXTRA_BUF, FIELD_START,
				    FIELD_END - FIELD_START, LC_CITE_ILK,
				    DO_INSERT);
          if (hash_found)
          BEGIN
            cite_loc = ilk_info[lc_cite_loc];
            if (ilk_info[cite_loc] >= old_num_cites)
            BEGIN
              INCR (cite_info[ilk_info[cite_loc]]);
            END
          END
          else
          BEGIN
            cite_loc = str_lookup (FIELD_VL_STR, FIELD_START,
				   FIELD_END - FIELD_START, CITE_ILK,
				   DO_INSERT);
            if (hash_found)
            BEGIN
              hash_cite_confusion ();
            END
            add_database_cite (&cite_ptr);
            cite_info[ilk_info[cite_loc]] = 1;
          END
/*^^^^^^^^^^^^^^^^^^^^^^^^^^ END OF SECTION 264 ^^^^^^^^^^^^^^^^^^^^^^^^^^^*/

        END
      END
/*^^^^^^^^^^^^^^^^^^^^^^^^^^ END OF SECTION 263 ^^^^^^^^^^^^^^^^^^^^^^^^^^^*/

    END
/*^^^^^^^^^^^^^^^^^^^^^^^^^^ END OF SECTION 261 ^^^^^^^^^^^^^^^^^^^^^^^^^^^*/

  END
  scan_and_store_the_field_value = TRUE;
Exit_Label: DO_NOTHING;
  return (scan_and_store_the_field_value);
END
/*^^^^^^^^^^^^^^^^^^^^^^^^^^ END OF SECTION 249 ^^^^^^^^^^^^^^^^^^^^^^^^^^^*/



/***************************************************************************
 * WEB section number:	 253
 * ~~~~~~~~~~~~~~~~~~~
 * This .bib-specific function scans a string with balanced braces,
 * stopping just past the matching |right_str_delim|.  How much work it
 * does depends on whether |store_field = true|.  It returns |false| if
 * there was a serious syntax error.
 ***************************************************************************/
Boolean_T         scan_balanced_braces (void)
BEGIN
  Boolean_T    scan_balanced_braces;

  scan_balanced_braces = FALSE;
  INCR (buf_ptr2);
  CHECK_FOR_AND_COMPRESS_BIB_WHIT;
  if (FIELD_END > 1)
  BEGIN
    if (FIELD_VL_STR[FIELD_END- 1] == SPACE)
    BEGIN
      if (ex_buf[FIELD_END- 2] == SPACE)
      BEGIN
        DECR (FIELD_END);
      END
    END
  END
  bib_brace_level = 0;
  if (store_field)
  BEGIN

/***************************************************************************
 * WEB section number:	256
 * ~~~~~~~~~~~~~~~~~~~
 * This module scans over a brace-balanced string, compressing multiple
 * |white_space| characters into a single |space|.  It starts with
 * |bib_brace_level = 0| and starts at a non|white_space| character.
 ***************************************************************************/
    while (SCAN_CHAR != right_str_delim)
    BEGIN
      switch (SCAN_CHAR)
      BEGIN
        case LEFT_BRACE:
          INCR (bib_brace_level);
	  COPY_CHAR (LEFT_BRACE);
          INCR (buf_ptr2);
	  CHECK_FOR_AND_COMPRESS_BIB_WHIT;

/***************************************************************************
 * WEB section number:	257
 * ~~~~~~~~~~~~~~~~~~~
 * This module is similar to the last but starts with |bib_brace_level > 0|
 * (and, like the last, it starts at a non|white_space| character).
 ***************************************************************************/
          LOOP
          BEGIN
            switch (SCAN_CHAR)
            BEGIN
              case RIGHT_BRACE:
                DECR (bib_brace_level);
                COPY_CHAR (RIGHT_BRACE);
                INCR (buf_ptr2);
		CHECK_FOR_AND_COMPRESS_BIB_WHIT;
                if (bib_brace_level == 0)
                BEGIN
                  goto Loop_Exit_Label;
                END
                break;
              case LEFT_BRACE:
                INCR (bib_brace_level);
		COPY_CHAR (LEFT_BRACE);
                INCR (buf_ptr2);
		CHECK_FOR_AND_COMPRESS_BIB_WHIT;
                break;
              default:
		COPY_CHAR (SCAN_CHAR);
                INCR (buf_ptr2);
		CHECK_FOR_AND_COMPRESS_BIB_WHIT;
                break;
            END
          END
      Loop_Exit_Label: DO_NOTHING
/*^^^^^^^^^^^^^^^^^^^^^^^^^^ END OF SECTION 257 ^^^^^^^^^^^^^^^^^^^^^^^^^^^*/

          break;
        case RIGHT_BRACE:
          BIB_UNBALANCED_BRACES_ERR;
        default:
	  COPY_CHAR (SCAN_CHAR);
          INCR (buf_ptr2);
	  CHECK_FOR_AND_COMPRESS_BIB_WHIT;
          break;
      END
    END
/*^^^^^^^^^^^^^^^^^^^^^^^^^^ END OF SECTION 256 ^^^^^^^^^^^^^^^^^^^^^^^^^^^*/

  END
  else
  BEGIN

/***************************************************************************
 * WEB section number:	254
 * ~~~~~~~~~~~~~~~~~~~
 * This module scans over a brace-balanced string without keeping track
 * of anything but the brace level.  It starts with |bib_brace_level = 0|
 * and at a non|white_space| character.
 ***************************************************************************/
    while (SCAN_CHAR != right_str_delim)
    BEGIN
      if (SCAN_CHAR == LEFT_BRACE)
      BEGIN
        INCR (bib_brace_level);
        INCR (buf_ptr2);
	EAT_BIB_WHITE_AND_EOF_CHECK;
        while (bib_brace_level > 0)
        BEGIN

/***************************************************************************
 * WEB section number:	255
 * ~~~~~~~~~~~~~~~~~~~
 * This module does the same as above but, because |bib_brace_level > 0|, it
 * doesn't have to look for a |right_str_delim|.
 ***************************************************************************/
          if (SCAN_CHAR == RIGHT_BRACE)
          BEGIN
            DECR (bib_brace_level);
            INCR (buf_ptr2);
	    EAT_BIB_WHITE_AND_EOF_CHECK;
	  END
          else if (SCAN_CHAR == LEFT_BRACE)
          BEGIN
            INCR (bib_brace_level);
            INCR (buf_ptr2);
	    EAT_BIB_WHITE_AND_EOF_CHECK;
          END
          else
          BEGIN
            INCR (buf_ptr2);
            if ( ! scan2 (RIGHT_BRACE, LEFT_BRACE))
            BEGIN
	      EAT_BIB_WHITE_AND_EOF_CHECK;
            END
          END
/*^^^^^^^^^^^^^^^^^^^^^^^^^^ END OF SECTION 255 ^^^^^^^^^^^^^^^^^^^^^^^^^^^*/

        END
      END
      else if (SCAN_CHAR == RIGHT_BRACE)
      BEGIN
        BIB_UNBALANCED_BRACES_ERR;
      END
      else
      BEGIN
        INCR (buf_ptr2);
        if ( ! scan3 (right_str_delim, LEFT_BRACE, RIGHT_BRACE))
        BEGIN
	  EAT_BIB_WHITE_AND_EOF_CHECK;
        END
      END
    END
/*^^^^^^^^^^^^^^^^^^^^^^^^^^ END OF SECTION 254 ^^^^^^^^^^^^^^^^^^^^^^^^^^^*/

  END
  INCR (buf_ptr2);
  scan_balanced_braces = TRUE;
Exit_Label: DO_NOTHING;
  return (scan_balanced_braces);
END
/*^^^^^^^^^^^^^^^^^^^^^^^^^^ END OF SECTION 253 ^^^^^^^^^^^^^^^^^^^^^^^^^^^*/


/***************************************************************************
 * WEB section number:	 187
 * ~~~~~~~~~~~~~~~~~~~
 * This recursive function reads and stores the list of functions
 * (separated by |white_space| characters or ends-of-line) that define
 * this new function, and reads a |right_brace|.
 ***************************************************************************/
void          scan_fn_def (HashLoc_T fn_hash_loc)
BEGIN
  typedef Integer_T     FnDefLoc_T;
  HashPtr2_T		singl_function[SINGLE_FN_SPACE + 1];
  FnDefLoc_T		single_ptr;
  FnDefLoc_T		copy_ptr;
  BufPointer_T		end_of_num;
  HashLoc_T		impl_fn_loc;

  EAT_BST_WHITE_AND_EOF_CHECK ("function");
  single_ptr = 0;
  while (SCAN_CHAR != RIGHT_BRACE)
  BEGIN

/***************************************************************************
 * WEB section number:	189
 * ~~~~~~~~~~~~~~~~~~~
 * There are five possibilities for the first character of the token
 * representing the next function of the definition: If it's a
 * |number_sign|, the token is an |int_literal|; if it's a
 * |double_quote|, the token is a |str_literal|; if it's a
 * |single_quote|, the token is a quoted function; if it's a
 * |left_brace|, the token isn't really a token, but rather the start of
 * another function definition (which will result in a recursive call to
 * |scan_fn_def|); if it's anything else, the token is the name of an
 * already-defined function.  Note: To prevent the wizard from using
 * recursion, we have to check that neither a quoted function nor an
 * already-defined-function is actually the currently-being-defined
 * function (which is stored at |wiz_loc|).
 ***************************************************************************/
    switch (SCAN_CHAR)
    BEGIN
      case NUMBER_SIGN:

/***************************************************************************
 * WEB section number:	190
 * ~~~~~~~~~~~~~~~~~~~
 * An |int_literal| is preceded by a |number_sign|, consists of an
 * integer (i.e., an optional |minus_sign| followed by one or more
 * |numeric| characters), and is followed either by a |white_space|
 * character, an end-of-line, or a |right_brace|.  The array |fn_info|
 * contains the value of the integer for |int_literal|s.
 ***************************************************************************/
	BEGIN
	  INCR (buf_ptr2);
	  if ( ! scan_integer ())
	  BEGIN
	    SKIP_TOKEN ("Illegal integer in integer literal");
	  END

#ifdef TRACE
          if (Flag_trace) {
	    TRACE_PR ("#");
	    TRACE_PR_TOKEN;
	    TRACE_PR_LN2 (" is an integer literal with value %ld",
			  (long) token_value);
          }
#endif                      			/* TRACE */

	  literal_loc = str_lookup (buffer, buf_ptr1, TOKEN_LEN, INTEGER_ILK,
				    DO_INSERT);
	  if ( ! hash_found)
	  BEGIN
	    fn_type[literal_loc] = INT_LITERAL;
	    FN_INFO[literal_loc] = token_value;
	  END
	  if ((lex_class[SCAN_CHAR] != WHITE_SPACE) && (buf_ptr2 < last)
		  && (SCAN_CHAR != RIGHT_BRACE) && (SCAN_CHAR != COMMENT))
	  BEGIN
	    SKIP_TOKEN_ILLEGAL_STUFF_AFTER;
	  END
	  INSERT_FN_LOC (literal_loc);
	END
/*^^^^^^^^^^^^^^^^^^^^^^^^^^ END OF SECTION 190 ^^^^^^^^^^^^^^^^^^^^^^^^^^^*/

        break;
      case DOUBLE_QUOTE:

/***************************************************************************
 * WEB section number:	191
 * ~~~~~~~~~~~~~~~~~~~
 * A |str_literal| is preceded by a |double_quote| and consists of all
 * characters on this line up to the next |double_quote|.  Also, there
 * must be either a |white_space| character, an end-of-line, a
 * |right_brace|, or a |comment| following (since functions in the
 * definition must be separated by |white_space|).  The array |fn_info|
 * contains nothing for |str_literal|s.
 ***************************************************************************/
	BEGIN
	  INCR (buf_ptr2);
	  if ( ! scan1 (DOUBLE_QUOTE))
	  BEGIN
	    SKIP_TOKEN2 ("No `%c' to end string literal", xchr[DOUBLE_QUOTE]);
	  END

#ifdef TRACE
          if (Flag_trace) {
  	    TRACE_PR ("\"");
	    TRACE_PR_TOKEN;
	    TRACE_PR ("\"");
	    TRACE_PR_LN (" is a string literal");
          }
#endif                      			/* TRACE */

	  literal_loc = str_lookup (buffer, buf_ptr1, TOKEN_LEN, TEXT_ILK,
				   DO_INSERT);
	  fn_type[literal_loc] = STR_LITERAL;
	  INCR (buf_ptr2);
	  if ((lex_class[SCAN_CHAR] != WHITE_SPACE) && (buf_ptr2 < last)
	      && (SCAN_CHAR != RIGHT_BRACE)  && (SCAN_CHAR != COMMENT))
	  BEGIN
	    SKIP_TOKEN_ILLEGAL_STUFF_AFTER;
	  END
	  INSERT_FN_LOC (literal_loc);
	END
/*^^^^^^^^^^^^^^^^^^^^^^^^^^ END OF SECTION 191 ^^^^^^^^^^^^^^^^^^^^^^^^^^^*/

        break;
      case SINGLE_QUOTE:

/***************************************************************************
 * WEB section number:	192
 * ~~~~~~~~~~~~~~~~~~~
 * A quoted function is preceded by a |single_quote| and consists of all
 * characters up to the next |white_space| character, end-of-line,
 * |right_brace|, or |comment|.
 ***************************************************************************/
	BEGIN
	  INCR (buf_ptr2);
	  if (scan2_white (RIGHT_BRACE, COMMENT))
	  BEGIN
	    DO_NOTHING;
	  END

#ifdef TRACE
          if (Flag_trace) {
	    TRACE_PR ("'");
	    TRACE_PR_TOKEN;
	    TRACE_PR (" is a quoted function ");
          }
#endif                      			/* TRACE */

	  lower_case (buffer, buf_ptr1, TOKEN_LEN);
	  fn_loc = str_lookup (buffer, buf_ptr1, TOKEN_LEN, BST_FN_ILK,
			       DONT_INSERT);
	  if ( ! hash_found)
	  BEGIN
	    SKIP_TOKEN_UNKNOWN_FUNCTION;
	  END
	  else

/***************************************************************************
 * WEB section number:	193
 * ~~~~~~~~~~~~~~~~~~~
 * Here we check that this quoted function is a legal one---the function
 * name must already exist, but it mustn't be the currently-being-defined
 * function (which is stored at |wiz_loc|).
 ***************************************************************************/
	  BEGIN
	    if (fn_loc == wiz_loc)
	    BEGIN
	      SKIP_RECURSIVE_TOKEN;
	    END
	    else
	    BEGIN

#ifdef TRACE
              if (Flag_trace) {
	        TRACE_PR ("of type ");
	        trace_pr_fn_class (fn_loc);
	        TRACE_PR_NEWLINE;
              }
#endif                      			/* TRACE */

	      INSERT_FN_LOC (QUOTE_NEXT_FN);
	      INSERT_FN_LOC (fn_loc);
	    END
	  END
/*^^^^^^^^^^^^^^^^^^^^^^^^^^ END OF SECTION 193 ^^^^^^^^^^^^^^^^^^^^^^^^^^^*/

	END
/*^^^^^^^^^^^^^^^^^^^^^^^^^^ END OF SECTION 192 ^^^^^^^^^^^^^^^^^^^^^^^^^^^*/

        break;
      case LEFT_BRACE:

/***************************************************************************
 * WEB section number:	194
 * ~~~~~~~~~~~~~~~~~~~
 * This module marks the implicit function as being quoted, generates a
 * name, and stores it in the hash table.  This name is strictly internal
 * to this program, starts with a |single_quote| (since that will make
 * this function name unique), and ends with the variable |impl_fn_num|
 * converted to ASCII.  The alias kludge helps make the stack space not
 * overflow on some machines.
 ***************************************************************************/
        BEGIN
	  EX_BUF2[0] = SINGLE_QUOTE;
	  int_to_ASCII (impl_fn_num, EX_BUF2, 1, &end_of_num);
	  impl_fn_loc = str_lookup (EX_BUF2, 0, end_of_num, BST_FN_ILK,
				    DO_INSERT);
	  if (hash_found)
	  BEGIN
	    CONFUSION ("Already encountered implicit function");
	  END

#ifdef TRACE
          if (Flag_trace) {
	    TRACE_PR_POOL_STR (hash_text[impl_fn_loc]);
	    TRACE_PR_LN (" is an implicit function");
          }
#endif                      			/* TRACE */

	  INCR (impl_fn_num);
	  fn_type[impl_fn_loc] = WIZ_DEFINED;
	  INSERT_FN_LOC (QUOTE_NEXT_FN);
	  INSERT_FN_LOC (impl_fn_loc);
	  INCR (buf_ptr2);
	  scan_fn_def (impl_fn_loc);
	END
/*^^^^^^^^^^^^^^^^^^^^^^^^^^ END OF SECTION 194 ^^^^^^^^^^^^^^^^^^^^^^^^^^^*/

        break;
      default:

/***************************************************************************
 * WEB section number:	199
 * ~~~~~~~~~~~~~~~~~~~
 * An already-defined function consists of all characters up to the next
 * |white_space| character, end-of-line, |right_brace|, or |comment|.
 * This function name must already exist, but it mustn't be the
 * currently-being-defined function (which is stored at |wiz_loc|).
 ***************************************************************************/
        BEGIN
	    if (scan2_white (RIGHT_BRACE, COMMENT))
	    BEGIN
	      DO_NOTHING;
	    END

#ifdef TRACE
            if (Flag_trace) {
	      TRACE_PR_TOKEN;
	      TRACE_PR (" is a function ");
            }
#endif                      			/* TRACE */

	    lower_case (buffer, buf_ptr1, TOKEN_LEN);
	    fn_loc = str_lookup (buffer, buf_ptr1, TOKEN_LEN, BST_FN_ILK,
				    DONT_INSERT);
	    if ( ! hash_found)
	    BEGIN
	      SKIP_TOKEN_UNKNOWN_FUNCTION;
	    END
	    else if (fn_loc == wiz_loc)
	    BEGIN
	      SKIP_RECURSIVE_TOKEN;
	    END
	    else
	    BEGIN

#ifdef TRACE
              if (Flag_trace) {
	        TRACE_PR ("of type ");
	        trace_pr_fn_class (fn_loc);
	        TRACE_PR_NEWLINE;
              }
#endif                      			/* TRACE */

	      INSERT_FN_LOC (fn_loc);
	    END
	  END
/*^^^^^^^^^^^^^^^^^^^^^^^^^^ END OF SECTION 199 ^^^^^^^^^^^^^^^^^^^^^^^^^^^*/

        break;
    END
/*^^^^^^^^^^^^^^^^^^^^^^^^^^ END OF SECTION 189 ^^^^^^^^^^^^^^^^^^^^^^^^^^^*/

Next_Token_Label:
    EAT_BST_WHITE_AND_EOF_CHECK ("function");
  END

/***************************************************************************
 * WEB section number:	200
 * ~~~~~~~~~~~~~~~~~~~
 * Now we add the |end_of_def| special marker, make sure this function will
 * fit into |wiz_functions|, and put it there.
 ***************************************************************************/
  BEGIN
      INSERT_FN_LOC (END_OF_DEF);
      if ((single_ptr + wiz_def_ptr) > Wiz_Fn_Space)
      BEGIN
	PRINT2 ("%ld: ", (long) (single_ptr + wiz_def_ptr));
	BIBTEX_OVERFLOW ("wizard-defined function space ", Wiz_Fn_Space);
      END
      FN_INFO[fn_hash_loc] = wiz_def_ptr;
      copy_ptr = 0;
      while (copy_ptr < single_ptr)
      BEGIN
	wiz_functions[wiz_def_ptr] = singl_function[copy_ptr];
	INCR (copy_ptr);
	INCR (wiz_def_ptr);
      END
    END
/*^^^^^^^^^^^^^^^^^^^^^^^^^^ END OF SECTION 200 ^^^^^^^^^^^^^^^^^^^^^^^^^^^*/

  INCR (buf_ptr2);
Exit_Label: DO_NOTHING;
END
/*^^^^^^^^^^^^^^^^^^^^^^^^^^ END OF SECTION 187 ^^^^^^^^^^^^^^^^^^^^^^^^^^^*/




/***************************************************************************
 * WEB section number:	 90
 * ~~~~~~~~~~~~~~~~~~~
 * This procedure scans for an identifier, stopping at the first
 * |illegal_id_char|, or stopping at the first character if it's
 * |numeric|.  It sets the global variable |scan_result| to |id_null| if
 * the identifier is null, else to |white_adjacent| if it ended at a
 * |white_space| character or an end-of-line, else to
 * |specified_char_adjacent| if it ended at one of |char1| or |char2| or
 * |char3|, else to |other_char_adjacent| if it ended at a nonspecified,
 * non|white_space| |illegal_id_char|.  By convention, when some calling
 * code really wants just one or two ``specified'' characters, it merely
 * repeats one of the characters.
 ***************************************************************************/
void          scan_identifier (ASCIICode_T char1, ASCIICode_T char2,
			       ASCIICode_T char3)
BEGIN
  buf_ptr1 = buf_ptr2;
  if (lex_class[SCAN_CHAR] != NUMERIC)
  BEGIN
    while ((id_class[SCAN_CHAR] == LEGAL_ID_CHAR) && (buf_ptr2 < last))
    BEGIN
      INCR (buf_ptr2);
    END
  END
  if (TOKEN_LEN == 0)
  BEGIN
    scan_result = ID_NULL;
  END
  else if ((lex_class[SCAN_CHAR] == WHITE_SPACE) || (buf_ptr2 == last))
  BEGIN
    scan_result = SPECIFIED_CHAR_ADJACENT;
  END
  else if ((SCAN_CHAR == char1) || (SCAN_CHAR == char2)
	    || (SCAN_CHAR == char3))
  BEGIN
    scan_result = SPECIFIED_CHAR_ADJACENT;
  END
  else
  BEGIN
    scan_result = OTHER_CHAR_ADJACENT;
  END
END
/*^^^^^^^^^^^^^^^^^^^^^^^^^^ END OF SECTION 90 ^^^^^^^^^^^^^^^^^^^^^^^^^^^*/




/***************************************************************************
 * WEB section number:	 93
 * ~~~~~~~~~~~~~~~~~~~
 * This procedure scans for an integer, stopping at the first nondigit;
 * it sets the value of |token_value| accordingly.  It returns |true| if
 * the token was a legal integer (i.e., consisted of an optional
 * |minus_sign| followed by one or more digits).
 ***************************************************************************/
Boolean_T         scan_integer (void)
BEGIN
  Integer8_T		sign_length;
  Boolean_T		scan_integer;

  buf_ptr1 = buf_ptr2;
  if (SCAN_CHAR == MINUS_SIGN)
  BEGIN
    sign_length = 1;
    INCR (buf_ptr2);
  END
  else
  BEGIN
    sign_length = 0;
  END
  token_value = 0;
  while ((lex_class[SCAN_CHAR] == NUMERIC) && (buf_ptr2 < last))
  BEGIN
    token_value = (token_value * 10) + CHAR_VALUE;
    INCR (buf_ptr2);
  END
  if (NEGATIVE)
  BEGIN
    token_value = -token_value;
  END
  if (TOKEN_LEN == sign_length)
  BEGIN
    scan_integer = FALSE;
  END
  else
  BEGIN
    scan_integer = TRUE;
  END
  return(scan_integer);
END
/*^^^^^^^^^^^^^^^^^^^^^^^^^^ END OF SECTION  93 ^^^^^^^^^^^^^^^^^^^^^^^^^^^*/




/***************************************************************************
 * WEB section number:	 92
 * ~~~~~~~~~~~~~~~~~~~
 * This function scans for a nonnegative integer, stopping at the first
 * nondigit; it sets the value of |token_value| accordingly.  It returns
 * |true| if the token was a legal nonnegative integer (i.e., consisted
 * of one or more digits).
 ***************************************************************************/
Boolean_T         scan_nonneg_integer (void)
BEGIN
  Boolean_T	  scan_nonneg_integer;

  buf_ptr1 = buf_ptr2;
  token_value = 0;
  while ((lex_class[SCAN_CHAR] == NUMERIC) && (buf_ptr2 < last))
  BEGIN
    token_value = (token_value * 10) + CHAR_VALUE;
    INCR (buf_ptr2);
  END
  if (TOKEN_LEN == 0)
  BEGIN
    scan_nonneg_integer = FALSE;
  END
  else
  BEGIN
    scan_nonneg_integer = TRUE;
  END
  return (scan_nonneg_integer);
END
/*^^^^^^^^^^^^^^^^^^^^^^^^^^ END OF SECTION  92 ^^^^^^^^^^^^^^^^^^^^^^^^^^^*/




/***************************************************************************
 * WEB section number:	 94
 * ~~~~~~~~~~~~~~~~~~~
 * This function scans over |white_space| characters, stopping either at
 * the first nonwhite character or the end of the line, respectively
 * returning |true| or |false|.
 ***************************************************************************/
Boolean_T         scan_white_space (void)
BEGIN
  Boolean_T	  scan_white_space;

  while ((lex_class[SCAN_CHAR] == WHITE_SPACE) && (buf_ptr2 < last))
  BEGIN
    INCR (buf_ptr2);
  END
  if (buf_ptr2 < last)
  BEGIN
    scan_white_space = TRUE;
  END
  else
  BEGIN
    scan_white_space = FALSE;
  END
  return (scan_white_space);
END
/*^^^^^^^^^^^^^^^^^^^^^^^^^^ END OF SECTION  94 ^^^^^^^^^^^^^^^^^^^^^^^^^^^*/




/***************************************************************************
 * WEB section number:	 188
 * ~~~~~~~~~~~~~~~~~~~
 * This macro inserts a hash-table location (or one of the two
 * special markers |quote_next_fn| and |end_of_def|) into the
 * |singl_function| array, which will later be copied into the
 * |wiz_functions| array.
 ***************************************************************************/
void          singl_fn_overflow (void)
BEGIN
  BIBTEX_OVERFLOW ("single function space ", SINGLE_FN_SPACE);
END
/*^^^^^^^^^^^^^^^^^^^^^^^^^^ END OF SECTION 188 ^^^^^^^^^^^^^^^^^^^^^^^^^^^*/




/***************************************************************************
 * WEB section number:	 186
 * ~~~~~~~~~~~~~~~~~~~
 * And another.
 ***************************************************************************/
void          skip_illegal_stuff_after_token (void)
BEGIN
  PRINT2 ("\"%c\" can't follow a literal", xchr[SCAN_CHAR]);
  skip_token_print ();
END
/*^^^^^^^^^^^^^^^^^^^^^^^^^^ END OF SECTION 186 ^^^^^^^^^^^^^^^^^^^^^^^^^^^*/



/***************************************************************************
 * WEB section number:	 404
 * ~~~~~~~~~~~~~~~~~~~
 * When we come here |sp_ptr| is just past the |left_brace|, and when we
 * leave it's either at |sp_end| or just past the matching |right_brace|.
 ***************************************************************************/
void          skip_stuff_at_sp_brace_level_gr (void)
BEGIN
  while ((sp_brace_level > 1) && (sp_ptr < sp_end))
  BEGIN
    if (str_pool[sp_ptr] == RIGHT_BRACE)
    BEGIN
      DECR (sp_brace_level);
    END
    else if (str_pool[sp_ptr] == LEFT_BRACE)
    BEGIN
      INCR (sp_brace_level);
    END
    INCR (sp_ptr);
  END
END
/*^^^^^^^^^^^^^^^^^^^^^^^^^^ END OF SECTION 404 ^^^^^^^^^^^^^^^^^^^^^^^^^^^*/




/***************************************************************************
 * WEB section number:	 183
 * ~~~~~~~~~~~~~~~~~~~
 * We're about to start scanning tokens in a function definition.  When a
 * function token is illegal, we skip until it ends; a |white_space|
 * character, an end-of-line, a |right_brace|, or a |comment| marks the
 * end of the current token.
 ***************************************************************************/
void          skip_token_print (void)
BEGIN
  PRINT ("-");
  bst_ln_num_print ();
  mark_error ();
  if (scan2_white (RIGHT_BRACE, COMMENT))
  BEGIN
    DO_NOTHING;
  END
END
/*^^^^^^^^^^^^^^^^^^^^^^^^^^ END OF SECTION 183 ^^^^^^^^^^^^^^^^^^^^^^^^^^^*/




/***************************************************************************
 * WEB section number:	 185
 * ~~~~~~~~~~~~~~~~~~~
 * Here's another macro for saving some space when there's a problem with
 * a token.
 ***************************************************************************/
void          skp_token_unknown_function_prin (void)
BEGIN
  PRINT_TOKEN;
  PRINT (" is an unknown function");
  skip_token_print ();
END
/*^^^^^^^^^^^^^^^^^^^^^^^^^^ END OF SECTION 185 ^^^^^^^^^^^^^^^^^^^^^^^^^^^*/




/***************************************************************************
 * WEB section number:	 58
 * ~~~~~~~~~~~~~~~~~~~
 * This procedure copies file name |file_name| into the beginning of
 * |name_of_file|, if it will fit.  It also sets the global variable
 * |name_length| to the appropriate value.
 *
 * NOTE: because C arrays start at index 0, not 1, the subscripts of array
 *	 |name_of_file| are generally 1 less than those in the WEB source.
 ***************************************************************************/
void          start_name (StrNumber_T file_name)
BEGIN
  PoolPointer_T       p_ptr;

  if (LENGTH (file_name) > FILE_NAME_SIZE)
  BEGIN
    PRINT ("File=");
    PRINT_POOL_STR (file_name);
    PRINT_LN (",");
    file_nm_size_overflow ();
  END
  name_ptr = 0;
  p_ptr = str_start[file_name];
  while (p_ptr < str_start[file_name + 1])
  BEGIN
    name_of_file[name_ptr] = CHR (str_pool[p_ptr]);
    INCR (name_ptr);
    INCR (p_ptr);
  END
  name_length = LENGTH (file_name);
END
/*^^^^^^^^^^^^^^^^^^^^^^^^^^ END OF SECTION  58 ^^^^^^^^^^^^^^^^^^^^^^^^^^^*/




/***************************************************************************
 * WEB section number:	 56
 * ~~~~~~~~~~~~~~~~~~~
 * This subroutine compares string |s| with another string that appears
 * in the buffer |buf| between positions |bf_ptr| and |bf_ptr+len-1|; the
 * result is |true| if and only if the strings are equal.
 ***************************************************************************/
Boolean_T         str_eq_buf (StrNumber_T s, BufType_T buf,
			      BufPointer_T bf_ptr, BufPointer_T len)
BEGIN
  BufPointer_T		i;
  PoolPointer_T		j;
  Boolean_T		str_eq_buf;

  if (LENGTH (s) != len)
  BEGIN
    str_eq_buf = FALSE;
    goto Exit_Label;
  END
  i = bf_ptr;
  j = str_start[s];
  while (j < str_start[s + 1])
  BEGIN
    if (str_pool[j] != buf[i])
    BEGIN
      str_eq_buf = FALSE;
      goto Exit_Label;
    END
    INCR (i);
    INCR (j);
  END
  str_eq_buf = TRUE;
Exit_Label:
  return (str_eq_buf);
END
/*^^^^^^^^^^^^^^^^^^^^^^^^^^ END OF SECTION  56 ^^^^^^^^^^^^^^^^^^^^^^^^^^^*/




/***************************************************************************
 * WEB section number:	 57
 * ~~~~~~~~~~~~~~~~~~~
 * This subroutine compares two |str_pool| strings and returns true
 * |true| if and only if the strings are equal.
 ***************************************************************************/
Boolean_T         str_eq_str (StrNumber_T s1, StrNumber_T s2)
BEGIN
  Boolean_T	  str_eq_str;

  if (LENGTH (s1) != LENGTH (s2))
  BEGIN
    str_eq_str = FALSE;
    goto Exit_Label;
  END
  p_ptr1 = str_start[s1];
  p_ptr2 = str_start[s2];
  while (p_ptr1 < str_start[s1 + 1])
  BEGIN
    if (str_pool[p_ptr1] != str_pool[p_ptr2])
    BEGIN
      str_eq_str = FALSE;
      goto Exit_Label;
    END
    INCR (p_ptr1);
    INCR (p_ptr2);
  END
  str_eq_str = TRUE;
Exit_Label:
  return (str_eq_str);
END
/*^^^^^^^^^^^^^^^^^^^^^^^^^^ END OF SECTION  57 ^^^^^^^^^^^^^^^^^^^^^^^^^^^*/




/***************************************************************************
 * WEB section number:	 68
 * ~~~~~~~~~~~~~~~~~~~
 * Here is the subroutine that searches the hash table for a
 * (string,~|str_ilk|) pair, where the string is of length |l>=0| and
 * appears in |buffer[j..(j+l-1)]|.  If it finds the pair, it returns the
 * corresponding hash-table location and sets the global variable
 * |hash_found| to |true|.  Otherwise it sets |hash_found| to |false|,
 * and if the parameter |insert_it| is |true|, it inserts the pair into
 * the hash table, inserts the string into |str_pool| if not previously
 * encountered, and returns its location.  Note that two different pairs
 * can have the same string but different |str_ilk|s, in which case the
 * second pair encountered, if |insert_it| were |true|, would be inserted
 * into the hash table though its string wouldn't be inserted into
 * |str_pool| because it would already be there.
 ***************************************************************************/
HashLoc_T         str_lookup (BufType_T buf, BufPointer_T j, BufPointer_T l,
			      StrIlk_T ilk, Boolean_T insert_it)
BEGIN
  HashLoc_T		str_lookup;
  long                  h;
  HashLoc_T		p;
  BufPointer_T		k;
  Boolean_T		old_string;
  StrNumber_T		str_num;

/***************************************************************************
 * WEB section number:	69
 * ~~~~~~~~~~~~~~~~~~~
 * The value of |Hash_Prime| should be roughly 85\% of |Hash_Size|, and
 * it should be a prime number
 * (it should also be less than $2^14 + 2^6 = 16320$ because of
 * WEB's simple-macro bound).  The theory of hashing tells us to expect
 * fewer than two table probes, on the average, when the search is
 * successful.
 *
 * NOTE: the limit imposed on the value of Hash_Prime no longer applies
 *       because we are using C #defines.
 ***************************************************************************/
  BEGIN
    h = 0;
    k = j;
    while (k < (j + l))
    BEGIN
      h = h + h + buf[k];
      while (h >= Hash_Prime)
	h = h - Hash_Prime;
      INCR (k);
    END
  END
/*^^^^^^^^^^^^^^^^^^^^^^^^^^ END OF SECTION  69 ^^^^^^^^^^^^^^^^^^^^^^^^^^^*/

  p = h + HASH_BASE;
  hash_found = FALSE;
  old_string = FALSE;
  LOOP
  BEGIN

/***************************************************************************
 * WEB section number:	70
 * ~~~~~~~~~~~~~~~~~~~
 * Here we handle the case in which we've already encountered this
 * string; note that even if we have, we'll still have to insert the pair
 * into the hash table if |str_ilk| doesn't match.
 ***************************************************************************/
    BEGIN
      if (hash_text[p] > 0)
      BEGIN
	if (str_eq_buf (hash_text[p], buf, j, l))
	BEGIN
	  if (hash_ilk[p] == ilk)
	  BEGIN
	    hash_found = TRUE;
	    goto Str_Found_Label;
	  END
	  else
	  BEGIN
	    old_string = TRUE;
	    str_num = hash_text[p];
	  END
	END
      END
    END
/*^^^^^^^^^^^^^^^^^^^^^^^^^^ END OF SECTION  70 ^^^^^^^^^^^^^^^^^^^^^^^^^^^*/

    if (hash_next[p] == EMPTY)
    BEGIN
      if ( ! insert_it)
      BEGIN
        goto Str_Not_Found_Label;
      END

/***************************************************************************
 * WEB section number:	71
 * ~~~~~~~~~~~~~~~~~~~
 * This code inserts the pair in the appropriate unused location.
 ***************************************************************************/
      BEGIN
	if (hash_text[p] > 0)
	BEGIN
	  REPEAT
	  BEGIN
	    if (HASH_IS_FULL)
	    BEGIN
	      BIBTEX_OVERFLOW ("hash size ", Hash_Size);
	    END
	    DECR (hash_used);
	  END UNTIL (hash_text[hash_used] == 0);
	  hash_next[p] = hash_used;
	  p = hash_used;
	END
	if (old_string)
	BEGIN
	  hash_text[p] = str_num;
	END
	else
	BEGIN
	  STR_ROOM (l);
	  k = j;
	  while (k < (j + l))
	  BEGIN
	    APPEND_CHAR (buf[k]);
	    INCR (k);
	  END
	  hash_text[p] = make_string ();
	END
	hash_ilk[p] = ilk;
      END
/*^^^^^^^^^^^^^^^^^^^^^^^^^^ END OF SECTION  71 ^^^^^^^^^^^^^^^^^^^^^^^^^^^*/

      goto Str_Found_Label;
    END
    p = hash_next[p];
  END
Str_Not_Found_Label: DO_NOTHING;
Str_Found_Label: str_lookup = p;
  return (str_lookup);
END
/*^^^^^^^^^^^^^^^^^^^^^^^^^^ END OF SECTION  68 ^^^^^^^^^^^^^^^^^^^^^^^^^^^*/



/***************************************************************************
 * WEB section number:	 300
 * ~~~~~~~~~~~~~~~~~~~
 * The |swap| procedure exchanges the two elements its arguments point
 * to.
 ***************************************************************************/
void          swap (CiteNumber_T swap1, CiteNumber_T swap2)
BEGIN
  CiteNumber_T      innocent_bystander;

  innocent_bystander = SORTED_CITES[swap2];
  SORTED_CITES[swap2] = SORTED_CITES[swap1];
  SORTED_CITES[swap1] = innocent_bystander;
END
/*^^^^^^^^^^^^^^^^^^^^^^^^^^ END OF SECTION 300 ^^^^^^^^^^^^^^^^^^^^^^^^^^^*/



/***************************************************************************
 * WEB section number:	 456
 * ~~~~~~~~~~~~~~~~~~~
 * Here we print |trace| and/or |stat| information, if desired.
 ***************************************************************************/
void          trace_and_stat_printing (void)
BEGIN

#ifdef TRACE

  if (Flag_trace) {
  
/***************************************************************************
 * WEB section number:	457
 * ~~~~~~~~~~~~~~~~~~~
 * This prints information obtained from the .aux file about the
 * other files.
 ***************************************************************************/
    BEGIN
      if (num_bib_files == 1)
      BEGIN
        TRACE_PR_LN ("The 1 database file is");
      END
      else
      BEGIN
        TRACE_PR_LN2 ("The %ld database files are", (long) num_bib_files);
      END
      if (num_bib_files == 0)
      BEGIN
        TRACE_PR_LN ("   undefined");
      END
      else
      BEGIN
        bib_ptr = 0;
        while (bib_ptr < num_bib_files)
        BEGIN
    	  TRACE_PR ("   ");
  	  TRACE_PR_POOL_STR (CUR_BIB_STR);
  	  TRACE_PR_POOL_STR (s_bib_extension);
  	  TRACE_PR_NEWLINE;
	  INCR (bib_ptr);
        END
      END
      TRACE_PR ("The style file is ");
      if (bst_str == 0)
      BEGIN
        TRACE_PR_LN ("undefined");
      END
      else
      BEGIN
        TRACE_PR_POOL_STR (bst_str);
        TRACE_PR_POOL_STR (s_bst_extension);
        TRACE_PR_NEWLINE;
      END
    END
/*^^^^^^^^^^^^^^^^^^^^^^^^^^ END OF SECTION 457 ^^^^^^^^^^^^^^^^^^^^^^^^^^^*/

/***************************************************************************
 * WEB section number:	458
 * ~~~~~~~~~~~~~~~~~~~
 * In entry-sorted order, this prints an entry's |cite_list| string and,
 * indirectly, its entry type and entry variables.
 ***************************************************************************/
    BEGIN
      if (all_entries)
      BEGIN
        TRACE_PR2 ("all_marker=%ld, ", (long) all_marker);
      END
      if (read_performed)
      BEGIN
        TRACE_PR_LN2 ("old_num_cites=%ld", (long) old_num_cites);
      END
      else
      BEGIN
        TRACE_PR_NEWLINE;
      END
      TRACE_PR2 ("The %ld", (long) num_cites);
      if (num_cites == 1)
      BEGIN
        TRACE_PR_LN (" entry:");
      END
      else
      BEGIN
        TRACE_PR_LN (" entries:");
      END
      if (num_cites == 0)
      BEGIN
        TRACE_PR_LN ("   undefined");
      END
      else
      BEGIN
        sort_cite_ptr = 0;
        while (sort_cite_ptr < num_cites)
        BEGIN
  	  if ( ! read_completed)
	  BEGIN
	    cite_ptr = sort_cite_ptr;
	  END
  	  else
  	  BEGIN
	    cite_ptr = SORTED_CITES[sort_cite_ptr];
	  END
	  TRACE_PR_POOL_STR (CUR_CITE_STR);
	  if (read_performed)

/***************************************************************************
 * WEB section number:	458
 * ~~~~~~~~~~~~~~~~~~~
 * This prints information gathered while reading the .bst and
 * .bib files.
 ***************************************************************************/
  	  BEGIN
	    TRACE_PR (", entry-type ");
	    if (type_list[cite_ptr] == UNDEFINED)
	    BEGIN
	      TRACE_PR ("unknown");
	    END
	    else if (type_list[cite_ptr] == EMPTY)
	    BEGIN
	      TRACE_PR ("--- no type found");
	    END
	    else
	    BEGIN
	      TRACE_PR_POOL_STR (hash_text[type_list[cite_ptr]]);
	    END
	    TRACE_PR_LN (", has entry strings");

/***************************************************************************
 * WEB section number:	460
 * ~~~~~~~~~~~~~~~~~~~
 * This prints, for the current entry, the strings declared by the
 * entry command.
 ***************************************************************************/
	    BEGIN
	      if (num_ent_strs == 0)
	      BEGIN
	        TRACE_PR_LN ("    undefined");
	      END
	      else if ( ! read_completed)
	      BEGIN
	        TRACE_PR_LN ("    uninitialized");
	      END
	      else
	      BEGIN
	        str_ent_ptr = cite_ptr * num_ent_strs;
	        while (str_ent_ptr < ((cite_ptr + 1) * num_ent_strs))
	        BEGIN
	  	  ent_chr_ptr = 0;
		  TRACE_PR ("    \"");

		  while (ENTRY_STRS(str_ent_ptr, ent_chr_ptr) != END_OF_STRING)
		  BEGIN
		    TRACE_PR2 ("%c",
                               xchr[ENTRY_STRS(str_ent_ptr, ent_chr_ptr)]);
		    INCR (ent_chr_ptr);
		  END
		  TRACE_PR_LN ("\"");
		  INCR (str_ent_ptr);
	        END
	      END
	    END
/*^^^^^^^^^^^^^^^^^^^^^^^^^^ END OF SECTION 460 ^^^^^^^^^^^^^^^^^^^^^^^^^^^*/

	    TRACE_PR ("  has entry integers");

/***************************************************************************
 * WEB section number:	461
 * ~~~~~~~~~~~~~~~~~~~
 * This prints, for the current entry, the integers declared by the
 * entry command.
 ***************************************************************************/
  	    BEGIN
	      if (num_ent_ints == 0)
	      BEGIN
	        TRACE_PR (" undefined");
	      END
	      else if ( ! read_completed)
	      BEGIN
	        TRACE_PR (" uninitialized");
	      END
	      else
	      BEGIN
	        int_ent_ptr = cite_ptr * num_ent_ints;
	        while (int_ent_ptr < ((cite_ptr + 1) * num_ent_ints))
	        BEGIN
		  TRACE_PR2 (" %ld", (long) entry_ints[int_ent_ptr]);
		  INCR (int_ent_ptr);
	        END
	      END
	      TRACE_PR_NEWLINE;
	    END
/*^^^^^^^^^^^^^^^^^^^^^^^^^^ END OF SECTION 461 ^^^^^^^^^^^^^^^^^^^^^^^^^^^*/

	    TRACE_PR_LN ("  and has fields");

/***************************************************************************
 * WEB section number:	462
 * ~~~~~~~~~~~~~~~~~~~
 * This prints the fields stored for the current entry.
 ***************************************************************************/
	    BEGIN
	      if ( ! read_performed)
	      BEGIN
	        TRACE_PR_LN ("    uninitialized");
	      END
	      else
	      BEGIN
	        field_ptr = cite_ptr * num_fields;
	        field_end_ptr = field_ptr + num_fields;
	        no_fields = TRUE;
	        while (field_ptr < field_end_ptr)
	        BEGIN
		  if (field_info[field_ptr] != MISSING)
		  BEGIN
		    TRACE_PR ("    \"");
		    TRACE_PR_POOL_STR (field_info[field_ptr]);
		    TRACE_PR_LN ("\"");
		    no_fields = FALSE;
		  END
		  INCR (field_ptr);
	        END
	        if (no_fields)
	        BEGIN
		  TRACE_PR_LN ("    missing");
	        END
	      END
	    END
/*^^^^^^^^^^^^^^^^^^^^^^^^^^ END OF SECTION 462 ^^^^^^^^^^^^^^^^^^^^^^^^^^^*/

  	  END
/*^^^^^^^^^^^^^^^^^^^^^^^^^^ END OF SECTION 459 ^^^^^^^^^^^^^^^^^^^^^^^^^^^*/

	  else
	  BEGIN
	    TRACE_PR_NEWLINE;
	  END
	  INCR (sort_cite_ptr);
        END
      END
    END
/*^^^^^^^^^^^^^^^^^^^^^^^^^^ END OF SECTION 458 ^^^^^^^^^^^^^^^^^^^^^^^^^^^*/

/***************************************************************************
 * WEB section number:	463
 * ~~~~~~~~~~~~~~~~~~~
 * This gives all the |wiz_defined| functions that appeared in the
 * .bst file.
 ***************************************************************************/
    BEGIN
      TRACE_PR_LN ("The wiz-defined functions are");
      if (wiz_def_ptr == 0)
      BEGIN
        TRACE_PR_LN ("   nonexistent");
      END
      else
      BEGIN
        wiz_fn_ptr = 0;

        while (wiz_fn_ptr < wiz_def_ptr)
        BEGIN
	  if (wiz_functions[wiz_fn_ptr] == END_OF_DEF)
	  BEGIN
	    TRACE_PR_LN2 ("%ld--end-of-def--", (long) wiz_fn_ptr);
	  END
	  else if (wiz_functions[wiz_fn_ptr] == QUOTE_NEXT_FN)
	  BEGIN
	    TRACE_PR2 ("%ld  quote_next_function    ", (long) wiz_fn_ptr);
	  END
	  else
	  BEGIN
	    TRACE_PR2 ("%ld  `", (long) wiz_fn_ptr);
	    TRACE_PR_POOL_STR (hash_text[wiz_functions[wiz_fn_ptr]]);
	    TRACE_PR_LN ("'");
	  END
	  INCR (wiz_fn_ptr);
        END
      END
    END
/*^^^^^^^^^^^^^^^^^^^^^^^^^^ END OF SECTION 463 ^^^^^^^^^^^^^^^^^^^^^^^^^^^*/

/***************************************************************************
 * WEB section number:	464
 * ~~~~~~~~~~~~~~~~~~~
 * This includes all the `static' strings (that is, those that are also
 * in the hash table), but none of the dynamic strings (that is, those
 * put on the stack while executing .bst commands).
 ***************************************************************************/
    BEGIN
      TRACE_PR_LN ("The string pool is");
      str_num = 1;

      while (str_num < str_ptr)
      BEGIN
        TRACE_PR3 ("%4ld%6ld \"", (long) str_num, (long) str_start[str_num]);
        TRACE_PR_POOL_STR (str_num);
        TRACE_PR_LN ("\"");
        INCR (str_num);
      END
    END
  }                             /* end if (Flag_trace) */

/*^^^^^^^^^^^^^^^^^^^^^^^^^^ END OF SECTION 464 ^^^^^^^^^^^^^^^^^^^^^^^^^^^*/

#endif                      			/* TRACE */


#ifdef STAT

/***************************************************************************
 * WEB section number:	465
 * ~~~~~~~~~~~~~~~~~~~
 * These statistics can help determine how large some of the constants
 * should be and can tell how useful certain |built_in| functions are.
 * They are written to the same files as tracing information.
 ***************************************************************************/
  if (Flag_stats) {
    BEGIN
      STAT_PR2 ("You've used %ld", (long) num_cites);
      if (num_cites == 1)
      BEGIN
        STAT_PR_LN (" entry,");
      END
      else
      BEGIN
        STAT_PR_LN (" entries,");
      END
      STAT_PR_LN2 ("            %ld wiz_defined-function locations,",
  		  (long) wiz_def_ptr);
      STAT_PR_LN3 ("            %ld strings with %ld characters,",
  		  (long) str_ptr, (long) str_start[str_ptr]);
      blt_in_ptr = 0;
      total_ex_count = 0;
      while (blt_in_ptr < NUM_BLT_IN_FNS)
      BEGIN
        total_ex_count = total_ex_count + execution_count[blt_in_ptr];
        INCR (blt_in_ptr);
      END
      STAT_PR_LN2 ("and the built_in function-call counts, %ld in all, are:",
  		  (long) total_ex_count);
      blt_in_ptr = 0;
      while (blt_in_ptr < NUM_BLT_IN_FNS)
      BEGIN
        STAT_PR_POOL_STR (hash_text[blt_in_loc[blt_in_ptr]]);
        STAT_PR_LN2 (" -- %ld", (long) execution_count[blt_in_ptr]);
        INCR (blt_in_ptr);
      END
    END
  }                             /* end if (Flag_stats) */

/*^^^^^^^^^^^^^^^^^^^^^^^^^^ END OF SECTION 465 ^^^^^^^^^^^^^^^^^^^^^^^^^^^*/

#endif                      			/* STAT */
END
/*^^^^^^^^^^^^^^^^^^^^^^^^^^ END OF SECTION 456 ^^^^^^^^^^^^^^^^^^^^^^^^^^^*/




/***************************************************************************
 * WEB section number:	 159
 * ~~~~~~~~~~~~~~~~~~~
 * This version is for printing when in |trace| mode.
 ***************************************************************************/
#ifdef TRACE
void          trace_pr_fn_class (HashLoc_T fn_loc)
BEGIN

  if (!Flag_trace)
    return;

  switch (fn_type[fn_loc])
  BEGIN
    case BUILT_IN:
      TRACE_PR ("built-in");
      break;
    case WIZ_DEFINED:
      TRACE_PR ("wizard-defined");
      break;
    case INT_LITERAL:
      TRACE_PR ("integer-literal");
      break;
    case STR_LITERAL:
      TRACE_PR ("string-literal");
      break;
    case FIELD:
      TRACE_PR ("field");
      break;
    case INT_ENTRY_VAR:
      TRACE_PR ("integer-entry-variable");
      break;
    case STR_ENTRY_VAR:
      TRACE_PR ("string-entry-variable");
      break;
    case INT_GLOBAL_VAR:
      TRACE_PR ("integer-global-variable");
      break;
    case STR_GLOBAL_VAR:
      TRACE_PR ("string-global-variable");
      break;
    default:
      unknwn_function_class_confusion ();
      break;
  END
END
#endif                      			/* TRACE */
/*^^^^^^^^^^^^^^^^^^^^^^^^^^ END OF SECTION 159 ^^^^^^^^^^^^^^^^^^^^^^^^^^^*/





/***************************************************************************
 * WEB section number:	 157
 * ~~~~~~~~~~~~~~~~~~~
 * Here's another bug report.
 ***************************************************************************/
void          unknwn_function_class_confusion (void)
BEGIN
  CONFUSION ("Unknown function class");
END
/*^^^^^^^^^^^^^^^^^^^^^^^^^^ END OF SECTION 157 ^^^^^^^^^^^^^^^^^^^^^^^^^^^*/




/***************************************************************************
 * WEB section number:	 310
 * ~~~~~~~~~~~~~~~~~~~
 * More bug complaints, this time about bad literals.
 ***************************************************************************/
void          unknwn_literal_confusion (void)
BEGIN
  CONFUSION ("Unknown literal type");
END
/*^^^^^^^^^^^^^^^^^^^^^^^^^^ END OF SECTION 310 ^^^^^^^^^^^^^^^^^^^^^^^^^^^*/




/***************************************************************************
 * WEB section number:	 63
 * ~~~~~~~~~~~~~~~~~~~
 * This system-independent procedure is the same as the previous except
 * that it converts lower- to upper-case letters.
 ***************************************************************************/
void          upper_case (BufType_T buf, BufPointer_T bf_ptr,
			  BufPointer_T len)
BEGIN
  BufPointer_T      i;

  if (len > 0)
  BEGIN
    for (i = bf_ptr; i <= (bf_ptr+len-1); i++)
    BEGIN

#ifdef SUPPORT_8BIT
      if (IsLower (buf[i]))
      BEGIN
	buf[i] = ToUpper(buf[i]);
      END
#else                           /* NOT SUPPORT_8BIT */
      if ((buf[i] >= 'a') && (buf[i] <= 'z'))
      BEGIN
        buf[i] = buf[i] - CASE_DIFFERENCE;
      END
#endif                          /* SUPPORT_8BIT */

    END
  END
END
/*^^^^^^^^^^^^^^^^^^^^^^^^^^ END OF SECTION  63 ^^^^^^^^^^^^^^^^^^^^^^^^^^^*/




/***************************************************************************
 * WEB section number:	 401
 * ~~~~~~~~~~~~~~~~~~~
 * The last name starts just past the last token, before the first
 * |comma| (if there is no |comma|, there is deemed to be one at the end
 * of the string), for which there exists a first brace-level-0 letter
 * (or brace-level-1 special character), and it's in lower case, unless
 * this last token is also the last token before the |comma|, in which
 * case the last name starts with this token (unless this last token is
 * connected by a |sep_char| other than a |tie| to the previous token, in
 * which case the last name starts with as many tokens earlier as are
 * connected by non|tie|s to this last one (except on Tuesdays
 * $\ldots\,$), although this module never sees such a case).  Note that
 * if there are any tokens in either the von or last names, then the last
 * name has at least one, even if it starts with a lower-case letter.
 ***************************************************************************/
void          von_name_ends_and_last_name_sta (void)
BEGIN
  von_end = last_end - 1;
  while (von_end > von_start)
  BEGIN
    name_bf_ptr = name_tok[von_end - 1];
    name_bf_xptr = name_tok[von_end];
    if (von_token_found ())
    BEGIN
      goto Exit_Label;
    END
    DECR (von_end);
  END
Exit_Label: DO_NOTHING;
END
/*^^^^^^^^^^^^^^^^^^^^^^^^^^ END OF SECTION 401 ^^^^^^^^^^^^^^^^^^^^^^^^^^^*/




/***************************************************************************
 * WEB section number:	 397
 * ~~~~~~~~~~~~~~~~~~~
 * It's a von token if there exists a first brace-level-0 letter (or
 * brace-level-1 special character), and it's in lower case; in this case
 * we return |true|.  The token is in |name_buf|, starting at
 * |name_bf_ptr| and ending just before |name_bf_xptr|.
 ***************************************************************************/
Boolean_T         von_token_found (void)
BEGIN
  Boolean_T    von_token_found;

  nm_brace_level = 0;
  von_token_found = FALSE;
  while (name_bf_ptr < name_bf_xptr)
  BEGIN

#ifdef SUPPORT_8BIT
    if IsUpper(NAME_BUF[name_bf_ptr])
    BEGIN
      goto Exit_Label;
    END
    else if IsLower(NAME_BUF[name_bf_ptr])
    BEGIN
      RETURN_VON_FOUND;
    END
#else                           /* NOT SUPPORT_8BIT */
    if ((NAME_BUF[name_bf_ptr] >= 'A') && (NAME_BUF[name_bf_ptr] <= 'Z'))
    BEGIN
      goto Exit_Label;
    END
    else if ((NAME_BUF[name_bf_ptr] >= 'a') && (NAME_BUF[name_bf_ptr] <= 'z'))
    BEGIN
      RETURN_VON_FOUND;
    END
#endif                          /* SUPPORT_8BIT */

    else if (NAME_BUF[name_bf_ptr] == LEFT_BRACE)
    BEGIN
      INCR (nm_brace_level);
      INCR (name_bf_ptr);
      if (((name_bf_ptr + 2) < name_bf_xptr)
	    && (NAME_BUF[name_bf_ptr] == BACKSLASH))

/***************************************************************************
 * WEB section number:	398
 * ~~~~~~~~~~~~~~~~~~~
 * When we come here |name_bf_ptr| is just past the |left_brace|,
 * but we always leave by |return|ing.
 ***************************************************************************/
      BEGIN
        INCR (name_bf_ptr);
        name_bf_yptr = name_bf_ptr;
        while ((name_bf_ptr < name_bf_xptr)
		&& (lex_class[NAME_BUF[name_bf_ptr]] == ALPHA))
        BEGIN
          INCR (name_bf_ptr);
        END
        control_seq_loc = str_lookup (NAME_BUF, name_bf_yptr,
					name_bf_ptr - name_bf_yptr,
					CONTROL_SEQ_ILK, DONT_INSERT);
        if (hash_found)

/***************************************************************************
 * WEB section number:	399
 * ~~~~~~~~~~~~~~~~~~~
 * The accented or foreign character is either `\i' or `\j' or
 * one of the eleven alphabetic foreign characters in Table~3.2 of the
 * \LaTeX\ manual.
 ***************************************************************************/
        BEGIN
          switch (ilk_info[control_seq_loc])
          BEGIN
            case N_OE_UPPER:
            case N_AE_UPPER:
            case N_AA_UPPER:
            case N_O_UPPER:
            case N_L_UPPER:
              goto Exit_Label;
            case N_I:
            case N_J:
            case N_OE:
            case N_AE:
            case N_AA:
            case N_O:
            case N_L:
            case N_SS:
	      RETURN_VON_FOUND;
            default:
              CONFUSION ("Control-sequence hash error");
          END
        END
/*^^^^^^^^^^^^^^^^^^^^^^^^^^ END OF SECTION 399 ^^^^^^^^^^^^^^^^^^^^^^^^^^^*/

        while ((name_bf_ptr < name_bf_xptr) && (nm_brace_level > 0))
        BEGIN

#ifdef SUPPORT_8BIT
	  if IsUpper(NAME_BUF[name_bf_ptr])
	  BEGIN
	    goto Exit_Label;
	  END
	  else if IsLower(NAME_BUF[name_bf_ptr])
	  BEGIN
	    RETURN_VON_FOUND;
	  END
#else                           /* NOT SUPPORT_8BIT */
	  if ((NAME_BUF[name_bf_ptr] >= 'A') && (NAME_BUF[name_bf_ptr] <= 'Z'))
	  BEGIN
	    goto Exit_Label;
	  END
	  else if ((NAME_BUF[name_bf_ptr] >= 'a') 
                    && (NAME_BUF[name_bf_ptr] <= 'z'))
	  BEGIN
	    RETURN_VON_FOUND;
	  END
#endif                          /* SUPPORT_8BIT */

	  else if (NAME_BUF[name_bf_ptr] == RIGHT_BRACE)
	  BEGIN
	    DECR (nm_brace_level);
	  END
	  else if (NAME_BUF[name_bf_ptr] == LEFT_BRACE)
	  BEGIN
	    INCR (nm_brace_level);
	  END
	  INCR (name_bf_ptr);
	END
	goto Exit_Label;
      END
/*^^^^^^^^^^^^^^^^^^^^^^^^^^ END OF SECTION 398 ^^^^^^^^^^^^^^^^^^^^^^^^^^^*/

      else

/***************************************************************************
 * WEB section number:	400
 * ~~~~~~~~~~~~~~~~~~~
 * When we come here |name_bf_ptr| is just past the |left_brace|; when we
 * leave it's either at |name_bf_xptr| or just past the matching
 * |right_brace|.
 ***************************************************************************/
      BEGIN
        while ((nm_brace_level > 0) && (name_bf_ptr < name_bf_xptr))
        BEGIN
          if (NAME_BUF[name_bf_ptr] == RIGHT_BRACE)
          BEGIN
            DECR (nm_brace_level);
          END
          else if (NAME_BUF[name_bf_ptr] == LEFT_BRACE)
          BEGIN
            INCR (nm_brace_level);
          END
          INCR (name_bf_ptr);
        END
      END
/*^^^^^^^^^^^^^^^^^^^^^^^^^^ END OF SECTION 400 ^^^^^^^^^^^^^^^^^^^^^^^^^^^*/

    END
    else
    BEGIN
      INCR (name_bf_ptr);
    END
  END
Exit_Label: DO_NOTHING;
  return (von_token_found);
END
/*^^^^^^^^^^^^^^^^^^^^^^^^^^ END OF SECTION 397 ^^^^^^^^^^^^^^^^^^^^^^^^^^^*/




/***************************************************************************
 * WEB section number:	 360
 * ~~~~~~~~~~~~~~~~~~~
 * The |built_in| function add.period$ pops the top (string)
 * literal, adds a |period| to a nonnull string if its last
 * non|right_brace| character isn't a |period|, |question_mark|, or
 * |exclamation_mark|, and pushes this resulting string back onto the
 * stack.  If the literal isn't a string, it complains and pushes the
 * null string.
 ***************************************************************************/
void          x_add_period (void)
BEGIN
  pop_lit_stk (&pop_lit1, &pop_typ1);
  if (pop_typ1 != STK_STR)
  BEGIN
    print_wrong_stk_lit (pop_lit1, pop_typ1, STK_STR);
    push_lit_stk (s_null, STK_STR);
  END
  else if (LENGTH (pop_lit1) == 0)
  BEGIN
    push_lit_stk (s_null, STK_STR);
  END
  else

/***************************************************************************
 * WEB section number:	361
 * ~~~~~~~~~~~~~~~~~~~
 * Here we scan backwards from the end of the string, skipping
 * non|right_brace| characters, to see if we have to add the |period|.
 ***************************************************************************/
  BEGIN
    sp_ptr = str_start[pop_lit1 + 1];
    sp_end = str_start[pop_lit1];
    while (sp_ptr > sp_end)
    BEGIN
      DECR (sp_ptr);
      if (str_pool[sp_ptr] != RIGHT_BRACE)
      BEGIN
        goto Loop_Exit_Label;
      END
    END
Loop_Exit_Label:
    switch (str_pool[sp_ptr])
    BEGIN
      case PERIOD:
      case QUESTION_MARK:
      case EXCLAMATION_MARK:
	REPUSH_STRING;
        break;
      default:

/***************************************************************************
 * WEB section number:	362
 * ~~~~~~~~~~~~~~~~~~~
 * Ok guys, we really have to do it.
 ***************************************************************************/
	BEGIN
	  if (pop_lit1 < cmd_str_ptr)
	  BEGIN
	    STR_ROOM (LENGTH (pop_lit1) + 1);
	    sp_ptr = str_start[pop_lit1];
	    sp_end = str_start[pop_lit1 + 1];
	    while (sp_ptr < sp_end)
	    BEGIN
	      APPEND_CHAR (str_pool[sp_ptr]);
	      INCR (sp_ptr);
	    END
	  END
	  else
	  BEGIN
	    pool_ptr = str_start[pop_lit1 + 1];
	    STR_ROOM (1);
	  END
	  APPEND_CHAR (PERIOD);
	  push_lit_stk (make_string (), STK_STR);
	  break;
      END
    END
/*^^^^^^^^^^^^^^^^^^^^^^^^^^ END OF SECTION 362 ^^^^^^^^^^^^^^^^^^^^^^^^^^^*/

  END
/*^^^^^^^^^^^^^^^^^^^^^^^^^^ END OF SECTION 361 ^^^^^^^^^^^^^^^^^^^^^^^^^^^*/

END
/*^^^^^^^^^^^^^^^^^^^^^^^^^^ END OF SECTION 360 ^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
