% $Id: biblatex.bst,v 0.9e 2010/10/09 16:39:36 lehman beta $

% Copyright (c) 2006-2010 Philipp Lehman.
%
% Permission is granted to copy, distribute and/or modify this
% software under the terms of the LaTeX Project Public License
% (LPPL), version 1.3.
%
% The LPPL maintenance status of this software is
% 'author-maintained'.
%
% This software is provided 'as is', without warranty of any kind,
% either expressed or implied, including, but not limited to, the
% implied warranties of merchantability and fitness for a
% particular purpose.

% -------------------------------------------------------------------
% Initialization
% -------------------------------------------------------------------

ENTRY {
    % special fields
    entryset
    entrysubtype
    execute
    hyphenation
    keywords
    label
    options
    presort
    shorthand
    sortkey
    sortname
    sorttitle
    sortyear
    xref
    % data fields
    abstract
    addendum
    address
    afterword
    annotation
    annote
    annotator
    author
    authortype
    bookauthor
    booksubtitle
    booktitle
    booktitleaddon
    chapter
    commentator
    date
    doi
    edition
    editor
    editora
    editorb
    editorc
    editortype
    editoratype
    editorbtype
    editorctype
    eid
    eprint
    eprintclass
    eprinttype
    eventdate
    eventtitle
    file
    foreword
    gender
    howpublished
    indexsorttitle
    indextitle
    institution
    introduction
    isan
    isbn
    ismn
    isrn
    issn
    issue
    issuetitle
    issuesubtitle
    iswc
    journal
    journaltitle
    journalsubtitle
    language
    library
    location
    bookpagination
    mainsubtitle
    maintitle
    maintitleaddon
    month
    nameaddon
    note
    number
    organization
    origlanguage
    origlocation
    origpublisher
    origtitle
    origdate
    pages
    pagetotal
    pagination
    part
    pdf
    pubstate
    reprinttitle
    holder
    publisher
    school
    series
    shortauthor
    shorteditor
    shorthandintro
    shortjournal
    shortseries
    shorttitle
    subtitle
    title
    titleaddon
    translator
    type
    url
    urldate
    venue
    version
    volume
    volumes
    year
    % aliases
    archiveprefix
    primaryclass
    % custom fields
    namea
    nameb
    namec
    nameatype
    namebtype
    namectype
    lista
    listb
    listc
    listd
    liste
    listf
    usera
    userb
    userc
    userd
    usere
    userf
    verba
    verbb
    verbc
  }
  { skipbib skiplos skiplab useauthor useeditor usetranslator useprefix singletitle uniquename }
  { entryoptions labelhash namehash fullhash dateyear dateendyear extrayear labelalpha extraalpha 
    sortinit label.name label.uniq label.year sortkey.nosort sortkey.name sortkey.year
    sortkey.title sortkey.alpha sort.year sort.alph warningmsg }

INTEGERS { ctrl.debug ctrl.bibtex8 ctrl.maxline ctrl.sorting ctrl.cssort ctrl.sortlos 
           ctrl.maxnames ctrl.minnames ctrl.useauthor ctrl.useeditor ctrl.usetranslator
           ctrl.useprefix ctrl.terseinits ctrl.labelalpha ctrl.singletitle
           ctrl.uniquename ctrl.labelyear citecount 
           tempctra tempctrb tempctrc resvctra resvctrb resvctrc
           last.extra.num last.uniq.num }

STRINGS  { ctrl.alphaothers templist tempstrga tempstrgb resvstrga
           last.name last.hash last.uniq last.year last.extra }

FUNCTION {initialize} {
  "$Revision: 0.9e $"
  #12 entry.max$ substring$
  #-3 entry.max$ substring$
  "Biblatex version: " swap$ * top$
   #0  'ctrl.terseinits :=
   #0  'ctrl.debug :=
   #0  'ctrl.labelalpha :=
   #0  'ctrl.labelyear :=
   #0  'ctrl.singletitle :=
   #0  'ctrl.uniquename :=
   #0  'ctrl.sorting :=
   #0  'ctrl.sortlos :=
   #1  'ctrl.useauthor :=
   #1  'ctrl.useeditor :=
   #0  'ctrl.usetranslator :=
   #0  'ctrl.useprefix :=
   #1  'ctrl.minnames :=
  #99  'ctrl.maxnames :=
  #79  'ctrl.maxline :=
  "+"  'ctrl.alphaothers :=
}

% -------------------------------------------------------------------
% Strings
% -------------------------------------------------------------------

MACRO {jan} { "01" }
MACRO {feb} { "02" }
MACRO {mar} { "03" }
MACRO {apr} { "04" }
MACRO {may} { "05" }
MACRO {jun} { "06" }
MACRO {jul} { "07" }
MACRO {aug} { "08" }
MACRO {sep} { "09" }
MACRO {oct} { "10" }
MACRO {nov} { "11" }
MACRO {dec} { "12" }

% -------------------------------------------------------------------
% Generic functions
% -------------------------------------------------------------------

