1 /***** Autogenerated from runlabel.in; changes will be overwritten *****/
2 
3 #line 1 "runtimebase.in"
4 /*****
5  * runtimebase.in
6  * Andy Hammerlindl  2009/07/28
7  *
8  * Common declarations needed for all code-generating .in files.
9  *
10  *****/
11 
12 
13 #line 1 "runlabel.in"
14 /*****
15  * runlabel.in
16  *
17  * Runtime functions for label operations.
18  *
19  *****/
20 
21 #line 1 "runtimebase.in"
22 #include "stack.h"
23 #include "types.h"
24 #include "builtin.h"
25 #include "entry.h"
26 #include "errormsg.h"
27 #include "array.h"
28 #include "triple.h"
29 #include "callable.h"
30 #include "opsymbols.h"
31 
32 using vm::stack;
33 using vm::error;
34 using vm::array;
35 using vm::read;
36 using vm::callable;
37 using types::formal;
38 using types::function;
39 using camp::triple;
40 
41 #define PRIMITIVE(name,Name,asyName) using types::prim##Name;
42 #include <primitives.h>
43 #undef PRIMITIVE
44 
45 typedef double real;
46 
47 void unused(void *);
48 
49 namespace run {
50 array *copyArray(array *a);
51 array *copyArray2(array *a);
52 array *copyArray3(array *a);
53 
54 double *copyTripleArray2Components(array *a, bool square=true, size_t dim2=0,
55                                    GCPlacement placement=NoGC);
56 }
57 
58 function *realRealFunction();
59 
60 #define CURRENTPEN processData().currentpen
61 
62 #line 19 "runlabel.in"
63 #include "picture.h"
64 #include "drawlabel.h"
65 #include "locate.h"
66 
67 using namespace camp;
68 using namespace vm;
69 using namespace settings;
70 
71 typedef array realarray;
72 typedef array stringarray;
73 typedef array penarray;
74 typedef array patharray;
75 typedef array patharray2;
76 
77 using types::realArray;
78 using types::stringArray;
79 using types::penArray;
80 using types::pathArray;
81 using types::pathArray2;
82 
cannotread(const string & s)83 void cannotread(const string& s)
84 {
85   ostringstream buf;
86   buf << "Cannot read from " << s;
87   error(buf);
88 }
89 
cannotwrite(const string & s)90 void cannotwrite(const string& s)
91 {
92   ostringstream buf;
93   buf << "Cannot write to " << s;
94   error(buf);
95 }
96 
readpair(stringstream & s,double hscale=1.0,double vscale=1.0)97 pair readpair(stringstream& s, double hscale=1.0, double vscale=1.0)
98 {
99   double x,y;
100   s >> y;
101   s >> x;
102   return pair(hscale*x,vscale*y);
103 }
104 
105 string ASYx="/ASYx {( ) print ASYX sub 12 string cvs print} bind def";
106 string ASYy="/ASYy {( ) print ASYY sub 12 string cvs print} bind def";
107 string pathforall="{(M) print ASYy ASYx} {(L) print ASYy ASYx} {(C) print ASYy ASYx ASYy ASYx ASYy ASYx} {(c) print} pathforall";
108 string currentpoint="print currentpoint ASYy ASYx ";
109 string ASYinit="/ASYX currentpoint pop def /ASYY currentpoint exch pop def ";
110 string ASY1="ASY1 {"+ASYinit+"/ASY1 false def} if ";
111 
endpath(std::ostream & ps)112 void endpath(std::ostream& ps)
113 {
114   ps << ASY1 << pathforall << " (M) " << currentpoint
115      << "currentpoint newpath moveto} bind def" << endl;
116 }
117 
fillpath(std::ostream & ps)118 void fillpath(std::ostream& ps)
119 {
120   ps << "/fill {closepath ";
121   endpath(ps);
122 }
123 
showpath(std::ostream & ps)124 void showpath(std::ostream& ps)
125 {
126   ps << ASYx << newl
127      << ASYy << newl
128      << "/ASY1 true def" << newl
129      << "/stroke {strokepath ";
130   endpath(ps);
131   fillpath(ps);
132 }
133 
readpath(const string & psname,bool keep,bool pdf=false,double hscale=1.0,double vsign=1.0)134 array *readpath(const string& psname, bool keep, bool pdf=false,
135                 double hscale=1.0, double vsign=1.0)
136 {
137   double vscale=vsign*hscale;
138   array *PP=new array(0);
139 
140   char *oldPath=NULL;
141   string dir=stripFile(outname());
142   if(!dir.empty()) {
143     oldPath=getPath();
144     setPath(dir.c_str());
145   }
146 
147   mem::vector<string> cmd;
148   cmd.push_back(getSetting<string>("gs"));
149   cmd.push_back("-q");
150   cmd.push_back("-dBATCH");
151   cmd.push_back("-P");
152   if(safe) cmd.push_back("-dSAFER");
153 #ifdef __MSDOS__
154   const string null="NUL";
155 #else
156   const string null="/dev/null";
157 #endif
158   cmd.push_back("-sDEVICE=eps2write");
159   cmd.push_back("-sOutputFile="+null);
160   cmd.push_back(stripDir(psname));
161   iopipestream gs(cmd,"gs","Ghostscript");
162   while(gs.running()) {
163     stringstream buf;
164     string s=gs.readline();
165     if(s.empty()) break;
166     if(!pdf) gs << newl;
167 
168 // Workaround broken stringstream container in MacOS 10.9 libc++.
169 #if defined(__APPLE__) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__ )
170     for(string::iterator i=s.begin(); i != s.end(); ++i) {
171       if(isalpha(*i) && *i != 'e') {buf << " ";}
172       buf << *i;
173     }
174 #else
175     buf << s;
176 #endif
177 
178     if(verbose > 2) cout << endl;
179 
180     mem::vector<solvedKnot> nodes;
181     solvedKnot node;
182     bool cyclic=false;
183     bool active=false;
184 
185     array *P=new array(0);
186     PP->push(P);
187 
188     while(!buf.eof()) {
189       char c;
190       buf >> c;
191       if(c == '>') break;
192 
193       switch(c) {
194         case 'M':
195         {
196           if(active) {
197             if(cyclic) {
198               if(node.point == nodes[0].point)
199                 nodes[0].pre=node.pre;
200               else {
201                 pair delta=(nodes[0].point-node.point)*third;
202                 node.post=node.point+delta;
203                 nodes[0].pre=nodes[0].point-delta;
204                 node.straight=true;
205                 nodes.push_back(node);
206               }
207             } else {
208               node.post=node.point;
209               node.straight=false;
210               nodes.push_back(node);
211             }
212             if(cyclic) // Discard noncyclic paths.
213               P->push(path(nodes,nodes.size(),cyclic));
214             nodes.clear();
215           }
216           active=false;
217           cyclic=false;
218           node.pre=node.point=readpair(buf,hscale,vscale);
219           node.straight=false;
220           break;
221         }
222         case 'L':
223         {
224           pair point=readpair(buf,hscale,vscale);
225           pair delta=(point-node.point)*third;
226           node.post=node.point+delta;
227           node.straight=true;
228           nodes.push_back(node);
229           active=true;
230           node.pre=point-delta;
231           node.point=point;
232           break;
233         }
234         case 'C':
235         {
236           pair point=readpair(buf,hscale,vscale);
237           pair pre=readpair(buf,hscale,vscale);
238           node.post=readpair(buf,hscale,vscale);
239           node.straight=false;
240           nodes.push_back(node);
241           active=true;
242           node.pre=pre;
243           node.point=point;
244           break;
245         }
246         case 'c':
247         {
248           cyclic=true;
249           break;
250         }
251       }
252     }
253   }
254 
255   if(oldPath != NULL)
256     setPath(oldPath);
257 
258   if(!keep)
259     unlink(psname.c_str());
260   return PP;
261 }
262 
263 // Autogenerated routines:
264 
265 
266 
267 #ifndef NOSYM
268 #include "runlabel.symbols.h"
269 
270 #endif
271 namespace run {
272 #line 222 "runlabel.in"
273 // void label(picture *f, string *s, string *size, transform t, pair position,           pair align, pen p);
gen_runlabel0(stack * Stack)274 void gen_runlabel0(stack *Stack)
275 {
276   pen p=vm::pop<pen>(Stack);
277   pair align=vm::pop<pair>(Stack);
278   pair position=vm::pop<pair>(Stack);
279   transform t=vm::pop<transform>(Stack);
280   string * size=vm::pop<string *>(Stack);
281   string * s=vm::pop<string *>(Stack);
282   picture * f=vm::pop<picture *>(Stack);
283 #line 224 "runlabel.in"
284   f->append(new drawLabel(*s,*size,t,position,align,p));
285 }
286 
287 #line 228 "runlabel.in"
288 // bool labels(picture *f);
gen_runlabel1(stack * Stack)289 void gen_runlabel1(stack *Stack)
290 {
291   picture * f=vm::pop<picture *>(Stack);
292 #line 229 "runlabel.in"
293   {Stack->push<bool>(f->havelabels()); return;}
294 }
295 
296 #line 233 "runlabel.in"
297 // realarray* texsize(string *s, pen p=CURRENTPEN);
gen_runlabel2(stack * Stack)298 void gen_runlabel2(stack *Stack)
299 {
300   pen p=vm::pop<pen>(Stack,CURRENTPEN);
301   string * s=vm::pop<string *>(Stack);
302 #line 234 "runlabel.in"
303   texinit();
304   processDataStruct &pd=processData();
305 
306   string texengine=getSetting<string>("tex");
307   setpen(pd.tex,texengine,p);
308 
309   double width,height,depth;
310   texbounds(width,height,depth,pd.tex,*s);
311 
312   array *t=new array(3);
313   (*t)[0]=width;
314   (*t)[1]=height;
315   (*t)[2]=depth;
316   {Stack->push<realarray*>(t); return;}
317 }
318 
319 #line 251 "runlabel.in"
320 // patharray2* _texpath(stringarray *s, penarray *p);
gen_runlabel3(stack * Stack)321 void gen_runlabel3(stack *Stack)
322 {
323   penarray * p=vm::pop<penarray *>(Stack);
324   stringarray * s=vm::pop<stringarray *>(Stack);
325 #line 252 "runlabel.in"
326   size_t n=checkArrays(s,p);
327   if(n == 0) {Stack->push<patharray2*>(new array(0)); return;}
328 
329   string prefix=cleanpath(outname());
330   string psname=auxname(prefix,"ps");
331   string texname=auxname(prefix,"tex");
332   string dviname=auxname(prefix,"dvi");
333   bbox b;
334   string texengine=getSetting<string>("tex");
335   bool xe=settings::xe(texengine) || settings::context(texengine);
336   texfile tex(texname,b,true);
337   tex.miniprologue();
338 
339   for(size_t i=0; i < n; ++i) {
340     tex.setfont(read<pen>(p,i));
341     if(i != 0) {
342       if(texengine == "context")
343         tex.verbatimline("}\\page\\hbox{%");
344       else if(texengine == "luatex" || texengine == "tex" ||
345               texengine == "pdftex")
346         tex.verbatimline("\\eject");
347       else
348         tex.verbatimline("\\newpage");
349     }
350     if(!xe) {
351       tex.verbatimline("\\special{ps:");
352       tex.verbatimline(ASYx);
353       tex.verbatimline(ASYy);
354       tex.verbatimline("/ASY1 true def");
355       tex.verbatimline("/show {"+ASY1+
356                        "currentpoint newpath moveto false charpath "+pathforall+
357                        "} bind def");
358       tex.verbatimline("/V {"+ASY1+"Ry neg Rx 4 copy 4 2 roll 2 copy 6 2 roll 2 copy (M) print ASYy ASYx (L) print ASYy add ASYx (L) print add ASYy add ASYx (L) print add ASYy ASYx (c) print} bind def}");
359     }
360     tex.verbatimline(read<string>(s,i)+"\\ %");
361   }
362 
363   tex.epilogue(true);
364   tex.close();
365 
366   int status=opentex(texname,prefix,!xe);
367 
368   string pdfname,pdfname2,psname2;
369   bool keep=getSetting<bool>("keep");
370 
371   if(!status) {
372     if(xe) {
373       pdfname=auxname(prefix,"pdf");
374       pdfname2=auxname(prefix+"_","pdf");
375       psname2=auxname(prefix+"_","ps");
376       if(!fs::exists(pdfname)) {Stack->push<patharray2*>(new array(n)); return;}
377       std::ofstream ps(psname.c_str(),std::ios::binary);
378       if(!ps) cannotwrite(psname);
379 
380       showpath(ps);
381 
382       mem::vector<string> pcmd;
383       pcmd.push_back(getSetting<string>("gs"));
384       pcmd.push_back("-q");
385       pcmd.push_back("-dNOCACHE");
386       pcmd.push_back("-dNOPAUSE");
387       pcmd.push_back("-dBATCH");
388       if(safe) pcmd.push_back("-dSAFER");
389       pcmd.push_back("-sDEVICE=pdfwrite");
390       pcmd.push_back("-sOutputFile="+pdfname2);
391       pcmd.push_back(pdfname);
392       status=System(pcmd,0,true,"gs");
393       if(status == 0) {
394         mem::vector<string> cmd;
395         cmd.push_back(getSetting<string>("gs"));
396         cmd.push_back("-q");
397         cmd.push_back("-dNOCACHE");
398         cmd.push_back("-dNOPAUSE");
399         cmd.push_back("-dBATCH");
400         if(safe) cmd.push_back("-dSAFER");
401         cmd.push_back("-sDEVICE=eps2write");
402         // Work around eps2write bug that forces all postscript to first page.
403         cmd.push_back("-sOutputFile="+psname2+"%d");
404         cmd.push_back(pdfname2);
405         status=System(cmd,0,true,"gs");
406 
407         for(unsigned int i=1; i <= n ; ++i) {
408           ostringstream buf;
409           buf << psname2.c_str() << i;
410           const char *name=buf.str().c_str();
411           std::ifstream in(name,std::ios::binary);
412           ps << in.rdbuf();
413           ps << "(>\n) print flush\n";
414           if(!keep) unlink(name);
415         }
416         ps.close();
417       }
418     } else {
419       if(!fs::exists(dviname)) {Stack->push<patharray2*>(new array(n)); return;}
420       mem::vector<string> dcmd;
421       dcmd.push_back(getSetting<string>("dvips"));
422       dcmd.push_back("-R");
423       dcmd.push_back("-Pdownload35");
424       dcmd.push_back("-D600");
425       push_split(dcmd,getSetting<string>("dvipsOptions"));
426       if(verbose <= 2) dcmd.push_back("-q");
427       dcmd.push_back("-o"+psname);
428       dcmd.push_back(dviname);
429       status=System(dcmd,0,true,"dvips");
430     }
431   }
432 
433   if(status != 0)
434     error("texpath failed");
435 
436   if(!keep) { // Delete temporary files.
437     unlink(texname.c_str());
438     if(!getSetting<bool>("keepaux"))
439       unlink(auxname(prefix,"aux").c_str());
440     unlink(auxname(prefix,"log").c_str());
441     if(xe) {
442       unlink(pdfname.c_str());
443       unlink(pdfname2.c_str());
444     } else
445       unlink(dviname.c_str());
446     if(settings::context(texengine)) {
447       unlink(auxname(prefix,"top").c_str());
448       unlink(auxname(prefix,"tua").c_str());
449       unlink(auxname(prefix,"tuc").c_str());
450       unlink(auxname(prefix,"tui").c_str());
451     }
452   }
453   {Stack->push<patharray2*>(xe ? readpath(psname,keep,true,0.1) :
454     readpath(psname,keep,false,0.12,-1.0)); return;}
455 }
456 
457 #line 384 "runlabel.in"
458 // patharray2* textpath(stringarray *s, penarray *p);
gen_runlabel4(stack * Stack)459 void gen_runlabel4(stack *Stack)
460 {
461   penarray * p=vm::pop<penarray *>(Stack);
462   stringarray * s=vm::pop<stringarray *>(Stack);
463 #line 385 "runlabel.in"
464   size_t n=checkArrays(s,p);
465   if(n == 0) {Stack->push<patharray2*>(new array(0)); return;}
466 
467   string prefix=cleanpath(outname());
468   string outputname=auxname(prefix,getSetting<string>("textoutformat"));
469 
470   string textname=auxname(prefix,getSetting<string>("textextension"));
471   std::ofstream text(textname.c_str());
472 
473   if(!text) cannotwrite(textname);
474 
475   for(size_t i=0; i < n; ++i) {
476     text << getSetting<string>("textprologue") << newl
477          << read<pen>(p,i).Font() << newl
478          << read<string>(s,i) << newl
479          << getSetting<string>("textepilogue") << endl;
480   }
481   text.close();
482 
483   string psname=auxname(prefix,"ps");
484   std::ofstream ps(psname.c_str());
485   if(!ps) cannotwrite(psname);
486 
487   showpath(ps);
488 
489   mem::vector<string> cmd;
490   cmd.push_back(getSetting<string>("textcommand"));
491   push_split(cmd,getSetting<string>("textcommandOptions"));
492   cmd.push_back(textname);
493   iopipestream typesetter(cmd);
494   typesetter.block(true,false);
495 
496   mem::vector<string> cmd2;
497   cmd2.push_back(getSetting<string>("gs"));
498   cmd2.push_back("-q");
499   cmd2.push_back("-dNOCACHE");
500   cmd2.push_back("-dNOPAUSE");
501   cmd2.push_back("-dBATCH");
502   cmd2.push_back("-P");
503   if(safe) cmd2.push_back("-dSAFER");
504   cmd2.push_back("-sDEVICE=eps2write");
505   cmd2.push_back("-sOutputFile=-");
506   cmd2.push_back("-");
507   iopipestream gs(cmd2,"gs","Ghostscript");
508   gs.block(false,false);
509 
510   // TODO: Simplify by connecting the pipes directly.
511   while(true) {
512     string out;
513     if(typesetter.isopen()) {
514       typesetter >> out;
515       if(!out.empty()) gs << out;
516       else if(!typesetter.running()) {
517         typesetter.pipeclose();
518         gs.eof();
519       }
520     }
521     string out2;
522     gs >> out2;
523     if(out2.empty() && !gs.running()) break;
524     ps << out2;
525   }
526   ps.close();
527 
528   if(verbose > 2) cout << endl;
529 
530   bool keep=getSetting<bool>("keep");
531   if(!keep) // Delete temporary files.
532     unlink(textname.c_str());
533   {Stack->push<patharray2*>(readpath(psname,keep,false,0.1)); return;}
534 }
535 
536 #line 458 "runlabel.in"
537 // patharray* _strokepath(path g, pen p=CURRENTPEN);
gen_runlabel5(stack * Stack)538 void gen_runlabel5(stack *Stack)
539 {
540   pen p=vm::pop<pen>(Stack,CURRENTPEN);
541   path g=vm::pop<path>(Stack);
542 #line 459 "runlabel.in"
543   array *P=new array(0);
544   if(g.size() == 0) {Stack->push<patharray*>(P); return;}
545 
546   string prefix=cleanpath(outname());
547   string psname=auxname(prefix,"ps");
548   bbox b;
549   psfile ps(psname,false);
550   ps.prologue(b);
551   ps.verbatimline(ASYx);
552   ps.verbatimline(ASYy);
553   ps.verbatimline("/stroke {"+ASYinit+pathforall+"} bind def");
554   ps.resetpen();
555   ps.setpen(p);
556   ps.write(g);
557   ps.strokepath();
558   ps.stroke(p);
559   ps.verbatimline("(M) "+currentpoint);
560   ps.epilogue();
561   ps.close();
562   array *a=readpath(psname,getSetting<bool>("keep"));
563   {Stack->push<patharray*>(a->size() > 0 ? read<array *>(a,0) : a); return;}
564 }
565 
566 } // namespace run
567 
568 namespace trans {
569 
gen_runlabel_venv(venv & ve)570 void gen_runlabel_venv(venv &ve)
571 {
572 #line 222 "runlabel.in"
573   addFunc(ve, run::gen_runlabel0, primVoid(), SYM(label), formal(primPicture(), SYM(f), false, false), formal(primString(), SYM(s), false, false), formal(primString(), SYM(size), false, false), formal(primTransform(), SYM(t), false, false), formal(primPair(), SYM(position), false, false), formal(primPair(), SYM(align), false, false), formal(primPen(), SYM(p), false, false));
574 #line 228 "runlabel.in"
575   addFunc(ve, run::gen_runlabel1, primBoolean(), SYM(labels), formal(primPicture(), SYM(f), false, false));
576 #line 233 "runlabel.in"
577   addFunc(ve, run::gen_runlabel2, realArray(), SYM(texsize), formal(primString(), SYM(s), false, false), formal(primPen(), SYM(p), true, false));
578 #line 251 "runlabel.in"
579   addFunc(ve, run::gen_runlabel3, pathArray2() , SYM(_texpath), formal(stringArray() , SYM(s), false, false), formal(penArray() , SYM(p), false, false));
580 #line 384 "runlabel.in"
581   addFunc(ve, run::gen_runlabel4, pathArray2() , SYM(textpath), formal(stringArray() , SYM(s), false, false), formal(penArray() , SYM(p), false, false));
582 #line 458 "runlabel.in"
583   addFunc(ve, run::gen_runlabel5, pathArray() , SYM(_strokepath), formal(primPath(), SYM(g), false, false), formal(primPen(), SYM(p), true, false));
584 }
585 
586 } // namespace trans
587