# command  args optional
set dir $env(L2X)

set cmdlist {
  {@writefile        2}
  {" "  0 0 space}
  {# 0 0 hash}
  {' 1 0 acute}
  {& 0 0 amp}
  {% 0 0 percent}
  {LARGE}
  {LaTeX}
  {Large}
  {\"   1 0 umlaut}
  {\$ 0 0 dollar}
  {\\ 0 1 backslash}
  {_}
  {`    1 0 grave}
  {aa}
  {abstract          1}
  {alpha}
  {author            1}
  {begin             1 0 begin r}
  {beta}
  {bibitem           1}
  {bibstyle          1}
  {bibcite           2 0 bibcite e}
  {bibdata           1}
  {bibliography      1}
  {bibliographystyle 1}
  {bf} 
  {c 1}
  {caption           1 1}
  {cdot}
  {center            1}
  {centerline        0 0 1}
  {chapter           1 1}
  {chapter*          1}
  {citation          1}
  {cite              1 1}
  {cite*             1 1}
  {contentsline      3}
  {delta}
  {description}
  {documentclass     1 1}
  {documentstyle     1 1}
  {document}
  {dots}
  {em}
  {end               1}
  {enumerate}
  {figure            1 1}
  {flushleft         1}
  {flushright        1}
  {footnote          1}
  {footnotesize} 
  {gamma} 
  {hline}
  {include           1}
  {input             1}
  {ignorespaces}
  {item              0 1}
  {itemize} 
  {it}
  {label             1}
  {large} 
  {ldots} 
  {lquote}
  {maketitle}
  {mu}
  {newblock}
  {newcommand        2 1 newcommand e}
  {newlabel          2 0 newlabel   e}
  {normalsize} 
  {numberline}
  {pageref           1}
  {paragraph         1 1}
  {par}
  {parbox            2}
  {part              1 1}
  {part*             1}
  {ref               1}
  {relax}
  {rm}
  {rquote}
  {sc}
  {section           1 1}
  {section*          1}
  {sf}
  {small}
  {subsection        1 1}
  {subsection*       1}
  {subsubsection     1 1}
  {subsubsection*    1}
  {table             1 1}
  {tableofcontents}
  {tabular           2 1}
  {textwidth}
  {thebibliography   2 1}
  {tiny}
  {title             1}
  {today} 
  {tt}
  {usepackage        1 1}
  {verb              1}
  {verbatim}
}

set counter(table) 0
set counter(figure) 0

foreach e $cmdlist {
  parser_init [lindex $e 0] [lindex $e 1] \
              [lindex $e 2] [lindex $e 3] [lindex $e 4]
}

# generic routines
#
# call environment with 'begin' or 'end'
proc begin {type opt cmd {arg ""}} {
  eval $cmd begin "{$opt}" $arg
}

proc end {type opt cmd} {
  eval $cmd end $opt
}

# specific routines
# commands are invoked with command type (command, begin, end)
#   and optional and fixed arguments
set authors ""
set title   ""
set llevel  0
set in_tabular 0

proc @writefile {type opt file what} {
  return ""
}

proc abstract {type {opt ""}} {
  if {$type == "begin"} {
    return ".AB\n"
  } else {
    return ".AE\n"
  }
}

proc amp {type opt} {
  return "&"
}
   
proc author {type opt arg} {
  global authors
  set authors $arg
  return ""
}

proc backslash {type opt} {
  global in_tabular
  if {$in_tabular} {return "\n"} {return "\n.br\n"}
}

proc bf {type opt} {
  global prop g
  lappend prop($g) "\n.R\n"
  return "\n.B\n"
}

proc bibcite {type opt arg1 arg2} {
  global c

  set c($arg1) $arg2
  return ""
}

proc bibdata {type opt arg} {
}

proc bibitem {type opt arg} {
  global bcount

  incr bcount
  return "\[$bcount\] "
}

proc bibliography {type opt arg} {
}

proc bibliographystyle {type opt arg} {
}

proc bibstyle {type opt arg} {
}

proc caption {type opt txt} {
  global counter float_type

  if {$float_type == "table"} {
    incr counter($float_type)
    return ".LP
Table $counter($float_type): $txt
"
  } else {
    incr counter($float_type)
    return ".LP
Figure $counter($float_type): $txt
"
  }
}

proc cdot {type {opt ""}} {
  return "."
}

proc center {type {opt ""} {arg ""}} {
  if {$type == "begin"} {return ".ce 100"} {return ".ce 0"}
}
   
proc citation {type opt arg} {
  return ""
}

# \cite{c1, c2, ...}
proc cite {type opt clist} {
  global c

  set clist [split $clist ,]
  foreach e $clist {
    lappend nlist $c([string trim $e])
  }
  return "\[[join $nlist ,]\]"
}

proc contentsline {type opt level text page} {
  return ""
}

proc dash {c} {
  if {$c == 1} {return "-"}
  return "\\*-"
}

proc description {type {opt ""}} {
  global llevel ltype

  set v ""
  if {$type == "begin"} {
    incr llevel
    set ltype($llevel) description
    if {$llevel >= 1} {set v ".RS\n"}
  } else {
    if {$llevel >= 1} {set v ".RE\n"}
    incr llevel -1
  }
  return $v
}

proc dollar {type opt} {
  return "$"
}

proc dots {type opt} {
  return "..."
}

set initial ".nr PO 0
.AM
.pl 100i
.nr LL 7i
.nr HF 0i
.nr FM 0i
.ds CH
.ds CF
.na
"

proc document {type {opt ""}} {
  global initial
  if {$type == "begin"} {return $initial}
  if {$type == "end"}   {return ""}
}

proc documentstyle {type opt arg} {
  global errorInfo dir

  set plist [split $opt ,]
  foreach e $plist {
    if {[catch "source ${e}.tcl" msg]} {
      if {[catch "source ${dir}/ms/${e}.tcl" msg]} {
      }
    }
  }
  return ""
}

proc documentclass {type opt arg} {
}

proc em {type {opt ""}} {
  global prop g

  case $type in {
    begin   {set v "\n.I\n"}
    end     {set v "\n.R\n"}
    command {lappend prop($g) "\n.R\n"; set v "\n.I\n"}
  }
  return $v
}

proc enumerate {type {opt ""}} {
  global llevel ltype lcount

  set v ""
  if {$type == "begin"} {
    incr llevel
    set ltype($llevel) enumerate
    set lcount($llevel) 0
    if {$llevel >= 1} {set v ".RS\n"}
  } else {
    if {$llevel >= 1} {set v ".RE\n"}
    incr llevel -1
  }
  return $v
}

proc figure {type {opt ""}} {
  global float_type

  if {$type == "begin"} {
    set float_type figure
  }
  return ""
}

proc flushleft {type {opt ""}} {
  return ""
}

proc flushright {type {opt ""}} {
  return ""
}

proc footnote {type opt arg} {
  return "\\**\n.FS\n${arg}\n.FE\n" 
}

proc group {type level} {
  global prop g

  set g $level
  if {$type == "begin"} {
    set prop($g) ""
    return ""
  } else {
    set s ""
    foreach e $prop($g) {
      set s "$s$e"
    }
    return $s
  }
}

proc gt {} {
  return ">"
}

proc hash {type opt} {
  return "#"
}

proc hline {type opt} {
  return "_"
}

proc it {type {opt ""}} {
  global prop g
  lappend prop($g) "\n.R\n"
  return "\n.I\n"
}

proc item {type {opt ""}} {
  global llevel ltype lcount

  case $ltype($llevel) in {
    itemize     {
          if {$llevel == 1} {return ".IP \\(bu 2\n"}
          if {$llevel >= 2} {return ".IP - 2\n"}
                }
    enumerate   {
          incr lcount($llevel)
          return ".IP $lcount($llevel).\n"
                }
    description {return ".IP \"$opt \"\n"}
  }
}

proc ignorespaces {type opt} {
}

proc itemize {type {opt ""}} {
  global llevel ltype

  set v ""
  if {$type == "begin"} {
    incr llevel
    set ltype($llevel) itemize
    if {$llevel >= 1} {set v ".RS\n"}
  } else {
    if {$llevel >= 1} {set v ".RE\n"}
    incr llevel -1
  }
  return $v
}

proc label {type opt arg} {
  return ""
}

proc LaTeX {type opt} {
  return "LaTeX"
}

proc ldots {type opt} {
  return "..."
}

proc lquote {} {
  return "\\*Q"
}

proc lt {} {
  return "<"
}

proc maketitle {type opt {arg ""}} {
  global title authors
  return "\n.TL\n$title\n.AU\n$authors\n"
}

proc math {cmd} {
  return ""
}

proc mu {args} {
  return "mu"
}

proc newblock {type opt} {
  return ""
}

# create a new procedure
proc newcommand {type argc cmd f} {
  set cmd [string range $cmd 1 end]
  set out [open "newcommand" w]
  puts $out "proc $cmd \{" nonewline
  lappend args type opt
  for {set i 1} {$i <= $argc} {incr i} {
    lappend args arg$i
  }
  puts $out "$args\} \{"
  regsub -all {\\} $f {\\\\} f
  puts $out "  set x \"$f\""
  for {set i 1} {$i <= $argc} {incr i} {
    puts $out "  regsub -all \#$i \$x \$arg$i x" 
  }
  puts $out "  return \[parse \$x\]"
  puts $out "\}"
  close $out
  source "newcommand"
  exec rm "newcommand"
  parser_init $cmd $argc
  return ""
}

# \newlabel{label}{{1}{9}}
proc newlabel {type opt label sec_pg} {
  global r
  regsub -all {[{}]} $sec_pg " " sec_pg
  set r($label) $sec_pg 
  return ""
}

proc numberline {type opt} {
}

proc par {type opt} {
   return ".PP\n"
}

proc para {} {
  return ""
}

proc pageref {type opt label} {
  global r

  lindex $r($label) 1
}

proc parbox {type opt size txt} {
  $txt
}

proc percent {type opt} {
  return "%"
}

proc relax {type opt} {
}

proc ref {type opt label} {
  global r

  lindex $r($label) 0
}

proc rquote {} {
  return "\\*U"
}

proc section {type opt arg} {
  return ".NH 1
${arg}
.XS
${arg}
.XE
.PP
"
}

proc section* {type opt arg} {
  return "\n.SH\n${arg}\n.PP\n"
}

proc space {type opt} {
  return " "
}

proc subsection {type opt arg} {
  return ".NH 2\n${arg}\n.PP\n"
}

proc subsection* {type opt arg} {
  return ".SH\n${arg}\n.PP\n"
}

proc table {type {opt ""}} {
  global float_type

  if {$type == "begin"} {
    set float_type table
  }
  return ""
}

proc tableofcontents {type {opt ""}} {
}

# We don't use vertical bars since they don't come out right in
# the ASCII version.
proc tabular {type {opt ""} {arg ""}} {
  global in_tabular

  if {$type == "begin"} {
    set in_tabular 1
    set d [split $arg {}]  
    set t "\n.TS\ntab(&);\n"
    foreach e $d {
      case $e in {
        l {set t "$t L"}
        r {set t "$t R"}
        c {set t "$t C"}
        | {set t "$t"}
      }
    }
    return "$t .\n"
  } else {
    set in_tabular 0
    return "\n.TE\n"
  }
}

proc thebibliography {type {opt ""} {arg ""}} {
  global bcount

  if {$type == "begin"} {
    set bcount 0
    return ".NH 1
Bibliography
.XS
Bibliography
.XE
.PP
"
  }
}

proc tie {} {
  return " "
}

proc textwidth {type opt} {
}

proc title {type opt {arg ""}} {
  global title
  set title $arg
  return ""
}

proc today {type opt} {
  return "\\*(DY"
}

proc tt {type opt} {
  global prop g
  lappend prop($g) "\n.R\n"
  return "\n.R\n"
}

proc umlaut {type opt arg} {
  return "${arg}\\*:"
}

proc usepackage {type opt arg} {
  global errorInfo dir

  set plist [split $arg ,]
  foreach e $plist {
    if {[catch "source ./${e}.tcl" msg] && [catch "source ${dir}/ms/${e}.tcl" msg]} {
      puts stderr "$e: $msg"
    }
  }
  return ""
}

proc verb {type opt {arg ""}} {
  if {$type == "command"} {
    parser_suspend verb $arg
  } elseif {$type == "body"} {
    parser_resume
    return "\n.eo\n$opt\n.ec\n"
  }
}

proc verbatim {type {arg ""}} {
  if {$type == "begin"} {
    parser_suspend verbatim "\\end{verbatim}"
    return "\n.LD\001\n"
  } elseif {$type == "body"} {
    return "$arg\n.DE\001"
  }
}

proc _ {type opt} {
  return "_"
}

puts [include command {} -]
