PageRenderTime 59ms CodeModel.GetById 28ms RepoModel.GetById 1ms app.codeStats 0ms

/tags/jade_1_2_2/jade/style/Interpreter.cxx

#
C++ | 1949 lines | 1820 code | 101 blank | 28 comment | 414 complexity | ba859348db9584ccc6ca0ee418b00ee0 MD5 | raw file
Possible License(s): LGPL-2.1, LGPL-2.0
  1. // Copyright (c) 1996 James Clark
  2. // See the file copying.txt for copying permission.
  3. #include "stylelib.h"
  4. #include "Interpreter.h"
  5. #include "Insn.h"
  6. #include "InterpreterMessages.h"
  7. #include "LocNode.h"
  8. #include "Pattern.h"
  9. #include "MacroFlowObj.h"
  10. #include "ELObjMessageArg.h"
  11. #include "VM.h"
  12. #include "Owner.h"
  13. #include "SchemeParser.h"
  14. #include "macros.h"
  15. #include <stdlib.h>
  16. #ifdef DSSSL_NAMESPACE
  17. namespace DSSSL_NAMESPACE {
  18. #endif
  19. const Char defaultChar = 0xfffd;
  20. static
  21. size_t maxObjSize()
  22. {
  23. static size_t sz[] = {
  24. sizeof(UnresolvedQuantityObj),
  25. sizeof(VarStyleObj),
  26. sizeof(OverriddenStyleObj),
  27. sizeof(MergeStyleObj),
  28. sizeof(DeviceRGBColorObj),
  29. sizeof(ColorSpaceObj),
  30. sizeof(PairObj),
  31. sizeof(QuantityObj),
  32. sizeof(GlyphIdObj),
  33. sizeof(NamedNodeListPtrNodeListObj),
  34. sizeof(ProcessNodeSosofoObj),
  35. sizeof(AppendSosofoObj),
  36. sizeof(SetNonInheritedCsSosofoObj),
  37. sizeof(LabelSosofoObj),
  38. sizeof(MacroFlowObj),
  39. sizeof(FlowObj) + sizeof(StringC), // for FormattingInstructionFlowObj
  40. };
  41. size_t n = sz[0];
  42. for (size_t i = 1; i < SIZEOF(sz); i++)
  43. if (sz[i] > n)
  44. n = sz[i];
  45. return n;
  46. }
  47. Interpreter::Interpreter(GroveManager *groveManager,
  48. Messenger *messenger,
  49. int unitsPerInch,
  50. bool debugMode,
  51. bool dsssl2,
  52. const FOTBuilder::Extension *extensionTable)
  53. : groveManager_(groveManager),
  54. messenger_(messenger),
  55. extensionTable_(extensionTable),
  56. Collector(maxObjSize()),
  57. partIndex_(1), // 0 is for command-line definitions
  58. dPartIndex_(1),
  59. lexCategory_(lexOther),
  60. unitsPerInch_(unitsPerInch),
  61. nInheritedC_(0),
  62. initialProcessingMode_(StringC()),
  63. currentPartFirstInitialValue_(0),
  64. initialStyle_(0),
  65. nextGlyphSubstTableUniqueId_(0),
  66. debugMode_(debugMode),
  67. dsssl2_(dsssl2)
  68. {
  69. makePermanent(theNilObj_ = new (*this) NilObj);
  70. makePermanent(theFalseObj_ = new (*this) FalseObj);
  71. makePermanent(theTrueObj_ = new (*this) TrueObj);
  72. makePermanent(theErrorObj_ = new (*this) ErrorObj);
  73. makePermanent(theUnspecifiedObj_ = new (*this) UnspecifiedObj);
  74. makePermanent(addressNoneObj_
  75. = new (*this) AddressObj(FOTBuilder::Address::none));
  76. makePermanent(emptyNodeListObj_
  77. = new (*this) NodePtrNodeListObj);
  78. installSyntacticKeys();
  79. installCValueSymbols();
  80. installPortNames();
  81. installPrimitives();
  82. installUnits();
  83. installCharNames();
  84. installSdata();
  85. installFlowObjs();
  86. installInheritedCs();
  87. installNodeProperties();
  88. static const char *lexCategories[] = {
  89. "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",
  90. "!$%&*/<=>?~_^:",
  91. "0123456789",
  92. "-+.",
  93. "();\"",
  94. " \t\r\n\f",
  95. };
  96. lexCategory_.setChar(InputSource::eE, lexDelimiter);
  97. for (size_t i = 0; i < SIZEOF(lexCategories); i++)
  98. for (const char *s = lexCategories[i]; *s; s++)
  99. lexCategory_.setChar(*s, i);
  100. initialProcessingMode_.setDefined();
  101. }
  102. void Interpreter::compile()
  103. {
  104. // FIXME compile all definitions
  105. compileInitialValues();
  106. initialProcessingMode_.compile(*this);
  107. NamedTableIter<ProcessingMode> iter(processingModeTable_);
  108. for (;;) {
  109. ProcessingMode *mode = iter.next();
  110. if (!mode)
  111. break;
  112. mode->compile(*this);
  113. }
  114. }
  115. void Interpreter::compileInitialValues()
  116. {
  117. Vector<ConstPtr<InheritedC> > ics;
  118. for (size_t i = 0; i < initialValueNames_.size(); i++) {
  119. const Identifier *ident = initialValueNames_[i];
  120. Owner<Expression> &expr = initialValueValues_[i];
  121. ConstPtr<InheritedC> ic(ident->inheritedC());
  122. expr->optimize(*this, Environment(), expr);
  123. ELObj *val = expr->constantValue();
  124. if (val) {
  125. ConstPtr<InheritedC> tem(ic->make(val, expr->location(), *this));
  126. if (!tem.isNull())
  127. ics.push_back(tem);
  128. }
  129. else
  130. ics.push_back(new VarInheritedC(ic,
  131. expr->compile(*this, Environment(), 0, InsnPtr()),
  132. expr->location()));
  133. }
  134. if (ics.size()) {
  135. Vector<ConstPtr<InheritedC> > forceIcs;
  136. initialStyle_ = new (*this) VarStyleObj(new StyleSpec(forceIcs, ics), 0, 0, NodePtr());
  137. makePermanent(initialStyle_);
  138. }
  139. }
  140. void Interpreter::installInitialValue(Identifier *ident, Owner<Expression> &expr)
  141. {
  142. for (size_t i = 0; i < initialValueNames_.size(); i++) {
  143. if (ident == initialValueNames_[i]) {
  144. if (i >= currentPartFirstInitialValue_) {
  145. setNextLocation(expr->location());
  146. message(InterpreterMessages::duplicateInitialValue,
  147. StringMessageArg(ident->name()),
  148. initialValueValues_[i]->location());
  149. }
  150. return;
  151. }
  152. }
  153. initialValueValues_.resize(initialValueValues_.size() + 1);
  154. expr.swap(initialValueValues_.back());
  155. initialValueNames_.push_back(ident);
  156. }
  157. void Interpreter::defineVariable(const StringC &str)
  158. {
  159. lookup(str)->setValue(makeTrue(), 0);
  160. }
  161. void Interpreter::installUnits()
  162. {
  163. static struct {
  164. const char *name;
  165. int numer;
  166. int denom;
  167. bool dsssl2;
  168. } units[] = {
  169. { "m", 5000, 127 },
  170. { "cm", 50, 127 },
  171. { "mm", 5, 127 },
  172. { "in", 1, 1 },
  173. { "pt", 1, 72 },
  174. { "pica", 1, 6 },
  175. { "pc", 1, 6 } // a DSSSL2 addition
  176. };
  177. size_t nUnits = dsssl2() ? SIZEOF(units) : SIZEOF(units) - 1;
  178. for (size_t i = 0; i < nUnits; i++) {
  179. Unit *unit = lookupUnit(makeStringC(units[i].name));
  180. long n = unitsPerInch_ * units[i].numer;
  181. if (n % units[i].denom == 0)
  182. unit->setValue(long(n / units[i].denom));
  183. else
  184. unit->setValue(double(n)/units[i].denom);
  185. }
  186. }
  187. void Interpreter::installSyntacticKeys()
  188. {
  189. static struct {
  190. const char *name;
  191. Identifier::SyntacticKey key;
  192. } keys[] = {
  193. { "quote", Identifier::keyQuote },
  194. { "lambda", Identifier::keyLambda },
  195. { "if", Identifier::keyIf },
  196. { "cond", Identifier::keyCond },
  197. { "and", Identifier::keyAnd },
  198. { "or", Identifier::keyOr },
  199. { "case", Identifier::keyCase },
  200. { "let", Identifier::keyLet },
  201. { "let*", Identifier::keyLetStar },
  202. { "letrec", Identifier::keyLetrec },
  203. { "quasiquote", Identifier::keyQuasiquote },
  204. { "unquote", Identifier::keyUnquote },
  205. { "unquote-splicing", Identifier::keyUnquoteSplicing },
  206. { "define", Identifier::keyDefine },
  207. { "else", Identifier::keyElse },
  208. { "=>", Identifier::keyArrow },
  209. { "make", Identifier::keyMake },
  210. { "style", Identifier::keyStyle },
  211. { "with-mode", Identifier::keyWithMode },
  212. { "define-unit", Identifier::keyDefineUnit },
  213. { "element", Identifier::keyElement },
  214. { "default", Identifier::keyDefault },
  215. { "root", Identifier::keyRoot },
  216. { "id", Identifier::keyId },
  217. { "mode", Identifier::keyMode },
  218. { "declare-initial-value", Identifier::keyDeclareInitialValue },
  219. { "declare-characteristic", Identifier::keyDeclareCharacteristic },
  220. { "declare-flow-object-class", Identifier::keyDeclareFlowObjectClass },
  221. { "declare-char-characteristic+property", Identifier::keyDeclareCharCharacteristicAndProperty },
  222. { "declare-reference-value-type", Identifier::keyDeclareReferenceValueType },
  223. { "declare-default-language", Identifier::keyDeclareDefaultLanguage },
  224. { "declare-char-property", Identifier::keyDeclareCharProperty },
  225. { "define-page-model", Identifier::keyDefinePageModel },
  226. { "define-column-set-model", Identifier::keyDefineColumnSetModel },
  227. { "define-language", Identifier::keyDefineLanguage },
  228. { "add-char-properties", Identifier::keyAddCharProperties },
  229. { "use", Identifier::keyUse },
  230. { "label", Identifier::keyLabel },
  231. { "content-map", Identifier::keyContentMap },
  232. { "keep-with-previous?", Identifier::keyIsKeepWithPrevious },
  233. { "keep-with-next?", Identifier::keyIsKeepWithNext },
  234. { "space-before", Identifier::keySpaceBefore },
  235. { "space-after", Identifier::keySpaceAfter },
  236. { "left-header", Identifier::keyLeftHeader },
  237. { "center-header", Identifier::keyCenterHeader },
  238. { "right-header", Identifier::keyRightHeader },
  239. { "left-footer", Identifier::keyLeftFooter },
  240. { "center-footer", Identifier::keyCenterFooter },
  241. { "right-footer", Identifier::keyRightFooter },
  242. { "destination", Identifier::keyDestination },
  243. { "type", Identifier::keyType },
  244. { "coalesce-id", Identifier::keyCoalesceId },
  245. { "display?", Identifier::keyIsDisplay },
  246. { "scale", Identifier::keyScale },
  247. { "max-width", Identifier::keyMaxWidth },
  248. { "max-height", Identifier::keyMaxHeight },
  249. { "entity-system-id", Identifier::keyEntitySystemId },
  250. { "notation-system-id", Identifier::keyNotationSystemId },
  251. { "position-point-x", Identifier::keyPositionPointX },
  252. { "position-point-y", Identifier::keyPositionPointY },
  253. { "escapement-direction", Identifier::keyEscapementDirection },
  254. { "break-before-priority", Identifier::keyBreakBeforePriority },
  255. { "break-after-priority", Identifier::keyBreakAfterPriority },
  256. { "orientation", Identifier::keyOrientation },
  257. { "length", Identifier::keyLength },
  258. { "char", Identifier::keyChar },
  259. { "glyph-id", Identifier::keyGlyphId },
  260. { "space?", Identifier::keyIsSpace },
  261. { "record-end?", Identifier::keyIsRecordEnd },
  262. { "input-tab?", Identifier::keyIsInputTab },
  263. { "input-whitespace?", Identifier::keyIsInputWhitespace },
  264. { "punct?", Identifier::keyIsPunct },
  265. { "drop-after-line-break?", Identifier::keyIsDropAfterLineBreak },
  266. { "drop-unless-before-line-break?", Identifier::keyIsDropUnlessBeforeLineBreak },
  267. { "math-class", Identifier::keyMathClass },
  268. { "math-font-posture", Identifier::keyMathFontPosture },
  269. { "script", Identifier::keyScript },
  270. { "stretch-factor", Identifier::keyStretchFactor },
  271. { "keep", Identifier::keyKeep },
  272. { "break-before", Identifier::keyBreakBefore },
  273. { "break-after", Identifier::keyBreakAfter },
  274. { "may-violate-keep-before?", Identifier::keyIsMayViolateKeepBefore },
  275. { "may-violate-keep-after?", Identifier::keyIsMayViolateKeepAfter },
  276. { "before-row-border", Identifier::keyBeforeRowBorder },
  277. { "after-row-border", Identifier::keyAfterRowBorder },
  278. { "before-column-border", Identifier::keyBeforeColumnBorder },
  279. { "after-column-border", Identifier::keyAfterColumnBorder },
  280. { "column-number", Identifier::keyColumnNumber },
  281. { "row-number", Identifier::keyRowNumber },
  282. { "n-columns-spanned", Identifier::keyNColumnsSpanned },
  283. { "n-rows-spanned", Identifier::keyNRowsSpanned },
  284. { "width", Identifier::keyWidth },
  285. { "starts-row?", Identifier::keyIsStartsRow },
  286. { "ends-row?", Identifier::keyIsEndsRow },
  287. { "table-width", Identifier::keyTableWidth },
  288. { "multi-modes", Identifier::keyMultiModes },
  289. { "data", Identifier::keyData },
  290. { "min", Identifier::keyMin },
  291. { "max", Identifier::keyMax },
  292. { "conditional?", Identifier::keyIsConditional },
  293. { "priority", Identifier::keyPriority },
  294. { "grid-n-rows", Identifier::keyGridNRows },
  295. { "grid-n-columns", Identifier::keyGridNColumns },
  296. { "radical", Identifier::keyRadical },
  297. { "null", Identifier::keyNull },
  298. { "rcs?", Identifier::keyIsRcs },
  299. { "parent", Identifier::keyParent },
  300. { "active", Identifier::keyActive },
  301. { "attributes", Identifier::keyAttributes },
  302. { "children", Identifier::keyChildren },
  303. { "repeat", Identifier::keyRepeat },
  304. { "position", Identifier::keyPosition },
  305. { "only", Identifier::keyOnly },
  306. { "class", Identifier::keyClass },
  307. { "importance", Identifier::keyImportance },
  308. { "position-preference", Identifier::keyPositionPreference },
  309. { "architecture", Identifier::keyArchitecture },
  310. }, keys2[] = {
  311. { "declare-class-attribute", Identifier::keyDeclareClassAttribute },
  312. { "declare-id-attribute", Identifier::keyDeclareIdAttribute },
  313. { "declare-flow-object-macro", Identifier::keyDeclareFlowObjectMacro },
  314. { "or-element", Identifier::keyOrElement },
  315. { "set!", Identifier::keySet },
  316. { "begin", Identifier::keyBegin },
  317. };
  318. for (size_t i = 0; i < SIZEOF(keys); i++) {
  319. StringC tem(makeStringC(keys[i].name));
  320. lookup(tem)->setSyntacticKey(keys[i].key);
  321. if (dsssl2() && tem[tem.size() - 1] == '?') {
  322. tem.resize(tem.size() - 1);
  323. lookup(tem)->setSyntacticKey(keys[i].key);
  324. }
  325. }
  326. if (dsssl2()) {
  327. for (size_t i = 0; i < SIZEOF(keys2); i++)
  328. lookup(makeStringC(keys2[i].name))->setSyntacticKey(keys2[i].key);
  329. }
  330. }
  331. void Interpreter::installCValueSymbols()
  332. {
  333. cValueSymbols_[0] = makeFalse();
  334. cValueSymbols_[1] = makeTrue();
  335. for (size_t i = 2; i < FOTBuilder::nSymbols; i++) {
  336. SymbolObj *sym = makeSymbol(makeStringC(FOTBuilder::symbolName(FOTBuilder::Symbol(i))));
  337. sym->setCValue(FOTBuilder::Symbol(i));
  338. cValueSymbols_[i] = sym;
  339. }
  340. }
  341. void Interpreter::installPortNames()
  342. {
  343. // These must match the order in SymbolObj.
  344. static const char *names[] = {
  345. "numerator",
  346. "denominator",
  347. "pre-sup",
  348. "pre-sub",
  349. "post-sup",
  350. "post-sub",
  351. "mid-sup",
  352. "mid-sub",
  353. "over-mark",
  354. "under-mark",
  355. "open",
  356. "close",
  357. "degree",
  358. "operator",
  359. "lower-limit",
  360. "upper-limit",
  361. "header",
  362. "footer"
  363. };
  364. ASSERT(SIZEOF(names) == nPortNames);
  365. for (size_t i = 0; i < SIZEOF(names); i++)
  366. portNames_[i] = makeSymbol(makeStringC(names[i]));
  367. }
  368. void Interpreter::installCharNames()
  369. {
  370. static struct {
  371. Char c;
  372. const char *name;
  373. } chars[] = {
  374. #include "charNames.h"
  375. };
  376. for (size_t i = 0; i < SIZEOF(chars); i++) {
  377. CharPart ch;
  378. ch.c = chars[i].c;
  379. ch.defPart = unsigned(-1);
  380. namedCharTable_.insert(makeStringC(chars[i].name), ch, 1);
  381. }
  382. }
  383. void Interpreter::installSdata()
  384. {
  385. // This comes from uni2sgml.txt on ftp://unicode.org.
  386. // It is marked there as obsolete, so it probably ought to be checked.
  387. // The definitions of apos and quot have been fixed for consistency with XML.
  388. static struct {
  389. Char c;
  390. const char *name;
  391. } entities[] = {
  392. #include "sdata.h"
  393. };
  394. for (size_t i = 0; i < SIZEOF(entities); i++) {
  395. CharPart ch;
  396. ch.c = entities[i].c;
  397. ch.defPart = unsigned(-1);
  398. sdataEntityNameTable_.insert(makeStringC(entities[i].name), ch, 1);
  399. }
  400. }
  401. void Interpreter::installNodeProperties()
  402. {
  403. for (int i = 0; i < ComponentName::nIds; i++) {
  404. ComponentName::Id id = ComponentName::Id(i);
  405. nodePropertyTable_.insert(makeStringC(ComponentName::rcsName(id)), i);
  406. nodePropertyTable_.insert(makeStringC(ComponentName::sdqlName(id)), i);
  407. }
  408. }
  409. static
  410. bool isWhitespace(Xchar c)
  411. {
  412. switch (c) {
  413. case InputSource::eE:
  414. case '\t':
  415. case '\f':
  416. case '\r':
  417. case '\n':
  418. case ' ':
  419. return 1;
  420. default:
  421. return 0;
  422. }
  423. }
  424. static
  425. bool getToken(InputSource *in, Interpreter &inp)
  426. {
  427. // Get the next sequence of nonblank chars from
  428. // in. Ignore inital blanks. Return 1 if at least
  429. // one nonblank was found, else 0.
  430. for (;;) {
  431. in->startToken();
  432. int length = 0;
  433. Xchar c = in->tokenChar(inp);
  434. if (c == InputSource::eE)
  435. return 0;
  436. if (!isWhitespace(c)) {
  437. length = in->currentTokenLength();
  438. while (!isWhitespace(c)) {
  439. c = in->tokenChar(inp);
  440. length++;
  441. }
  442. in->endToken(length - 1);
  443. return 1;
  444. }
  445. }
  446. }
  447. void Interpreter::addStandardChars(Owner<InputSource> &ins)
  448. {
  449. InputSource *in = ins.pointer();
  450. if (!in)
  451. return;
  452. for (;;) {
  453. // FIXME we do not check that we have valid character names
  454. // and numbers (in decimal)
  455. if (!getToken(in, *this))
  456. break;
  457. StringC name(in->currentTokenStart(), in->currentTokenLength());
  458. if (!getToken(in, *this)) {
  459. setNextLocation(in->currentLocation());
  460. message(InterpreterMessages::badDeclaration);
  461. break;
  462. }
  463. StringC digits(in->currentTokenStart(), in->currentTokenLength());
  464. int n;
  465. unsigned int i=0;
  466. if (!scanSignDigits(digits, i, n)) {
  467. setNextLocation(in->currentLocation());
  468. message(InterpreterMessages::badCharNumber, StringMessageArg(digits));
  469. continue;
  470. }
  471. const CharPart *def = namedCharTable_.lookup(name);
  472. CharPart ch;
  473. ch.c = n;
  474. ch.defPart = dPartIndex_;
  475. if (def) {
  476. if (dPartIndex_ < def->defPart)
  477. namedCharTable_.insert(name, ch, 1);
  478. else if (def->defPart == dPartIndex_ && def->c != ch.c) {
  479. setNextLocation(in->currentLocation());
  480. message(InterpreterMessages::duplicateCharName,
  481. StringMessageArg(name));
  482. }
  483. }
  484. else
  485. namedCharTable_.insert(name, ch, 1);
  486. }
  487. }
  488. void Interpreter::addSdataEntity(const StringC &name, const StringC &text, Owner<InputSource> &ins)
  489. {
  490. InputSource *in = ins.pointer();
  491. if (!in)
  492. return;
  493. if (!getToken(in, *this)) {
  494. setNextLocation(in->currentLocation());
  495. message(InterpreterMessages::badDeclaration);
  496. return;
  497. }
  498. StringC chnum(in->currentTokenStart(), in->currentTokenLength());
  499. // FIXME we do not check that there is only one token
  500. const CharPart *cp = namedCharTable_.lookup(chnum);
  501. if (!cp)
  502. return; // FIXME
  503. CharPart ch;
  504. ch.c = cp->c;
  505. ch.defPart = dPartIndex_;
  506. if (name.size() > 0) {
  507. const CharPart *def = sdataEntityNameTable_.lookup(name);
  508. if (def) {
  509. if (dPartIndex_ < def->defPart)
  510. sdataEntityNameTable_.insert(name, ch);
  511. else if (def->defPart == dPartIndex_ && def->c != cp->c) {
  512. setNextLocation(in->currentLocation());
  513. message(InterpreterMessages::duplicateSdataEntityName,
  514. StringMessageArg(name));
  515. }
  516. }
  517. else
  518. sdataEntityNameTable_.insert(name, ch);
  519. }
  520. if (text.size() > 0) {
  521. const CharPart *def = sdataEntityTextTable_.lookup(text);
  522. if (def) {
  523. if (dPartIndex_ < def->defPart)
  524. sdataEntityTextTable_.insert(text, ch);
  525. else if (def->defPart == dPartIndex_ && def->c != cp->c) {
  526. setNextLocation(in->currentLocation());
  527. message(InterpreterMessages::duplicateSdataEntityText,
  528. StringMessageArg(text));
  529. }
  530. }
  531. else
  532. sdataEntityTextTable_.insert(text, ch);
  533. }
  534. }
  535. bool Interpreter::sdataMap(GroveString name, GroveString text, GroveChar &c) const
  536. {
  537. StringC tem(name.data(), name.size());
  538. StringC tem2(text.data(), text.size());
  539. const CharPart *cp = sdataEntityNameTable_.lookup(tem);
  540. if (cp) {
  541. c = cp->c;
  542. return 1;
  543. }
  544. cp = sdataEntityTextTable_.lookup(tem2);
  545. if (cp) {
  546. c = cp->c;
  547. return 1;
  548. }
  549. if (convertUnicodeCharName(tem, c))
  550. return 1;
  551. // I think this is the best thing to do.
  552. // At least it makes preserve-sdata work with unknown SDATA entities.
  553. c = defaultChar;
  554. return 1;
  555. }
  556. ELObj *Interpreter::convertGlyphId(const Char *str, size_t len, const Location &loc)
  557. {
  558. unsigned long n = 0;
  559. const char *publicId = 0;
  560. for (size_t i = len; i > 1; --i) {
  561. if (str[i - 1] == ':' && str[i - 2] == ':' && i < len && str[i] != '0') {
  562. for (size_t j = i; j < len; j++)
  563. n = n*10 + (str[j] - '0');
  564. publicId = storePublicId(str, i - 2, loc);
  565. break;
  566. }
  567. if (str[i - 1] < '0' || str[i - 1] > '9')
  568. break;
  569. }
  570. if (!publicId)
  571. publicId = storePublicId(str, len, loc);
  572. return new (*this) GlyphIdObj(FOTBuilder::GlyphId(publicId, n));
  573. }
  574. bool Interpreter::convertCharName(const StringC &str, Char &c) const
  575. {
  576. const CharPart *cp = namedCharTable_.lookup(str);
  577. if (cp) {
  578. c = cp->c;
  579. return 1;
  580. }
  581. return convertUnicodeCharName(str, c);
  582. }
  583. bool Interpreter::convertUnicodeCharName(const StringC &str, Char &c)
  584. {
  585. if (str.size() != 6 || str[0] != 'U' || str[1] != '-')
  586. return 0;
  587. Char value = 0;
  588. for (int i = 2; i < 6; i++) {
  589. value <<= 4;
  590. switch (str[i]) {
  591. case '0':
  592. case '1':
  593. case '2':
  594. case '3':
  595. case '4':
  596. case '5':
  597. case '6':
  598. case '7':
  599. case '8':
  600. case '9':
  601. value |= str[i] - '0';
  602. break;
  603. case 'A':
  604. case 'B':
  605. case 'C':
  606. case 'D':
  607. case 'E':
  608. case 'F':
  609. value |= 10 + (str[i] - 'A');
  610. break;
  611. default:
  612. return 0;
  613. }
  614. }
  615. c = value;
  616. return 1;
  617. }
  618. SymbolObj *Interpreter::makeSymbol(const StringC &str)
  619. {
  620. SymbolObj *sym = symbolTable_.lookup(str);
  621. if (!sym) {
  622. StringObj *strObj = new (*this) StringObj(str);
  623. makePermanent(strObj);
  624. sym = new (*this) SymbolObj(strObj);
  625. makePermanent(sym);
  626. symbolTable_.insert(sym);
  627. }
  628. return sym;
  629. }
  630. Identifier *Interpreter::lookup(const StringC &str)
  631. {
  632. Identifier *ident = identTable_.lookup(str);
  633. if (!ident) {
  634. ident = new Identifier(str);
  635. identTable_.insert(ident);
  636. }
  637. return ident;
  638. }
  639. bool Interpreter::lookupNodeProperty(const StringC &str, ComponentName::Id &id)
  640. {
  641. const int *val = nodePropertyTable_.lookup(str);
  642. if (!val) {
  643. StringC tem(str);
  644. for (size_t i = 0; i < tem.size(); i++) {
  645. if (tem[i] >= 'A' && tem[i] <= 'Z')
  646. tem[i] = 'a' + (tem[i] - 'A');
  647. }
  648. val = nodePropertyTable_.lookup(tem);
  649. if (!val)
  650. return 0;
  651. }
  652. id = ComponentName::Id(*val);
  653. return 1;
  654. }
  655. Unit *Interpreter::lookupUnit(const StringC &str)
  656. {
  657. Unit *unit = unitTable_.lookup(str);
  658. if (!unit) {
  659. unit = new Unit(str);
  660. unitTable_.insert(unit);
  661. }
  662. return unit;
  663. }
  664. ProcessingMode *Interpreter::lookupProcessingMode(const StringC &str)
  665. {
  666. ProcessingMode *mode = processingModeTable_.lookup(str);
  667. if (!mode) {
  668. mode = new ProcessingMode(str, &initialProcessingMode_);
  669. processingModeTable_.insert(mode);
  670. }
  671. return mode;
  672. }
  673. StringC Interpreter::makeStringC(const char *s)
  674. {
  675. StringC tem;
  676. if (s)
  677. while (*s)
  678. tem += (unsigned char)*s++;
  679. return tem;
  680. }
  681. void Interpreter::endPart()
  682. {
  683. currentPartFirstInitialValue_ = initialValueNames_.size();
  684. partIndex_++;
  685. }
  686. void Interpreter::dEndPart()
  687. {
  688. dPartIndex_++;
  689. }
  690. void Interpreter::normalizeGeneralName(const NodePtr &nd, StringC &str)
  691. {
  692. NamedNodeListPtr nnl;
  693. NodePtr root;
  694. if (nd->getGroveRoot(root) == accessOK
  695. && root->getElements(nnl) == accessOK)
  696. str.resize(nnl->normalize(str.begin(), str.size()));
  697. }
  698. ELObj *Interpreter::makeLengthSpec(const FOTBuilder::LengthSpec &ls)
  699. {
  700. if (ls.displaySizeFactor != 0.0) {
  701. LengthSpec result(LengthSpec::displaySize, ls.displaySizeFactor);
  702. result += double(ls.length);
  703. return new (*this) LengthSpecObj(result);
  704. }
  705. else
  706. return new (*this) LengthObj(ls.length);
  707. }
  708. bool Interpreter::convertBooleanC(ELObj *obj, const Identifier *ident, const Location &loc,
  709. bool &result)
  710. {
  711. obj = convertFromString(obj, convertAllowBoolean, loc);
  712. if (obj == makeFalse()) {
  713. result = 0;
  714. return 1;
  715. }
  716. if (obj == makeTrue()) {
  717. result = 1;
  718. return 1;
  719. }
  720. invalidCharacteristicValue(ident, loc);
  721. return 0;
  722. }
  723. bool Interpreter::convertPublicIdC(ELObj *obj, const Identifier *ident,
  724. const Location &loc,
  725. FOTBuilder::PublicId &pubid)
  726. {
  727. if (obj == makeFalse()) {
  728. pubid = 0;
  729. return 1;
  730. }
  731. const Char *s;
  732. size_t n;
  733. if (obj->stringData(s, n)) {
  734. if (n == 0)
  735. pubid = 0;
  736. else
  737. pubid = storePublicId(s, n, loc);
  738. return 1;
  739. }
  740. invalidCharacteristicValue(ident, loc);
  741. return 0;
  742. }
  743. const char *Interpreter::storePublicId(const Char *s, size_t n, const Location &loc)
  744. {
  745. String<char> buf;
  746. for (; n > 0; s++, n--) {
  747. if (*s >= 128) {
  748. setNextLocation(loc);
  749. message(InterpreterMessages::invalidPublicIdChar,
  750. StringMessageArg(StringC(s, 1)));
  751. }
  752. else
  753. buf += char(*s);
  754. }
  755. buf += '\0';
  756. return publicIds_.store(buf);
  757. }
  758. bool Interpreter::convertStringC(ELObj *obj, const Identifier *ident, const Location &loc,
  759. StringC &result)
  760. {
  761. const Char *s;
  762. size_t n;
  763. if (obj->stringData(s, n)) {
  764. result.assign(s, n);
  765. return 1;
  766. }
  767. invalidCharacteristicValue(ident, loc);
  768. return 0;
  769. }
  770. bool Interpreter::convertLengthSpec(ELObj *obj,
  771. FOTBuilder::LengthSpec &result)
  772. {
  773. int dim;
  774. double d;
  775. switch (obj->quantityValue(result.length, d, dim)) {
  776. case ELObj::longQuantity:
  777. if (dim == 1)
  778. return 1;
  779. break;
  780. case ELObj::doubleQuantity:
  781. if (dim == 1) {
  782. // FIXME catch overflow
  783. result.length = d < 0.0 ? long(d - .5) : long(d + .5);
  784. return 1;
  785. }
  786. break;
  787. default:
  788. {
  789. const LengthSpec *ls = obj->lengthSpec();
  790. if (ls)
  791. return ls->convert(result);
  792. }
  793. break;
  794. }
  795. return 0;
  796. }
  797. bool Interpreter::convertLengthC(ELObj *obj, const Identifier *ident,
  798. const Location &loc,
  799. FOTBuilder::Length &n)
  800. {
  801. obj = convertFromString(obj, convertAllowNumber, loc);
  802. int dim;
  803. double d;
  804. switch (obj->quantityValue(n, d, dim)) {
  805. case ELObj::longQuantity:
  806. if (dim == 1)
  807. return 1;
  808. break;
  809. case ELObj::doubleQuantity:
  810. if (dim == 1) {
  811. // FIXME catch overflow
  812. n = long(d);
  813. return 1;
  814. }
  815. break;
  816. default:
  817. break;
  818. }
  819. invalidCharacteristicValue(ident, loc);
  820. return 0;
  821. }
  822. bool Interpreter::convertLengthSpecC(ELObj *obj, const Identifier *ident,
  823. const Location &loc,
  824. FOTBuilder::LengthSpec &result)
  825. {
  826. obj = convertFromString(obj, convertAllowNumber, loc);
  827. if (convertLengthSpec(obj, result))
  828. return 1;
  829. invalidCharacteristicValue(ident, loc);
  830. return 0;
  831. }
  832. bool Interpreter::convertOptLengthSpecC(ELObj *obj, const Identifier *ident,
  833. const Location &loc,
  834. FOTBuilder::OptLengthSpec &result)
  835. {
  836. obj = convertFromString(obj, convertAllowBoolean|convertAllowNumber, loc);
  837. if (obj == makeFalse()) {
  838. result.hasLength = 0;
  839. return 1;
  840. }
  841. if (convertLengthSpecC(obj, ident, loc, result.length)) {
  842. result.hasLength = 1;
  843. return 1;
  844. }
  845. return 0;
  846. }
  847. bool Interpreter::convertOptPositiveIntegerC(ELObj *obj, const Identifier *ident, const Location &loc,
  848. long &result)
  849. {
  850. obj = convertFromString(obj, convertAllowNumber|convertAllowBoolean, loc);
  851. if (obj == makeFalse()) {
  852. result = 0;
  853. return 1;
  854. }
  855. if (obj->exactIntegerValue(result) && result > 0)
  856. return 1;
  857. // FIXME allow inexact value
  858. invalidCharacteristicValue(ident, loc);
  859. return 0;
  860. }
  861. bool Interpreter::convertIntegerC(ELObj *obj, const Identifier *ident, const Location &loc,
  862. long &result)
  863. {
  864. obj = convertFromString(obj, convertAllowNumber, loc);
  865. if (obj->exactIntegerValue(result))
  866. return 1;
  867. // FIXME allow inexact value
  868. invalidCharacteristicValue(ident, loc);
  869. return 0;
  870. }
  871. bool Interpreter::convertLetter2C(ELObj *obj, const Identifier *ident, const Location &loc,
  872. FOTBuilder::Letter2 &code)
  873. {
  874. StringObj *strObj = obj->convertToString();
  875. if (strObj) {
  876. const StringC &str = *strObj;
  877. if (str.size() == 2
  878. && str[0] >= 'A' && str[0] <= 'Z'
  879. && str[1] >= 'A' && str[1] <= 'Z') {
  880. code = SP_LETTER2(str[0], str[1]);
  881. return 1;
  882. }
  883. if (str.size() == 0) {
  884. code = 0;
  885. return 1;
  886. }
  887. }
  888. else if (obj == makeFalse()) {
  889. code = 0;
  890. return 1;
  891. }
  892. invalidCharacteristicValue(ident, loc);
  893. return 0;
  894. }
  895. bool Interpreter::convertCharC(ELObj *obj, const Identifier *ident, const Location &loc,
  896. Char &result)
  897. {
  898. if (obj->charValue(result))
  899. return 1;
  900. const Char *s;
  901. size_t n;
  902. if (obj->stringData(s, n) && n == 1) {
  903. result = s[0];
  904. return 1;
  905. }
  906. invalidCharacteristicValue(ident, loc);
  907. return 0;
  908. }
  909. bool Interpreter::convertColorC(ELObj *obj, const Identifier *ident, const Location &loc, ColorObj *&color)
  910. {
  911. color = obj->asColor();
  912. if (color)
  913. return 1;
  914. invalidCharacteristicValue(ident, loc);
  915. return 0;
  916. }
  917. bool Interpreter::convertOptColorC(ELObj *obj, const Identifier *ident, const Location &loc, ColorObj *&color)
  918. {
  919. color = obj->asColor();
  920. if (color)
  921. return 1;
  922. if (obj == makeFalse())
  923. return 1;
  924. invalidCharacteristicValue(ident, loc);
  925. return 0;
  926. }
  927. bool Interpreter::convertRealC(ELObj *obj, const Identifier *ident, const Location &loc,
  928. double &result)
  929. {
  930. obj = convertFromString(obj, convertAllowNumber, loc);
  931. if (obj->realValue(result))
  932. return 1;
  933. invalidCharacteristicValue(ident, loc);
  934. return 0;
  935. }
  936. bool Interpreter::convertEnumC(ELObj *obj, const Identifier *ident, const Location &loc,
  937. FOTBuilder::Symbol &sym)
  938. {
  939. obj = convertFromString(obj, convertAllowSymbol|convertAllowBoolean, loc);
  940. if (obj == makeFalse()) {
  941. sym = FOTBuilder::symbolFalse;
  942. return 1;
  943. }
  944. SymbolObj *symObj = obj->asSymbol();
  945. if (symObj) {
  946. sym = symObj->cValue();
  947. if (sym != FOTBuilder::symbolFalse)
  948. return 1;
  949. }
  950. if (obj == makeTrue()) {
  951. sym = FOTBuilder::symbolTrue;
  952. return 1;
  953. }
  954. invalidCharacteristicValue(ident, loc);
  955. return 0;
  956. }
  957. bool Interpreter::convertEnumC(const FOTBuilder::Symbol *syms, size_t nSyms,
  958. ELObj *obj, const Identifier *ident, const Location &loc,
  959. FOTBuilder::Symbol &result)
  960. {
  961. obj = convertFromString(obj, convertAllowSymbol|convertAllowBoolean, loc);
  962. SymbolObj *symObj = obj->asSymbol();
  963. FOTBuilder::Symbol val;
  964. if (symObj) {
  965. val = symObj->cValue();
  966. if (val == FOTBuilder::symbolFalse) {
  967. invalidCharacteristicValue(ident, loc);
  968. return 0;
  969. }
  970. }
  971. else if (obj == makeFalse())
  972. val = FOTBuilder::symbolFalse;
  973. else if (obj == makeTrue())
  974. val = FOTBuilder::symbolTrue;
  975. else {
  976. invalidCharacteristicValue(ident, loc);
  977. return 0;
  978. }
  979. for (size_t i = 0; i < nSyms; i++)
  980. if (val == syms[i]) {
  981. result = val;
  982. return 1;
  983. }
  984. invalidCharacteristicValue(ident, loc);
  985. return 0;
  986. }
  987. void Interpreter::invalidCharacteristicValue(const Identifier *ident, const Location &loc)
  988. {
  989. setNextLocation(loc);
  990. message(InterpreterMessages::invalidCharacteristicValue,
  991. StringMessageArg(ident->name()));
  992. }
  993. static
  994. bool equal(const Char *s1, const char *s2, size_t n)
  995. {
  996. while (n > 0) {
  997. if (*s1++ != (unsigned char)*s2++)
  998. return 0;
  999. --n;
  1000. }
  1001. return 1;
  1002. }
  1003. ELObj *Interpreter::convertFromString(ELObj *obj, unsigned hints, const Location &loc)
  1004. {
  1005. // FIXME fold to lower case
  1006. const Char *s;
  1007. size_t n;
  1008. if (!dsssl2() || !obj->stringData(s, n))
  1009. return obj;
  1010. if (hints & convertAllowNumber) {
  1011. ELObj *tem = convertNumber(StringC(s, n));
  1012. if (tem)
  1013. return tem->resolveQuantities(1, *this, loc);
  1014. }
  1015. if (hints & convertAllowSymbol) {
  1016. StringC tem(s, n);
  1017. SymbolObj *sym = symbolTable_.lookup(tem);
  1018. if (sym && sym->cValue() != FOTBuilder::symbolFalse)
  1019. return sym;
  1020. }
  1021. if (hints & convertAllowBoolean) {
  1022. switch (n) {
  1023. case 2:
  1024. if (equal(s, "no", n))
  1025. return makeFalse();
  1026. break;
  1027. case 3:
  1028. if (equal(s, "yes", n))
  1029. return makeTrue();
  1030. break;
  1031. case 4:
  1032. if (equal(s, "true", n))
  1033. return makeTrue();
  1034. break;
  1035. case 5:
  1036. if (equal(s, "false", n))
  1037. return makeFalse();
  1038. break;
  1039. }
  1040. }
  1041. return obj;
  1042. }
  1043. ELObj *Interpreter::convertNumber(const StringC &str, int radix)
  1044. {
  1045. {
  1046. if (str.size() == 0)
  1047. return 0;
  1048. size_t i = 0;
  1049. if (str[0] == '#') {
  1050. if (str.size() < 2)
  1051. return 0;
  1052. switch (str[1]) {
  1053. case 'd':
  1054. radix = 10;
  1055. break;
  1056. case 'x':
  1057. radix = 16;
  1058. break;
  1059. case 'o':
  1060. radix = 8;
  1061. break;
  1062. case 'b':
  1063. radix = 2;
  1064. break;
  1065. default:
  1066. return 0;
  1067. }
  1068. i += 2;
  1069. }
  1070. if (i >= str.size())
  1071. return 0;
  1072. bool negative;
  1073. if (str[i] == '-') {
  1074. negative = 1;
  1075. i++;
  1076. }
  1077. else {
  1078. negative = 0;
  1079. if (str[i] == '+')
  1080. i++;
  1081. }
  1082. bool hadDecimalPoint = 0;
  1083. bool hadDigit = 0;
  1084. long n = 0;
  1085. int exp = 0;
  1086. for (; i < str.size(); i++) {
  1087. Char c = str[i];
  1088. int weight;
  1089. switch (c) {
  1090. case '0':
  1091. weight = 0;
  1092. break;
  1093. case '1':
  1094. weight = 1;
  1095. break;
  1096. case '2':
  1097. weight = 2;
  1098. break;
  1099. case '3':
  1100. weight = 3;
  1101. break;
  1102. case '4':
  1103. weight = 4;
  1104. break;
  1105. case '5':
  1106. weight = 5;
  1107. break;
  1108. case '6':
  1109. weight = 6;
  1110. break;
  1111. case '7':
  1112. weight = 7;
  1113. break;
  1114. case '8':
  1115. weight = 8;
  1116. break;
  1117. case '9':
  1118. weight = 9;
  1119. break;
  1120. case 'a':
  1121. weight = 10;
  1122. break;
  1123. case 'b':
  1124. weight = 11;
  1125. break;
  1126. case 'c':
  1127. weight = 12;
  1128. break;
  1129. case 'd':
  1130. weight = 13;
  1131. break;
  1132. case 'e':
  1133. weight = 14;
  1134. break;
  1135. case 'f':
  1136. weight = 15;
  1137. break;
  1138. default:
  1139. weight = -1;
  1140. break;
  1141. }
  1142. if (weight >= 0 && weight < radix) {
  1143. hadDigit = 1;
  1144. if (negative) {
  1145. if (-(unsigned long)n > (-(unsigned long)LONG_MIN - weight)/radix) {
  1146. if (radix != 10)
  1147. return 0;
  1148. return convertNumberFloat(str);
  1149. }
  1150. else
  1151. n = n*radix - weight;
  1152. }
  1153. else {
  1154. if (n > (LONG_MAX - weight)/radix) {
  1155. if (radix != 10)
  1156. return 0;
  1157. return convertNumberFloat(str);
  1158. }
  1159. else
  1160. n = n*radix + weight;
  1161. }
  1162. if (hadDecimalPoint)
  1163. exp--;
  1164. }
  1165. else if (c == '.' && radix == 10) {
  1166. if (hadDecimalPoint)
  1167. return 0;
  1168. hadDecimalPoint = 1;
  1169. }
  1170. else
  1171. break;
  1172. }
  1173. if (!hadDigit || (radix != 10 && i < str.size()))
  1174. return 0;
  1175. if (i + 1 < str.size() && str[i] == 'e'
  1176. && lexCategory(str[i + 1]) != lexLetter) {
  1177. hadDecimalPoint = 1;
  1178. i++;
  1179. int e;
  1180. if (!scanSignDigits(str, i, e))
  1181. return 0;
  1182. exp += e;
  1183. }
  1184. if (i < str.size()) {
  1185. int unitExp;
  1186. Unit *unit = scanUnit(str, i, unitExp);
  1187. if (!unit)
  1188. return 0;
  1189. if (unitExp == 1)
  1190. return new (*this) UnresolvedLengthObj(n, exp, unit);
  1191. else
  1192. return convertNumberFloat(str);
  1193. }
  1194. if (hadDecimalPoint)
  1195. return convertNumberFloat(str);
  1196. return makeInteger(n);
  1197. }
  1198. }
  1199. bool Interpreter::scanSignDigits(const StringC &str, size_t &i, int &n)
  1200. {
  1201. bool negative = 0;
  1202. if (i < str.size()) {
  1203. if (str[i] == '-') {
  1204. i++;
  1205. negative = 1;
  1206. } else if (str[i] == '+')
  1207. i++;
  1208. }
  1209. size_t j = i;
  1210. n = 0;
  1211. while (i < str.size()
  1212. && ('0' <= str[i] && str[i] <= '9')) {
  1213. if (negative)
  1214. n = n*10 - (str[i] - '0');
  1215. else
  1216. n = n*10 + (str[i] - '0');
  1217. i++;
  1218. }
  1219. if (i == j)
  1220. return 0;
  1221. return 1;
  1222. }
  1223. ELObj *Interpreter::convertNumberFloat(const StringC &str)
  1224. {
  1225. String<char> buf;
  1226. // omit an optional radix prefix
  1227. size_t i0 = 0;
  1228. if (str.size() > 1 && str[0] == '#' && str[1] == 'd')
  1229. i0 = 2;
  1230. for (size_t i = i0; i < str.size(); i++) {
  1231. if (str[i] > CHAR_MAX || str[i] == '\0')
  1232. return 0;
  1233. // 'E' is a valid exponent marker for C but not us
  1234. if (str[i] == 'E')
  1235. break;
  1236. buf += char(str[i]);
  1237. }
  1238. buf += '\0';
  1239. const char *endPtr;
  1240. double val = strtod((char *)buf.data(), (char **)&endPtr);
  1241. if (endPtr - buf.data() == str.size() - i0)
  1242. return new (*this) RealObj(val);
  1243. if (endPtr == buf.data())
  1244. return 0;
  1245. int unitExp;
  1246. Unit *unit = scanUnit(str, endPtr - buf.data(), unitExp);
  1247. if (!unit)
  1248. return 0;
  1249. return new (*this) UnresolvedQuantityObj(val, unit, unitExp);
  1250. }
  1251. // Return 0 for error.
  1252. Unit *Interpreter::scanUnit(const StringC &str, size_t i, int &unitExp)
  1253. {
  1254. StringC unitName;
  1255. while (i < str.size()) {
  1256. if (str[i] == '-' || str[i] == '+' || ('0' <= str[i] && str[i] <= '9'))
  1257. break;
  1258. unitName += str[i++];
  1259. }
  1260. if (i >= str.size())
  1261. unitExp = 1;
  1262. else {
  1263. unitExp = 0;
  1264. bool neg = 0;
  1265. if (str[i] == '-' || str[i] == '+') {
  1266. if (str[i] == '-')
  1267. neg = 1;
  1268. i++;
  1269. if (i >= str.size())
  1270. return 0;
  1271. }
  1272. while (i < str.size()) {
  1273. if (str[i] < '0' || str[i] > '9')
  1274. return 0;
  1275. unitExp *= 10;
  1276. if (neg)
  1277. unitExp -= (str[i] - '0');
  1278. else
  1279. unitExp += (str[i] - '0');
  1280. i++;
  1281. }
  1282. }
  1283. return lookupUnit(unitName);
  1284. }
  1285. void Interpreter::setNodeLocation(const NodePtr &nd)
  1286. {
  1287. const LocNode *lnp;
  1288. Location nodeLoc;
  1289. if ((lnp = LocNode::convert(nd)) != 0
  1290. && lnp->getLocation(nodeLoc) == accessOK)
  1291. setNextLocation(nodeLoc);
  1292. }
  1293. bool Interpreter::convertToPattern(ELObj *obj, const Location &loc, Pattern &pattern)
  1294. {
  1295. IList<Pattern::Element> list;
  1296. if (!convertToPattern(obj, loc, 0, list))
  1297. return 0;
  1298. Pattern tem(list);
  1299. tem.swap(pattern);
  1300. return 1;
  1301. }
  1302. bool Interpreter::convertToPattern(ELObj *obj, const Location &loc,
  1303. bool isChild,
  1304. IList<Pattern::Element> &list)
  1305. {
  1306. StringObj *str = obj->convertToString();
  1307. if (str) {
  1308. const Char *s;
  1309. size_t n;
  1310. str->stringData(s, n);
  1311. if (!n) {
  1312. setNextLocation(loc);
  1313. message(InterpreterMessages::patternEmptyGi);
  1314. return 0;
  1315. }
  1316. list.insert(new Pattern::Element(StringC(s, n)));
  1317. return 1;
  1318. }
  1319. if (obj == makeTrue()) {
  1320. list.insert(new Pattern::Element(StringC()));
  1321. return 1;
  1322. }
  1323. Pattern::Element *curElement = 0;
  1324. while (!obj->isNil()) {
  1325. PairObj *pair = obj->asPair();
  1326. if (!pair) {
  1327. setNextLocation(loc);
  1328. message(InterpreterMessages::patternNotList);
  1329. return 0;
  1330. }
  1331. ELObj *head = pair->car();
  1332. obj = pair->cdr();
  1333. if (head == makeTrue() && dsssl2()) {
  1334. list.insert(curElement = new Pattern::Element(StringC()));
  1335. continue;
  1336. }
  1337. str = head->convertToString();
  1338. if (str) {
  1339. const Char *s;
  1340. size_t n;
  1341. str->stringData(s, n);
  1342. if (!n) {
  1343. setNextLocation(loc);
  1344. message(InterpreterMessages::patternEmptyGi);
  1345. return 0;
  1346. }
  1347. list.insert(curElement = new Pattern::Element(StringC(s, n)));
  1348. continue;
  1349. }
  1350. if (!curElement) {
  1351. setNextLocation(loc);
  1352. message(InterpreterMessages::patternBadGi,
  1353. ELObjMessageArg(head, *this));
  1354. return 0;
  1355. }
  1356. if (head->isNil())
  1357. continue; // empty attribute list
  1358. if (head->asPair()) {
  1359. if (!patternAddAttributeQualifiers(head, loc, *curElement)) {
  1360. setNextLocation(loc);
  1361. message(InterpreterMessages::patternBadAttributeQualifier);
  1362. return 0;
  1363. }
  1364. continue;
  1365. }
  1366. KeywordObj *key = dsssl2() ? head->asKeyword() : 0;
  1367. if (!key) {
  1368. setNextLocation(loc);
  1369. message(InterpreterMessages::patternBadMember,
  1370. ELObjMessageArg(head, *this));
  1371. return 0;
  1372. }
  1373. pair = obj->asPair();
  1374. if (!pair) {
  1375. setNextLocation(loc);
  1376. message(obj->isNil()
  1377. ? InterpreterMessages::patternMissingQualifierValue
  1378. : InterpreterMessages::patternNotList);
  1379. return 0;
  1380. }
  1381. ELObj *value = pair->car();
  1382. obj = pair->cdr();
  1383. Identifier::SyntacticKey k;
  1384. if (!key->identifier()->syntacticKey(k)) {
  1385. setNextLocation(loc);
  1386. message(InterpreterMessages::patternUnknownQualifier,
  1387. StringMessageArg(key->identifier()->name()));
  1388. return 0;
  1389. }
  1390. switch (k) {
  1391. case Identifier::keyAttributes:
  1392. if (!patternAddAttributeQualifiers(value, loc, *curElement)) {
  1393. setNextLocation(loc);
  1394. message(InterpreterMessages::patternBadAttributeQualifier);
  1395. return 0;
  1396. }
  1397. break;
  1398. case Identifier::keyChildren:
  1399. {
  1400. IList<Pattern::Element> children;
  1401. if (!convertToPattern(value, loc, 1, children))
  1402. return 0;
  1403. if (!children.empty())
  1404. curElement->addQualifier(new Pattern::ChildrenQualifier(children));
  1405. }
  1406. break;
  1407. case Identifier::keyRepeat:
  1408. {
  1409. if (isChild) {
  1410. setNextLocation(loc);
  1411. message(InterpreterMessages::patternChildRepeat);
  1412. return 0;
  1413. }
  1414. SymbolObj *sym = value->asSymbol();
  1415. if (sym) {
  1416. const StringC &str = *sym->name();
  1417. if (str.size() == 1) {
  1418. switch (str[0]) {
  1419. case '*':
  1420. curElement->setRepeat(0, Pattern::Repeat(-1));
  1421. value = 0;
  1422. break;
  1423. case '?':
  1424. curElement->setRepeat(0, 1);
  1425. value = 0;
  1426. break;
  1427. case '+':
  1428. curElement->setRepeat(1, Pattern::Repeat(-1));
  1429. value = 0;
  1430. break;
  1431. default:
  1432. break;
  1433. }
  1434. }
  1435. }
  1436. if (value) {
  1437. setNextLocation(loc);
  1438. message(InterpreterMessages::patternBadQualifierValue,
  1439. ELObjMessageArg(value, *this),
  1440. StringMessageArg(key->identifier()->name()));
  1441. return 0;
  1442. }
  1443. }
  1444. break;
  1445. case Identifier::keyPosition:
  1446. {
  1447. SymbolObj *sym = value->asSymbol();
  1448. if (sym) {
  1449. Pattern::Qualifier *qual = 0;
  1450. const StringC &str = *sym->name();
  1451. if (str == "first-of-type")
  1452. qual = new Pattern::FirstOfTypeQualifier;
  1453. else if (str == "last-of-type")
  1454. qual = new Pattern::LastOfTypeQualifier;
  1455. else if (str == "first-of-any")
  1456. qual = new Pattern::FirstOfAnyQualifier;
  1457. else if (str == "last-of-any")
  1458. qual = new Pattern::LastOfAnyQualifier;
  1459. if (qual) {
  1460. curElement->addQualifier(qual);
  1461. break;
  1462. }
  1463. }
  1464. setNextLocation(loc);
  1465. message(InterpreterMessages::patternBadQualifierValue,
  1466. ELObjMessageArg(value, *this),
  1467. StringMessageArg(key->identifier()->name()));
  1468. return 0;
  1469. }
  1470. case Identifier::keyOnly:
  1471. {
  1472. SymbolObj *sym = value->asSymbol();
  1473. if (sym) {
  1474. Pattern::Qualifier *qual = 0;
  1475. const StringC &str = *sym->name();
  1476. if (str == "of-type")
  1477. qual = new Pattern::OnlyOfTypeQualifier;
  1478. else if (str == "of-any")
  1479. qual = new Pattern::OnlyOfAnyQualifier;
  1480. if (qual) {
  1481. curElement->addQualifier(qual);
  1482. break;
  1483. }
  1484. }
  1485. setNextLocation(loc);
  1486. message(InterpreterMessages::patternBadQualifierValue,
  1487. ELObjMessageArg(value, *this),
  1488. StringMessageArg(key->identifier()->name()));
  1489. return 0;
  1490. }
  1491. break;
  1492. case Identifier::keyId:
  1493. {
  1494. StringObj *str = value->convertToString();
  1495. if (!str) {
  1496. setNextLocation(loc);
  1497. message(InterpreterMessages::patternBadQualifierValue,
  1498. ELObjMessageArg(value, *this),
  1499. StringMessageArg(key->identifier()->name()));
  1500. return 0;
  1501. }
  1502. const Char *s;
  1503. size_t n;
  1504. str->stringData(s, n);
  1505. curElement->addQualifier(new Pattern::IdQualifier(StringC(s, n)));
  1506. }
  1507. break;
  1508. case Identifier::keyClass:
  1509. {
  1510. StringObj *str = value->convertToString();
  1511. if (!str) {
  1512. setNextLocation(loc);
  1513. message(InterpreterMessages::patternBadQualifierValue,
  1514. ELObjMessageArg(value, *this),
  1515. StringMessageArg(key->identifier()->name()));
  1516. return 0;
  1517. }
  1518. const Char *s;
  1519. size_t n;
  1520. str->stringData(s, n);
  1521. curElement->addQualifier(new Pattern::ClassQualifier(StringC(s, n)));
  1522. }
  1523. break;
  1524. case Identifier::keyImportance:
  1525. {
  1526. long n;
  1527. if (!value->exactIntegerValue(n)) {
  1528. setNextLocation(loc);
  1529. message(InterpreterMessages::patternBadQualifierValue,
  1530. ELObjMessageArg(value, *this),
  1531. StringMessageArg(key->identifier()->name()));
  1532. return 0;
  1533. }
  1534. curElement->addQualifier(new Pattern::ImportanceQualifier(n));
  1535. }
  1536. break;
  1537. case Identifier::keyPriority:
  1538. {
  1539. long n;
  1540. if (!value->exactIntegerValue(n)) {
  1541. setNextLocation(loc);
  1542. message(InterpreterMessages::patternBadQualifierValue,
  1543. ELObjMessageArg(value, *this),
  1544. StringMessageArg(key->identifier()->name()));
  1545. return 0;
  1546. }
  1547. curElement->addQualifier(new Pattern::PriorityQualifier(n));
  1548. }
  1549. break;
  1550. default:
  1551. setNextLocation(loc);
  1552. message(InterpreterMessages::patternUnknownQualifier,
  1553. StringMessageArg(key->identifier()->name()));
  1554. return 0;
  1555. }
  1556. }
  1557. return 1;
  1558. }
  1559. bool Interpreter::patternAddAttributeQualifiers(ELObj *obj,
  1560. const Location &loc,
  1561. Pattern::Element &elem)
  1562. {
  1563. while (!obj->isNil()) {
  1564. PairObj *pair = obj->asPair();
  1565. if (!pair)
  1566. return 0;
  1567. StringObj *tem = pair->car()->convertToString();
  1568. if (!tem)
  1569. return 0;
  1570. const Char *s;
  1571. size_t n;
  1572. tem->stringData(s, n);
  1573. if (n == 0)
  1574. return 0;
  1575. StringC name(s, n);
  1576. obj = pair->cdr();
  1577. pair = obj->asPair();
  1578. if (!pair)
  1579. return 0;
  1580. obj = pair->cdr();
  1581. if (pair->car() == makeFalse() && dsssl2())
  1582. elem.addQualifier(new Pattern::AttributeMissingValueQualifier(name));
  1583. else if (pair->car() == makeTrue() && dsssl2())
  1584. elem.addQualifier(new Pattern::AttributeHasValueQualifier(name));
  1585. else {
  1586. tem = pair->car()->convertToString();
  1587. if (!tem)
  1588. return 0;
  1589. tem->stringData(s, n);
  1590. elem.addQualifier(new Pattern::AttributeQualifier(name, StringC(s, n)));
  1591. }
  1592. }
  1593. return 1;
  1594. }
  1595. void Interpreter::dispatchMessage(Message &msg)
  1596. {
  1597. messenger_->dispatchMessage(msg);
  1598. }
  1599. void Interpreter::dispatchMessage(const Message &msg)
  1600. {
  1601. messenger_->dispatchMessage(msg);
  1602. }
  1603. Interpreter::StringSet::StringSet()
  1604. {
  1605. }
  1606. const char *Interpreter::StringSet::store(String<char> &str)
  1607. {
  1608. str += '\0';
  1609. const String<char> *p = table_.lookup(str);
  1610. if (!p) {
  1611. String<char> *tem = new String<char>;
  1612. str.swap(*tem);
  1613. table_.insert(tem);
  1614. p = tem;
  1615. }
  1616. return p->data();
  1617. }
  1618. unsigned long Interpreter::StringSet::hash(const String<char> &str)
  1619. {
  1620. const char *p = str.data();
  1621. unsigned long h = 0;
  1622. for (size_t n = str.size(); n > 0; n--)
  1623. h = (h << 5) + h + (unsigned char)*p++; // from Chris Torek
  1624. return h;
  1625. }
  1626. Identifier::Identifier(const StringC &name)
  1627. : Named(name), value_(0), syntacticKey_(notKey), beingComputed_(0), flowObj_(0)
  1628. {
  1629. }
  1630. void Identifier::setDefinition(Owner<Expression> &expr,
  1631. unsigned part,
  1632. const Location &loc)
  1633. {
  1634. def_.swap(expr);
  1635. defPart_ = part;
  1636. defLoc_ = loc;
  1637. value_ = 0;
  1638. }
  1639. void Identifier::setValue(ELObj *value, unsigned partIndex)
  1640. {
  1641. value_ = value;
  1642. // Built in functions have lowest priority.
  1643. defPart_ = partIndex;
  1644. }
  1645. bool Identifier::defined(unsigned &part, Location &loc) const
  1646. {
  1647. if (!def_ && !value_)
  1648. return 0;
  1649. part = defPart_;
  1650. loc = defLoc_;
  1651. return 1;
  1652. }
  1653. ELObj *Identifier::computeValue(bool force, Interpreter &interp) const
  1654. {
  1655. if (value_)
  1656. return value_;
  1657. ASSERT(def_);
  1658. if (beingComputed_) {
  1659. if (force) {
  1660. interp.setNextLocation(defLoc_);
  1661. interp.message(InterpreterMessages::identifierLoop,
  1662. StringMessageArg(name()));
  1663. ((Identifier *)this)->value_ = interp.makeError();
  1664. }
  1665. }
  1666. else {
  1667. ((Identifier *)this)->beingComputed_ = 1;
  1668. if (insn_.isNull())
  1669. ((Identifier *)this)->insn_
  1670. = Expression::optimizeCompile(((Identifier *)this)->def_, interp,
  1671. Environment(), 0, InsnPtr());
  1672. if (force || def_->canEval(0)) {
  1673. VM vm(interp);
  1674. ELObj *v = vm.eval(insn_.pointer());
  1675. interp.makePermanent(v);
  1676. ((Identifier *)this)->value_ = v;
  1677. }
  1678. ((Identifier *)this)->beingComputed_ = 0;
  1679. }
  1680. return value_;
  1681. }
  1682. Unit::Unit(const StringC &name)
  1683. : Named(name), computed_(notComputed)
  1684. {
  1685. }
  1686. bool Unit::defined(unsigned &part, Location &loc) const
  1687. {
  1688. if (!def_ && computed_ == notComputed)
  1689. return 0;
  1690. part = defPart_;
  1691. loc = defLoc_;
  1692. return 1;
  1693. }
  1694. void Unit::setDefinition(Owner<Expression> &expr,
  1695. unsigned part,
  1696. const Location &loc)
  1697. {
  1698. def_.swap(expr);
  1699. defPart_ = part;
  1700. defLoc_ = loc;
  1701. computed_ = notComputed;
  1702. }
  1703. void Unit::setValue(long n)
  1704. {
  1705. computed_ = computedExact;
  1706. exact_ = n;
  1707. dim_ = 1;
  1708. defPart_ = unsigned(-1);
  1709. }
  1710. void Unit::setValue(double n)
  1711. {
  1712. computed_ = computedInexact;
  1713. inexact_ = n;
  1714. dim_ = 1;
  1715. defPart_ = unsigned(-1);
  1716. }
  1717. void Unit::tryCompute(bool force, Interpreter &interp)
  1718. {
  1719. if (computed_ == notComputed) {
  1720. computed_ = beingComputed;
  1721. if (insn_.isNull())
  1722. insn_ = Expression::optimizeCompile(def_, interp, Environment(), 0, InsnPtr());
  1723. if (force || def_->canEval(0)) {
  1724. VM vm(interp);
  1725. ELObj *v = vm.eval(insn_.pointer());
  1726. switch (v->quantityValue(exact_, inexact_, dim_)) {
  1727. case ELObj::noQuantity:
  1728. if (!interp.isError(v)) {
  1729. interp.setNextLocation(defLoc_);
  1730. interp.message(InterpreterMessages::badUnitDefinition,
  1731. StringMessageArg(name()));
  1732. }
  1733. computed_ = computedError;
  1734. break;
  1735. case ELObj::longQuantity:
  1736. computed_ = computedExact;
  1737. break;
  1738. case ELObj::doubleQuantity:
  1739. computed_ = computedInexact;
  1740. break;
  1741. default:
  1742. CANNOT_HAPPEN();
  1743. }
  1744. }
  1745. if (computed_ == beingComputed)
  1746. computed_ = notComputed;
  1747. }
  1748. else if (computed_ == beingComputed) {
  1749. interp.setNextLocation(defLoc_);
  1750. interp.message(InterpreterMessages::unitLoop,
  1751. StringMessageArg(name()));
  1752. computed_ = computedError;
  1753. }
  1754. }
  1755. // multiply by 10^valExp
  1756. // quantity has exponent of 1
  1757. ELObj *Unit::resolveQuantity(bool force, Interpreter &interp,
  1758. long val, int valExp)
  1759. {
  1760. tryCompute(force, interp);
  1761. long result;
  1762. if (computed_ == computedExact && scale(val, valExp, exact_, result))
  1763. return new (interp) LengthObj(result);
  1764. double x = val;
  1765. while (valExp > 0) {
  1766. x *= 10.0;
  1767. valExp--;
  1768. }
  1769. while (valExp < 0) {
  1770. x /= 10.0;
  1771. valExp++;
  1772. }
  1773. return resolveQuantity(force, interp, x, 1);
  1774. }
  1775. // val * 10^valExp * factor
  1776. // return 0 if it can't be done without overflow
  1777. bool Unit::scale(long val, int valExp, long factor, long &result)
  1778. {
  1779. if (factor <= 0)
  1780. return 0; // feeble
  1781. while (valExp > 0) {
  1782. if (factor > LONG_MAX/10)
  1783. return 0;
  1784. valExp--;
  1785. factor *= 10;
  1786. }
  1787. if (val >= 0) {
  1788. if (val > LONG_MAX/factor)
  1789. return 0;
  1790. }
  1791. else {
  1792. if (-(unsigned long)val > -(unsigned long)LONG_MIN/factor)
  1793. return 0;
  1794. }
  1795. result = val*factor;
  1796. while (valExp < 0) {
  1797. result /= 10;
  1798. valExp++;
  1799. }
  1800. return 1;
  1801. }
  1802. ELObj *Unit::resolveQuantity(bool force, Interpreter &interp,
  1803. double val, int unitExp)
  1804. {
  1805. tryCompute(force, interp);
  1806. double factor;
  1807. switch (computed_) {
  1808. case computedExact:
  1809. factor = exact_;
  1810. break;
  1811. case computedInexact:
  1812. factor = inexact_;
  1813. break;
  1814. case computedError:
  1815. return interp.makeError();
  1816. default:
  1817. return 0;
  1818. }
  1819. int resultDim = 0;
  1820. double resultVal = val;
  1821. while (unitExp > 0) {
  1822. resultDim += dim_;
  1823. resultVal *= factor;
  1824. unitExp--;
  1825. }
  1826. while (unitExp < 0) {
  1827. resultDim -= dim_;
  1828. resultVal /= factor;
  1829. unitExp++;
  1830. }
  1831. if (resultDim == 0)
  1832. return new (interp) RealObj(resultVal);
  1833. return new (interp) QuantityObj(resultVal, resultDim);
  1834. }
  1835. void ELObjDynamicRoot::trace(Collector &c) const
  1836. {
  1837. c.trace(obj_);
  1838. }
  1839. bool operator==(const StringC &s, const char *p)
  1840. {
  1841. for (size_t i = 0; i < s.size(); i++)
  1842. if (p[i] == '\0' || (unsigned char)p[i] != s[i])
  1843. return 0;
  1844. return p[s.size()] == '\0';
  1845. }
  1846. #ifdef DSSSL_NAMESPACE
  1847. }
  1848. #endif