Annotation of OpenXM_contrib/pari-2.2/misc/tex2mail.in, Revision 1.2
1.1 noro 1: #!@perl@
2:
1.2 ! noro 3: # $Id: tex2mail.in,v 1.2 2002/04/27 21:00:46 karim Exp $
1.1 noro 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];}
1.2 ! noro 740: local($LHS,$RHS);
! 741: $LHS = int($left/2); $RHS = $left - $LHS;
1.1 noro 742: local($out,$first)=("",1);
743: for (split(/\n/,$str1,$h1)) {
744: if ($first) {$first=0;}
745: else {$out .= "\n";}
1.2 ! noro 746: $out .= " " x $LHS. $_ . " " x $RHS;
1.1 noro 747: }
748: return "$h1,$len,$b1,0,$out";
749: }
750:
751: # Example of radical
752: #<<'EOF';
753: # +--+
754: #\|12
755: #EOF
756: <<EOF; # To hide HERE-DOC start above from old CPerl
757: EOF
758:
759: # Takes the last record, returns a record that contains it and forms
760: # radical block
761:
762: sub f_radical {
763: warn "Entering f_radical...\n" if $debug & $debug_flow;
764: &trim(1);
765: &collapse(1);
766: &assertHave(1) || &finish("",1);
767: warn "Radical of $out[$#out]\n__END__\n" if $debug & $debug_record;
768: local($h,$l,$b)=($out[$#out] =~ /^(\d+),(\d+),(\d+)/g);
769: $h || $h++;
770: local($out,$b1,$h1);
771: $out=&vStack(&string2record(("-" x $l)."+" ),$out[$#out]);
772: $b1=$b+1;
773: $h1=$h+1;
774: #$out =~ s/^(\d+,\d+,)(\d+)/\1$b1/;
775: &setbaseline($out,$b1);
776: $out[$#out]=&join("$h1,2,$b1,0, +\n" . (" |\n" x ($h-1)) . '\|',$out);
777: warn "a:Last $#chunks, the first on the last level=$#level is $level[$#level]" if $debug & $debug_flow;
778: &finish(1,1);
779: }
780:
781: # Takes the last two records, returns a record that contains them and forms
782: # fraction block
783:
784: sub f_fraction {
785: warn "Entering f_fraction...\n" if $debug & $debug_flow;
786: &trim(2);
787: &collapse(2);
788: &assertHave(2) || &finish("",1);
789: warn "Numer `$out[$#out-1]'\nDenom `$out[$#out]'\n__END__\n" if $debug & $debug_record;
790: local($l1,$l2)=(&length($out[$#out-1]),&length($out[$#out]));
791: local($len)=(($l1>$l2 ? $l1: $l2));
792: $out[$#out-1]=&vStack(&vStack(¢er($len,$out[$#out-1]),
793: &string2record("-" x $len)),
794: ¢er($len,$out[$#out]));
795: $#chunks--;
796: $#out--;
797: warn "a:Last $#chunks, the first on the last level=$#level is $level[$#level]" if $debug & $debug_flow;
798: &finish(2,1);
799: }
800:
801: sub f_choose {
802: warn "Entering f_choose...\n" if $debug & $debug_flow;
803: &trim(2);
804: &collapse(2);
805: &assertHave(2) || &finish("",1);
806: warn "Numer `$out[$#out-1]'\nDenom `$out[$#out]'\n__END__\n" if $debug & $debug_record;
807: local($l1,$l2)=(&length($out[$#out-1]),&length($out[$#out]));
808: local($len)=(($l1>$l2 ? $l1: $l2));
809: $out[$#out]=&vStack(&vStack(¢er($len,$out[$#out-1]),
810: &string2record(" " x $len)),
811: ¢er($len,$out[$#out]));
812: $#chunks++;
813: $#out++;
814: #warn "a:Last $#chunks, the first on the last level=$#level is $level[$#level]" if $debug & $debug_flow;
815: $out[$#out - 2] = &string2record("(");
816: $out[$#out] = &string2record(")");
817: local($h,$b)=($out[$#out-1] =~ /^(\d+),\d+,(\d+)/)[0,1];
818: &makehigh($out[$#out-2],$h,$b,0,1);
819: &makehigh($out[$#out],$h,$b,1,0);
820: &finish(2,1);
821: }
822:
823:
824: sub f_buildrel {
825: warn "Entering f_buildrel...\n" if $debug & $debug_flow;
826: &trim(3);
827: &collapse(3);
828: &assertHave(3) || &finish("",1);
829: warn "What: $out[$#out-2]\nOver $out[$#out]\n__END__\n" if $debug & $debug_record;
830: local($rec)=($out[$#out-2]);
831: $out[$#out-2]=$out[$#out];
832: $#chunks-=2;
833: $#out-=2;
834: &f_putover($rec,1);
835: warn "a:Last $#chunks, the first on the last level=$#level is $level[$#level]" if $debug & $debug_flow;
836: &finish(3,1);
837: }
838:
839: # Takes two records, returns a record that contains them and forms a
840: # fraction block
841:
842: sub fraction {
843: local($l1,$l2)=(&length($_[0]),&length($_[1]));
844: local($len)=(($l1>$l2 ? $l1: $l2));
845: return &vStack(&vStack(¢er($len,shift),
846: &string2record("-" x $len)),
847: ¢er($len,shift));
848: }
849:
850: # Commits a given string
851:
852: sub puts {
853: &commit(&string2record);
854: }
855:
856: # digests an eaten paragraph
857:
858: sub paragraph {
859: local($par);
860: $par=<>;
861: return 0 unless defined $par;
862: return 1 unless $par =~ /\S/; # whitespace only
863: print "\n" if $secondtime++ && !$opt_by_par;
864: #$par =~ s/(^|[^\\])%.*\n[ \t]*/\1/g;
865: $par =~ s/((^|[^\\])(\\\\)*)(%.*\n[ \t]*)+/\1/g;
866: $par =~ s/\n\s*\n/\\par /g;
867: $par =~ s/\s+/ /g;
868: $par =~ s/\s+$//;
869: $par =~ s/(\$\$)\s+/\1/g;
870: $par =~ s/\\par\s*$//;
871: local($defcount,$piece,$pure,$type,$sub,@t,$arg)=(0);
872: &commit("1,5,0,0, ")
873: unless $opt_noindent || ($par =~ s/^\s*\\noindent\s*([^a-zA-Z\s]|$)/\1/);
874: while ($tokenByToken[$#level] ?
875: ($par =~ s/^\s*($tokenpattern)//o): ($par =~ s/^($multitokenpattern)//o)) {
876: warn "tokenByToken=$tokenByToken[$#level], eaten=`$1'\n"
877: if $debug & $debug_parsing;
878: if (($piece=$1) =~ /^$usualtokenclass/o) {
879: # plain piece
880: &puts($piece);
881: } else {
882: # macro or delimiter
883: ($pure = $piece) =~ s/\s+$//;
884: if (defined ($type=$type{$pure})) {
885: if ($type eq "def") {
886: warn "To many def expansions in a paragraph" if $defcount++==$maxdef;
887: last if $defcount>$maxdef;
888: @t=(0);
889: for (1..$args{$pure}) {
890: push(@t,&get_balanced());
891: }
892: warn "Defined token `$pure' found with $args{$pure} arguments @t[1..$#t]\n"
893: if $debug & $debug_parsing;
894: $sub=$def{$pure};
895: $sub =~ s/(^|[^\\#])#(\d)/$1 . $t[$2]/ge if $args{$pure};
896: $par=$sub . $par;
897: } elsif ($type eq "sub") {
898: $sub=$contents{$pure};
899: index($sub,";")>=0?
900: (($sub,$arg)=split(";",$sub,2), &$sub($pure,$arg)):
901: &$sub($pure);
902: } elsif ($type =~ /^sub(\d+)$/) {
903: &start($1,"f_$contents{$pure}");
904: $tokenByToken[$#level]=1;
905: } elsif ($type =~ /^get(\d+)$/) {
906: &start($1+1);
907: &puts($piece);
908: $tokenByToken[$#level]=1;
909: } elsif ($type =~ /^discard(\d+)$/) {
910: &start($1,"f_discard");
911: $tokenByToken[$#level]=1;
912: } elsif ($type eq "record") {
913: &commit($contents{$pure});
914: } elsif ($type eq "self") {
915: &puts(substr($pure,1) . ($pure =~ /^\\[a-zA-Z]/ ? " ": ""));
916: } elsif ($type eq "par_self") {
917: &finishBuffer;
918: &commit("1,5,0,0, ");
919: &puts($pure . ($pure =~ /^\\[a-zA-Z]/ ? " ": ""));
920: } elsif ($type eq "self_par") {
921: &puts($pure . ($pure =~ /^\\[a-zA-Z]/ ? " ": ""));
922: &finishBuffer;
923: &commit("1,5,0,0, ")
924: unless $par =~ s/^\s*\\noindent(\s+|([^a-zA-Z\s])|$)/\2/;
925: } elsif ($type eq "string") {
926: &puts($contents{$pure},1);
927: } elsif ($type eq "nothing") {
928: } else {
929: warn "Error with type `$type' while interpreting `$pure'";
930: }
931: } else {
932: &puts($piece);
933: }
934: }
935: }
936: warn "Unrecognized part of input `$par',\n\ttoken-by-token[$#level]=$tokenByToken[$#level]"
937: if $par ne "";
938: &finishBuffer if $#out>=0;
939: # return 0 if eof();
940: 1;
941: }
942:
943: sub subscript {
944: &start(1,"f_subscript");
945: $tokenByToken[$#level]=1;
946: }
947:
948: sub superscript {
949: &start(1,"f_superscript");
950: $tokenByToken[$#level]=1;
951: }
952:
953:
954: sub f_subscript {
955: $wait[$#level]=2;
956: $action[$#level]="f_subSuper";
957: if (($par !~ s/^\s*\^//) &&
958: ($par !~ s:^\s*\\begin\s*\{Sp\}:\\begin\{matrix\}:)) {
959: &commit(&empty);
960: }
961: }
962:
963: sub f_overline {
964: warn "Entering f_overline...\n" if $debug & $debug_flow;
965: &trim(1);
966: &collapse(1);
967: &assertHave(1) || &finish("",1);
968: warn "Overlining $out[$#out]\n__END__\n" if $debug & $debug_record;
969: local($h,$len,$b)=($out[$#out] =~ /^(\d+),(\d+),(\d+)/);
970: $out[$#out]=&vStack(&string2record("_" x $len),
971: $out[$#out]);
972: $b++;
973: #$out[$#out] =~ s/^(\d+,\d+,)(\d+)/\1$b/;
974: &setbaseline($out[$#out],$b);
975: warn "a:Last $#chunks, the first on the last level=$#level is $level[$#level]" if $debug & $debug_flow;
976: &finish(1,1);
977: }
978:
979: sub f_underline {
980: warn "Entering f_underline...\n" if $debug & $debug_flow;
981: &trim(1);
982: &collapse(1);
983: &assertHave(1) || &finish("",1);
984: warn "Underlining $out[$#out]\n__END__\n" if $debug & $debug_record;
985: local($h,$len,$b)=($out[$#out] =~ /^(\d+),(\d+),(\d+)/);
986: $out[$#out]=&vStack($out[$#out],&string2record("_" x $len));
987: #$out[$#out] =~ s/^(\d+,\d+,)(\d+)/\1$b/;
988: &setbaseline($out[$#out],$b);
989: warn "a:Last $#chunks, the first on the last level=$#level is $level[$#level]" if $debug & $debug_flow;
990: &finish(1,1);
991: }
992:
993: sub f_not {
994: warn "Entering f_not...\n" if $debug & $debug_flow;
995: &collapse(1);
996: &assertHave(1) || &finish("",1);
997: warn "Negating $out[$#out]\n__END__\n" if $debug & $debug_record;
998: local($str)=(split(/,/,$out[$#out]))[4];
999: if ($str eq "=") {
1000: $out[$#out]=$contents{"\\neq"};
1001: } elsif ($str =~ /^\s*\|\s*$/) {
1002: $out[$#out]=$contents{"\\nmid"};
1003: } elsif ($out[$#out] eq $contents{"\\in"}) {
1004: $out[$#out]=$contents{"\\notin"};
1005: } else {
1006: $out[$#out]=&join(&string2record("\\not"),$out[$#out]);
1007: }
1008: warn "a:Last $#chunks, the first on the last level=$#level is $level[$#level]" if $debug & $debug_flow;
1009: &finish(1,1);
1010: }
1011:
1012: sub f_putunder {
1013: warn "Entering f_putunder...\n" if $debug & $debug_flow;
1014: &trim(1);
1015: &collapse(1);
1016: &assertHave(1) || &finish("",1);
1017: warn "Putting Under $out[$#out]\n__END__\n" if $debug & $debug_record;
1018: local($h,$len,$b)=($out[$#out] =~ /^(\d+),(\d+),(\d+)/);
1019: local($l2)=(&length($_[0]));
1020: local($len)=(($l1>$l2 ? $l1: $l2));
1021: $out[$#out]=&vStack(¢er($len,$out[$#out]),¢er($len,shift));
1022: #$out[$#out] =~ s/^(\d+,\d+,)(\d+)/\1$b/;
1023: &setbaseline($out[$#out],$b);
1024: warn "a:Last $#chunks, the first on the last level=$#level is $level[$#level]" if $debug & $debug_flow;
1025: &finish(1,1);
1026: }
1027:
1028: # if has additional true argument will not finish
1029: # Takes record to put over
1030:
1031: sub f_putover {
1032: warn "Entering f_putover...\n" if $debug & $debug_flow;
1033: &trim(1);
1034: &collapse(1);
1035: &assertHave(1) || &finish("",1);
1036: warn "Putting Over $out[$#out]\n__END__\n" if $debug & $debug_record;
1037: local($h,$l1,$b,$b1)=($out[$#out] =~ /^(\d+),(\d+),(\d+)/);
1038: local($l2)=(&length($_[0]));
1039: local($len)=(($l1>$l2 ? $l1: $l2));
1040: ($b1)=($_[0] =~ /^(\d+)/);
1041: $b+=$b1+1;
1042: $out[$#out]=&vStack(¢er($len,shift),¢er($len,$out[$#out]));
1043: #$out[$#out] =~ s/^(\d+,\d+,)(\d+)/\1$b/;
1044: &setbaseline($out[$#out],$b);
1045: warn "a:Last $#chunks, the first on the last level=$#level is $level[$#level]" if $debug & $debug_flow;
1046: &finish(1,1) unless shift;
1047: }
1048:
1049: sub f_putpar {
1050: warn "Entering f_putpar...\n" if $debug & $debug_flow;
1051: &trim(1);
1052: local($l,$r)=split(";",shift);
1053: &collapse(1);
1054: &assertHave(1) || &finish("",1);
1055: warn "Putting Parentheses $out[$#out]\n__END__\n" if $debug & $debug_record;
1056: $out[$#out]=&join(&string2record($l),
1057: &join($out[$#out],&string2record($r)));
1058: &finish(1,1);
1059: }
1060:
1061: sub f_putover_string {
1062: &f_putover(&string2record);
1063: }
1064:
1065: sub f_widehat {
1066: &trim(1);
1067: &collapse(1);
1068: local($l)=(&length($out[$#out]));
1069: if ($l<=1) {&f_putover(&string2record("^"));}
1070: else {&f_putover(&string2record("/" . "~" x ($l-2) . "\\"));}
1071: }
1072:
1073: sub f_widetilde {
1074: &trim(1);
1075: &collapse(1);
1076: local($l,$l1)=(&length($out[$#out]));
1077: if ($l<=1) {&f_putover(&string2record("~"));}
1078: elsif ($l<=3) {&f_putover(&string2record("/\\/"));}
1079: else {&f_putover(&string2record("/" . "~" x ($l1=int($l/2-1)) .
1080: "\\" . "_" x ($l-3-$l1) . "/"));}
1081: }
1082:
1083: sub f_superscript {
1084: $wait[$#level]=2;
1085: $action[$#level]="f_superSub";
1086: if (($par !~ s/^\s*\_//) &&
1087: ($par !~ s:^\s*\\begin\s*\{Sb\}:\\begin\{matrix\}:)) {
1088: &commit(&empty);
1089: }
1090: }
1091:
1092: sub let {
1093: $par =~ s/^($tokenpattern)(= ?)?($tokenpattern)//o;
1094: }
1095:
1096: sub let_exp {
1097: $par =~ s/^($tokenpattern)(= ?)?($tokenpattern)//o;
1098: return if index($&,'@')>=0;
1099: local($what)=$1;
1100: $type{$what}='def';
1101: $& =~ /($tokenpattern)$/;
1102: $def{$what}=$1;
1103: $args{$what}=0;
1104: warn "Definition of `$what' with $args{$what} args is `$def{$what}'\n"
1105: if $debug & $debug_parsing;
1106: }
1107:
1108:
1109: sub def {
1110: $par =~ s/^[^{]*//;
1111: &start(1,"f_discard");
1112: $tokenByToken[$#level]=1;
1113: }
1114:
1115: sub def_exp {
1116: return unless $par =~ s:^(([^\\{]|\\.)*)\{:\{:;
1117: local($arg)=($1);
1118: local($def,$act)=(&get_balanced());
1119: return unless defined $def;
1120: return if index("$arg$def",'@')>=0;
1121: return if $def =~ /\\([egx]?def|fi)([^a-zA-Z]|$)/;
1122: $def .= " " if $def =~ /($macro)$/o;
1123: &define($arg,$def);
1124: }
1125:
1126: # Arguments: Token . Parameters, Expansion
1127:
1128: sub define {
1129: local($arg,$def,$act)=(shift,shift);
1130: return unless $arg =~ /^($active)/o;
1131: $act=$1;
1132: $args{$act}=$';
1133: return unless $args{$act} =~ /^(#\d)*$/;
1134: $args{$act}=length($args{$act})/2;
1135: $def{$act}=$def;
1136: $type{$act}='def';
1137: warn "Definition of `$act' with $args{$act} args is `$def'\n"
1138: if $debug & $debug_parsing;
1139: }
1140:
1141: sub defb {
1142: for (@_) {
1143: &define("\\$_","\\begin{$_}");&define("\\end$_","\\end{$_}");
1144: }
1145: }
1146:
1147: # Discards surrounding {}
1148:
1149: sub get_balanced {
1150: return undef unless $par =~ s/^($tokenpattern)//;
1151: return $1 unless $1 eq '{';
1152: local($def,$lev)=('',1);
1153: while ($lev) {
1154: last unless $par =~ s/^[^\\{}]|\\.|[{}]//;
1155: $lev++ if $& eq '{';
1156: $lev-- if $& eq '}';
1157: $def .= $& if $lev;
1158: }
1159: (warn "Balanced text not finished!",return undef) if $lev;
1160: return $def;
1161: }
1162:
1163:
1164: sub open_curly {
1165: #&puts("{") unless $tokenByToken[$#level];
1166: &start("}");
1167: }
1168:
1169: # Deletes extra spaces at the end of a record
1170:
1171: sub trim_end {
1172: local($h,$str)=(split(/,/,$_[0],5))[0,4];
1173: if (!$h) {
1174: $str =~ s/\s+$//;
1175: $_[0]=&string2record($str);
1176: warn "Trimmed End `$_[0]'\n__END__\n" if $debug & $debug_record;
1177: }
1178: }
1179:
1180: # Deletes extra spaces at the beginning of a record
1181:
1182: sub trim_beg {
1183: local($h,$str)=(split(/,/,$_[0],5))[0,4];
1184: if (!$h) {
1185: $str =~ s/^\s+//;
1186: $_[0]=&string2record($str);
1187: warn "Trimmed Beg `$_[0]'\n__END__\n" if $debug & $debug_record;
1188: }
1189: }
1190:
1191: # Deletes extra spaces at the ends of a chunk with given number
1192:
1193: sub trim_one {
1194: &trim_beg($out[$chunks[$_[0]]]);
1195: &trim_end($_[0]==$#chunks? $out[$#out]: $out[$chunks[$_[0]+1]-1]);
1196: }
1197:
1198: # Deletes extra spaces at the ends of a given number of chunks
1199:
1200: sub trim {
1201: for ($#chunks-$_[0]+1..$#chunks) {&trim_one($_);}
1202: }
1203:
1204: sub dollar {
1205: if ($wait[$#level] eq '$') { # ';
1206: &trim_end($out[$#out]);
1207: &finish('$');
1208: }
1209: else {
1210: &start('$');
1211: $par =~ s/^\s+//;
1212: }
1213: }
1214:
1215: sub ddollar {
1216: if ($wait[$#level] eq '$$') {
1217: &trim_end($out[$#out]);
1218: &finish('$$');
1219: return unless $#out>=0;
1220: $#chunks=0;
1221: $chunks[0]=0;
1222: &trim(1);
1223: &collapse(1);
1224: &printrecord(¢er($linelength,$out[0]));
1225: @level=(0);
1226: @chunks=(0);
1227: @tokenByToken=(0);
1228: @out=();
1229: $curlength=0;
1230: # Maybe after \begin{align}
1231: }
1232: else {
1233: &finishBuffer;
1234: &start('$$');
1235: }
1236: $par =~ s/^\s+//;
1237: }
1238:
1239: sub item {
1240: &finishBuffer;
1241: # To make unexpandable:
1242: &commit("1,11,0,0, (\@) ");
1243: }
1244:
1245: sub bbackslash {
1246: if ($wait[$#level] eq '$$') {
1247: &ddollar();
1248: &ddollar();
1249: } elsif ($wait[$#level] eq 'endCell') {
1250: return if $par =~ /^\s*\\end/; # Ignore the last one
1251: &finish('endCell', 1);
1252: &trim(1);
1253: &collapse(1);
1254: &finish('endRow', 1);
1255: &start('endRow');
1256: &start('endCell');
1257: } else {
1258: #&puts(" \\\\ ");
1259: ∥
1260: }
1261: }
1262:
1263: sub ampersand {
1264: if ($wait[$#level] eq 'endCell') {
1265: &finish('endCell',1);
1266: &trim(1);
1267: &collapse(1);
1268: &start('endCell');
1269: }
1270: }
1271:
1272: sub matrix {
1273: &start('endMatrix');
1274: &start('endRow');
1275: &start('endCell');
1276: }
1277:
1278: sub endmatrix {
1279: &finish('endCell',1);
1280: &trim(1);
1281: &collapse(1);
1282: &finish('endRow',1);
1283: # Now chunks correspond to rows of the matrix, records inside chunks to
1284: # Cells
1285: &halign(split(";",shift));
1286: &finish('endMatrix',1);
1287: }
1288:
1289: sub endmatrixArg {
1290: &endmatrix(join(";",($_[0],split("",pop(@argStack)))));
1291: }
1292:
1293: # Takes a matrix in the following form: chunks on the last level
1294: # are row of the matrix, records inside chunks are cells.
1295: # Puts the resulting matrix in the first record on the given level
1296: # and truncates the rest
1297:
1298: # I'm trying to add parameters:
1299: # length to insert between columns
1300: # Array of centering options one for a column (last one repeated if needed)
1301: # Currently supported: c for center
1302: # r for right
1303: # l for left
1304:
1305: sub halign {
1306: local($explength)=(shift);
1307: local(@c)=@_;
1308: local($last,$le,$b,$h);
1309: local(@w)=();
1310: #warn "levels @level, chunks @chunks, records @out\n";
1311: # Find metrics of cells
1312: for $r (0..$#chunks-$level[$#level]) {
1313: $last= ($r==$#chunks-$level[$#level]) ? $#out:
1314: $chunks[$r+1+$level[$#level]]-1;
1315: warn "Row $r: last column " . ($last-$chunks[$r+$level[$#level]]) ."\n"
1316: if $debug & $debug_matrix;
1317: for $c (0..$last-$chunks[$r+$level[$#level]]) {
1318: ($h,$le,$b)=
1319: ($out[$chunks[$r+$level[$#level]]+$c] =~ /(\d+),(\d+),(\d+)/);
1320: # Format is Height:Length:Baseline
1321: $w[$c]=$le unless $w[$c]>$le;
1322: }
1323: }
1324: # expand the height and depth
1325: for $c (0..$#w-1) {$w[$c]+=$explength;}
1326: # Extend the @c array by the last element or "c" if it is empty
1327: @c=("c") x @w unless @c;
1328: @c=(@c,($c[$#c]) x (@w-@c));
1329: # Now expand the cells
1330: warn "Widths of columns @w\n" if $debug & $debug_matrix;
1331: for $r (0..$#chunks-$level[$#level]) {
1332: $last= ($r==$#chunks-$level[$#level]) ? $#out:
1333: $chunks[$r+1+$level[$#level]]-1;
1334: warn "Row $r: last column " . ($last-$chunks[$r+$level[$#level]]) ."\n"
1335: if $debug & $debug_matrix;
1336: for $c (0..$last-$chunks[$r+$level[$#level]]) {
1337: if ($c[$c] eq "c") {
1338: warn "Centering row $r col $c to width $w[$c]\n"
1339: if $debug & $debug_matrix;
1340: $out[$chunks[$r+$level[$#level]]+$c]=
1341: ¢er($w[$c],$out[$chunks[$r+$level[$#level]]+$c]);
1342: } elsif ($c[$c] eq "l") {
1343: warn "Expanding row $r col $c to width $w[$c]\n"
1344: if $debug & $debug_matrix;
1345: $out[$chunks[$r+$level[$#level]]+$c]=
1346: &join($out[$chunks[$r+$level[$#level]]+$c],
1347: &string2record(" " x
1348: ($w[$c] - &length($out[$chunks[$r+$level[$#level]]+$c]))));
1349: } elsif ($c[$c] eq "r") {
1350: warn "Expanding row $r col $c to width $w[$c] on the left\n"
1351: if $debug & $debug_matrix;
1352: $out[$chunks[$r+$level[$#level]]+$c]=
1353: &join(&string2record(" " x
1354: ($w[$c]-$explength-
1355: &length($out[$chunks[$r+$level[$#level]]+$c]))),
1356: $out[$chunks[$r+$level[$#level]]+$c]);
1357: $out[$chunks[$r+$level[$#level]]+$c]=
1358: &join($out[$chunks[$r+$level[$#level]]+$c],
1359: &string2record(" " x $explength));
1360: } else {warn "Unknown centering option `$c[$c]' for halign";}
1361: }
1362: }
1363: # Now we creat rows
1364: &collapseAll;
1365: # And stack them vertically
1366: for ($chunks[$level[$#level]]+1..$#out) {
1367: $out[$chunks[$level[$#level]]]=&vStack($out[$chunks[$level[$#level]]],
1368: $out[$_]);
1369: }
1370: &setbaseline($out[$chunks[$level[$#level]]],
1371: int((&height($out[$chunks[$level[$#level]]])-1)/2));
1372: $#chunks=$level[$#level];
1373: $#out=$chunks[$level[$#level]];
1374: }
1375:
1376: sub close_curly {
1377: &finish("}");
1378: #&puts("}") unless $tokenByToken[$#level]; # well, this can change under our foot...
1379: }
1380:
1381: sub at {
1382: local($c,$first,$second,$t,$m)=($par =~ /^(.)/);
1383: if ($c eq '@') {&puts('@');$par =~ s/^.//;}
1384: elsif (index("<>AV",$c)>=0) {
1385: $m="&" if ($wait[$#level] eq 'endCell');
1386: $m="&&" if $m eq "&" && index("AV",$c)>=0;
1387: &ersand if $m eq "&";
1388: $par =~ s/^.//;
1389: $first=$second="";
1390: while (($t=&get_balanced()) ne $c && defined $t) {
1391: $first .= $t;
1392: }
1393: while (($t=&get_balanced()) ne $c && defined $t) {
1394: $second .= $t;
1395: }
1396: $par="{$first}{$second}$m" . $par;
1397: local($l,$r);
1398: ($l=$c) =~ tr/A>V/^/d;
1399: ($r=$c) =~ tr/<A//d;
1400: index("<>",$c)>=0 ?
1401: &start(2,"f_arrow;$l;$r"):
1402: &start(2,"f_arrow_v;$l;$r");
1403: }
1404: elsif ($c eq "." && $wait[$#level] eq 'endCell') {
1405: &ersand;
1406: &ersand;
1407: $par =~ s/^.//;
1408: }
1409: else {&puts('@');}
1410: }
1411:
1412: # takes two tips of arrow as argument separated by ";",
1413: # we assume that total length is 1
1414:
1415: sub f_arrow {
1416: warn "Entering f_arrow...\n" if $debug & $debug_flow;
1417: local($l,$r)=split(";",shift);
1418: &trim(2);
1419: &collapse(2);
1420: &assertHave(2) || &finish("",1);
1421: warn "Over: $out[$#out-1]\nUnder: $out[$#out]\n__END__\n" if $debug & $debug_record;
1422: local($l1,$l2)=(&length($out[$#out-1]),&length($out[$#out]));
1423: local($len)=(($l1>$l2 ? $l1: $l2));
1424: $out[$#out-1]=&vStack(&vStack(¢er($len+4,$out[$#out-1]),
1425: &string2record(" $l" ."-" x ($len+1) . "$r ")),
1426: ¢er($len+4,$out[$#out]));
1427: $#chunks--;
1428: $#out--;
1429: warn "a:Last $#chunks, the first on the last level=$#level is $level[$#level]" if $debug & $debug_flow;
1430: &finish(2,1);
1431: }
1432:
1433: # takes two tips of arrow as argument separated by ";",
1434: # we assume that total length is 1
1435:
1436: sub f_arrow_v {
1437: warn "Entering f_arrow_v...\n" if $debug & $debug_flow;
1438: local($l,$r)=split(";",shift);
1439: &trim(2);
1440: &collapse(2);
1441: &assertHave(2) || &finish("",1);
1442: warn "Over: $out[$#out-1]\nUnder: $out[$#out]\n__END__\n" if $debug & $debug_record;
1443: local($h1,$b1)=($out[$#out-1] =~ /^(\d+),\d+,(\d+)/);
1444: local($h2,$b2)=($out[$#out] =~ /^(\d+),\d+,(\d+)/);
1445: local($b)=(($b1>$b2 ? $b1: $b2));
1446: local($res)=(&join($out[$#out-1],$out[$#out]));
1447: local($h,$bb)=($res =~ /^(\d+),\d+,(\d+)/);
1448: $bb=$b+1;
1449: $out[$#out-1]=&vStack(&vputs(" " x ($b-$b1+1)),
1450: $out[$#out-1]);
1451: #$out[$#out-1] =~ s/^(\d+,\d+,)(\d+)/\1$bb/;
1452: &setbaseline($out[$#out-1],$bb);
1453: $out[$#out]=&vStack(&vputs(" " x ($b-$b2+1)),
1454: $out[$#out]);
1455: #$out[$#out] =~ s/^(\d+,\d+,)(\d+)/\1$bb/;
1456: &setbaseline($out[$#out],$bb);
1457: $out[$#out-1]=&join(&join($out[$#out-1],
1458: &vputs($l ."|" x ($h+1) . $r,$b+1)),
1459: $out[$#out]);
1460: $#chunks--;
1461: $#out--;
1462: warn "a:Last $#chunks, the first on the last level=$#level is $level[$#level]" if $debug & $debug_flow;
1463: &finish(2,1);
1464: }
1465:
1466: sub noindent {
1467: if ($#out == 0 && $#chunks == 0 && $out[$#out] eq '1,5,0,0, ') {
1468: $#out--;
1469: $#chunks--;
1470: } else {
1471: &puts('\\noindent');
1472: }
1473: }
1474:
1475: # put strings vertically, returns a record with the second argument as baseline
1476:
1477: sub vputs {
1478: local($b)=($_[1]);
1479: $b=0 unless defined $b;
1480: return length($_[0]) . ",1,$b,0," . join("\n",split('',$_[0]));
1481: }
1482:
1483: sub choose {
1484: if ($wait[$#level] eq '}') {
1485: local($prevw)=($wait[$#level-1]);
1486: $wait[$#level-1]="junk";
1487: &finish("}",1);
1488: &collapse(1);
1489: &assertHave(1) || &finish("",1);
1490: local($rec)=$out[$#out];
1491: $#out--;
1492: $#chunks--;
1493: &start(2,"f_choose");
1494: $wait[$#level-1]=$prevw;
1495: &start("}");
1496: &commit($rec);
1497: &finish("}",1);
1498: &start("}");
1499: } else {&puts("\\choose");}
1500: }
1501:
1502: sub over {
1503: if ($wait[$#level] eq '}') {
1504: local($prevw)=($wait[$#level-1]);
1505: $wait[$#level-1]="junk";
1506: &finish("}", 1);
1507: &collapse(1);
1508: &assertHave(1) || &finish("",1);
1509: local($rec)=$out[$#out];
1510: $#out--;
1511: $#chunks--;
1512: &start(2,"f_fraction");
1513: $wait[$#level-1]=$prevw;
1514: &start("}");
1515: &commit($rec);
1516: &finish("}",1);
1517: &start("}");
1518: } else {&puts("\\over");}
1519: }
1520:
1521: # Takes a record, height, baseline, spaces_toleft and _toright
1522: # and makes this record this high
1523:
1524: sub makehigh {
1525: local($str)=(split(",",$_[0],5))[4];
1526: local($h,$b,$d)=($_[1],$_[2]+1);
1527: warn "Entering makehigh(@_)\n" if $debug & $debug_flow;
1528: if ($str eq ".") {$_[0] =~ s/\.$/ /;return;}
1529: #$str="<" if $str eq "\\langle";
1530: #$str=">" if $str eq "\\rangle";
1531: $h=1 unless $h;
1532: $d=$h-$b;
1533: return if $h<2 || $h==2 && index("()<>",$str)>=0;
1534: local(@c);
1535: if ($str eq "(") {@c=split(":",'(: :|:/:\:|');}
1536: elsif ($str eq ")") {@c=split(":",'): :|:\:/:|');}
1537: elsif ($str eq "{") {@c=split(":",'{: :|:/:\:<');}
1538: elsif ($str eq "}") {@c=split(":",'}: :|:\:/:>');}
1539: elsif ($str eq "|" && $str eq "||")
1540: {@c=split(":",'|:|:|:|:|:|');}
1541: elsif ($str eq "[") {@c=split(":",'[:[:|:[:[:|');}
1542: elsif ($str eq "]") {@c=split(":",']:]:|:]:]:|');}
1543: elsif ($str eq "<" || $str eq ">") {
1544: return if $h==2;
1545: local($l)=($b);
1546: $l=$d+1 if $b<$d+1;
1547: for (2..$l) {
1548: $_[0]=&join($_[0],
1549: &vputs("/" . " " x (2*$_-3) . "\\",$_-1)) if $str eq "<";
1550: $_[0]=&join(&vputs("\\" . " " x (2*$_-3) . "/",$_-1),
1551: $_[0]) if $str eq ">";
1552: }
1553: $_[0]=&join($_[0],&string2record(" ")) if $str eq "<";
1554: $_[0]=&join(&string2record(" "),$_[0]) if $str eq ">";
1555: return;
1556: }
1557: else {return;}
1558: $_[0]=&vputs(&makecompound($b,$d,@c),$b-1);
1559: $_[0]=&join($_[0],$_[0]) if length($str)==2;
1560: $_[0]=&join(&string2record(" " x $_[3]),$_[0]) if $_[3];
1561: $_[0]=&join($_[0],&string2record(" " x $_[4])) if $_[4];
1562: }
1563:
1564:
1565: sub right {
1566: &finish("LeftRight",1);
1567: &trim(1);
1568: &collapse(1);
1569: }
1570:
1571: sub f_left {
1572: &trim(1);
1573: &collapse(1);
1574: &finish(1);
1575: &start("LeftRight");
1576: }
1577:
1578: sub left {
1579: &start(3,"f_leftright");
1580: $tokenByToken[$#level]=1;
1581: &start(1,"f_left");
1582: $tokenByToken[$#level]=1;
1583: }
1584:
1585: sub f_leftright_go {
1586: &trim(1);
1587: &collapse(1);
1588: local($l,$r)=split(";",shift);
1589: &assertHave(1) || warn "Left-Right not balanced";
1590: local($rec)=($out[$#out]);
1591: $#out--;
1592: $wait[$#level]="junk";
1593: &start(3,"f_leftright");
1594: &puts($l);
1595: &commit($rec);
1596: &puts($r);
1597: &finish("junk");
1598: }
1599:
1600: sub beg_lr {
1601: &start(1,"f_leftright_go" . ";" . shift);
1602: $tokenByToken[$#level]=1;
1603: }
1604:
1605: sub f_leftright {
1606: &trim(1);
1607: &collapse(1);
1608: &assertHave(3) || warn "Left-Right not balanced";
1609: local($h,$b)=($out[$#out-1] =~ /^(\d+),\d+,(\d+)/)[0,1];
1610: &makehigh($out[$#out-2],$h,$b,0,1);
1611: &makehigh($out[$#out],$h,$b,1,0);
1612: &finish(3);
1613: }
1614:
1615: # Arguments: Ascent, descent, base string, oneside expander, real expander
1616: # 0 1 2 3 4
1617: # Top tip, Bottom tip, Mid
1618: # 5 6 7
1619: # All component should be one character long
1620:
1621: sub makecompound {
1622: # If Mid is the same as real expander, all depends on the height only
1623: # if there is extend on both sides
1624: # If it is 3 or more
1625: if ($_[0]>1 && $_[1]>0 && $_[4] eq $_[7]) {
1626: return $_[5] . $_[4] x ($_[0]+$_[1]-2) . $_[6];
1627: }
1628: # No descent:
1629: if ($_[1] <= 0) {return $_[3] x ($_[0]-1) . $_[2];}
1630: # No ascent:
1631: if ($_[0] <= 1) {return $_[2] . $_[3] x $_[1];}
1632: local($mid,$asc,$des)=($_[2]);
1633: # descent == 1
1634: $des = ($_[1]==1) ? $_[2]: $_[4] x ($_[1]-1) . $_[6];
1635: $asc = ($_[0]==2) ? $_[2]: $_[5] . $_[4] x ($_[0]-2);
1636: $mid = $_[7] unless $_[0]==2 || $_[1]==1;
1637: return "$asc$mid$des";
1638: }
1639:
1640: sub arg2stack {push(@argStack,&get_balanced());}
1641:
1642: sub par {&finishBuffer;&commit("1,5,0,0, ")
1643: unless $par =~ s/^\s*\\noindent\s*(\s+|([^a-zA-Z\s])|$)/\2/;}
1644:
1645: $type{"\\sum"}="record";
1646: $contents{"\\sum"}="3,4,1,0," . <<'EOF';
1647: \~~
1648: >
1649: /__
1650: EOF
1651:
1652: $type{"\\int"}="record";
1653: $contents{"\\int"}="3,3,1,0," . <<'EOF';
1654: ,-
1655: |
1656: -'
1657: EOF
1658:
1659: $type{"\\prod"}="record";
1660: $contents{"\\prod"}="3,3,1,0," . <<'EOF';
1661: ___
1662: | |
1663: | |
1664: EOF
1665:
1666: $type{"\\Pi"}="record";
1667: $contents{"\\Pi"}="2,3,1,0," . <<'EOF';
1668: _
1669: | |
1670: EOF
1671:
1672: $type{"\\Sigma"}="record";
1673: $contents{"\\Sigma"}="3,2,1,0," . <<'EOF';
1674: __
1675: >
1676: ~~
1677: EOF
1678:
1679: $type{"\\Delta"}="record";
1680: $contents{"\\Delta"}="2,2,0,0," . <<'EOF';
1681: /\
1682: ~~
1683: EOF
1684:
1685: $type{"\\oplus"}="record";
1686: $contents{"\\oplus"}="3,5,1,0," . <<'EOF';
1687: _
1688: (+)
1689: ~
1690: EOF
1691:
1692: $type{"\\otimes"}="record";
1693: $contents{"\\otimes"}="3,5,1,0," . <<'EOF';
1694: _
1695: (x)
1696: ~
1697: EOF
1698:
1699: $type{"\\ominus"}="record";
1700: $contents{"\\ominus"}="3,5,1,0," . <<'EOF';
1701: _
1702: (-)
1703: ~
1704: EOF
1705:
1706: $type{"\\leq"}="record";
1707: $contents{"\\leq"}="2,4,1,0," . <<'EOF';
1708: _
1709: <
1710: EOF
1711:
1712: $type{"\\equiv"}="record";
1713: $contents{"\\equiv"}="2,4,1,0," . <<'EOF';
1714: _
1715: =
1716: EOF
1717:
1718: $type{"\\geq"}="record";
1719: $contents{"\\geq"}="2,4,1,0," . <<'EOF';
1720: _
1721: >
1722: EOF
1723:
1724: $type{"\\partial"}="record";
1725: $contents{"\\partial"}="2,2,1,0," . <<'EOF';
1726: \
1727: d
1728: EOF
1729:
1730: $type{"\\forall"}="record";
1731: $contents{"\\forall"}="3,4,1,0," . <<'EOF';
1732: \__/
1733: \/
1734: EOF
1735:
1736: $type{"\\exists"}="record";
1737: $contents{"\\exists"}="3,2,1,0," . <<'EOF';
1738: _.
1739: -|
1740: ~'
1741: EOF
1742:
1743: $type{"\\owns"}="record";
1744: $contents{"\\owns"}="3,4,1,0," . <<'EOF';
1745: _
1746: -)
1747: ~
1748: EOF
1749:
1750: $type{"\\ni"}="record";
1751: $contents{"\\ni"}="3,4,1,0," . <<'EOF';
1752: _
1753: -)
1754: ~
1755: EOF
1756:
1757: $type{"\\in"}="record";
1758: $contents{"\\in"}="3,4,1,0," . <<'EOF';
1759: _
1760: (-
1761: ~
1762: EOF
1763:
1764: $type{"\\notin"}="record";
1765: $contents{"\\notin"}="3,5,1,0," . <<'EOF';
1766: |_
1767: (|-
1768: |~
1769: EOF
1770:
1771: $type{"\\qed"}="record";
1772: $contents{"\\qed"}="2,6,1,0," . <<'EOF';
1773: _
1774: |_|
1775: EOF
1776:
1777: $type{"\\pm"}="record";
1778: $contents{"\\pm"}="2,1,0,0," . <<'EOF';
1779: +
1780: -
1781: EOF
1782:
1783: $type{"\\mp"}="record";
1784: $contents{"\\mp"}="2,1,1,0," . <<'EOF';
1785: _
1786: +
1787: EOF
1788:
1789: $type{"\\cong"}="record";
1790: $contents{"\\cong"}="2,1,0,0," . <<'EOF';
1791: =
1792: ~
1793: EOF
1794:
1795: $type{"\\neq"}="record";
1796: $contents{"\\neq"}="1,5,0,0," . <<'EOF';
1797: =/=
1798: EOF
1799:
1800: $type{"\\nmid"}="record";
1801: $contents{"\\nmid"}="3,3,1,0," . <<'EOF';
1802: |/
1803: |
1804: /|
1805: EOF
1806:
1807: $type{"\\subset"}="record";
1808: $contents{"\\subset"}="2,4,1,0," . <<'EOF';
1809: _
1810: (_
1811: EOF
1812:
1813: $type{"\\subseteq"}="record";
1814: $contents{"\\subseteq"}="3,4,1,0," . <<'EOF';
1815: _
1816: (_
1817: ~
1818: EOF
1819:
1820: $type{"\\supseteq"}="record";
1821: $contents{"\\subseteq"}="3,4,1,0," . <<'EOF';
1822: _
1823: _)
1824: ~
1825: EOF
1826:
1827: $type{"\\supset"}="record";
1828: $contents{"\\supset"}="2,4,1,0," . <<'EOF';
1829: _
1830: _)
1831: EOF
1832:
1833: $type{"\\sqrt"}="sub1";
1834: $contents{"\\sqrt"}="radical";
1835:
1836: $type{"\\buildrel"}="sub3";
1837: $contents{"\\buildrel"}="buildrel";
1838:
1839: $type{"\\frac"}="sub2";
1840: $contents{"\\frac"}="fraction";
1841:
1842: $type{"\\LITERALnoLENGTH"}="sub1";
1843: $contents{"\\LITERALnoLENGTH"}="literal_no_length";
1844:
1845: for ("text","operatorname","operatornamewithlimits","relax","-",
1846: "notag","!","/","protect","mathcal","Bbb","bf","it","em","boldsymbol",
1847: "cal","Cal","goth","ref","maketitle","expandafter","csname","endcsname",
1848: "makeatletter","makeatother","topmatter","endtopmatter","rm",
1849: "NoBlackBoxes","document","TagsOnRight","bold","dsize","roster",
1850: "endroster","endkey","endRefs","enddocument","displaystyle",
1851: "twelverm","tenrm","twelvefm","tenfm","hbox","mbox") {
1852: $type{"\\$_"}="nothing";
1853: }
1854: for ("par","endtitle","endauthor","endaffil","endaddress","endemail",
1855: "endhead","key","medskip","smallskip","bigskip","newpage",
1856: "vfill","eject","endgraph") {
1857: $type{"\\$_"}="sub";
1858: $contents{"\\$_"}="par";
1859: }
1860:
1861: for ("proclaim","demo",) {
1862: $type{"\\$_"}="par_self";
1863: }
1864:
1865: for ("endproclaim","enddemo",) {
1866: $type{"\\$_"}="self_par";
1867: }
1868:
1869: #$type{"&"}="nothing";
1870:
1871: $type{"\\let"}="sub";
1872: $contents{"\\let"}="let_exp";
1873:
1874: $type{"\\def"}="sub";
1875: $contents{"\\def"}="def_exp";
1876:
1877: $type{"\\item"}="sub";
1878: $contents{"\\item"}="item";
1879:
1880: $type{"{"}="sub";
1881: $contents{"{"}="open_curly";
1882:
1883: $type{"}"}="sub";
1884: $contents{"}"}="close_curly";
1885:
1886: $type{"&"}="sub";
1887: $contents{"&"}="ampersand";
1888:
1889: $type{'$'}="sub";
1890: $contents{'$'}="dollar";
1891:
1892: $type{'$$'}="sub";
1893: $contents{'$$'}="ddollar";
1894:
1895: $type{'\\\\'}="sub";
1896: $contents{'\\\\'}="bbackslash";
1897:
1898: $type{"^"}="sub1";
1899: $contents{"^"}="superscript";
1900:
1901: $type{"_"}="sub1";
1902: $contents{"_"}="subscript";
1903:
1904: $type{"@"}="sub";
1905: $contents{"@"}="at";
1906:
1907: $type{"\\over"}="sub";
1908: $contents{"\\over"}="over";
1909:
1910:
1911: $type{"\\choose"}="sub";
1912: $contents{"\\choose"}="choose";
1913:
1914: $type{"\\noindent"}="sub";
1915: $contents{"\\noindent"}="noindent";
1916:
1917:
1918: $type{"\\left"}="sub";
1919: $contents{"\\left"}="left";
1920:
1921: $type{"\\right"}="sub";
1922: $contents{"\\right"}="right";
1923:
1924: $type{"\\underline"}="sub1";
1925: $contents{"\\underline"}="underline";
1926:
1927: $type{"\\overline"}="sub1";
1928: $contents{"\\overline"}="overline";
1929:
1930: $type{"\\bar"}="sub1";
1931: $contents{"\\bar"}="overline";
1932:
1933: $type{"\\v"}="sub1";
1934: $contents{"\\v"}="putover_string;v";
1935:
1936: $type{"\\widetilde"}="sub1";
1937: $contents{"\\widetilde"}="widetilde";
1938:
1939: $type{"\\~"}="sub1";
1940: $contents{"\\~"}="putover_string;~";
1941:
1942: $type{"\\tilde"}="sub1";
1943: $contents{"\\tilde"}="putover_string;~";
1944:
1945: $type{"\\widehat"}="sub1";
1946: $contents{"\\widehat"}="widehat";
1947:
1948: $type{"\\hat"}="sub1";
1949: $contents{"\\hat"}="putover_string;^";
1950:
1951: $type{"\\^"}="sub1";
1952: $contents{"\\^"}="putover_string;^";
1953:
1954: $type{'\\"'}="sub1";
1955: $contents{'\\"'}='putover_string;"';
1956:
1957: $type{'\\dot'}="sub1";
1958: $contents{'\\dot'}='putover_string;.';
1959:
1960: $type{"\\not"}="sub1";
1961: $contents{"\\not"}="not";
1962:
1963: $type{"\\label"}="sub1";
1964: $contents{"\\label"}="putpar;(;)";
1965:
1966: $type{"\\eqref"}="sub1";
1967: $contents{"\\eqref"}="putpar;(;)";
1968:
1969: $type{"\\cite"}="sub1";
1970: $contents{"\\cite"}="putpar;[;]";
1971:
1972: $type{"\\begin"}="sub1";
1973: $contents{"\\begin"}="begin";
1974:
1975: $type{"\\end"}="sub1";
1976: $contents{"\\end"}="end";
1977:
1978: for ('@',"_","\$","{","}","#","&","arccos","arcsin","arctan","arg","cos",
1979: "cosh","cot","coth","csc","deg","det","dim","exp","gcd","hom",
1980: "inf","ker","lg","lim","liminf","limsup","ln","log","max","min",
1981: "mod","Pr","sec","sin","sinh","sup","tan","tanh", "%") {
1982: $type{"\\$_"}="self";
1983: }
1984:
1985: for ("bibliography","myLabel","theoremstyle","theorembodyfont",
1986: "bibliographystyle","hphantom","vphantom","phantom","hspace") {
1987: $type{"\\$_"}="discard1";
1988: }
1989:
1990: for ("numberwithin","newtheorem","renewcommand","setcounter"
1991: ) {
1992: $type{"\\$_"}="discard2";
1993: }
1994:
1995: for ("equation","gather","align"
1996: ) {$environment{"$_"}="ddollar,ddollar";}
1997:
1998: for ("matrix","CD","smallmatrix"
1999: ) {$environment{"$_"}="matrix,endmatrix;1;c";}
2000:
2001: for ("document","split","enumerate"
2002: ) {$environment_none{"$_"}++;}
2003:
2004: $environment{"Sb"}="subscript:matrix,endmatrix;1;l";
2005:
2006: $environment{"Sp"}="superscript:matrix,endmatrix;1;l";
2007:
2008: $environment{"eqnarray"}="ddollar:matrix,endmatrix;0;r;c;l:ddollar";
2009: $environment{"split"}="ddollar:matrix,endmatrix;0;r;l:ddollar";
2010: $environment{"multiline"}="ddollar:matrix,endmatrix;0;r;l:ddollar";
2011: $environment{"align"}="ddollar:matrix,endmatrix;0;r;l:ddollar";
2012: $environment{"aligned"}="matrix,endmatrix;0;r;l";
2013: $environment{"gather"}="ddollar:matrix,endmatrix;0;c:ddollar";
2014: $environment{"gathered"}="matrix,endmatrix;0;c";
2015: $environment{"array"}="arg2stack:matrix,endmatrixArg;1";
2016:
2017: # $environment{"pmatrix"}="beg_lr;(;):matrix,endmatrix;1;c";
2018: $environment{"bmatrix"}="beg_lr;[;]:matrix,endmatrix;1;c";
2019: $environment{"vmatrix"}="beg_lr;|;|:matrix,endmatrix;1;c";
2020:
2021: $type{"~"}="string";
2022: $contents{"~"}=" ";
2023:
2024: $type{"\\,"}="string";
2025: $contents{"\\,"}=" ";
2026:
2027: $type{"\\dots"}="string";
2028: $contents{"\\dots"}="...";
2029:
2030: $type{"\\ldots"}="string";
2031: $contents{"\\ldots"}="...";
2032:
2033: $type{"\\cdots"}="string";
2034: $contents{"\\cdots"}="...";
2035:
2036: $type{"\\colon"}="string";
2037: $contents{"\\colon"}=": ";
2038:
2039: $type{"\\mid"}="string";
2040: $contents{"\\mid"}=" | ";
2041:
2042: $type{"\\smallsetminus"}="string";
2043: $contents{"\\smallsetminus"}=" \\ ";
2044:
2045: $type{"\\setminus"}="string";
2046: $contents{"\\setminus"}=" \\ ";
2047:
2048: $type{"\\backslash"}="string";
2049: $contents{"\\backslash"}="\\";
2050:
2051: $type{"\\approx"}="string";
2052: $contents{"\\approx"}=" ~ ";
2053:
2054: $type{"\\simeq"}="string";
2055: $contents{"\\simeq"}=" ~ ";
2056:
2057: $type{"\\quad"}="string";
2058: $contents{"\\quad"}=" ";
2059:
2060: $type{"\\qquad"}="string";
2061: $contents{"\\qquad"}=" ";
2062:
2063: $type{"\\to"}="string";
2064: $contents{"\\to"}=" --> ";
2065:
2066: $type{"\\from"}="string";
2067: $contents{"\\from"}=" <-- ";
2068:
2069: $type{"\\wedge"}="string";
2070: $contents{"\\wedge"}="/\\";
2071:
2072: $type{"\\Lambda"}="string";
2073: $contents{"\\Lambda"}="/\\";
2074:
2075: $type{"\\ltimes"}="string";
2076: $contents{"\\ltimes"}=" |>< ";
2077:
2078: $type{"\\lhd"}="string";
2079: $contents{"\\lhd"}=" <| ";
2080:
2081: $type{"\\rhd"}="string";
2082: $contents{"\\rhd"}=" |> ";
2083:
2084: $type{"\\cdot"}="string";
2085: $contents{"\\cdot"}=" . ";
2086:
2087: # $type{"\dot"}="string";
2088: # $contents{"\\dot"}=" . ";
2089:
2090: $type{"\\circ"}="string";
2091: $contents{"\\circ"}=" o ";
2092:
2093: $type{"\\bullet"}="string";
2094: $contents{"\\bullet"}="\@";
2095:
2096: $type{"\\infty"}="string";
2097: $contents{"\\infty"}="oo";
2098:
2099: $type{"\\rtimes"}="string";
2100: $contents{"\\rtimes"}=" ><| ";
2101:
2102: $type{"\\times"}="string";
2103: $contents{"\\times"}=" >< ";
2104:
2105: $type{"\\hookrightarrow"}="string";
2106: $contents{"\\hookrightarrow"}=" c--> ";
2107:
2108: $type{"\\hookleftarrow"}="string";
2109: $contents{"\\hookleftarrow"}=" <--j ";
2110:
2111: $type{"\\longleftarrow"}="string";
2112: $contents{"\\longleftarrow"}=" <----- ";
2113:
2114: $type{"\\longleftrightarrow"}="string";
2115: $contents{"\\longleftrightarrow"}=" <----> ";
2116:
2117: $type{"\\longrightarrow"}="string";
2118: $contents{"\\longrightarrow"}=" -----> ";
2119:
2120: $type{"\\rightarrow"}="string";
2121: $contents{"\\rightarrow"}=" ---> ";
2122:
2123: $type{"\\leftarrow"}="string";
2124: $contents{"\\leftarrow"}=" <--- ";
2125:
2126: $type{"\\mapsto"}="string";
2127: $contents{"\\mapsto"}=" |--> ";
2128:
2129: $type{"\\longmapsto"}="string";
2130: $contents{"\\longmapsto"}=" |----> ";
2131:
2132: $type{"\\cap"}="string";
2133: $contents{"\\cap"}=" /~\\ ";
2134:
2135: $type{"\\cup"}="string";
2136: $contents{"\\cup"}=" \\_/ ";
2137:
2138: $type{"\\section"}="string";
2139: $contents{"\\section"}="Section ";
2140:
2141: $type{"\\subsection"}="string";
2142: $contents{"\\subsection"}="Subsection ";
2143:
2144: $type{"\|"}="string";
2145: $contents{"\|"}="||";
2146:
2147: $type{'\;'}="string";
2148: $contents{'\;'}=" ";
2149:
2150: $type{'\noindent'}="string";
2151: $contents{'\noindent'}="";
2152:
2153:
2154: &define('\\define','\\def');
2155: &define('\\ge','\\geq');
2156: &define('\\le','\\leq');
2157: &define('\\ne','\\neq');
2158: &define('\\langle','<');
2159: &define('\\rangle','>');
2160: &define('\\subheading','\\par\\underline');
2161: &define('\\(','$');
2162: &define('\\)','$');
2163: &define('\\[','$$');
2164: &define('\\]','$$');
2165: &define('\\centerline#1','$$#1$$');
2166: &define('\\eqalign#1','\\aligned #1 \\endaligned');
2167: &define('\\cr','\\\\');
2168: &define('\\sb','_');
2169: &define('\\sp','^');
2170: &define('\\proclaim','\\noindent ');
2171: &defb("matrix","vmatrix","Vmatrix","smallmatrix","bmatrix","Sp","Sb",
2172: "CD","align","aligned","split","multiline","gather","gathered");
2173:
2174: if ($opt_TeX) {
2175: &define('\pmatrix#1','\left(\begin{matrix}#1\end{matrix}\right)');
2176: } else {
2177: $environment{"pmatrix"}="beg_lr;(;):matrix,endmatrix;1;c";
2178: &defb("pmatrix") unless $opt_TeX;
2179: }
2180:
2181:
2182: ## All the records should be specified before this point
2183: {local(@a)=grep("record" eq $type{$_},keys %type);
2184: for (@a) {chop $contents{$_} if
2185: substr($contents{$_},length($contents{$_})-1,1) eq "\n";}}
2186:
2187: for ("oplus","otimes","cup","wedge") {
2188: $type{"\\big$_"}=$type{"\\$_"};
2189: $contents{"\\big$_"}=$contents{"\\$_"};
2190: }
2191:
2192:
2193: @level=(0);
2194: @chunks=(0);
2195: @tokenByToken=(0);
2196: @out=();
2197: $curlength=0;
2198: $debug_flow=1;
2199: $debug_record=2;
2200: $debug_parsing=4;
2201: $debug_length=8;
2202: $debug_matrix=16;
2203: #$debug |= $debug_flow | $debug_record | $debug_parsing | $debug_length;
2204: #$debug |= $debug_flow;
2205: #$debug |= $debug_record;
2206: #$debug |= $debug_parsing;
2207: #$debug |= $debug_length;
2208: #$debug |= $debug_matrix;
2209:
2210:
2211: $/ = $opt_by_par ? "\n\n" : ''; # whole paragraph mode
2212: while (¶graph()) { 1 }
2213: &finishBuffer;
2214:
2215: __END__
2216:
2217: # History: Jul 98: \choose added, fixed RE for \noindent, \eqalign and \cr.
2218: # \proclaim and better \noindent added.
2219: # Sep 98: last was used inside an if block, was leaking out.
2220: # Jan 00: \sb \sp
2221: # Feb 00: remove extraneous second EOF needed at end.
2222: remove an empty line at end of output
2223: New option -by_par to support per-paragraph processing
2224: New option -TeX which support a different \pmatrix
2225: New option -ragged to not insert whitespace to align right margin.
2226: New option -noindent to not insert whitespace at beginning.
2227: Ignore \\ and \cr if followed by \end{whatever}.
2228: Ignore \noindent if not important.
2229: Ignore whitespace paragraphs.
2230: # Apr 00: Finishing a level 1 would not merge things into one chunk.
2231: # May 00: Additional argument to finish() to distinguish finishing
2232: things which cannot be broken between lines.
2233: # Sep 00: Add support for new macro for strings with screen escapes sequences:
2234: \LITERALnoLENGTH{escapeseq}.
2235: # Oct 00: \LITERALnoLENGTH can have a chance to work in the baseline only;
2236: in fact the previous version did not work even there...
2237: If the added record is longer than line length, do not try to
2238: break the line before it...
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>