From: Daniel Wang I got bored and hacked up a SML-NG to Postscript converter. It's written in Standard ML... but most of the work was hacking Postscript... in particular You just need to tack on the Postscript prologue below and have your processor output something very close to the semantic meaning of the document. The prologue is smart and handles all the line wrapping and and page breaking. You just need to insert hard line breaks for TT and expand tabs. The prologue is included below.. and example is included below. Its probably easy to reuse with the reference validator... Enjoy %! %%%%%%%%%%% start prologue /inch { 72 mul } bind def /paperWd 8.5 inch def /paperHt 11 inch def /vMarginSz 1 inch def /hMarginSz 1 inch def /botMargin vMarginSz def /leftMargin hMarginSz def /topMargin paperHt vMarginSz sub def /rightMargin paperWd hMarginSz sub def % set up fonts /R_font /Times-Roman findfont def /B_font /Times-Bold findfont def /I_font /Times-Italic findfont def /BI_font /Times-BoldItalic findfont def % /TT_font R_font def % /BT_font B_font def % /IT_font I_font def % /BIT_font BI_font def /TT_font /Courier findfont def /BT_font /Courier-Bold findfont def /IT_font /Courier-Oblique findfont def /BIT_font /Courier-BoldOblique findfont def % sizes /Size0 12 def /Size1 Size0 1.25 mul def /Size2 Size0 1.50 mul def /Size3 Size0 1.75 mul def /Size4 Size0 2.00 mul def /Size5 Size0 2.25 mul def /Size6 Size0 2.50 mul def /Size7 Size0 2.75 mul def /Size8 Size0 3.00 mul def /Size9 Size0 3.25 mul def % /uline 0 def /baseFont R_font def /fontSize Size0 def /lineHt fontSize def /posX leftMargin def /posY topMargin def /setDefault { /fontSize Size0 store /baseFont R_font store /uline 0 store 0.0 0.0 0.0 setrgbcolor} bind def /drawPageBB { newpath leftMargin botMargin moveto rightMargin botMargin lineto rightMargin topMargin lineto leftMargin topMargin lineto closepath stroke } bind def % show with underlining /ushow { /n exch def /str exch def n 0 eq { str show } { currentpoint str show currentpoint n setlinewidth newpath moveto lineto stroke } ifelse } bind def /setFont { /baseFont exch store } bind def /setSize { /fontSize exch store fontSize lineHt gt { /lineHt fontSize store } if } bind def /setColor { setrgbcolor } bind def /setU { /uline exch store } bind def % set up page /START { /posX leftMargin store /posY topMargin store /lineHt fontSize store [ } bind def % done with page /END { flushLine % flush pending output pop % throw away the mark showpage } bind def /flushLine { /posX leftMargin store % move to line start /posY posY lineHt sub store % move line down posY botMargin lt % handle page overflow { gsave showpage grestore /posY topMargin lineHt sub store } if posX posY moveto % execute the buffer gsave ] { aload pop posY add moveto setfont setcolor ushow } forall [ grestore /lineHt fontSize store } bind def % new line /NL { flushLine } bind def % compute text size print and wrap to next line if needed /T { baseFont fontSize scalefont setfont /str exch def % string to print str stringwidth /dy exch def % x delta of string /dx exch def % y delta of string dy lineHt add lineHt gt % base line { /lineHt lineHt dy store } if posX dx add rightMargin gt { NL } if [str uline currentcolor currentfont posX dy] % add to line buffer /posX posX dx add store setDefault } bind def % bold italic tt /Fbit { R_font setFont } bind def /FBit { B_font setFont } bind def /FbIt { I_font setFont } bind def /FBIt { BI_font setFont } bind def /FbiT { TT_font setFont } bind def /FBiT { BT_font setFont } bind def /FbIT { IT_font setFont } bind def /FBIT { BIT_font setFont } bind def /U0 { 0 setU } bind def /U1 { 1 setU } bind def /U2 { 2 setU } bind def /U3 { 3 setU } bind def /S0 { Size0 setSize } bind def /S1 { Size1 setSize } bind def /S2 { Size2 setSize } bind def /S3 { Size3 setSize } bind def /S4 { Size4 setSize } bind def /S5 { Size5 setSize } bind def /S6 { Size6 setSize } bind def /S7 { Size7 setSize } bind def /S8 { Size8 setSize } bind def /S9 { Size9 setSize } bind def /Cr { 1.0 0.0 0.0 setColor } bind def /Cg { 0.0 1.0 0.0 setColor } bind def /Cb { 0.0 0.0 1.0 setColor } bind def /Cc { 0.0 1.0 1.0 setColor } bind def /Cm { 1.0 0.0 1.0 setColor } bind def /Cy { 1.0 1.0 0.0 setColor } bind def /Ck { 0.0 0.0 0.0 setColor } bind def /Cw { 1.0 1.0 1.0 setColor } bind def setDefault %%%%%%%%%%%%%%%%% end prologue START % notice the capitalization Fbit (Hello World!) T FBit (Hello World!) T FbIt (Hello World!) T FBIt (Hello World!) T FbiT (Hello World!) T FBiT (Hello World!) T FbIT (Hello World!) T FBIT (Hello World!) T Fbit U0 (Hello World!) T Fbit U1 (Hello World!) T Fbit U2 (Hello World!) T Fbit U3 (Hello World!) T NL Fbit Cr (Hello World!) T Fbit Cb (Hello World!) T Fbit Cg (Hello World!) T Fbit Cc (Hello World!) T NL Fbit S0 (Hello World!) T Fbit S1 (Hello World!) T Fbit S2 (Hello World!) T Fbit S3 (Hello World!) T NL Fbit Cr U0 (Hello World!) T Fbit Cb U1 (Hello World!) T Fbit Cg U2 (Hello World!) T Fbit Cc U3 (Hello World!) T NL Fbit S0 U0 (Hello World!) T Fbit S1 U1 (Hello World!) T Fbit S2 U2 (Hello World!) T Fbit S3 U3 (Hello World!) T NL Fbit S1 Cy U0 (Hello World!) T Fbit S2 Cm U1 (Hello World!) T Fbit S3 Ck U2 (Hello World!) T Fbit S4 Cw U3 (Hello World!) T NL END