;;;; This is a -*- Common-Lisp -*- program, automatically translated
;;;; from the BibTeX style file `/usr/share/texmf/bibtex/bst/ams/amsalpha.bst'
;;;; by the CL-BibTeX compiler (version 0.1).

(defpackage "BIBTEX-STYLE-AMSALPHA"
            (:use "COMMON-LISP" "BIBTEX-RUNTIME" "BIBTEX-COMPILER"))

(in-package "BIBTEX-STYLE-AMSALPHA")

;;;; ====================================================================
;;;;  @BibTeX-style-file{
;;;;     filename        = "amsalpha.bst",
;;;;     version         = "2.0",
;;;;     date            = "2000/03/27",
;;;;     time            = "13:49:36 EST",
;;;;     checksum        = "00166 1404 4124 29978",
;;;;     author          = "American Mathematical Society",
;;;;     address         = "American Mathematical Society,
;;;;                        Technical Support,
;;;;                        Electronic Products and Services,
;;;;                        P. O. Box 6248,
;;;;                        Providence, RI 02940,
;;;;                        USA",
;;;;     telephone       = "401-455-4080 or (in the USA and Canada)
;;;;                        800-321-4AMS (321-4267)",
;;;;     FAX             = "401-331-3842",
;;;;     email           = "tech-support@ams.org (Internet)",
;;;;     copyright       = "Copyright 1995 American Mathematical Society,
;;;;                        all rights reserved.  Copying of this file is
;;;;                        authorized only if either:
;;;;                        (1) you make absolutely no changes to your copy,
;;;;                        including name; OR
;;;;                        (2) if you do make changes, you first rename it
;;;;                        to some other name.",
;;;;     codetable       = "ISO/ASCII",
;;;;     keywords        = "bibtex, bibliography, amslatex, ams-latex",
;;;;     supported       = "yes",
;;;;     abstract        = "BibTeX bibliography style `amsalpha' for BibTeX
;;;;                        versions 0.99a or later and LaTeX version 2e.
;;;;                        Produces alphabetic-label bibliography items in
;;;;                        a form typical for American Mathematical Society
;;;;                        publications.",
;;;;     docstring       = "The checksum field above contains a CRC-16
;;;;                        checksum as the first value, followed by the
;;;;                        equivalent of the standard UNIX wc (word
;;;;                        count) utility output of lines, words, and
;;;;                        characters.  This is produced by Robert
;;;;                        Solovay's checksum utility.",
;;;;  }
;;;; ====================================================================
;; See the file btxbst.doc for extra documentation other than
;; what is included here.  And see btxhak.tex for a description
;; of the BibTeX language and how to use it.
;; This defines the types of fields that can occur in a database entry
;; for this particular bibliography style.  Except for `language',
;; this is the standard list from alpha.bst.
;;; Types of entries currently allowed in a BibTeX file:
;;;
;;; ARTICLE -- An article from a journal or magazine.
;;;
;;; BOOK -- A book with an explicit publisher.
;;;
;;; BOOKLET -- A work that is printed and bound,
;;; but without a named publisher or sponsoring institution.
;;;
;;; CONFERENCE -- The same as INPROCEEDINGS,
;;; included for Scribe compatibility.
;;;
;;; INBOOK -- A part of a book,
;;; which may be a chapter (or section or whatever) and/or a range of pages.
;;;
;;; INCOLLECTION -- A part of a book having its own title.
;;;
;;; INPROCEEDINGS -- An article in a conference proceedings.
;;;
;;; MANUAL -- Technical documentation.
;;;
;;; MASTERSTHESIS -- A Master's thesis.
;;;
;;; MISC -- Use this type when nothing else fits.
;;;
;;; PHDTHESIS -- A PhD thesis.
;;;
;;; PROCEEDINGS -- The proceedings of a conference.
;;;
;;; TECHREPORT -- A report published by a school or other institution,
;;; usually numbered within a series.
;;;
;;; UNPUBLISHED -- A document having an author and title, but not formally
;;; published.

;; Removed after.sentence, after.block---not needed.

(defvar *output-state* 0)

(defvar *before-all* 0)

(defvar *mid-sentence* 0)

;; () --> () 
;; with assignment to "MID.SENTENCE" "BEFORE.ALL"
(defun init-state-consts () (setq *before-all* 0) (setq *mid-sentence* 1))

;; Scratch variables:

;; Utility functions

;; (T) --> (T) with side-effects 
(defun shows (arg1)
  (format *error-output* "~A~%" (concatenate 'string "::::  `" arg1 "'"))
  arg1)

;; () --> () with side-effects 
(defun showstack ()
  (format *error-output*
          "~A~%"
          "STACK=====================================================================")
  (format *error-output*
          "~A~%"
          "ENDSTACK==================================================================")
  (values))

;; (T) --> (T) 
(defun field-or-null (arg1) (if (empty-field-p arg1) "" arg1))

