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