PageRenderTime 93ms CodeModel.GetById 31ms RepoModel.GetById 1ms app.codeStats 1ms

/branches/jade_features/style/Interpreter.cxx

#
C++ | 2432 lines | 2248 code | 139 blank | 45 comment | 485 complexity | b1678ddc4ee8118c489da0a6b3d26688 MD5 | raw file
Possible License(s): LGPL-2.1, LGPL-2.0

Large files files are truncated, but you can click here to view the full file

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

Large files files are truncated, but you can click here to view the full file