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

/tags/jade_1_3_pre1/jade/style/Interpreter.cxx

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