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

/tags/jade_RELEASE-1_3_3-pre1/style/Interpreter.cxx

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

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