summaryrefslogtreecommitdiff
path: root/systems/unix/tex-gpc/mp
diff options
context:
space:
mode:
Diffstat (limited to 'systems/unix/tex-gpc/mp')
-rw-r--r--systems/unix/tex-gpc/mp/README186
-rw-r--r--systems/unix/tex-gpc/mp/dvitomp.ch208
-rw-r--r--systems/unix/tex-gpc/mp/mk_MP_dir2
-rw-r--r--systems/unix/tex-gpc/mp/mp.ch651
-rw-r--r--systems/unix/tex-gpc/mp/mptotex.c224
-rw-r--r--systems/unix/tex-gpc/mp/mpx8
6 files changed, 1279 insertions, 0 deletions
diff --git a/systems/unix/tex-gpc/mp/README b/systems/unix/tex-gpc/mp/README
new file mode 100644
index 0000000000..eab901fca6
--- /dev/null
+++ b/systems/unix/tex-gpc/mp/README
@@ -0,0 +1,186 @@
+Aug. 2008
+This is the stage directory to build and install John Hobby's
+METAPOST for GPC. METAPOST produces pictures as PostScript files
+that are to be included by dvips in its output.
+
+METAPOST's file formats and their documentation:
+------------------------------------------------
+.mp METAPOST source,
+ see "A User's manual for MetaPost", AT&T Bell Laboratories
+ Computing Science Technical Report 162, 1992
+.mpx METAPOST source, auxiliary file, needed if a .mp file contains text.
+.mem METAPOST format file (plain.mp)
+.c C source (Kernighan/Ritchie The C Programming Language)
+.ps Adobe PostScript
+.<n> Where n an integer, a PostScript file for picture n, to be included
+ by dvips.
+
+
+builtin file names:
+------------------
+MPlib/mp.pool string pool for mp, (in inimp)
+MPlib/plain.mem base file for Plain METAFONT, (in mf)
+
+METAPOST's processors:
+----------------------
+ inimp
+ plain.mp -------> MPlib/plain.mem
+
+ mp
+.mp, .mpx -------> .n
+
+ mptotex
+.mp -------> .tex
+
+ tex
+.tex -------> .dvi
+
+ dvitomp
+.dvi --------> .mpx
+
+ mpx
+.mp --------> .n (combines the last four steps)
+
+Use the shell script mpx instead of mp if your .mp file contains
+TeX programs. These extra steps are necessary to include TeX's output
+in the picture.
+
+And finally:
+ dvips
+.<n>, .dvi, .pk, .tfm ----> PostScript file/printer
+
+
+Get John Hobby's distribution
+-----------------------------
+The sources from CTAN only work with web2c but not with WEB programs,
+so I downloaded the originals from netlib:
+ ftp ftp://ftp.netlib.org/research/metapost.tar.Z
+unpack it with uncompress and tar xf:
+ uncompress metapost.tar.Z
+ tar xf metapost.tar
+This will give you a directory metapost, from which you copy at least
+mp.web, plain.mp, mptotex.c and dvitomp.web into this directory.
+
+Masterdirectories:
+------------------
+Create the master directories MPlib and MPinputs. Prepare a directory from
+where you want to run mp with the shell script mk_MP_dir.
+(Additionally to mk_TeX_dir)
+
+Building and installing:
+-----------------------
+Move a.out into your binary directory under the name at the
+right end of --->.
+
+1. mp.web, mp.ch ---> inimp
+Change mp.ch for initialization (see building inimf, initex) and tgl.
+Move mp.pool to MPlib.
+
+2. plain.mp ---> MPlib/plain.mem
+ inimp plain.mp dump
+mv plain.mem to MPlib
+
+3. mp.web, mp.ch ---> mp
+Change mp.ch for production (see building inimf, initex) and tgl.
+
+4. dvitomp.web, dvitomp.ch ---> dvitomp
+Just tgl and move a.out as dvitomp to your binary directory
+
+5. mptotex.c ---> mptotex
+cc mptotex.c, ignore the warning and move a.out to ....
+
+6. mpx ---> mpx (just move the shell script to your binary dir)
+
+Using MetaPost:
+--------------
+To include a MetaPost picture xxx.mp in your output, \input
+the TeX macro epsf.tex. At the place where you want to include your
+picture, write
+ \epsfbox{xxx.n}
+where xxx is the name of the picture and n is the argument given
+in the beginfig() command.
+
+Here are those files:
+fig.mp
+
+beginfig(1);
+a=.7in; b=0.5in;
+z0=(0,); z1=(a,0); z2=(0,b);
+z0=.5[z1,z3]=.5[z2,z4];
+draw z1..z2..z3..z4..cycle;
+drawarrow z0..z1;
+drawarrow z0..z2;
+label.top(btex $a$ etex, .5[z0, z1]);
+label.lft(btex $b$ etex, .5[z0, z2]);
+endfig;
+end
+
+fig.mp contains two Tex programs, $a$ and $b$. So you need to call mpx instead
+of mp. This creates fig.mpx:
+
+% Written by DVItoMP-GPC
+begingroup save _p,_r,_s,_n; picture _p; _p=nullpicture;
+string _n[];
+vardef _s(expr _t,_f,_m,_x,_y)=
+ addto _p also _t infont _f scaled _m shifted (_x,_y); enddef;
+_n0="cmmi10";
+_s("a",_n0,1.00000,0.0000,0.0000);
+setbounds _p to (0,0.0000)--(5.2661,0.0000)--
+ (5.2661,4.2895)--(0,4.2895)--cycle;
+_p endgroup
+mpxbreak
+begingroup save _p,_r,_s,_n; picture _p; _p=nullpicture;
+string _n[];
+vardef _s(expr _t,_f,_m,_x,_y)=
+ addto _p also _t infont _f scaled _m shifted (_x,_y); enddef;
+_n0="cmmi10";
+_s("b",_n0,1.00000,0.0000,0.0000);
+setbounds _p to (0,0.0000)--(4.2756,0.0000)--
+ (4.2756,6.9185)--(0,6.9185)--cycle;
+_p endgroup
+mpxbreak
+
+From fig.mp and fig.mpx METAPOST creates fig.1
+
+%!PS
+%%BoundingBox: -51 -37 51 37
+%%Creator: MetaPost
+%%CreationDate: 2008.08.25:1829
+%%Pages: 1
+%*Font: cmmi10 9.96265 9.96265 61:c
+%%EndProlog
+%%Page: 1 1
+ 0 0.5 dtransform truncate idtransform setlinewidth pop [] 0 setdash
+ 1 setlinejoin 10 setmiterlimit
+newpath 50.39978 0 moveto
+50.39978 23.04858 25.56044 36 0 36 curveto
+-25.56044 36 -50.39978 23.04858 -50.39978 0 curveto
+-50.39978 -23.04858 -25.56044 -36 0 -36 curveto
+25.56044 -36 50.39978 -23.04858 50.39978 0 curveto closepath stroke
+ 1 setlinecap
+newpath 0 0 moveto
+50.39978 0 lineto stroke
+newpath 46.70451 -1.53067 moveto
+50.39978 0 lineto
+46.70451 1.53067 lineto
+ closepath
+gsave fill grestore stroke
+ 0.5 0 dtransform exch truncate exch idtransform pop setlinewidth
+newpath 0 0 moveto
+0 36 lineto stroke
+ 0 0.5 dtransform truncate idtransform setlinewidth pop
+newpath 1.5308 32.3044 moveto
+0 36 lineto
+-1.5308 32.3044 lineto
+ closepath
+gsave fill grestore stroke
+22.56683 3 moveto
+(a) cmmi10 9.96265 fshow
+-7.2756 14.54074 moveto
+(b) cmmi10 9.96265 fshow
+showpage
+%%EOF
+
+Finally, include the figure in your TeX document by
+\input epsf
+\epsfbox{fig.1}
diff --git a/systems/unix/tex-gpc/mp/dvitomp.ch b/systems/unix/tex-gpc/mp/dvitomp.ch
new file mode 100644
index 0000000000..1d8f7db09d
--- /dev/null
+++ b/systems/unix/tex-gpc/mp/dvitomp.ch
@@ -0,0 +1,208 @@
+% This is a change file of DVItoMP-GPC, Wolfgang Helbig, Aug. 2008
+To be used with the GNU Pascal Compiler Version 2.1
+
+[0] About DVItoMP-GPC
+@x
+\pageno=\contentspagenumber \advance\pageno by 1
+@y
+\pageno=\contentspagenumber \advance\pageno by 1
+\input webmac-gpc
+
+% \let\maybe=\iffalse % uncomment to print changed modules only.
+
+\def\name{\tt DVItoMP}
+
+\N0\*. About \namegpc.\fi
+
+This is an adaption of John Hobby's \name, version 0.64, to Unix
+and GNU~Pascal, version 2.1.
+
+This program expects the input file (\.{.dvi}) and the output file,
+(\.{mpx}) which is a text file, on the command line. To support shell
+scripting, \namegpc\ sets the exit code to one when something was
+wrong with the input file.
+
+\hint
+
+Comments and questions are welcome!
+
+\bigskip
+\address
+@z
+[1] Change the banner line
+@x
+@d banner=='% Written by DVItoMP, Version 0.64'
+@y
+@d banner=='% Written by DVItoMP-GPC'
+@z
+
+[3] only stdio files in program header.
+@x
+@p program DVI_to_MP(@!dvi_file,@!mpx_file,@!output);
+@y
+@p
+@{@&$I-@} {no I/O checking}
+program DVI_to_MP(input, output);
+@z
+
+[9] check command line arguments
+@x
+history:=spotless;
+@y
+history:=spotless;
+if param_count <> 2 then
+ begin write_ln('Usage: dvitomp dvi_file mpx_file'); halt(1);
+ end;
+@z
+
+[12] Pascal's type of text_files is text
+@x
+@!text_file=packed file of text_char;
+@y
+@!text_file=text;
+@z
+
+[14] get file name from command line
+@x
+begin rewrite(mpx_file);
+@y
+begin
+rewrite(mpx_file, param_str(2));
+@z
+
+[17] use GPC extension for packing subranges.
+@x
+@!eight_bits=0..255; {unsigned one-byte quantity}
+@y
+@!eight_bits=packed 0..255; {unsigned one-byte quantity}
+@z
+
+[22] declare out_file
+@x
+@!tfm_file:byte_file; {a font metric file}
+@y
+@!tfm_file:byte_file; {a font metric file}
+@!out_file:text; {the outfile}
+@z
+
+[19] open file whose name is not known at compile time
+@x
+has acted, these routines assume that no file named |s| is accessible.
+@y
+has acted, these routines assume that no file named |s| is accessible.
+@d io_ok==io_result=0
+@d clear_io_result==@+if io_result=0 then
+@z
+
+@x
+begin reset(dvi_file);
+@y
+begin reset(dvi_file, param_str(1));
+@z
+
+@x
+begin reset(tfm_file,cur_name);
+@y
+begin reset(tfm_file,trim(cur_name)); {ignore leading and trailing blanks}
+@z
+
+@x
+begin reset(vf_file,cur_name);
+open_vf_file:=(not eof(vf_file));
+@y
+begin clear_io_result; reset(vf_file,trim(cur_name));
+ open_vf_file:=io_ok;
+@z
+
+ [28] no random access
+ @x;
+ begin set_pos(dvi_file,-1); dvi_length:=cur_pos(dvi_file);
+ end;
+ @#
+ procedure move_to_byte(n:integer);
+ begin set_pos(dvi_file,n); cur_loc:=n;
+ end;
+ @y;
+ begin do_nothing;
+ end;
+ @#
+ procedure move_to_byte(n:integer);
+ begin do_nothing;
+ end;
+ @z
+
+[47]
+ @x
+ is always at least one blank space in |buffer|.
+ @^system dependencies@>
+
+ @p procedure input_ln; {inputs a line from the terminal}
+ var k:0..terminal_line_length;
+ begin update_terminal; reset(term_in);
+ if eoln(term_in) then read_ln(term_in);
+ k:=0;
+ while (k<terminal_line_length)and not eoln(term_in) do
+ begin buffer[k]:=xord[term_in^]; incr(k); get(term_in);
+ end;
+ buffer[k]:=" ";
+ end;
+ @y
+ is always at least one blank space in |buffer|.
+ This is changed here: |term_in| is standard input and is not supposed
+ to be opened. There is never an end-of-line marker at the beginning of
+ a line but always at the end of a line.
+ @^system dependencies@>
+
+ @p procedure input_ln; {inputs a line from the terminal}
+ var k:0..terminal_line_length;
+ begin update_terminal;
+ k:=0;
+ while (k<terminal_line_length)and not eoln(term_in) do
+ begin buffer[k]:=xord[term_in^]; incr(k); get(term_in);
+ end;
+ read_ln(term_in);
+ buffer[k]:=" ";
+ end;
+ @z
+
+ [50] don't rewrite output file, write the banner while initializing
+ @x
+ begin rewrite(term_out); {prepare the terminal for output}
+ write_ln(term_out,banner);
+ @y
+ begin
+ @z
+
+[61]
+@x
+@d default_directory_name=='TeXfonts:' {change this to the correct name}
+@y
+@d default_directory_name=='TeXfonts/' {change this to the correct name}
+@z
+
+[63] lowercase filename
+@x
+ if (names[k]>="a")and(names[k]<="z") then
+ cur_name[l]:=xchr[names[k]-@'40]
+ else cur_name[l]:=xchr[names[k]];
+ end;
+cur_name[l+1]:='.'; cur_name[l+2]:='V'; cur_name[l+3]:='F'
+@y
+ cur_name[l]:=xchr[names[k]]
+ end;
+cur_name[l+1]:='.'; cur_name[l+2]:='v'; cur_name[l+3]:='f'
+@z
+
+[64] lowercase filename
+@x
+cur_name[l+2]:='T'; cur_name[l+3]:='F'; cur_name[l+4]:='M'
+@y
+cur_name[l+2]:='t'; cur_name[l+3]:='f'; cur_name[l+4]:='m'
+@z
+
+[107] set exit code
+@x
+final_end:end.
+@y
+final_end:halt(history) end.
+@z
diff --git a/systems/unix/tex-gpc/mp/mk_MP_dir b/systems/unix/tex-gpc/mp/mk_MP_dir
new file mode 100644
index 0000000000..7e755a9d40
--- /dev/null
+++ b/systems/unix/tex-gpc/mp/mk_MP_dir
@@ -0,0 +1,2 @@
+ln -s ~/MPlib .
+ln -s ~/MPinputs .
diff --git a/systems/unix/tex-gpc/mp/mp.ch b/systems/unix/tex-gpc/mp/mp.ch
new file mode 100644
index 0000000000..60dec6ee13
--- /dev/null
+++ b/systems/unix/tex-gpc/mp/mp.ch
@@ -0,0 +1,651 @@
+% This is a change file of METAPOST for GPC, Wolfgang Helbig, Aug. 2008
+% See tex.ch and mf.ch from tex-gpc
+[0] to print changed sections only
+@x
+\def\gglob{20, 26} % this should be the next two sections of "<Global...>"
+@y
+\def\gglob{20, 26} % this should be the next two sections of "<Global...>"
+\input webmac-gpc
+\emergencystretch 0.5in % avoid overfull boxes
+
+% \let\maybe=\iffalse % uncomment to print changed modules only.
+
+\def\name{\MP}
+
+\N0\*. \[0] About \namegpc.
+
+This is an adaption of John Hobby's \MP, version 0.641, to Unix,
+and GNU~Pascal, version 2.1.
+
+The features added include treating the command line as the first
+input line and invoking a system editor, in this case \.{vi}, to
+let the user correct the input file.
+On exit, \namegpc\ passes its `history' to the operating system.
+
+\hint
+
+Comments and questions are welcome!
+
+\bigskip
+\address
+\fi
+@z
+
+[2] Change the banner line
+@x
+@d banner=='This is MetaPost, Version 0.641' {printed when \MP\ starts}
+@y
+@d banner=='This is MetaPost-GPC' {printed when \MP\ starts}
+@z
+
+[4] terminal output and input
+@x
+@d mtype==t@&y@&p@&e {this is a \.{WEB} coding trick:}
+@y
+@d term_in==i@&n@&p@&u@&t
+@d term_out==o@&u@&t@&p@&u@&t
+@d mtype==t@&y@&p@&e {this is a \.{WEB} coding trick:}
+@z
+
+[4] terminal output and input
+@x
+program MP; {all file names are defined dynamically}
+@y
+program MP(@!term_in,@!term_out);
+{all other file names are defined dynamically}
+import gpc only (gpc_execute,gpc_install_signal_handler,
+ gpc_t_signal_handler, gpc_sig_int);
+@z
+
+[4] forward reference for signal handler
+@x
+procedure initialize; {this procedure gets things started properly}
+@y
+procedure set_interrupt(signal: gpc_integer); forward; @t\2@>
+{|initialize| installs |set_interrupt| as a Unix signal handler}
+@#
+procedure initialize; {this procedure gets things started properly}
+@z
+
+Since @x, @y, and @z only define a change block when they begin a
+line, you deactivate a block by indenting it (shift right) and
+activate it by unindenting it (shift left). With vi set the
+cursor to the @x line and enter >} or <} to (un)indent a paragraph.
+
+[7] shift left to turn debugging on, right to turn it off
+@x
+@d debug==@{ {change this to `$\\{debug}\equiv\null$' when debugging}
+@d gubed==@t@>@} {change this to `$\\{gubed}\equiv\null$' when debugging}
+@y
+@d debug== {change this to `$\\{debug}\equiv\.{@@\{}$' when not debugging}
+@d gubed== {change this to `$\\{gubed}\equiv\.{@@\}}$' when not debugging}
+@z
+
+[7] shift left to turn on statistics, shift rigth to turn off statistics
+@x
+@d stat==@{ {change this to `$\\{stat}\equiv\null$' when gathering
+ usage statistics}
+@d tats==@t@>@} {change this to `$\\{tats}\equiv\null$' when gathering
+ usage statistics}
+@y
+@d stat== {change this to `$\\{stat}\equiv\.{@@\{}$' to turn off statistics}
+@d tats== {change this to `$\\{tats}\equiv\.{@@\}}$' to turn off statistics}
+@z
+
+[8] shift left to build MP and right it to build INIMP.
+ @x inimp
+ @d init== {change this to `$\\{init}\equiv\.{@@\{}$' in the production version}
+ @d tini== {change this to `$\\{tini}\equiv\.{@@\}}$' in the production version}
+ @y
+ @d init==@{
+ @d tini==@}
+ @z
+
+[9] compiler directives, turn off I/O checking.
+@x
+@{@&$C-,A+,D-@} {no range check, catch arithmetic overflow, no debug overhead}
+@!debug @{@&$C+,D+@}@+ gubed {but turn everything on when debugging}
+@y
+@{@&$I-@} {no I/O checking}
+@z
+
+[10] default case branch
+@x
+@d othercases == others: {default for cases not listed explicitly}
+@y
+@d othercases == @+ else {default for cases not listed explicitly}
+@z
+
+[11] location of pool file
+@x
+@!pool_name='MPlib:MP.POOL ';
+ {string of length |file_name_size|; tells where the string pool appears}
+@.MPlib@>
+@!ps_tab_name='MPlib:PSFONTS.MAP ';
+ {string of length |file_name_size|; locates font name translation table}
+@y
+@!pool_name='MPlib/mp.pool ';
+ {string of length |file_name_size|; tells where the string pool appears}
+@.MPlib@>
+@!ps_tab_name='MPlib/psfonts.map ';
+ {string of length |file_name_size|; locates font name translation table}
+@z
+
+
+[22] accept tab and formfeed
+@x
+for i:=0 to @'37 do xchr[i]:=' ';
+@y
+for i:=0 to @'37 do xchr[i]:=' ';
+xchr[@'11] := chr(@'11); {accept horizontal tab}
+xchr[@'14] := chr(@'14); {accept form feed}
+@z
+
+[24] the type of text_files is text in ISO Pascal
+@x
+@!eight_bits=0..255; {unsigned one-byte quantity}
+@!alpha_file=packed file of text_char; {files that contain textual data}
+@y
+@!eight_bits=packed 0..255; {unsigned one-byte quantity}
+@!alpha_file=t@&e@&x@&t; {coding trick is needed since |text| is a macro}
+@z
+
+[26] dynamic io
+@x
+@d reset_OK(#)==erstat(#)=0
+@d rewrite_OK(#)==erstat(#)=0
+@y
+@d gpc_trim==t@&r@&i@&m
+@d gpc_io_result==i@&o@&r@&e@&s@&u@&l@&t
+@d reset_OK(#)==gpc_io_result=0
+@d rewrite_OK(#)==gpc_io_result=0
+@d clear_io_result==@+if gpc_io_result=0 then do_nothing
+@z
+
+[26] (reset and rewrite for each of three file types) alpha
+@x
+begin reset(f,name_of_file,'/O'); a_open_in:=reset_OK(f);
+@y
+begin clear_io_result; reset(f,gpc_trim(name_of_file)); a_open_in:=reset_OK(f);
+@z
+
+[26]
+@x
+begin rewrite(f,name_of_file,'/O'); a_open_out:=rewrite_OK(f);
+@y
+begin clear_io_result; rewrite(f,gpc_trim(name_of_file));
+a_open_out:=rewrite_OK(f);
+@z
+
+[26] byte file
+@x
+begin reset(f,name_of_file,'/O'); b_open_in:=reset_OK(f);
+@y
+begin clear_io_result; reset(f,gpc_trim(name_of_file)); b_open_in:=reset_OK(f);
+@z
+
+@x
+begin rewrite(f,name_of_file,'/O'); b_open_out:=rewrite_OK(f);
+@y
+begin clear_io_result; rewrite(f,gpc_trim(name_of_file));
+b_open_out:=reset_OK(f);
+@z
+
+[26] word_file
+@x
+begin reset(f,name_of_file,'/O'); w_open_in:=reset_OK(f);
+@y
+begin clear_io_result; reset(f,gpc_trim(name_of_file)); w_open_in:=reset_OK(f);
+@z
+
+[26]
+@x
+begin rewrite(f,name_of_file,'/O'); w_open_out:=rewrite_OK(f);
+@y
+begin clear_io_result; rewrite(f,gpc_trim(name_of_file));
+w_open_out:=rewrite_OK(f);
+@z
+
+[30] eoln handling
+@x
+@p function input_ln(var @!f:alpha_file;@!bypass_eoln:boolean):boolean;
+ {inputs the next line or returns |false|}
+var @!last_nonblank:0..buf_size; {|last| with trailing blanks removed}
+begin if bypass_eoln then if not eof(f) then get(f);
+ {input the first character of the line into |f^|}
+last:=first; {cf.\ Matthew 19\thinspace:\thinspace30}
+if eof(f) then input_ln:=false
+else begin last_nonblank:=first;
+ while not eoln(f) do
+ begin if last>=max_buf_stack then
+ begin max_buf_stack:=last+1;
+ if max_buf_stack=buf_size then
+ @<Report overflow of the input buffer, and abort@>;
+ end;
+ buffer[last]:=xord[f^]; get(f); incr(last);
+ if buffer[last-1]<>" " then last_nonblank:=last;
+ end;
+ last:=last_nonblank; input_ln:=true;
+ end;
+end;
+@y
+@p function input_ln(var f:alpha_file;@!bypass_eoln:boolean):boolean;
+ {inputs the next line or returns |false|}
+begin
+ {ignore |bypass_eoln|. Assuming |f| being positioned at the first character}
+last:=first; {cf.\ Matthew 19\thinspace:\thinspace30}
+if eof(f) then input_ln:=false
+else begin
+ while not eoln(f) do
+ begin if last>=max_buf_stack then
+ begin max_buf_stack:=last+1;
+ if max_buf_stack=buf_size then begin
+ read_ln(f); {complete the current line}
+ @<Report overflow of the input buffer, and abort@>;
+ end;
+ end;
+ buffer[last]:=xord[f^]; get(f); incr(last);
+ end;
+ get(f); {Advance |f| to the first character of the next line}
+ input_ln:=true;
+ end;
+end;
+@z
+
+[31] term_in and term_out are the standard pascal files
+@x
+is considered an output file the file variable is |term_out|.
+@^system dependencies@>
+
+@<Glob...@>=
+@!term_in:alpha_file; {the terminal as an input file}
+@!term_out:alpha_file; {the terminal as an output file}
+@y
+is considered an output file the file variable is |term_out|.
+The file |term_in| is declared as \\{input} and |term_out| as
+\\{output} in the program header.
+@z
+
+[32]
+@x
+@d t_open_in==reset(term_in,'TTY:','/O/I') {open the terminal for text input}
+@d t_open_out==rewrite(term_out,'TTY:','/O') {open the terminal for text output}
+@y
+@d t_open_in==do_nothing {open the terminal for text input}
+@d t_open_out==do_nothing {open the terminal for text output}
+@z
+
+[33]
+@x
+@d update_terminal == break(term_out) {empty the terminal output buffer}
+@d clear_terminal == break_in(term_in,true) {clear the terminal input buffer}
+@y
+@d update_terminal == do_nothing {empty the terminal output buffer}
+@d clear_terminal == do_nothing {clear the terminal input buffer}
+@z
+
+[35] command line
+@x
+@d loc==cur_input.loc_field {location of first unread character in |buffer|}
+@y
+@d loc==cur_input.loc_field {location of first unread character in |buffer|}
+@d gpc_string==s@&t@&r@&i@&n@&g {a string with varying length}
+@d gpc_length==l@&e@&n@&g@&t@&h
+@d gpc_param_count==p@&a@&r@&a@&m@&c@&o@&u@&n@&t
+@d gpc_param_str==p@&a@&r@&a@&m@&s@&t@&r
+
+{GPC function returning the length of a |gpc_string|}
+
+@p procedure input_command_ln; {get the command line in |buffer|}
+var argc: integer; {argument counter}
+ arg: gpc_string; {argument}
+ cc: integer; {character counter in argument}
+begin last := first; argc := 1;
+while argc <= gpc_param_count do
+ begin cc := 1; arg := gpc_param_str(argc); incr(argc);
+ while cc <= gpc_length(arg) do
+ begin
+ if last+1>=buf_size then
+ @<Report overflow of the input buffer, and abort@>;
+ buffer[last] := xord[arg[cc]]; incr(last); incr(cc);
+ end;
+ if (argc <= gpc_param_count) then begin
+ buffer[last] := " "; incr(last);
+ end;
+ end;
+end;
+@z
+
+[36] command line
+@x
+@p function init_terminal:boolean; {gets the terminal input started}
+label exit;
+begin t_open_in;
+loop@+begin wake_up_terminal; write(term_out,'**'); update_terminal;
+@.**@>
+ if not input_ln(term_in,true) then {this shouldn't happen}
+ begin write_ln(term_out);
+ write(term_out,'! End of file on the terminal... why?');
+@.End of file on the terminal@>
+ init_terminal:=false; return;
+ end;
+ loc:=first;
+ while (loc<last)and(buffer[loc]=" ") do incr(loc);
+ if loc<last then
+ begin init_terminal:=true;
+ return; {return unless the line was all blank}
+ end;
+ write_ln(term_out,'Please type the name of your input file.');
+ end;
+exit:end;
+@y
+@p function init_terminal:boolean; {gets the terminal input started}
+label exit;
+begin t_open_in; input_command_ln;
+while first=last do begin
+ wake_up_terminal; write(term_out,'**'); update_terminal;
+@.**@>
+ if not input_ln(term_in, true) then {this shouldn't happen}
+ begin write_ln(term_out);
+ write_ln(term_out,'! End of file on the terminal... why?');
+@.End of file on the terminal@>
+ init_terminal:=false; return;
+ end;
+ if first=last then
+ write_ln(term_out,'Please type the name of your input file.');
+ end;
+loc := first; {trim leading spaces}
+while buffer[loc]=" " do incr(loc);
+init_terminal:=true;
+exit: end;
+@z
+
+[76] print banner line on terminal
+@x
+@<Initialize the output...@>=
+update_terminal;
+@y
+@<Initialize the output...@>=
+wterm(banner);
+if mem_ident=0 then wterm_ln(' (no mem preloaded)')
+else begin print(mem_ident); print_ln;
+ end;
+update_terminal;
+@z
+
+[89] start editor
+@x
+@!use_err_help:boolean; {should the |err_help| string be shown?}
+@y
+@!use_err_help:boolean; {should the |err_help| string be shown?}
+@!edit_line: integer; {line number to be passed to the system editor}
+@!edit_file_name: str_number; {file name to be passed to the system editor}
+@z
+
+[90] initial value for edit argument
+@x
+help_ptr:=0; use_err_help:=false; err_help:=0;
+@y
+help_ptr:=0; use_err_help:=false; err_help:=0;
+edit_line:=0; edit_file_name:=0;
+@z
+
+[94] set edit_cmd
+@x
+ begin print_nl("You want to edit file ");
+@.You want to edit file x@>
+ print(input_stack[file_ptr].name_field);
+ print(" at line "); print_int(true_line);@/
+ interaction:=scroll_mode; jump_out;
+ end;
+@y
+ begin {save values to be passed to the system editor}
+ edit_file_name := input_stack[file_ptr].name_field;
+ add_str_ref(edit_file_name);
+ edit_line := true_line;
+ interaction:=scroll_mode; jump_out;
+ end;
+@z
+
+[106] interrupt is predefined and not implemented in GNU~Pascal
+@x
+@d check_interrupt==begin if interrupt<>0 then pause_for_instructions;
+@y
+@d interrupt==buginterrupt
+@f interrupt==true
+@d check_interrupt==begin if interrupt<>0 then pause_for_instructions;
+@z
+
+[171] pack subranges
+@x
+@!quarterword = min_quarterword..max_quarterword; {1/4 of a word}
+@!halfword=min_halfword..max_halfword; {1/2 of a word}
+@y
+@!quarterword = packed min_quarterword..max_quarterword; {1/4 of a word}
+@!halfword=packed min_halfword..max_halfword; {1/2 of a word}
+@z
+
+[212] time and date
+@x
+begin internal[time]:=12*60*unity; {minutes since midnight}
+internal[day]:=4*unity; {fourth day of the month}
+internal[month]:=7*unity; {seventh month of the year}
+internal[year]:=1776*unity; {Anno Domini}
+@y
+var t: time_stamp;
+begin
+get_time_stamp(t);
+internal[time]:=(t.minute + t.hour*60)*unity; {minutes since midnight}
+internal[day]:=t.d@&a@&y*unity;
+internal[month]:=t.m@&o@&n@&t@&h*unity;
+internal[year]:=t.y@&e@&a@&r*unity; {Anno Domini}
+@z
+
+[217] character class for tab and lf
+@x
+for k:=127 to 255 do char_class[k]:=invalid_class;
+@y
+for k:=127 to 255 do char_class[k]:=invalid_class;
+char_class[@'11] := space_class;
+char_class[@'14] := space_class;
+@z
+
+[640] spurious empty line on terminal
+@x
+ print_ln; first:=start;
+ prompt_input("*"); {input on-line into |buffer|}
+@y
+ print_nl("");
+ first:=start; {avoid empty lines on terminal and log file}
+ prompt_input("*"); {input on-line into |buffer|}
+@z
+
+[746] Path separator in Unix
+@x
+@d MP_area=="MPinputs:"
+@.MPinputs@>
+@d MF_area=="MFinputs:"
+@.MFinputs@>
+@d MP_font_area=="TeXfonts:"
+@.TeXfonts@>
+@y
+@d MP_area=="MPinputs/"
+@.MPinputs@>
+@d MF_area=="MFinputs/"
+@.MFinputs@>
+@d MP_font_area=="TeXfonts/"
+@.TeXfonts@>
+@z
+
+[748]
+@x
+else begin if (c=">")or(c=":") then
+@y
+else begin if c="/" then
+@z
+
+[752]
+@x
+MP_mem_default:='MPlib:plain.mem';
+@y
+MP_mem_default:='MPlib/plain.mem';
+@z
+
+[771] filename is needed for system editor
+@x
+flush_string(name); name:=cur_name; cur_name:=0
+@y
+do_nothing
+@z
+
+[1298]
+@x
+@p begin @!{|start_here|}
+@y
+@d gpc_halt == h@&a@&l@&t
+
+@p begin @!{|start_here|}
+@z
+
+[1298] load the mem file before printing the banner line
+@x
+start_of_MP: @<Initialize the output routines@>;
+@y
+start_of_MP: @<Preload the default mem file@>;
+@<Initialize the output routines@>;
+@z
+
+[1298] start editor and pass history
+@x
+final_end: ready_already:=0;
+@y
+final_end:
+if edit_file_name > 0 then start_editor; {user typed `\.{E}'}
+gpc_halt(history);
+ {pass |history| as the exit value to the system}
+@z
+
+[1299] print last end-of-line marker if needed
+@x
+if log_opened then
+ begin wlog_cr;
+ a_close(log_file); selector:=selector-2;
+ if selector=term_only then
+ begin print_nl("Transcript written on ");
+@.Transcript written...@>
+ print(log_name); print_char(".");
+ end;
+ end;
+end;
+@y
+if log_opened then
+ begin if file_offset > 0 then wlog_cr;
+ a_close(log_file); selector:=selector-2;
+ if selector=term_only then
+ begin print_nl("Transcript written on ");
+@.Transcript written...@>
+ print(log_name); print_char(".");
+ end;
+ end;
+ if term_offset > 0 then wterm_cr;
+end;
+@z
+
+[1307] return if eof
+@x
+ read(term_in,m);
+@y
+ if eof(term_in) then return;
+ {don't try to read past end of file}
+ read(term_in,m);
+@z
+
+[1307] return if eof
+@x
+ else begin read(term_in,n);
+@y
+ else begin if eof(term_in) then return;
+ {don't try to read past end of file}
+ read(term_in,n);
+@z
+
+[1308] return eof
+@x
+13: begin read(term_in,l); print_cmd_mod(n,l);
+@y
+13: begin if eof(term_in) then return;
+ {don't try to read past end of file}
+read(term_in,l); print_cmd_mod(n,l);
+@z
+
+[1309 and modules added for METAPOST-GPC]
+@x
+itself will get a new section number.
+@^system dependencies@>
+@y
+itself will get a new section number.
+@^system dependencies@>
+
+@ Try to preload the default mem file. This is called even before
+the first line is read from the terminal, and thus turns \.{VIRMP}
+into \.{MP}, at least as seen by the user.
+
+\indent\.{INIMP} sets |mem_ident| to `\.{INIMP}' and won't load a mem
+file here.
+
+@<Preload the default mem file@> =
+if mem_ident = 0 then
+ begin pack_buffered_name(mem_default_length - mem_ext_length, 1, 0);
+ if not w_open_in(mem_file) then
+ begin
+ wterm_ln('I can''t find the mem file');
+ goto final_end
+ end;
+ if not load_mem_file then
+ begin w_close(mem_file); goto final_end
+ end;
+ w_close(mem_file);
+ end
+
+@
+@d gpc_execute == e@&x@&e@&c@&u@&t@&e
+@d gpc_write_str == w@&r@&i@&t@&e@&s@&t@&r
+
+@<Error hand...@>=
+procedure start_editor;
+var i: integer; {index into |name_of_file|}
+ j: pool_pointer; {index into |str_pool|}
+ cmd_line: gpc_string(200); {area to build the command line}
+begin i := 1; j := str_start[edit_file_name];
+while j<str_stop(edit_file_name) do
+ begin name_of_file[i] := xchr[str_pool[j]]; incr(i); incr(j)
+ end;
+while i<=file_name_size do begin name_of_file[i] := ' '; incr(i) end;
+gpc_write_str(cmd_line, 'vi +', edit_line, ' ', gpc_trim(name_of_file));
+if 0 <> gpc_execute(cmd_line) then
+ write_ln(gpc_param_str(0), ': could not start editor with: "',
+ cmd_line, '"');
+end;
+
+@
+@d gpc_t_signal_handler == t@&s@&i@&g@&n@&a@&l@&h@&a@&n@&d@&l@&e@&r
+@d gpc_install_signal_handler ==
+ i@&n@&s@&t@&a@&l@&l@&s@&i@&g@&n@&a@&l@&h@&a@&n@&d@&l@&e@&r
+@d gpc_sig_int == s@&i@&g@&i@&n@&t
+@d gpc_integer == integer {for later versions of GPC (3.4+) replace
+ \\{integer} by \\{cinteger}}
+
+@<Error hand...@>=
+procedure set_interrupt(signal: gpc_integer);
+begin interrupt := 1 @+end;
+
+@
+@<Set initial values ... @>=
+gpc_install_signal_handler(gpc_sig_int,set_interrupt,true,true,dummy_handler,
+ dummy_boolean);
+
+@ Here are two variables that are needed to install |set_interrupt|.
+@<Local variables for initialization@> =
+dummy_handler: gpc_t_signal_handler;
+dummy_boolean: boolean;
+@z
diff --git a/systems/unix/tex-gpc/mp/mptotex.c b/systems/unix/tex-gpc/mp/mptotex.c
new file mode 100644
index 0000000000..9defdf2f9e
--- /dev/null
+++ b/systems/unix/tex-gpc/mp/mptotex.c
@@ -0,0 +1,224 @@
+/****************************************************************
+Copyright 1990 - 1995 by AT&T Bell Laboratories.
+
+Permission to use, copy, modify, and distribute this software
+and its documentation for any purpose and without fee is hereby
+granted, provided that the above copyright notice appear in all
+copies and that both that the copyright notice and this
+permission notice and warranty disclaimer appear in supporting
+documentation, and that the names of AT&T Bell Laboratories or
+any of its entities not be used in advertising or publicity
+pertaining to distribution of the software without specific,
+written prior permission.
+
+AT&T disclaims all warranties with regard to this software,
+including all implied warranties of merchantability and fitness.
+In no event shall AT&T be liable for any special, indirect or
+consequential damages or any damages whatsoever resulting from
+loss of use, data or profits, whether in an action of contract,
+negligence or other tortious action, arising out of or in
+connection with the use or performance of this software.
+****************************************************************/
+
+/* This program transforms a MetaPost input file into a TeX or LaTeX input
+ * file by stripping out btex...etex and verbatimtex...etex sections.
+ * Leading and trailing spaces and tabs are removed from the extracted
+ * material and it is surrounded by the preceeding and following strings
+ * defined immediately below. The input file should be given as argument 1
+ * and the resulting TeX file is written on standard output.
+ */
+
+#include <stdio.h>
+#define bufsize 1000
+
+char* predoc = "";
+char* postdoc = "\\end{document}\n";
+char* pretex1 = "\\shipout\\hbox{\\smash{\\hbox{\\hbox{%% line %d %s\n";
+char* pretex = "\\shipout\\hbox{\\smash{\\hbox{\\hbox{%% line %d %s\n";
+char* posttex = "}\\vrule width1sp}}}\n";
+char* preverb = "%% line %d %s\n";
+char* postverb = "%\n";
+
+char *mpname;
+FILE *mpfile;
+int lnno = 0; /* current line number */
+int texcnt = 0; /* btex..etex blocks so far */
+char buf[bufsize]; /* the input line */
+char *bb, *tt, *aa; /* start of before, token, and after strings */
+
+void usage(nam)
+ char *nam;
+{
+ fprintf(stderr, "Usage: %s <mp-file>\n", nam);
+ exit(1);
+}
+
+void err(msg)
+ char *msg;
+{
+ fprintf(stderr, "! Error in %s at line %d: %s\n", mpname, lnno, msg);
+ exit(1);
+}
+
+char *getline() /* returns NULL on EOF or error, otherwise buf */
+{
+ char *s;
+
+ if (fgets(buf, bufsize, mpfile)==NULL)
+ return NULL;
+ lnno++;
+ for (s= &buf[1]; *s!='\0'; s++) /* do nothing */;
+ if (s==&buf[bufsize-1] && s[-1]!='\n') err("Line is too long");
+ s[-1] = '\0';
+ return buf;
+}
+
+
+/* Return nonzero if a prefix of string s matches the null-terminated string t
+ * and the next character is not a letter of an underscore.
+ */
+int match_str(s, t)
+ char *s, *t;
+{
+ while (*t!=0) {
+ if (*s!=*t) return 0;
+ s++; t++;
+ }
+ switch (*s) {
+ case 'a': case 'c': case 'd': case 'f': case 'g': case 'h':
+ case 'i': case 'j': case 'k': case 'l': case 'm': case 'n':
+ case 'o': case 'p': case 'q': case 'r': case 's': case 't':
+ case 'u': case 'w': case 'x': case 'y': case 'z': case '_':
+ case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
+ case 'G': case 'H': case 'I': case 'J': case 'K': case 'L':
+ case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
+ case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
+ case 'Y': case 'Z': case 'b': case 'e': case 'v':
+ return 0;
+ default:
+ return 1;
+ }
+}
+
+
+/* This function tries to express s as the concatination of three strings
+ * b, t, a, with the global pointers bb, tt, and aa set to the start of the
+ * corresponding strings. String t is either a quote mark, a percent sign,
+ * or an alphabetic token "btex", "etex", or "verbatimtex". (An alphabetic
+ * token is a maximal sequence of letters and underscores.) If there are
+ * several possible substrings t, we choose the leftmost one. If there is
+ * no such t, we set b=s and return 0.
+ */
+int getbta(s)
+ char *s;
+{
+ int ok=1; /* zero if last character was a-z, A-Z, or _ */
+
+ bb = s;
+ for (tt=bb; *tt!=0; tt++)
+ switch (*tt) {
+ case '"': case '%':
+ aa = tt+1;
+ return 1;
+ case 'b':
+ if (ok && match_str(tt,"btex")) {
+ aa = tt+4;
+ return 1;
+ } else ok=0;
+ break;
+ case 'e':
+ if (ok && match_str(tt,"etex")) {
+ aa = tt+4;
+ return 1;
+ } else ok=0;
+ break;
+ case 'v':
+ if (ok && match_str(tt,"verbatimtex")) {
+ aa = tt+11;
+ return 1;
+ } else ok=0;
+ break;
+ case 'a': case 'c': case 'd': case 'f': case 'g': case 'h':
+ case 'i': case 'j': case 'k': case 'l': case 'm': case 'n':
+ case 'o': case 'p': case 'q': case 'r': case 's': case 't':
+ case 'u': case 'w': case 'x': case 'y': case 'z': case '_':
+ case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
+ case 'G': case 'H': case 'I': case 'J': case 'K': case 'L':
+ case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
+ case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
+ case 'Y': case 'Z':
+ ok = 0;
+ break;
+ default:
+ ok = 1;
+ }
+ aa = tt;
+ return 0;
+}
+
+
+void copytex()
+{
+ char *s; /* where a string to print stops */
+ char c;
+ int ignore = 1;
+
+ do { if (*aa==0)
+ if ((aa=getline())==NULL)
+ err("btex section does not end");
+ else if (--ignore<0) printf("\n");
+ if (getbta(aa) && *tt=='e') {
+ s = tt-1;
+ while (s>=bb && (*s==' ' || *s=='\t'))
+ s--;
+ s++;
+ } else {
+ if (*tt=='b') err("btex in TeX mode");
+ if (*tt=='v') err("verbatimtex in TeX mode");
+ s = aa;
+ }
+ c = *s;
+ *s = 0;
+ printf("%s", bb);
+ *s = c;
+ } while (*tt!='e');
+}
+
+
+void do_line()
+{
+ aa = buf;
+ while (getbta(aa))
+ if (*tt=='%') break;
+ else if (*tt=='"') {
+ do if (!getbta(aa)) err("string does not end");
+ while (*tt!='"');
+ } else if (*tt=='b') {
+ if (texcnt++ ==0) printf(pretex1,lnno,mpname);
+ else printf(pretex,lnno,mpname);
+ while (*aa==' ' || *aa=='\t') aa++;
+ copytex();
+ printf("%s",posttex);
+ } else if (*tt=='v') {
+ printf(preverb,lnno,mpname);
+ while (*aa==' ' || *aa=='\t') aa++;
+ copytex();
+ printf("%s",postverb);
+ } else err("unmatched etex");
+}
+
+
+
+void main(argc, argv)
+ char *argv[];
+{
+ if (argc!=2) usage(argv[0]);
+ mpname = argv[1];
+ mpfile = fopen(mpname, "r");
+ if (mpname==NULL) usage(argv[0]);
+ printf("%s",predoc);
+ while (getline()!=NULL)
+ do_line();
+ printf("%s",postdoc);
+ exit(0);
+}
diff --git a/systems/unix/tex-gpc/mp/mpx b/systems/unix/tex-gpc/mp/mpx
new file mode 100644
index 0000000000..866bad0600
--- /dev/null
+++ b/systems/unix/tex-gpc/mp/mpx
@@ -0,0 +1,8 @@
+# process .mp files that include TeX programs.
+case $# in
+1) f=`basename $1 .mp`;;
+*) echo Usage: $0 mp-file; exit 1;;
+esac
+mptotex $f.mp \
+| tex && dvitomp texput.dvi $f.mpx && mp $f.mp \
+|| echo $0 failed!; exit 1