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

/branches/jade_RELEASE-1_3/style/Interpreter.cxx

#
C++ | 2498 lines | 2288 code | 145 blank | 65 comment | 492 complexity | 0a6c125235f9fbb7a23494ad1dae22da MD5 | raw file
Possible License(s): LGPL-2.1, LGPL-2.0
  1. // Copyright (c) 1996 James Clark
  2. // See the file copying.txt for copying permission.
  3. //modificado Cristian Tornador Antolin 09-2003
  4. #include "stylelib.h"
  5. #include "Interpreter.h"
  6. #include "Insn.h"
  7. #include "InterpreterMessages.h"
  8. #include "LocNode.h"
  9. #include "Pattern.h"
  10. #include "MacroFlowObj.h"
  11. #include "ELObjMessageArg.h"
  12. #include "VM.h"
  13. #include "Owner.h"
  14. #include "SchemeParser.h"
  15. #include "macros.h"
  16. #include "InternalInputSource.h"
  17. #include <stdlib.h>
  18. #include "LangObj.h"
  19. #include "PageModelObj.h"
  20. #ifdef DSSSL_NAMESPACE
  21. namespace DSSSL_NAMESPACE {
  22. #endif
  23. const Char defaultChar = 0xfffd;
  24. static
  25. size_t maxObjSize()
  26. {
  27. static size_t sz[] = {
  28. sizeof(UnresolvedQuantityObj),
  29. sizeof(VarStyleObj),
  30. sizeof(OverriddenStyleObj),
  31. sizeof(MergeStyleObj),
  32. sizeof(DeviceRGBColorObj),
  33. sizeof(ColorSpaceObj),
  34. sizeof(PairObj),
  35. sizeof(QuantityObj),
  36. sizeof(GlyphIdObj),
  37. sizeof(NamedNodeListPtrNodeListObj),
  38. sizeof(ProcessNodeSosofoObj),
  39. sizeof(AppendSosofoObj),
  40. sizeof(SetNonInheritedCsSosofoObj),
  41. sizeof(LabelSosofoObj),
  42. sizeof(MacroFlowObj),
  43. sizeof(FlowObj) + sizeof(StringC), // for FormattingInstructionFlowObj
  44. sizeof(LangObj),
  45. sizeof(PageModelObj),
  46. #ifdef SP_HAVE_LOCALE
  47. #ifdef SP_HAVE_WCHAR
  48. sizeof(RefLangObj),
  49. #endif
  50. #endif
  51. };
  52. size_t n = sz[0];
  53. for (size_t i = 1; i < SIZEOF(sz); i++)
  54. if (sz[i] > n)
  55. n = sz[i];
  56. return n;
  57. }
  58. Interpreter::Interpreter(GroveManager *groveManager,
  59. Messenger *messenger,
  60. int unitsPerInch,
  61. bool debugMode,
  62. bool dsssl2,
  63. bool strictMode,
  64. const FOTBuilder::Extension *extensionTable)
  65. : groveManager_(groveManager),
  66. messenger_(messenger),
  67. extensionTable_(extensionTable),
  68. Collector(maxObjSize()),
  69. partIndex_(0), // 0 is for command-line definitions
  70. dPartIndex_(1),
  71. lexCategory_(lexOther),
  72. unitsPerInch_(unitsPerInch),
  73. nInheritedC_(0),
  74. initialProcessingMode_(StringC()),
  75. currentPartFirstInitialValue_(0),
  76. initialStyle_(0),
  77. nextGlyphSubstTableUniqueId_(0),
  78. debugMode_(debugMode),
  79. dsssl2_(dsssl2),
  80. strictMode_(strictMode)
  81. {
  82. makePermanent(theNilObj_ = new (*this) NilObj);
  83. makePermanent(theFalseObj_ = new (*this) FalseObj);
  84. makePermanent(theTrueObj_ = new (*this) TrueObj);
  85. makePermanent(theErrorObj_ = new (*this) ErrorObj);
  86. makePermanent(theUnspecifiedObj_ = new (*this) UnspecifiedObj);
  87. makePermanent(addressNoneObj_
  88. = new (*this) AddressObj(FOTBuilder::Address::none));
  89. makePermanent(pageModelNoneObj_
  90. = new (*this) PageModelObj);
  91. makePermanent(emptyNodeListObj_
  92. = new (*this) NodePtrNodeListObj);
  93. defaultLanguage_ = theFalseObj_;
  94. installSyntacticKeys();
  95. installCValueSymbols();
  96. installPortNames();
  97. installPrimitives();
  98. installUnits();
  99. if (!strictMode_) {
  100. installCharNames();
  101. installSdata();
  102. }
  103. installFlowObjs();
  104. installInheritedCs();
  105. installNodeProperties();
  106. static const char *lexCategories[] = {
  107. "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",
  108. "!$%&*/<=>?~_^:",
  109. "",
  110. "0123456789",
  111. "-+.",
  112. "",
  113. "();\"",
  114. " \t\r\n\f",
  115. "",
  116. };
  117. lexCategory_.setEe(lexDelimiter);
  118. for (size_t i = 0; i < SIZEOF(lexCategories); i++)
  119. for (const char *s = lexCategories[i]; *s; s++)
  120. lexCategory_.setChar(*s, i);
  121. // #',@[\\]`{|} are ASCII chars not mentioned above,
  122. // but I guess we don't want to allow any of these
  123. // in names (as most of them have special meaning in
  124. // scheme/dsssl).
  125. if (!strictMode_)
  126. for (Char i = 127; i < charMax; i++)
  127. lexCategory_.setChar(i, lexAddNameStart);
  128. initialProcessingMode_.setDefined();
  129. // can't be done before initializing lexCategory_
  130. installBuiltins();
  131. installCharProperties();
  132. }
  133. void Interpreter::compile()
  134. {
  135. // FIXME compile all definitions
  136. compileInitialValues();
  137. initialProcessingMode_.compile(*this);
  138. NamedTableIter<ProcessingMode> iter(processingModeTable_);
  139. for (;;) {
  140. ProcessingMode *mode = iter.next();
  141. if (!mode)
  142. break;
  143. mode->compile(*this);
  144. }
  145. compileCharProperties();
  146. compileDefaultLanguage();
  147. }
  148. void Interpreter::compileInitialValues()
  149. {
  150. Vector<ConstPtr<InheritedC> > ics;
  151. for (size_t i = 0; i < initialValueNames_.size(); i++) {
  152. const Identifier *ident = initialValueNames_[i];
  153. Owner<Expression> &expr = initialValueValues_[i];
  154. ConstPtr<InheritedC> ic(ident->inheritedC());
  155. expr->optimize(*this, Environment(), expr);
  156. ELObj *val = expr->constantValue();
  157. if (val) {
  158. ConstPtr<InheritedC> tem(ic->make(val, expr->location(), *this));
  159. if (!tem.isNull())
  160. ics.push_back(tem);
  161. }
  162. else
  163. ics.push_back(new VarInheritedC(ic,
  164. expr->compile(*this, Environment(), 0, InsnPtr()),
  165. expr->location()));
  166. }
  167. if (ics.size()) {
  168. Vector<ConstPtr<InheritedC> > forceIcs;
  169. initialStyle_ = new (*this) VarStyleObj(new StyleSpec(forceIcs, ics), 0, 0, NodePtr());
  170. makePermanent(initialStyle_);
  171. }
  172. }
  173. void Interpreter::installInitialValue(Identifier *ident, Owner<Expression> &expr)
  174. {
  175. for (size_t i = 0; i < initialValueNames_.size(); i++) {
  176. if (ident == initialValueNames_[i]) {
  177. if (i >= currentPartFirstInitialValue_) {
  178. setNextLocation(expr->location());
  179. message(InterpreterMessages::duplicateInitialValue,
  180. StringMessageArg(ident->name()),
  181. initialValueValues_[i]->location());
  182. }
  183. return;
  184. }
  185. }
  186. initialValueValues_.resize(initialValueValues_.size() + 1);
  187. expr.swap(initialValueValues_.back());
  188. initialValueNames_.push_back(ident);
  189. }
  190. void Interpreter::installUnits()
  191. {
  192. static struct {
  193. const char *name;
  194. int numer;
  195. int denom;
  196. bool dsssl2;
  197. } units[] = {
  198. { "m", 5000, 127 },
  199. { "cm", 50, 127 },
  200. { "mm", 5, 127 },
  201. { "in", 1, 1 },
  202. { "pt", 1, 72 },
  203. { "pica", 1, 6 },
  204. { "pc", 1, 6 } // a DSSSL2 addition
  205. };
  206. size_t nUnits = dsssl2() ? SIZEOF(units) : SIZEOF(units) - 1;
  207. for (size_t i = 0; i < nUnits; i++) {
  208. Unit *unit = lookupUnit(makeStringC(units[i].name));
  209. long n = unitsPerInch_ * units[i].numer;
  210. if (n % units[i].denom == 0)
  211. unit->setValue(long(n / units[i].denom));
  212. else
  213. unit->setValue(double(n)/units[i].denom);
  214. }
  215. }
  216. void Interpreter::installSyntacticKeys()
  217. {
  218. static struct {
  219. const char *name;
  220. Identifier::SyntacticKey key;
  221. } keys[] = {
  222. { "quote", Identifier::keyQuote },
  223. { "lambda", Identifier::keyLambda },
  224. { "if", Identifier::keyIf },
  225. { "cond", Identifier::keyCond },
  226. { "and", Identifier::keyAnd },
  227. { "or", Identifier::keyOr },
  228. { "case", Identifier::keyCase },
  229. { "let", Identifier::keyLet },
  230. { "let*", Identifier::keyLetStar },
  231. { "letrec", Identifier::keyLetrec },
  232. { "quasiquote", Identifier::keyQuasiquote },
  233. { "unquote", Identifier::keyUnquote },
  234. { "unquote-splicing", Identifier::keyUnquoteSplicing },
  235. { "define", Identifier::keyDefine },
  236. { "else", Identifier::keyElse },
  237. { "=>", Identifier::keyArrow },
  238. { "there-exists?", Identifier::keyThereExists },
  239. { "for-all?", Identifier::keyForAll },
  240. { "select-each", Identifier::keySelectEach },
  241. { "union-for-each", Identifier::keyUnionForEach },
  242. { "make", Identifier::keyMake },
  243. { "style", Identifier::keyStyle },
  244. { "with-mode", Identifier::keyWithMode },
  245. { "define-unit", Identifier::keyDefineUnit },
  246. { "query", Identifier::keyQuery },
  247. { "element", Identifier::keyElement },
  248. { "default", Identifier::keyDefault },
  249. { "root", Identifier::keyRoot },
  250. { "id", Identifier::keyId },
  251. { "mode", Identifier::keyMode },
  252. { "declare-initial-value", Identifier::keyDeclareInitialValue },
  253. { "declare-characteristic", Identifier::keyDeclareCharacteristic },
  254. { "declare-flow-object-class", Identifier::keyDeclareFlowObjectClass },
  255. { "declare-char-characteristic+property", Identifier::keyDeclareCharCharacteristicAndProperty },
  256. { "declare-reference-value-type", Identifier::keyDeclareReferenceValueType },
  257. { "declare-default-language", Identifier::keyDeclareDefaultLanguage },
  258. { "declare-char-property", Identifier::keyDeclareCharProperty },
  259. { "define-page-model", Identifier::keyDefinePageModel },
  260. { "define-column-set-model", Identifier::keyDefineColumnSetModel },
  261. { "define-language", Identifier::keyDefineLanguage },
  262. { "add-char-properties", Identifier::keyAddCharProperties },
  263. { "use", Identifier::keyUse },
  264. { "label", Identifier::keyLabel },
  265. { "content-map", Identifier::keyContentMap },
  266. { "keep-with-previous?", Identifier::keyIsKeepWithPrevious },
  267. { "keep-with-next?", Identifier::keyIsKeepWithNext },
  268. { "space-before", Identifier::keySpaceBefore },
  269. { "space-after", Identifier::keySpaceAfter },
  270. { "left-header", Identifier::keyLeftHeader },
  271. { "center-header", Identifier::keyCenterHeader },
  272. { "right-header", Identifier::keyRightHeader },
  273. { "left-footer", Identifier::keyLeftFooter },
  274. { "center-footer", Identifier::keyCenterFooter },
  275. { "right-footer", Identifier::keyRightFooter },
  276. { "destination", Identifier::keyDestination },
  277. { "type", Identifier::keyType },
  278. { "coalesce-id", Identifier::keyCoalesceId },
  279. { "display?", Identifier::keyIsDisplay },
  280. { "scale", Identifier::keyScale },
  281. { "max-width", Identifier::keyMaxWidth },
  282. { "max-height", Identifier::keyMaxHeight },
  283. { "entity-system-id", Identifier::keyEntitySystemId },
  284. { "notation-system-id", Identifier::keyNotationSystemId },
  285. { "position-point-x", Identifier::keyPositionPointX },
  286. { "position-point-y", Identifier::keyPositionPointY },
  287. { "escapement-direction", Identifier::keyEscapementDirection },
  288. { "break-before-priority", Identifier::keyBreakBeforePriority },
  289. { "break-after-priority", Identifier::keyBreakAfterPriority },
  290. { "orientation", Identifier::keyOrientation },
  291. { "length", Identifier::keyLength },
  292. { "char", Identifier::keyChar },
  293. { "glyph-id", Identifier::keyGlyphId },
  294. { "space?", Identifier::keyIsSpace },
  295. { "record-end?", Identifier::keyIsRecordEnd },
  296. { "input-tab?", Identifier::keyIsInputTab },
  297. { "input-whitespace?", Identifier::keyIsInputWhitespace },
  298. { "punct?", Identifier::keyIsPunct },
  299. { "drop-after-line-break?", Identifier::keyIsDropAfterLineBreak },
  300. { "drop-unless-before-line-break?", Identifier::keyIsDropUnlessBeforeLineBreak },
  301. { "math-class", Identifier::keyMathClass },
  302. { "math-font-posture", Identifier::keyMathFontPosture },
  303. { "script", Identifier::keyScript },
  304. { "stretch-factor", Identifier::keyStretchFactor },
  305. { "keep", Identifier::keyKeep },
  306. { "break-before", Identifier::keyBreakBefore },
  307. { "break-after", Identifier::keyBreakAfter },
  308. { "may-violate-keep-before?", Identifier::keyIsMayViolateKeepBefore },
  309. { "may-violate-keep-after?", Identifier::keyIsMayViolateKeepAfter },
  310. { "before-row-border", Identifier::keyBeforeRowBorder },
  311. { "after-row-border", Identifier::keyAfterRowBorder },
  312. { "before-column-border", Identifier::keyBeforeColumnBorder },
  313. { "after-column-border", Identifier::keyAfterColumnBorder },
  314. { "column-number", Identifier::keyColumnNumber },
  315. { "row-number", Identifier::keyRowNumber },
  316. { "n-columns-spanned", Identifier::keyNColumnsSpanned },
  317. { "n-rows-spanned", Identifier::keyNRowsSpanned },
  318. { "width", Identifier::keyWidth },
  319. { "starts-row?", Identifier::keyIsStartsRow },
  320. { "ends-row?", Identifier::keyIsEndsRow },
  321. { "table-width", Identifier::keyTableWidth },
  322. { "multi-modes", Identifier::keyMultiModes },
  323. { "data", Identifier::keyData },
  324. { "min", Identifier::keyMin },
  325. { "max", Identifier::keyMax },
  326. { "conditional?", Identifier::keyIsConditional },
  327. { "priority", Identifier::keyPriority },
  328. { "grid-n-rows", Identifier::keyGridNRows },
  329. { "grid-n-columns", Identifier::keyGridNColumns },
  330. { "radical", Identifier::keyRadical },
  331. { "null", Identifier::keyNull },
  332. { "rcs?", Identifier::keyIsRcs },
  333. { "parent", Identifier::keyParent },
  334. { "active", Identifier::keyActive },
  335. { "attributes", Identifier::keyAttributes },
  336. { "children", Identifier::keyChildren },
  337. { "repeat", Identifier::keyRepeat },
  338. { "position", Identifier::keyPosition },
  339. { "only", Identifier::keyOnly },
  340. { "class", Identifier::keyClass },
  341. { "importance", Identifier::keyImportance },
  342. { "position-preference", Identifier::keyPositionPreference },
  343. { "collate", Identifier::keyCollate },
  344. { "toupper", Identifier::keyToupper },
  345. { "tolower", Identifier::keyTolower },
  346. { "symbol", Identifier::keySymbol },
  347. { "order", Identifier::keyOrder },
  348. { "forward", Identifier::keyForward },
  349. { "backward", Identifier::keyBackward },
  350. { "white-point", Identifier::keyWhitePoint },
  351. { "black-point", Identifier::keyBlackPoint },
  352. { "range", Identifier::keyRange },
  353. { "range-abc", Identifier::keyRangeAbc },
  354. { "range-lmn", Identifier::keyRangeLmn },
  355. { "range-a", Identifier::keyRangeA },
  356. { "decode-abc", Identifier::keyDecodeAbc },
  357. { "decode-lmn", Identifier::keyDecodeLmn },
  358. { "decode-a", Identifier::keyDecodeA },
  359. { "matrix-abc", Identifier::keyMatrixAbc },
  360. { "matrix-lmn", Identifier::keyMatrixLmn },
  361. { "matrix-a", Identifier::keyMatrixA },
  362. { "architecture", Identifier::keyArchitecture },
  363. { "height", Identifier::keyHeight },
  364. { "contents-rotation", Identifier::keyContentsRotation },
  365. { "open", Identifier::keyOpen },
  366. { "close", Identifier::keyClose },
  367. { "mark", Identifier::keyMark },
  368. { "direction", Identifier::keyDirection },
  369. { "filling-direction", Identifier::keyFillingDirection },
  370. { "region", Identifier::keyRegion},
  371. { "x-origin", Identifier::keyXOrigin},
  372. { "y-origin", Identifier::keyYOrigin},
  373. { "header", Identifier::keyHeader},
  374. { "contents-alignment", Identifier::keyContentsalignment},
  375. { "footer", Identifier::keyFooter},
  376. }, keys2[] = {
  377. { "declare-class-attribute", Identifier::keyDeclareClassAttribute },
  378. { "declare-id-attribute", Identifier::keyDeclareIdAttribute },
  379. { "declare-flow-object-macro", Identifier::keyDeclareFlowObjectMacro },
  380. { "or-element", Identifier::keyOrElement },
  381. { "set!", Identifier::keySet },
  382. { "begin", Identifier::keyBegin },
  383. };
  384. for (size_t i = 0; i < SIZEOF(keys); i++) {
  385. StringC tem(makeStringC(keys[i].name));
  386. lookup(tem)->setSyntacticKey(keys[i].key);
  387. if (dsssl2() && tem[tem.size() - 1] == '?') {
  388. tem.resize(tem.size() - 1);
  389. lookup(tem)->setSyntacticKey(keys[i].key);
  390. }
  391. }
  392. if (dsssl2()) {
  393. for (size_t i = 0; i < SIZEOF(keys2); i++)
  394. lookup(makeStringC(keys2[i].name))->setSyntacticKey(keys2[i].key);
  395. }
  396. }
  397. void Interpreter::installCValueSymbols()
  398. {
  399. cValueSymbols_[0] = makeFalse();
  400. cValueSymbols_[1] = makeTrue();
  401. for (size_t i = 2; i < FOTBuilder::nSymbols; i++) {
  402. SymbolObj *sym = makeSymbol(makeStringC(FOTBuilder::symbolName(FOTBuilder::Symbol(i))));
  403. sym->setCValue(FOTBuilder::Symbol(i));
  404. cValueSymbols_[i] = sym;
  405. }
  406. }
  407. void Interpreter::installPortNames()
  408. {
  409. // These must match the order in SymbolObj.
  410. static const char *names[] = {
  411. "numerator",
  412. "denominator",
  413. "pre-sup",
  414. "pre-sub",
  415. "post-sup",
  416. "post-sub",
  417. "mid-sup",
  418. "mid-sub",
  419. "over-mark",
  420. "under-mark",
  421. "open",
  422. "close",
  423. "degree",
  424. "operator",
  425. "lower-limit",
  426. "upper-limit",
  427. "header",
  428. "footer"
  429. };
  430. ASSERT(SIZEOF(names) == nPortNames);
  431. for (size_t i = 0; i < SIZEOF(names); i++)
  432. portNames_[i] = makeSymbol(makeStringC(names[i]));
  433. }
  434. void Interpreter::installCharNames()
  435. {
  436. static struct {
  437. Char c;
  438. const char *name;
  439. } chars[] = {
  440. #include "charNames.h"
  441. };
  442. for (size_t i = 0; i < SIZEOF(chars); i++) {
  443. CharPart ch;
  444. ch.c = chars[i].c;
  445. ch.defPart = unsigned(-1);
  446. namedCharTable_.insert(makeStringC(chars[i].name), ch, 1);
  447. }
  448. }
  449. void Interpreter::installSdata()
  450. {
  451. // This comes from uni2sgml.txt on ftp://unicode.org.
  452. // It is marked there as obsolete, so it probably ought to be checked.
  453. // The definitions of apos and quot have been fixed for consistency with XML.
  454. static struct {
  455. Char c;
  456. const char *name;
  457. } entities[] = {
  458. #include "sdata.h"
  459. };
  460. for (size_t i = 0; i < SIZEOF(entities); i++) {
  461. CharPart ch;
  462. ch.c = entities[i].c;
  463. ch.defPart = unsigned(-1);
  464. sdataEntityNameTable_.insert(makeStringC(entities[i].name), ch, 1);
  465. }
  466. }
  467. void Interpreter::installNodeProperties()
  468. {
  469. for (int i = 0; i < ComponentName::nIds; i++) {
  470. ComponentName::Id id = ComponentName::Id(i);
  471. nodePropertyTable_.insert(makeStringC(ComponentName::rcsName(id)), i);
  472. nodePropertyTable_.insert(makeStringC(ComponentName::sdqlName(id)), i);
  473. }
  474. }
  475. void Interpreter::setCharRepertoire(const StringC &pubid)
  476. {
  477. if (pubid == "UNREGISTERED::OpenJade//Character Repertoire::OpenJade") {
  478. if (strictMode_) {
  479. installCharNames();
  480. installSdata();
  481. // This assumes that we process char-repertoire
  482. // declaration before any declarations which change
  483. // lexical categories.
  484. for (Char i = 127; i < charMax; i++)
  485. lexCategory_.setChar(i, lexAddNameStart);
  486. strictMode_ = 0;
  487. }
  488. } else
  489. message(InterpreterMessages::unsupportedCharRepertoire,
  490. StringMessageArg(pubid));
  491. }
  492. void Interpreter::addStandardChar(const StringC &name, const StringC &num)
  493. {
  494. int n;
  495. size_t i = 0;
  496. if (!scanSignDigits(num, i, n)) {
  497. message(InterpreterMessages::invalidCharNumber, StringMessageArg(num));
  498. return;
  499. }
  500. const CharPart *def = namedCharTable_.lookup(name);
  501. CharPart ch;
  502. ch.c = n;
  503. ch.defPart = dPartIndex_;
  504. if (def) {
  505. if (dPartIndex_ < def->defPart)
  506. namedCharTable_.insert(name, ch, 1);
  507. else if (def->defPart == dPartIndex_ && def->c != ch.c)
  508. message(InterpreterMessages::duplicateCharName,
  509. StringMessageArg(name));
  510. }
  511. else
  512. namedCharTable_.insert(name, ch, 1);
  513. }
  514. void Interpreter::addNameChar(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, lexAddNameStart);
  525. }
  526. void Interpreter::addSeparatorChar(const StringC &name)
  527. {
  528. const CharPart *cp = namedCharTable_.lookup(name);
  529. if (!cp)
  530. message(InterpreterMessages::badCharName,
  531. StringMessageArg(name));
  532. else if (lexCategory_[cp->c] != lexOther)
  533. // FIXME give a more specific error
  534. message(InterpreterMessages::badDeclaration);
  535. else
  536. lexCategory_.setChar(cp->c, lexAddWhiteSpace);
  537. }
  538. void Interpreter::addSdataEntity(const StringC &ename, const StringC &etext, const StringC &name)
  539. {
  540. const CharPart *cp = namedCharTable_.lookup(name);
  541. if (!cp) {
  542. message(InterpreterMessages::badCharName,
  543. StringMessageArg(name));
  544. return;
  545. }
  546. CharPart ch;
  547. ch.c = cp->c;
  548. ch.defPart = dPartIndex_;
  549. if (ename.size() > 0) {
  550. const CharPart *def = sdataEntityNameTable_.lookup(ename);
  551. if (def) {
  552. if (dPartIndex_ < def->defPart)
  553. sdataEntityNameTable_.insert(ename, ch);
  554. else if (def->defPart == dPartIndex_ && def->c != cp->c)
  555. message(InterpreterMessages::duplicateSdataEntityName,
  556. StringMessageArg(ename));
  557. }
  558. else
  559. sdataEntityNameTable_.insert(ename, ch);
  560. }
  561. if (etext.size() > 0) {
  562. const CharPart *def = sdataEntityTextTable_.lookup(etext);
  563. if (def) {
  564. if (dPartIndex_ < def->defPart)
  565. sdataEntityTextTable_.insert(etext, ch);
  566. else if (def->defPart == dPartIndex_ && def->c != cp->c)
  567. message(InterpreterMessages::duplicateSdataEntityText,
  568. StringMessageArg(etext));
  569. }
  570. else
  571. sdataEntityTextTable_.insert(etext, ch);
  572. }
  573. }
  574. bool Interpreter::sdataMap(GroveString name, GroveString text, GroveChar &c) const
  575. {
  576. StringC tem(name.data(), name.size());
  577. StringC tem2(text.data(), text.size());
  578. const CharPart *cp = sdataEntityNameTable_.lookup(tem);
  579. if (cp) {
  580. c = cp->c;
  581. return 1;
  582. }
  583. cp = sdataEntityTextTable_.lookup(tem2);
  584. if (cp) {
  585. c = cp->c;
  586. return 1;
  587. }
  588. if (convertUnicodeCharName(tem, c))
  589. return 1;
  590. // I think this is the best thing to do.
  591. // At least it makes preserve-sdata work with unknown SDATA entities.
  592. c = defaultChar;
  593. return 1;
  594. }
  595. ELObj *Interpreter::convertGlyphId(const Char *str, size_t len, const Location &loc)
  596. {
  597. unsigned long n = 0;
  598. const char *publicId = 0;
  599. for (size_t i = len; i > 1; --i) {
  600. if (str[i - 1] == ':' && str[i - 2] == ':' && i < len && str[i] != '0') {
  601. for (size_t j = i; j < len; j++)
  602. n = n*10 + (str[j] - '0');
  603. publicId = storePublicId(str, i - 2, loc);
  604. break;
  605. }
  606. if (str[i - 1] < '0' || str[i - 1] > '9')
  607. break;
  608. }
  609. if (!publicId)
  610. publicId = storePublicId(str, len, loc);
  611. return new (*this) GlyphIdObj(FOTBuilder::GlyphId(publicId, n));
  612. }
  613. bool Interpreter::convertCharName(const StringC &str, Char &c) const
  614. {
  615. const CharPart *cp = namedCharTable_.lookup(str);
  616. if (cp) {
  617. c = cp->c;
  618. return 1;
  619. }
  620. return convertUnicodeCharName(str, c);
  621. }
  622. bool Interpreter::convertUnicodeCharName(const StringC &str, Char &c)
  623. {
  624. if (str.size() != 6 || str[0] != 'U' || str[1] != '-')
  625. return 0;
  626. Char value = 0;
  627. for (int i = 2; i < 6; i++) {
  628. value <<= 4;
  629. switch (str[i]) {
  630. case '0':
  631. case '1':
  632. case '2':
  633. case '3':
  634. case '4':
  635. case '5':
  636. case '6':
  637. case '7':
  638. case '8':
  639. case '9':
  640. value |= str[i] - '0';
  641. break;
  642. case 'A':
  643. case 'B':
  644. case 'C':
  645. case 'D':
  646. case 'E':
  647. case 'F':
  648. value |= 10 + (str[i] - 'A');
  649. break;
  650. default:
  651. return 0;
  652. }
  653. }
  654. c = value;
  655. return 1;
  656. }
  657. SymbolObj *Interpreter::makeSymbol(const StringC &str)
  658. {
  659. SymbolObj *sym = symbolTable_.lookup(str);
  660. if (!sym) {
  661. StringObj *strObj = new (*this) StringObj(str);
  662. makePermanent(strObj);
  663. sym = new (*this) SymbolObj(strObj);
  664. makePermanent(sym);
  665. symbolTable_.insert(sym);
  666. }
  667. return sym;
  668. }
  669. Identifier *Interpreter::lookup(const StringC &str)
  670. {
  671. Identifier *ident = identTable_.lookup(str);
  672. if (!ident) {
  673. ident = new Identifier(str);
  674. identTable_.insert(ident);
  675. }
  676. return ident;
  677. }
  678. bool Interpreter::lookupNodeProperty(const StringC &str, ComponentName::Id &id)
  679. {
  680. const int *val = nodePropertyTable_.lookup(str);
  681. if (!val) {
  682. StringC tem(str);
  683. for (size_t i = 0; i < tem.size(); i++) {
  684. if (tem[i] >= 'A' && tem[i] <= 'Z')
  685. tem[i] = 'a' + (tem[i] - 'A');
  686. }
  687. val = nodePropertyTable_.lookup(tem);
  688. if (!val)
  689. return 0;
  690. }
  691. id = ComponentName::Id(*val);
  692. return 1;
  693. }
  694. Unit *Interpreter::lookupUnit(const StringC &str)
  695. {
  696. Unit *unit = unitTable_.lookup(str);
  697. if (!unit) {
  698. unit = new Unit(str);
  699. unitTable_.insert(unit);
  700. }
  701. return unit;
  702. }
  703. ProcessingMode *Interpreter::lookupProcessingMode(const StringC &str)
  704. {
  705. ProcessingMode *mode = processingModeTable_.lookup(str);
  706. if (!mode) {
  707. mode = new ProcessingMode(str, &initialProcessingMode_);
  708. processingModeTable_.insert(mode);
  709. }
  710. return mode;
  711. }
  712. StringC Interpreter::makeStringC(const char *s)
  713. {
  714. StringC tem;
  715. if (s)
  716. while (*s)
  717. tem += (unsigned char)*s++;
  718. return tem;
  719. }
  720. void Interpreter::endPart()
  721. {
  722. currentPartFirstInitialValue_ = initialValueNames_.size();
  723. partIndex_++;
  724. }
  725. void Interpreter::dEndPart()
  726. {
  727. dPartIndex_++;
  728. }
  729. void Interpreter::normalizeGeneralName(const NodePtr &nd, StringC &str)
  730. {
  731. NamedNodeListPtr nnl;
  732. NodePtr root;
  733. if (nd->getGroveRoot(root) == accessOK
  734. && root->getElements(nnl) == accessOK)
  735. str.resize(nnl->normalize(str.begin(), str.size()));
  736. }
  737. ELObj *Interpreter::makeLengthSpec(const FOTBuilder::LengthSpec &ls)
  738. {
  739. if (ls.displaySizeFactor != 0.0) {
  740. LengthSpec result(LengthSpec::displaySize, ls.displaySizeFactor);
  741. result += double(ls.length);
  742. return new (*this) LengthSpecObj(result);
  743. }
  744. else
  745. return new (*this) LengthObj(ls.length);
  746. }
  747. bool Interpreter::convertBooleanC(ELObj *obj, const Identifier *ident, const Location &loc,
  748. bool &result)
  749. {
  750. obj = convertFromString(obj, convertAllowBoolean, loc);
  751. if (obj == makeFalse()) {
  752. result = 0;
  753. return 1;
  754. }
  755. if (obj == makeTrue()) {
  756. result = 1;
  757. return 1;
  758. }
  759. invalidCharacteristicValue(ident, loc);
  760. return 0;
  761. }
  762. bool Interpreter::convertPublicIdC(ELObj *obj, const Identifier *ident,
  763. const Location &loc,
  764. FOTBuilder::PublicId &pubid)
  765. {
  766. if (obj == makeFalse()) {
  767. pubid = 0;
  768. return 1;
  769. }
  770. const Char *s;
  771. size_t n;
  772. if (obj->stringData(s, n)) {
  773. if (n == 0)
  774. pubid = 0;
  775. else
  776. pubid = storePublicId(s, n, loc);
  777. return 1;
  778. }
  779. invalidCharacteristicValue(ident, loc);
  780. return 0;
  781. }
  782. const char *Interpreter::storePublicId(const Char *s, size_t n, const Location &loc)
  783. {
  784. String<char> buf;
  785. for (; n > 0; s++, n--) {
  786. if (*s >= 128) {
  787. setNextLocation(loc);
  788. message(InterpreterMessages::invalidPublicIdChar,
  789. StringMessageArg(StringC(s, 1)));
  790. }
  791. else
  792. buf += char(*s);
  793. }
  794. buf += '\0';
  795. return publicIds_.store(buf);
  796. }
  797. bool Interpreter::convertStringC(ELObj *obj, const Identifier *ident, const Location &loc,
  798. StringC &result)
  799. {
  800. const Char *s;
  801. size_t n;
  802. if (obj->stringData(s, n)) {
  803. result.assign(s, n);
  804. return 1;
  805. }
  806. invalidCharacteristicValue(ident, loc);
  807. return 0;
  808. }
  809. bool Interpreter::convertLengthSpec(ELObj *obj,
  810. FOTBuilder::LengthSpec &result)
  811. {
  812. int dim;
  813. double d;
  814. switch (obj->quantityValue(result.length, d, dim)) {
  815. case ELObj::longQuantity:
  816. if (dim == 1)
  817. return 1;
  818. break;
  819. case ELObj::doubleQuantity:
  820. if (dim == 1) {
  821. // FIXME catch overflow
  822. result.length = d < 0.0 ? long(d - .5) : long(d + .5);
  823. return 1;
  824. }
  825. break;
  826. default:
  827. {
  828. const LengthSpec *ls = obj->lengthSpec();
  829. if (ls)
  830. return ls->convert(result);
  831. }
  832. break;
  833. }
  834. return 0;
  835. }
  836. bool Interpreter::convertLengthC(ELObj *obj, const Identifier *ident,
  837. const Location &loc,
  838. FOTBuilder::Length &n)
  839. {
  840. obj = convertFromString(obj, convertAllowNumber, loc);
  841. int dim;
  842. double d;
  843. switch (obj->quantityValue(n, d, dim)) {
  844. case ELObj::longQuantity:
  845. if (dim == 1)
  846. return 1;
  847. break;
  848. case ELObj::doubleQuantity:
  849. if (dim == 1) {
  850. // FIXME catch overflow
  851. n = long(d);
  852. return 1;
  853. }
  854. break;
  855. default:
  856. break;
  857. }
  858. invalidCharacteristicValue(ident, loc);
  859. return 0;
  860. }
  861. bool Interpreter::convertLengthSpecC(ELObj *obj, const Identifier *ident,
  862. const Location &loc,
  863. FOTBuilder::LengthSpec &result)
  864. {
  865. obj = convertFromString(obj, convertAllowNumber, loc);
  866. if (convertLengthSpec(obj, result))
  867. return 1;
  868. invalidCharacteristicValue(ident, loc);
  869. return 0;
  870. }
  871. bool Interpreter::convertOptLengthSpecC(ELObj *obj, const Identifier *ident,
  872. const Location &loc,
  873. FOTBuilder::OptLengthSpec &result)
  874. {
  875. obj = convertFromString(obj, convertAllowBoolean|convertAllowNumber, loc);
  876. if (obj == makeFalse()) {
  877. result.hasLength = 0;
  878. return 1;
  879. }
  880. if (convertLengthSpecC(obj, ident, loc, result.length)) {
  881. result.hasLength = 1;
  882. return 1;
  883. }
  884. return 0;
  885. }
  886. bool Interpreter::convertOptPositiveIntegerC(ELObj *obj, const Identifier *ident, const Location &loc,
  887. long &result)
  888. {
  889. obj = convertFromString(obj, convertAllowNumber|convertAllowBoolean, loc);
  890. if (obj == makeFalse()) {
  891. result = 0;
  892. return 1;
  893. }
  894. if (obj->exactIntegerValue(result) && result > 0)
  895. return 1;
  896. // FIXME allow inexact value
  897. invalidCharacteristicValue(ident, loc);
  898. return 0;
  899. }
  900. bool Interpreter::convertIntegerC(ELObj *obj, const Identifier *ident, const Location &loc,
  901. long &result)
  902. {
  903. obj = convertFromString(obj, convertAllowNumber, loc);
  904. if (obj->exactIntegerValue(result))
  905. return 1;
  906. // FIXME allow inexact value
  907. invalidCharacteristicValue(ident, loc);
  908. return 0;
  909. }
  910. bool Interpreter::convertLetter2C(ELObj *obj, const Identifier *ident, const Location &loc,
  911. FOTBuilder::Letter2 &code)
  912. {
  913. StringObj *strObj = obj->convertToString();
  914. if (strObj) {
  915. const StringC &str = *strObj;
  916. if (str.size() == 2
  917. && str[0] >= 'A' && str[0] <= 'Z'
  918. && str[1] >= 'A' && str[1] <= 'Z') {
  919. code = SP_LETTER2(str[0], str[1]);
  920. return 1;
  921. }
  922. if (str.size() == 0) {
  923. code = 0;
  924. return 1;
  925. }
  926. }
  927. else if (obj == makeFalse()) {
  928. code = 0;
  929. return 1;
  930. }
  931. invalidCharacteristicValue(ident, loc);
  932. return 0;
  933. }
  934. bool Interpreter::convertCharC(ELObj *obj, const Identifier *ident, const Location &loc,
  935. Char &result)
  936. {
  937. if (obj->charValue(result))
  938. return 1;
  939. const Char *s;
  940. size_t n;
  941. if (obj->stringData(s, n) && n == 1) {
  942. result = s[0];
  943. return 1;
  944. }
  945. invalidCharacteristicValue(ident, loc);
  946. return 0;
  947. }
  948. bool Interpreter::convertColorC(ELObj *obj, const Identifier *ident, const Location &loc, ColorObj *&color)
  949. {
  950. color = obj->asColor();
  951. if (color)
  952. return 1;
  953. invalidCharacteristicValue(ident, loc);
  954. return 0;
  955. }
  956. bool Interpreter::convertOptColorC(ELObj *obj, const Identifier *ident, const Location &loc, ColorObj *&color)
  957. {
  958. color = obj->asColor();
  959. if (color)
  960. return 1;
  961. if (obj == makeFalse())
  962. return 1;
  963. invalidCharacteristicValue(ident, loc);
  964. return 0;
  965. }
  966. bool Interpreter::convertRealC(ELObj *obj, const Identifier *ident, const Location &loc,
  967. double &result)
  968. {
  969. obj = convertFromString(obj, convertAllowNumber, loc);
  970. if (obj->realValue(result))
  971. return 1;
  972. invalidCharacteristicValue(ident, loc);
  973. return 0;
  974. }
  975. bool Interpreter::convertEnumC(ELObj *obj, const Identifier *ident, const Location &loc,
  976. FOTBuilder::Symbol &sym)
  977. {
  978. obj = convertFromString(obj, convertAllowSymbol|convertAllowBoolean, loc);
  979. if (obj == makeFalse()) {
  980. sym = FOTBuilder::symbolFalse;
  981. return 1;
  982. }
  983. SymbolObj *symObj = obj->asSymbol();
  984. if (symObj) {
  985. sym = symObj->cValue();
  986. if (sym != FOTBuilder::symbolFalse)
  987. return 1;
  988. }
  989. if (obj == makeTrue()) {
  990. sym = FOTBuilder::symbolTrue;
  991. return 1;
  992. }
  993. invalidCharacteristicValue(ident, loc);
  994. return 0;
  995. }
  996. bool Interpreter::convertEnumC(const FOTBuilder::Symbol *syms, size_t nSyms,
  997. ELObj *obj, const Identifier *ident, const Location &loc,
  998. FOTBuilder::Symbol &result)
  999. {
  1000. obj = convertFromString(obj, convertAllowSymbol|convertAllowBoolean, loc);
  1001. SymbolObj *symObj = obj->asSymbol();
  1002. FOTBuilder::Symbol val;
  1003. if (symObj) {
  1004. val = symObj->cValue();
  1005. if (val == FOTBuilder::symbolFalse) {
  1006. invalidCharacteristicValue(ident, loc);
  1007. return 0;
  1008. }
  1009. }
  1010. else if (obj == makeFalse())
  1011. val = FOTBuilder::symbolFalse;
  1012. else if (obj == makeTrue())
  1013. val = FOTBuilder::symbolTrue;
  1014. else {
  1015. invalidCharacteristicValue(ident, loc);
  1016. return 0;
  1017. }
  1018. for (size_t i = 0; i < nSyms; i++)
  1019. if (val == syms[i]) {
  1020. result = val;
  1021. return 1;
  1022. }
  1023. invalidCharacteristicValue(ident, loc);
  1024. return 0;
  1025. }
  1026. //para PageModel -> Generic IC FALTA
  1027. bool Interpreter::convertPageModelC(ELObj *obj, const Identifier *ident, const Location &loc,
  1028. FOTBuilder::StModel &stpm, int tipo)
  1029. {
  1030. //obj tiene los valores del .dsl, lo convertimos a tipo PageModelObj
  1031. //si es un simbolo quiere decir que es una lista!!
  1032. PageModelObj *pmobj = 0;
  1033. if (obj->asSymbol()) {
  1034. pmobj = getSendPageModel(tipo);
  1035. }
  1036. else pmobj = obj->asPageModel();
  1037. if (pmobj){
  1038. //DEBUG: pmobj->whatID();
  1039. //obtenemos en stpm el valor del fichero .dsl, para despues pasarlo al FOTBuilder
  1040. if (pmobj->pageModelData(stpm)){
  1041. return 1;
  1042. }
  1043. }
  1044. invalidCharacteristicValue(ident, loc);
  1045. return 0;
  1046. }
  1047. //no habra demasiados define-page-model (lista enlazada)
  1048. //FALTA
  1049. void Interpreter::sendPageModel(PageModelObj *send)
  1050. {
  1051. PairObj *last;
  1052. //DEBUG
  1053. //send->print();
  1054. //send->whatID();
  1055. if (!pageModelsSends_){
  1056. pageModelsSends_ = new (*this) PairObj(send, 0);
  1057. actualpair_ = pageModelsSends_;
  1058. }
  1059. else{
  1060. last = pageModelsSends_;
  1061. while (last->cdr())
  1062. last = last->cdr()->asPair();
  1063. //el siguiente de last es nulo! fin!
  1064. PairObj *nuevo = new (*this) PairObj(send, 0);
  1065. //introducimos el siguiente
  1066. last->setCdr(nuevo);
  1067. }
  1068. }
  1069. //FALTA : nos de el ultimo define-page-model
  1070. PageModelObj* Interpreter::getSendPageModel(int tipo)
  1071. {
  1072. PageModelObj *pmobj = 0;
  1073. FOTBuilder::StModel stpm;
  1074. //actualpair_->car()->asPageModel()->print(*this,cout);
  1075. //si hay alguno
  1076. if (actualpair_){
  1077. while(actualpair_->cdr()){
  1078. pmobj = actualpair_->car()->asPageModel();
  1079. //FALTA controlar
  1080. pmobj->pageModelData(stpm);
  1081. if (sonIguales(contID.RaizID[contID.actualRaizID].init_rep[tipo].getActual(), stpm.id_)){
  1082. break;
  1083. }
  1084. else actualpair_ = actualpair_->cdr()->asPair();
  1085. }
  1086. //cuidado si no lo encontrara coge el ultimo, que en principio no se puede dar
  1087. pmobj = actualpair_->car()->asPageModel();
  1088. }
  1089. actualpair_ = pageModelsSends_;
  1090. return pmobj;
  1091. }
  1092. char* Interpreter::st_listIDs::getActual()
  1093. {
  1094. return id[actual];
  1095. }
  1096. void Interpreter::st_listIDs::insertarStr(char *str)
  1097. {
  1098. int i = 0;
  1099. while (str[i] != '\0')
  1100. {
  1101. id[quant][i] = str[i];
  1102. i++;
  1103. }
  1104. id[quant][i] = '\0';
  1105. }
  1106. void Interpreter::st_raizID::insert_ID(char *str)
  1107. {
  1108. switch (ultim){
  1109. case 0:
  1110. init_rep[0].insertarStr(str);
  1111. init_rep[0].quant++;
  1112. break;
  1113. case 1:
  1114. init_rep[1].insertarStr(str);
  1115. init_rep[1].quant++;
  1116. break;
  1117. default:
  1118. //FALTA caracteristica invalida
  1119. break;
  1120. }
  1121. }
  1122. //struct st_raizID Para PageModel. identificar IDs
  1123. //0-> intial 1->repeat
  1124. void Interpreter::st_raizID::insert_charact(int n)
  1125. {
  1126. switch(n){
  1127. case 0:
  1128. ultim = 0;
  1129. break;
  1130. case 1:
  1131. ultim = 1;
  1132. break;
  1133. default:
  1134. //FALTA caracteristica invalida
  1135. break;
  1136. }
  1137. }
  1138. bool Interpreter::sonIguales(char *s1, char *s2)
  1139. {
  1140. int i = 0;
  1141. bool igual = true;
  1142. bool res = false;
  1143. while ((s1[i] != '\0') && (s2[i] != '\0') && (igual)){
  1144. igual = (s1[i] == s2[i]);
  1145. i++;
  1146. }
  1147. if ((igual) && (s1[i] == '\0') && (s2[i] == '\0')) res = true;
  1148. return res;
  1149. }
  1150. void Interpreter::invalidCharacteristicValue(const Identifier *ident, const Location &loc)
  1151. {
  1152. setNextLocation(loc);
  1153. message(InterpreterMessages::invalidCharacteristicValue,
  1154. StringMessageArg(ident->name()));
  1155. }
  1156. static
  1157. bool equal(const Char *s1, const char *s2, size_t n)
  1158. {
  1159. while (n > 0) {
  1160. if (*s1++ != (unsigned char)*s2++)
  1161. return 0;
  1162. --n;
  1163. }
  1164. return 1;
  1165. }
  1166. ELObj *Interpreter::convertFromString(ELObj *obj, unsigned hints, const Location &loc)
  1167. {
  1168. // FIXME fold to lower case
  1169. const Char *s;
  1170. size_t n;
  1171. if (!dsssl2() || !obj->stringData(s, n)){
  1172. return obj;
  1173. }
  1174. if (hints & convertAllowNumber) {
  1175. ELObj *tem = convertNumber(StringC(s, n));
  1176. if (tem)
  1177. return tem->resolveQuantities(1, *this, loc);
  1178. }
  1179. if (hints & convertAllowPageModel) {
  1180. ELObj *tem = convertNumber(StringC(s, n));
  1181. if (tem)
  1182. return tem->resolveQuantities(1, *this, loc);
  1183. }
  1184. if (hints & convertAllowSymbol) {
  1185. StringC tem(s, n);
  1186. SymbolObj *sym = symbolTable_.lookup(tem);
  1187. if (sym && sym->cValue() != FOTBuilder::symbolFalse)
  1188. return sym;
  1189. }
  1190. if (hints & convertAllowBoolean) {
  1191. switch (n) {
  1192. case 2:
  1193. if (equal(s, "no", n))
  1194. return makeFalse();
  1195. break;
  1196. case 3:
  1197. if (equal(s, "yes", n))
  1198. return makeTrue();
  1199. break;
  1200. case 4:
  1201. if (equal(s, "true", n))
  1202. return makeTrue();
  1203. break;
  1204. case 5:
  1205. if (equal(s, "false", n))
  1206. return makeFalse();
  1207. break;
  1208. }
  1209. }
  1210. return obj;
  1211. }
  1212. ELObj *Interpreter::convertNumber(const StringC &str, int radix)
  1213. {
  1214. {
  1215. if (str.size() == 0)
  1216. return 0;
  1217. size_t i = 0;
  1218. if (str[0] == '#') {
  1219. if (str.size() < 2)
  1220. return 0;
  1221. switch (str[1]) {
  1222. case 'd':
  1223. radix = 10;
  1224. break;
  1225. case 'x':
  1226. radix = 16;
  1227. break;
  1228. case 'o':
  1229. radix = 8;
  1230. break;
  1231. case 'b':
  1232. radix = 2;
  1233. break;
  1234. default:
  1235. return 0;
  1236. }
  1237. i += 2;
  1238. }
  1239. if (i >= str.size())
  1240. return 0;
  1241. bool negative;
  1242. if (str[i] == '-') {
  1243. negative = 1;
  1244. i++;
  1245. }
  1246. else {
  1247. negative = 0;
  1248. if (str[i] == '+')
  1249. i++;
  1250. }
  1251. bool hadDecimalPoint = 0;
  1252. bool hadDigit = 0;
  1253. long n = 0;
  1254. int exp = 0;
  1255. for (; i < str.size(); i++) {
  1256. Char c = str[i];
  1257. int weight;
  1258. switch (c) {
  1259. case '0':
  1260. weight = 0;
  1261. break;
  1262. case '1':
  1263. weight = 1;
  1264. break;
  1265. case '2':
  1266. weight = 2;
  1267. break;
  1268. case '3':
  1269. weight = 3;
  1270. break;
  1271. case '4':
  1272. weight = 4;
  1273. break;
  1274. case '5':
  1275. weight = 5;
  1276. break;
  1277. case '6':
  1278. weight = 6;
  1279. break;
  1280. case '7':
  1281. weight = 7;
  1282. break;
  1283. case '8':
  1284. weight = 8;
  1285. break;
  1286. case '9':
  1287. weight = 9;
  1288. break;
  1289. case 'a':
  1290. weight = 10;
  1291. break;
  1292. case 'b':
  1293. weight = 11;
  1294. break;
  1295. case 'c':
  1296. weight = 12;
  1297. break;
  1298. case 'd':
  1299. weight = 13;
  1300. break;
  1301. case 'e':
  1302. weight = 14;
  1303. break;
  1304. case 'f':
  1305. weight = 15;
  1306. break;
  1307. default:
  1308. weight = -1;
  1309. break;
  1310. }
  1311. if (weight >= 0 && weight < radix) {
  1312. hadDigit = 1;
  1313. if (negative) {
  1314. if (-(unsigned long)n > (-(unsigned long)LONG_MIN - weight)/radix) {
  1315. if (radix != 10)
  1316. return 0;
  1317. return convertNumberFloat(str);
  1318. }
  1319. else
  1320. n = n*radix - weight;
  1321. }
  1322. else {
  1323. if (n > (LONG_MAX - weight)/radix) {
  1324. if (radix != 10)
  1325. return 0;
  1326. return convertNumberFloat(str);
  1327. }
  1328. else
  1329. n = n*radix + weight;
  1330. }
  1331. if (hadDecimalPoint)
  1332. exp--;
  1333. }
  1334. else if (c == '.' && radix == 10) {
  1335. if (hadDecimalPoint)
  1336. return 0;
  1337. hadDecimalPoint = 1;
  1338. }
  1339. else
  1340. break;
  1341. }
  1342. if (!hadDigit || (radix != 10 && i < str.size()))
  1343. return 0;
  1344. if (i + 1 < str.size() && str[i] == 'e'
  1345. && lexCategory(str[i + 1]) != lexLetter) {
  1346. hadDecimalPoint = 1;
  1347. i++;
  1348. int e;
  1349. if (!scanSignDigits(str, i, e))
  1350. return 0;
  1351. exp += e;
  1352. }
  1353. if (i < str.size()) {
  1354. int unitExp;
  1355. Unit *unit = scanUnit(str, i, unitExp);
  1356. if (!unit)
  1357. return 0;
  1358. if (unitExp == 1)
  1359. return new (*this) UnresolvedLengthObj(n, exp, unit);
  1360. else
  1361. return convertNumberFloat(str);
  1362. }
  1363. if (hadDecimalPoint)
  1364. return convertNumberFloat(str);
  1365. return makeInteger(n);
  1366. }
  1367. }
  1368. bool Interpreter::scanSignDigits(const StringC &str, size_t &i, int &n)
  1369. {
  1370. bool negative = 0;
  1371. if (i < str.size()) {
  1372. if (str[i] == '-') {
  1373. i++;
  1374. negative = 1;
  1375. } else if (str[i] == '+')
  1376. i++;
  1377. }
  1378. size_t j = i;
  1379. n = 0;
  1380. while (i < str.size()
  1381. && ('0' <= str[i] && str[i] <= '9')) {
  1382. if (negative)
  1383. n = n*10 - (str[i] - '0');
  1384. else
  1385. n = n*10 + (str[i] - '0');
  1386. i++;
  1387. }
  1388. if (i == j)
  1389. return 0;
  1390. return 1;
  1391. }
  1392. ELObj *Interpreter::convertNumberFloat(const StringC &str)
  1393. {
  1394. String<char> buf;
  1395. // omit an optional radix prefix
  1396. size_t i0 = 0;
  1397. if (str.size() > 1 && str[0] == '#' && str[1] == 'd')
  1398. i0 = 2;
  1399. for (size_t i = i0; i < str.size(); i++) {
  1400. if (str[i] > CHAR_MAX || str[i] == '\0')
  1401. return 0;
  1402. // 'E' is a valid exponent marker for C but not us
  1403. if (str[i] == 'E')
  1404. break;
  1405. buf += char(str[i]);
  1406. }
  1407. buf += '\0';
  1408. const char *endPtr;
  1409. double val = strtod((char *)buf.data(), (char **)&endPtr);
  1410. if (endPtr - buf.data() == str.size() - i0)
  1411. return new (*this) RealObj(val);
  1412. if (endPtr == buf.data())
  1413. return 0;
  1414. int unitExp;
  1415. Unit *unit = scanUnit(str, endPtr - buf.data() + i0, unitExp);
  1416. if (!unit)
  1417. return 0;
  1418. return new (*this) UnresolvedQuantityObj(val, unit, unitExp);
  1419. }
  1420. // Return 0 for error.
  1421. Unit *Interpreter::scanUnit(const StringC &str, size_t i, int &unitExp)
  1422. {
  1423. StringC unitName;
  1424. while (i < str.size()) {
  1425. if (str[i] == '-' || str[i] == '+' || ('0' <= str[i] && str[i] <= '9'))
  1426. break;
  1427. unitName += str[i++];
  1428. }
  1429. if (i >= str.size())
  1430. unitExp = 1;
  1431. else {
  1432. unitExp = 0;
  1433. bool neg = 0;
  1434. if (str[i] == '-' || str[i] == '+') {
  1435. if (str[i] == '-')
  1436. neg = 1;
  1437. i++;
  1438. if (i >= str.size())
  1439. return 0;
  1440. }
  1441. while (i < str.size()) {
  1442. if (str[i] < '0' || str[i] > '9')
  1443. return 0;
  1444. unitExp *= 10;
  1445. if (neg)
  1446. unitExp -= (str[i] - '0');
  1447. else
  1448. unitExp += (str[i] - '0');
  1449. i++;
  1450. }
  1451. }
  1452. return lookupUnit(unitName);
  1453. }
  1454. void Interpreter::setNodeLocation(const NodePtr &nd)
  1455. {
  1456. const LocNode *lnp;
  1457. Location nodeLoc;
  1458. if ((lnp = LocNode::convert(nd)) != 0
  1459. && lnp->getLocation(nodeLoc) == accessOK)
  1460. setNextLocation(nodeLoc);
  1461. }
  1462. bool Interpreter::convertToPattern(ELObj *obj, const Location &loc, Pattern &pattern)
  1463. {
  1464. IList<Pattern::Element> list;
  1465. if (!convertToPattern(obj, loc, 0, list))
  1466. return 0;
  1467. Pattern tem(list);
  1468. tem.swap(pattern);
  1469. return 1;
  1470. }
  1471. bool Interpreter::convertToPattern(ELObj *obj, const Location &loc,
  1472. bool isChild,
  1473. IList<Pattern::Element> &list)
  1474. {
  1475. StringObj *str = obj->convertToString();
  1476. if (str) {
  1477. const Char *s;
  1478. size_t n;
  1479. str->stringData(s, n);
  1480. if (!n) {
  1481. setNextLocation(loc);
  1482. message(InterpreterMessages::patternEmptyGi);
  1483. return 0;
  1484. }
  1485. list.insert(new Pattern::Element(StringC(s, n)));
  1486. return 1;
  1487. }
  1488. if (obj == makeTrue()) {
  1489. list.insert(new Pattern::Element(StringC()));
  1490. return 1;
  1491. }
  1492. Pattern::Element *curElement = 0;
  1493. while (!obj->isNil()) {
  1494. PairObj *pair = obj->asPair();
  1495. if (!pair) {
  1496. setNextLocation(loc);
  1497. message(InterpreterMessages::patternNotList);
  1498. return 0;
  1499. }
  1500. ELObj *head = pair->car();
  1501. obj = pair->cdr();
  1502. if (head == makeTrue() && dsssl2()) {
  1503. list.insert(curElement = new Pattern::Element(StringC()));
  1504. continue;
  1505. }
  1506. str = head->convertToString();
  1507. if (str) {
  1508. const Char *s;
  1509. size_t n;
  1510. str->stringData(s, n);
  1511. if (!n) {
  1512. setNextLocation(loc);
  1513. message(InterpreterMessages::patternEmptyGi);
  1514. return 0;
  1515. }
  1516. list.insert(curElement = new Pattern::Element(StringC(s, n)));
  1517. continue;
  1518. }
  1519. if (!curElement) {
  1520. setNextLocation(loc);
  1521. message(InterpreterMessages::patternBadGi,
  1522. ELObjMessageArg(head, *this));
  1523. return 0;
  1524. }
  1525. if (head->isNil())
  1526. continue; // empty attribute list
  1527. if (head->asPair()) {
  1528. if (!patternAddAttributeQualifiers(head, loc, *curElement)) {
  1529. setNextLocation(loc);
  1530. message(InterpreterMessages::patternBadAttributeQualifier);
  1531. return 0;
  1532. }
  1533. continue;
  1534. }
  1535. KeywordObj *key = dsssl2() ? head->asKeyword() : 0;
  1536. if (!key) {
  1537. setNextLocation(loc);
  1538. message(InterpreterMessages::patternBadMember,
  1539. ELObjMessageArg(head, *this));
  1540. return 0;
  1541. }
  1542. pair = obj->asPair();
  1543. if (!pair) {
  1544. setNextLocation(loc);
  1545. message(obj->isNil()
  1546. ? InterpreterMessages::patternMissingQualifierValue
  1547. : InterpreterMessages::patternNotList);
  1548. return 0;
  1549. }
  1550. ELObj *value = pair->car();
  1551. obj = pair->cdr();
  1552. Identifier::SyntacticKey k;
  1553. if (!key->identifier()->syntacticKey(k)) {
  1554. setNextLocation(loc);
  1555. message(InterpreterMessages::patternUnknownQualifier,
  1556. StringMessageArg(key->identifier()->name()));
  1557. return 0;
  1558. }
  1559. switch (k) {
  1560. case Identifier::keyAttributes:
  1561. if (!patternAddAttributeQualifiers(value, loc, *curElement)) {
  1562. setNextLocation(loc);
  1563. message(InterpreterMessages::patternBadAttributeQualifier);
  1564. return 0;
  1565. }
  1566. break;
  1567. case Identifier::keyChildren:
  1568. {
  1569. IList<Pattern::Element> children;
  1570. if (!convertToPattern(value, loc, 1, children))
  1571. return 0;
  1572. if (!children.empty())
  1573. curElement->addQualifier(new Pattern::ChildrenQualifier(children));
  1574. }
  1575. break;
  1576. case Identifier::keyRepeat:
  1577. {
  1578. if (isChild) {
  1579. setNextLocation(loc);
  1580. message(InterpreterMessages::patternChildRepeat);
  1581. return 0;
  1582. }
  1583. SymbolObj *sym = value->asSymbol();
  1584. if (sym) {
  1585. const StringC &str = *sym->name();
  1586. if (str.size() == 1) {
  1587. switch (str[0]) {
  1588. case '*':
  1589. curElement->setRepeat(0, Pattern::Repeat(-1));
  1590. value = 0;
  1591. break;
  1592. case '?':
  1593. curElement->setRepeat(0, 1);
  1594. value = 0;
  1595. break;
  1596. case '+':
  1597. curElement->setRepeat(1, Pattern::Repeat(-1));
  1598. value = 0;
  1599. break;
  1600. default:
  1601. break;
  1602. }
  1603. }
  1604. }
  1605. if (value) {
  1606. setNextLocation(loc);
  1607. message(InterpreterMessages::patternBadQualifierValue,
  1608. ELObjMessageArg(value, *this),
  1609. StringMessageArg(key->identifier()->name()));
  1610. return 0;
  1611. }
  1612. }
  1613. break;
  1614. case Identifier::keyPosition:
  1615. {
  1616. SymbolObj *sym = value->asSymbol();
  1617. if (sym) {
  1618. Pattern::Qualifier *qual = 0;
  1619. const StringC &str = *sym->name();
  1620. if (str == "first-of-type")
  1621. qual = new Pattern::FirstOfTypeQualifier;
  1622. else if (str == "last-of-type")
  1623. qual = new Pattern::LastOfTypeQualifier;
  1624. else if (str == "first-of-any")
  1625. qual = new Pattern::FirstOfAnyQualifier;
  1626. else if (str == "last-of-any")
  1627. qual = new Pattern::LastOfAnyQualifier;
  1628. if (qual) {
  1629. curElement->addQualifier(qual);
  1630. break;
  1631. }
  1632. }
  1633. setNextLocation(loc);
  1634. message(InterpreterMessages::patternBadQualifierValue,
  1635. ELObjMessageArg(value, *this),
  1636. StringMessageArg(key->identifier()->name()));
  1637. return 0;
  1638. }
  1639. case Identifier::keyOnly:
  1640. {
  1641. SymbolObj *sym = value->asSymbol();
  1642. if (sym) {
  1643. Pattern::Qualifier *qual = 0;
  1644. const StringC &str = *sym->name();
  1645. if (str == "of-type")
  1646. qual = new Pattern::OnlyOfTypeQualifier;
  1647. else if (str == "of-any")
  1648. qual = new Pattern::OnlyOfAnyQualifier;
  1649. if (qual) {
  1650. curElement->addQualifier(qual);
  1651. break;
  1652. }
  1653. }
  1654. setNextLocation(loc);
  1655. message(InterpreterMessages::patternBadQualifierValue,
  1656. ELObjMessageArg(value, *this),
  1657. StringMessageArg(key->identifier()->name()));
  1658. return 0;
  1659. }
  1660. break;
  1661. case Identifier::keyId:
  1662. {
  1663. StringObj *str = value->convertToString();
  1664. if (!str) {
  1665. setNextLocation(loc);
  1666. message(InterpreterMessages::patternBadQualifierValue,
  1667. ELObjMessageArg(value, *this),
  1668. StringMessageArg(key->identifier()->name()));
  1669. return 0;
  1670. }
  1671. const Char *s;
  1672. size_t n;
  1673. str->stringData(s, n);
  1674. curElement->addQualifier(new Pattern::IdQualifier(StringC(s, n)));
  1675. }
  1676. break;
  1677. case Identifier::keyClass:
  1678. {
  1679. StringObj *str = value->convertToString();
  1680. if (!str) {
  1681. setNextLocation(loc);
  1682. message(InterpreterMessages::patternBadQualifierValue,
  1683. ELObjMessageArg(value, *this),
  1684. StringMessageArg(key->identifier()->name()));
  1685. return 0;
  1686. }
  1687. const Char *s;
  1688. size_t n;
  1689. str->stringData(s, n);
  1690. curElement->addQualifier(new Pattern::ClassQualifier(StringC(s, n)));
  1691. }
  1692. break;
  1693. case Identifier::keyImportance:
  1694. {
  1695. long n;
  1696. if (!value->exactIntegerValue(n)) {
  1697. setNextLocation(loc);
  1698. message(InterpreterMessages::patternBadQualifierValue,
  1699. ELObjMessageArg(value, *this),
  1700. StringMessageArg(key->identifier()->name()));
  1701. return 0;
  1702. }
  1703. curElement->addQualifier(new Pattern::ImportanceQualifier(n));
  1704. }
  1705. break;
  1706. case Identifier::keyPriority:
  1707. {
  1708. long n;
  1709. if (!value->exactIntegerValue(n)) {
  1710. setNextLocation(loc);
  1711. message(InterpreterMessages::patternBadQualifierValue,
  1712. ELObjMessageArg(value, *this),
  1713. StringMessageArg(key->identifier()->name()));
  1714. return 0;
  1715. }
  1716. curElement->addQualifier(new Pattern::PriorityQualifier(n));
  1717. }
  1718. break;
  1719. default:
  1720. setNextLocation(loc);
  1721. message(InterpreterMessages::patternUnknownQualifier,
  1722. StringMessageArg(key->identifier()->name()));
  1723. return 0;
  1724. }
  1725. }
  1726. return 1;
  1727. }
  1728. bool Interpreter::patternAddAttributeQualifiers(ELObj *obj,
  1729. const Location &loc,
  1730. Pattern::Element &elem)
  1731. {
  1732. while (!obj->isNil()) {
  1733. PairObj *pair = obj->asPair();
  1734. if (!pair)
  1735. return 0;
  1736. StringObj *tem = pair->car()->convertToString();
  1737. if (!tem)
  1738. return 0;
  1739. const Char *s;
  1740. size_t n;
  1741. tem->stringData(s, n);
  1742. if (n == 0)
  1743. return 0;
  1744. StringC name(s, n);
  1745. obj = pair->cdr();
  1746. pair = obj->asPair();
  1747. if (!pair)
  1748. return 0;
  1749. obj = pair->cdr();
  1750. if (pair->car() == makeFalse() && dsssl2())
  1751. elem.addQualifier(new Pattern::AttributeMissingValueQualifier(name));
  1752. else if (pair->car() == makeTrue() && dsssl2())
  1753. elem.addQualifier(new Pattern::AttributeHasValueQualifier(name));
  1754. else {
  1755. tem = pair->car()->convertToString();
  1756. if (!tem)
  1757. return 0;
  1758. tem->stringData(s, n);
  1759. elem.addQualifier(new Pattern::AttributeQualifier(name, StringC(s, n)));
  1760. }
  1761. }
  1762. return 1;
  1763. }
  1764. void Interpreter::dispatchMessage(Message &msg)
  1765. {
  1766. messenger_->dispatchMessage(msg);
  1767. }
  1768. void Interpreter::dispatchMessage(const Message &msg)
  1769. {
  1770. messenger_->dispatchMessage(msg);
  1771. }
  1772. Interpreter::StringSet::StringSet()
  1773. {
  1774. }
  1775. const char *Interpreter::StringSet::store(String<char> &str)
  1776. {
  1777. str += '\0';
  1778. const String<char> *p = table_.lookup(str);
  1779. if (!p) {
  1780. String<char> *tem = new String<char>;
  1781. str.swap(*tem);
  1782. table_.insert(tem);
  1783. p = tem;
  1784. }
  1785. return p->data();
  1786. }
  1787. unsigned long Interpreter::StringSet::hash(const String<char> &str)
  1788. {
  1789. const char *p = str.data();
  1790. unsigned long h = 0;
  1791. for (size_t n = str.size(); n > 0; n--)
  1792. h = (h << 5) + h + (unsigned char)*p++; // from Chris Torek
  1793. return h;
  1794. }
  1795. bool Identifier::preferBuiltin_ = 0;
  1796. Identifier::Identifier(const StringC &name)
  1797. : Named(name), value_(0), syntacticKey_(notKey), beingComputed_(0),
  1798. flowObj_(0), builtin_(0), defPart_(0), charNIC_(0)
  1799. {
  1800. }
  1801. void Identifier::maybeSaveBuiltin()
  1802. {
  1803. if (defPart_ == unsigned(-1) && !builtin_) {
  1804. builtin_ = new Identifier(name());
  1805. if (value_)
  1806. builtin_->setValue(value_, defPart_);
  1807. else
  1808. builtin_->setDefinition(def_, defPart_, defLoc_);
  1809. }
  1810. }
  1811. void Identifier::setDefinition(Owner<Expression> &expr,
  1812. unsigned part,
  1813. const Location &loc)
  1814. {
  1815. maybeSaveBuiltin();
  1816. def_.swap(expr);
  1817. defPart_ = part;
  1818. defLoc_ = loc;
  1819. value_ = 0;
  1820. }
  1821. void Identifier::setValue(ELObj *value, unsigned partIndex)
  1822. {
  1823. maybeSaveBuiltin();
  1824. value_ = value;
  1825. // Built in functions have lowest priority.
  1826. defPart_ = partIndex;
  1827. }
  1828. bool Identifier::defined(unsigned &part, Location &loc) const
  1829. {
  1830. if (!def_ && !value_)
  1831. return 0;
  1832. part = defPart_;
  1833. loc = defLoc_;
  1834. return 1;
  1835. }
  1836. ELObj *Identifier::computeValue(bool force, Interpreter &interp) const
  1837. {
  1838. if (builtin_ && preferBuiltin_)
  1839. return builtin_->computeValue(force, interp);
  1840. if (value_)
  1841. return value_;
  1842. bool preferred = 0;
  1843. if (defPart_ == unsigned(-1) && !preferBuiltin_) {
  1844. preferBuiltin_ = 1;
  1845. preferred = 1;
  1846. }
  1847. ASSERT(def_);
  1848. if (beingComputed_) {
  1849. if (force) {
  1850. interp.setNextLocation(defLoc_);
  1851. interp.message(InterpreterMessages::identifierLoop,
  1852. StringMessageArg(name()));
  1853. ((Identifier *)this)->value_ = interp.makeError();
  1854. }
  1855. }
  1856. else {
  1857. ((Identifier *)this)->beingComputed_ = 1;
  1858. if (insn_.isNull())
  1859. ((Identifier *)this)->insn_
  1860. = Expression::optimizeCompile(((Identifier *)this)->def_, interp,
  1861. Environment(), 0, InsnPtr());
  1862. if (force || def_->canEval(0)) {
  1863. VM vm(interp);
  1864. ELObj *v = vm.eval(insn_.pointer());
  1865. interp.makePermanent(v);
  1866. ((Identifier *)this)->value_ = v;
  1867. }
  1868. ((Identifier *)this)->beingComputed_ = 0;
  1869. }
  1870. if (preferred)
  1871. preferBuiltin_ = 0;
  1872. return value_;
  1873. }
  1874. ELObj *Identifier::computeBuiltinValue(bool force, Interpreter &interp) const
  1875. {
  1876. preferBuiltin_ = 1;
  1877. ELObj *res = computeValue(force, interp);
  1878. preferBuiltin_ = 0;
  1879. return res;
  1880. }
  1881. Unit::Unit(const StringC &name)
  1882. : Named(name), computed_(notComputed)
  1883. {
  1884. }
  1885. bool Unit::defined(unsigned &part, Location &loc) const
  1886. {
  1887. if (!def_ && computed_ == notComputed)
  1888. return 0;
  1889. part = defPart_;
  1890. loc = defLoc_;
  1891. return 1;
  1892. }
  1893. void Unit::setDefinition(Owner<Expression> &expr,
  1894. unsigned part,
  1895. const Location &loc)
  1896. {
  1897. def_.swap(expr);
  1898. defPart_ = part;
  1899. defLoc_ = loc;
  1900. computed_ = notComputed;
  1901. }
  1902. void Unit::setValue(long n)
  1903. {
  1904. computed_ = computedExact;
  1905. exact_ = n;
  1906. dim_ = 1;
  1907. defPart_ = unsigned(-1);
  1908. }
  1909. void Unit::setValue(double n)
  1910. {
  1911. computed_ = computedInexact;
  1912. inexact_ = n;
  1913. dim_ = 1;
  1914. defPart_ = unsigned(-1);
  1915. }
  1916. void Unit::tryCompute(bool force, Interpreter &interp)
  1917. {
  1918. if (computed_ == notComputed) {
  1919. computed_ = beingComputed;
  1920. if (insn_.isNull())
  1921. insn_ = Expression::optimizeCompile(def_, interp, Environment(), 0, InsnPtr());
  1922. if (force || def_->canEval(0)) {
  1923. VM vm(interp);
  1924. ELObj *v = vm.eval(insn_.pointer());
  1925. switch (v->quantityValue(exact_, inexact_, dim_)) {
  1926. case ELObj::noQuantity:
  1927. if (!interp.isError(v)) {
  1928. interp.setNextLocation(defLoc_);
  1929. interp.message(InterpreterMessages::badUnitDefinition,
  1930. StringMessageArg(name()));
  1931. }
  1932. computed_ = computedError;
  1933. break;
  1934. case ELObj::longQuantity:
  1935. computed_ = computedExact;
  1936. break;
  1937. case ELObj::doubleQuantity:
  1938. computed_ = computedInexact;
  1939. break;
  1940. default:
  1941. CANNOT_HAPPEN();
  1942. }
  1943. }
  1944. if (computed_ == beingComputed)
  1945. computed_ = notComputed;
  1946. }
  1947. else if (computed_ == beingComputed) {
  1948. interp.setNextLocation(defLoc_);
  1949. interp.message(InterpreterMessages::unitLoop,
  1950. StringMessageArg(name()));
  1951. computed_ = computedError;
  1952. }
  1953. }
  1954. // multiply by 10^valExp
  1955. // quantity has exponent of 1
  1956. ELObj *Unit::resolveQuantity(bool force, Interpreter &interp,
  1957. long val, int valExp)
  1958. {
  1959. tryCompute(force, interp);
  1960. long result;
  1961. if (computed_ == computedExact && scale(val, valExp, exact_, result))
  1962. return new (interp) LengthObj(result);
  1963. double x = val;
  1964. while (valExp > 0) {
  1965. x *= 10.0;
  1966. valExp--;
  1967. }
  1968. while (valExp < 0) {
  1969. x /= 10.0;
  1970. valExp++;
  1971. }
  1972. return resolveQuantity(force, interp, x, 1);
  1973. }
  1974. // val * 10^valExp * factor
  1975. // return 0 if it can't be done without overflow
  1976. bool Unit::scale(long val, int valExp, long factor, long &result)
  1977. {
  1978. if (factor <= 0)
  1979. return 0; // feeble
  1980. while (valExp > 0) {
  1981. if (factor > LONG_MAX/10)
  1982. return 0;
  1983. valExp--;
  1984. factor *= 10;
  1985. }
  1986. if (val >= 0) {
  1987. if (val > LONG_MAX/factor)
  1988. return 0;
  1989. }
  1990. else {
  1991. if (-(unsigned long)val > -(unsigned long)LONG_MIN/factor)
  1992. return 0;
  1993. }
  1994. result = val*factor;
  1995. while (valExp < 0) {
  1996. result /= 10;
  1997. valExp++;
  1998. }
  1999. return 1;
  2000. }
  2001. ELObj *Unit::resolveQuantity(bool force, Interpreter &interp,
  2002. double val, int unitExp)
  2003. {
  2004. tryCompute(force, interp);
  2005. double factor;
  2006. switch (computed_) {
  2007. case computedExact:
  2008. factor = exact_;
  2009. break;
  2010. case computedInexact:
  2011. factor = inexact_;
  2012. break;
  2013. case computedError:
  2014. return interp.makeError();
  2015. default:
  2016. return 0;
  2017. }
  2018. int resultDim = 0;
  2019. double resultVal = val;
  2020. while (unitExp > 0) {
  2021. resultDim += dim_;
  2022. resultVal *= factor;
  2023. unitExp--;
  2024. }
  2025. while (unitExp < 0) {
  2026. resultDim -= dim_;
  2027. resultVal /= factor;
  2028. unitExp++;
  2029. }
  2030. if (resultDim == 0)
  2031. return new (interp) RealObj(resultVal);
  2032. return new (interp) QuantityObj(resultVal, resultDim);
  2033. }
  2034. void ELObjDynamicRoot::trace(Collector &c) const
  2035. {
  2036. c.trace(obj_);
  2037. }
  2038. bool operator==(const StringC &s, const char *p)
  2039. {
  2040. for (size_t i = 0; i < s.size(); i++)
  2041. if (p[i] == '\0' || (unsigned char)p[i] != s[i])
  2042. return 0;
  2043. return p[s.size()] == '\0';
  2044. }
  2045. void Interpreter::installBuiltins()
  2046. {
  2047. partIndex_ = unsigned(-1);
  2048. StringC sysid(makeStringC(DEFAULT_SCHEME_BUILTINS));
  2049. StringC src;
  2050. groveManager_->mapSysid(sysid);
  2051. if (groveManager_->readEntity(sysid, src)) {
  2052. Owner<InputSource> in(new InternalInputSource(src,
  2053. InputSourceOrigin::make()));
  2054. SchemeParser scm(*this, in);
  2055. scm.parse();
  2056. }
  2057. endPart();
  2058. partIndex_ = 0;
  2059. }
  2060. void Interpreter::setDefaultLanguage(Owner<Expression> &expr,
  2061. unsigned part,
  2062. const Location &loc)
  2063. {
  2064. defaultLanguageDef_.swap(expr);
  2065. defaultLanguageDefPart_ = part;
  2066. defaultLanguageDefLoc_ = loc;
  2067. }
  2068. ELObj *Interpreter::defaultLanguage() const
  2069. {
  2070. return defaultLanguage_;
  2071. }
  2072. bool Interpreter::defaultLanguageSet(unsigned &part,Location &loc) const
  2073. {
  2074. if(defaultLanguageDef_) {
  2075. part = defaultLanguageDefPart_;
  2076. loc = defaultLanguageDefLoc_;
  2077. return true;
  2078. }
  2079. return false;
  2080. }
  2081. void Interpreter::compileDefaultLanguage()
  2082. {
  2083. if(defaultLanguageDef_) {
  2084. InsnPtr insn = Expression::optimizeCompile(defaultLanguageDef_, *this,
  2085. Environment(), 0, InsnPtr());
  2086. VM vm(*this);
  2087. ELObj *obj = vm.eval(insn.pointer());
  2088. if(!obj->asLanguage()) {
  2089. if(!isError(obj)) {
  2090. setNextLocation(defaultLanguageDefLoc_);
  2091. message(InterpreterMessages::defLangDeclRequiresLanguage,
  2092. ELObjMessageArg(obj, *this));
  2093. }
  2094. return;
  2095. }
  2096. makePermanent(obj);
  2097. defaultLanguage_ = obj;
  2098. }
  2099. }
  2100. void Interpreter::installCharProperties()
  2101. {
  2102. //FIXME convert this to tables
  2103. // initialize charProperties_;
  2104. // if a character doesn't have a value for a property,
  2105. // the CharMap contains 0.
  2106. CharProp cp;
  2107. cp.def = ELObjPart(makeFalse(), unsigned(-1));
  2108. cp.loc = Location();
  2109. cp.map = new CharMap<ELObjPart>(ELObjPart(0, 0));
  2110. if (!strictMode_)
  2111. for (int i = 0; i < 10; i++) {
  2112. ELObjPart num(makeInteger(i), unsigned(-1));
  2113. makePermanent(num.obj);
  2114. cp.map->setChar(i+'0', num);
  2115. }
  2116. charProperties_.insert(makeStringC("numeric-equiv"), cp);
  2117. cp.def = ELObjPart(makeFalse(), unsigned(-1));
  2118. cp.map = new CharMap<ELObjPart>(ELObjPart(0, 0));
  2119. if (!strictMode_) {
  2120. static struct {
  2121. Char c;
  2122. unsigned num;
  2123. } chars[] = {
  2124. #define SPACE
  2125. #include "charProps.h"
  2126. #undef SPACE
  2127. };
  2128. for (size_t i = 0; i < SIZEOF(chars); i++)
  2129. cp.map->setRange(chars[i].c, chars[i].c+chars[i].num-1,
  2130. ELObjPart(makeTrue(), unsigned(-1)));
  2131. }
  2132. charProperties_.insert(makeStringC("space?"), cp);
  2133. cp.def = ELObjPart(makeFalse(), unsigned(-1));
  2134. cp.map = new CharMap<ELObjPart>(ELObjPart(0, 0));
  2135. if (!strictMode_) {
  2136. static struct {
  2137. Char c;
  2138. unsigned num;
  2139. } chars[] = {
  2140. #define RECORD_END
  2141. #include "charProps.h"
  2142. #undef RECORD_END
  2143. };
  2144. for (size_t i = 0; i < SIZEOF(chars); i++)
  2145. cp.map->setRange(chars[i].c, chars[i].c+chars[i].num-1,
  2146. ELObjPart(makeTrue(), unsigned(-1)));
  2147. }
  2148. charProperties_.insert(makeStringC("record-end?"), cp);
  2149. cp.def = ELObjPart(makeFalse(), unsigned(-1));
  2150. cp.map = new CharMap<ELObjPart>(ELObjPart(0, 0));
  2151. if (!strictMode_) {
  2152. static struct {
  2153. Char c;
  2154. unsigned num;
  2155. } chars[] = {
  2156. #define BLANK
  2157. #include "charProps.h"
  2158. #undef BLANK
  2159. };
  2160. for (size_t i = 0; i < SIZEOF(chars); i++)
  2161. cp.map->setRange(chars[i].c, chars[i].c+chars[i].num-1,
  2162. ELObjPart(makeTrue(), unsigned(-1)));
  2163. }
  2164. charProperties_.insert(makeStringC("blank?"), cp);
  2165. cp.def = ELObjPart(makeFalse(), unsigned(-1));
  2166. cp.map = new CharMap<ELObjPart>(ELObjPart(0, 0));
  2167. if (!strictMode_) {
  2168. static struct {
  2169. Char c;
  2170. unsigned num;
  2171. } chars[] = {
  2172. #define INPUT_TAB
  2173. #include "charProps.h"
  2174. #undef INPUT_TAB
  2175. };
  2176. for (size_t i = 0; i < SIZEOF(chars); i++)
  2177. cp.map->setRange(chars[i].c, chars[i].c+chars[i].num-1,
  2178. ELObjPart(makeTrue(), unsigned(-1)));
  2179. }
  2180. charProperties_.insert(makeStringC("input-tab?"), cp);
  2181. cp.def = ELObjPart(makeFalse(), unsigned(-1));
  2182. cp.map = new CharMap<ELObjPart>(ELObjPart(0, 0));
  2183. if (!strictMode_) {
  2184. static struct {
  2185. Char c;
  2186. unsigned num;
  2187. } chars[] = {
  2188. #define INPUT_WHITESPACE
  2189. #include "charProps.h"
  2190. #undef INPUT_WHITESPACE
  2191. };
  2192. for (size_t i = 0; i < SIZEOF(chars); i++)
  2193. cp.map->setRange(chars[i].c, chars[i].c+chars[i].num-1,
  2194. ELObjPart(makeTrue(), unsigned(-1)));
  2195. }
  2196. charProperties_.insert(makeStringC("input-whitespace?"), cp);
  2197. cp.def = ELObjPart(makeFalse(), unsigned(-1));
  2198. cp.map = new CharMap<ELObjPart>(ELObjPart(0, 0));
  2199. if (!strictMode_) {
  2200. static struct {
  2201. Char c;
  2202. unsigned num;
  2203. } chars[] = {
  2204. #define PUNCT
  2205. #include "charProps.h"
  2206. #undef PUNCT
  2207. };
  2208. for (size_t i = 0; i < SIZEOF(chars); i++)
  2209. cp.map->setRange(chars[i].c, chars[i].c+chars[i].num-1,
  2210. ELObjPart(makeTrue(), unsigned(-1)));
  2211. }
  2212. charProperties_.insert(makeStringC("punct?"), cp);
  2213. cp.def = ELObjPart(makeFalse(), unsigned(-1));
  2214. cp.map = new CharMap<ELObjPart>(ELObjPart(0, 0));
  2215. if (!strictMode_) {
  2216. static struct {
  2217. Char c1, c2;
  2218. char *script;
  2219. } chars[] = {
  2220. #define SCRIPT
  2221. #include "charProps.h"
  2222. #undef SCRIPT
  2223. };
  2224. StringC prefix = makeStringC("ISO/IEC 10179::1996//Script::");
  2225. for (size_t i = 0; i < SIZEOF(chars); i++) {
  2226. StringC tem(prefix);
  2227. tem += makeStringC(chars[i].script);
  2228. StringObj *obj = new (*this) StringObj(tem);
  2229. makePermanent(obj);
  2230. cp.map->setRange(chars[i].c1, chars[i].c2,
  2231. ELObjPart(obj, unsigned(-1)));
  2232. }
  2233. }
  2234. charProperties_.insert(makeStringC("script"), cp);
  2235. cp.def = ELObjPart(makeFalse(), unsigned(-1));
  2236. cp.map = new CharMap<ELObjPart>(ELObjPart(0, 0));
  2237. charProperties_.insert(makeStringC("glyph-id"), cp);
  2238. cp.def = ELObjPart(makeFalse(), unsigned(-1));
  2239. cp.map = new CharMap<ELObjPart>(ELObjPart(0, 0));
  2240. charProperties_.insert(makeStringC("drop-after-line-break?"), cp);
  2241. cp.def = ELObjPart(makeFalse(), unsigned(-1));
  2242. cp.map = new CharMap<ELObjPart>(ELObjPart(0, 0));
  2243. charProperties_.insert(makeStringC("drop-unless-before-line-break?"), cp);
  2244. cp.def = ELObjPart(makeInteger(0), unsigned(-1));
  2245. makePermanent(cp.def.obj);
  2246. cp.map = new CharMap<ELObjPart>(ELObjPart(0, 0));
  2247. CharProp cp2;
  2248. cp2.def = ELObjPart(cp.def.obj, unsigned(-1));
  2249. cp2.loc = Location();
  2250. cp2.map = new CharMap<ELObjPart>(ELObjPart(0, 0));
  2251. if(!strictMode_) {
  2252. static struct {
  2253. Char c;
  2254. unsigned short num;
  2255. unsigned short bbp;
  2256. unsigned short bap;
  2257. } chars[] ={
  2258. #define BREAK_PRIORITIES
  2259. #include "charProps.h"
  2260. #undef BREAK_PRIORITIES
  2261. };
  2262. for(size_t i = 0; i<SIZEOF(chars); ++i) {
  2263. ELObj *obj = makeInteger(chars[i].bbp);
  2264. makePermanent(obj);
  2265. cp.map->setRange(chars[i].c, chars[i].c + chars[i].num-1,
  2266. ELObjPart(obj, unsigned(-1)));
  2267. if(chars[i].bap!=chars[i].bbp) {
  2268. obj = makeInteger(chars[i].bap);
  2269. makePermanent(obj);
  2270. }
  2271. cp2.map->setRange(chars[i].c, chars[i].c+chars[i].num-1,
  2272. ELObjPart(obj, unsigned(-1)));
  2273. }
  2274. }
  2275. charProperties_.insert(makeStringC("break-before-priority"), cp);
  2276. charProperties_.insert(makeStringC("break-after-priority"), cp2);
  2277. cp.def = ELObjPart(makeSymbol(makeStringC("ordinary")), unsigned(-1));
  2278. makePermanent(cp.def.obj);
  2279. cp.map = new CharMap<ELObjPart>(ELObjPart(0, 0));
  2280. charProperties_.insert(makeStringC("math-class"), cp);
  2281. cp.def = ELObjPart(makeFalse(), unsigned(-1));
  2282. cp.map = new CharMap<ELObjPart>(ELObjPart(0, 0));
  2283. charProperties_.insert(makeStringC("math-font-posture"), cp);
  2284. }
  2285. // return 1 if the character has the property, return 0 if no such property
  2286. // or the character doesn't have the property
  2287. // set ret to the value or the default value
  2288. ELObj *Interpreter::charProperty(const StringC &prop, Char c, const Location &loc, ELObj *def)
  2289. {
  2290. const CharProp *cp = charProperties_.lookup(prop);
  2291. if (!cp) {
  2292. setNextLocation(loc);
  2293. message(InterpreterMessages::unknownCharProperty,
  2294. StringMessageArg(prop));
  2295. return makeError();
  2296. }
  2297. if ((*cp->map)[c].obj)
  2298. return (*cp->map)[c].obj;
  2299. else if (def)
  2300. return def;
  2301. else
  2302. return cp->def.obj;
  2303. }
  2304. void Interpreter::addCharProperty(const Identifier *prop, Owner<Expression> &defval)
  2305. {
  2306. // FIXME: what about variable default values ?
  2307. defval->optimize(*this, Environment(), defval);
  2308. if(!defval->constantValue()) {
  2309. setNextLocation(defval->location());
  2310. message(InterpreterMessages::varCharPropertyExprUnsupported);
  2311. return;
  2312. }
  2313. // FIXME: this is a kind of memory leak
  2314. makePermanent(defval->constantValue());
  2315. ELObjPart val(defval->constantValue(), partIndex_);
  2316. const CharProp *cp = charProperties_.lookup(prop->name());
  2317. if (cp) {
  2318. if (partIndex_ < cp->def.defPart)
  2319. ((CharProp *)cp)->def = val;
  2320. else if (partIndex_ == cp->def.defPart &&
  2321. !ELObj::eqv(*val.obj, *cp->def.obj)) {
  2322. // FIXME: report previous location
  2323. setNextLocation(defval->location());
  2324. message(InterpreterMessages::duplicateCharPropertyDecl,
  2325. StringMessageArg(prop->name()), cp->loc);
  2326. }
  2327. }
  2328. else {
  2329. CharProp ncp;
  2330. ncp.map = new CharMap<ELObjPart>(ELObjPart(0,0));
  2331. ncp.def = val;
  2332. ncp.loc = defval->location();
  2333. charProperties_.insert(prop->name(), ncp);
  2334. }
  2335. }
  2336. void Interpreter::setCharProperty(const Identifier *prop, Char c, Owner<Expression> &val)
  2337. {
  2338. // FIXME: what about variable default values ?
  2339. val->optimize(*this, Environment(), val);
  2340. if(!val->constantValue()) {
  2341. setNextLocation(val->location());
  2342. message(InterpreterMessages::varCharPropertyExprUnsupported);
  2343. return;
  2344. }
  2345. makePermanent(val->constantValue());
  2346. const CharProp *cp = charProperties_.lookup(prop->name());
  2347. if (!cp) {
  2348. CharProp ncp;
  2349. ncp.map = new CharMap<ELObjPart>(ELObjPart(0,0));
  2350. ncp.def = ELObjPart(0, unsigned(-1));
  2351. ncp.loc = val->location();
  2352. charProperties_.insert(prop->name(), ncp);
  2353. cp =