1 // Copyright (c) 1996 James Clark
2 // See the file copying.txt for copying permission.
6 #include "Interpreter.h"
7 #include "InterpreterMessages.h"
13 #ifdef DSSSL_NAMESPACE
14 namespace DSSSL_NAMESPACE {
17 class ReverseNodeListObj : public NodeListObj {
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;
27 NodeListObj *reversed(EvalContext &context, Interpreter &interp);
29 NodeListObj *reversed_;
37 bool ELObj::isEqual(ELObj &)
42 bool ELObj::isEquiv(ELObj &obj)
47 bool ELObj::isNil() const
52 bool ELObj::isList() const
57 bool ELObj::isTrue() const
62 PairObj *ELObj::asPair()
67 VectorObj *ELObj::asVector()
72 SymbolObj *ELObj::asSymbol()
77 KeywordObj *ELObj::asKeyword()
82 StringObj *ELObj::convertToString()
87 FunctionObj *ELObj::asFunction()
92 SosofoObj *ELObj::asSosofo()
97 AppendSosofoObj *ELObj::asAppendSosofo()
102 ColorObj *ELObj::asColor()
107 ColorSpaceObj *ELObj::asColorSpace()
112 AddressObj *ELObj::asAddress()
117 DisplaySpaceObj *ELObj::asDisplaySpace()
122 InlineSpaceObj *ELObj::asInlineSpace()
127 GlyphSubstTableObj *ELObj::asGlyphSubstTable()
132 LanguageObj *ELObj::asLanguage()
137 bool ELObj::optSingletonNodeList(EvalContext &, Interpreter &, NodePtr &)
142 NodeListObj *ELObj::asNodeList()
147 NamedNodeListObj *ELObj::asNamedNodeList()
152 StyleObj *ELObj::asStyle()
157 BoxObj *ELObj::asBox()
162 void ELObj::print(Interpreter &interp, OutputCharStream &out)
164 out << "#<unknown object " << (unsigned long)this << ">";
167 void ELObj::print(Interpreter &interp, OutputCharStream &out, unsigned)
172 bool ELObj::exactIntegerValue(long &)
177 bool ELObj::realValue(double &)
182 bool ELObj::inexactRealValue(double &)
187 bool ELObj::lengthValue(long &n)
192 ELObj::QuantityType ELObj::quantityValue(long &, double &, int &)
197 const LengthSpec *ELObj::lengthSpec() const
202 bool ELObj::stringData(const Char *&, size_t &)
207 bool ELObj::charValue(Char &)
212 const FOTBuilder::GlyphId *ELObj::glyphId() const
217 ELObj *ELObj::resolveQuantities(bool, Interpreter &, const Location &)
226 void ErrorObj::print(Interpreter &interp, OutputCharStream &out)
231 UnspecifiedObj::UnspecifiedObj()
235 void UnspecifiedObj::print(Interpreter &interp, OutputCharStream &out)
244 bool NilObj::isNil() const
249 bool NilObj::isList() const
254 void NilObj::print(Interpreter &, OutputCharStream &out)
263 void TrueObj::print(Interpreter &, OutputCharStream &out)
272 bool FalseObj::isTrue() const
277 void FalseObj::print(Interpreter &, OutputCharStream &out)
282 SymbolObj::SymbolObj(StringObj *name)
283 : name_(name), cValue_(FOTBuilder::symbolFalse)
288 void SymbolObj::traceSubObjects(Collector &c) const
293 void SymbolObj::print(Interpreter &interp, OutputCharStream &out)
295 out.write(name()->data(), name()->size());
298 SymbolObj *SymbolObj::asSymbol()
303 StringObj *SymbolObj::convertToString()
308 KeywordObj::KeywordObj(const Identifier *ident)
313 KeywordObj *KeywordObj::asKeyword()
318 bool KeywordObj::isEqual(ELObj &obj)
320 KeywordObj *k = obj.asKeyword();
321 return k && k->ident_ == ident_;
324 void KeywordObj::print(Interpreter &interp, OutputCharStream &out)
326 out << ident_->name() << ":";
329 PairObj::PairObj(ELObj *car, ELObj *cdr)
330 : car_(car), cdr_(cdr)
335 bool PairObj::isEqual(ELObj &obj)
337 PairObj *p = obj.asPair();
338 // FIXME need non-recursive implementation
339 return p && equal(*p->car(), *car()) && equal(*p->cdr(), *cdr());
342 bool PairObj::isEquiv(ELObj &obj)
344 PairObj *p = obj.asPair();
345 // FIXME need non-recursive implementation
346 return p && eqv(*p->car(), *car()) && eqv(*p->cdr(), *cdr());
349 void PairObj::traceSubObjects(Collector &c) const
355 ELObj *PairObj::resolveQuantities(bool force, Interpreter &interp,
359 PairObj *pair = this;
361 ELObj *tem = pair->car_->resolveQuantities(force, interp, loc);
365 if (pair->permanent())
366 interp.makePermanent(tem);
369 PairObj *nextPair = pair->cdr_->asPair();
374 ELObj *tem = pair->cdr_->resolveQuantities(force, interp, loc);
378 if (pair->permanent())
379 interp.makePermanent(tem);
389 PairObj *PairObj::asPair()
394 bool PairObj::isList() const
397 while (!p->isNil()) {
398 PairObj *pair = p->asPair();
406 void PairObj::print(Interpreter &interp, OutputCharStream &out)
409 car_->print(interp, out);
416 PairObj *pair = p->asPair();
419 p->print(interp, out);
424 pair->car()->print(interp, out);
429 VectorObj::VectorObj()
434 VectorObj::VectorObj(Vector<ELObj *> &v)
440 void VectorObj::traceSubObjects(Collector &c) const
442 for (size_t i = 0; i < Vector<ELObj *>::size(); i++)
446 VectorObj *VectorObj::asVector()
451 bool VectorObj::isEquiv(ELObj &)
456 bool VectorObj::isEqual(ELObj &obj)
458 VectorObj *v = obj.asVector();
461 if (size() != v->size())
463 for (size_t i = 0; i < size(); i++)
464 if (!equal(*(*this)[i], *(*v)[i]))
469 void VectorObj::print(Interpreter &interp, OutputCharStream &out)
472 Vector<ELObj *> &v = *this;
473 for (size_t i = 0; i < v.size(); i++) {
481 tem->print(interp, out);
488 ELObj *VectorObj::resolveQuantities(bool force, Interpreter &interp,
492 Vector<ELObj *> &v = *this;
493 for (size_t i = 0; i < v.size(); i++) {
494 ELObj *tem = v[i]->resolveQuantities(force, interp, loc);
497 interp.makePermanent(tem);
508 CharObj::CharObj(Char ch)
513 void CharObj::display(Interpreter &interp, OutputCharStream &out) const
515 out.put(ch_); // FIXME
518 void CharObj::print(Interpreter &, OutputCharStream &out)
521 out.put(ch_); // FIXME
524 bool CharObj::charValue(Char &c)
530 bool CharObj::isEqual(ELObj &obj)
533 return obj.charValue(c) && c == ch_;
536 StringObj::StringObj()
540 StringObj::StringObj(const StringC &str)
545 StringObj::StringObj(const Char *s, size_t len)
550 bool StringObj::stringData(const Char *&s, size_t &n)
557 bool StringObj::isEqual(ELObj &obj)
561 return (obj.stringData(s, n)
563 && (n == 0 || memcmp(s, data(), n*sizeof(Char)) == 0));
566 StringObj *StringObj::convertToString()
571 void StringObj::print(Interpreter &interp, OutputCharStream &out)
575 const Char *s = data();
576 for (size_t i = 0; i < size(); i++)
589 IntegerObj::IntegerObj()
594 IntegerObj::IntegerObj(long n)
599 bool IntegerObj::isEqual(ELObj &obj)
602 return obj.exactIntegerValue(n) && n == n_;
605 void IntegerObj::print(Interpreter &interp, OutputCharStream &out)
607 print(interp, out, 10);
610 void IntegerObj::print(Interpreter &, OutputCharStream &out, unsigned radix)
614 out << '-' << (unsigned long)-n_;
616 out << (unsigned long)n_;
638 buf[i++] = "0123456789abcdef"[n % radix];
646 bool IntegerObj::exactIntegerValue(long &n)
652 bool IntegerObj::realValue(double &n)
658 ELObj::QuantityType IntegerObj::quantityValue(long &val, double &, int &dim)
665 RealObj::RealObj(double n)
670 bool RealObj::isEqual(ELObj &obj)
673 return obj.inexactRealValue(n) && n == n_;
677 bool RealObj::realValue(double &n)
683 bool RealObj::inexactRealValue(double &n)
689 ELObj::QuantityType RealObj::quantityValue(long &, double &val, int &dim)
693 return doubleQuantity;
696 void RealObj::print(Interpreter &, OutputCharStream &out)
699 sprintf(buf, "%g", n_);
703 LengthObj::LengthObj(long n)
708 bool LengthObj::lengthValue(long &n)
714 ELObj::QuantityType LengthObj::quantityValue(long &val, double &, int &dim)
721 bool LengthObj::isEqual(ELObj &obj)
726 switch (obj.quantityValue(n, d, dim)) {
730 return dim == 1 && d == n_;
732 return dim == 1 && n == n_;
737 void LengthObj::print(Interpreter &interp, OutputCharStream &out)
740 sprintf(buf, "%gpt", n_ * 72.0/interp.unitsPerInch());
744 QuantityObj::QuantityObj(double val, int dim)
745 : val_(val), dim_(dim)
749 bool QuantityObj::isEqual(ELObj &obj)
754 switch (obj.quantityValue(n, d, dim)) {
758 return dim == dim_ && d == val_;
760 return dim == dim_ && n == val_;
765 ELObj::QuantityType QuantityObj::quantityValue(long &, double &val, int &dim)
769 return doubleQuantity;
772 void QuantityObj::print(Interpreter &interp, OutputCharStream &out)
775 sprintf(buf, "%gpt%d", val_ * pow(72.0/interp.unitsPerInch(), double(dim_)),
780 bool QuantityObj::realValue(double &d)
788 bool QuantityObj::inexactRealValue(double &d)
796 LengthSpecObj::LengthSpecObj(const LengthSpec &spec)
797 : lengthSpec_(new LengthSpec(spec))
801 const LengthSpec *LengthSpecObj::lengthSpec() const
803 return lengthSpec_.pointer();
806 LengthSpec::LengthSpec()
808 for (int i = 0; i < nVals; i++)
812 LengthSpec::LengthSpec(double d)
815 for (int i = 1; i < nVals; i++)
819 LengthSpec::LengthSpec(Unknown unknown, double d)
822 for (i = 0; i < unknown; i++)
825 for (i = unknown + 1; i < nVals; i++)
829 void LengthSpec::operator+=(const LengthSpec &ls)
831 for (int i = 0; i < nVals; i++)
832 val_[i] += ls.val_[i];
835 void LengthSpec::operator-=(const LengthSpec &ls)
837 for (int i = 0; i < nVals; i++)
838 val_[i] -= ls.val_[i];
841 void LengthSpec::operator*=(double d)
843 for (int i = 0; i < nVals; i++)
847 void LengthSpec::operator/=(double d)
849 for (int i = 0; i < nVals; i++)
853 bool LengthSpec::convert(FOTBuilder::LengthSpec &result) const
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];
861 bool LengthSpec::convert(FOTBuilder::TableLengthSpec &result) const
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];
870 DisplaySpaceObj::DisplaySpaceObj(const FOTBuilder::DisplaySpace &displaySpace)
871 : displaySpace_(new FOTBuilder::DisplaySpace(displaySpace))
875 const FOTBuilder::DisplaySpace &DisplaySpaceObj::displaySpace() const
877 return *displaySpace_;
880 DisplaySpaceObj *DisplaySpaceObj::asDisplaySpace()
885 InlineSpaceObj::InlineSpaceObj(const FOTBuilder::InlineSpace &inlineSpace)
886 : inlineSpace_(new FOTBuilder::InlineSpace(inlineSpace))
890 const FOTBuilder::InlineSpace &InlineSpaceObj::inlineSpace() const
892 return *inlineSpace_;
895 InlineSpaceObj *InlineSpaceObj::asInlineSpace()
900 UnresolvedLengthObj::UnresolvedLengthObj(long val, int valExp, Unit *unit)
901 : val_(val), valExp_(valExp), unit_(unit)
905 ELObj *UnresolvedLengthObj::resolveQuantities(bool force,
911 if (!unit_->defined(part, defLoc)) {
912 interp.setNextLocation(loc);
913 interp.message(InterpreterMessages::undefinedQuantity,
914 StringMessageArg(unit_->name()));
915 return interp.makeError();
917 return unit_->resolveQuantity(force, interp, val_, valExp_);
920 UnresolvedQuantityObj
921 ::UnresolvedQuantityObj(double val, Unit *unit, int unitExp)
922 : val_(val), unit_(unit), unitExp_(unitExp)
926 ELObj *UnresolvedQuantityObj::resolveQuantities(bool force,
932 if (!unit_->defined(part, defLoc)) {
933 interp.setNextLocation(loc);
934 interp.message(InterpreterMessages::undefinedQuantity,
935 StringMessageArg(unit_->name()));
936 return interp.makeError();
938 return unit_->resolveQuantity(force, interp, val_, unitExp_);
941 GlyphIdObj::GlyphIdObj(const FOTBuilder::GlyphId &glyphId)
946 const FOTBuilder::GlyphId *GlyphIdObj::glyphId() const
951 bool GlyphIdObj::isEqual(ELObj &obj)
953 const FOTBuilder::GlyphId *p = obj.glyphId();
955 && p->publicId == glyphId_.publicId
956 && p->suffix == glyphId_.suffix);
959 GlyphSubstTableObj::GlyphSubstTableObj(const ConstPtr<FOTBuilder::GlyphSubstTable> &table)
964 GlyphSubstTableObj *GlyphSubstTableObj::asGlyphSubstTable()
969 AddressObj::AddressObj(FOTBuilder::Address::Type type,
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;
983 AddressObj *AddressObj::asAddress()
988 NodeListObj *NodeListObj::asNodeList()
993 NodeListObj *NodeListObj::nodeListNoOrder(Collector &)
998 NodeListObj *NodeListObj::nodeListChunkRest(EvalContext &context, Interpreter &interp, bool &chunk)
1001 return nodeListRest(context, interp);
1004 bool NodeListObj::optSingletonNodeList(EvalContext &context, Interpreter &interp, NodePtr &node)
1006 NodeListObj *rest = nodeListRest(context, interp);
1007 ELObjDynamicRoot protect(interp, rest);
1008 if (rest->nodeListFirst(context, interp))
1010 node = nodeListFirst(context, interp);
1014 NodePtr NodeListObj::nodeListRef(long n, EvalContext &context, Interpreter &interp)
1018 NodeListObj *nl = this;
1019 ELObjDynamicRoot protect(interp, nl);
1021 NodePtr nd(nl->nodeListFirst(context, interp));
1025 if (nd->charChunk(interp, str) == accessOK && str.size() <= n) {
1027 nl = nl->nodeListChunkRest(context, interp, chunk);
1034 nl = nl->nodeListRest(context, interp);
1039 return nl->nodeListFirst(context, interp);
1042 NodeListObj *NodeListObj::nodeListReverse(EvalContext &, Interpreter &interp)
1044 return new (interp) ReverseNodeListObj(this);
1047 long NodeListObj::nodeListLength(EvalContext &context, Interpreter &interp)
1049 NodeListObj *nl = this;
1051 ELObjDynamicRoot protect(interp, nl);
1053 NodePtr nd(nl->nodeListFirst(context, interp));
1057 nl = nl->nodeListChunkRest(context, interp, chunk);
1060 if (chunk && nd->charChunk(interp, str) == accessOK)
1068 bool NodeListObj::suppressError()
1073 NamedNodeListObj *NamedNodeListObj::asNamedNodeList()
1078 NodePtrNodeListObj::NodePtrNodeListObj()
1082 NodePtrNodeListObj::NodePtrNodeListObj(const NodePtr &node)
1087 bool NodePtrNodeListObj::optSingletonNodeList(EvalContext &, Interpreter &, NodePtr &node)
1093 NodePtr NodePtrNodeListObj::nodeListFirst(EvalContext &, Interpreter &)
1098 NodeListObj *NodePtrNodeListObj::nodeListRest(EvalContext &context, Interpreter &interp)
1101 return new (interp) NodePtrNodeListObj;
1106 NodeListPtrNodeListObj::NodeListPtrNodeListObj(const NodeListPtr &nodeList)
1107 : nodeList_(nodeList)
1111 NodePtr NodeListPtrNodeListObj::nodeListFirst(EvalContext &, Interpreter &)
1114 if (nodeList_->first(nd) == accessOK)
1120 NodeListObj *NodeListPtrNodeListObj::nodeListRest(EvalContext &context, Interpreter &interp)
1123 if (nodeList_->rest(nl) == accessOK)
1124 return new (interp) NodeListPtrNodeListObj(nl);
1126 return interp.makeEmptyNodeList();
1129 NodeListObj *NodeListPtrNodeListObj::nodeListChunkRest(EvalContext &context, Interpreter &interp, bool &chunk)
1132 if (nodeList_->chunkRest(nl) == accessOK) {
1134 return new (interp) NodeListPtrNodeListObj(nl);
1138 return interp.makeEmptyNodeList();
1142 NodePtr NodeListPtrNodeListObj::nodeListRef(long i, EvalContext &, Interpreter &interp)
1145 if (i < 0 || nodeList_->ref(i, nd) != accessOK)
1150 NamedNodeListPtrNodeListObj
1151 ::NamedNodeListPtrNodeListObj(const NamedNodeListPtr &nnl)
1152 : namedNodeList_(nnl)
1156 NodePtr NamedNodeListPtrNodeListObj::namedNode(const Char *s, size_t n)
1159 if (namedNodeList_->namedNode(GroveString(s, n), node) != accessOK)
1164 bool NamedNodeListPtrNodeListObj::nodeName(const NodePtr &nd, GroveString &str)
1166 return namedNodeList_->nodeName(nd, str) == accessOK;
1169 size_t NamedNodeListPtrNodeListObj::normalize(Char *s, size_t n)
1171 return namedNodeList_->normalize(s, n);
1174 NodePtr NamedNodeListPtrNodeListObj::nodeListFirst(EvalContext &, Interpreter &)
1177 nodeList_ = namedNodeList_->nodeList();
1179 if (nodeList_->first(nd) == accessOK)
1185 NodeListObj *NamedNodeListPtrNodeListObj::nodeListRest(EvalContext &context, Interpreter &interp)
1188 nodeList_ = namedNodeList_->nodeList();
1190 if (nodeList_->rest(nl) == accessOK)
1191 return new (interp) NodeListPtrNodeListObj(nl);
1193 return new (interp) NodePtrNodeListObj;
1196 NodeListObj *NamedNodeListPtrNodeListObj::nodeListNoOrder(Collector &c)
1198 return new (c) NodeListPtrNodeListObj(namedNodeList_->nodeListNoOrder());
1201 PairNodeListObj::PairNodeListObj(NodeListObj *head, NodeListObj *tail)
1202 : head_(head), tail_(tail)
1207 NodePtr PairNodeListObj::nodeListFirst(EvalContext &context, Interpreter &interp)
1210 NodePtr nd(head_->nodeListFirst(context, interp));
1215 return tail_->nodeListFirst(context, interp);
1218 NodeListObj *PairNodeListObj::nodeListRest(EvalContext &context, Interpreter &interp)
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_);
1227 NodeListObj *PairNodeListObj::nodeListChunkRest(EvalContext &context, Interpreter &interp, bool &chunk)
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_);
1236 void PairNodeListObj::traceSubObjects(Collector &c) const
1242 ReverseNodeListObj::ReverseNodeListObj(NodeListObj *nl)
1243 : nl_(nl), reversed_(0)
1248 NodePtr ReverseNodeListObj::nodeListFirst(EvalContext &context, Interpreter &interp)
1250 return reversed(context, interp)->nodeListFirst(context, interp);
1253 NodeListObj *ReverseNodeListObj::nodeListRest(EvalContext &context, Interpreter &interp)
1255 return reversed(context, interp)->nodeListRest(context, interp);
1258 NodePtr ReverseNodeListObj::nodeListRef(long n, EvalContext &context, Interpreter &interp)
1261 return reversed_->nodeListRef(n, context, interp);
1264 size_t len = nl_->nodeListLength(context, interp);
1267 return nl_->nodeListRef(len - n - 1, context, interp);
1270 NodeListObj *ReverseNodeListObj::reversed(EvalContext &context, Interpreter &interp)
1273 NodePtr nd(nl_->nodeListFirst(context, interp));
1275 reversed_ = new (interp) NodePtrNodeListObj(nd);
1276 NodeListObj *tem = nl_;
1277 ELObjDynamicRoot protect(interp, tem);
1278 ELObjDynamicRoot protect2(interp, reversed_);
1280 tem = tem->nodeListRest(context, interp);
1282 nd = tem->nodeListFirst(context, interp);
1285 NodeListObj *single = new (interp) NodePtrNodeListObj(nd);
1287 reversed_ = new (interp) PairNodeListObj(single, reversed_);
1296 NodeListObj *ReverseNodeListObj::nodeListReverse(EvalContext &, Interpreter &)
1301 long ReverseNodeListObj::nodeListLength(EvalContext &context, Interpreter &interp)
1303 return nl_->nodeListLength(context, interp);
1306 void ReverseNodeListObj::traceSubObjects(Collector &c) const
1312 #ifdef DSSSL_NAMESPACE