PageRenderTime 93ms CodeModel.GetById 26ms RepoModel.GetById 0ms app.codeStats 1ms

/branches/jade_valid_fo/style/Interpreter.cxx

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

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