;; (T) --> ((STRING)) 
(defun emphasize (arg1)
  (if (empty-field-p arg1) "" (concatenate 'string "\\emph{" arg1 "}")))

;; n.dashify is used to make sure page ranges get the TeX code
;; (two hyphens) for en-dashes.

;; ((STRING)) --> ((STRING)) 
;; with reference to "GLOBAL.MAX$"
(defun n-dashify (temp86)
  (do ((arg8 ""))
      ((empty-field-p temp86) arg8)
    (setq arg8
            (cond
             ((string/= "-" (bibtex-substring temp86 1 1))
              (let ((t9
                     (concatenate 'string arg8 (bibtex-substring temp86 1 1))))
                (setq temp86 (bibtex-substring temp86 2))
                t9))
             ((string/= "--" (bibtex-substring temp86 1 2))
              (setq temp86 (bibtex-substring temp86 2))
              (concatenate 'string arg8 "--"))
             (t
              (do ((arg13 arg8))
                  ((string/= "-" (bibtex-substring temp86 1 1)) arg13)
                (setq temp86 (bibtex-substring temp86 2))
                (setq arg13 (concatenate 'string arg13 "-"))))))))

;; tie.or.space.connect connects two items with a ~ if the
;; second item is less than 3 letters long, otherwise it just puts an
;; ordinary space.

;; ((STRING) T) --> ((STRING)) 
(defun tie-or-space-connect (arg2 arg1)
  (concatenate 'string arg2 (if (< (length arg1) 3) "~" " ") arg1))

;; (T) --> ((STRING)) 
(defun add-space-if-necessary (arg1)
  (if (string= "" arg1) arg1 (concatenate 'string arg1 " ")))

;; either.or.check gives a warning if two mutually exclusive fields
;; were used in the database.

;; (T (STRING BIBTEX-COMPILER::MISSING)) --> () with side-effects 
(defun either-or-check (arg4 arg1)
  (unless (empty-field-p arg1)
    (bib-warn* "can't use both "
               arg4
               " fields in "
               (gethash "KEY" *bib-entry* ""))))

;; output.nonnull is called by output.

;; ((STRING) (STRING)) --> ((STRING)) with side-effects 
;; with possible assignment to "OUTPUT.STATE"
;; with reference to "OUTPUT.STATE" "BEFORE.ALL" "MID.SENTENCE"
(defun output-nonnull (arg5 s)
  (cond
   ((= *mid-sentence* *output-state*)
    (princ (concatenate 'string arg5 ", ") *bbl-output*))
   (t
    (if (= *before-all* *output-state*)
        (princ arg5 *bbl-output*)
        (princ (concatenate 'string (add-period-unless-sentence-end arg5) " ")
               *bbl-output*))
    (setq *output-state* *mid-sentence*)))
  s)

;; Output checks to see if the stack top is empty; if not, it
;; calls output.nonnull to write it out.

;; ((STRING) T) --> ((STRING)) with side-effects 
;; with possible assignment to "OUTPUT.STATE"
;; with reference to "MID.SENTENCE" "BEFORE.ALL" "OUTPUT.STATE"
(defun output (arg5 arg1)
  (if (empty-field-p arg1) arg5 (output-nonnull arg5 arg1)))

;; Standard warning message for a missing or empty field. For the user
;; we call any such field `missing' without respect to the distinction
;; made by BibTeX between missing and empty.

;; (T) --> () with side-effects 
(defun missing-warning (arg1)
  (bib-warn* "missing " arg1 " in " (gethash "KEY" *bib-entry* "")))

;; Output.check is like output except that it gives a warning on-screen
;; if the given field in the database entry is empty.  t is the field
;; name.

;; ((STRING) T (STRING)) --> ((STRING)) with side-effects 
;; with possible assignment to "OUTPUT.STATE"
;; with reference to "MID.SENTENCE" "BEFORE.ALL" "OUTPUT.STATE"
(defun output-check (arg5 arg1 temp87)
  (cond ((empty-field-p arg1) (missing-warning temp87) arg5)
        (t (output-nonnull arg5 arg1))))

;; () --> ((STRING)) with side-effects 
;; with assignment to "OUTPUT.STATE"
;; with reference to "BEFORE.ALL" "LABEL"
(defun output-bibitem ()
  (terpri *bbl-output*)
  (princ "\\bibitem[" *bbl-output*)
  (princ (gethash "LABEL" *bib-entry* "") *bbl-output*)
  (princ "]{" *bbl-output*)
  (princ (gethash "KEY" *bib-entry* "") *bbl-output*)
  (princ "}" *bbl-output*)
  (terpri *bbl-output*)
  (setq *output-state* *before-all*)
  "")

;; (T) --> () with side-effects 
(defun output-nonempty-mrnumber (arg1)
  (let ((t3 (if (null arg1) "" arg1)))
    (unless (empty-field-p t3)
      (princ (concatenate 'string " \\MR{" t3 "}") *bbl-output*))))

;; ((STRING)) --> () with side-effects 
;; with reference to "MRNUMBER"
(defun fin-entry (arg1)
  (princ (add-period-unless-sentence-end arg1) *bbl-output*)
  (output-nonempty-mrnumber (gethash "MRNUMBER" *bib-entry* nil))
  (terpri *bbl-output*))

;; Removed new.block, new.block.checka, new.block.checkb, new.sentence,
;; new.sentence.checka, and new.sentence.checkb functions here, since they
;; don't seem to be needed in the AMS style.  Also moved some real
;; basic functions like `and' and 'or' earlier in the file.

;; The extra section to write out a language field was added
;; for AMSPLAIN.BST.  Not present in plain.bst.

;; () --> ((STRING)) 
;; with reference to "LANGUAGE"
(defun format-language ()
  (if (empty-field-p (gethash "LANGUAGE" *bib-entry* nil))
      ""
      (concatenate 'string " (" (gethash "LANGUAGE" *bib-entry* nil) ")")))

;; This version of format.names puts names in the format
;;
;; First von Last, Jr.
;;
;; (i.e., first name first, no abbreviating to initials).

;; ((STRING)) --> ((STRING)) 
(defun format-names (s)
  (do* ((nameptr 1)
        (numnames (num-bibtex-names s))
        (namesleft numnames)
        arg10)
       ((<= namesleft 0) arg10)
    (let* ((temp88
            (format-nth-bibtex-name nil "{ff~}{vv~}{ll}{, jj}" s nameptr))
           (t19
            (cond ((<= nameptr 1) temp88)
                  ((> namesleft 1) (concatenate 'string arg10 ", " temp88))
                  ((string= "others" temp88)
                   (concatenate 'string
                                (if (> numnames 2)
                                    (concatenate 'string arg10 ",")
                                    arg10)
                                " et~al."))
                  (t
                   (concatenate 'string
                                (if (> numnames 2)
                                    (concatenate 'string arg10 ",")
                                    arg10)
                                " and "
                                temp88)))))
      (setq nameptr (+ nameptr 1))
      (setq namesleft (- namesleft 1))
      (setq arg10 t19))))

;; () --> ((STRING)) 
;; with reference to "BYSAME" "AUTHOR"
(defun format-authors ()
  (cond ((empty-field-p (gethash "AUTHOR" *bib-entry* nil)) "")
        ((string= "\\bysame" (gethash "BYSAME" *bib-entry* ""))
         (gethash "BYSAME" *bib-entry* ""))
        (t (format-names (gethash "AUTHOR" *bib-entry* nil)))))

;; () --> ((STRING)) 
;; with reference to "EDITOR"
(defun format-editors ()
  (cond ((empty-field-p (gethash "EDITOR" *bib-entry* nil)) "")
        ((> (num-bibtex-names (gethash "EDITOR" *bib-entry* nil)) 1)
         (concatenate 'string
                      (format-names (gethash "EDITOR" *bib-entry* nil))
                      " (eds.)"))
        (t
         (concatenate 'string
                      (format-names (gethash "EDITOR" *bib-entry* nil))
                      " (ed.)"))))

;; () --> ((STRING)) 
;; with reference to "EDITOR"
(defun format-nonauthor-editors ()
  (cond ((empty-field-p (gethash "EDITOR" *bib-entry* nil)) "")
        ((> (num-bibtex-names (gethash "EDITOR" *bib-entry* nil)) 1)
         (concatenate 'string
                      (format-names (gethash "EDITOR" *bib-entry* nil))
                      ", eds."))
        (t
         (concatenate 'string
                      (format-names (gethash "EDITOR" *bib-entry* nil))
                      ", ed."))))

;; () --> ((STRING)) 
;; with reference to "TITLE"
(defun format-title ()
  (if (empty-field-p (gethash "TITLE" *bib-entry* nil))
      ""
      (emphasize
       (bibtex-string-titledowncase (gethash "TITLE" *bib-entry* nil)))))

;; () --> ((STRING)) with side-effects 
;; with reference to "YEAR" "JOURNAL" "VOLUME"
(defun format-journal-vol-year ()
  (cond
   ((empty-field-p (gethash "JOURNAL" *bib-entry* nil))
    (missing-warning "journal name") "")
   ((empty-field-p (gethash "YEAR" *bib-entry* nil)) (missing-warning "year")
    (if (empty-field-p (gethash "VOLUME" *bib-entry* nil))
        (gethash "JOURNAL" *bib-entry* nil)
        (concatenate 'string
                     (gethash "JOURNAL" *bib-entry* nil)
                     " \\textbf{"
                     (gethash "VOLUME" *bib-entry* nil)
                     "}")))
   (t
    (concatenate 'string
                 (if (empty-field-p (gethash "VOLUME" *bib-entry* nil))
                     (gethash "JOURNAL" *bib-entry* nil)
                     (concatenate 'string
                                  (gethash "JOURNAL" *bib-entry* nil)
                                  " \\textbf{"
                                  (gethash "VOLUME" *bib-entry* nil)
                                  "}"))
                 " ("
                 (gethash "YEAR" *bib-entry* nil)
                 ")"))))

;; For formatting the issue number for a journal article.

;; () --> ((STRING)) 
;; with reference to "NUMBER"
(defun format-number ()
  (if (empty-field-p (gethash "NUMBER" *bib-entry* nil))
      ""
      (concatenate 'string "no.~" (gethash "NUMBER" *bib-entry* nil))))

;; For formatting miscellaneous dates

;; () --> ((BIBTEX-COMPILER::MISSING STRING)) with side-effects 
;; with reference to "MONTH" "YEAR"
(defun format-date ()
  (cond
   ((empty-field-p (gethash "YEAR" *bib-entry* nil))
    (cond ((empty-field-p (gethash "MONTH" *bib-entry* nil)) "")
          (t
           (bib-warn* "there's a month but no year in "
                      (gethash "KEY" *bib-entry* ""))
           (gethash "MONTH" *bib-entry* nil))))
   ((empty-field-p (gethash "MONTH" *bib-entry* nil))
    (gethash "YEAR" *bib-entry* nil))
   (t
    (concatenate 'string
                 (gethash "MONTH" *bib-entry* nil)
                 " "
                 (gethash "YEAR" *bib-entry* nil)))))

;;;      The volume, series and number information is sort of tricky.
;;;      This code handles it as follows:
;;;      If the series is present, and the volume, but not the number,
;;;        then we do "\emph{Book title}, Series Name, vol. 000"
;;;      If the series is present, and the number, but not the volume,
;;;        then we do "\emph{Book title}, Series Name, no. 000"
;;;      If the series is present, and both number and volume,
;;;        then we do "\emph{Book title}, vol. XX, Series Name, no. 000"
;;;      Finally, if the series is absent,
;;;        then we do "\emph{Book title}, vol. XX"
;;;        or         "\emph{Book title}, no. 000"
;;;        and if both volume and number are present, give a warning message.

;; () --> ((BIBTEX-COMPILER::MISSING STRING)) with side-effects 
;; with reference to "VOLUME" "SERIES" "NUMBER"
(defun format-bookvolume-series-number ()
  (cond
   ((empty-field-p (gethash "VOLUME" *bib-entry* nil))
    (cond
     ((not (empty-field-p (gethash "NUMBER" *bib-entry* nil)))
      (let ((t21
             (if (empty-field-p (gethash "SERIES" *bib-entry* nil))
                 ""
                 (gethash "SERIES" *bib-entry* nil))))
        (concatenate 'string
                     (if (empty-field-p t21)
                         t21
                         (concatenate 'string t21 ", "))
                     (tie-or-space-connect "no."
                      (gethash "NUMBER" *bib-entry* nil)))))
     ((empty-field-p (gethash "SERIES" *bib-entry* nil)) "")
     (t (gethash "SERIES" *bib-entry* nil))))
   ((empty-field-p (gethash "NUMBER" *bib-entry* nil))
    (if (empty-field-p (gethash "SERIES" *bib-entry* nil))
        (tie-or-space-connect "vol." (gethash "VOLUME" *bib-entry* nil))
        (concatenate 'string
                     (gethash "SERIES" *bib-entry* nil)
                     ", "
                     (tie-or-space-connect "vol."
                      (gethash "VOLUME" *bib-entry* nil)))))
   ((empty-field-p (gethash "SERIES" *bib-entry* nil))
    (bib-warn* "can't use both volume and number if series info is missing")
    (format *error-output*
            "~A~%"
            (concatenate 'string
                         "in BibTeX entry type `"
                         (gethash "ENTRY-TYPE" *bib-entry* "")
                         "'"))
    (tie-or-space-connect "vol." (gethash "VOLUME" *bib-entry* nil)))
   (t
    (tie-or-space-connect
     (concatenate 'string
                  (tie-or-space-connect "vol."
                   (gethash "VOLUME" *bib-entry* nil))
                  ", "
                  (gethash "SERIES" *bib-entry* nil)
                  ", no.")
     (gethash "NUMBER" *bib-entry* nil)))))

;; end of format.bookvolume.series.number
;;; format.inproc.title.where.editors is used by inproceedings entry types
;;;      No case changing or emphasizing for the title.  We want initial
;;;      caps, roman.
;;;      We add parentheses around the address (place where conference
;;;      was held).
;;;      Likewise we add parentheses around the editors' names.

;; () --> ((BIBTEX-COMPILER::MISSING STRING)) 
;; with reference to "EDITOR" "BOOKTITLE" "ADDRESS"
(defun format-inproc-title-address-editors ()
  (cond ((empty-field-p (gethash "BOOKTITLE" *bib-entry* nil)) "")
        ((not (empty-field-p (gethash "EDITOR" *bib-entry* nil)))
         (concatenate 'string
                      (add-space-if-necessary
                       (if (empty-field-p (gethash "ADDRESS" *bib-entry* nil))
                           (gethash "BOOKTITLE" *bib-entry* nil)
                           (concatenate 'string
                                        (add-space-if-necessary
                                         (gethash "BOOKTITLE" *bib-entry* nil))
                                        "("
                                        (gethash "ADDRESS" *bib-entry* nil)
                                        ")")))
                      "("
                      (format-nonauthor-editors)
                      ")"))
        ((empty-field-p (gethash "ADDRESS" *bib-entry* nil))
         (gethash "BOOKTITLE" *bib-entry* nil))
        (t
         (concatenate 'string
                      (add-space-if-necessary
                       (gethash "BOOKTITLE" *bib-entry* nil))
                      "("
                      (gethash "ADDRESS" *bib-entry* nil)
                      ")"))))

;;; format.incoll.title.editors is similar to format.inproc... but
;;; omits the address. For collections that are not proceedings volumes.

;; () --> ((BIBTEX-COMPILER::MISSING STRING)) 
;; with reference to "EDITOR" "BOOKTITLE"
(defun format-incoll-title-editors ()
  (cond ((empty-field-p (gethash "BOOKTITLE" *bib-entry* nil)) "")
        ((empty-field-p (gethash "EDITOR" *bib-entry* nil))
         (gethash "BOOKTITLE" *bib-entry* nil))
        (t
         (concatenate 'string
                      (add-space-if-necessary
                       (gethash "BOOKTITLE" *bib-entry* nil))
                      "("
                      (format-nonauthor-editors)
                      ")"))))

;; () --> ((STRING)) 
;; with reference to "MID.SENTENCE" "OUTPUT.STATE" "EDITION"
(defun format-edition ()
  (cond ((empty-field-p (gethash "EDITION" *bib-entry* nil)) "")
        ((= *mid-sentence* *output-state*)
         (concatenate 'string
                      (bibtex-string-downcase
                       (gethash "EDITION" *bib-entry* nil))
                      " ed."))
        (t
         (concatenate 'string
                      (bibtex-string-titledowncase
                       (gethash "EDITION" *bib-entry* nil))
                      " ed."))))

;; ((STRING)) --> ((INTEGER)) 
;; with reference to "GLOBAL.MAX$"
(defun multi-page-check (temp89)
  (let ((multiresult 0))
    (do ()
        ((or (> multiresult 0) (empty-field-p temp89)))
      (let ((t1 (bibtex-substring temp89 1 1)))
        (if (or (string= "-" t1) (string= "," t1) (string= "+" t1))
            (setq multiresult 1)
            (setq temp89 (bibtex-substring temp89 2)))))
    multiresult))

;; () --> ((STRING)) 
;; with reference to "GLOBAL.MAX$" "PAGES"
(defun format-pages ()
  (if (empty-field-p (gethash "PAGES" *bib-entry* nil))
      ""
      (n-dashify (gethash "PAGES" *bib-entry* nil))))

;; () --> ((STRING)) 
;; with reference to "GLOBAL.MAX$" "PAGES"
(defun format-book-pages ()
  (cond ((empty-field-p (gethash "PAGES" *bib-entry* nil)) "")
        ((> (multi-page-check (gethash "PAGES" *bib-entry* nil)) 0)
         (concatenate 'string
                      "pp.~"
                      (n-dashify (gethash "PAGES" *bib-entry* nil))))
        (t (concatenate 'string "p.~" (gethash "PAGES" *bib-entry* nil)))))

;; () --> ((STRING)) 
;; with reference to "TYPE" "CHAPTER" "GLOBAL.MAX$" "PAGES"
(defun format-chapter-pages ()
  (cond
   ((empty-field-p (gethash "CHAPTER" *bib-entry* nil)) (format-book-pages))
   ((empty-field-p (gethash "PAGES" *bib-entry* nil))
    (concatenate 'string
                 (if (empty-field-p (gethash "TYPE" *bib-entry* nil))
                     "ch.~"
                     (concatenate 'string
                                  (bibtex-string-downcase
                                   (gethash "TYPE" *bib-entry* nil))
                                  " "))
                 (gethash "CHAPTER" *bib-entry* nil)))
   (t
    (concatenate 'string
                 (if (empty-field-p (gethash "TYPE" *bib-entry* nil))
                     "ch.~"
                     (concatenate 'string
                                  (bibtex-string-downcase
                                   (gethash "TYPE" *bib-entry* nil))
                                  " "))
                 (gethash "CHAPTER" *bib-entry* nil)
                 ", "
                 (format-book-pages)))))

;; () --> () with side-effects 
;; with reference to "NOTE" "YEAR" "MONTH" "HOWPUBLISHED" "TITLE" "AUTHOR" "KEY"
(defun empty-misc-check ()
  (when
      (and (empty-field-p (gethash "AUTHOR" *bib-entry* nil))
           (empty-field-p (gethash "TITLE" *bib-entry* nil))
           (empty-field-p (gethash "HOWPUBLISHED" *bib-entry* nil))
           (empty-field-p (gethash "MONTH" *bib-entry* nil))
           (empty-field-p (gethash "YEAR" *bib-entry* nil))
           (empty-field-p (gethash "NOTE" *bib-entry* nil))
           (not (empty-field-p (gethash "KEY" *bib-entry* nil))))
    (bib-warn* "all relevant fields are empty in "
               (gethash "KEY" *bib-entry* ""))))

;; (T) --> (T) 
;; with reference to "TYPE"
(defun format-thesis-type (arg2)
  (if (empty-field-p (gethash "TYPE" *bib-entry* nil))
      arg2
      (bibtex-string-titledowncase (gethash "TYPE" *bib-entry* nil))))

;; () --> ((STRING)) 
;; with reference to "TYPE" "NUMBER"
(defun format-tr-number ()
  (if (empty-field-p (gethash "NUMBER" *bib-entry* nil))
      (bibtex-string-titledowncase
       (if (empty-field-p (gethash "TYPE" *bib-entry* nil))
           "Tech. Report"
           (gethash "TYPE" *bib-entry* nil)))
      (tie-or-space-connect
       (if (empty-field-p (gethash "TYPE" *bib-entry* nil))
           "Tech. Report"
           (gethash "TYPE" *bib-entry* nil))
       (gethash "NUMBER" *bib-entry* nil))))

;; The format.crossref functions haven't been paid much attention
;; at the present time (June 1990) and could probably use some
;; work.  MJD

;; () --> ((STRING)) with side-effects 
;; with reference to "KEY" "CROSSREF" "JOURNAL"
(defun format-article-crossref ()
  (let ((t1
         (cond
          ((not (empty-field-p (gethash "KEY" *bib-entry* nil)))
           (concatenate 'string "in " (gethash "KEY" *bib-entry* nil)))
          ((empty-field-p (gethash "JOURNAL" *bib-entry* nil))
           (bib-warn* "need key or journal for "
                      (gethash "KEY" *bib-entry* "")
                      " to crossref "
                      (gethash "CROSSREF" *bib-entry* nil))
           "")
          (t (concatenate 'string "in " (gethash "JOURNAL" *bib-entry* nil))))))
    (concatenate 'string
                 t1
                 " \\cite{"
                 (gethash "CROSSREF" *bib-entry* nil)
                 "}")))

;; () --> ((STRING)) 
;; with reference to "EDITOR"
(defun format-crossref-editor ()
  (let ((t1 (num-bibtex-names (gethash "EDITOR" *bib-entry* nil))))
    (cond
     ((> t1 2)
      (concatenate 'string
                   (format-nth-bibtex-name nil
                                           "{vv~}{ll}"
                                           (gethash "EDITOR" *bib-entry* nil)
                                           1)
                   " et~al."))
     ((< t1 2)
      (format-nth-bibtex-name nil
                              "{vv~}{ll}"
                              (gethash "EDITOR" *bib-entry* nil)
                              1))
     ((string= "others"
               (format-nth-bibtex-name nil
                                       "{ff }{vv }{ll}{ jj}"
                                       (gethash "EDITOR" *bib-entry* nil)
                                       2))
      (concatenate 'string
                   (format-nth-bibtex-name nil
                                           "{vv~}{ll}"
                                           (gethash "EDITOR" *bib-entry* nil)
                                           1)
                   " et~al."))
     (t
      (concatenate 'string
                   (format-nth-bibtex-name nil
                                           "{vv~}{ll}"
                                           (gethash "EDITOR" *bib-entry* nil)
                                           1)
                   " and "
                   (format-nth-bibtex-name nil
                                           "{vv~}{ll}"
                                           (gethash "EDITOR" *bib-entry* nil)
                                           2))))))

;; () --> ((STRING)) with side-effects 
;; with reference to "VOLUME" "CROSSREF" "EDITOR" "AUTHOR" "SERIES" "KEY"
(defun format-book-crossref ()
  (let* ((t1
          (cond
           ((empty-field-p (gethash "VOLUME" *bib-entry* nil))
            (bib-warn* "empty volume in "
                       (gethash "KEY" *bib-entry* "")
                       "'s crossref of "
                       (gethash "CROSSREF" *bib-entry* nil))
            "in ")
           (t
            (concatenate 'string
                         (tie-or-space-connect "vol."
                          (gethash "VOLUME" *bib-entry* nil))
                         " of "))))
         (t16
          (cond
           ((not
             (or (empty-field-p (gethash "EDITOR" *bib-entry* nil))
                 (equal (field-or-null (gethash "AUTHOR" *bib-entry* nil))
                        (field-or-null (gethash "EDITOR" *bib-entry* nil)))))
            (concatenate 'string t1 (format-crossref-editor)))
           ((not (empty-field-p (gethash "KEY" *bib-entry* nil)))
            (concatenate 'string t1 (gethash "KEY" *bib-entry* nil)))
           ((empty-field-p (gethash "SERIES" *bib-entry* nil))
            (bib-warn* "need editor, key, or series for "
                       (gethash "KEY" *bib-entry* "")
                       " to crossref "
                       (gethash "CROSSREF" *bib-entry* nil))
            (concatenate 'string t1 ""))
           (t (concatenate 'string t1 (gethash "SERIES" *bib-entry* nil))))))
    (concatenate 'string
                 t16
                 " \\cite{"
                 (gethash "CROSSREF" *bib-entry* nil)
                 "}")))

;; () --> ((STRING)) with side-effects 
;; with reference to "EDITOR" "AUTHOR" "BOOKTITLE" "CROSSREF" "KEY"
(defun format-incoll-inproc-crossref ()
  (let ((t1
         (cond
          ((not
            (or (empty-field-p (gethash "EDITOR" *bib-entry* nil))
                (equal (field-or-null (gethash "AUTHOR" *bib-entry* nil))
                       (field-or-null (gethash "EDITOR" *bib-entry* nil)))))
           (concatenate 'string "in " (format-crossref-editor)))
          ((not (empty-field-p (gethash "KEY" *bib-entry* nil)))
           (concatenate 'string "in " (gethash "KEY" *bib-entry* nil)))
          ((empty-field-p (gethash "BOOKTITLE" *bib-entry* nil))
           (bib-warn* "need editor, key, or booktitle for "
                      (gethash "KEY" *bib-entry* "")
                      " to crossref "
                      (gethash "CROSSREF" *bib-entry* nil))
           "")
          (t
           (concatenate 'string
                        "in \\emph{"
                        (gethash "BOOKTITLE" *bib-entry* nil)
                        "}")))))
    (concatenate 'string
                 t1
                 " \\cite{"
                 (gethash "CROSSREF" *bib-entry* nil)
                 "}")))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; The main functions for each entry type.
;; journal, vol and year are formatted together because they are
;; not separated by commas.

;; () --> () with side-effects 
;; with assignment to "OUTPUT.STATE"
;; with reference to "LABEL" "BEFORE.ALL" "MID.SENTENCE" "OUTPUT.STATE" "BYSAME" "AUTHOR" "TITLE" "GLOBAL.MAX$" "PAGES" "KEY" "CROSSREF" "JOURNAL" "VOLUME" "YEAR" "NUMBER" "MRNUMBER" "LANGUAGE" "NOTE"
(defun article ()
  (let* ((t1 (output-bibitem))
         (t2 (output-check t1 (format-authors) "author"))
         (t3 (output-check t2 (format-title) "title"))
         (t14
          (if (null (gethash "CROSSREF" *bib-entry* nil))
              (let* ((t11 (format-journal-vol-year))
                     (t12 (output-check t3 t11 "journal, volume, and year"))
                     (t13 (output t12 (format-number))))
                (output-check t13 (format-pages) "pages"))
              (let ((t10 (output-nonnull t3 (format-article-crossref))))
                (output-check t10 (format-pages) "pages")))))
    (fin-entry
     (output (concatenate 'string t14 (format-language))
      (gethash "NOTE" *bib-entry* nil)))))

;; () --> () with side-effects 
;; with assignment to "OUTPUT.STATE"
;; with reference to "LABEL" "BEFORE.ALL" "CROSSREF" "EDITOR" "OUTPUT.STATE" "MID.SENTENCE" "BYSAME" "AUTHOR" "TITLE" "EDITION" "KEY" "SERIES" "VOLUME" "NUMBER" "PUBLISHER" "ADDRESS" "YEAR" "MONTH" "MRNUMBER" "LANGUAGE" "NOTE"
(defun book ()
  (let* ((t1 (output-bibitem))
         (t6
          (if (empty-field-p (gethash "AUTHOR" *bib-entry* nil))
              (output-check t1 (format-editors) "author and editor")
              (let ((t5 (output-nonnull t1 (format-authors))))
                (when (null (gethash "CROSSREF" *bib-entry* nil))
                  (either-or-check "author and editor"
                   (gethash "EDITOR" *bib-entry* nil)))
                t5)))
         (t7 (output-check t6 (format-title) "title"))
         (t8 (output t7 (format-edition)))
         (t15
          (if (null (gethash "CROSSREF" *bib-entry* nil))
              (let* ((t13 (output t8 (format-bookvolume-series-number)))
                     (t14
                      (output-check t13 (gethash "PUBLISHER" *bib-entry* nil)
                       "publisher")))
                (output t14 (gethash "ADDRESS" *bib-entry* nil)))
              (output-nonnull t8 (format-book-crossref))))
         (t16 (format-date))
         (t17 (output-check t15 t16 "year")))
    (fin-entry
     (output (concatenate 'string t17 (format-language))
      (gethash "NOTE" *bib-entry* nil)))))

;; () --> () with side-effects 
;; with assignment to "OUTPUT.STATE"
;; with reference to "LABEL" "BEFORE.ALL" "AUTHOR" "BYSAME" "OUTPUT.STATE" "MID.SENTENCE" "TITLE" "HOWPUBLISHED" "ADDRESS" "YEAR" "MONTH" "MRNUMBER" "NOTE"
(defun booklet ()
  (let* ((t1 (output-bibitem))
         (t2 (output t1 (format-authors)))
         (t3 (output-check t2 (format-title) "title"))
         (t4 (output t3 (gethash "HOWPUBLISHED" *bib-entry* nil)))
         (t5 (output t4 (gethash "ADDRESS" *bib-entry* nil)))
         (t6 (output t5 (format-date))))
    (fin-entry (output t6 (gethash "NOTE" *bib-entry* nil)))))

;; () --> () with side-effects 
;; with assignment to "OUTPUT.STATE"
;; with reference to "LABEL" "BEFORE.ALL" "CROSSREF" "EDITOR" "OUTPUT.STATE" "MID.SENTENCE" "BYSAME" "AUTHOR" "TITLE" "EDITION" "KEY" "SERIES" "VOLUME" "PAGES" "GLOBAL.MAX$" "CHAPTER" "TYPE" "NUMBER" "PUBLISHER" "ADDRESS" "YEAR" "MONTH" "MRNUMBER" "LANGUAGE" "NOTE"
(defun inbook ()
  (let* ((t1 (output-bibitem))
         (t6
          (if (empty-field-p (gethash "AUTHOR" *bib-entry* nil))
              (output-check t1 (format-editors) "author and editor")
              (let ((t5 (output-nonnull t1 (format-authors))))
                (when (null (gethash "CROSSREF" *bib-entry* nil))
                  (either-or-check "author and editor"
                   (gethash "EDITOR" *bib-entry* nil)))
                t5)))
         (t7 (output-check t6 (format-title) "title"))
         (t8 (output t7 (format-edition)))
         (t19
          (if (null (gethash "CROSSREF" *bib-entry* nil))
              (let* ((t16 (output t8 (format-bookvolume-series-number)))
                     (t17
                      (output-check t16 (format-chapter-pages)
                       "chapter and pages"))
                     (t18
                      (output-check t17 (gethash "PUBLISHER" *bib-entry* nil)
                       "publisher")))
                (output t18 (gethash "ADDRESS" *bib-entry* nil)))
              (let ((t15
                     (output-check t8 (format-chapter-pages)
                      "chapter and pages")))
                (output-nonnull t15 (format-book-crossref)))))
         (t20 (format-date))
         (t21 (output-check t19 t20 "year")))
    (fin-entry
     (output (concatenate 'string t21 (format-language))
      (gethash "NOTE" *bib-entry* nil)))))

;; () --> () with side-effects 
;; with assignment to "OUTPUT.STATE"
;; with reference to "LABEL" "BEFORE.ALL" "MID.SENTENCE" "OUTPUT.STATE" "BYSAME" "AUTHOR" "TITLE" "KEY" "CROSSREF" "BOOKTITLE" "EDITOR" "NUMBER" "SERIES" "VOLUME" "PUBLISHER" "ADDRESS" "EDITION" "YEAR" "MONTH" "NOTE" "PAGES" "GLOBAL.MAX$" "MRNUMBER" "LANGUAGE"
(defun incollection ()
  (let* ((t1 (output-bibitem))
         (t2 (output-check t1 (format-authors) "author"))
         (t3 (output-check t2 (format-title) "title"))
         (t18
          (if (null (gethash "CROSSREF" *bib-entry* nil))
              (let* ((t12
                      (output-check t3 (format-incoll-title-editors)
                       "booktitle"))
                     (t13 (output t12 (format-bookvolume-series-number)))
                     (t14
                      (output-check t13 (gethash "PUBLISHER" *bib-entry* nil)
                       "publisher"))
                     (t15 (output t14 (gethash "ADDRESS" *bib-entry* nil)))
                     (t16 (output t15 (format-edition)))
                     (t17 (format-date)))
                (output-check t16 t17 "year"))
              (output-nonnull t3 (format-incoll-inproc-crossref))))
         (t19 (output t18 (gethash "NOTE" *bib-entry* nil)))
         (t20 (output t19 (format-book-pages))))
    (fin-entry (concatenate 'string t20 (format-language)))))

;; () --> () with side-effects 
;; with assignment to "OUTPUT.STATE"
;; with reference to "LABEL" "BEFORE.ALL" "MID.SENTENCE" "OUTPUT.STATE" "BYSAME" "AUTHOR" "TITLE" "KEY" "CROSSREF" "BOOKTITLE" "EDITOR" "ADDRESS" "NUMBER" "SERIES" "VOLUME" "ORGANIZATION" "PUBLISHER" "YEAR" "MONTH" "NOTE" "PAGES" "GLOBAL.MAX$" "MRNUMBER" "LANGUAGE"
(defun inproceedings ()
  (let* ((t1 (output-bibitem))
         (t2 (output-check t1 (format-authors) "author"))
         (t3 (output-check t2 (format-title) "title"))
         (t16
          (if (null (gethash "CROSSREF" *bib-entry* nil))
              (let* ((t11
                      (output-check t3 (format-inproc-title-address-editors)
                       "booktitle"))
                     (t12 (output t11 (format-bookvolume-series-number)))
                     (t13
                      (output t12 (gethash "ORGANIZATION" *bib-entry* nil)))
                     (t14 (output t13 (gethash "PUBLISHER" *bib-entry* nil)))
                     (t15 (format-date)))
                (output-check t14 t15 "year"))
              (output-nonnull t3 (format-incoll-inproc-crossref))))
         (t17 (output t16 (gethash "NOTE" *bib-entry* nil)))
         (t18 (output t17 (format-book-pages))))
    (fin-entry (concatenate 'string t18 (format-language)))))

;; () --> () with side-effects 
;; with assignment to "OUTPUT.STATE"
;; with reference to "LABEL" "BEFORE.ALL" "MID.SENTENCE" "OUTPUT.STATE" "BYSAME" "AUTHOR" "TITLE" "KEY" "CROSSREF" "BOOKTITLE" "EDITOR" "ADDRESS" "NUMBER" "SERIES" "VOLUME" "ORGANIZATION" "PUBLISHER" "YEAR" "MONTH" "NOTE" "PAGES" "GLOBAL.MAX$" "MRNUMBER" "LANGUAGE"
(defun conference () (inproceedings))

;; () --> () with side-effects 
;; with assignment to "OUTPUT.STATE"
;; with reference to "LABEL" "BEFORE.ALL" "AUTHOR" "BYSAME" "MID.SENTENCE" "OUTPUT.STATE" "ORGANIZATION" "ADDRESS" "TITLE" "EDITION" "YEAR" "MONTH" "MRNUMBER" "NOTE"
(defun manual ()
  (let* ((t1 (output-bibitem))
         (t10
          (cond
           ((not (empty-field-p (gethash "AUTHOR" *bib-entry* nil)))
            (output-nonnull t1 (format-authors)))
           ((empty-field-p (gethash "ORGANIZATION" *bib-entry* nil)) t1)
           (t
            (let ((t9
                   (output-nonnull t1
                    (gethash "ORGANIZATION" *bib-entry* nil))))
              (output t9 (gethash "ADDRESS" *bib-entry* nil))))))
         (t11 (output-check t10 (format-title) "title"))
         (t18
          (cond
           ((not (empty-field-p (gethash "AUTHOR" *bib-entry* nil)))
            (let ((t16 (output t11 (gethash "ORGANIZATION" *bib-entry* nil))))
              (output t16 (gethash "ADDRESS" *bib-entry* nil))))
           ((empty-field-p (gethash "ORGANIZATION" *bib-entry* nil))
            (output t11 (gethash "ADDRESS" *bib-entry* nil)))
           (t t11)))
         (t19 (output t18 (format-edition)))
         (t20 (output t19 (format-date))))
    (fin-entry (output t20 (gethash "NOTE" *bib-entry* nil)))))

;; () --> () with side-effects 
;; with assignment to "OUTPUT.STATE"
;; with reference to "LABEL" "BEFORE.ALL" "MID.SENTENCE" "OUTPUT.STATE" "BYSAME" "AUTHOR" "TITLE" "TYPE" "SCHOOL" "ADDRESS" "YEAR" "MONTH" "NOTE" "MRNUMBER" "GLOBAL.MAX$" "PAGES"
(defun mastersthesis ()
  (let* ((t1 (output-bibitem))
         (t2 (output-check t1 (format-authors) "author"))
         (t3 (output-check t2 (format-title) "title"))
         (t4 (output-nonnull t3 (format-thesis-type "Master's thesis")))
         (t5 (output-check t4 (gethash "SCHOOL" *bib-entry* nil) "school"))
         (t6 (output t5 (gethash "ADDRESS" *bib-entry* nil)))
         (t7 (format-date))
         (t8 (output-check t6 t7 "year"))
         (t9 (output t8 (gethash "NOTE" *bib-entry* nil))))
    (fin-entry (output t9 (format-book-pages)))))

;; () --> () with side-effects 
;; with assignment to "OUTPUT.STATE"
;; with reference to "LABEL" "BEFORE.ALL" "AUTHOR" "BYSAME" "OUTPUT.STATE" "MID.SENTENCE" "TITLE" "HOWPUBLISHED" "YEAR" "MONTH" "NOTE" "KEY" "MRNUMBER" "GLOBAL.MAX$" "PAGES"
(defun misc ()
  (let* ((t1 (output-bibitem))
         (t2 (output t1 (format-authors)))
         (t3 (output t2 (format-title)))
         (t4 (output t3 (gethash "HOWPUBLISHED" *bib-entry* nil)))
         (t5 (output t4 (format-date)))
         (t6 (output t5 (gethash "NOTE" *bib-entry* nil))))
    (fin-entry (output t6 (format-book-pages)))
    (empty-misc-check)))

;; () --> () with side-effects 
;; with assignment to "OUTPUT.STATE"
;; with reference to "LABEL" "BEFORE.ALL" "MID.SENTENCE" "OUTPUT.STATE" "BYSAME" "AUTHOR" "TITLE" "TYPE" "SCHOOL" "ADDRESS" "YEAR" "MONTH" "NOTE" "MRNUMBER" "GLOBAL.MAX$" "PAGES"
(defun phdthesis ()
  (let* ((t1 (output-bibitem))
         (t2 (output-check t1 (format-authors) "author"))
         (t3 (output-check t2 (format-title) "title"))
         (t4 (output-nonnull t3 (format-thesis-type "Ph.D. thesis")))
         (t5 (output-check t4 (gethash "SCHOOL" *bib-entry* nil) "school"))
         (t6 (output t5 (gethash "ADDRESS" *bib-entry* nil)))
         (t7 (format-date))
         (t8 (output-check t6 t7 "year"))
         (t9 (output t8 (gethash "NOTE" *bib-entry* nil))))
    (fin-entry (output t9 (format-book-pages)))))

;; () --> () with side-effects 
;; with assignment to "OUTPUT.STATE"
;; with reference to "LABEL" "BEFORE.ALL" "EDITOR" "MID.SENTENCE" "OUTPUT.STATE" "ORGANIZATION" "TITLE" "NUMBER" "SERIES" "VOLUME" "MONTH" "YEAR" "PUBLISHER" "ADDRESS" "MRNUMBER" "NOTE"
(defun proceedings ()
  (let* ((t1 (output-bibitem))
         (t4
          (if (empty-field-p (gethash "EDITOR" *bib-entry* nil))
              (output t1 (gethash "ORGANIZATION" *bib-entry* nil))
              (output-nonnull t1 (format-editors))))
         (t5 (output-check t4 (format-title) "title"))
         (t6 (output t5 (format-bookvolume-series-number)))
         (t27
          (if (empty-field-p (gethash "ADDRESS" *bib-entry* nil))
              (let* ((t24
                      (if (empty-field-p (gethash "EDITOR" *bib-entry* nil))
                          t6
                          (output t6
                           (gethash "ORGANIZATION" *bib-entry* nil))))
                     (t25 (output t24 (gethash "PUBLISHER" *bib-entry* nil)))
                     (t26 (format-date)))
                (output-check t25 t26 "year"))
              (let* ((t18
                      (output-nonnull t6 (gethash "ADDRESS" *bib-entry* nil)))
                     (t20
                      (if (empty-field-p (gethash "EDITOR" *bib-entry* nil))
                          t18
                          (output t18
                           (gethash "ORGANIZATION" *bib-entry* nil))))
                     (t21 (output t20 (gethash "PUBLISHER" *bib-entry* nil)))
                     (t22 (format-date)))
                (output-check t21 t22 "year")))))
    (fin-entry (output t27 (gethash "NOTE" *bib-entry* nil)))))

;; () --> () with side-effects 
;; with assignment to "OUTPUT.STATE"
;; with reference to "LABEL" "BEFORE.ALL" "MID.SENTENCE" "OUTPUT.STATE" "BYSAME" "AUTHOR" "TITLE" "NUMBER" "TYPE" "INSTITUTION" "ADDRESS" "YEAR" "MONTH" "MRNUMBER" "NOTE"
(defun techreport ()
  (let* ((t1 (output-bibitem))
         (t2 (output-check t1 (format-authors) "author"))
         (t3 (output-check t2 (format-title) "title"))
         (t4 (output-nonnull t3 (format-tr-number)))
         (t5
          (output-check t4 (gethash "INSTITUTION" *bib-entry* nil)
           "institution"))
         (t6 (output t5 (gethash "ADDRESS" *bib-entry* nil)))
         (t7 (format-date))
         (t8 (output-check t6 t7 "year")))
    (fin-entry (output t8 (gethash "NOTE" *bib-entry* nil)))))

;; () --> () with side-effects 
;; with assignment to "OUTPUT.STATE"
;; with reference to "LABEL" "BEFORE.ALL" "MID.SENTENCE" "OUTPUT.STATE" "BYSAME" "AUTHOR" "TITLE" "NOTE" "MRNUMBER" "MONTH" "YEAR"
(defun unpublished ()
  (let* ((t1 (output-bibitem))
         (t2 (output-check t1 (format-authors) "author"))
         (t3 (output-check t2 (format-title) "title"))
         (t4 (output-check t3 (gethash "NOTE" *bib-entry* nil) "note")))
    (fin-entry (output t4 (format-date)))))

;; () --> () with side-effects 
;; with assignment to "OUTPUT.STATE"
;; with reference to "LABEL" "BEFORE.ALL" "AUTHOR" "BYSAME" "OUTPUT.STATE" "MID.SENTENCE" "TITLE" "HOWPUBLISHED" "YEAR" "MONTH" "NOTE" "KEY" "MRNUMBER" "GLOBAL.MAX$" "PAGES"
(defun default-type () (misc))

;; ((STRING)) --> ((STRING)) 
(defun sortify (arg1) (bibtex-string-downcase (bibtex-string-purify arg1)))

;; ((STRING) (INTEGER) (STRING)) --> ((STRING)) 
;; with reference to "GLOBAL.MAX$"
(defun chop-word (arg1 len s)
  (if (string= (bibtex-substring s 1 len) arg1)
      (bibtex-substring s (+ len 1))
      s))

(defvar *et-al-char-used* 0)

;; () --> () 
;; with assignment to "ET.AL.CHAR.USED"
(defun initialize-et-al-char-used () (setq *et-al-char-used* 0))

;; ((STRING)) --> ((STRING)) 
;; with possible assignment to "ET.AL.CHAR.USED"
(defun format-lab-names (s)
  (let* ((numnames (num-bibtex-names s)) namesleft nameptr)
    (cond
     ((> numnames 1)
      (if (> numnames 4) (setq namesleft 3) (setq namesleft numnames))
      (setq nameptr 1)
      (let ((t23
             (do ((arg19 ""))
                 ((<= namesleft 0) arg19)
               (let ((t22
                      (cond
                       ((not (= numnames nameptr))
                        (concatenate 'string
                                     arg19
                                     (format-nth-bibtex-name nil
                                                             "{v{}}{l{}}"
                                                             s
                                                             nameptr)))
                       ((string= "others"
                                 (format-nth-bibtex-name nil
                                                         "{ff }{vv }{ll}{ jj}"
                                                         s
                                                         nameptr))
                        (setq *et-al-char-used* 1)
                        (concatenate 'string arg19 "{\\etalchar{+}}"))
                       (t
                        (concatenate 'string
                                     arg19
                                     (format-nth-bibtex-name nil
                                                             "{v{}}{l{}}"
                                                             s
                                                             nameptr))))))
                 (setq nameptr (+ nameptr 1))
                 (setq namesleft (- namesleft 1))
                 (setq arg19 t22)))))
        (cond
         ((> numnames 4) (setq *et-al-char-used* 1)
          (concatenate 'string t23 "{\\etalchar{+}}"))
         (t t23))))
     (t
      (let ((t13 (format-nth-bibtex-name nil "{v{}}{l{}}" s 1)))
        (if (< (length t13) 2)
            (bibtex-string-prefix (format-nth-bibtex-name nil "{ll}" s 1) 3)
            t13))))))

;; () --> ((STRING)) 
;; with possible assignment to "ET.AL.CHAR.USED"
;; with reference to "KEY" "AUTHOR"
(defun author-key-label ()
  (cond
   ((not (empty-field-p (gethash "AUTHOR" *bib-entry* nil)))
    (format-lab-names (gethash "AUTHOR" *bib-entry* nil)))
   ((empty-field-p (gethash "KEY" *bib-entry* nil))
    (bibtex-substring (gethash "KEY" *bib-entry* "") 1 3))
   (t (bibtex-string-prefix (gethash "KEY" *bib-entry* nil) 3))))

;; () --> ((STRING)) 
;; with possible assignment to "ET.AL.CHAR.USED"
;; with reference to "EDITOR" "KEY" "AUTHOR"
(defun author-editor-key-label ()
  (cond
   ((not (empty-field-p (gethash "AUTHOR" *bib-entry* nil)))
    (format-lab-names (gethash "AUTHOR" *bib-entry* nil)))
   ((not (empty-field-p (gethash "EDITOR" *bib-entry* nil)))
    (format-lab-names (gethash "EDITOR" *bib-entry* nil)))
   ((empty-field-p (gethash "KEY" *bib-entry* nil))
    (bibtex-substring (gethash "KEY" *bib-entry* "") 1 3))
   (t (bibtex-string-prefix (gethash "KEY" *bib-entry* nil) 3))))

;; () --> ((STRING)) 
;; with possible assignment to "ET.AL.CHAR.USED"
;; with reference to "KEY" "ORGANIZATION" "GLOBAL.MAX$" "AUTHOR"
(defun author-key-organization-label ()
  (cond
   ((not (empty-field-p (gethash "AUTHOR" *bib-entry* nil)))
    (format-lab-names (gethash "AUTHOR" *bib-entry* nil)))
   ((not (empty-field-p (gethash "KEY" *bib-entry* nil)))
    (bibtex-string-prefix (gethash "KEY" *bib-entry* nil) 3))
   ((empty-field-p (gethash "ORGANIZATION" *bib-entry* nil))
    (bibtex-substring (gethash "KEY" *bib-entry* "") 1 3))
   (t
    (bibtex-string-prefix
     (chop-word "The " 4 (gethash "ORGANIZATION" *bib-entry* nil))
     3))))

;; () --> ((STRING)) 
;; with possible assignment to "ET.AL.CHAR.USED"
;; with reference to "KEY" "ORGANIZATION" "GLOBAL.MAX$" "EDITOR"
(defun editor-key-organization-label ()
  (cond
   ((not (empty-field-p (gethash "EDITOR" *bib-entry* nil)))
    (format-lab-names (gethash "EDITOR" *bib-entry* nil)))
   ((not (empty-field-p (gethash "KEY" *bib-entry* nil)))
    (bibtex-string-prefix (gethash "KEY" *bib-entry* nil) 3))
   ((empty-field-p (gethash "ORGANIZATION" *bib-entry* nil))
    (bibtex-substring (gethash "KEY" *bib-entry* "") 1 3))
   (t
    (bibtex-string-prefix
     (chop-word "The " 4 (gethash "ORGANIZATION" *bib-entry* nil))
     3))))

;; () --> () 
;; with assignment to "SORT.LABEL" "LABEL"
;; with possible assignment to "ET.AL.CHAR.USED"
;; with reference to "AUTHOR" "KEY" "ORGANIZATION" "GLOBAL.MAX$" "EDITOR" "YEAR"
(defun calc-label ()
  (let ((t1
         (cond
          ((or (string= "book" (gethash "ENTRY-TYPE" *bib-entry* ""))
               (string= "inbook" (gethash "ENTRY-TYPE" *bib-entry* "")))
           (author-editor-key-label))
          ((string= "proceedings" (gethash "ENTRY-TYPE" *bib-entry* ""))
           (editor-key-organization-label))
          ((string= "manual" (gethash "ENTRY-TYPE" *bib-entry* ""))
           (author-key-organization-label))
          (t (author-key-label)))))
    (setf (gethash "LABEL" *bib-entry*)
            (concatenate 'string
                         t1
                         (bibtex-substring
                          (bibtex-string-purify
                           (field-or-null (gethash "YEAR" *bib-entry* nil)))
                          -1
                          2)))
    (setf (gethash "SORT.LABEL" *bib-entry*)
            (sortify
             (concatenate 'string
                          t1
                          (bibtex-substring
                           (bibtex-string-purify
                            (field-or-null (gethash "YEAR" *bib-entry* nil)))
                           -1
                           4))))))

;; ((STRING)) --> ((STRING)) 
(defun sort-format-names (s)
  (do* ((nameptr 1)
        (numnames (num-bibtex-names s))
        (namesleft numnames)
        (arg2 ""))
       ((<= namesleft 0) arg2)
    (let* ((temp90
            (format-nth-bibtex-name nil
                                    "{vv{ } }{ll{ }}{  ff{ }}{  jj{ }}"
                                    s
                                    nameptr))
           (t5
            (if (and (= numnames nameptr) (string= "others" temp90))
                (concatenate 'string
                             (if (> nameptr 1)
                                 (concatenate 'string arg2 "   ")
                                 arg2)
                             "et al")
                (concatenate 'string
                             (if (> nameptr 1)
                                 (concatenate 'string arg2 "   ")
                                 arg2)
                             (sortify temp90)))))
      (setq nameptr (+ nameptr 1))
      (setq namesleft (- namesleft 1))
      (setq arg2 t5))))

;; ((STRING)) --> ((STRING)) 
;; with reference to "GLOBAL.MAX$"
(defun sort-format-title (temp91)
  (sortify (chop-word "A " 2 (chop-word "An " 3 (chop-word "The " 4 temp91)))))

;; () --> ((STRING)) with side-effects 
;; with reference to "KEY" "AUTHOR"
(defun author-sort ()
  (cond
   ((not (empty-field-p (gethash "AUTHOR" *bib-entry* nil)))
    (sort-format-names (gethash "AUTHOR" *bib-entry* nil)))
   ((empty-field-p (gethash "KEY" *bib-entry* nil))
    (bib-warn* "to sort, need author or key in "
               (gethash "KEY" *bib-entry* ""))
    "")
   (t (sortify (gethash "KEY" *bib-entry* nil)))))

;; () --> ((STRING)) with side-effects 
;; with reference to "EDITOR" "KEY" "AUTHOR"
(defun author-editor-sort ()
  (cond
   ((not (empty-field-p (gethash "AUTHOR" *bib-entry* nil)))
    (sort-format-names (gethash "AUTHOR" *bib-entry* nil)))
   ((not (empty-field-p (gethash "EDITOR" *bib-entry* nil)))
    (sort-format-names (gethash "EDITOR" *bib-entry* nil)))
   ((empty-field-p (gethash "KEY" *bib-entry* nil))
    (bib-warn* "to sort, need author, editor, or key in "
               (gethash "KEY" *bib-entry* ""))
    "")
   (t (sortify (gethash "KEY" *bib-entry* nil)))))

;; () --> ((STRING)) with side-effects 
;; with reference to "ORGANIZATION" "GLOBAL.MAX$" "KEY" "AUTHOR"
(defun author-organization-sort ()
  (cond
   ((not (empty-field-p (gethash "AUTHOR" *bib-entry* nil)))
    (sort-format-names (gethash "AUTHOR" *bib-entry* nil)))
   ((not (empty-field-p (gethash "ORGANIZATION" *bib-entry* nil)))
    (sortify (chop-word "The " 4 (gethash "ORGANIZATION" *bib-entry* nil))))
   ((empty-field-p (gethash "KEY" *bib-entry* nil))
    (bib-warn* "to sort, need author, organization, or key in "
               (gethash "KEY" *bib-entry* ""))
    "")
   (t (sortify (gethash "KEY" *bib-entry* nil)))))

;; () --> ((STRING)) with side-effects 
;; with reference to "ORGANIZATION" "GLOBAL.MAX$" "KEY" "EDITOR"
(defun editor-organization-sort ()
  (cond
   ((not (empty-field-p (gethash "EDITOR" *bib-entry* nil)))
    (sort-format-names (gethash "EDITOR" *bib-entry* nil)))
   ((not (empty-field-p (gethash "ORGANIZATION" *bib-entry* nil)))
    (sortify (chop-word "The " 4 (gethash "ORGANIZATION" *bib-entry* nil))))
   ((empty-field-p (gethash "KEY" *bib-entry* nil))
    (bib-warn* "to sort, need editor, organization, or key in "
               (gethash "KEY" *bib-entry* ""))
    "")
   (t (sortify (gethash "KEY" *bib-entry* nil)))))

;; () --> () with side-effects 
;; with assignment to "SORT.KEY$" "SORT.LABEL" "LABEL"
;; with possible assignment to "ET.AL.CHAR.USED"
;; with reference to "TITLE" "ENTRY.MAX$" "SORT.LABEL" "AUTHOR" "KEY" "ORGANIZATION" "GLOBAL.MAX$" "EDITOR" "YEAR"
(defun presort ()
  (calc-label)
  (let ((t1
         (concatenate 'string
                      (gethash "SORT.LABEL" *bib-entry* "")
                      "    "
                      (cond
                       ((or
                         (string= "book" (gethash "ENTRY-TYPE" *bib-entry* ""))
                         (string= "inbook"
                                  (gethash "ENTRY-TYPE" *bib-entry* "")))
                        (author-editor-sort))
                       ((string= "proceedings"
                                 (gethash "ENTRY-TYPE" *bib-entry* ""))
                        (editor-organization-sort))
                       ((string= "manual"
                                 (gethash "ENTRY-TYPE" *bib-entry* ""))
                        (author-organization-sort))
                       (t (author-sort))))))
    (setf (gethash "SORT.KEY$" *bib-entry*)
            (concatenate 'string
                         t1
                         "    "
                         (sortify
                          (field-or-null (gethash "YEAR" *bib-entry* nil)))
                         "    "
                         (sort-format-title
                          (field-or-null (gethash "TITLE" *bib-entry* nil)))))))

(defvar *longest-label* "")

(defvar *last-sort-label* "")

(defvar *next-extra* "")

(defvar *prev-author* "")

(defvar *this-author* "")

(defvar *longest-label-width* 0)

(defvar *last-extra-num* 0)

;; () --> () 
;; with assignment to "LAST.SORT.LABEL" "LONGEST.LABEL.WIDTH" "PREV.AUTHOR" "THIS.AUTHOR" "LAST.EXTRA.NUM" "NEXT.EXTRA" "LONGEST.LABEL"
(defun initialize-longest-label ()
  (setq *longest-label* "")
  (setq *last-sort-label* (string (code-char 0)))
  (setq *next-extra* "")
  (setq *longest-label-width* 0)
  (setq *last-extra-num* 0)
  (setq *prev-author* "abcxyz")
  (setq *this-author* ""))

;; () --> () 
;; with assignment to "THIS.AUTHOR" "BYSAME" "LAST.EXTRA.NUM" "EXTRA.LABEL"
;; with possible assignment to "LAST.SORT.LABEL" "PREV.AUTHOR"
;; with reference to "EDITOR" "AUTHOR" "PREV.AUTHOR" "THIS.AUTHOR" "LAST.EXTRA.NUM" "LAST.SORT.LABEL" "SORT.LABEL"
(defun forward-pass ()
  (cond
   ((string= (gethash "SORT.LABEL" *bib-entry* "") *last-sort-label*)
    (setq *last-extra-num* (+ *last-extra-num* 1))
    (setf (gethash "EXTRA.LABEL" *bib-entry*)
            (string (code-char *last-extra-num*))))
   (t (setq *last-extra-num* (char-code #\a))
    (setf (gethash "EXTRA.LABEL" *bib-entry*) "")
    (setq *last-sort-label* (gethash "SORT.LABEL" *bib-entry* ""))))
  (setq *this-author*
          (cond
           ((not (empty-field-p (gethash "AUTHOR" *bib-entry* nil)))
            (gethash "AUTHOR" *bib-entry* nil))
           ((empty-field-p (gethash "EDITOR" *bib-entry* nil)) "")
           (t (gethash "EDITOR" *bib-entry* nil))))
  (cond
   ((string= *prev-author* *this-author*)
    (setf (gethash "BYSAME" *bib-entry*) "\\bysame"))
   (t (setf (gethash "BYSAME" *bib-entry*) "")
    (setq *prev-author*
            (if (string= "" *this-author*) "abcxyz" *this-author*)))))

;; () --> () 
;; with assignment to "LABEL" "NEXT.EXTRA"
;; with possible assignment to "EXTRA.LABEL" "LONGEST.LABEL.WIDTH" "LONGEST.LABEL"
;; with reference to "LABEL" "EXTRA.LABEL" "LONGEST.LABEL.WIDTH" "NEXT.EXTRA"
(defun reverse-pass ()
  (when (string= "b" *next-extra*)
    (setf (gethash "EXTRA.LABEL" *bib-entry*) "a"))
  (setf (gethash "LABEL" *bib-entry*)
          (concatenate 'string
                       (gethash "LABEL" *bib-entry* "")
                       (gethash "EXTRA.LABEL" *bib-entry* "")))
  (when
      (> (bibtex-string-width (gethash "LABEL" *bib-entry* ""))
         *longest-label-width*)
    (setq *longest-label* (gethash "LABEL" *bib-entry* ""))
    (setq *longest-label-width*
            (bibtex-string-width (gethash "LABEL" *bib-entry* ""))))
  (setq *next-extra* (gethash "EXTRA.LABEL" *bib-entry* "")))

;; () --> () with side-effects 
;; with reference to "LONGEST.LABEL" "ET.AL.CHAR.USED"
(defun begin-bib ()
  (when (> *et-al-char-used* 0)
    (princ "\\newcommand{\\etalchar}[1]{$^{#1}$}" *bbl-output*)
    (terpri *bbl-output*))
  (unless (empty-field-p *bib-preamble*)
    (princ *bib-preamble* *bbl-output*)
    (terpri *bbl-output*))
  (princ
   "\\providecommand{\\bysame}{\\leavevmode\\hbox to3em{\\hrulefill}\\thinspace}"
   *bbl-output*)
  (terpri *bbl-output*)
  (princ "\\providecommand{\\MR}{\\relax\\ifhmode\\unskip\\space\\fi MR }"
         *bbl-output*)
  (terpri *bbl-output*)
  (princ "% \\MRhref is called by the amsart/book/proc definition of \\MR."
         *bbl-output*)
  (terpri *bbl-output*)
  (princ "\\providecommand{\\MRhref}[2]{%" *bbl-output*)
  (terpri *bbl-output*)
  (princ "  \\href{http://www.ams.org/mathscinet-getitem?mr=#1}{#2}"
         *bbl-output*)
  (terpri *bbl-output*)
  (princ "}" *bbl-output*)
  (terpri *bbl-output*)
  (princ "\\providecommand{\\href}[2]{#2}" *bbl-output*)
  (terpri *bbl-output*)
  (princ (concatenate 'string "\\begin{thebibliography}{" *longest-label* "}")
         *bbl-output*)
  (terpri *bbl-output*))

;; () --> () with side-effects 
(defun end-bib ()
  (terpri *bbl-output*)
  (princ "\\end{thebibliography}" *bbl-output*)
  (terpri *bbl-output*))

;;; \CharacterTable
;;;  {Upper-case    \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z
;;;   Lower-case    \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z
;;;   Digits        \0\1\2\3\4\5\6\7\8\9
;;;   Exclamation   \!     Double quote  \"     Hash (number) \#
;;;   Dollar        \$     Percent       \%     Ampersand     \&
;;;   Acute accent  \'     Left paren    \(     Right paren   \)
;;;   Asterisk      \*     Plus          \+     Comma         \,
;;;   Minus         \-     Point         \.     Solidus       \/
;;;   Colon         \:     Semicolon     \;     Less than     \<
;;;   Equals        \=     Greater than  \>     Question mark \?
;;;   Commercial at \@     Left bracket  \[     Backslash     \\
;;;   Right bracket \]     Circumflex    \^     Underscore    \_
;;;   Grave accent  \`     Left brace    \{     Vertical bar  \|
;;;   Right brace   \}     Tilde         \~}

(define-bibtex-style "amsalpha"
  (let ((*bib-entry-type-functions*
         '(("SHOWSTACK" . showstack) ("EMPTY.MISC.CHECK" . empty-misc-check)
           ("ARTICLE" . article) ("BOOK" . book) ("BOOKLET" . booklet)
           ("INBOOK" . inbook) ("INCOLLECTION" . incollection)
           ("INPROCEEDINGS" . inproceedings) ("CONFERENCE" . conference)
           ("MANUAL" . manual) ("MASTERSTHESIS" . mastersthesis)
           ("MISC" . misc) ("PHDTHESIS" . phdthesis)
           ("PROCEEDINGS" . proceedings) ("TECHREPORT" . techreport)
           ("UNPUBLISHED" . unpublished) ("DEFAULT.TYPE" . default-type)
           ("PRESORT" . presort) ("BEGIN.BIB" . begin-bib)
           ("END.BIB" . end-bib)))
        bib-entries)
    (setq bib-entries (read-all-bib-files-and-compute-bib-entries))
    (initialize-et-al-char-used)
    (dolist (*bib-entry* bib-entries) (presort))
    (setq bib-entries
            (stable-sort bib-entries
                         'string<=
                         :key
                         (lambda (entry) (gethash "SORT.KEY$" entry ""))))
    (initialize-longest-label)
    (dolist (*bib-entry* bib-entries) (forward-pass))
    (dolist (*bib-entry* (reverse bib-entries)) (reverse-pass))
    (begin-bib)
    (init-state-consts)
    (dolist (*bib-entry* bib-entries)
      (let ((type/fun
             (assoc (gethash "ENTRY-TYPE" *bib-entry*)
                    *bib-entry-type-functions*
                    :test
                    'string-equal)))
        (if type/fun (funcall (cdr type/fun)) (default-type))))
    (end-bib)))