1 // Copyright (c) 1996 James Clark
2 // See the file copying.txt for copying permission.
3 
4 #include "stylelib.h"
5 #include "ELObj.h"
6 #include "Interpreter.h"
7 #include "InterpreterMessages.h"
8 #include "macros.h"
9 #include <string.h>
10 #include <math.h>
11 #include <stdio.h>
12 
13 #ifdef DSSSL_NAMESPACE
14 namespace DSSSL_NAMESPACE {
15 #endif
16 
17 class ReverseNodeListObj : public NodeListObj {
18 public:
19   ReverseNodeListObj(NodeListObj *);
20   NodePtr nodeListFirst(EvalContext &, Interpreter &);
21   NodeListObj *nodeListRest(EvalContext &, Interpreter &);
22   NodeListObj *nodeListReverse(EvalContext &context, Interpreter &interp);
23   NodePtr nodeListRef(long, EvalContext &, Interpreter &);
24   long nodeListLength(EvalContext &context, Interpreter &interp);
25   void traceSubObjects(Collector &) const;
26 private:
27   NodeListObj *reversed(EvalContext &context, Interpreter &interp);
28   NodeListObj *nl_;
29   NodeListObj *reversed_;
30 };
31 
ELObj()32 ELObj::ELObj()
33 {
34   hasSubObjects_ = 0;
35 }
36 
isEqual(ELObj &)37 bool ELObj::isEqual(ELObj &)
38 {
39   return false;
40 }
41 
isEquiv(ELObj & obj)42 bool ELObj::isEquiv(ELObj &obj)
43 {
44   return isEqual(obj);
45 }
46 
isNil() const47 bool ELObj::isNil() const
48 {
49   return false;
50 }
51 
isList() const52 bool ELObj::isList() const
53 {
54   return false;
55 }
56 
isTrue() const57 bool ELObj::isTrue() const
58 {
59   return true;
60 }
61 
asPair()62 PairObj *ELObj::asPair()
63 {
64   return 0;
65 }
66 
asVector()67 VectorObj *ELObj::asVector()
68 {
69   return 0;
70 }
71 
asSymbol()72 SymbolObj *ELObj::asSymbol()
73 {
74   return 0;
75 }
76 
asKeyword()77 KeywordObj *ELObj::asKeyword()
78 {
79   return 0;
80 }
81 
convertToString()82 StringObj *ELObj::convertToString()
83 {
84   return 0;
85 }
86 
asFunction()87 FunctionObj *ELObj::asFunction()
88 {
89   return 0;
90 }
91 
asSosofo()92 SosofoObj *ELObj::asSosofo()
93 {
94   return 0;
95 }
96 
asAppendSosofo()97 AppendSosofoObj *ELObj::asAppendSosofo()
98 {
99   return 0;
100 }
101 
asColor()102 ColorObj *ELObj::asColor()
103 {
104   return 0;
105 }
106 
asColorSpace()107 ColorSpaceObj *ELObj::asColorSpace()
108 {
109   return 0;
110 }
111 
asAddress()112 AddressObj *ELObj::asAddress()
113 {
114   return 0;
115 }
116 
asDisplaySpace()117 DisplaySpaceObj *ELObj::asDisplaySpace()
118 {
119   return 0;
120 }
121 
asInlineSpace()122 InlineSpaceObj *ELObj::asInlineSpace()
123 {
124   return 0;
125 }
126 
asGlyphSubstTable()127 GlyphSubstTableObj *ELObj::asGlyphSubstTable()
128 {
129   return 0;
130 }
131 
asLanguage()132 LanguageObj *ELObj::asLanguage()
133 {
134   return 0;
135 }
136 
optSingletonNodeList(EvalContext &,Interpreter &,NodePtr &)137 bool ELObj::optSingletonNodeList(EvalContext &, Interpreter &, NodePtr &)
138 {
139   return 0;
140 }
141 
asNodeList()142 NodeListObj *ELObj::asNodeList()
143 {
144   return 0;
145 }
146 
asNamedNodeList()147 NamedNodeListObj *ELObj::asNamedNodeList()
148 {
149   return 0;
150 }
151 
asStyle()152 StyleObj *ELObj::asStyle()
153 {
154   return 0;
155 }
156 
asBox()157 BoxObj *ELObj::asBox()
158 {
159   return 0;
160 }
161 
print(Interpreter & interp,OutputCharStream & out)162 void ELObj::print(Interpreter &interp, OutputCharStream &out)
163 {
164   out << "#<unknown object " << (unsigned long)this << ">";
165 }
166 
print(Interpreter & interp,OutputCharStream & out,unsigned)167 void ELObj::print(Interpreter &interp, OutputCharStream &out, unsigned)
168 {
169   print(interp, out);
170 }
171 
exactIntegerValue(long &)172 bool ELObj::exactIntegerValue(long &)
173 {
174   return false;
175 }
176 
realValue(double &)177 bool ELObj::realValue(double &)
178 {
179   return false;
180 }
181 
inexactRealValue(double &)182 bool ELObj::inexactRealValue(double &)
183 {
184   return false;
185 }
186 
lengthValue(long & n)187 bool ELObj::lengthValue(long &n)
188 {
189   return false;
190 }
191 
quantityValue(long &,double &,int &)192 ELObj::QuantityType ELObj::quantityValue(long &, double &, int &)
193 {
194   return noQuantity;
195 }
196 
lengthSpec() const197 const LengthSpec *ELObj::lengthSpec() const
198 {
199   return 0;
200 }
201 
stringData(const Char * &,size_t &)202 bool ELObj::stringData(const Char *&, size_t &)
203 {
204   return false;
205 }
206 
charValue(Char &)207 bool ELObj::charValue(Char &)
208 {
209   return false;
210 }
211 
glyphId() const212 const FOTBuilder::GlyphId *ELObj::glyphId() const
213 {
214   return 0;
215 }
216 
resolveQuantities(bool,Interpreter &,const Location &)217 ELObj *ELObj::resolveQuantities(bool, Interpreter &, const Location &)
218 {
219   return this;
220 }
221 
ErrorObj()222 ErrorObj::ErrorObj()
223 {
224 }
225 
print(Interpreter & interp,OutputCharStream & out)226 void ErrorObj::print(Interpreter &interp, OutputCharStream &out)
227 {
228   out << "#<error>";
229 }
230 
UnspecifiedObj()231 UnspecifiedObj::UnspecifiedObj()
232 {
233 }
234 
print(Interpreter & interp,OutputCharStream & out)235 void UnspecifiedObj::print(Interpreter &interp, OutputCharStream &out)
236 {
237   out << "#v";
238 }
239 
NilObj()240 NilObj::NilObj()
241 {
242 }
243 
isNil() const244 bool NilObj::isNil() const
245 {
246   return true;
247 }
248 
isList() const249 bool NilObj::isList() const
250 {
251   return true;
252 }
253 
print(Interpreter &,OutputCharStream & out)254 void NilObj::print(Interpreter &, OutputCharStream &out)
255 {
256   out << "()";
257 }
258 
TrueObj()259 TrueObj::TrueObj()
260 {
261 }
262 
print(Interpreter &,OutputCharStream & out)263 void TrueObj::print(Interpreter &, OutputCharStream &out)
264 {
265   out << "#t";
266 }
267 
FalseObj()268 FalseObj::FalseObj()
269 {
270 }
271 
isTrue() const272 bool FalseObj::isTrue() const
273 {
274   return false;
275 }
276 
print(Interpreter &,OutputCharStream & out)277 void FalseObj::print(Interpreter &, OutputCharStream &out)
278 {
279   out << "#f";
280 }
281 
SymbolObj(StringObj * name)282 SymbolObj::SymbolObj(StringObj *name)
283 : name_(name), cValue_(FOTBuilder::symbolFalse)
284 {
285   hasSubObjects_ = 1;
286 }
287 
traceSubObjects(Collector & c) const288 void SymbolObj::traceSubObjects(Collector &c) const
289 {
290   c.trace(name_);
291 }
292 
print(Interpreter & interp,OutputCharStream & out)293 void SymbolObj::print(Interpreter &interp, OutputCharStream &out)
294 {
295   out.write(name()->data(), name()->size());
296 }
297 
asSymbol()298 SymbolObj *SymbolObj::asSymbol()
299 {
300   return this;
301 }
302 
convertToString()303 StringObj *SymbolObj::convertToString()
304 {
305   return name();
306 }
307 
KeywordObj(const Identifier * ident)308 KeywordObj::KeywordObj(const Identifier *ident)
309 : ident_(ident)
310 {
311 }
312 
asKeyword()313 KeywordObj *KeywordObj::asKeyword()
314 {
315   return this;
316 }
317 
isEqual(ELObj & obj)318 bool KeywordObj::isEqual(ELObj &obj)
319 {
320   KeywordObj *k = obj.asKeyword();
321   return k && k->ident_ == ident_;
322 }
323 
print(Interpreter & interp,OutputCharStream & out)324 void KeywordObj::print(Interpreter &interp, OutputCharStream &out)
325 {
326   out << ident_->name() << ":";
327 }
328 
PairObj(ELObj * car,ELObj * cdr)329 PairObj::PairObj(ELObj *car, ELObj *cdr)
330 : car_(car), cdr_(cdr)
331 {
332   hasSubObjects_ = 1;
333 }
334 
isEqual(ELObj & obj)335 bool PairObj::isEqual(ELObj &obj)
336 {
337   PairObj *p = obj.asPair();
338   // FIXME need non-recursive implementation
339   return p && equal(*p->car(), *car()) && equal(*p->cdr(), *cdr());
340 }
341 
isEquiv(ELObj & obj)342 bool PairObj::isEquiv(ELObj &obj)
343 {
344   PairObj *p = obj.asPair();
345   // FIXME need non-recursive implementation
346   return p && eqv(*p->car(), *car()) && eqv(*p->cdr(), *cdr());
347 }
348 
traceSubObjects(Collector & c) const349 void PairObj::traceSubObjects(Collector &c) const
350 {
351   c.trace(car_);
352   c.trace(cdr_);
353 }
354 
resolveQuantities(bool force,Interpreter & interp,const Location & loc)355 ELObj *PairObj::resolveQuantities(bool force, Interpreter &interp,
356 				  const Location &loc)
357 {
358   bool fail = 0;
359   PairObj *pair = this;
360   for (;;) {
361     ELObj *tem = pair->car_->resolveQuantities(force, interp, loc);
362     if (!tem)
363       fail = 1;
364     else {
365       if (pair->permanent())
366 	interp.makePermanent(tem);
367       pair->car_ = tem;
368     }
369     PairObj *nextPair = pair->cdr_->asPair();
370     if (!nextPair)
371       break;
372     pair = nextPair;
373   }
374   ELObj *tem = pair->cdr_->resolveQuantities(force, interp, loc);
375   if (!tem)
376     fail = 1;
377   else {
378     if (pair->permanent())
379       interp.makePermanent(tem);
380     pair->cdr_ = tem;
381   }
382   if (fail)
383     return 0;
384   else
385     return this;
386 }
387 
388 
asPair()389 PairObj *PairObj::asPair()
390 {
391   return this;
392 }
393 
isList() const394 bool PairObj::isList() const
395 {
396   ELObj *p = cdr_;
397   while (!p->isNil()) {
398     PairObj *pair = p->asPair();
399     if (!pair)
400       return false;
401     p = pair->cdr();
402   }
403   return true;
404 }
405 
print(Interpreter & interp,OutputCharStream & out)406 void PairObj::print(Interpreter &interp, OutputCharStream &out)
407 {
408   out << "(";
409   car_->print(interp, out);
410   ELObj *p = cdr_;
411   for (;;) {
412     if (p->isNil()) {
413       out << ")";
414       return;
415     }
416     PairObj *pair = p->asPair();
417     if (!pair) {
418       out << " . ";
419       p->print(interp, out);
420       out << ")";
421       return;
422     }
423     out << " ";
424     pair->car()->print(interp, out);
425     p = pair->cdr();
426   }
427 }
428 
VectorObj()429 VectorObj::VectorObj()
430 {
431   hasSubObjects_ = 1;
432 }
433 
VectorObj(Vector<ELObj * > & v)434 VectorObj::VectorObj(Vector<ELObj *> &v)
435 {
436   hasSubObjects_ = 1;
437   v.swap(*this);
438 }
439 
traceSubObjects(Collector & c) const440 void VectorObj::traceSubObjects(Collector &c) const
441 {
442   for (size_t i = 0; i < Vector<ELObj *>::size(); i++)
443     c.trace((*this)[i]);
444 }
445 
asVector()446 VectorObj *VectorObj::asVector()
447 {
448   return this;
449 }
450 
isEquiv(ELObj &)451 bool VectorObj::isEquiv(ELObj &)
452 {
453   return 0;
454 }
455 
isEqual(ELObj & obj)456 bool VectorObj::isEqual(ELObj &obj)
457 {
458   VectorObj *v = obj.asVector();
459   if (!v)
460     return 0;
461   if (size() != v->size())
462     return 0;
463   for (size_t i = 0; i < size(); i++)
464     if (!equal(*(*this)[i], *(*v)[i]))
465       return 0;
466   return 1;
467 }
468 
print(Interpreter & interp,OutputCharStream & out)469 void VectorObj::print(Interpreter &interp, OutputCharStream &out)
470 {
471   out << "#(";
472   Vector<ELObj *> &v = *this;
473   for (size_t i = 0; i < v.size(); i++) {
474     if (i)
475       out << " ";
476     ELObj *tem = v[i];
477     if (!tem)
478       out << "#<cycle>";
479     else {
480       v[i] = 0;
481       tem->print(interp, out);
482       v[i] = tem;
483     }
484   }
485   out << ")";
486 }
487 
resolveQuantities(bool force,Interpreter & interp,const Location & loc)488 ELObj *VectorObj::resolveQuantities(bool force, Interpreter &interp,
489 				    const Location &loc)
490 {
491   bool fail = 0;
492   Vector<ELObj *> &v = *this;
493   for (size_t i = 0; i < v.size(); i++) {
494     ELObj *tem = v[i]->resolveQuantities(force, interp, loc);
495     if (tem) {
496       if (permanent())
497 	interp.makePermanent(tem);
498       v[i] = tem;
499     }
500     else
501       fail = 1;
502   }
503   if (fail)
504     return 0;
505   return this;
506 }
507 
CharObj(Char ch)508 CharObj::CharObj(Char ch)
509 : ch_(ch)
510 {
511 }
512 
display(Interpreter & interp,OutputCharStream & out) const513 void CharObj::display(Interpreter &interp, OutputCharStream &out) const
514 {
515   out.put(ch_);		// FIXME
516 }
517 
print(Interpreter &,OutputCharStream & out)518 void CharObj::print(Interpreter &, OutputCharStream &out)
519 {
520   out << "#\\";
521   out.put(ch_);	// FIXME
522 }
523 
charValue(Char & c)524 bool CharObj::charValue(Char &c)
525 {
526   c = ch_;
527   return 1;
528 }
529 
isEqual(ELObj & obj)530 bool CharObj::isEqual(ELObj &obj)
531 {
532   Char c;
533   return obj.charValue(c) && c == ch_;
534 }
535 
StringObj()536 StringObj::StringObj()
537 {
538 }
539 
StringObj(const StringC & str)540 StringObj::StringObj(const StringC &str)
541 : StringC(str)
542 {
543 }
544 
StringObj(const Char * s,size_t len)545 StringObj::StringObj(const Char *s, size_t len)
546 : StringC(s, len)
547 {
548 }
549 
stringData(const Char * & s,size_t & n)550 bool StringObj::stringData(const Char *&s, size_t &n)
551 {
552   s = data();
553   n = size();
554   return true;
555 }
556 
isEqual(ELObj & obj)557 bool StringObj::isEqual(ELObj &obj)
558 {
559   const Char *s;
560   size_t n;
561   return (obj.stringData(s, n)
562 	  && n == size()
563 	  && (n == 0 || memcmp(s, data(), n*sizeof(Char)) == 0));
564 }
565 
convertToString()566 StringObj *StringObj::convertToString()
567 {
568   return this;
569 }
570 
print(Interpreter & interp,OutputCharStream & out)571 void StringObj::print(Interpreter &interp, OutputCharStream &out)
572 {
573   // FIXME
574   out << "\"";
575   const Char *s = data();
576   for (size_t i = 0; i < size(); i++)
577     switch (s[i]) {
578     case '\\':
579     case '"':
580       out << "\\";
581       // fall through
582     default:
583       out.put(s[i]);
584       break;
585     }
586   out << "\"";
587 }
588 
IntegerObj()589 IntegerObj::IntegerObj()
590 : n_(0)
591 {
592 }
593 
IntegerObj(long n)594 IntegerObj::IntegerObj(long n)
595 : n_(n)
596 {
597 }
598 
isEqual(ELObj & obj)599 bool IntegerObj::isEqual(ELObj &obj)
600 {
601   long n;
602   return obj.exactIntegerValue(n) && n == n_;
603 }
604 
print(Interpreter & interp,OutputCharStream & out)605 void IntegerObj::print(Interpreter &interp, OutputCharStream &out)
606 {
607   print(interp, out, 10);
608 }
609 
print(Interpreter &,OutputCharStream & out,unsigned radix)610 void IntegerObj::print(Interpreter &, OutputCharStream &out, unsigned radix)
611 {
612   if (radix == 10) {
613     if (n_ < 0)
614       out << '-' << (unsigned long)-n_;
615     else
616       out << (unsigned long)n_;
617     return;
618   }
619 
620   if (n_ == 0) {
621     out << '0';
622     return;
623   }
624 
625   unsigned long n;
626 
627   if (n_ < 0) {
628     out << '-';
629     n = -n_;
630   }
631   else
632     n = n_;
633 
634   char buf[64];
635   int i = 0;
636 
637   while (n != 0) {
638     buf[i++] = "0123456789abcdef"[n % radix];
639     n /= radix;
640   }
641 
642   while (i > 0)
643     out << buf[--i];
644 }
645 
exactIntegerValue(long & n)646 bool IntegerObj::exactIntegerValue(long &n)
647 {
648   n = n_;
649   return true;
650 }
651 
realValue(double & n)652 bool IntegerObj::realValue(double &n)
653 {
654   n = n_;
655   return true;
656 }
657 
quantityValue(long & val,double &,int & dim)658 ELObj::QuantityType IntegerObj::quantityValue(long &val, double &, int &dim)
659 {
660   val = n_;
661   dim = 0;
662   return longQuantity;
663 }
664 
RealObj(double n)665 RealObj::RealObj(double n)
666 : n_(n)
667 {
668 }
669 
isEqual(ELObj & obj)670 bool RealObj::isEqual(ELObj &obj)
671 {
672   double n;
673   return obj.inexactRealValue(n) && n == n_;
674 }
675 
676 
realValue(double & n)677 bool RealObj::realValue(double &n)
678 {
679   n = n_;
680   return true;
681 }
682 
inexactRealValue(double & n)683 bool RealObj::inexactRealValue(double &n)
684 {
685   n = n_;
686   return true;
687 }
688 
quantityValue(long &,double & val,int & dim)689 ELObj::QuantityType RealObj::quantityValue(long &, double &val, int &dim)
690 {
691   val = n_;
692   dim = 0;
693   return doubleQuantity;
694 }
695 
print(Interpreter &,OutputCharStream & out)696 void RealObj::print(Interpreter &, OutputCharStream &out)
697 {
698   char buf[1024];
699   sprintf(buf, "%g", n_);
700   out << buf;
701 }
702 
LengthObj(long n)703 LengthObj::LengthObj(long n)
704 : n_(n)
705 {
706 }
707 
lengthValue(long & n)708 bool LengthObj::lengthValue(long &n)
709 {
710   n = n_;
711   return true;
712 }
713 
quantityValue(long & val,double &,int & dim)714 ELObj::QuantityType LengthObj::quantityValue(long &val, double &, int &dim)
715 {
716   val = n_;
717   dim = 1;
718   return longQuantity;
719 }
720 
isEqual(ELObj & obj)721 bool LengthObj::isEqual(ELObj &obj)
722 {
723   long n;
724   double d;
725   int dim;
726   switch (obj.quantityValue(n, d, dim)) {
727   case noQuantity:
728     break;
729   case doubleQuantity:
730     return dim == 1 && d == n_;
731   case longQuantity:
732     return dim == 1 && n == n_;
733   }
734   return 0;
735 }
736 
print(Interpreter & interp,OutputCharStream & out)737 void LengthObj::print(Interpreter &interp, OutputCharStream &out)
738 {
739   char buf[1024];
740   sprintf(buf, "%gpt", n_ * 72.0/interp.unitsPerInch());
741   out << buf;
742 }
743 
QuantityObj(double val,int dim)744 QuantityObj::QuantityObj(double val, int dim)
745 : val_(val), dim_(dim)
746 {
747 }
748 
isEqual(ELObj & obj)749 bool QuantityObj::isEqual(ELObj &obj)
750 {
751   long n;
752   double d;
753   int dim;
754   switch (obj.quantityValue(n, d, dim)) {
755   case noQuantity:
756     break;
757   case doubleQuantity:
758     return dim == dim_ && d == val_;
759   case longQuantity:
760     return dim == dim_ && n == val_;
761   }
762   return 0;
763 }
764 
quantityValue(long &,double & val,int & dim)765 ELObj::QuantityType QuantityObj::quantityValue(long &, double &val, int &dim)
766 {
767   val = val_;
768   dim = dim_;
769   return doubleQuantity;
770 }
771 
print(Interpreter & interp,OutputCharStream & out)772 void QuantityObj::print(Interpreter &interp, OutputCharStream &out)
773 {
774   char buf[1024];
775   sprintf(buf, "%gpt%d", val_ * pow(72.0/interp.unitsPerInch(), double(dim_)),
776 	  dim_);
777   out << buf;
778 }
779 
realValue(double & d)780 bool QuantityObj::realValue(double &d)
781 {
782   if (dim_ != 0)
783     return 0;
784   d = val_;
785   return 1;
786 }
787 
inexactRealValue(double & d)788 bool QuantityObj::inexactRealValue(double &d)
789 {
790   if (dim_ != 0)
791     return 0;
792   d = val_;
793   return 1;
794 }
795 
LengthSpecObj(const LengthSpec & spec)796 LengthSpecObj::LengthSpecObj(const LengthSpec &spec)
797 : lengthSpec_(new LengthSpec(spec))
798 {
799 }
800 
lengthSpec() const801 const LengthSpec *LengthSpecObj::lengthSpec() const
802 {
803   return lengthSpec_.pointer();
804 }
805 
LengthSpec()806 LengthSpec::LengthSpec()
807 {
808   for (int i = 0; i < nVals; i++)
809     val_[i] = 0.0;
810 }
811 
LengthSpec(double d)812 LengthSpec::LengthSpec(double d)
813 {
814   val_[0] = d;
815   for (int i = 1; i < nVals; i++)
816     val_[i] = 0.0;
817 }
818 
LengthSpec(Unknown unknown,double d)819 LengthSpec::LengthSpec(Unknown unknown, double d)
820 {
821   int i;
822   for (i = 0; i < unknown; i++)
823     val_[i] = 0.0;
824   val_[unknown] = d;
825   for (i = unknown + 1; i < nVals; i++)
826     val_[i] = 0.0;
827 }
828 
operator +=(const LengthSpec & ls)829 void LengthSpec::operator+=(const LengthSpec &ls)
830 {
831   for (int i = 0; i < nVals; i++)
832     val_[i] += ls.val_[i];
833 }
834 
operator -=(const LengthSpec & ls)835 void LengthSpec::operator-=(const LengthSpec &ls)
836 {
837   for (int i = 0; i < nVals; i++)
838     val_[i] -= ls.val_[i];
839 }
840 
operator *=(double d)841 void LengthSpec::operator*=(double d)
842 {
843   for (int i = 0; i < nVals; i++)
844     val_[i] *= d;
845 }
846 
operator /=(double d)847 void LengthSpec::operator/=(double d)
848 {
849   for (int i = 0; i < nVals; i++)
850     val_[i] /= d;
851 }
852 
convert(FOTBuilder::LengthSpec & result) const853 bool LengthSpec::convert(FOTBuilder::LengthSpec &result) const
854 {
855   // FIXME do some checking
856   result.length = long(val_[0] < 0.0 ? val_[0] - 0.5 : val_[0] + .5);
857   result.displaySizeFactor = val_[1];
858   return 1;
859 }
860 
convert(FOTBuilder::TableLengthSpec & result) const861 bool LengthSpec::convert(FOTBuilder::TableLengthSpec &result) const
862 {
863   // FIXME do some checking
864   result.length = long(val_[0] < 0.0 ? val_[0] - 0.5 : val_[0] + .5);
865   result.displaySizeFactor = val_[1];
866   result.tableUnitFactor = val_[2];
867   return 1;
868 }
869 
DisplaySpaceObj(const FOTBuilder::DisplaySpace & displaySpace)870 DisplaySpaceObj::DisplaySpaceObj(const FOTBuilder::DisplaySpace &displaySpace)
871 : displaySpace_(new FOTBuilder::DisplaySpace(displaySpace))
872 {
873 }
874 
displaySpace() const875 const FOTBuilder::DisplaySpace &DisplaySpaceObj::displaySpace() const
876 {
877   return *displaySpace_;
878 }
879 
asDisplaySpace()880 DisplaySpaceObj *DisplaySpaceObj::asDisplaySpace()
881 {
882   return this;
883 }
884 
InlineSpaceObj(const FOTBuilder::InlineSpace & inlineSpace)885 InlineSpaceObj::InlineSpaceObj(const FOTBuilder::InlineSpace &inlineSpace)
886 : inlineSpace_(new FOTBuilder::InlineSpace(inlineSpace))
887 {
888 }
889 
inlineSpace() const890 const FOTBuilder::InlineSpace &InlineSpaceObj::inlineSpace() const
891 {
892   return *inlineSpace_;
893 }
894 
asInlineSpace()895 InlineSpaceObj *InlineSpaceObj::asInlineSpace()
896 {
897   return this;
898 }
899 
UnresolvedLengthObj(long val,int valExp,Unit * unit)900 UnresolvedLengthObj::UnresolvedLengthObj(long val, int valExp, Unit *unit)
901 : val_(val), valExp_(valExp), unit_(unit)
902 {
903 }
904 
resolveQuantities(bool force,Interpreter & interp,const Location & loc)905 ELObj *UnresolvedLengthObj::resolveQuantities(bool force,
906 					      Interpreter &interp,
907 					      const Location &loc)
908 {
909   unsigned part;
910   Location defLoc;
911   if (!unit_->defined(part, defLoc)) {
912     interp.setNextLocation(loc);
913     interp.message(InterpreterMessages::undefinedQuantity,
914 		   StringMessageArg(unit_->name()));
915     return interp.makeError();
916   }
917   return unit_->resolveQuantity(force, interp, val_, valExp_);
918 }
919 
920 UnresolvedQuantityObj
UnresolvedQuantityObj(double val,Unit * unit,int unitExp)921 ::UnresolvedQuantityObj(double val, Unit *unit, int unitExp)
922 : val_(val), unit_(unit), unitExp_(unitExp)
923 {
924 }
925 
resolveQuantities(bool force,Interpreter & interp,const Location & loc)926 ELObj *UnresolvedQuantityObj::resolveQuantities(bool force,
927 						Interpreter &interp,
928 						const Location &loc)
929 {
930   unsigned part;
931   Location defLoc;
932   if (!unit_->defined(part, defLoc)) {
933     interp.setNextLocation(loc);
934     interp.message(InterpreterMessages::undefinedQuantity,
935 		   StringMessageArg(unit_->name()));
936     return interp.makeError();
937   }
938   return unit_->resolveQuantity(force, interp, val_, unitExp_);
939 }
940 
GlyphIdObj(const FOTBuilder::GlyphId & glyphId)941 GlyphIdObj::GlyphIdObj(const FOTBuilder::GlyphId &glyphId)
942 : glyphId_(glyphId)
943 {
944 }
945 
glyphId() const946 const FOTBuilder::GlyphId *GlyphIdObj::glyphId() const
947 {
948   return &glyphId_;
949 }
950 
isEqual(ELObj & obj)951 bool GlyphIdObj::isEqual(ELObj &obj)
952 {
953   const FOTBuilder::GlyphId *p = obj.glyphId();
954   return (p
955           && p->publicId == glyphId_.publicId
956 	  && p->suffix == glyphId_.suffix);
957 }
958 
GlyphSubstTableObj(const ConstPtr<FOTBuilder::GlyphSubstTable> & table)959 GlyphSubstTableObj::GlyphSubstTableObj(const ConstPtr<FOTBuilder::GlyphSubstTable> &table)
960 : table_(table)
961 {
962 }
963 
asGlyphSubstTable()964 GlyphSubstTableObj *GlyphSubstTableObj::asGlyphSubstTable()
965 {
966   return this;
967 }
968 
AddressObj(FOTBuilder::Address::Type type,const NodePtr & node,const StringC & str1,const StringC & str2,const StringC & str3)969 AddressObj::AddressObj(FOTBuilder::Address::Type type,
970 		       const NodePtr &node,
971 		       const StringC &str1,
972 		       const StringC &str2,
973 		       const StringC &str3)
974 {
975   address_ = new FOTBuilder::Address;
976   address_->type = type;
977   address_->node = node;
978   address_->params[0] = str1;
979   address_->params[1] = str2;
980   address_->params[2] = str3;
981 }
982 
asAddress()983 AddressObj *AddressObj::asAddress()
984 {
985   return this;
986 }
987 
asNodeList()988 NodeListObj *NodeListObj::asNodeList()
989 {
990   return this;
991 }
992 
nodeListNoOrder(Collector &)993 NodeListObj *NodeListObj::nodeListNoOrder(Collector &)
994 {
995   return this;
996 }
997 
nodeListChunkRest(EvalContext & context,Interpreter & interp,bool & chunk)998 NodeListObj *NodeListObj::nodeListChunkRest(EvalContext &context, Interpreter &interp, bool &chunk)
999 {
1000   chunk = 0;
1001   return nodeListRest(context, interp);
1002 }
1003 
optSingletonNodeList(EvalContext & context,Interpreter & interp,NodePtr & node)1004 bool NodeListObj::optSingletonNodeList(EvalContext &context, Interpreter &interp, NodePtr &node)
1005 {
1006   NodeListObj *rest = nodeListRest(context, interp);
1007   ELObjDynamicRoot protect(interp, rest);
1008   if (rest->nodeListFirst(context, interp))
1009     return 0;
1010   node = nodeListFirst(context, interp);
1011   return 1;
1012 }
1013 
nodeListRef(long n,EvalContext & context,Interpreter & interp)1014 NodePtr NodeListObj::nodeListRef(long n, EvalContext &context, Interpreter &interp)
1015 {
1016   if (n < 0)
1017     return NodePtr();
1018   NodeListObj *nl = this;
1019   ELObjDynamicRoot protect(interp, nl);
1020   while (n > 0) {
1021     NodePtr nd(nl->nodeListFirst(context, interp));
1022     if (!nd)
1023       return NodePtr();
1024     GroveString str;
1025     if (nd->charChunk(interp, str) == accessOK && str.size() <= n) {
1026       bool chunk;
1027       nl = nl->nodeListChunkRest(context, interp, chunk);
1028       if (chunk)
1029 	n -= str.size();
1030       else
1031 	n--;
1032     }
1033     else {
1034       nl = nl->nodeListRest(context, interp);
1035       n--;
1036     }
1037     protect = nl;
1038   }
1039   return nl->nodeListFirst(context, interp);
1040 }
1041 
nodeListReverse(EvalContext &,Interpreter & interp)1042 NodeListObj *NodeListObj::nodeListReverse(EvalContext &, Interpreter &interp)
1043 {
1044   return new (interp) ReverseNodeListObj(this);
1045 }
1046 
nodeListLength(EvalContext & context,Interpreter & interp)1047 long NodeListObj::nodeListLength(EvalContext &context, Interpreter &interp)
1048 {
1049   NodeListObj *nl = this;
1050   long n = 0;
1051   ELObjDynamicRoot protect(interp, nl);
1052   for (;;) {
1053     NodePtr nd(nl->nodeListFirst(context, interp));
1054     if (!nd)
1055       break;
1056     bool chunk;
1057     nl = nl->nodeListChunkRest(context, interp, chunk);
1058     protect = nl;
1059     GroveString str;
1060     if (chunk && nd->charChunk(interp, str) == accessOK)
1061       n += str.size();
1062     else
1063       n += 1;
1064   }
1065   return n;
1066 }
1067 
suppressError()1068 bool NodeListObj::suppressError()
1069 {
1070   return 0;
1071 }
1072 
asNamedNodeList()1073 NamedNodeListObj *NamedNodeListObj::asNamedNodeList()
1074 {
1075   return this;
1076 }
1077 
NodePtrNodeListObj()1078 NodePtrNodeListObj::NodePtrNodeListObj()
1079 {
1080 }
1081 
NodePtrNodeListObj(const NodePtr & node)1082 NodePtrNodeListObj::NodePtrNodeListObj(const NodePtr &node)
1083 : node_(node)
1084 {
1085 }
1086 
optSingletonNodeList(EvalContext &,Interpreter &,NodePtr & node)1087 bool NodePtrNodeListObj::optSingletonNodeList(EvalContext &, Interpreter &, NodePtr &node)
1088 {
1089   node = node_;
1090   return 1;
1091 }
1092 
nodeListFirst(EvalContext &,Interpreter &)1093 NodePtr NodePtrNodeListObj::nodeListFirst(EvalContext &, Interpreter &)
1094 {
1095   return node_;
1096 }
1097 
nodeListRest(EvalContext & context,Interpreter & interp)1098 NodeListObj *NodePtrNodeListObj::nodeListRest(EvalContext &context, Interpreter &interp)
1099 {
1100   if (node_)
1101     return new (interp) NodePtrNodeListObj;
1102   else
1103     return this;
1104 }
1105 
NodeListPtrNodeListObj(const NodeListPtr & nodeList)1106 NodeListPtrNodeListObj::NodeListPtrNodeListObj(const NodeListPtr &nodeList)
1107 : nodeList_(nodeList)
1108 {
1109 }
1110 
nodeListFirst(EvalContext &,Interpreter &)1111 NodePtr NodeListPtrNodeListObj::nodeListFirst(EvalContext &, Interpreter &)
1112 {
1113   NodePtr nd;
1114   if (nodeList_->first(nd) == accessOK)
1115     return nd;
1116   else
1117     return NodePtr();
1118 }
1119 
nodeListRest(EvalContext & context,Interpreter & interp)1120 NodeListObj *NodeListPtrNodeListObj::nodeListRest(EvalContext &context, Interpreter &interp)
1121 {
1122   NodeListPtr nl;
1123   if (nodeList_->rest(nl) == accessOK)
1124     return new (interp) NodeListPtrNodeListObj(nl);
1125   else
1126     return interp.makeEmptyNodeList();
1127 }
1128 
nodeListChunkRest(EvalContext & context,Interpreter & interp,bool & chunk)1129 NodeListObj *NodeListPtrNodeListObj::nodeListChunkRest(EvalContext &context, Interpreter &interp, bool &chunk)
1130 {
1131   NodeListPtr nl;
1132   if (nodeList_->chunkRest(nl) == accessOK) {
1133     chunk = 1;
1134     return new (interp) NodeListPtrNodeListObj(nl);
1135   }
1136   else {
1137     chunk = 0;
1138     return interp.makeEmptyNodeList();
1139   }
1140 }
1141 
nodeListRef(long i,EvalContext &,Interpreter & interp)1142 NodePtr NodeListPtrNodeListObj::nodeListRef(long i, EvalContext &, Interpreter &interp)
1143 {
1144   NodePtr nd;
1145   if (i < 0 || nodeList_->ref(i, nd) != accessOK)
1146     return NodePtr();
1147   return nd;
1148 }
1149 
1150 NamedNodeListPtrNodeListObj
NamedNodeListPtrNodeListObj(const NamedNodeListPtr & nnl)1151 ::NamedNodeListPtrNodeListObj(const NamedNodeListPtr &nnl)
1152 : namedNodeList_(nnl)
1153 {
1154 }
1155 
namedNode(const Char * s,size_t n)1156 NodePtr NamedNodeListPtrNodeListObj::namedNode(const Char *s, size_t n)
1157 {
1158   NodePtr node;
1159   if (namedNodeList_->namedNode(GroveString(s, n), node) != accessOK)
1160     node.clear();
1161   return node;
1162 }
1163 
nodeName(const NodePtr & nd,GroveString & str)1164 bool NamedNodeListPtrNodeListObj::nodeName(const NodePtr &nd, GroveString &str)
1165 {
1166   return namedNodeList_->nodeName(nd, str) == accessOK;
1167 }
1168 
normalize(Char * s,size_t n)1169 size_t NamedNodeListPtrNodeListObj::normalize(Char *s, size_t n)
1170 {
1171   return namedNodeList_->normalize(s, n);
1172 }
1173 
nodeListFirst(EvalContext &,Interpreter &)1174 NodePtr NamedNodeListPtrNodeListObj::nodeListFirst(EvalContext &, Interpreter &)
1175 {
1176   if (!nodeList_)
1177     nodeList_ = namedNodeList_->nodeList();
1178   NodePtr nd;
1179   if (nodeList_->first(nd) == accessOK)
1180     return nd;
1181   else
1182     return NodePtr();
1183 }
1184 
nodeListRest(EvalContext & context,Interpreter & interp)1185 NodeListObj *NamedNodeListPtrNodeListObj::nodeListRest(EvalContext &context, Interpreter &interp)
1186 {
1187   if (!nodeList_)
1188     nodeList_ = namedNodeList_->nodeList();
1189   NodeListPtr nl;
1190   if (nodeList_->rest(nl) == accessOK)
1191     return new (interp) NodeListPtrNodeListObj(nl);
1192   else
1193     return new (interp) NodePtrNodeListObj;
1194 }
1195 
nodeListNoOrder(Collector & c)1196 NodeListObj *NamedNodeListPtrNodeListObj::nodeListNoOrder(Collector &c)
1197 {
1198   return new (c) NodeListPtrNodeListObj(namedNodeList_->nodeListNoOrder());
1199 }
1200 
PairNodeListObj(NodeListObj * head,NodeListObj * tail)1201 PairNodeListObj::PairNodeListObj(NodeListObj *head, NodeListObj *tail)
1202 : head_(head), tail_(tail)
1203 {
1204   hasSubObjects_ = 1;
1205 }
1206 
nodeListFirst(EvalContext & context,Interpreter & interp)1207 NodePtr PairNodeListObj::nodeListFirst(EvalContext &context, Interpreter &interp)
1208 {
1209   if (head_) {
1210     NodePtr nd(head_->nodeListFirst(context, interp));
1211     if (nd)
1212       return nd;
1213     head_ = 0;
1214   }
1215   return tail_->nodeListFirst(context, interp);
1216 }
1217 
nodeListRest(EvalContext & context,Interpreter & interp)1218 NodeListObj *PairNodeListObj::nodeListRest(EvalContext &context, Interpreter &interp)
1219 {
1220   if (!head_ || !head_->nodeListFirst(context, interp))
1221     return tail_->nodeListRest(context, interp);
1222   NodeListObj *tem = head_->nodeListRest(context, interp);
1223   ELObjDynamicRoot protect(interp, tem);
1224   return new (interp) PairNodeListObj(tem, tail_);
1225 }
1226 
nodeListChunkRest(EvalContext & context,Interpreter & interp,bool & chunk)1227 NodeListObj *PairNodeListObj::nodeListChunkRest(EvalContext &context, Interpreter &interp, bool &chunk)
1228 {
1229   if (!head_ || !head_->nodeListFirst(context, interp))
1230     return tail_->nodeListChunkRest(context, interp, chunk);
1231   NodeListObj *tem = head_->nodeListChunkRest(context, interp, chunk);
1232   ELObjDynamicRoot protect(interp, tem);
1233   return new (interp) PairNodeListObj(tem, tail_);
1234 }
1235 
traceSubObjects(Collector & c) const1236 void PairNodeListObj::traceSubObjects(Collector &c) const
1237 {
1238   c.trace(head_);
1239   c.trace(tail_);
1240 }
1241 
ReverseNodeListObj(NodeListObj * nl)1242 ReverseNodeListObj::ReverseNodeListObj(NodeListObj *nl)
1243 : nl_(nl), reversed_(0)
1244 {
1245   hasSubObjects_ = 1;
1246 }
1247 
nodeListFirst(EvalContext & context,Interpreter & interp)1248 NodePtr ReverseNodeListObj::nodeListFirst(EvalContext &context, Interpreter &interp)
1249 {
1250   return reversed(context, interp)->nodeListFirst(context, interp);
1251 }
1252 
nodeListRest(EvalContext & context,Interpreter & interp)1253 NodeListObj *ReverseNodeListObj::nodeListRest(EvalContext &context, Interpreter &interp)
1254 {
1255   return reversed(context, interp)->nodeListRest(context, interp);
1256 }
1257 
nodeListRef(long n,EvalContext & context,Interpreter & interp)1258 NodePtr ReverseNodeListObj::nodeListRef(long n, EvalContext &context, Interpreter &interp)
1259 {
1260   if (reversed_)
1261     return reversed_->nodeListRef(n, context, interp);
1262   if (n < 0)
1263     return NodePtr();
1264   size_t len = nl_->nodeListLength(context, interp);
1265   if (n >= len)
1266     return 0;
1267   return nl_->nodeListRef(len - n - 1, context, interp);
1268 }
1269 
reversed(EvalContext & context,Interpreter & interp)1270 NodeListObj *ReverseNodeListObj::reversed(EvalContext &context, Interpreter &interp)
1271 {
1272   if (!reversed_) {
1273     NodePtr nd(nl_->nodeListFirst(context, interp));
1274     if (nd) {
1275       reversed_ = new (interp) NodePtrNodeListObj(nd);
1276       NodeListObj *tem = nl_;
1277       ELObjDynamicRoot protect(interp, tem);
1278       ELObjDynamicRoot protect2(interp, reversed_);
1279       for (;;) {
1280 	tem = tem->nodeListRest(context, interp);
1281 	protect = tem;
1282 	nd = tem->nodeListFirst(context, interp);
1283 	if (!nd)
1284 	  break;
1285 	NodeListObj *single = new (interp) NodePtrNodeListObj(nd);
1286 	protect2 = single;
1287 	reversed_ = new (interp) PairNodeListObj(single, reversed_);
1288       }
1289     }
1290     else
1291       reversed_ = nl_;
1292   }
1293   return reversed_;
1294 }
1295 
nodeListReverse(EvalContext &,Interpreter &)1296 NodeListObj *ReverseNodeListObj::nodeListReverse(EvalContext &, Interpreter &)
1297 {
1298   return nl_;
1299 }
1300 
nodeListLength(EvalContext & context,Interpreter & interp)1301 long ReverseNodeListObj::nodeListLength(EvalContext &context, Interpreter &interp)
1302 {
1303   return nl_->nodeListLength(context, interp);
1304 }
1305 
traceSubObjects(Collector & c) const1306 void ReverseNodeListObj::traceSubObjects(Collector &c) const
1307 {
1308   c.trace(nl_);
1309   c.trace(reversed_);
1310 }
1311 
1312 #ifdef DSSSL_NAMESPACE
1313 }
1314 #endif
1315