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

/tags/jade_1_2/jade/style/Interpreter.cxx

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