[BACK]Return to tex2mail CVS log [TXT][DIR] Up to [local] / OpenXM_contrib / pari-2.2 / misc

Annotation of OpenXM_contrib/pari-2.2/misc/tex2mail, Revision 1.1

1.1     ! noro        1: #!/usr/bin/perl
        !             2:
        !             3: # $Id: tex2mail.in,v 1.1 2000/10/27 19:13:53 karim Exp $
        !             4: #
        !             5: # Features:
        !             6: #      % at the end of a line followed by \n\n is recognized as end of
        !             7: #      paragraph :-(
        !             8: #
        !             9: # Change log is at bottom.
        !            10: #
        !            11: # Options:
        !            12: #      linelength=75           # Cut at this line
        !            13: #      maxdef=400              # definition loops: croak if many substitutions
        !            14: #      debug=0
        !            15: #      by_par=0                # Expect each paragraph to be terminated
        !            16: #                              # by *exactly* 2 "\n", and do not print
        !            17: #                              # an extra "\n" between paragraphs
        !            18: #      TeX                     # Assume it is not LaTeX
        !            19: #      ragged                  # leave right ragged
        !            20: #      noindent                # assume \noindent everywhere
        !            21:
        !            22: eval 'require "newgetopt.pl";
        !            23:   &NGetOpt("linelength=i","maxdef=i","debug=i","by_par", "TeX",
        !            24:           "ragged", "noindent")'
        !            25:     || warn "Errors during parsing command line options" .
        !            26:        ($@ ? ": $@" : '') . ".\n";
        !            27: $linelength= $opt_linelength || 75;
        !            28: $maxdef= $opt_maxdef || 400;
        !            29: $debug=$opt_debug;
        !            30:
        !            31: $notusualtoks="\\\\" . '\${}^_~&@';
        !            32: $notusualtokenclass="[$notusualtoks]";
        !            33: $usualtokenclass="[^$notusualtoks]";
        !            34: $macro='\\\\([^a-zA-Z]|([a-zA-Z]+\s*))'; # Why \\\\? double interpretation!
        !            35: $active="$macro|\\\$\\\$|$notusualtokenclass";
        !            36: $tokenpattern="$usualtokenclass|$active";
        !            37: $multitokenpattern="$usualtokenclass+|$active";
        !            38:
        !            39:
        !            40: # Format of the record: height,length,baseline,expandable-spaces,string
        !            41: # The string is not terminated by \n, but separated into rows by \n.
        !            42: # height=0 denotes expandable string
        !            43: # Baseline=3 means the 4th row is the baseline
        !            44:
        !            45: sub debug_print_record {
        !            46:   local($h,$l,$b,$xs,$s) = split /,/, shift, 5;
        !            47:   local(@arr) = split /\n/, $s;
        !            48:   print STDERR "len=$l, h=$h, b=$b, exp_sp=$xs.\n";
        !            49:   local($i) = 0;
        !            50:   for (@arr) {
        !            51:     local($lead) = ($i++ == $b) ? 'b [' : '  [';
        !            52:     print STDERR "$lead$_]\n";
        !            53:   }
        !            54:   while ($i < $h) {            # Empty lines may skipped
        !            55:     local($lead) = ($i++ == $b) ? 'b' : '';
        !            56:     print STDERR "$lead\n";
        !            57:   }
        !            58: }
        !            59:
        !            60: # Takes length and a record, returns 2 records
        !            61:
        !            62: sub cut {
        !            63:   local($length)=(shift);
        !            64:   local($h,$l,$b,$sp,$str)=split(/,/,shift,5);
        !            65:   local($st1,$st2)=("","");
        !            66:   local($sp1,$sp2,$first,$l2)=(0,0,1,$l-$length);
        !            67:   return (shift,&empty) if $l2<0;
        !            68:   if ($h) {
        !            69:     for (split(/\n/,$str,$h)) {
        !            70:       if (!$first) {
        !            71:         $st1 .= "\n";
        !            72:         $st2 .= "\n";
        !            73:       } else {$first=0;}
        !            74:       $st1 .= substr($_,0,$length);
        !            75:       $st2 .= substr($_,$length);
        !            76:     }
        !            77:   } else {
        !            78:     $st1 = substr($str,0,$length);
        !            79:     $st2 = substr($str,$length);
        !            80:     #if ($sp && ($st1 =~ /(\S)(\s+\S*)$/)) {
        !            81:     # $st2 = $2 . $st2;
        !            82:     # $st1 = $` . $1;
        !            83:     # $sp1 = ($st1 =~ /(\s)/g);
        !            84:     # $sp2 = ($st2 =~ /(\s)/g);
        !            85:     #}
        !            86:   }
        !            87:   return ("$h,$length,$b,$sp1,$st1","$h,$l2,$b,$sp2,$st2");
        !            88: }
        !            89:
        !            90: # Outputs a record
        !            91:
        !            92: sub printrecord {
        !            93:   warn "Printing $_[0]\n__ENDPRINT__\n" if $debug & $debug_record;
        !            94:   local($h,$l,$b,$sp,$str)=split(/,/,shift,5);
        !            95:   print $str,"\n";
        !            96: }
        !            97:
        !            98: # Joins two records
        !            99:
        !           100: sub join {
        !           101:   local($h1,$l1,$b1,$sp1,$str1)=split(/,/,shift,5);
        !           102:   local($h2,$l2,$b2,$sp2,$str2)=split(/,/,shift,5);
        !           103:   $h1 || $h1++;
        !           104:   $h2 || $h2++;
        !           105:   local($h,$l,$b,$sp,$str,@str,@str2)=(0,0,0,$sp1+$sp2,"");
        !           106:   $b = $b1 > $b2 ? $b1 : $b2;
        !           107:   # Calculate space below baseline
        !           108:   $h = $h1-$b1 > $h2-$b2 ? $h1-$b1 : $h2-$b2;
        !           109:   # And height
        !           110:   $h += $b;
        !           111:   $l=$l1+$l2;
        !           112:   @str="" x $h;
        !           113:   @str[$b-$b1 .. $b-$b1+$h1-1]=split(/\n/,$str1,$h1);
        !           114:   @str2[0..$h2-1]=split(/\n/,$str2,$h2);
        !           115:   unless (length($str2[$b2])) {
        !           116:     $str2[$b2] = ' ' x $l2;    # Needed for length=0 "color" strings
        !           117:                                 # in the baseline.
        !           118:   }
        !           119:   if ($debug & $debug_record && (grep(/\n/,@str) || grep(/\n/,@str2))) {
        !           120:     warn "\\n found in \@str or \@str2";
        !           121:     warn "`$str1', need $h1 rows\n";
        !           122:     warn "`$str2', need $h2 rows\n";
        !           123:   }
        !           124:   # This is may be wrong if a zero-length record with escape sequences
        !           125:   # is appended to with something not on the same row...  But
        !           126:   # apparently, it should be OK for PARI...
        !           127:   for (0..$h2-1) {
        !           128:     $str[$b-$b2+$_] .= " " x ($l1 - length ($str[$b-$b2+$_])) . $str2[$_];
        !           129:   }
        !           130:   return "$h,$l,$b,$sp," . join("\n",@str);
        !           131: }
        !           132:
        !           133: # The current line is contained in the array @out of records and, possibly,
        !           134: # one additional record $last. If $last exists, $islast is set to 1.
        !           135: # The output channel length is contained in $linelength, the accumulated
        !           136: # length of @out and $last is contained in $curlength.
        !           137: # We guaranty that if $curlength>$linelength, then @out is empty.
        !           138:
        !           139: # Gets a length of a record
        !           140:
        !           141: sub length {
        !           142:   (warn "Wrong format of a record `$_[0]'", return 0)
        !           143:       unless $_[0] =~ /^\d+,(\d+)/;
        !           144:   $1;
        !           145: }
        !           146:
        !           147: # Gets a height of a record
        !           148:
        !           149: sub height {
        !           150:   (warn "Wrong format of a record `$_[0]'", return 0)
        !           151:       unless $_[0] =~ /^(\d+),/;
        !           152:   $1;
        !           153: }
        !           154:
        !           155: # Sets baseline of a record, Usage s...(rec,base)
        !           156:
        !           157: sub setbaseline {
        !           158:   (warn("Wrong format of a record `$_[0]'"), return undef)
        !           159:       unless $_[0] =~ s/^(\d+,\d+,)(\d+)/\1$_[1]/;
        !           160: }
        !           161:
        !           162: # The hierarchical structure: the records to work are in the array @out.
        !           163: # The array @chunks keeps the beginning record of the chunks,
        !           164: # The array @level keeps the beginning chunks of the given level.
        !           165: # The last chunk can begin after the last record if this chunk is still empty.
        !           166:
        !           167: # We do not keep the inner structure of the chunk unless it is the last
        !           168: # chunk on the given level.
        !           169:
        !           170: # Each record is a rectangle to output to the "page".
        !           171:
        !           172: # Each chunk is a sequence of records which reflect one finished subgroup
        !           173: # on the given level.
        !           174:
        !           175: # Each level is a sequence of chunks which correspond to a
        !           176: # not-yet-finished group in TeX input.
        !           177:
        !           178:
        !           179: # The parallel to @level array @wait
        !           180: # contains an event we wait to complete the given level of array.
        !           181:
        !           182: # Chunks on a given level
        !           183:
        !           184: # Used to expand spaces
        !           185:
        !           186: sub exp_sp {$c1++;$c2=0 if $c1>$re; return " " x ($c2+$fr+1);}
        !           187:
        !           188: # Outputs the outermost level of the output list (until the start of level 1)
        !           189: # If gets a true argument, does not expand spaces
        !           190:
        !           191: sub print {
        !           192:   warn "Printing...\n" if $debug & $debug_flow;
        !           193:   local($last,$l,$exp) = ($#level? $chunks[$level[1]]-1: $#out);
        !           194:   ($last >=0) || return;
        !           195:   $l=&length($out[0]);
        !           196:   if ($last >= 1) {
        !           197:     for (1..$last) {
        !           198:       $l += &length($out[$_]);
        !           199:     }
        !           200:   }
        !           201:   if ($debug & $debug_length)  {
        !           202:     if ($l != $curlength) {
        !           203:       for (0..$last) {
        !           204:         warn "Wrong lengths Record $_ $out[$_]\n__ENDREC__\n" ;
        !           205:       }
        !           206:     }
        !           207:   }
        !           208:   $curlength=$l;
        !           209:   warn "l=$l, linelength=$linelength, curlength=$curlength\n"
        !           210:     if $debug & $debug_length;
        !           211:  IF_L:
        !           212:  {
        !           213:   if (!shift && ($l=$linelength-$curlength)>=0) {
        !           214:     warn "entered branch for long string\n"
        !           215:       if $debug & $debug_length;
        !           216:     $exp=0;
        !           217:     (($out[$last] =~ s/\s+$//) && ($l+=length($&)))
        !           218:         if $out[$last] =~ /^0,/;
        !           219:     warn "l=$l with whitespace\n"
        !           220:       if $debug & $debug_length;
        !           221:     last IF_L if $l<=0;
        !           222:     local($str,$h,$fr,$re,$c1,$c2,@t);
        !           223:     for (0..$last) {
        !           224:       ($str,$h)=(split(/,/,$out[$_],5))[4,0];
        !           225:       (@t = ($str =~ /( )/g), $exp+=@t) if (!$h);
        !           226:     }
        !           227:     if ($exp) {
        !           228:       $re=$l % $exp;
        !           229:       $fr=int(($l-$re)/$exp);
        !           230:       warn "$l Extra spaces in $exp places, Fr=$fr," .
        !           231:           " Remainder=$re, LL=$linelength, CL=$curlength\n" if $debug & $debug_length;
        !           232:       $c1=0;
        !           233:       $c2=1;
        !           234:       for (0..$last) {
        !           235:         ($str,$h)=(split(/,/,$out[$_],5))[4,0];
        !           236:         unless ($h || $opt_ragged) {
        !           237:           $str =~ s/ /&exp_sp/ge;
        !           238:           $out[$_]=&string2record($str);
        !           239:         }
        !           240:       }
        !           241:     }
        !           242:   }
        !           243:   else {warn "Do not want to expand $l spaces\n" if $debug & $debug_length;}
        !           244:  }
        !           245:   if ($last >= 1) {
        !           246:     for (1..$last) {
        !           247:       $out[0] = &join($out[0],$out[$_]);
        !           248:     }
        !           249:   }
        !           250:   $l=&length($out[0]);
        !           251:   warn "LL=$linelength, CurL=$curlength, OutL=$l\n" if $debug & $debug_length;
        !           252:   &printrecord($out[0]);
        !           253:   $curlength=0;
        !           254:   if ($#out>$last) {
        !           255:     @out=@out[$last+1..$#out];
        !           256:     for (0..$#chunks) {$chunks[$_] -= $last+1;}
        !           257:   } else {
        !           258:     @out=();
        !           259:   }
        !           260:   if ($#level) {
        !           261:     splice(@chunks,1,$level[1]-2);
        !           262:   } else {
        !           263:     @chunks=(0);
        !           264:   }
        !           265: }
        !           266:
        !           267: # Cuts prepared piece and arg into printable parts (unfinished)
        !           268: # Suppose that level==0
        !           269:
        !           270: sub prepare_cut {
        !           271:   warn "Preparing to cut $_[0]\n" if $debug & $debug_flow;
        !           272:   warn "B:Last chunk number $#chunks, last record $#out\n" if $debug & $debug_flow;
        !           273:   (warn "\$#level non 0", return $_[0]) if ($#level!=0);
        !           274:   local($lenadd)=(&length($_[0]));
        !           275:   local($lenrem)=($linelength-$curlength);
        !           276:   if ($lenadd+$curlength<=$linelength) {
        !           277:     warn "No need to cut, extra=$lenrem\n" if $debug & $debug_flow;
        !           278:     return $_[0];
        !           279:   }
        !           280:   # Try to find a cut in the added record before $lenrem
        !           281:   local($rec)=@_;
        !           282:   local($h,$str,$ind,@p)=(split(/,/,$rec,5))[0,4];
        !           283:   local($good)=(0);
        !           284:   if ($h<2) {
        !           285:     while ($lenrem<$lenadd && ($ind=rindex($str," ",$lenrem))>-1) {
        !           286:       warn "Cut found at $ind, lenrem=$lenrem\n" if $debug & $debug_flow;
        !           287:       $good=1;
        !           288:       # $ind=1 means we can cut 2 chars
        !           289:       @p= &cut($ind+1,$rec);
        !           290:       warn "After cut: @p\n" if $debug & $debug_record;
        !           291:       push(@out,$p[0]);
        !           292:       $curlength+=$ind+1;
        !           293:       #if ($#out!=$chunks[$#chunks]) {push(@chunks,$#out);}
        !           294:       &print();
        !           295:       $rec=$p[1];
        !           296:       ($lenadd,$str)=(split(/,/,$rec,5))[1,4];
        !           297:       $lenrem=$linelength;
        !           298:     }
        !           299:     return $rec if $good;
        !           300:   }
        !           301:   # If the added record is too long, there is no sense in cutting
        !           302:   # things we have already, since we will cut the added record anyway...
        !           303:   local($forcedcut);
        !           304:   if ($lenadd > $linelength && $lenrem) {
        !           305:       @p= &cut($lenrem,$rec);
        !           306:       warn "After forced cut: @p\n" if $debug & $debug_record;
        !           307:       push(@out,$p[0]);
        !           308:       $curlength+=$lenrem;
        !           309:       &print();
        !           310:       $rec=$p[1];
        !           311:       ($lenadd,$str)=(split(/,/,$rec,5))[1,4];
        !           312:       $lenrem=$linelength;
        !           313:   }
        !           314:   # Now try to find a cut before the added record
        !           315:   if ($#out>=0 && !$forcedcut) {
        !           316:     for (0..$#out) {
        !           317:       ($h,$str)=(split(/,/,$out[$#out-$_],5))[0,4];
        !           318:       if ($h<2 && ($ind=rindex($str," "))>-1 && ($ind>0 || $_<$#out)) {
        !           319:         warn "Cut found at $ind, in chunk $#out-$_\n"
        !           320:             if $debug & $debug_flow;
        !           321:         # split at given position
        !           322:         @p=&cut($ind+1,$out[$#out-$_]);
        !           323:         $out[$#out-$_]=$p[0];
        !           324:         @p=($p[1],@out[$#out-$_+1..$#out]);
        !           325:         @out=@out[0..$#out-$_];
        !           326: warn "\@p is !", join('!', @p), "!\n\@out is !", join('!', @out), "!\n"
        !           327:             if $debug & $debug_flow;
        !           328:         &print();
        !           329:        warn "did reach that\n"
        !           330:          if $debug & $debug_length;
        !           331:         @out=@p;
        !           332:         $good=1;
        !           333:         $curlength=0;
        !           334:         for (@out) {$curlength+=&length($_);}
        !           335:         last;
        !           336:       }
        !           337:       warn "did reach wow-this\n"
        !           338:        if $debug & $debug_length;
        !           339:     }
        !           340:     warn "did reach this\n"
        !           341:       if $debug & $debug_length;
        !           342:   }
        !           343:   return &prepare_cut if $good;
        !           344:   warn "No cut found!\n" if $debug & $debug_flow;
        !           345:   # If anything else fails use force
        !           346:   &print();
        !           347:   while (&length($rec)>$linelength) {
        !           348:     @p=&cut($linelength,$rec);
        !           349:     @out=($p[0]);
        !           350:     &print();
        !           351:     $rec=$p[1];
        !           352:   }
        !           353:   $curlength=0;
        !           354:   return $rec;
        !           355: }
        !           356:
        !           357: # Adds a record to the output list
        !           358:
        !           359: sub commit {
        !           360:   warn "Adding $_[0]\n" if $debug & $debug_flow;
        !           361:   warn "B:Last chunk number $#chunks, last record $#out\n" if $debug & $debug_flow;
        !           362:   local($rec)=@_;
        !           363:   if ($#level==0) {
        !           364:     local($len)=&length($_[0]);
        !           365:     if ($curlength+$len>$linelength) {
        !           366:       $rec=&prepare_cut;
        !           367:       $len=&length($rec);
        !           368:     }
        !           369:     $curlength+=$len;
        !           370:   }
        !           371:   push(@out,$rec);
        !           372:   if ($#out!=$chunks[$#chunks]) {push(@chunks,$#out);}
        !           373:   warn "a:Last chunk number $#chunks, last record $#out, the first chunk\n" if $debug & $debug_flow;
        !           374:   warn " on the last level=$#level is $level[$#level], waiting for $wait[$#level]\n" if $debug & $debug_flow;
        !           375:   if ($#level && $wait[$#level] == $#chunks-$level[$#level]+1) {
        !           376:     local($sub,$arg)=($action[$#level]);
        !           377:     if ($sub eq "") {&finish($wait[$#level]);}
        !           378:     else {
        !           379:       &callsub($sub);
        !           380:     }
        !           381:   }
        !           382:   warn "curlength=$curlength on level=$#level\n" if $debug & $debug_length;
        !           383: }
        !           384:
        !           385: # Calls a subroutine, possibly with arguments
        !           386:
        !           387: sub callsub {
        !           388:   local($sub)=(shift);
        !           389:   index($sub,";")>=0?
        !           390:     (($sub,$arg)=split(";",$sub,2), &$sub($arg)):
        !           391:       &$sub;
        !           392: }
        !           393:
        !           394: # Simulates Removing a record from the output list (unfinished)
        !           395:
        !           396: sub uncommit {
        !           397:   warn "Deleting...\n" if $debug & $debug_flow;
        !           398:   warn "B:Last chunk number $#chunks, last record $#out\n" if $debug & $debug_flow;
        !           399:   (warn "Nothing to uncommit", return) if $#out<0;
        !           400:   if ($#level==0) {
        !           401:     local($len)=&length($out[$#out]);
        !           402:     $curlength-=$len;
        !           403:   }
        !           404:   local($rec);
        !           405:   $rec=$out[$#out];
        !           406:   $out[$#out]=&empty();
        !           407:   warn "UnCommit: now $chunks[$#chunks] $rec\n__ENDREC__\n"
        !           408:       if $debug & $debug_record;
        !           409:   #if ($#out<$chunks[$#chunks]) {pop(@chunks);}
        !           410:   warn "a:Last chunk number $#chunks, last record $#out, the first chunk\n" if $debug & $debug_flow;
        !           411:   warn " on the last level=$#level is $level[$#level], waiting for $wait[$#level]" if $debug & $debug_flow;
        !           412:   warn "curlength=$curlength on level=$#level\n" if $debug & $debug_length;
        !           413:   return $rec;
        !           414: }
        !           415:
        !           416: # finish($event, $force_one_group)
        !           417:
        !           418: # Finish the inner scope with the event $event. If this scope is empty,
        !           419: # add an empty record.  If finishing the group would bring us to toplevel
        !           420: # and $force_one_group is not set, can break things into chunks to improve
        !           421: # line-breaking.
        !           422:
        !           423: # No additional action is executed
        !           424:
        !           425: sub finish {
        !           426:   warn "Finishing with $_[0]\n" if $debug & $debug_flow;
        !           427:   local($event,$len,$rec)=(shift);
        !           428:   if (($wait[$#level] ne "") && ($wait[$#level] ne $event)) {
        !           429:     warn "Got `$event' while waiting for `$wait[$#wait]', rest=$par";
        !           430:   }
        !           431:   warn "Got finishing event `$event' in the outermost block, rest=$par"
        !           432:       unless $#level;
        !           433:   if ($#out<$chunks[$level[$#level]]) {push(@out,&empty);}
        !           434:   # Make anything after $level[$#level] one chunk if there is anything
        !           435:   warn "B:Last $#chunks, the first on the last level=$#level is $level[$#level]" if $debug & $debug_flow;
        !           436:   $#chunks=$level[$#level]; #if $chunks[$level[$#level]]<=$#out;
        !           437:   local(@t);
        !           438:   if ($#level==1 && !$_[0]) {
        !           439:     @t=@out[$chunks[$#chunks]..$#out];
        !           440:     $#out=$chunks[$#chunks]-1;
        !           441:   }
        !           442:   #  $#chunks-- if $chunks[$#chunks-1]==$chunks[$#chunks];
        !           443:   $#level--;
        !           444:   $#action--;
        !           445:   $#tokenByToken--;
        !           446:   $#wait--;
        !           447:   if ($#level==0 && !$_[0]) {
        !           448:     for (@t) {&commit($_);}
        !           449:   }
        !           450:   warn
        !           451:       "a:Last $#chunks, the first on the last level=$#level is $level[$#level]"
        !           452:            if $debug & $debug_flow;
        !           453:   if ($wait[$#level] == $#chunks-$level[$#level]+1) {
        !           454:     local($sub)=($action[$#level]);
        !           455:     if ($sub eq "") {&finish($wait[$#level]);}
        !           456:     else {&callsub($sub);}
        !           457:   }
        !           458: }
        !           459:
        !           460: # finish level and discard it
        !           461:
        !           462: sub finish_ignore {
        !           463:         warn "Finish_ignoring with $_[0]\n" if $debug & $debug_flow;
        !           464:         local($event,$len)=(shift);
        !           465:         if (($wait[$#level] ne "") && ($wait[$#level] ne $event)) {
        !           466:                 warn "Got `$event' while waiting for `$wait[$#wait]', rest=$par";
        !           467:         }
        !           468:         warn "Got finishing event `$event' in the outermost block, rest=$par" unless $#level;
        !           469:   $#out=$chunks[$level[$#level]]-1;
        !           470:   pop(@level);
        !           471:   pop(@tokenByToken);
        !           472:   pop(@action);
        !           473:   pop(@wait);
        !           474: }
        !           475:
        !           476: # Begin a new level with waiting for $event
        !           477:
        !           478: # Special events: If number, wait this number of chunks
        !           479:
        !           480: sub start {
        !           481:   warn "Beginning with $_[0], $_[1]\n" if $debug & $debug_flow;
        !           482:   warn "B:Last $#chunks, the first on the last level=$#level is $level[$#level]" if $debug & $debug_flow;
        !           483:   if ($chunks[$level[$#level]]<=$#out && $chunks[$#chunks]<=$#out) {
        !           484:     # the last level is non empty
        !           485:     push(@chunks,$#out+1);
        !           486:   }
        !           487:   push(@level,$#chunks);
        !           488:   push(@tokenByToken,0);
        !           489:   $wait[$#level]=shift;
        !           490:   if ($#_<0) {$action[$#level]="";} else {$action[$#level]=shift;}
        !           491:   warn "a:Last $#chunks, the first on the last level=$#level is $level[$#level]" if $debug & $debug_flow;
        !           492: }
        !           493:
        !           494: # Asserts that the given number of chunks exists in the last level
        !           495:
        !           496: sub assertHave {
        !           497:   local($i,$ii)=(shift);
        !           498:   if (($ii=$#chunks-$level[$#level]+1)<$i) {
        !           499:     warn "Too few chunks ($ii) in inner level, expecting $i";
        !           500:     return 0;
        !           501:   }
        !           502:   return 1;
        !           503: }
        !           504:
        !           505: # Takes the last ARGUMENT chunks, collapse them to records
        !           506:
        !           507: sub collapse {
        !           508:   warn "Collapsing $_[0]...\n" if $debug & $debug_flow;
        !           509:   local($i,$ii,$_)=(shift);
        !           510:   if (($ii=$#chunks-$level[$#level]+1)<$i) {
        !           511:     warn "Too few chunks ($ii) in inner level, expecting $i";
        !           512:     $i=$ii;
        !           513:   }
        !           514:   if ($i>0) {
        !           515:     for (0..$i-1) {
        !           516:       &collapseOne($#chunks-$_);
        !           517:     }
        !           518:     for (1..$i-1) {
        !           519:       $chunks[$#chunks-$_+1]=$chunks[$#chunks-$i+1]+$i-$_;
        !           520:     }
        !           521:   }
        !           522: }
        !           523:
        !           524: # Collapses all the chunks on given level
        !           525:
        !           526: sub collapseAll {&collapse($#chunks-$level[$#level]+1);}
        !           527:
        !           528: # Collapses a given chunk in the array @out. No correction of @chunks is
        !           529: # performed
        !           530:
        !           531: sub collapseOne {
        !           532:   local($n)=(shift);
        !           533:   local($out,$last,$_)=($out[$chunks[$n]]);
        !           534:   if ($n==$#chunks) {$last=$#out;} else {$last=$chunks[$n+1]-1;}
        !           535:         warn "Collapsing_one $n, records $chunks[$n]..$last\n"
        !           536:                 if $debug & $debug_flow;
        !           537:   return unless $last>$chunks[$n];
        !           538:   warn "Collapsing chunk $n beginning at $chunks[$n], ending at $last\n" if $debug & $debug_flow;
        !           539:   for ($chunks[$n]+1..$last) {
        !           540:     $out=&join($out,$out[$_]);
        !           541:   }
        !           542:   splice(@out,$chunks[$n],$last+1-$chunks[$n],$out);
        !           543:   # $#out-=$last-$chunks[$n]; #bug in perl?
        !           544:   warn "Collapsed $chunks[$n]: $out[$chunks[$n]]\n__END__\n" if $debug & $debug_record;
        !           545: }
        !           546:
        !           547: # Return an empty record
        !           548:
        !           549: sub empty {
        !           550:   return "0,0,0,0,";
        !           551: }
        !           552:
        !           553: # Commits a record with a sum symbol
        !           554:
        !           555: sub sum {
        !           556:   &commit("4,3,2,0," . <<'EOF');
        !           557: ___
        !           558: \
        !           559:  >
        !           560: /__
        !           561: EOF
        !           562: }
        !           563:
        !           564: # Additional argument specifies if to make not-expandable, not-trimmable
        !           565:
        !           566: sub string2record {
        !           567:   local($h,$sp)=(0);
        !           568:   if ($_[1]) {$h=1;$sp=0;}
        !           569:   else {
        !           570:     $sp=($_[0] =~ /(\s)/g);
        !           571:     $sp || ($sp=0); # Sometimes it is undef?
        !           572:   }
        !           573:   return "$h," . length($_[0]) . ",0,$sp,$_[0]";
        !           574: }
        !           575:
        !           576: # The second argument forces the block length no matter what is the
        !           577: # length the string (for strings with screen escapes).
        !           578:
        !           579: sub record_forcelength {
        !           580:   $_[0] =~ s/^(\d+),(\d+)/$1,$_[1]/;
        !           581: }
        !           582:
        !           583: sub finishBuffer {
        !           584:   while ($#level>0) {&finish("");}
        !           585:   &print(1);
        !           586: }
        !           587:
        !           588: # Takes two records, returns a record that concatenates them vertically
        !           589: # To make fraction simpler, baseline is the last line of the first record
        !           590:
        !           591: sub vStack {
        !           592:   local($h1,$l1,$b1,$sp1,$str1)=split(/,/,shift,5);
        !           593:   local($h2,$l2,$b2,$sp2,$str2)=split(/,/,shift,5);
        !           594:   $h1 || $h1++;
        !           595:   $h2 || $h2++;
        !           596:   local($h,$l,$b)=($h1+$h2, ($l1>$l2 ? $l1: $l2), $h1-1);
        !           597:   warn "\$h1=$h1, \$h2=$h2, Vstacked: $h,$l,$b,0,$str1\n$str2\n__END__\n" if $debug & $debug_record;
        !           598:   return "$h,$l,$b,0,$str1\n$str2";
        !           599: }
        !           600:
        !           601: # Takes two records, returns a record that contains them and forms
        !           602: # SupSub block
        !           603:
        !           604: sub superSub {
        !           605:   local($h1,$l1,$b1,$sp1,$str1)=split(/,/,shift,5);
        !           606:   local($h2,$l2,$b2,$sp2,$str2)=split(/,/,shift,5);
        !           607:   $h1 || $h1++;
        !           608:   $h2 || $h2++;
        !           609:   local($h,$l)=($h1+$h2+1, ($l1>$l2 ? $l1: $l2));
        !           610:   return "$h,$l,$h1,0,$str1\n\n$str2";
        !           611: }
        !           612:
        !           613: # Takes two records, returns a record that contains them and forms
        !           614: # SupSub block
        !           615:
        !           616: sub subSuper {
        !           617:   local($h1,$l1,$b1,$sp1,$str1)=split(/,/,shift,5);
        !           618:   local($h2,$l2,$b2,$sp2,$str2)=split(/,/,shift,5);
        !           619:   $h1 || $h1++;
        !           620:   $h2 || $h2++;
        !           621:   local($h,$l)=($h1+$h2+1, ($l1>$l2 ? $l1: $l2));
        !           622:   return "$h,$l,$h1,0,$str2\n\n$str1";
        !           623: }
        !           624:
        !           625: # Takes the last two records, returns a record that contains them and forms
        !           626: # SupSub block
        !           627:
        !           628: sub f_subSuper {
        !           629:   warn "Entering f_subSuper...\n" if $debug & $debug_flow;
        !           630:   &trim(2);
        !           631:   &collapse(2);
        !           632:   &assertHave(2) || &finish("",1);
        !           633:   &sup_sub(0,1);
        !           634: }
        !           635:
        !           636: sub sup_sub {
        !           637:   local($p1,$p2)=($#out-shift,$#out-shift);
        !           638:   warn "Super $p1 $out[$p1]\nSub $p2 $out[$p2]\n__END__\n" if $debug & $debug_record;
        !           639:   local($h1,$l1,$b1,$sp1,$str1)=split(/,/,$out[$p1],5);
        !           640:   local($h2,$l2,$b2,$sp2,$str2)=split(/,/,$out[$p2],5);
        !           641:   if ($l1==0 && $l2==0) {return;}
        !           642:   $h1 || $h1++;
        !           643:   $h2 || $h2++;
        !           644:   local($h,$l)=($h1+$h2+1, ($l1>$l2 ? $l1: $l2));
        !           645:   $#chunks--;
        !           646:   $#out--;
        !           647:   if ($l1==0) {
        !           648:     $h2++;
        !           649:     $out[$#out]="$h2,$l,0,0,\n$str2";
        !           650:   } elsif ($l2==0) {
        !           651:     $h=$h1+1;
        !           652:     $out[$#out]="$h,$l,$h1,0,$str1\n";
        !           653:   } else {
        !           654:     $out[$#out]="$h,$l,$h1,0,$str1\n\n$str2";
        !           655:   }
        !           656:   warn "a:Last $#chunks, the first on the last level=$#level is $level[$#level]" if $debug & $debug_flow;
        !           657:   &finish(2,1);
        !           658: }
        !           659:
        !           660: # Takes the last two records, returns a record that contains them and forms
        !           661: # SupSub block
        !           662:
        !           663: sub f_superSub {
        !           664:   warn "Entering f_superSub...\n" if $debug & $debug_flow;
        !           665:   &trim(2);
        !           666:   &collapse(2);
        !           667:   &assertHave(2) || &finish("",1);
        !           668:   &sup_sub(1,0);
        !           669: }
        !           670:
        !           671: # digest \begin{...} and similar: handles argument to a subroutine
        !           672: # given as argument
        !           673:
        !           674: sub f_get1 {
        !           675:   warn "Entering f_get1...\n" if $debug & $debug_flow;
        !           676:   (warn "Argument of f_get1 consists of 2 or more chunks", return)
        !           677:       if $#out != $chunks[$#chunks];
        !           678:   local($rec,$sub);
        !           679:   #$rec=&uncommit;
        !           680:   $rec=$out[$#out];
        !           681:   $rec=~s/.*,//;
        !           682:   $sub=shift;
        !           683:   defined $sub ? return &$sub($rec): return $rec;
        !           684: }
        !           685:
        !           686: sub f_begin {
        !           687:   warn "Entering f_begin...\n" if $debug & $debug_flow;
        !           688:   &collapse(1);
        !           689:   &assertHave(1) || &finish("");
        !           690:   local($arg,$env)=(&f_get1());
        !           691:   &finish_ignore(1);
        !           692:   $arg=~s/^\s+//;
        !           693:   $arg=~s/\s+$//;
        !           694:   return if defined $environment_none{$arg};
        !           695:   if (defined ($env=$environment{$arg})) {
        !           696:     local($b,$e)=split(/,/,$env);
        !           697:     for (split(":",$b)) {&callsub($_);}
        !           698:   } else {&puts("\\begin{$arg}");}
        !           699: }
        !           700:
        !           701: sub f_end {
        !           702:   warn "Entering f_end...\n" if $debug & $debug_flow;
        !           703:   &collapse(1);
        !           704:   &assertHave(1) || &finish("");
        !           705:   local($arg,$env)=(&f_get1());
        !           706:   &finish_ignore(1);
        !           707:   $arg=~s/^\s+//;
        !           708:   $arg=~s/\s+$//;
        !           709:   return if defined $environment_none{$arg};
        !           710:   if (defined ($env=$environment{$arg})) {
        !           711:     local($b,$e)=split(/,/,$env,2);
        !           712:     for (split(":",$e)) {&callsub($_);}
        !           713:   } else {&puts("\\end{$arg}");}
        !           714: }
        !           715:
        !           716:
        !           717: sub f_literal_no_length {
        !           718:   warn "Entering f_literal_with_length...\n" if $debug & $debug_flow;
        !           719:   # &trim(1);
        !           720:   &collapse(1);
        !           721:   &assertHave(1) || &finish("",1);
        !           722:   record_forcelength($out[$#out], 0);
        !           723:   &finish(1,1);
        !           724: }
        !           725:
        !           726: sub f_discard {
        !           727:   warn "Entering f_discard...\n" if $debug & $debug_flow;
        !           728:   &finish_ignore($wait[$#level]);
        !           729: }
        !           730:
        !           731: # Takes a number and a record, returns a centered record
        !           732:
        !           733: sub center {
        !           734:   local($len,$left)=(shift,0);
        !           735:         warn "Entering center, ll=$len, rec=$_[0]\n__ENDREC__\n" if $debug & $debug_flow;
        !           736:   #$_[0]; # bug in perl?
        !           737:   local($h1,$l1,$b1,$sp1,$str1)=split(/,/,$_[0],5);
        !           738:   $h1 || $h1++;
        !           739:   if (($left=$len-$l1)<=0) {return $_[0];}
        !           740:   $left=int($left/2);
        !           741:   local($out,$first)=("",1);
        !           742:   for (split(/\n/,$str1,$h1)) {
        !           743:     if ($first) {$first=0;}
        !           744:     else {$out .= "\n";}
        !           745:     $out .= " " x $left . $_;
        !           746:   }
        !           747:   return "$h1,$len,$b1,0,$out";
        !           748: }
        !           749:
        !           750: # Example of radical
        !           751: #<<'EOF';
        !           752: # +--+
        !           753: #\|12
        !           754: #EOF
        !           755: <<EOF;                         # To hide HERE-DOC start above  from old CPerl
        !           756: EOF
        !           757:
        !           758: # Takes the last record, returns a record that contains it and forms
        !           759: # radical block
        !           760:
        !           761: sub f_radical {
        !           762:   warn "Entering f_radical...\n" if $debug & $debug_flow;
        !           763:   &trim(1);
        !           764:   &collapse(1);
        !           765:   &assertHave(1) || &finish("",1);
        !           766:   warn "Radical of $out[$#out]\n__END__\n" if $debug & $debug_record;
        !           767:   local($h,$l,$b)=($out[$#out] =~ /^(\d+),(\d+),(\d+)/g);
        !           768:   $h || $h++;
        !           769:   local($out,$b1,$h1);
        !           770:   $out=&vStack(&string2record(("-" x $l)."+" ),$out[$#out]);
        !           771:   $b1=$b+1;
        !           772:   $h1=$h+1;
        !           773:   #$out =~ s/^(\d+,\d+,)(\d+)/\1$b1/;
        !           774:   &setbaseline($out,$b1);
        !           775:   $out[$#out]=&join("$h1,2,$b1,0, +\n" . (" |\n" x ($h-1)) . '\|',$out);
        !           776:   warn "a:Last $#chunks, the first on the last level=$#level is $level[$#level]" if $debug & $debug_flow;
        !           777:   &finish(1,1);
        !           778: }
        !           779:
        !           780: # Takes the last two records, returns a record that contains them and forms
        !           781: # fraction block
        !           782:
        !           783: sub f_fraction {
        !           784:   warn "Entering f_fraction...\n" if $debug & $debug_flow;
        !           785:   &trim(2);
        !           786:   &collapse(2);
        !           787:   &assertHave(2) || &finish("",1);
        !           788:   warn "Numer `$out[$#out-1]'\nDenom `$out[$#out]'\n__END__\n" if $debug & $debug_record;
        !           789:   local($l1,$l2)=(&length($out[$#out-1]),&length($out[$#out]));
        !           790:   local($len)=(($l1>$l2 ? $l1: $l2));
        !           791:   $out[$#out-1]=&vStack(&vStack(&center($len,$out[$#out-1]),
        !           792:                          &string2record("-" x $len)),
        !           793:                  &center($len,$out[$#out]));
        !           794:   $#chunks--;
        !           795:   $#out--;
        !           796:   warn "a:Last $#chunks, the first on the last level=$#level is $level[$#level]" if $debug & $debug_flow;
        !           797:   &finish(2,1);
        !           798: }
        !           799:
        !           800: sub f_choose {
        !           801:   warn "Entering f_choose...\n" if $debug & $debug_flow;
        !           802:   &trim(2);
        !           803:   &collapse(2);
        !           804:   &assertHave(2) || &finish("",1);
        !           805:   warn "Numer `$out[$#out-1]'\nDenom `$out[$#out]'\n__END__\n" if $debug & $debug_record;
        !           806:   local($l1,$l2)=(&length($out[$#out-1]),&length($out[$#out]));
        !           807:   local($len)=(($l1>$l2 ? $l1: $l2));
        !           808:   $out[$#out]=&vStack(&vStack(&center($len,$out[$#out-1]),
        !           809:                          &string2record(" " x $len)),
        !           810:                  &center($len,$out[$#out]));
        !           811:   $#chunks++;
        !           812:   $#out++;
        !           813:   #warn "a:Last $#chunks, the first on the last level=$#level is $level[$#level]" if $debug & $debug_flow;
        !           814:   $out[$#out - 2] = &string2record("(");
        !           815:   $out[$#out] = &string2record(")");
        !           816:   local($h,$b)=($out[$#out-1] =~ /^(\d+),\d+,(\d+)/)[0,1];
        !           817:   &makehigh($out[$#out-2],$h,$b,0,1);
        !           818:   &makehigh($out[$#out],$h,$b,1,0);
        !           819:   &finish(2,1);
        !           820: }
        !           821:
        !           822:
        !           823: sub f_buildrel {
        !           824:         warn "Entering f_buildrel...\n" if $debug & $debug_flow;
        !           825:   &trim(3);
        !           826:         &collapse(3);
        !           827:         &assertHave(3) || &finish("",1);
        !           828:         warn "What: $out[$#out-2]\nOver $out[$#out]\n__END__\n" if $debug & $debug_record;
        !           829:         local($rec)=($out[$#out-2]);
        !           830:         $out[$#out-2]=$out[$#out];
        !           831:         $#chunks-=2;
        !           832:         $#out-=2;
        !           833:   &f_putover($rec,1);
        !           834:         warn "a:Last $#chunks, the first on the last level=$#level is $level[$#level]" if $debug & $debug_flow;
        !           835:         &finish(3,1);
        !           836: }
        !           837:
        !           838: # Takes two records, returns a record that contains them and forms a
        !           839: # fraction block
        !           840:
        !           841: sub fraction {
        !           842:   local($l1,$l2)=(&length($_[0]),&length($_[1]));
        !           843:   local($len)=(($l1>$l2 ? $l1: $l2));
        !           844:   return &vStack(&vStack(&center($len,shift),
        !           845:                          &string2record("-" x $len)),
        !           846:                  &center($len,shift));
        !           847: }
        !           848:
        !           849: # Commits a given string
        !           850:
        !           851: sub puts {
        !           852:   &commit(&string2record);
        !           853: }
        !           854:
        !           855: # digests an eaten paragraph
        !           856:
        !           857: sub paragraph {
        !           858:   local($par);
        !           859:   $par=<>;
        !           860:   return 0 unless defined $par;
        !           861:   return 1 unless $par =~ /\S/;                        # whitespace only
        !           862:   print "\n" if $secondtime++ && !$opt_by_par;
        !           863:   #$par =~ s/(^|[^\\])%.*\n[ \t]*/\1/g;
        !           864:   $par =~ s/((^|[^\\])(\\\\)*)(%.*\n[ \t]*)+/\1/g;
        !           865:   $par =~ s/\n\s*\n/\\par /g;
        !           866:   $par =~ s/\s+/ /g;
        !           867:   $par =~ s/\s+$//;
        !           868:   $par =~ s/(\$\$)\s+/\1/g;
        !           869:   $par =~ s/\\par\s*$//;
        !           870:   local($defcount,$piece,$pure,$type,$sub,@t,$arg)=(0);
        !           871:   &commit("1,5,0,0,     ")
        !           872:     unless $opt_noindent || ($par =~ s/^\s*\\noindent\s*([^a-zA-Z\s]|$)/\1/);
        !           873:   while ($tokenByToken[$#level] ?
        !           874:       ($par =~ s/^\s*($tokenpattern)//o): ($par =~ s/^($multitokenpattern)//o)) {
        !           875:     warn "tokenByToken=$tokenByToken[$#level], eaten=`$1'\n"
        !           876:         if $debug & $debug_parsing;
        !           877:     if (($piece=$1) =~ /^$usualtokenclass/o) {
        !           878:       # plain piece
        !           879:       &puts($piece);
        !           880:     } else {
        !           881:       # macro or delimiter
        !           882:       ($pure = $piece) =~ s/\s+$//;
        !           883:       if (defined ($type=$type{$pure})) {
        !           884:         if ($type eq "def") {
        !           885:     warn "To many def expansions in a paragraph" if $defcount++==$maxdef;
        !           886:     last if $defcount>$maxdef;
        !           887:     @t=(0);
        !           888:     for (1..$args{$pure}) {
        !           889:       push(@t,&get_balanced());
        !           890:     }
        !           891:     warn "Defined token `$pure' found with $args{$pure} arguments @t[1..$#t]\n"
        !           892:     if $debug & $debug_parsing;
        !           893:     $sub=$def{$pure};
        !           894:     $sub =~ s/(^|[^\\#])#(\d)/$1 . $t[$2]/ge if $args{$pure};
        !           895:     $par=$sub . $par;
        !           896:         } elsif ($type eq "sub") {
        !           897:          $sub=$contents{$pure};
        !           898:          index($sub,";")>=0?
        !           899:            (($sub,$arg)=split(";",$sub,2), &$sub($pure,$arg)):
        !           900:              &$sub($pure);
        !           901:         } elsif ($type =~ /^sub(\d+)$/) {
        !           902:           &start($1,"f_$contents{$pure}");
        !           903:           $tokenByToken[$#level]=1;
        !           904:         } elsif ($type =~ /^get(\d+)$/) {
        !           905:           &start($1+1);
        !           906:           &puts($piece);
        !           907:           $tokenByToken[$#level]=1;
        !           908:         } elsif ($type =~ /^discard(\d+)$/) {
        !           909:           &start($1,"f_discard");
        !           910:           $tokenByToken[$#level]=1;
        !           911:         } elsif ($type eq "record") {
        !           912:           &commit($contents{$pure});
        !           913:         } elsif ($type eq "self") {
        !           914:           &puts(substr($pure,1) . ($pure =~ /^\\[a-zA-Z]/ ? " ": ""));
        !           915:         } elsif ($type eq "par_self") {
        !           916:          &finishBuffer;
        !           917:          &commit("1,5,0,0,     ");
        !           918:           &puts($pure . ($pure =~ /^\\[a-zA-Z]/ ? " ": ""));
        !           919:         } elsif ($type eq "self_par") {
        !           920:           &puts($pure . ($pure =~ /^\\[a-zA-Z]/ ? " ": ""));
        !           921:          &finishBuffer;
        !           922:          &commit("1,5,0,0,     ")
        !           923:            unless $par =~ s/^\s*\\noindent(\s+|([^a-zA-Z\s])|$)/\2/;
        !           924:         } elsif ($type eq "string") {
        !           925:           &puts($contents{$pure},1);
        !           926:         } elsif ($type eq "nothing") {
        !           927:         } else {
        !           928:           warn "Error with type `$type' while interpreting `$pure'";
        !           929:         }
        !           930:       } else {
        !           931:         &puts($piece);
        !           932:       }
        !           933:     }
        !           934:   }
        !           935:   warn "Unrecognized part of input `$par',\n\ttoken-by-token[$#level]=$tokenByToken[$#level]"
        !           936:     if $par ne "";
        !           937:   &finishBuffer if $#out>=0;
        !           938: # return 0 if eof();
        !           939:   1;
        !           940: }
        !           941:
        !           942: sub subscript {
        !           943:   &start(1,"f_subscript");
        !           944:   $tokenByToken[$#level]=1;
        !           945: }
        !           946:
        !           947: sub superscript {
        !           948:   &start(1,"f_superscript");
        !           949:   $tokenByToken[$#level]=1;
        !           950: }
        !           951:
        !           952:
        !           953: sub f_subscript {
        !           954:   $wait[$#level]=2;
        !           955:   $action[$#level]="f_subSuper";
        !           956:   if (($par !~ s/^\s*\^//) &&
        !           957:       ($par !~ s:^\s*\\begin\s*\{Sp\}:\\begin\{matrix\}:)) {
        !           958:     &commit(&empty);
        !           959:   }
        !           960: }
        !           961:
        !           962: sub f_overline {
        !           963:   warn "Entering f_overline...\n" if $debug & $debug_flow;
        !           964:   &trim(1);
        !           965:   &collapse(1);
        !           966:   &assertHave(1) || &finish("",1);
        !           967:   warn "Overlining $out[$#out]\n__END__\n" if $debug & $debug_record;
        !           968:   local($h,$len,$b)=($out[$#out] =~ /^(\d+),(\d+),(\d+)/);
        !           969:   $out[$#out]=&vStack(&string2record("_" x $len),
        !           970:                       $out[$#out]);
        !           971:   $b++;
        !           972:   #$out[$#out] =~ s/^(\d+,\d+,)(\d+)/\1$b/;
        !           973:   &setbaseline($out[$#out],$b);
        !           974:   warn "a:Last $#chunks, the first on the last level=$#level is $level[$#level]" if $debug & $debug_flow;
        !           975:   &finish(1,1);
        !           976: }
        !           977:
        !           978: sub f_underline {
        !           979:   warn "Entering f_underline...\n" if $debug & $debug_flow;
        !           980:   &trim(1);
        !           981:   &collapse(1);
        !           982:   &assertHave(1) || &finish("",1);
        !           983:   warn "Underlining $out[$#out]\n__END__\n" if $debug & $debug_record;
        !           984:   local($h,$len,$b)=($out[$#out] =~ /^(\d+),(\d+),(\d+)/);
        !           985:   $out[$#out]=&vStack($out[$#out],&string2record("_" x $len));
        !           986:   #$out[$#out] =~ s/^(\d+,\d+,)(\d+)/\1$b/;
        !           987:   &setbaseline($out[$#out],$b);
        !           988:   warn "a:Last $#chunks, the first on the last level=$#level is $level[$#level]" if $debug & $debug_flow;
        !           989:   &finish(1,1);
        !           990: }
        !           991:
        !           992: sub f_not {
        !           993:   warn "Entering f_not...\n" if $debug & $debug_flow;
        !           994:   &collapse(1);
        !           995:   &assertHave(1) || &finish("",1);
        !           996:   warn "Negating $out[$#out]\n__END__\n" if $debug & $debug_record;
        !           997:   local($str)=(split(/,/,$out[$#out]))[4];
        !           998:   if ($str eq "=") {
        !           999:     $out[$#out]=$contents{"\\neq"};
        !          1000:   } elsif ($str =~ /^\s*\|\s*$/) {
        !          1001:     $out[$#out]=$contents{"\\nmid"};
        !          1002:   } elsif ($out[$#out] eq $contents{"\\in"}) {
        !          1003:     $out[$#out]=$contents{"\\notin"};
        !          1004:   } else {
        !          1005:     $out[$#out]=&join(&string2record("\\not"),$out[$#out]);
        !          1006:   }
        !          1007:   warn "a:Last $#chunks, the first on the last level=$#level is $level[$#level]" if $debug & $debug_flow;
        !          1008:   &finish(1,1);
        !          1009: }
        !          1010:
        !          1011: sub f_putunder {
        !          1012:   warn "Entering f_putunder...\n" if $debug & $debug_flow;
        !          1013:   &trim(1);
        !          1014:   &collapse(1);
        !          1015:   &assertHave(1) || &finish("",1);
        !          1016:   warn "Putting Under $out[$#out]\n__END__\n" if $debug & $debug_record;
        !          1017:   local($h,$len,$b)=($out[$#out] =~ /^(\d+),(\d+),(\d+)/);
        !          1018:         local($l2)=(&length($_[0]));
        !          1019:         local($len)=(($l1>$l2 ? $l1: $l2));
        !          1020:   $out[$#out]=&vStack(&center($len,$out[$#out]),&center($len,shift));
        !          1021:   #$out[$#out] =~ s/^(\d+,\d+,)(\d+)/\1$b/;
        !          1022:   &setbaseline($out[$#out],$b);
        !          1023:   warn "a:Last $#chunks, the first on the last level=$#level is $level[$#level]" if $debug & $debug_flow;
        !          1024:   &finish(1,1);
        !          1025: }
        !          1026:
        !          1027: # if has additional true argument will not finish
        !          1028: # Takes record to put over
        !          1029:
        !          1030: sub f_putover {
        !          1031:   warn "Entering f_putover...\n" if $debug & $debug_flow;
        !          1032:   &trim(1);
        !          1033:   &collapse(1);
        !          1034:   &assertHave(1) || &finish("",1);
        !          1035:   warn "Putting Over $out[$#out]\n__END__\n" if $debug & $debug_record;
        !          1036:   local($h,$l1,$b,$b1)=($out[$#out] =~ /^(\d+),(\d+),(\d+)/);
        !          1037:         local($l2)=(&length($_[0]));
        !          1038:         local($len)=(($l1>$l2 ? $l1: $l2));
        !          1039:   ($b1)=($_[0] =~ /^(\d+)/);
        !          1040:   $b+=$b1+1;
        !          1041:   $out[$#out]=&vStack(&center($len,shift),&center($len,$out[$#out]));
        !          1042:   #$out[$#out] =~ s/^(\d+,\d+,)(\d+)/\1$b/;
        !          1043:   &setbaseline($out[$#out],$b);
        !          1044:   warn "a:Last $#chunks, the first on the last level=$#level is $level[$#level]" if $debug & $debug_flow;
        !          1045:   &finish(1,1) unless shift;
        !          1046: }
        !          1047:
        !          1048: sub f_putpar {
        !          1049:         warn "Entering f_putpar...\n" if $debug & $debug_flow;
        !          1050:   &trim(1);
        !          1051:   local($l,$r)=split(";",shift);
        !          1052:         &collapse(1);
        !          1053:         &assertHave(1) || &finish("",1);
        !          1054:         warn "Putting Parentheses $out[$#out]\n__END__\n" if $debug & $debug_record;
        !          1055:   $out[$#out]=&join(&string2record($l),
        !          1056:       &join($out[$#out],&string2record($r)));
        !          1057:         &finish(1,1);
        !          1058: }
        !          1059:
        !          1060: sub f_putover_string {
        !          1061:   &f_putover(&string2record);
        !          1062: }
        !          1063:
        !          1064: sub f_widehat {
        !          1065:         &trim(1);
        !          1066:   &collapse(1);
        !          1067:         local($l)=(&length($out[$#out]));
        !          1068:         if ($l<=1) {&f_putover(&string2record("^"));}
        !          1069:         else {&f_putover(&string2record("/" . "~" x ($l-2) . "\\"));}
        !          1070: }
        !          1071:
        !          1072: sub f_widetilde {
        !          1073:         &trim(1);
        !          1074:   &collapse(1);
        !          1075:   local($l,$l1)=(&length($out[$#out]));
        !          1076:   if ($l<=1) {&f_putover(&string2record("~"));}
        !          1077:         elsif ($l<=3) {&f_putover(&string2record("/\\/"));}
        !          1078:         else {&f_putover(&string2record("/" . "~" x ($l1=int($l/2-1)) .
        !          1079:      "\\" . "_" x ($l-3-$l1) . "/"));}
        !          1080: }
        !          1081:
        !          1082: sub f_superscript {
        !          1083:   $wait[$#level]=2;
        !          1084:   $action[$#level]="f_superSub";
        !          1085:   if (($par !~ s/^\s*\_//) &&
        !          1086:       ($par !~ s:^\s*\\begin\s*\{Sb\}:\\begin\{matrix\}:)) {
        !          1087:     &commit(&empty);
        !          1088:   }
        !          1089: }
        !          1090:
        !          1091: sub let {
        !          1092:         $par =~ s/^($tokenpattern)(= ?)?($tokenpattern)//o;
        !          1093: }
        !          1094:
        !          1095: sub let_exp {
        !          1096:         $par =~ s/^($tokenpattern)(= ?)?($tokenpattern)//o;
        !          1097:   return if index($&,'@')>=0;
        !          1098:   local($what)=$1;
        !          1099:   $type{$what}='def';
        !          1100:   $& =~ /($tokenpattern)$/;
        !          1101:   $def{$what}=$1;
        !          1102:   $args{$what}=0;
        !          1103:         warn "Definition of `$what' with $args{$what} args is `$def{$what}'\n"
        !          1104:                         if $debug & $debug_parsing;
        !          1105: }
        !          1106:
        !          1107:
        !          1108: sub def {
        !          1109:   $par =~ s/^[^{]*//;
        !          1110:   &start(1,"f_discard");
        !          1111:   $tokenByToken[$#level]=1;
        !          1112: }
        !          1113:
        !          1114: sub def_exp {
        !          1115:   return unless $par =~ s:^(([^\\{]|\\.)*)\{:\{:;
        !          1116:   local($arg)=($1);
        !          1117:   local($def,$act)=(&get_balanced());
        !          1118:   return unless defined $def;
        !          1119:   return if index("$arg$def",'@')>=0;
        !          1120:   return if $def =~ /\\([egx]?def|fi)([^a-zA-Z]|$)/;
        !          1121:   $def .= " "  if $def =~ /($macro)$/o;
        !          1122:   &define($arg,$def);
        !          1123: }
        !          1124:
        !          1125: # Arguments: Token . Parameters, Expansion
        !          1126:
        !          1127: sub define {
        !          1128:   local($arg,$def,$act)=(shift,shift);
        !          1129:   return unless $arg =~ /^($active)/o;
        !          1130:   $act=$1;
        !          1131:   $args{$act}=$';
        !          1132:   return unless $args{$act} =~ /^(#\d)*$/;
        !          1133:   $args{$act}=length($args{$act})/2;
        !          1134:   $def{$act}=$def;
        !          1135:   $type{$act}='def';
        !          1136:   warn "Definition of `$act' with $args{$act} args is `$def'\n"
        !          1137:       if $debug & $debug_parsing;
        !          1138: }
        !          1139:
        !          1140: sub defb {
        !          1141:   for (@_) {
        !          1142:     &define("\\$_","\\begin{$_}");&define("\\end$_","\\end{$_}");
        !          1143:   }
        !          1144: }
        !          1145:
        !          1146: # Discards surrounding {}
        !          1147:
        !          1148: sub get_balanced {
        !          1149:         return undef unless $par =~ s/^($tokenpattern)//;
        !          1150:   return $1 unless $1 eq '{';
        !          1151:         local($def,$lev)=('',1);
        !          1152:         while ($lev) {
        !          1153:                 last unless $par =~ s/^[^\\{}]|\\.|[{}]//;
        !          1154:                 $lev++ if $& eq '{';
        !          1155:                 $lev-- if $& eq '}';
        !          1156:                 $def .= $& if $lev;
        !          1157:         }
        !          1158:         (warn "Balanced text not finished!",return undef) if $lev;
        !          1159:         return $def;
        !          1160: }
        !          1161:
        !          1162:
        !          1163: sub open_curly {
        !          1164:   #&puts("{") unless $tokenByToken[$#level];
        !          1165:   &start("}");
        !          1166: }
        !          1167:
        !          1168: # Deletes extra spaces at the end of a record
        !          1169:
        !          1170: sub trim_end {
        !          1171:   local($h,$str)=(split(/,/,$_[0],5))[0,4];
        !          1172:   if (!$h) {
        !          1173:     $str =~ s/\s+$//;
        !          1174:     $_[0]=&string2record($str);
        !          1175:     warn "Trimmed End `$_[0]'\n__END__\n" if $debug & $debug_record;
        !          1176:   }
        !          1177: }
        !          1178:
        !          1179: # Deletes extra spaces at the beginning of a record
        !          1180:
        !          1181: sub trim_beg {
        !          1182:   local($h,$str)=(split(/,/,$_[0],5))[0,4];
        !          1183:   if (!$h) {
        !          1184:     $str =~ s/^\s+//;
        !          1185:     $_[0]=&string2record($str);
        !          1186:     warn "Trimmed Beg `$_[0]'\n__END__\n" if $debug & $debug_record;
        !          1187:   }
        !          1188: }
        !          1189:
        !          1190: # Deletes extra spaces at the ends of a chunk with given number
        !          1191:
        !          1192: sub trim_one {
        !          1193:   &trim_beg($out[$chunks[$_[0]]]);
        !          1194:   &trim_end($_[0]==$#chunks? $out[$#out]: $out[$chunks[$_[0]+1]-1]);
        !          1195: }
        !          1196:
        !          1197: # Deletes extra spaces at the ends of a given number of chunks
        !          1198:
        !          1199: sub trim {
        !          1200:   for ($#chunks-$_[0]+1..$#chunks) {&trim_one($_);}
        !          1201: }
        !          1202:
        !          1203: sub dollar {
        !          1204:   if ($wait[$#level] eq '$') {        # ';
        !          1205:     &trim_end($out[$#out]);
        !          1206:     &finish('$');
        !          1207:   }
        !          1208:   else {
        !          1209:     &start('$');
        !          1210:     $par =~ s/^\s+//;
        !          1211:   }
        !          1212: }
        !          1213:
        !          1214: sub ddollar {
        !          1215:   if ($wait[$#level] eq '$$') {
        !          1216:     &trim_end($out[$#out]);
        !          1217:     &finish('$$');
        !          1218:     return unless $#out>=0;
        !          1219:     $#chunks=0;
        !          1220:     $chunks[0]=0;
        !          1221:     &trim(1);
        !          1222:     &collapse(1);
        !          1223:     &printrecord(&center($linelength,$out[0]));
        !          1224:     @level=(0);
        !          1225:     @chunks=(0);
        !          1226:     @tokenByToken=(0);
        !          1227:     @out=();
        !          1228:     $curlength=0;
        !          1229:     # Maybe after \begin{align}
        !          1230:   }
        !          1231:   else {
        !          1232:     &finishBuffer;
        !          1233:     &start('$$');
        !          1234:   }
        !          1235:   $par =~ s/^\s+//;
        !          1236: }
        !          1237:
        !          1238: sub item {
        !          1239:   &finishBuffer;
        !          1240:   # To make unexpandable:
        !          1241:   &commit("1,11,0,0,     (\@)   ");
        !          1242: }
        !          1243:
        !          1244: sub bbackslash {
        !          1245:   if ($wait[$#level] eq '$$') {
        !          1246:     &ddollar();
        !          1247:     &ddollar();
        !          1248:   } elsif ($wait[$#level] eq 'endCell') {
        !          1249:     return if $par =~ /^\s*\\end/;             # Ignore the last one
        !          1250:     &finish('endCell', 1);
        !          1251:     &trim(1);
        !          1252:     &collapse(1);
        !          1253:     &finish('endRow', 1);
        !          1254:     &start('endRow');
        !          1255:     &start('endCell');
        !          1256:   } else {
        !          1257:     #&puts(" \\\\ ");
        !          1258:     &par;
        !          1259:   }
        !          1260: }
        !          1261:
        !          1262: sub ampersand {
        !          1263:   if ($wait[$#level] eq 'endCell') {
        !          1264:     &finish('endCell',1);
        !          1265:     &trim(1);
        !          1266:     &collapse(1);
        !          1267:     &start('endCell');
        !          1268:   }
        !          1269: }
        !          1270:
        !          1271: sub matrix {
        !          1272:   &start('endMatrix');
        !          1273:   &start('endRow');
        !          1274:   &start('endCell');
        !          1275: }
        !          1276:
        !          1277: sub endmatrix {
        !          1278:   &finish('endCell',1);
        !          1279:   &trim(1);
        !          1280:   &collapse(1);
        !          1281:   &finish('endRow',1);
        !          1282:   # Now chunks correspond to rows of the matrix, records inside chunks to
        !          1283:   # Cells
        !          1284:   &halign(split(";",shift));
        !          1285:   &finish('endMatrix',1);
        !          1286: }
        !          1287:
        !          1288: sub endmatrixArg {
        !          1289:   &endmatrix(join(";",($_[0],split("",pop(@argStack)))));
        !          1290: }
        !          1291:
        !          1292: # Takes a matrix in the following form: chunks on the last level
        !          1293: # are row of the matrix, records inside chunks are cells.
        !          1294: # Puts the resulting matrix in the first record on the given level
        !          1295: # and truncates the rest
        !          1296:
        !          1297: # I'm trying to add parameters:
        !          1298: #      length to insert between columns
        !          1299: #      Array of centering options one for a column (last one repeated if needed)
        !          1300: #              Currently supported:    c for center
        !          1301: #                                      r for right
        !          1302: #                                      l for left
        !          1303:
        !          1304: sub halign {
        !          1305:   local($explength)=(shift);
        !          1306:   local(@c)=@_;
        !          1307:   local($last,$le,$b,$h);
        !          1308:   local(@w)=();
        !          1309:   #warn "levels @level, chunks @chunks, records @out\n";
        !          1310:   # Find metrics of cells
        !          1311:   for $r (0..$#chunks-$level[$#level]) {
        !          1312:     $last= ($r==$#chunks-$level[$#level]) ? $#out:
        !          1313:                                             $chunks[$r+1+$level[$#level]]-1;
        !          1314:   warn "Row $r: last column " . ($last-$chunks[$r+$level[$#level]]) ."\n"
        !          1315:                                 if $debug & $debug_matrix;
        !          1316:     for $c (0..$last-$chunks[$r+$level[$#level]]) {
        !          1317:       ($h,$le,$b)=
        !          1318:                 ($out[$chunks[$r+$level[$#level]]+$c] =~ /(\d+),(\d+),(\d+)/);
        !          1319:         # Format is Height:Length:Baseline
        !          1320:       $w[$c]=$le unless $w[$c]>$le;
        !          1321:     }
        !          1322:   }
        !          1323:   # expand the height and depth
        !          1324:   for $c (0..$#w-1) {$w[$c]+=$explength;}
        !          1325:   # Extend the @c array by the last element or "c" if it is empty
        !          1326:   @c=("c") x @w unless @c;
        !          1327:   @c=(@c,($c[$#c]) x (@w-@c));
        !          1328:   # Now expand the cells
        !          1329:   warn "Widths of columns @w\n" if $debug & $debug_matrix;
        !          1330:   for $r (0..$#chunks-$level[$#level]) {
        !          1331:     $last= ($r==$#chunks-$level[$#level]) ? $#out:
        !          1332:                                             $chunks[$r+1+$level[$#level]]-1;
        !          1333:     warn "Row $r: last column " . ($last-$chunks[$r+$level[$#level]]) ."\n"
        !          1334:         if $debug & $debug_matrix;
        !          1335:     for $c (0..$last-$chunks[$r+$level[$#level]]) {
        !          1336:       if ($c[$c] eq "c") {
        !          1337:         warn "Centering row $r col $c to width $w[$c]\n"
        !          1338:             if $debug & $debug_matrix;
        !          1339:         $out[$chunks[$r+$level[$#level]]+$c]=
        !          1340:           &center($w[$c],$out[$chunks[$r+$level[$#level]]+$c]);
        !          1341:       } elsif ($c[$c] eq "l") {
        !          1342:         warn "Expanding row $r col $c to width $w[$c]\n"
        !          1343:             if $debug & $debug_matrix;
        !          1344:         $out[$chunks[$r+$level[$#level]]+$c]=
        !          1345:           &join($out[$chunks[$r+$level[$#level]]+$c],
        !          1346:                 &string2record(" " x
        !          1347:                   ($w[$c] - &length($out[$chunks[$r+$level[$#level]]+$c]))));
        !          1348:       } elsif ($c[$c] eq "r") {
        !          1349:         warn "Expanding row $r col $c to width $w[$c] on the left\n"
        !          1350:             if $debug & $debug_matrix;
        !          1351:         $out[$chunks[$r+$level[$#level]]+$c]=
        !          1352:           &join(&string2record(" " x
        !          1353:                   ($w[$c]-$explength-
        !          1354:                        &length($out[$chunks[$r+$level[$#level]]+$c]))),
        !          1355:                 $out[$chunks[$r+$level[$#level]]+$c]);
        !          1356:         $out[$chunks[$r+$level[$#level]]+$c]=
        !          1357:           &join($out[$chunks[$r+$level[$#level]]+$c],
        !          1358:                 &string2record(" " x $explength));
        !          1359:       } else {warn "Unknown centering option `$c[$c]' for halign";}
        !          1360:     }
        !          1361:   }
        !          1362:   # Now we creat rows
        !          1363:   &collapseAll;
        !          1364:   # And stack them vertically
        !          1365:   for ($chunks[$level[$#level]]+1..$#out) {
        !          1366:     $out[$chunks[$level[$#level]]]=&vStack($out[$chunks[$level[$#level]]],
        !          1367:                                            $out[$_]);
        !          1368:   }
        !          1369:   &setbaseline($out[$chunks[$level[$#level]]],
        !          1370:                int((&height($out[$chunks[$level[$#level]]])-1)/2));
        !          1371:   $#chunks=$level[$#level];
        !          1372:   $#out=$chunks[$level[$#level]];
        !          1373: }
        !          1374:
        !          1375: sub close_curly {
        !          1376:   &finish("}");
        !          1377:   #&puts("}") unless $tokenByToken[$#level]; # well, this can change under our foot...
        !          1378: }
        !          1379:
        !          1380: sub at {
        !          1381:   local($c,$first,$second,$t,$m)=($par =~ /^(.)/);
        !          1382:   if ($c eq '@') {&puts('@');$par =~ s/^.//;}
        !          1383:   elsif (index("<>AV",$c)>=0) {
        !          1384:     $m="&" if ($wait[$#level] eq 'endCell');
        !          1385:     $m="&&" if $m eq "&" && index("AV",$c)>=0;
        !          1386:     &ampersand if $m eq "&";
        !          1387:     $par =~ s/^.//;
        !          1388:     $first=$second="";
        !          1389:     while (($t=&get_balanced()) ne $c && defined $t) {
        !          1390:       $first .= $t;
        !          1391:     }
        !          1392:     while (($t=&get_balanced()) ne $c && defined $t) {
        !          1393:       $second .= $t;
        !          1394:     }
        !          1395:     $par="{$first}{$second}$m" . $par;
        !          1396:     local($l,$r);
        !          1397:     ($l=$c) =~ tr/A>V/^/d;
        !          1398:     ($r=$c) =~ tr/<A//d;
        !          1399:     index("<>",$c)>=0 ?
        !          1400:        &start(2,"f_arrow;$l;$r"):
        !          1401:        &start(2,"f_arrow_v;$l;$r");
        !          1402:   }
        !          1403:   elsif ($c eq "." && $wait[$#level] eq 'endCell') {
        !          1404:     &ampersand;
        !          1405:     &ampersand;
        !          1406:     $par =~ s/^.//;
        !          1407:   }
        !          1408:   else {&puts('@');}
        !          1409: }
        !          1410:
        !          1411: # takes two tips of arrow as argument separated by ";",
        !          1412: # we assume that total length is 1
        !          1413:
        !          1414: sub f_arrow {
        !          1415:   warn "Entering f_arrow...\n" if $debug & $debug_flow;
        !          1416:   local($l,$r)=split(";",shift);
        !          1417:   &trim(2);
        !          1418:   &collapse(2);
        !          1419:   &assertHave(2) || &finish("",1);
        !          1420:   warn "Over: $out[$#out-1]\nUnder: $out[$#out]\n__END__\n" if $debug & $debug_record;
        !          1421:   local($l1,$l2)=(&length($out[$#out-1]),&length($out[$#out]));
        !          1422:   local($len)=(($l1>$l2 ? $l1: $l2));
        !          1423:   $out[$#out-1]=&vStack(&vStack(&center($len+4,$out[$#out-1]),
        !          1424:                          &string2record(" $l" ."-" x ($len+1) . "$r ")),
        !          1425:                  &center($len+4,$out[$#out]));
        !          1426:   $#chunks--;
        !          1427:   $#out--;
        !          1428:   warn "a:Last $#chunks, the first on the last level=$#level is $level[$#level]" if $debug & $debug_flow;
        !          1429:   &finish(2,1);
        !          1430: }
        !          1431:
        !          1432: # takes two tips of arrow as argument separated by ";",
        !          1433: # we assume that total length is 1
        !          1434:
        !          1435: sub f_arrow_v {
        !          1436:   warn "Entering f_arrow_v...\n" if $debug & $debug_flow;
        !          1437:   local($l,$r)=split(";",shift);
        !          1438:   &trim(2);
        !          1439:   &collapse(2);
        !          1440:   &assertHave(2) || &finish("",1);
        !          1441:   warn "Over: $out[$#out-1]\nUnder: $out[$#out]\n__END__\n" if $debug & $debug_record;
        !          1442:   local($h1,$b1)=($out[$#out-1] =~ /^(\d+),\d+,(\d+)/);
        !          1443:   local($h2,$b2)=($out[$#out] =~ /^(\d+),\d+,(\d+)/);
        !          1444:   local($b)=(($b1>$b2 ? $b1: $b2));
        !          1445:   local($res)=(&join($out[$#out-1],$out[$#out]));
        !          1446:   local($h,$bb)=($res =~ /^(\d+),\d+,(\d+)/);
        !          1447:   $bb=$b+1;
        !          1448:   $out[$#out-1]=&vStack(&vputs(" " x ($b-$b1+1)),
        !          1449:                         $out[$#out-1]);
        !          1450:   #$out[$#out-1] =~ s/^(\d+,\d+,)(\d+)/\1$bb/;
        !          1451:   &setbaseline($out[$#out-1],$bb);
        !          1452:   $out[$#out]=&vStack(&vputs(" " x ($b-$b2+1)),
        !          1453:                                      $out[$#out]);
        !          1454:   #$out[$#out] =~ s/^(\d+,\d+,)(\d+)/\1$bb/;
        !          1455:   &setbaseline($out[$#out],$bb);
        !          1456:   $out[$#out-1]=&join(&join($out[$#out-1],
        !          1457:                          &vputs($l ."|" x ($h+1) . $r,$b+1)),
        !          1458:                       $out[$#out]);
        !          1459:   $#chunks--;
        !          1460:   $#out--;
        !          1461:   warn "a:Last $#chunks, the first on the last level=$#level is $level[$#level]" if $debug & $debug_flow;
        !          1462:   &finish(2,1);
        !          1463: }
        !          1464:
        !          1465: sub noindent {
        !          1466:   if ($#out == 0 && $#chunks == 0 && $out[$#out] eq '1,5,0,0,     ') {
        !          1467:     $#out--;
        !          1468:     $#chunks--;
        !          1469:   } else {
        !          1470:     &puts('\\noindent');
        !          1471:   }
        !          1472: }
        !          1473:
        !          1474: # put strings vertically, returns a record with the second argument as baseline
        !          1475:
        !          1476: sub vputs {
        !          1477:   local($b)=($_[1]);
        !          1478:   $b=0 unless defined $b;
        !          1479:   return length($_[0]) . ",1,$b,0," . join("\n",split('',$_[0]));
        !          1480: }
        !          1481:
        !          1482: sub choose {
        !          1483:   if ($wait[$#level] eq '}') {
        !          1484:     local($prevw)=($wait[$#level-1]);
        !          1485:     $wait[$#level-1]="junk";
        !          1486:     &finish("}",1);
        !          1487:           &collapse(1);
        !          1488:           &assertHave(1) || &finish("",1);
        !          1489:     local($rec)=$out[$#out];
        !          1490:     $#out--;
        !          1491:     $#chunks--;
        !          1492:     &start(2,"f_choose");
        !          1493:     $wait[$#level-1]=$prevw;
        !          1494:     &start("}");
        !          1495:     &commit($rec);
        !          1496:     &finish("}",1);
        !          1497:     &start("}");
        !          1498:   } else {&puts("\\choose");}
        !          1499: }
        !          1500:
        !          1501: sub over {
        !          1502:   if ($wait[$#level] eq '}') {
        !          1503:     local($prevw)=($wait[$#level-1]);
        !          1504:     $wait[$#level-1]="junk";
        !          1505:     &finish("}", 1);
        !          1506:           &collapse(1);
        !          1507:           &assertHave(1) || &finish("",1);
        !          1508:     local($rec)=$out[$#out];
        !          1509:     $#out--;
        !          1510:     $#chunks--;
        !          1511:     &start(2,"f_fraction");
        !          1512:     $wait[$#level-1]=$prevw;
        !          1513:     &start("}");
        !          1514:     &commit($rec);
        !          1515:     &finish("}",1);
        !          1516:     &start("}");
        !          1517:   } else {&puts("\\over");}
        !          1518: }
        !          1519:
        !          1520: # Takes a record, height, baseline, spaces_toleft and _toright
        !          1521: # and makes this record this high
        !          1522:
        !          1523: sub makehigh {
        !          1524:   local($str)=(split(",",$_[0],5))[4];
        !          1525:   local($h,$b,$d)=($_[1],$_[2]+1);
        !          1526:   warn "Entering makehigh(@_)\n" if $debug & $debug_flow;
        !          1527:   if ($str eq ".") {$_[0] =~ s/\.$/ /;return;}
        !          1528:   #$str="<" if $str eq "\\langle";
        !          1529:   #$str=">" if $str eq "\\rangle";
        !          1530:   $h=1 unless $h;
        !          1531:   $d=$h-$b;
        !          1532:   return if $h<2 || $h==2 && index("()<>",$str)>=0;
        !          1533:   local(@c);
        !          1534:   if    ($str eq "(") {@c=split(":",'(: :|:/:\:|');}
        !          1535:   elsif ($str eq ")") {@c=split(":",'): :|:\:/:|');}
        !          1536:   elsif ($str eq "{") {@c=split(":",'{: :|:/:\:<');}
        !          1537:   elsif ($str eq "}") {@c=split(":",'}: :|:\:/:>');}
        !          1538:   elsif ($str eq "|" && $str eq "||")
        !          1539:                       {@c=split(":",'|:|:|:|:|:|');}
        !          1540:   elsif ($str eq "[") {@c=split(":",'[:[:|:[:[:|');}
        !          1541:   elsif ($str eq "]") {@c=split(":",']:]:|:]:]:|');}
        !          1542:   elsif ($str eq "<" || $str eq ">") {
        !          1543:     return if $h==2;
        !          1544:     local($l)=($b);
        !          1545:     $l=$d+1 if $b<$d+1;
        !          1546:     for (2..$l) {
        !          1547:       $_[0]=&join($_[0],
        !          1548:                   &vputs("/" . " " x (2*$_-3) . "\\",$_-1)) if $str eq "<";
        !          1549:       $_[0]=&join(&vputs("\\" . " " x (2*$_-3) . "/",$_-1),
        !          1550:                   $_[0]) if $str eq ">";
        !          1551:     }
        !          1552:     $_[0]=&join($_[0],&string2record(" ")) if $str eq "<";
        !          1553:     $_[0]=&join(&string2record(" "),$_[0]) if $str eq ">";
        !          1554:     return;
        !          1555:   }
        !          1556:   else {return;}
        !          1557:   $_[0]=&vputs(&makecompound($b,$d,@c),$b-1);
        !          1558:   $_[0]=&join($_[0],$_[0]) if length($str)==2;
        !          1559:   $_[0]=&join(&string2record(" " x $_[3]),$_[0]) if $_[3];
        !          1560:   $_[0]=&join($_[0],&string2record(" " x $_[4])) if $_[4];
        !          1561: }
        !          1562:
        !          1563:
        !          1564: sub right {
        !          1565:   &finish("LeftRight",1);
        !          1566:   &trim(1);
        !          1567:   &collapse(1);
        !          1568: }
        !          1569:
        !          1570: sub f_left {
        !          1571:   &trim(1);
        !          1572:   &collapse(1);
        !          1573:   &finish(1);
        !          1574:   &start("LeftRight");
        !          1575: }
        !          1576:
        !          1577: sub left {
        !          1578:   &start(3,"f_leftright");
        !          1579:   $tokenByToken[$#level]=1;
        !          1580:   &start(1,"f_left");
        !          1581:   $tokenByToken[$#level]=1;
        !          1582: }
        !          1583:
        !          1584: sub f_leftright_go {
        !          1585:   &trim(1);
        !          1586:   &collapse(1);
        !          1587:   local($l,$r)=split(";",shift);
        !          1588:   &assertHave(1) || warn "Left-Right not balanced";
        !          1589:   local($rec)=($out[$#out]);
        !          1590:   $#out--;
        !          1591:   $wait[$#level]="junk";
        !          1592:   &start(3,"f_leftright");
        !          1593:   &puts($l);
        !          1594:   &commit($rec);
        !          1595:   &puts($r);
        !          1596:   &finish("junk");
        !          1597: }
        !          1598:
        !          1599: sub beg_lr {
        !          1600:   &start(1,"f_leftright_go" . ";" . shift);
        !          1601:   $tokenByToken[$#level]=1;
        !          1602: }
        !          1603:
        !          1604: sub f_leftright {
        !          1605:   &trim(1);
        !          1606:   &collapse(1);
        !          1607:   &assertHave(3) || warn "Left-Right not balanced";
        !          1608:   local($h,$b)=($out[$#out-1] =~ /^(\d+),\d+,(\d+)/)[0,1];
        !          1609:   &makehigh($out[$#out-2],$h,$b,0,1);
        !          1610:   &makehigh($out[$#out],$h,$b,1,0);
        !          1611:   &finish(3);
        !          1612: }
        !          1613:
        !          1614: # Arguments: Ascent, descent, base string, oneside expander, real expander
        !          1615: #            0       1        2            3                 4
        !          1616: #            Top tip, Bottom tip, Mid
        !          1617: #            5        6           7
        !          1618: # All component should be one character long
        !          1619:
        !          1620: sub makecompound {
        !          1621:   # If Mid is the same as real expander, all depends on the height only
        !          1622:   # if there is extend on both sides
        !          1623:   # If it is 3 or more
        !          1624:   if ($_[0]>1 && $_[1]>0 && $_[4] eq $_[7]) {
        !          1625:     return $_[5] . $_[4] x ($_[0]+$_[1]-2) . $_[6];
        !          1626:   }
        !          1627:   # No descent:
        !          1628:   if ($_[1] <= 0) {return $_[3] x ($_[0]-1) . $_[2];}
        !          1629:   # No ascent:
        !          1630:   if ($_[0] <= 1) {return $_[2] . $_[3] x $_[1];}
        !          1631:   local($mid,$asc,$des)=($_[2]);
        !          1632:   # descent == 1
        !          1633:   $des = ($_[1]==1) ? $_[2]: $_[4] x ($_[1]-1) . $_[6];
        !          1634:   $asc  = ($_[0]==2) ? $_[2]: $_[5] . $_[4] x ($_[0]-2);
        !          1635:   $mid = $_[7] unless $_[0]==2 || $_[1]==1;
        !          1636:   return "$asc$mid$des";
        !          1637: }
        !          1638:
        !          1639: sub arg2stack {push(@argStack,&get_balanced());}
        !          1640:
        !          1641: sub par {&finishBuffer;&commit("1,5,0,0,     ")
        !          1642:           unless $par =~ s/^\s*\\noindent\s*(\s+|([^a-zA-Z\s])|$)/\2/;}
        !          1643:
        !          1644: $type{"\\sum"}="record";
        !          1645: $contents{"\\sum"}="3,4,1,0," . <<'EOF';
        !          1646: \~~
        !          1647:  >
        !          1648: /__
        !          1649: EOF
        !          1650:
        !          1651: $type{"\\int"}="record";
        !          1652: $contents{"\\int"}="3,3,1,0," . <<'EOF';
        !          1653:  ,-
        !          1654:  |
        !          1655: -'
        !          1656: EOF
        !          1657:
        !          1658: $type{"\\prod"}="record";
        !          1659: $contents{"\\prod"}="3,3,1,0," . <<'EOF';
        !          1660: ___
        !          1661: | |
        !          1662: | |
        !          1663: EOF
        !          1664:
        !          1665: $type{"\\Pi"}="record";
        !          1666: $contents{"\\Pi"}="2,3,1,0," . <<'EOF';
        !          1667:  _
        !          1668: | |
        !          1669: EOF
        !          1670:
        !          1671: $type{"\\Sigma"}="record";
        !          1672: $contents{"\\Sigma"}="3,2,1,0," . <<'EOF';
        !          1673: __
        !          1674: >
        !          1675: ~~
        !          1676: EOF
        !          1677:
        !          1678: $type{"\\Delta"}="record";
        !          1679: $contents{"\\Delta"}="2,2,0,0," . <<'EOF';
        !          1680: /\
        !          1681: ~~
        !          1682: EOF
        !          1683:
        !          1684: $type{"\\oplus"}="record";
        !          1685: $contents{"\\oplus"}="3,5,1,0," . <<'EOF';
        !          1686:   _
        !          1687:  (+)
        !          1688:   ~
        !          1689: EOF
        !          1690:
        !          1691: $type{"\\otimes"}="record";
        !          1692: $contents{"\\otimes"}="3,5,1,0," . <<'EOF';
        !          1693:   _
        !          1694:  (x)
        !          1695:   ~
        !          1696: EOF
        !          1697:
        !          1698: $type{"\\ominus"}="record";
        !          1699: $contents{"\\ominus"}="3,5,1,0," . <<'EOF';
        !          1700:   _
        !          1701:  (-)
        !          1702:   ~
        !          1703: EOF
        !          1704:
        !          1705: $type{"\\leq"}="record";
        !          1706: $contents{"\\leq"}="2,4,1,0," . <<'EOF';
        !          1707:  _
        !          1708:  <
        !          1709: EOF
        !          1710:
        !          1711: $type{"\\equiv"}="record";
        !          1712: $contents{"\\equiv"}="2,4,1,0," . <<'EOF';
        !          1713:  _
        !          1714:  =
        !          1715: EOF
        !          1716:
        !          1717: $type{"\\geq"}="record";
        !          1718: $contents{"\\geq"}="2,4,1,0," . <<'EOF';
        !          1719:  _
        !          1720:  >
        !          1721: EOF
        !          1722:
        !          1723: $type{"\\partial"}="record";
        !          1724: $contents{"\\partial"}="2,2,1,0," . <<'EOF';
        !          1725: \
        !          1726: d
        !          1727: EOF
        !          1728:
        !          1729: $type{"\\forall"}="record";
        !          1730: $contents{"\\forall"}="3,4,1,0," . <<'EOF';
        !          1731: \__/
        !          1732:  \/
        !          1733: EOF
        !          1734:
        !          1735: $type{"\\exists"}="record";
        !          1736: $contents{"\\exists"}="3,2,1,0," . <<'EOF';
        !          1737: _.
        !          1738: -|
        !          1739: ~'
        !          1740: EOF
        !          1741:
        !          1742: $type{"\\owns"}="record";
        !          1743: $contents{"\\owns"}="3,4,1,0," . <<'EOF';
        !          1744:  _
        !          1745:  -)
        !          1746:  ~
        !          1747: EOF
        !          1748:
        !          1749: $type{"\\ni"}="record";
        !          1750: $contents{"\\ni"}="3,4,1,0," . <<'EOF';
        !          1751:  _
        !          1752:  -)
        !          1753:  ~
        !          1754: EOF
        !          1755:
        !          1756: $type{"\\in"}="record";
        !          1757: $contents{"\\in"}="3,4,1,0," . <<'EOF';
        !          1758:   _
        !          1759:  (-
        !          1760:   ~
        !          1761: EOF
        !          1762:
        !          1763: $type{"\\notin"}="record";
        !          1764: $contents{"\\notin"}="3,5,1,0," . <<'EOF';
        !          1765:   |_
        !          1766:  (|-
        !          1767:   |~
        !          1768: EOF
        !          1769:
        !          1770: $type{"\\qed"}="record";
        !          1771: $contents{"\\qed"}="2,6,1,0," . <<'EOF';
        !          1772:     _
        !          1773:    |_|
        !          1774: EOF
        !          1775:
        !          1776: $type{"\\pm"}="record";
        !          1777: $contents{"\\pm"}="2,1,0,0," . <<'EOF';
        !          1778: +
        !          1779: -
        !          1780: EOF
        !          1781:
        !          1782: $type{"\\mp"}="record";
        !          1783: $contents{"\\mp"}="2,1,1,0," . <<'EOF';
        !          1784: _
        !          1785: +
        !          1786: EOF
        !          1787:
        !          1788: $type{"\\cong"}="record";
        !          1789: $contents{"\\cong"}="2,1,0,0," . <<'EOF';
        !          1790: =
        !          1791: ~
        !          1792: EOF
        !          1793:
        !          1794: $type{"\\neq"}="record";
        !          1795: $contents{"\\neq"}="1,5,0,0," . <<'EOF';
        !          1796:  =/=
        !          1797: EOF
        !          1798:
        !          1799: $type{"\\nmid"}="record";
        !          1800: $contents{"\\nmid"}="3,3,1,0," . <<'EOF';
        !          1801:  |/
        !          1802:  |
        !          1803: /|
        !          1804: EOF
        !          1805:
        !          1806: $type{"\\subset"}="record";
        !          1807: $contents{"\\subset"}="2,4,1,0," . <<'EOF';
        !          1808:   _
        !          1809:  (_
        !          1810: EOF
        !          1811:
        !          1812: $type{"\\subseteq"}="record";
        !          1813: $contents{"\\subseteq"}="3,4,1,0," . <<'EOF';
        !          1814:   _
        !          1815:  (_
        !          1816:   ~
        !          1817: EOF
        !          1818:
        !          1819: $type{"\\supseteq"}="record";
        !          1820: $contents{"\\subseteq"}="3,4,1,0," . <<'EOF';
        !          1821:  _
        !          1822:  _)
        !          1823:  ~
        !          1824: EOF
        !          1825:
        !          1826: $type{"\\supset"}="record";
        !          1827: $contents{"\\supset"}="2,4,1,0," . <<'EOF';
        !          1828:  _
        !          1829:  _)
        !          1830: EOF
        !          1831:
        !          1832: $type{"\\sqrt"}="sub1";
        !          1833: $contents{"\\sqrt"}="radical";
        !          1834:
        !          1835: $type{"\\buildrel"}="sub3";
        !          1836: $contents{"\\buildrel"}="buildrel";
        !          1837:
        !          1838: $type{"\\frac"}="sub2";
        !          1839: $contents{"\\frac"}="fraction";
        !          1840:
        !          1841: $type{"\\LITERALnoLENGTH"}="sub1";
        !          1842: $contents{"\\LITERALnoLENGTH"}="literal_no_length";
        !          1843:
        !          1844: for ("text","operatorname","operatornamewithlimits","relax","-",
        !          1845:      "notag","!","/","protect","mathcal","Bbb","bf","it","em","boldsymbol",
        !          1846:      "cal","Cal","goth","ref","maketitle","expandafter","csname","endcsname",
        !          1847:      "makeatletter","makeatother","topmatter","endtopmatter","rm",
        !          1848:      "NoBlackBoxes","document","TagsOnRight","bold","dsize","roster",
        !          1849:      "endroster","endkey","endRefs","enddocument","displaystyle",
        !          1850:      "twelverm","tenrm","twelvefm","tenfm","hbox","mbox") {
        !          1851:   $type{"\\$_"}="nothing";
        !          1852: }
        !          1853: for ("par","endtitle","endauthor","endaffil","endaddress","endemail",
        !          1854:      "endhead","key","medskip","smallskip","bigskip","newpage",
        !          1855:      "vfill","eject","endgraph") {
        !          1856:   $type{"\\$_"}="sub";
        !          1857:   $contents{"\\$_"}="par";
        !          1858: }
        !          1859:
        !          1860: for ("proclaim","demo",) {
        !          1861:   $type{"\\$_"}="par_self";
        !          1862: }
        !          1863:
        !          1864: for ("endproclaim","enddemo",) {
        !          1865:   $type{"\\$_"}="self_par";
        !          1866: }
        !          1867:
        !          1868: #$type{"&"}="nothing";
        !          1869:
        !          1870: $type{"\\let"}="sub";
        !          1871: $contents{"\\let"}="let_exp";
        !          1872:
        !          1873: $type{"\\def"}="sub";
        !          1874: $contents{"\\def"}="def_exp";
        !          1875:
        !          1876: $type{"\\item"}="sub";
        !          1877: $contents{"\\item"}="item";
        !          1878:
        !          1879: $type{"{"}="sub";
        !          1880: $contents{"{"}="open_curly";
        !          1881:
        !          1882: $type{"}"}="sub";
        !          1883: $contents{"}"}="close_curly";
        !          1884:
        !          1885: $type{"&"}="sub";
        !          1886: $contents{"&"}="ampersand";
        !          1887:
        !          1888: $type{'$'}="sub";
        !          1889: $contents{'$'}="dollar";
        !          1890:
        !          1891: $type{'$$'}="sub";
        !          1892: $contents{'$$'}="ddollar";
        !          1893:
        !          1894: $type{'\\\\'}="sub";
        !          1895: $contents{'\\\\'}="bbackslash";
        !          1896:
        !          1897: $type{"^"}="sub1";
        !          1898: $contents{"^"}="superscript";
        !          1899:
        !          1900: $type{"_"}="sub1";
        !          1901: $contents{"_"}="subscript";
        !          1902:
        !          1903: $type{"@"}="sub";
        !          1904: $contents{"@"}="at";
        !          1905:
        !          1906: $type{"\\over"}="sub";
        !          1907: $contents{"\\over"}="over";
        !          1908:
        !          1909:
        !          1910: $type{"\\choose"}="sub";
        !          1911: $contents{"\\choose"}="choose";
        !          1912:
        !          1913: $type{"\\noindent"}="sub";
        !          1914: $contents{"\\noindent"}="noindent";
        !          1915:
        !          1916:
        !          1917: $type{"\\left"}="sub";
        !          1918: $contents{"\\left"}="left";
        !          1919:
        !          1920: $type{"\\right"}="sub";
        !          1921: $contents{"\\right"}="right";
        !          1922:
        !          1923: $type{"\\underline"}="sub1";
        !          1924: $contents{"\\underline"}="underline";
        !          1925:
        !          1926: $type{"\\overline"}="sub1";
        !          1927: $contents{"\\overline"}="overline";
        !          1928:
        !          1929: $type{"\\bar"}="sub1";
        !          1930: $contents{"\\bar"}="overline";
        !          1931:
        !          1932: $type{"\\v"}="sub1";
        !          1933: $contents{"\\v"}="putover_string;v";
        !          1934:
        !          1935: $type{"\\widetilde"}="sub1";
        !          1936: $contents{"\\widetilde"}="widetilde";
        !          1937:
        !          1938: $type{"\\~"}="sub1";
        !          1939: $contents{"\\~"}="putover_string;~";
        !          1940:
        !          1941: $type{"\\tilde"}="sub1";
        !          1942: $contents{"\\tilde"}="putover_string;~";
        !          1943:
        !          1944: $type{"\\widehat"}="sub1";
        !          1945: $contents{"\\widehat"}="widehat";
        !          1946:
        !          1947: $type{"\\hat"}="sub1";
        !          1948: $contents{"\\hat"}="putover_string;^";
        !          1949:
        !          1950: $type{"\\^"}="sub1";
        !          1951: $contents{"\\^"}="putover_string;^";
        !          1952:
        !          1953: $type{'\\"'}="sub1";
        !          1954: $contents{'\\"'}='putover_string;"';
        !          1955:
        !          1956: $type{'\\dot'}="sub1";
        !          1957: $contents{'\\dot'}='putover_string;.';
        !          1958:
        !          1959: $type{"\\not"}="sub1";
        !          1960: $contents{"\\not"}="not";
        !          1961:
        !          1962: $type{"\\label"}="sub1";
        !          1963: $contents{"\\label"}="putpar;(;)";
        !          1964:
        !          1965: $type{"\\eqref"}="sub1";
        !          1966: $contents{"\\eqref"}="putpar;(;)";
        !          1967:
        !          1968: $type{"\\cite"}="sub1";
        !          1969: $contents{"\\cite"}="putpar;[;]";
        !          1970:
        !          1971: $type{"\\begin"}="sub1";
        !          1972: $contents{"\\begin"}="begin";
        !          1973:
        !          1974: $type{"\\end"}="sub1";
        !          1975: $contents{"\\end"}="end";
        !          1976:
        !          1977: for ('@',"_","\$","{","}","#","&","arccos","arcsin","arctan","arg","cos",
        !          1978:     "cosh","cot","coth","csc","deg","det","dim","exp","gcd","hom",
        !          1979:     "inf","ker","lg","lim","liminf","limsup","ln","log","max","min",
        !          1980:     "mod","Pr","sec","sin","sinh","sup","tan","tanh", "%") {
        !          1981:   $type{"\\$_"}="self";
        !          1982: }
        !          1983:
        !          1984: for ("bibliography","myLabel","theoremstyle","theorembodyfont",
        !          1985:      "bibliographystyle","hphantom","vphantom","phantom","hspace") {
        !          1986:   $type{"\\$_"}="discard1";
        !          1987: }
        !          1988:
        !          1989: for ("numberwithin","newtheorem","renewcommand","setcounter"
        !          1990:     ) {
        !          1991:   $type{"\\$_"}="discard2";
        !          1992: }
        !          1993:
        !          1994: for ("equation","gather","align"
        !          1995:      ) {$environment{"$_"}="ddollar,ddollar";}
        !          1996:
        !          1997: for ("matrix","CD","smallmatrix"
        !          1998:      ) {$environment{"$_"}="matrix,endmatrix;1;c";}
        !          1999:
        !          2000: for ("document","split","enumerate"
        !          2001:      ) {$environment_none{"$_"}++;}
        !          2002:
        !          2003: $environment{"Sb"}="subscript:matrix,endmatrix;1;l";
        !          2004:
        !          2005: $environment{"Sp"}="superscript:matrix,endmatrix;1;l";
        !          2006:
        !          2007: $environment{"eqnarray"}="ddollar:matrix,endmatrix;0;r;c;l:ddollar";
        !          2008: $environment{"split"}="ddollar:matrix,endmatrix;0;r;l:ddollar";
        !          2009: $environment{"multiline"}="ddollar:matrix,endmatrix;0;r;l:ddollar";
        !          2010: $environment{"align"}="ddollar:matrix,endmatrix;0;r;l:ddollar";
        !          2011: $environment{"aligned"}="matrix,endmatrix;0;r;l";
        !          2012: $environment{"gather"}="ddollar:matrix,endmatrix;0;c:ddollar";
        !          2013: $environment{"gathered"}="matrix,endmatrix;0;c";
        !          2014: $environment{"array"}="arg2stack:matrix,endmatrixArg;1";
        !          2015:
        !          2016: # $environment{"pmatrix"}="beg_lr;(;):matrix,endmatrix;1;c";
        !          2017: $environment{"bmatrix"}="beg_lr;[;]:matrix,endmatrix;1;c";
        !          2018: $environment{"vmatrix"}="beg_lr;|;|:matrix,endmatrix;1;c";
        !          2019:
        !          2020: $type{"~"}="string";
        !          2021: $contents{"~"}=" ";
        !          2022:
        !          2023: $type{"\\,"}="string";
        !          2024: $contents{"\\,"}=" ";
        !          2025:
        !          2026: $type{"\\dots"}="string";
        !          2027: $contents{"\\dots"}="...";
        !          2028:
        !          2029: $type{"\\ldots"}="string";
        !          2030: $contents{"\\ldots"}="...";
        !          2031:
        !          2032: $type{"\\cdots"}="string";
        !          2033: $contents{"\\cdots"}="...";
        !          2034:
        !          2035: $type{"\\colon"}="string";
        !          2036: $contents{"\\colon"}=": ";
        !          2037:
        !          2038: $type{"\\mid"}="string";
        !          2039: $contents{"\\mid"}=" | ";
        !          2040:
        !          2041: $type{"\\smallsetminus"}="string";
        !          2042: $contents{"\\smallsetminus"}=" \\ ";
        !          2043:
        !          2044: $type{"\\setminus"}="string";
        !          2045: $contents{"\\setminus"}=" \\ ";
        !          2046:
        !          2047: $type{"\\backslash"}="string";
        !          2048: $contents{"\\backslash"}="\\";
        !          2049:
        !          2050: $type{"\\approx"}="string";
        !          2051: $contents{"\\approx"}=" ~ ";
        !          2052:
        !          2053: $type{"\\simeq"}="string";
        !          2054: $contents{"\\simeq"}=" ~ ";
        !          2055:
        !          2056: $type{"\\quad"}="string";
        !          2057: $contents{"\\quad"}="   ";
        !          2058:
        !          2059: $type{"\\qquad"}="string";
        !          2060: $contents{"\\qquad"}="     ";
        !          2061:
        !          2062: $type{"\\to"}="string";
        !          2063: $contents{"\\to"}=" --> ";
        !          2064:
        !          2065: $type{"\\from"}="string";
        !          2066: $contents{"\\from"}=" <-- ";
        !          2067:
        !          2068: $type{"\\wedge"}="string";
        !          2069: $contents{"\\wedge"}="/\\";
        !          2070:
        !          2071: $type{"\\Lambda"}="string";
        !          2072: $contents{"\\Lambda"}="/\\";
        !          2073:
        !          2074: $type{"\\ltimes"}="string";
        !          2075: $contents{"\\ltimes"}=" |>< ";
        !          2076:
        !          2077: $type{"\\lhd"}="string";
        !          2078: $contents{"\\lhd"}=" <| ";
        !          2079:
        !          2080: $type{"\\rhd"}="string";
        !          2081: $contents{"\\rhd"}=" |> ";
        !          2082:
        !          2083: $type{"\\cdot"}="string";
        !          2084: $contents{"\\cdot"}=" . ";
        !          2085:
        !          2086: # $type{"\dot"}="string";
        !          2087: # $contents{"\\dot"}=" . ";
        !          2088:
        !          2089: $type{"\\circ"}="string";
        !          2090: $contents{"\\circ"}=" o ";
        !          2091:
        !          2092: $type{"\\bullet"}="string";
        !          2093: $contents{"\\bullet"}="\@";
        !          2094:
        !          2095: $type{"\\infty"}="string";
        !          2096: $contents{"\\infty"}="oo";
        !          2097:
        !          2098: $type{"\\rtimes"}="string";
        !          2099: $contents{"\\rtimes"}=" ><| ";
        !          2100:
        !          2101: $type{"\\times"}="string";
        !          2102: $contents{"\\times"}=" >< ";
        !          2103:
        !          2104: $type{"\\hookrightarrow"}="string";
        !          2105: $contents{"\\hookrightarrow"}=" c--> ";
        !          2106:
        !          2107: $type{"\\hookleftarrow"}="string";
        !          2108: $contents{"\\hookleftarrow"}=" <--j ";
        !          2109:
        !          2110: $type{"\\longleftarrow"}="string";
        !          2111: $contents{"\\longleftarrow"}=" <----- ";
        !          2112:
        !          2113: $type{"\\longleftrightarrow"}="string";
        !          2114: $contents{"\\longleftrightarrow"}=" <----> ";
        !          2115:
        !          2116: $type{"\\longrightarrow"}="string";
        !          2117: $contents{"\\longrightarrow"}=" -----> ";
        !          2118:
        !          2119: $type{"\\rightarrow"}="string";
        !          2120: $contents{"\\rightarrow"}=" ---> ";
        !          2121:
        !          2122: $type{"\\leftarrow"}="string";
        !          2123: $contents{"\\leftarrow"}=" <--- ";
        !          2124:
        !          2125: $type{"\\mapsto"}="string";
        !          2126: $contents{"\\mapsto"}=" |--> ";
        !          2127:
        !          2128: $type{"\\longmapsto"}="string";
        !          2129: $contents{"\\longmapsto"}=" |----> ";
        !          2130:
        !          2131: $type{"\\cap"}="string";
        !          2132: $contents{"\\cap"}=" /~\\ ";
        !          2133:
        !          2134: $type{"\\cup"}="string";
        !          2135: $contents{"\\cup"}=" \\_/ ";
        !          2136:
        !          2137: $type{"\\section"}="string";
        !          2138: $contents{"\\section"}="Section ";
        !          2139:
        !          2140: $type{"\\subsection"}="string";
        !          2141: $contents{"\\subsection"}="Subsection ";
        !          2142:
        !          2143: $type{"\|"}="string";
        !          2144: $contents{"\|"}="||";
        !          2145:
        !          2146: $type{'\;'}="string";
        !          2147: $contents{'\;'}=" ";
        !          2148:
        !          2149: $type{'\noindent'}="string";
        !          2150: $contents{'\noindent'}="";
        !          2151:
        !          2152:
        !          2153: &define('\\define','\\def');
        !          2154: &define('\\ge','\\geq');
        !          2155: &define('\\le','\\leq');
        !          2156: &define('\\ne','\\neq');
        !          2157: &define('\\langle','<');
        !          2158: &define('\\rangle','>');
        !          2159: &define('\\subheading','\\par\\underline');
        !          2160: &define('\\(','$');
        !          2161: &define('\\)','$');
        !          2162: &define('\\[','$$');
        !          2163: &define('\\]','$$');
        !          2164: &define('\\centerline#1','$$#1$$');
        !          2165: &define('\\eqalign#1','\\aligned #1 \\endaligned');
        !          2166: &define('\\cr','\\\\');
        !          2167: &define('\\sb','_');
        !          2168: &define('\\sp','^');
        !          2169: &define('\\proclaim','\\noindent ');
        !          2170: &defb("matrix","vmatrix","Vmatrix","smallmatrix","bmatrix","Sp","Sb",
        !          2171:       "CD","align","aligned","split","multiline","gather","gathered");
        !          2172:
        !          2173: if ($opt_TeX) {
        !          2174:   &define('\pmatrix#1','\left(\begin{matrix}#1\end{matrix}\right)');
        !          2175: } else {
        !          2176:   $environment{"pmatrix"}="beg_lr;(;):matrix,endmatrix;1;c";
        !          2177:   &defb("pmatrix") unless $opt_TeX;
        !          2178: }
        !          2179:
        !          2180:
        !          2181:   ## All the records should be specified before this point
        !          2182:   {local(@a)=grep("record" eq $type{$_},keys %type);
        !          2183:                for (@a) {chop $contents{$_} if
        !          2184:       substr($contents{$_},length($contents{$_})-1,1) eq "\n";}}
        !          2185:
        !          2186: for ("oplus","otimes","cup","wedge") {
        !          2187:   $type{"\\big$_"}=$type{"\\$_"};
        !          2188:   $contents{"\\big$_"}=$contents{"\\$_"};
        !          2189: }
        !          2190:
        !          2191:
        !          2192: @level=(0);
        !          2193: @chunks=(0);
        !          2194: @tokenByToken=(0);
        !          2195: @out=();
        !          2196: $curlength=0;
        !          2197: $debug_flow=1;
        !          2198: $debug_record=2;
        !          2199: $debug_parsing=4;
        !          2200: $debug_length=8;
        !          2201: $debug_matrix=16;
        !          2202: #$debug |= $debug_flow | $debug_record | $debug_parsing | $debug_length;
        !          2203: #$debug |= $debug_flow;
        !          2204: #$debug |= $debug_record;
        !          2205: #$debug |= $debug_parsing;
        !          2206: #$debug |= $debug_length;
        !          2207: #$debug |= $debug_matrix;
        !          2208:
        !          2209:
        !          2210: $/ = $opt_by_par ? "\n\n" : ''; # whole paragraph mode
        !          2211: while (&paragraph()) { 1 }
        !          2212: &finishBuffer;
        !          2213:
        !          2214: __END__
        !          2215:
        !          2216: # History: Jul 98: \choose added, fixed RE for \noindent, \eqalign and \cr.
        !          2217: #                      \proclaim and better \noindent added.
        !          2218: # Sep 98: last was used inside an if block, was leaking out.
        !          2219: # Jan 00: \sb \sp
        !          2220: # Feb 00: remove extraneous second EOF needed at end.
        !          2221:          remove an empty line at end of output
        !          2222:          New option -by_par to support per-paragraph processing
        !          2223:          New option -TeX which support a different \pmatrix
        !          2224:          New option -ragged to not insert whitespace to align right margin.
        !          2225:          New option -noindent to not insert whitespace at beginning.
        !          2226:          Ignore \\ and \cr if followed by \end{whatever}.
        !          2227:          Ignore \noindent if not important.
        !          2228:          Ignore whitespace paragraphs.
        !          2229: # Apr 00: Finishing a level 1 would not merge things into one chunk.
        !          2230: # May 00: Additional argument to finish() to distinguish finishing
        !          2231:          things which cannot be broken between lines.
        !          2232: # Sep 00: Add support for new macro for strings with screen escapes sequences:
        !          2233:          \LITERALnoLENGTH{escapeseq}.
        !          2234: # Oct 00: \LITERALnoLENGTH can have a chance to work in the baseline only;
        !          2235:           in fact the previous version did not work even there...
        !          2236:          If the added record is longer than line length, do not try to
        !          2237:          break the line before it...

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>