FUNCTION {and} {
    'skip$
    { pop$ #0 }
  if$
}

FUNCTION {or} {
    { pop$ #1 }
    'skip$
  if$
}

FUNCTION {not} {
    { #0 }
    { #1 }
  if$
}

FUNCTION {ctrl:control} {
  type$ "control" =
}

FUNCTION {ctrl:set} {
  type$ "set" =
}

FUNCTION {ctrl:skiplos} {
  ctrl:control skiplos or
  ctrl:set not
  and
}

FUNCTION {ctrl:skiplab} {
  ctrl:control skiplab or
  ctrl:set not
  and
}

FUNCTION {ctrl:labelalpha} {
  ctrl.labelalpha ctrl:skiplab not and
  shorthand empty$
  and
}

FUNCTION {ctrl:labelyear} {
  ctrl.labelyear
  ctrl:skiplab not
  and
}

FUNCTION {wrap:braces} {
  duplicate$ empty$
    { pop$ "{}" }
    { "{" swap$ * "}" * }
  if$
}

FUNCTION {delimiter.1} {
  ctrl.bibtex8
    { "0" }
    { "    " }
  if$
}

FUNCTION {delimiter.2} {
  ctrl.bibtex8
    { "1" }
    { "   " }
  if$
}

FUNCTION {delimiter.3} {
  ctrl.bibtex8
    { "2" }
    { "  " }
  if$
}

FUNCTION {open.ended} {
  "9999"
}

FUNCTION {maxline} {
  duplicate$ empty$
    'skip$
    { #1 ctrl.maxline substring$ }
  if$
}

FUNCTION {truncate} {
  duplicate$ empty$
    { pop$ "" }
    { #1 entry.max$ substring$ }
  if$
}

FUNCTION {normalize} {
  duplicate$ empty$
    { pop$ "" }
    { purify$
      ctrl.bibtex8
      ctrl.cssort
      and
        'skip$
        { "l" change.case$ }
      if$
      truncate
    }
  if$
}

FUNCTION {enquote} {
  "'" swap$ * "'" *
}

FUNCTION {bol.to.int} {
  "true" =
    { #1 }
    { #0 }
  if$
}

FUNCTION {str.to.int} {
  'resvstrga :=
  resvstrga text.length$ 'resvctra :=
  #1 'resvctrb :=
  #0
  { resvctrb resvctra > not }
    { 'resvctrc :=
      resvstrga resvctrb #1 substring$
      chr.to.int$ "0" chr.to.int$ -
      #0
      { resvctrc #0 > }
        { resvctrc #1 - 'resvctrc :=
          #10 +
        }
      while$
      +
      resvctrb #1 + 'resvctrb :=
    }
  while$
}

FUNCTION {andothers} {
  duplicate$ num.names$ "{ff}{vv}{ll}{jj}" format.name$ "others" =
}

FUNCTION {push} {
  duplicate$ empty$
    { pop$ "" }
    { truncate }
  if$
}

FUNCTION {push:cite} {
  cite$ empty$
    { "Missing citation key" warning$ "" }
    { cite$ }
  if$
}

FUNCTION {push:presort} {
  presort empty$
    { "mm" }
    { presort normalize
      #1 #2 substring$
      "l" change.case$ }
  if$
}

FUNCTION {push:fullname} {
  author empty$ not
  useauthor
  and
    { author }
    { editor empty$ not
      useeditor
      and
        { editor }
        { translator empty$ not
          usetranslator
          and
            { translator }
            { "" }
          if$
        }
      if$
    }
  if$
}

FUNCTION {push:shortname:translator} {
  translator empty$ not
  usetranslator
  and
    { translator }
    { "" }
  if$
}

FUNCTION {push:shortname:editor} {
  useeditor
    { shorteditor empty$
        { editor empty$
            { push:shortname:translator }
            { editor }
          if$
        }
        { shorteditor }
      if$
    }
    { push:shortname:translator }
  if$
}

FUNCTION {push:shortname} {
  useauthor
    { shortauthor empty$
        { author empty$
            { push:shortname:editor }
            { author }
          if$
        }
        { shortauthor }
      if$
    }
    { push:shortname:editor }
  if$
}

FUNCTION {push:sorttitle} {
  sorttitle empty$
    { title empty$
        { "" }
        { title }
      if$
    }
    { sorttitle }
  if$
  push
}

FUNCTION {shortname:hash} {
  'tempctrc :=
  'templist :=
  #1 'tempctra :=
  templist num.names$ 'tempctrb :=
  templist andothers
    { tempctrb #1 - 'tempctrb := }
    'skip$
  if$
  tempctrc #0 =
    { tempctrb 'tempctrc := }
    { tempctrb tempctrc >
        { ctrl.minnames 'tempctrc := }
        { ctrl.maxnames 'tempctrc := }
      if$
    }
  if$
  ""
  { tempctra tempctrc > not
    tempctrb #0 >
    and }
    { templist tempctra "{vv{}}{ll{}}{ff{}}{jj{}}" format.name$ *
      tempctra #1 + 'tempctra :=
      tempctrb #1 - 'tempctrb :=
    }
  while$
  templist andothers
  tempctrb #0 >
  or
    { "+" * }
    'skip$
  if$
}

FUNCTION {push:name:namehash} {
  push:shortname duplicate$ empty$
    { pop$ push:sorttitle duplicate$ empty$
        { pop$ push:cite normalize }
        'skip$
      if$
    }
    { ctrl.maxnames shortname:hash }
  if$
}

FUNCTION {push:name:fullhash} {
  push:fullname duplicate$ empty$
    { pop$ push:sorttitle duplicate$ empty$
        { pop$ push:cite normalize }
        'skip$
      if$
    }
    { #0 shortname:hash }
  if$
}

FUNCTION {check:sortname} {
  sortname empty$
    'skip$
    { pop$ sortname }
  if$
}

FUNCTION {warning} {
  "\item " swap$ * 
  warningmsg empty$
    'skip$
    { warningmsg " " * swap$ * }
  if$
  'warningmsg :=
}

FUNCTION {warning:invalid} {
  "Invalid format of field " swap$ enquote * warning
}

FUNCTION {warning:duplicate} {
  "Can't use " swap$ enquote * " + " * swap$ enquote * warning
}

FUNCTION {pad.number} {
  'tempctra :=
  duplicate$ empty$
    { pop$ "" }
    'skip$
  if$
  { duplicate$ text.length$ tempctra < }
    { "0" swap$ * }
  while$
}

FUNCTION {extract.number} {
  purify$ 'tempstrga :=
  ""
  { tempstrga empty$ not }
    { tempstrga #1 #1 substring$ chr.to.int$ duplicate$
      #47 > swap$
      #58 < and
        { tempstrga #1 #1 substring$ * }
        'skip$
      if$
      tempstrga #2 global.max$ substring$ 'tempstrga :=
    }
  while$
  #1 #9 substring$
}

FUNCTION {format.range}
{ 'tempstrga :=
  ""
  { tempstrga empty$ not }
    { tempstrga #1 #1 substring$ "-" =
      { "\bibrangedash " *
        tempstrga #2 global.max$ substring$ 'tempstrga :=
        { tempstrga #1 #1 substring$ "-" = }
          { tempstrga #2 global.max$ substring$ 'tempstrga := }
        while$
      }
      { tempstrga #1 #1 substring$ *
        tempstrga #2 global.max$ substring$ 'tempstrga :=
      }
      if$
    }
  while$
}

FUNCTION {is.number} {
  #1
  { #0 > }
    { duplicate$ #1 #1 substring$ chr.to.int$ 
      duplicate$ #47 >
      swap$      #58 <
      and
        { #2 global.max$ substring$
          duplicate$ empty$
            { #0 }
            { #1 }
          if$
        }
        { #0 }
      if$
    }
  while$
  empty$
}

FUNCTION {split.date:invalid} {
  #0 'tempctra :=
}

FUNCTION {split.date:check.day} {
  duplicate$ empty$
    'skip$
    { duplicate$ is.number
        { duplicate$ str.to.int
          duplicate$  #0 >
          swap$      #32 <
          and
            { duplicate$ text.length$ #2 <
                { "0" swap$ * }
                'skip$
              if$
            }
            { pop$ "" split.date:invalid }
          if$
        }
        { pop$ "" split.date:invalid }
      if$
    }
  if$
}

FUNCTION {split.date:check.month} {
  duplicate$ empty$
    'skip$
    { duplicate$ is.number
        { duplicate$ str.to.int
          duplicate$  #0 >
          swap$      #13 <
          and
            { duplicate$ text.length$ #2 <
                { "0" swap$ * }
                'skip$
              if$
            }
            { pop$ "" split.date:invalid }
          if$
        }
        { pop$ "" split.date:invalid }
      if$
    }
  if$
}

FUNCTION {split.date:check.year} {
  duplicate$ empty$
    'skip$
    { duplicate$ is.number
        { duplicate$ "0" =
            'skip$
            { duplicate$
              duplicate$ str.to.int #0 >
              swap$    text.length$ #5 <
              and
                'skip$
                { pop$ "" split.date:invalid }
              if$
            }
          if$
        }
        { pop$ "" split.date:invalid }
      if$
    }
  if$
}

FUNCTION {split.date:check.date} {
  duplicate$ empty$
    'skip$
    { duplicate$
      duplicate$ text.length$  #0 >
      swap$      text.length$ #11 <
      and
        'skip$
        { pop$ "" split.date:invalid }
      if$
    }
  if$
}

FUNCTION {split.date:check.range} {
  duplicate$ empty$
    'skip$
    { duplicate$
      duplicate$ text.length$  #0 >
      swap$      text.length$ #22 <
      and
        'skip$
        { pop$ "" split.date:invalid }
      if$
    }
  if$
}

FUNCTION {split.date:date:part} {
  'tempstrgb :=
  ""
  { tempstrgb #1 #1 substring$
    duplicate$ empty$
      { pop$ #0 }
      { "-" = not }
    if$
  }
    { tempstrgb #1 #1 substring$ *
      tempstrgb #2 global.max$ substring$ 'tempstrgb :=
    }
  while$
  tempstrgb #2 global.max$ substring$
}

FUNCTION {split.date:date} {
  duplicate$ empty$
    { pop$ "" "" "" }
    { split.date:date:part swap$ split.date:check.year  swap$
      split.date:date:part swap$ split.date:check.month swap$
      split.date:date:part pop$  split.date:check.day
    }
  if$
}

FUNCTION {split.date:range} {
  duplicate$ empty$
    { pop$ "" "" }
    { 'tempstrgb :=
      ""
      #0 'tempctrb :=
      { tempstrgb #1 #1 substring$
        duplicate$ empty$
          { pop$ #0 }
          { "/" =
              { #1 'tempctrb :=
                #0
              }
              { #1 }
            if$
          }
        if$
      }
        { tempstrgb #1 #1 substring$ *
          tempstrgb #2 global.max$ substring$ 'tempstrgb :=
        }
      while$
      split.date:check.date
      tempstrgb #2 global.max$ substring$
      duplicate$ empty$
      tempctrb #1 =
      and
        { pop$ open.ended }
        'skip$
      if$
      split.date:check.date
    }
  if$
}

FUNCTION {split.date} {
  duplicate$ empty$
    { pop$ pop$ "" "" "" "" "" "" }
    { swap$ 'templist :=
      #1 'tempctra :=
      split.date:check.range
      split.date:range swap$ 'tempstrga :=
      split.date:date tempstrga
      split.date:date
      tempctra
        'skip$
        { pop$ pop$ pop$ pop$ pop$ pop$ "" "" "" "" "" "" 
          templist warning:invalid
        }
      if$
    }
  if$
}

% -------------------------------------------------------------------
% Sorting
% -------------------------------------------------------------------

FUNCTION {sortkey:name:format} {
  'templist :=
  #1 'tempctra :=
  templist num.names$ 'tempctrb :=
  templist andothers
    { tempctrb #1 - 'tempctrb := }
    'skip$
  if$
  tempctrb ctrl.maxnames >
    { ctrl.minnames 'tempctrc := }
    { ctrl.maxnames 'tempctrc := }
  if$
  ""
  { duplicate$ text.length$ entry.max$ #50 - <
    tempctra tempctrc > not and
    tempctrb #0 > and
    }
    { useprefix
        { templist tempctra "{vv}" format.name$
          duplicate$ empty$
            { pop$ "" }
            { "u" change.case$ "t" change.case$ 
              delimiter.3 * }
          if$
          templist tempctra
          "{ll}{" delimiter.3 *
          "ff}{"  delimiter.3 * *
          "jj}" *
          format.name$ *
        }
        { templist tempctra
          "{ll}{" delimiter.3 *
          "ff}{"  delimiter.3 * *
          "vv}{"  delimiter.3 * *
          "jj}" *
          format.name$ }
      if$
      tempctra #1 >
        { delimiter.2 swap$ * }
        'skip$
      if$
      *
      tempctra #1 + 'tempctra :=
      tempctrb #1 - 'tempctrb :=
    }
  while$
  templist andothers
  tempctrb #0 >
  or
    { delimiter.2 * "zzzz" * }
    'skip$
  if$
}

FUNCTION {sortkey:init:label} {
  push:shortname duplicate$ empty$
    { pop$ push:sorttitle }
    { check:sortname sortkey:name:format }
  if$
  normalize 'sortkey.name :=
  sortyear empty$
    { dateyear
      dateendyear empty$
        'skip$
        { dateyear dateendyear =
            'skip$
            { dateendyear open.ended =
                'skip$
                { "-" * dateendyear * }
              if$
            }
          if$
        }
      if$
    }
    { sortyear }
  if$
  normalize 'sortkey.year :=
  push:sorttitle normalize 'sortkey.title :=
}

FUNCTION {sortkey:init:main} {
  push:fullname duplicate$ empty$
    { pop$ push:sorttitle }
    { check:sortname sortkey:name:format }
  if$
  normalize 'sortkey.name :=
}

FUNCTION {sortkey:main:string} {
  duplicate$ #1 =
    { pop$
      sortkey.name    delimiter.1 *
      sortkey.title * delimiter.1 *
      sortkey.year  * delimiter.1 *
      volume normalize #4 pad.number * delimiter.1 *
    }
    { duplicate$ #2 =
        { pop$
          sortkey.name    delimiter.1 *
          sortkey.year  * delimiter.1 *
          sortkey.title * delimiter.1 *
          volume normalize #4 pad.number * delimiter.1 *
        }
        { #3 =
            { sortkey.name   delimiter.1 *
              sortkey.year * delimiter.1 *
              volume normalize #4 pad.number * delimiter.1 *
              sortkey.title *
            }
            { "" }
          if$
        }
      if$
    }
  if$
}

FUNCTION {sortkey:main:date:year} {
  duplicate$ empty$
    { pop$ }
    { extract.number #1 #4 substring$
      duplicate$ empty$
        { pop$ }
        { swap$ pop$ }
      if$
    }
  if$
}

FUNCTION {sortkey:main:date} {
  duplicate$ #1 =
    { pop$
      sortyear empty$
        { "9999" dateyear sortkey:main:date:year }
        { sortyear normalize }
      if$
    }
    { #2 =
        { sortyear empty$
            { "0" dateyear sortkey:main:date:year }
            { sortyear normalize }
          if$
          str.to.int #9999 swap$ - int.to.str$
        }
        { "" }
      if$
    }
  if$
  sortkey.name  * delimiter.1 *
  sortkey.title * delimiter.1 *
  volume normalize #4 pad.number * delimiter.1 *
}

FUNCTION {sortkey:main} {
  ctrl.sorting #0 =
    { sortkey.nosort }
    { sortkey:init:main
      ""
      ctrl.sorting #10 <
        { sortkey empty$
            { ctrl.sorting sortkey:main:string }
            { sortkey }
          if$
        }
        { ctrl.sorting #20 <
            { shorthand empty$
                { sortkey.alpha * }
                { shorthand normalize * }
              if$
              delimiter.1 *
              ctrl.sorting #10 - sortkey:main:string
            }
            { ctrl.sorting #30 <
                { sortkey empty$
                    { ctrl.sorting #20 - sortkey:main:date }
                    { sortkey }
                  if$
                }
                { push:cite normalize }
              if$
            }
          if$
        }
      if$
      *
      duplicate$ #1 text.prefix$ "u" change.case$ 'sortinit :=
      push:presort delimiter.1 * swap$ *
    }
  if$
  truncate
}

% -------------------------------------------------------------------
% Output
% -------------------------------------------------------------------

FUNCTION {output:indent:field} {
  duplicate$ empty$
    'skip$
    { "  " swap$ * write$ newline$ }
  if$
}

FUNCTION {output:indent:subfield} {
  duplicate$ empty$
    'skip$
    { "    " swap$ * write$ newline$ }
  if$
}

FUNCTION {output:write:field} {
  duplicate$ empty$
    { pop$ pop$ }
    { swap$ "\field" swap$ wrap:braces *
      swap$ wrap:braces * output:indent:field }
  if$
}

FUNCTION {output:write:year} {
  duplicate$ empty$
    { pop$ pop$ }
    { duplicate$ open.ended =
        { pop$ "" }
        'skip$
      if$
      swap$ "\field" swap$ wrap:braces *
      swap$ wrap:braces * output:indent:field 
      }
  if$
}

FUNCTION {output:write:multi} {
  duplicate$ empty$
    { pop$ pop$ }
    { swap$ "\field" swap$ wrap:braces * "{%" * output:indent:field
      "%" * output:indent:field
      "}"  output:indent:field
    }
  if$
}

FUNCTION {output:write:bool} {
  #0 >
    { "\true"  }
    { "\false" }
  if$
  swap$ wrap:braces * output:indent:field
}

FUNCTION {output:write:count} {
  int.to.str$ swap$ "\count" swap$ wrap:braces *
  swap$ wrap:braces * output:indent:field
}

FUNCTION {output:write:string} {
  duplicate$ empty$
    { pop$ pop$ }
    { swap$ "\strng" swap$ wrap:braces *
      swap$ wrap:braces * output:indent:field }
  if$
}

FUNCTION {output:write:range} {
  duplicate$ empty$
    { pop$ pop$ }
    { format.range output:write:field }
  if$
}

FUNCTION {output:write:number} {
  duplicate$ empty$
    { pop$ pop$ }
    { duplicate$ is.number
        'skip$
        { swap$ warning:invalid "" }
      if$
      output:write:field
    }
  if$
}

FUNCTION {output:write:gender} {
  duplicate$ empty$
    { pop$ pop$ }
    { 'tempstrga :=
      tempstrga "sf" =
      tempstrga "sm" = or
      tempstrga "sn" = or
      tempstrga "pf" = or
      tempstrga "pm" = or
      tempstrga "pn" = or
      tempstrga "pp" = or
        { tempstrga output:write:field }
        { warning:invalid }
      if$
    }
  if$
}

FUNCTION {output:write:verb} {
  duplicate$ empty$
    { pop$ pop$ }
    { 'tempstrga :=
      "\verb" swap$ wrap:braces * output:indent:field
      { tempstrga empty$ not }
        { "\verb " tempstrga #1 ctrl.maxline #8 - substring$ * output:indent:field
          tempstrga ctrl.maxline #7 - global.max$ substring$ 'tempstrga :=
        }
      while$
      "\endverb" output:indent:field }
  if$
}

FUNCTION {output:write:name:last} {
  templist tempctra "{ll}" format.name$
  duplicate$ 'tempstrga :=
  wrap:braces
  templist tempctra
  ctrl.terseinits
    { "{l{}}" format.name$ }
    { "{l.}"  format.name$
      duplicate$ tempstrga "." * =
        { duplicate$ text.length$ #1 - text.prefix$ }
        'skip$
      if$
    }
  if$
  wrap:braces *
}

FUNCTION {output:write:name:first} {
  templist tempctra "{ff}" format.name$
  duplicate$ 'tempstrga :=
  wrap:braces
  templist tempctra
  ctrl.terseinits
    { "{f{}}" format.name$ }
    { "{f.}"  format.name$
      duplicate$ tempstrga "." * =
        { duplicate$ text.length$ #1 - text.prefix$ }
        'skip$
      if$
    }
  if$
  wrap:braces *
}

FUNCTION {output:write:name:prefix} {
  templist tempctra "{vv}" format.name$
  duplicate$ 'tempstrga :=
  duplicate$ duplicate$ text.length$ duplicate$ substring$ "'" =
    { #1 'tempctrc := }
    { #0 'tempctrc := }
  if$
  wrap:braces
  templist tempctra
  ctrl.terseinits
    { "{v{}}" format.name$ }
    { "{v.}"  format.name$
      tempctrc
        { duplicate$ text.length$ #1 - text.prefix$ "'" * }
        { duplicate$ tempstrga "." * =
            { duplicate$ text.length$ #1 - text.prefix$ }
            'skip$
          if$
        }
      if$
    }
  if$
  wrap:braces *
}

FUNCTION {output:write:name:suffix} {
  templist tempctra "{jj}" format.name$
  duplicate$ 'tempstrga :=
  wrap:braces
  templist tempctra
  ctrl.terseinits
    { "{j{}}" format.name$ }
    { "{j.}"  format.name$
      duplicate$ tempstrga "." * =
        { duplicate$ text.length$ #1 - text.prefix$ }
        'skip$
      if$
    }
  if$
  wrap:braces *
}

FUNCTION {output:write:name} {
  duplicate$ empty$
    { pop$ pop$ }
    { 'templist :=
      'tempstrga :=
      #1 'tempctra :=
      templist num.names$ 'tempctrb :=
      templist andothers
        { tempctrb #1 - 'tempctrb :=
          "more" tempstrga * #1 output:write:bool
        }
        'skip$
      if$
      "\name" tempstrga wrap:braces *
      tempctrb int.to.str$ wrap:braces *
      "{%" * output:indent:field
      { tempctrb #0 > }
        { "{" output:write:name:last   * "%"  * output:indent:subfield
          " " output:write:name:first  * "%"  * output:indent:subfield
          " " output:write:name:prefix * "%"  * output:indent:subfield
          " " output:write:name:suffix * "}%" * output:indent:subfield
          tempctra #1 + 'tempctra :=
          tempctrb #1 - 'tempctrb :=
        }
      while$
      "}" output:indent:field
    }
  if$
}

FUNCTION {output:write:list} {
  duplicate$ empty$
    { pop$ pop$ }
    { 'templist :=
      'tempstrga :=
      templist num.names$ 'tempctra :=
      templist andothers
        { tempctra #1 - 'tempctra :=
          "more" tempstrga * #1 output:write:bool
        }
        'skip$
      if$
      "\list" tempstrga wrap:braces *
      tempctra int.to.str$ wrap:braces *
      "{%" * output:indent:field
      #1 'tempctra :=
      #1 'tempctrb :=
      #0 'tempctrc :=
      { templist normalize tempctrb global.max$ substring$ num.names$ #0 > }
        { templist tempctrb #1 substring$ "{" =
	    { tempctrc #1 + 'tempctrc :=
	      tempctrb #1 + 'tempctrb := }
	    { templist tempctrb #1 substring$ "}" =
		{ tempctrc #1 - 'tempctrc :=
		  tempctrb #1 + 'tempctrb := }
		{ templist tempctrb #5 substring$
        	  duplicate$ " AND " =
        	  swap$      " and " =
        	  or
		  tempctrc #1 <
		  and
        	    { templist tempctra tempctrb tempctra - substring$
        	      wrap:braces "%" * output:indent:subfield
        	      tempctrb #5 + duplicate$
        	      'tempctra :=
        	      'tempctrb :=
        	    }
        	    { tempctrb #1 + 'tempctrb := }
        	  if$
		}
              if$
	    }
          if$
        }
      while$
      templist tempctra global.max$ substring$
      duplicate$ "others" =
        { pop$ }
        { wrap:braces "%" * output:indent:subfield }
      if$
      "}" output:indent:field
    }
  if$
}

FUNCTION {output:specials} {
  entryset empty$
    'skip$
    { ctrl:set
        { "\set"   }
        { "\inset" }
      if$
      entryset wrap:braces * output:indent:field 
    }
  if$
  xref empty$
    'skip$
    { "\xref" xref wrap:braces * output:indent:field }
  if$
  keywords empty$
    'skip$
    { "\keyw" keywords wrap:braces * output:indent:field }
  if$
  "entrysubtype"    entrysubtype    output:write:field
  "crossref"        crossref        output:write:string
  "execute"         execute         output:write:field
  "namehash"        namehash        output:write:string
  "fullhash"        fullhash        output:write:string
  "gender"          gender          output:write:gender
  "shorthand"       shorthand       output:write:field
  shorthand empty$
    { label }
    { shorthand }
  if$
  "label"           swap$           output:write:field
  ctrl.labelalpha
    { "labelalpha"  labelalpha      output:write:field
      "extraalpha"  extraalpha      output:write:field
    }
    'skip$
  if$
  ctrl:labelyear
  dateyear empty$ not
  and
    { "labelyear"
      dateyear
      dateendyear empty$
        'skip$
        { dateyear dateendyear =
            'skip$
            { dateendyear open.ended =
                'skip$
                { "\bibdatedash " * dateendyear * }
              if$
            }
          if$
        }
      if$
      output:write:field
      "extrayear"   extrayear       output:write:field
    }
    'skip$
  if$
  "sortinit"        sortinit        output:write:field
  singletitle
    { "singletitle" #1 output:write:bool }
    'skip$
  if$
  ctrl.uniquename
    { "uniquename"  uniquename      output:write:count }
    'skip$
  if$
}

FUNCTION {output:names} {
  "author"          author          output:write:name
  "authortype"      authortype      output:write:field
  "shortauthor"     shortauthor     output:write:name
  "bookauthor"      bookauthor      output:write:name
  "editor"          editor          output:write:name
  "editortype"      editortype      output:write:field
  "editora"         editora         output:write:name
  "editoratype"     editoratype     output:write:field
  "editorb"         editorb         output:write:name
  "editorbtype"     editorbtype     output:write:field
  "editorc"         editorc         output:write:name
  "editorctype"     editorctype     output:write:field
  "shorteditor"     shorteditor     output:write:name
  "translator"      translator      output:write:name
  "annotator"       annotator       output:write:name
  "commentator"     commentator     output:write:name
  "introduction"    introduction    output:write:name
  "foreword"        foreword        output:write:name
  "afterword"       afterword       output:write:name
  "holder"          holder          output:write:name
}

FUNCTION {output:lists} {
  "language"        language        output:write:list
  "organization"    organization    output:write:list
  "origlocation"    origlocation    output:write:list
  "origpublisher"   origpublisher   output:write:list
  "publisher"       publisher       output:write:list
}

FUNCTION {output:fields.1} {
  "abstract"        abstract        output:write:multi
  "addendum"        addendum        output:write:field
  "bookpagination"  bookpagination  output:write:field
  "booksubtitle"    booksubtitle    output:write:field
  "booktitleaddon"  booktitleaddon  output:write:field
  "booktitle"       booktitle       output:write:field
  "chapter"         chapter         output:write:field
  "doi"             doi             output:write:verb
  "edition"         edition         output:write:field
  "eid"             eid             output:write:field
  "eprint"          eprint          output:write:verb
  "eventtitle"      eventtitle      output:write:field
  "howpublished"    howpublished    output:write:field
  "hyphenation"     hyphenation     output:write:field
  "indexsorttitle"  indexsorttitle  output:write:field
  "indextitle"      indextitle      output:write:field
  "isan"            isan            output:write:field
  "isbn"            isbn            output:write:field
  "ismn"            ismn            output:write:field
}

FUNCTION {output:fields.2} {
  "isrn"            isrn            output:write:field
  "issn"            issn            output:write:field
  "issue"           issue           output:write:field
  "issuesubtitle"   issuesubtitle   output:write:field
  "issuetitle"      issuetitle      output:write:field
  "iswc"            iswc            output:write:field
  "journalsubtitle" journalsubtitle output:write:field
  "library"         library         output:write:field
  "mainsubtitle"    mainsubtitle    output:write:field
  "maintitleaddon"  maintitleaddon  output:write:field
  "maintitle"       maintitle       output:write:field
  "nameaddon"       nameaddon       output:write:field
  "note"            note            output:write:field
  "number"          number          output:write:field
  "origlanguage"    origlanguage    output:write:field
  "origtitle"       origtitle       output:write:field
  "pages"           pages           output:write:range
  "pagetotal"       pagetotal       output:write:range
  "pagination"      pagination      output:write:field
  "part"            part            output:write:range
}

FUNCTION {output:fields.3} {
  "pubstate"        pubstate        output:write:field
  "reprinttitle"    reprinttitle    output:write:field
  "series"          series          output:write:field
  "shorthandintro"  shorthandintro  output:write:field
  "shortjournal"    shortjournal    output:write:field
  "shortseries"     shortseries     output:write:field
  "shorttitle"      shorttitle      output:write:field
  "subtitle"        subtitle        output:write:field
  "titleaddon"      titleaddon      output:write:field
  "title"           title           output:write:field
  "url"             url             output:write:verb
  "venue"           venue           output:write:field
  "version"         version         output:write:field
  "volumes"         volumes         output:write:field
  "volume"          volume          output:write:field
}

FUNCTION {output:dates.1} {
  "date" date split.date
  "day"      swap$ output:write:field
  duplicate$ empty$
    { month empty$
        'skip$
        { month is.number
            { month str.to.int
              duplicate$  #0 >
              swap$      #13 <
              and
                { pop$ month #2 pad.number  }
                { "month" warning:invalid }
              if$
            }
            { "month" warning:invalid }
          if$
        }
      if$
    }
    { month empty$
        'skip$
        { "month" "date" warning:duplicate }
      if$
    }
  if$
  "month"    swap$ output:write:field
  duplicate$ empty$
    { year empty$
        'skip$
        { pop$ year }
      if$
    }
    { year empty$
        'skip$
        { "year" "date" warning:duplicate }
      if$
    }
  if$
  "year"     swap$ output:write:field
  "endday"   swap$ output:write:field
  "endmonth" swap$ output:write:field
  "endyear"  swap$ output:write:year
}

FUNCTION {output:dates.2} {
  "origdate" origdate split.date
  "origday"       swap$ output:write:field
  "origmonth"     swap$ output:write:field
  "origyear"      swap$ output:write:field
  "origendday"    swap$ output:write:field
  "origendmonth"  swap$ output:write:field
  "origendyear"   swap$ output:write:year
  "eventdate" eventdate split.date
  "eventday"      swap$ output:write:field
  "eventmonth"    swap$ output:write:field
  "eventyear"     swap$ output:write:field
  "eventendday"   swap$ output:write:field
  "eventendmonth" swap$ output:write:field
  "eventendyear"  swap$ output:write:year
  "urldate" urldate split.date
  "urlday"        swap$ output:write:field
  "urlmonth"      swap$ output:write:field
  "urlyear"       swap$ output:write:field
  "urlendday"     swap$ output:write:field
  "urlendmonth"   swap$ output:write:field
  "urlendyear"    swap$ output:write:year
}

FUNCTION {output:user} {
  "namea"           namea           output:write:name
  "nameatype"       nameatype       output:write:field
  "nameb"           nameb           output:write:name
  "namebtype"       namebtype       output:write:field
  "namec"           namec           output:write:name
  "namectype"       namectype       output:write:field
  "lista"           lista           output:write:list
  "listb"           listb           output:write:list
  "listc"           listc           output:write:list
  "listd"           listd           output:write:list
  "liste"           liste           output:write:list
  "listf"           listf           output:write:list
  "usera"           usera           output:write:field
  "userb"           userb           output:write:field
  "userc"           userc           output:write:field
  "userd"           userd           output:write:field
  "usere"           usere           output:write:field
  "userf"           userf           output:write:field
  "verba"           verba           output:write:verb
  "verbb"           verbb           output:write:verb
  "verbc"           verbc           output:write:verb
}

FUNCTION {output:warning} {
  warningmsg empty$
    'skip$
    { "\warn" warningmsg wrap:braces * output:indent:field }
  if$
}

FUNCTION {output:compat.1} {
  "location" location
  duplicate$ empty$
    { pop$ address }
    { address empty$
        'skip$
        { "address" "location" warning:duplicate }
      if$
    }
  if$
  output:write:list
  "institution" institution
  duplicate$ empty$
    { pop$ school }
    { school empty$
        'skip$
        { "school" "institution" warning:duplicate }
      if$
    }
  if$
  output:write:list
  "file" file
  duplicate$ empty$
    { pop$ pdf }
    { pdf empty$
        'skip$
        { "pdf" "file" warning:duplicate }
      if$
    }
  if$
  output:write:verb
}

FUNCTION {output:compat.2} {
  "type" type
  duplicate$ empty$
    { type$ "patent"        =
      type$ "techreport"    = or
      type$ "phdthesis"     = or
        { pop$ type$ }
        { type$ "mastersthesis" =
            { pop$ "mathesis" }
            'skip$
          if$
        }
      if$
    }
    'skip$
  if$
  output:write:field
  "journaltitle" journaltitle
  duplicate$ empty$
    { pop$ journal }
    { journal empty$
        'skip$
        { "journal" "journaltitle" warning:duplicate }
      if$
    }
  if$
  output:write:field
  "annotation" annotation
  duplicate$ empty$
    { pop$ annote }
    { annote empty$
        'skip$
        { "annote" "annotation" warning:duplicate }
      if$
    }
  if$
  output:write:multi
}

FUNCTION {output:compat.3} {
  "eprinttype" eprinttype
  duplicate$ empty$
    { pop$ archiveprefix }
    { archiveprefix empty$
        'skip$
        { "archiveprefix" "eprinttype" warning:duplicate }
      if$
    }
  if$
  output:write:field
  "eprintclass" eprintclass
  duplicate$ empty$
    { pop$ primaryclass }
    { primaryclass empty$
        'skip$
        { "primaryclass" "eprintclass" warning:duplicate }
      if$
    }
  if$
  output:write:field
}

FUNCTION {output:debug} {
  "% sort.key$ = " sort.key$ * maxline write$ newline$
  sort.year empty$
    'skip$
    { "% sort.year = " sort.year * maxline write$ newline$ }
  if$
  sort.alph empty$
    'skip$
    { "% sort.alph = " sort.alph * maxline write$ newline$ }
  if$
}

FUNCTION {output:entry} {
  'tempstrga :=
  newline$
  ctrl.debug
    { output:debug }
    'skip$
  if$
  "\entry"
  push:cite wrap:braces *
  tempstrga wrap:braces *
  entryoptions wrap:braces *
  write$ newline$
  output:names
  output:lists
  output:specials
  output:fields.1
  output:fields.2
  output:fields.3
  output:compat.1
  output:compat.2
  output:compat.3
  output:dates.1
  output:dates.2
  output:user
  output:warning
  "\endentry" write$ newline$
}

FUNCTION {control}        { skip$ }
FUNCTION {set}            { type$ output:entry }

FUNCTION {article}        { type$ output:entry }
FUNCTION {book}           { type$ output:entry }
FUNCTION {bookinbook}     { type$ output:entry }
FUNCTION {booklet}        { type$ output:entry }
FUNCTION {collection}     { type$ output:entry }
FUNCTION {inbook}         { type$ output:entry }
FUNCTION {incollection}   { type$ output:entry }
FUNCTION {inproceedings}  { type$ output:entry }
FUNCTION {manual}         { type$ output:entry }
FUNCTION {misc}           { type$ output:entry }
FUNCTION {online}         { type$ output:entry }
FUNCTION {patent}         { type$ output:entry }
FUNCTION {periodical}     { type$ output:entry }
FUNCTION {proceedings}    { type$ output:entry }
FUNCTION {report}         { type$ output:entry }
FUNCTION {suppbook}       { type$ output:entry }
FUNCTION {suppcollection} { type$ output:entry }
FUNCTION {suppperiodical} { type$ output:entry }
FUNCTION {thesis}         { type$ output:entry }
FUNCTION {unpublished}    { type$ output:entry }

FUNCTION {artwork}        { type$ output:entry }
FUNCTION {audio}          { type$ output:entry }
FUNCTION {commentary}     { type$ output:entry }
FUNCTION {image}          { type$ output:entry }
FUNCTION {inreference}    { type$ output:entry }
FUNCTION {jurisdiction}   { type$ output:entry }
FUNCTION {legal}          { type$ output:entry }
FUNCTION {legislation}    { type$ output:entry }
FUNCTION {letter}         { type$ output:entry }
FUNCTION {movie}          { type$ output:entry }
FUNCTION {music}          { type$ output:entry }
FUNCTION {performance}    { type$ output:entry }
FUNCTION {reference}      { type$ output:entry }
FUNCTION {review}         { type$ output:entry }
FUNCTION {software}       { type$ output:entry }
FUNCTION {standard}       { type$ output:entry }
FUNCTION {video}          { type$ output:entry }

FUNCTION {customa}        { type$ output:entry }
FUNCTION {customb}        { type$ output:entry }
FUNCTION {customc}        { type$ output:entry }
FUNCTION {customd}        { type$ output:entry }
FUNCTION {custome}        { type$ output:entry }
FUNCTION {customf}        { type$ output:entry }

FUNCTION {conference}     { "inproceedings" output:entry }
FUNCTION {electronic}     { "online"        output:entry }
FUNCTION {mastersthesis}  { "thesis"        output:entry }
FUNCTION {other}          { "misc"          output:entry }
FUNCTION {phdthesis}      { "thesis"        output:entry }
FUNCTION {techreport}     { "report"        output:entry }
FUNCTION {www}            { "online"        output:entry }
FUNCTION {default.type}   { "misc"          output:entry }

% -------------------------------------------------------------------
% Input
% -------------------------------------------------------------------

FUNCTION {input:control:parse} {
  'tempstrga :=
  "" 'tempstrgb :=
  #1 'tempctra  :=
  { tempstrga empty$ not
    tempctra and }
    { tempstrga #1 #1 substring$ ":" =
        { #0 'tempctra := }
        { tempstrgb tempstrga #1 #1 substring$ * 'tempstrgb := }
      if$
      tempstrga #2 global.max$ substring$ 'tempstrga :=
    }
  while$
  tempstrga
  tempstrgb
}

FUNCTION {input:control:options} {
  input:control:parse str.to.int
}

FUNCTION {input:control:version} {
  input:control:parse
  "$Revision: 0.9e $"
  #12 entry.max$ substring$
  #-3 entry.max$ substring$
  'tempstrga :=
  duplicate$ tempstrga =
    { pop$ }
    { "Version mismatch: biblatex.bst=" tempstrga *
      ", biblatex.sty=" * swap$ * warning$
      pop$ "" }
  if$
}

FUNCTION {input:control} {
  options empty$
    'skip$
    { options input:control:version
      duplicate$ empty$
        { pop$ }
        { input:control:options 'ctrl.debug :=
          input:control:options 'ctrl.bibtex8 :=
          input:control:options 'ctrl.cssort :=
          input:control:options 'ctrl.terseinits :=
          input:control:options 'ctrl.useprefix :=
          input:control:options 'ctrl.useauthor :=
          input:control:options 'ctrl.useeditor :=
          input:control:options 'ctrl.usetranslator :=
          input:control:options 'ctrl.labelalpha :=
          input:control:options 'ctrl.labelyear :=
          input:control:options 'ctrl.singletitle :=
          input:control:options 'ctrl.uniquename :=
          input:control:options 'ctrl.sorting :=
          input:control:options 'ctrl.sortlos :=
          input:control:options 'ctrl.maxnames :=
          input:control:options 'ctrl.minnames :=
          input:control:options 'ctrl.maxline :=
          'ctrl.alphaothers :=
        }
      if$
      ctrl.maxline #49 <
        { #49 'ctrl.maxline := }
        { ctrl.maxline #79 >
            { #79 'ctrl.maxline := }
            'skip$
          if$
        }
      if$
    }
  if$
}

FUNCTION {input:options:add} {
  entryoptions empty$
    'skip$
    { entryoptions ", " * 'entryoptions := }
  if$
  entryoptions swap$ * 'entryoptions :=
  duplicate$ empty$
    { pop$ }
    { "=" swap$ * entryoptions swap$ * 'entryoptions := }
  if$
}

FUNCTION {input:options:known} {
  duplicate$ empty$
    { tempstrgb input:options:add
      #1 }
    { duplicate$ "true" =
        { pop$ "" tempstrgb input:options:add 
          #1 }
        { duplicate$ tempstrgb input:options:add
          bol.to.int 
        }
      if$
    }
  if$
}

FUNCTION {input:options:parse} {
  'tempstrgb :=
  tempstrgb "useprefix" =
    { input:options:known 'useprefix := }
    { tempstrgb "useauthor" =
        { input:options:known 'useauthor := }
        { tempstrgb "useeditor" =
            { input:options:known 'useeditor := }
            { tempstrgb "usetranslator" =
                { input:options:known 'usetranslator := }
                { tempstrgb "skipbib" =
                    { input:options:known 'skipbib := }
                    { tempstrgb "skiplos" =
                        { input:options:known 'skiplos := }
                        { tempstrgb "skiplab" =
                            { input:options:known 'skiplab := }
                            { tempstrgb "dataonly" = 
                                { input:options:known 
                                  duplicate$ 'skipbib :=
                                  duplicate$ 'skiplos := 
                                             'skiplab := 
                                }
                                { tempstrgb input:options:add }
                              if$
                            }
                          if$
                        }
                      if$
                    }
                  if$
                }
              if$
            }
          if$
        }
      if$
    }
  if$
}

FUNCTION {input:options:extract} {
  'tempstrgb :=
  #1 'tempctrb :=
  { tempstrgb text.length$ #0 > }
    { tempstrgb tempctrb #1 substring$ "=" =
        { tempstrgb tempctrb #1 + global.max$ substring$
          tempstrgb #1 tempctrb #1 - substring$
          input:options:parse
          "" 'tempstrgb :=
        }
        { tempstrgb text.length$ tempctrb =
            { "" tempstrgb input:options:parse
              "" 'tempstrgb :=
            }
            { tempctrb #1 + 'tempctrb := }
          if$
        }
      if$
    }
  while$
}

FUNCTION {input:options} {
  options 'tempstrga :=
  #1 'tempctra :=
  { tempstrga text.length$ #0 > }
    { tempstrga tempctra #1 substring$ "," =
        { tempstrga #1 tempctra #1 - substring$ input:options:extract
          tempctra #1 + 'tempctra :=
          { tempstrga tempctra #1 substring$ " " =
            tempctra tempstrga text.length$ > not
            and
          }
            { tempctra #1 + 'tempctra := }
          while$
          tempstrga tempctra global.max$ substring$ 'tempstrga :=
          #1 'tempctra :=
        }
        { tempstrga text.length$ tempctra =
            { tempstrga input:options:extract
              "" 'tempstrga :=
            }
            { tempctra #1 + 'tempctra := }
          if$
        }
      if$
    }
  while$
}

FUNCTION {input:iterate} {
  ctrl:control
    { input:control }
    { citecount #1 + 'citecount :=
      citecount int.to.str$ #9 pad.number 'sortkey.nosort :=
      ctrl.useprefix 'useprefix :=
      ctrl.useauthor 'useauthor :=
      ctrl.useeditor 'useeditor :=
      ctrl.usetranslator 'usetranslator :=
      ctrl.singletitle
        { #1 'singletitle := }
        'skip$
      if$
      options empty$
        'skip$
        { input:options }
      if$
      ctrl:set entryset empty$ or
        'skip$
        { #1 'skipbib :=
          #1 'skiplos := 
          #1 'skiplab := 
        }
      if$
      "date" date split.date
      pop$ pop$ 'dateyear    :=
      pop$ pop$ 'dateendyear :=
      dateyear empty$
        { year empty$
            'skip$
            { year 'dateyear := }
          if$
        }
        'skip$
      if$
    }
  if$
}

READ

EXECUTE {initialize}

ITERATE {input:iterate}

% -------------------------------------------------------------------
% Generate labels
% -------------------------------------------------------------------

FUNCTION {makelabel:name:format} {
  'templist :=
  #1 'tempctra :=
  templist num.names$ 'tempctrb :=
  templist andothers
    { tempctrb #1 - 'tempctrb := }
    'skip$
  if$
  tempctrb ctrl.maxnames >
    { ctrl.minnames 'tempctrc := }
    { ctrl.maxnames 'tempctrc := }
  if$
  ""
  { duplicate$ text.length$ entry.max$ #50 - <
    tempctra tempctrc > not and
    tempctrb #0 > and
    }
    { useprefix
        { templist tempctra "{vv}" format.name$
          duplicate$ empty$
            { pop$ "" }
            { "u" change.case$ "t" change.case$ 
              delimiter.3 * }
          if$
        }
        { "" }
      if$
      templist tempctra "{ll}" format.name$ *
      tempctra #1 >
        { delimiter.2 swap$ * }
        'skip$
      if$
      *
      tempctra #1 + 'tempctra :=
      tempctrb #1 - 'tempctrb :=
    }
  while$
  templist andothers
  tempctrb #0 >
  or
    { delimiter.2 * "zzzz" * }
    'skip$
  if$
}

FUNCTION {makelabel:name:uniq} {
  duplicate$ num.names$ #1 =
    { #1
      "{ll}{" delimiter.3 *
      "f}{" delimiter.3 * *
      "v}{" delimiter.3 * *
      "j}" *
      format.name$
    }
    { pop$ "" }
  if$
}

FUNCTION {makelabel:name:full} {
  duplicate$ num.names$ #1 =
    { #1
      "{ll}{" delimiter.3 *
      "ff}{" delimiter.3 * *
      "vv}{" delimiter.3 * *
      "jj}" *
      format.name$
    }
    { pop$ "" }
  if$
}

FUNCTION {makelabel:alpha:format} {
  duplicate$ empty$
    { pop$ "" }
    { 'templist :=
      #1 'tempctra :=
      templist andothers
        { templist num.names$ #1 - 'tempctrb := }
        { templist num.names$ 'tempctrb := }
      if$
      tempctrb ctrl.maxnames >
        { ctrl.minnames 'tempctrb := }
        'skip$
      if$
      tempctrb #1 >
        { ""
          { tempctrb #0 > }
            { templist tempctra "{l{}}" format.name$ *
              tempctra #1 + 'tempctra :=
              tempctrb #1 - 'tempctrb :=
            }
          while$
        }
        { templist #1 "{l{}}" format.name$ }
      if$
      duplicate$ text.length$ #2 <
        { pop$
          useprefix
            { templist #1 "{v{}}" format.name$ #2 text.prefix$
              templist #1 "{ll}"  format.name$ *
            }
            { templist #1 "{ll}" format.name$ }
          if$
          #3 text.prefix$
        }
        'skip$
      if$
    }
  if$
  templist num.names$ ctrl.maxnames >
  templist andothers
  or
    { ctrl.alphaothers * }
    'skip$
  if$
}

FUNCTION {makelabel:alpha:year} {
  dateyear normalize
  #1  #4 substring$
  #-1 #2 substring$
}

FUNCTION {makelabel:hash:format} {
  'templist :=
  #1 'tempctra :=
  templist num.names$ 'tempctrb :=
  templist andothers
    { tempctrb #1 - 'tempctrb := }
    'skip$
  if$
  tempctrb ctrl.maxnames >
    { ctrl.minnames 'tempctrc := }
    { ctrl.maxnames 'tempctrc := }
  if$
  ""
  { tempctra tempctrc > not
    tempctrb #0 >
    and }
    { templist tempctra
      useprefix
        { "{v{}}{l{}}{j{}}{f{}}" }
        { "{l{}}{j{}}{f{}}{v{}}" }
      if$
      format.name$ purify$ *
      tempctra #1 + 'tempctra :=
      tempctrb #1 - 'tempctrb :=
    }
  while$
  templist andothers
  tempctrb #0 >
  or
    { "+" * }
    'skip$
  if$
}

FUNCTION {makelabel:hash:format:full} {
  'templist :=
  #1 'tempctra :=
  templist num.names$ 'tempctrb :=
  templist andothers
    { tempctrb #1 - 'tempctrb := }
    'skip$
  if$
  ""
  { tempctrb #0 > }
    { templist tempctra
      useprefix
        { "{v{}}{l{}}{j{}}{f{}}" }
        { "{l{}}{j{}}{f{}}{v{}}" }
      if$
      format.name$ purify$ *
      tempctra #1 + 'tempctra :=
      tempctrb #1 - 'tempctrb :=
    }
  while$
  templist andothers
    { "+" * }
    'skip$
  if$
}

FUNCTION {makelabel:ctrl:alpha} {
  ctrl:labelalpha
    { label empty$
        { push:cite normalize #1 #3 substring$
          "u" change.case$ "t" change.case$ }
        { label makelabel:alpha:year * }
      if$
    }
    { "" }
  if$
}

FUNCTION {makelabel:ctrl:alpha:format} {
  ctrl:labelalpha
    { label empty$
        { makelabel:alpha:format }
        { pop$ label }
      if$
      makelabel:alpha:year *
    }
    { pop$ "" }
  if$
}

FUNCTION {makelabel:label} {
  push:shortname empty$
    { push:sorttitle 'label.name :=
      makelabel:ctrl:alpha 'labelalpha :=
    }
    { push:shortname
      duplicate$ makelabel:name:format 'label.name :=
      duplicate$ makelabel:hash:format 'namehash :=
      ctrl.uniquename
        { duplicate$ makelabel:name:uniq 'label.uniq := }
        'skip$
      if$
      makelabel:ctrl:alpha:format 'labelalpha :=
    }
  if$
  push:fullname empty$
    'skip$
    { push:fullname makelabel:hash:format:full 'fullhash := }
  if$
}

FUNCTION {makelabel:label:uniq} {
  uniquename #0 =
    'skip$
    { uniquename #1 =
        { label.uniq 'label.name := }
        { push:shortname makelabel:name:full 'label.name := }
      if$
    }
  if$
}

% -------------------------------------------------------------------
% Sort labels
% -------------------------------------------------------------------

FUNCTION {labelsort:label} {
  sortkey:init:label
  makelabel:label
}

FUNCTION {labelsort:main} {
  ctrl:skiplab not
  ctrl.singletitle ctrl.labelyear or
  and
    { label.name normalize delimiter.1 *
      sortkey.year * delimiter.1 *
      push:presort * delimiter.1 *
      sortkey empty$
        { sortkey.name * delimiter.1 * sortkey.title }
        { sortkey }
      if$
      *
      truncate
    }
    { "" }
  if$
  duplicate$
  'sort.key$ :=
  'sort.year :=
}

FUNCTION {labelsort:name} {
  ctrl:skiplab not
  ctrl.uniquename
  and
    { sortkey empty$
        { sortkey.name delimiter.1 * sortkey.title * }
        { sortkey }
      if$
      truncate
    }
    { "" }
  if$
  duplicate$
  'sort.key$ :=
  'sort.year :=
}

FUNCTION {labelsort:alph} {
  ctrl:labelalpha
    { labelalpha normalize delimiter.1 *
      push:presort * delimiter.1 *
      sortkey empty$
        { ctrl.sorting #10 >
          ctrl.sorting #20 <
          and
            { ctrl.sorting #10 - }
            { #2 }
          if$
          sortkey:main:string
        }
        { sortkey }
      if$
      *
      truncate
    }
    { "" }
  if$
  duplicate$
  'sort.key$ :=
  'sort.alph :=
}

FUNCTION {labelsort:hash} {
  ctrl:control
  namehash empty$
  or
    { "zzzz" 'sort.key$ := }
    { namehash normalize delimiter.1 *
      push:shortname duplicate$ empty$
        { pop$ "zzzz" * }
        { sortkey:name:format normalize * }
      if$
      truncate 'sort.key$ :=
    }
  if$
}

FUNCTION {labelsort:fullhash} {
  ctrl:control
  fullhash empty$
  or
    { "zzzz" 'sort.key$ := }
    { fullhash normalize delimiter.1 *
      push:shortname duplicate$ empty$
        { pop$ "zzzz" * }
        { sortkey:name:format normalize * }
      if$
      truncate 'sort.key$ :=
    }
  if$
}

% -------------------------------------------------------------------

FUNCTION {labelsort:init} {
  "" 'last.name  :=
  "" 'last.uniq  :=
  "" 'last.year  :=
  "" 'last.hash  :=
  "" 'last.extra :=
  #0 'last.uniq.num  :=
  #1 'last.extra.num :=
}

FUNCTION {labelsort:main:init} {
  "" 'last.name  :=
}

FUNCTION {labelsort:hash:init} {
  "" 'last.name :=
  #1 'last.extra.num :=
}

FUNCTION {labelsort:namehash:iterate} {
  ctrl:control
  namehash empty$
  or
    'skip$
    { namehash last.hash =
        { push:name:namehash last.name =
            'skip$
            { last.extra.num #1 + 'last.extra.num := }
          if$
          last.extra.num int.to.str$ 'labelhash :=
        }
        { #1  'last.extra.num :=
          "1" 'labelhash  :=
        }
      if$
      namehash 'last.hash :=
      push:name:namehash 'last.name :=
    }
  if$
}

FUNCTION {labelsort:namehash:reverse} {
  ctrl:control
  namehash empty$
  or
    'skip$
    { push:name:namehash last.name =
        { last.extra "1" =
            { "1" 'labelhash := }
            'skip$
          if$
        }
        { last.extra "2" =
            { "1" 'labelhash := }
            'skip$
          if$
        }
      if$
      labelhash 'last.extra :=
      push:name:namehash 'last.name  :=
      namehash labelhash * 'namehash :=
    }
  if$
}

FUNCTION {labelsort:fullhash:iterate} {
  ctrl:control
  fullhash empty$
  or
    'skip$
    { fullhash last.hash =
        { push:name:fullhash last.name =
            'skip$
            { last.extra.num #1 + 'last.extra.num := }
          if$
          last.extra.num int.to.str$ 'labelhash :=
        }
        { #1  'last.extra.num :=
          "1" 'labelhash  :=
        }
      if$
      fullhash 'last.hash :=
      push:name:fullhash 'last.name :=
    }
  if$
}

FUNCTION {labelsort:fullhash:reverse} {
  ctrl:control
  fullhash empty$
  or
    'skip$
    { push:name:fullhash last.name =
        { last.extra "1" =
            { "1" 'labelhash := }
            'skip$
          if$
        }
        { last.extra "2" =
            { "1" 'labelhash := }
            'skip$
          if$
        }
      if$
      labelhash 'last.extra :=
      push:name:fullhash 'last.name  :=
      fullhash labelhash * 'fullhash :=
    }
  if$
}

FUNCTION {labelsort:uniquename} {
  ctrl:skiplab not
  ctrl.uniquename
  and
    { push:shortname num.names$ #1 >
        'skip$
        { push:name:namehash last.hash =
            { last.uniq.num 'uniquename := }
            { label.name last.name =
                { label.uniq last.uniq =
                  ctrl.uniquename #2 =
                  and
                    { #2 'uniquename := }
                    { #1 'uniquename := }
                  if$
                }
                'skip$
              if$
            }
          if$
          label.name 'last.name :=
          label.uniq 'last.uniq :=
          uniquename 'last.uniq.num :=
          push:name:namehash 'last.hash :=
        }
      if$
    }
    'skip$
  if$
}

FUNCTION {labelsort:main:singletitle} {
  ctrl.singletitle
    { label.name last.name =
        { #0 'singletitle := }
        'skip$
      if$
      label.name 'last.name :=
    }
    'skip$
  if$
}

FUNCTION {labelsort:main:year:iterate} {
  ctrl:labelyear
    { label.name
      dateyear empty$
         'skip$
         { " " * dateyear *
           dateendyear empty$
             'skip$
             { dateyear dateendyear =
                 'skip$
                 { dateendyear open.ended =
                     'skip$
                     { "-" * dateendyear * }
                   if$
                 }
               if$
             }
           if$
         }
      if$
      'label.year :=
      label.year last.year =
        { last.extra.num #1 + 'last.extra.num :=
          last.extra.num int.to.str$ 'extrayear :=
        }
        { #1 'last.extra.num :=
          "" 'extrayear :=
          label.year 'last.year :=
        }
      if$
    }
    'skip$
  if$
}

FUNCTION {labelsort:main:year:reverse} {
  ctrl:labelyear
    { last.extra "2" =
        { "1" 'extrayear := }
        'skip$
      if$
      extrayear 'last.extra :=
    }
    'skip$
  if$
}

FUNCTION {labelsort:main:iterate} {
  ctrl:skiplab
    'skip$
    { labelsort:main:singletitle
      labelsort:main:year:iterate
    }
  if$
}

FUNCTION {labelsort:main:reverse} {
  ctrl:skiplab
    'skip$
    { labelsort:main:singletitle
      labelsort:main:year:reverse
    }
  if$
}

FUNCTION {labelsort:alph:iterate} {
  ctrl:labelalpha
    { labelalpha last.year =
        { last.extra.num #1 + 'last.extra.num :=
          last.extra.num int.to.str$ 'extraalpha :=
        }
        { #1 'last.extra.num :=
          "" 'extraalpha :=
        }
      if$
      labelalpha 'last.year :=
    }
    'skip$
  if$
}

FUNCTION {labelsort:alph:reverse} {
  ctrl:labelalpha
    { last.extra "2" =
        { "1" 'extraalpha := }
        'skip$
      if$
      extraalpha 'last.extra :=
      labelalpha empty$
        'skip$
        { extraalpha empty$
            { labelalpha normalize 'sortkey.alpha := }
            { labelalpha normalize extraalpha #4 pad.number * 'sortkey.alpha := }
          if$
        }
      if$
    }
    'skip$
  if$
}

ITERATE {labelsort:label}

EXECUTE {labelsort:init}

ITERATE {labelsort:hash}

SORT

EXECUTE {labelsort:hash:init}

ITERATE {labelsort:namehash:iterate}

EXECUTE {labelsort:hash:init}

REVERSE {labelsort:namehash:reverse}

EXECUTE {labelsort:init}

ITERATE {labelsort:fullhash}

SORT

EXECUTE {labelsort:hash:init}

ITERATE {labelsort:fullhash:iterate}

EXECUTE {labelsort:hash:init}

REVERSE {labelsort:fullhash:reverse}

EXECUTE {labelsort:init}

ITERATE {labelsort:name}

SORT

ITERATE {labelsort:uniquename}

EXECUTE {labelsort:init}

REVERSE {labelsort:uniquename}

ITERATE {makelabel:label:uniq}

EXECUTE {labelsort:init}

ITERATE {labelsort:main}

SORT

EXECUTE {labelsort:init}

EXECUTE {labelsort:main:init}

ITERATE {labelsort:main:iterate}

EXECUTE {labelsort:main:init}

REVERSE {labelsort:main:reverse}

EXECUTE {labelsort:init}

ITERATE {labelsort:alph}

SORT

ITERATE {labelsort:alph:iterate}

REVERSE {labelsort:alph:reverse}

% -------------------------------------------------------------------
% Sort bibliography, write .bbl file
% -------------------------------------------------------------------

FUNCTION {mainsort} {
  ctrl:control
    { "" }
    { sortkey:main }
  if$
  'sort.key$ :=
}

FUNCTION {lossort} {
  ctrl.sortlos
    { shorthand empty$
      ctrl:skiplos or
        { "" }
        { shorthand }
      if$
      truncate
      'sort.key$ :=
    }
    'skip$
  if$
}

ITERATE {mainsort}

SORT

FUNCTION {output:main:begin} {
  "% $ biblatex auxiliary file $"                               write$ newline$
  "% $ biblatex version " "$Revision: 0.9e $"
  #12 entry.max$ substring$ #-3 entry.max$ substring$ * " $" *  write$ newline$
  "% Do not modify the above lines!"                            write$ newline$
  "%"                                                           write$ newline$
  "% This is an auxiliary file used by the 'biblatex' package." write$ newline$
  "% This file may safely be deleted. It will be recreated as"  write$ newline$
  "% required."                                                 write$ newline$
  "%"                                                           write$ newline$
  "\begingroup"                                                 write$ newline$
  "\makeatletter"                                               write$ newline$
  "\@ifundefined{ver@biblatex.sty}"                             write$ newline$
  "  {\@latex@error"                                            write$ newline$
  "     {Missing 'biblatex' package}"                           write$ newline$
  "     {The bibliography requires the 'biblatex' package.}"    write$ newline$
  "      \aftergroup\endinput}"                                 write$ newline$
  "  {}"                                                        write$ newline$
  "\endgroup"                                                   write$ newline$
}

FUNCTION {output:main:preamble} {
  preamble$ empty$
    'skip$
    { newline$
      "\preamble{%" write$ newline$
      preamble$ write$ newline$
      "}" write$ newline$
    }
  if$
}

FUNCTION {output:main:end} {
  newline$
  "\endinput" write$ newline$
}

FUNCTION {output:los:begin} {
  newline$
  "\lossort" write$ newline$
}

FUNCTION {output:los:iterate} {
  shorthand empty$
  ctrl:skiplos or
    'skip$
    { "  \key{" push:cite * "}" * write$ newline$ }
  if$
}

FUNCTION {output:los:end} {
  "\endlossort" write$ newline$
}


EXECUTE {output:main:begin}

EXECUTE {output:main:preamble}

ITERATE {call.type$}

ITERATE {lossort}

SORT

EXECUTE {output:los:begin}

ITERATE {output:los:iterate}

EXECUTE {output:los:end}

EXECUTE {output:main:end}

% -------------------------------------------------------------------
