hqlwcpp.cpp 52 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860
  1. /*##############################################################################
  2. Copyright (C) 2011 HPCC Systems.
  3. All rights reserved. This program is free software: you can redistribute it and/or modify
  4. it under the terms of the GNU Affero General Public License as
  5. published by the Free Software Foundation, either version 3 of the
  6. License, or (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU Affero General Public License for more details.
  11. You should have received a copy of the GNU Affero General Public License
  12. along with this program. If not, see <http://www.gnu.org/licenses/>.
  13. ############################################################################## */
  14. #include "jliball.hpp"
  15. #include "hql.hpp"
  16. #include "platform.h"
  17. #include "jlib.hpp"
  18. #include "jexcept.hpp"
  19. #include "jmisc.hpp"
  20. #include "hqlexpr.hpp"
  21. #include "hqlattr.hpp"
  22. #include "hqlstmt.hpp"
  23. #include "hqlfunc.hpp"
  24. #include "hqlcerrors.hpp"
  25. #include "hqlcpp.ipp"
  26. #include "hqlwcpp.hpp"
  27. #include "hqlwcpp.ipp"
  28. #define INDENT_SOURCE
  29. #define FILE_CHUNK_SIZE 65000
  30. #define PREFERRED_LINE_LIMIT 160
  31. #define REASONABLE_LINE_LIMIT 512
  32. static const char * vcIntTypes[] = { "char","short","int","int","__int64","__int64","__int64","__int64" };
  33. static const char * vcUIntTypes[] = { "unsigned char","unsigned short","unsigned","unsigned","unsigned __int64","unsigned __int64","unsigned __int64","unsigned __int64" };
  34. static const char * gccIntTypes[] = { "char","short","int","int","long long","long long","long long","long long" };
  35. static const char * gccUIntTypes[] = { "unsigned char","unsigned short","unsigned","unsigned","unsigned long long","unsigned long long","unsigned long long","unsigned long long" };
  36. // ITypeInfo and IValue implementations
  37. inline const char * intTypeName(unsigned len, CompilerType compiler, bool isSigned)
  38. {
  39. switch (compiler)
  40. {
  41. case GccCppCompiler:
  42. return isSigned ? gccIntTypes[len] : gccUIntTypes[len];
  43. case Vs6CppCompiler:
  44. return isSigned ? vcIntTypes[len] : vcUIntTypes[len];
  45. default:
  46. throwUnexpected();
  47. }
  48. }
  49. bool isTypePassedByAddress(ITypeInfo * type)
  50. {
  51. switch (type->getTypeCode())
  52. {
  53. case type_decimal:
  54. case type_string:
  55. case type_data:
  56. case type_qstring:
  57. case type_varstring:
  58. case type_unicode:
  59. case type_varunicode:
  60. case type_utf8:
  61. case type_set:
  62. case type_row:
  63. return true;
  64. case type_table:
  65. case type_groupedtable:
  66. return !isArrayRowset(type);
  67. case type_record:
  68. throwUnexpected();
  69. }
  70. return false;
  71. }
  72. //---------------------------------------------------------------------------
  73. CppWriterTemplate::CppWriterTemplate()
  74. {
  75. text = NULL;
  76. len = 0;
  77. }
  78. CppWriterTemplate::~CppWriterTemplate()
  79. {
  80. free(text);
  81. }
  82. void CppWriterTemplate::generate(ISectionWriter & writer, unsigned pass, IProperties * properties)
  83. {
  84. writer.setOutput(out, outStream);
  85. const char * finger = text;
  86. bool output = true;
  87. BoolArray outputStack;
  88. StringBuffer temp;
  89. ForEachItemIn(idx, sections)
  90. {
  91. CppTemplateSection & cur = (CppTemplateSection &)sections.item(idx);
  92. if (output && (cur.position > finger))
  93. outputQuoted(writer, cur.position-finger, finger);
  94. switch (cur.type)
  95. {
  96. case TplEmbed:
  97. if (output && cur.id)
  98. writer.generateSection(cur.indent, cur.id, pass);
  99. break;
  100. case TplExpand:
  101. if (output && properties)
  102. {
  103. temp.clear();
  104. properties->getProp(cur.id->str(), temp);
  105. outputQuoted(writer, temp.length(), temp.str());
  106. }
  107. break;
  108. case TplCondition:
  109. outputStack.append(output);
  110. if (output)
  111. output = (properties && properties->hasProp(cur.id->str()));
  112. break;
  113. case TplEndCondition:
  114. output = outputStack.pop();
  115. break;
  116. }
  117. finger = cur.position + cur.len;
  118. }
  119. char * end = text+len;
  120. if (output && (end > finger))
  121. outputQuoted(writer, end-finger, finger);
  122. writer.setOutput(NULL, NULL);
  123. }
  124. bool CppWriterTemplate::loadTemplate(const char * filename, const char *dir)
  125. {
  126. StringBuffer tpl(dir);
  127. if(tpl.length())
  128. tpl.append(PATHSEPCHAR);
  129. tpl.append(filename);
  130. Owned<IFile> file = createIFile(tpl);
  131. Owned<IFileIO> io = file->openShared(IFOread, IFSHread);
  132. if (!io)
  133. return false;
  134. offset_t size = (size32_t)io->size();
  135. if (size != (size32_t)size)
  136. return false;
  137. text = (char *)malloc((size_t)size);
  138. len=io->read(0, (size32_t)size, text);
  139. unsigned index=0;
  140. unsigned startLine = 0;
  141. while (index != len)
  142. {
  143. char c = text[index];
  144. switch (c)
  145. {
  146. case '$':
  147. case '@':
  148. {
  149. unsigned start = index+1;
  150. TplSectionType type = TplEmbed;
  151. if (c == '$')
  152. {
  153. type = TplExpand;
  154. if ((start < len) && (text[start] == '?'))
  155. {
  156. start++;
  157. type = TplCondition;
  158. if ((start < len) && (text[start] == c))
  159. type = TplEndCondition;
  160. }
  161. }
  162. unsigned end = start;
  163. loop
  164. {
  165. if (end >= len)
  166. throwError(HQLERR_MissingTemplateTerminator);
  167. if (text[end] == c)
  168. break;
  169. ++end;
  170. }
  171. unsigned indent = 0;
  172. while (indent < index - startLine && isspace((byte)text[index-indent-1]))
  173. indent++;
  174. CppTemplateSection * next = new CppTemplateSection;
  175. next->type = type;
  176. next->position = text+index - indent;
  177. next->len = end+1 - index + indent;
  178. next->indent = indent;
  179. next->id = createAtom(text+start, end-start);
  180. if (end == index+1)
  181. next->len--; // quoted character => include the next @/$
  182. sections.append(*next);
  183. index = end+1;
  184. break;
  185. }
  186. case '\r':
  187. case '\n':
  188. startLine = index+1;
  189. index++;
  190. break;
  191. default:
  192. index++;
  193. break;
  194. }
  195. }
  196. return true;
  197. }
  198. //---------------------------------------------------------------------------
  199. const char * getOpText(node_operator op)
  200. {
  201. switch (op)
  202. {
  203. case no_mul: return "*";
  204. case no_div: return "/";
  205. case no_modulus: return "%";
  206. case no_negate: return "-";
  207. case no_add: return "+";
  208. case no_sub: return "-";
  209. case no_eq: return "==";
  210. case no_ne: return "!=";
  211. case no_lt: return "<";
  212. case no_le: return "<=";
  213. case no_gt: return ">";
  214. case no_ge: return ">=";
  215. case no_not: return "!";
  216. case no_and: return "&&";
  217. case no_or: return "||";
  218. case no_xor: return "xor"; //doesn't actually exist, should be transformed
  219. case no_comma: return ",";
  220. case no_compound: return ",";
  221. case no_select: return ".";
  222. case no_bnot: return "~";
  223. case no_band: return "&";
  224. case no_bor: return "|";
  225. case no_bxor: return "^";
  226. case no_postinc: return "++";
  227. case no_postdec: return "--";
  228. case no_preinc: return "++";
  229. case no_predec: return "--";
  230. case no_pselect: return "->";
  231. case no_address: return "&";
  232. case no_deref: return "*";
  233. case no_lshift: return "<<";
  234. case no_rshift: return ">>";
  235. }
  236. throwUnexpectedOp(op);
  237. }
  238. unsigned getPrecedence(IHqlExpression * expr)
  239. {
  240. node_operator op = expr->getOperator();
  241. if (op == no_typetransfer)
  242. return getPrecedence(expr->queryChild(0));
  243. switch (op)
  244. {
  245. case no_order: //pseudo operator always generated in brackets
  246. return 20;
  247. // :: = 18
  248. case no_pselect: case no_select: case no_index: case no_externalcall: case no_call:
  249. case no_reference:
  250. return 17;
  251. case no_postinc: case no_postdec:
  252. return 16;
  253. case no_not: case no_negate:
  254. case no_preinc: case no_predec:
  255. case no_bnot: case no_address: case no_deref:
  256. return 15;
  257. case no_cast:
  258. case no_implicitcast:
  259. return 14;
  260. case no_mul: case no_div: case no_modulus:
  261. return 13;
  262. case no_add: case no_sub:
  263. return 12;
  264. case no_lshift: case no_rshift:
  265. return 11;
  266. case no_lt: case no_gt: case no_le: case no_ge:
  267. return 10;
  268. case no_eq: case no_ne:
  269. return 9;
  270. case no_band:
  271. return 8;
  272. case no_bxor:
  273. return 7;
  274. case no_bor:
  275. return 6;
  276. case no_and:
  277. return 5;
  278. case no_or:
  279. return 4;
  280. case no_if:
  281. return 3;
  282. case no_assign: //op no_plus_assign etc.
  283. return 2;
  284. case no_compound:
  285. case no_comma:
  286. return 1;
  287. }
  288. return 50;
  289. }
  290. //---------------------------------------------------------------------------
  291. class TypeNameBuilder
  292. {
  293. public:
  294. TypeNameBuilder(const char * name) { typeOnLeft = false; str.append(name); }
  295. void addPrefix(const char * text)
  296. {
  297. if (str.length())
  298. str.insert(0, " ");
  299. str.insert(0, text);
  300. typeOnLeft = true;
  301. }
  302. StringBuffer & addSuffix()
  303. {
  304. if (typeOnLeft)
  305. {
  306. str.insert(0, "(").append(")");
  307. typeOnLeft = false;
  308. }
  309. return str;
  310. }
  311. StringBuffer & addArray(unsigned length)
  312. {
  313. return addSuffix().append("[").append(length ? length : 1).append("]");
  314. }
  315. void get(StringBuffer & out) { out.append(str); }
  316. protected:
  317. StringBuffer str;
  318. bool typeOnLeft;
  319. };
  320. void HqlCppWriter::generateType(ITypeInfo * type, const char * name)
  321. {
  322. TypeNameBuilder result(name);
  323. loop
  324. {
  325. bool isPointer = false;
  326. bool outOfLine= false;
  327. ITypeInfo * fullType = type;
  328. loop
  329. {
  330. typemod_t tmod = type->queryModifier();
  331. if (tmod == typemod_none)
  332. break;
  333. switch (tmod)
  334. {
  335. case typemod_const:
  336. // result.addPrefix("const");
  337. break;
  338. case typemod_outofline:
  339. outOfLine = false;
  340. break;
  341. case typemod_ref:
  342. isPointer = true;
  343. break;
  344. }
  345. type = type->queryTypeBase();
  346. }
  347. ITypeInfo * next = type->queryChildType();
  348. type_t tc = type->getTypeCode();
  349. size32_t size = type->getSize();
  350. const char * prefix = NULL;
  351. switch (tc)
  352. {
  353. case type_pointer:
  354. {
  355. prefix = "*";
  356. break;
  357. }
  358. case type_bitfield:
  359. result.addSuffix().append(":").append(type->getBitSize());
  360. break;
  361. case type_array:
  362. {
  363. unsigned dim = type->getCardinality();
  364. result.addSuffix().append("[");
  365. if (dim && (dim != UNKNOWN_LENGTH))
  366. result.addSuffix().append(dim);
  367. result.addSuffix().append("]");
  368. break;
  369. }
  370. case type_decimal:
  371. //MORE: decimal different as parameters???
  372. case type_varstring:
  373. case type_string:
  374. case type_qstring:
  375. case type_data:
  376. case type_utf8:
  377. {
  378. if ((size != UNKNOWN_LENGTH) && !isPointer)
  379. {
  380. result.addArray(size);
  381. }
  382. else
  383. isPointer = true;
  384. if (tc == type_data)
  385. {
  386. if (isPointer)
  387. prefix = "void";
  388. else
  389. prefix = "byte";
  390. }
  391. else if (tc == type_decimal)
  392. {
  393. //make this to byte
  394. if (isPointer)
  395. prefix = "void";
  396. else
  397. prefix = "char";
  398. }
  399. else
  400. prefix = "char";
  401. break;
  402. }
  403. case type_varunicode:
  404. case type_unicode:
  405. {
  406. if ((type->getSize() != UNKNOWN_LENGTH) && !isPointer)
  407. result.addArray(size/2);
  408. else
  409. isPointer = true;
  410. prefix = "UChar";
  411. break;
  412. }
  413. case type_char:
  414. prefix = "char";
  415. break;
  416. case type_row:
  417. case type_sortlist:
  418. if (hasLinkCountedModifier(fullType))
  419. isPointer = true;
  420. prefix = "byte";
  421. next = NULL;
  422. break;
  423. case type_groupedtable:
  424. //next = next->queryChildType();
  425. isPointer = false;
  426. break;
  427. case type_table:
  428. if (isArrayRowset(fullType))
  429. {
  430. prefix = "*";
  431. }
  432. else
  433. {
  434. isPointer = false;
  435. prefix = "*";
  436. }
  437. break;
  438. case type_class:
  439. prefix = type->queryTypeName();
  440. break;
  441. case type_boolean:
  442. prefix = "bool";
  443. break;
  444. case type_int:
  445. case type_swapint:
  446. prefix = intTypeName(size-1, compiler, type->isSigned());
  447. break;
  448. case type_real:
  449. prefix = (size == 4) ? "float" : "double";
  450. break;
  451. case type_packedint:
  452. case type_enumerated:
  453. //recurse to child type
  454. break;
  455. case type_void:
  456. case no_any:
  457. prefix = "void";
  458. break;
  459. case type_set:
  460. if (isPointer)
  461. {
  462. prefix = "byte";
  463. next = NULL;
  464. }
  465. else if (!next)
  466. {
  467. result.addPrefix("char * *");
  468. // result.addPrefix("byte");
  469. isPointer = false;
  470. }
  471. break;
  472. case type_function:
  473. {
  474. StringBuffer parameterText;
  475. IFunctionTypeExtra * extra = queryFunctionTypeExtra(type);
  476. IHqlExpression * args = static_cast<IHqlExpression *>(extra->queryParameters());
  477. ForEachChild(i, args)
  478. {
  479. if (i)
  480. parameterText.append(", ");
  481. ::generateExprCpp(parameterText, args->queryChild(i), compiler);
  482. }
  483. //Walk args and add the types
  484. result.addSuffix().append("(").append(parameterText).append(")");
  485. }
  486. break;
  487. case type_transform:
  488. default:
  489. throwUnexpected();
  490. }
  491. if (isPointer)
  492. {
  493. result.addPrefix("*");
  494. isPointer = false;
  495. }
  496. if (prefix)
  497. result.addPrefix(prefix);
  498. if (!next)
  499. {
  500. result.get(out);
  501. return;
  502. }
  503. type = next;
  504. }
  505. }
  506. void HqlCppWriter::generateInitializer(IHqlExpression * expr)
  507. {
  508. IValue * value = expr->queryValue();
  509. assertex(value);
  510. ITypeInfo * type = value->queryType();
  511. type_t tc = type->getTypeCode();
  512. size32_t size = value->getSize();
  513. const byte * raw = (const byte *)value->queryValue();
  514. out.append("{ ");
  515. switch (tc)
  516. {
  517. case type_data:
  518. case type_qstring:
  519. case type_decimal:
  520. {
  521. for (unsigned i=0; i < size; i++)
  522. {
  523. if (i)
  524. out.append(",");
  525. queryBreakLine();
  526. out.append((unsigned)raw[i]);
  527. }
  528. break;
  529. }
  530. case type_string:
  531. case type_varstring:
  532. case type_utf8:
  533. {
  534. for (unsigned i = 0; i < size; i++)
  535. {
  536. if (i)
  537. out.append(",");
  538. queryBreakLine();
  539. byte next = raw[i];
  540. switch (next)
  541. {
  542. case '\\': case '\'':
  543. out.append("'\\").append((char)next).append('\'');
  544. break;
  545. default:
  546. if (isprint(next))
  547. out.append('\'').append((char)next).append('\'');
  548. else
  549. out.append((int)next);
  550. break;
  551. }
  552. }
  553. break;
  554. }
  555. case type_unicode:
  556. case type_varunicode:
  557. {
  558. unsigned max = size/2;
  559. for (unsigned i = 0; i < max; i++)
  560. {
  561. if (i)
  562. out.append(",");
  563. queryBreakLine();
  564. UChar next = ((UChar *)raw)[i];
  565. switch (next)
  566. {
  567. case '\\': case '\'':
  568. out.append("'\\").append((char)next).append('\'');
  569. break;
  570. default:
  571. if ((next >= 32) && (next <= 126))
  572. out.append('\'').append((char)next).append('\'');
  573. else
  574. out.append((unsigned)next);
  575. break;
  576. }
  577. }
  578. break;
  579. }
  580. default:
  581. throwUnexpected();
  582. }
  583. out.append(" }");
  584. }
  585. static StringBuffer & appendCapital(StringBuffer & s, StringBuffer & _name)
  586. {
  587. const char * name = _name.str();
  588. if (name && name[0])
  589. {
  590. s.append((char)toupper(*name));
  591. s.append(name+1);
  592. }
  593. return s;
  594. }
  595. void HqlCppWriter::generateParamCpp(IHqlExpression * param)
  596. {
  597. ITypeInfo *paramType = param->queryType();
  598. //Case is significant if these parameters are use for BEGINC++ sections
  599. _ATOM paramName = param->queryName();
  600. StringBuffer paramNameText;
  601. paramNameText.append(paramName).toLowerCase();
  602. bool isOut = false;
  603. bool isConst = false;
  604. unsigned maxAttr = param->numChildren();
  605. unsigned attrIdx;
  606. for (attrIdx = 0; attrIdx < maxAttr; attrIdx++)
  607. {
  608. IHqlExpression * attr = param->queryChild(attrIdx);
  609. if (attr->isAttribute())
  610. {
  611. if (attr->queryName() == constAtom)
  612. isConst = true;
  613. else if (attr->queryName() == outAtom)
  614. isOut = true;
  615. }
  616. }
  617. switch (paramType->getTypeCode())
  618. {
  619. case type_string:
  620. case type_qstring:
  621. case type_data:
  622. case type_unicode:
  623. case type_utf8:
  624. case type_table:
  625. case type_groupedtable:
  626. if (paramType->getSize() == UNKNOWN_LENGTH)
  627. {
  628. out.append("size32_t");
  629. if (isOut)
  630. out.append(" &");
  631. if (paramName)
  632. appendCapital(out.append(" len"), paramNameText);
  633. out.append(",");
  634. }
  635. break;
  636. case type_set:
  637. if (!queryProperty(paramType, oldSetFormatAtom))
  638. {
  639. out.append("bool");
  640. if (paramName)
  641. appendCapital(out.append(" isAll"), paramNameText);
  642. out.append(",size32_t ");
  643. if(paramName)
  644. appendCapital(out.append(" len"), paramNameText);
  645. }
  646. else
  647. {
  648. out.append("unsigned");
  649. if(paramName)
  650. appendCapital(out.append(" num"), paramNameText);
  651. }
  652. out.append(",");
  653. break;
  654. case type_row:
  655. isConst = true;
  656. break;
  657. }
  658. bool nameappended = false;
  659. switch (paramType->getTypeCode())
  660. {
  661. case type_record:
  662. out.append("IOutputMetaData * ");
  663. break;
  664. case type_table:
  665. case type_groupedtable:
  666. if (isConst)
  667. out.append("const ");
  668. out.append("void *");
  669. if (isOut)
  670. out.append(" &");
  671. break;
  672. case type_set:
  673. if (!queryProperty(paramType, oldSetFormatAtom))
  674. {
  675. if (isConst)
  676. out.append("const ");
  677. out.append("void *");
  678. if (isOut)
  679. out.append(" &");
  680. break;
  681. }
  682. else
  683. {
  684. ITypeInfo* childType = paramType->queryChildType();
  685. if(!childType)
  686. break;
  687. if(isStringType(childType)) {
  688. // process stringn and varstringn specially.
  689. if(childType->getSize() > 0) {
  690. out.append("char ");
  691. if(paramName) {
  692. out.append(paramNameText);
  693. nameappended = true;
  694. }
  695. out.append("[][");
  696. unsigned setlen = childType->getSize();
  697. out.append(setlen);
  698. out.append("]");
  699. }
  700. // Process string and varstring specially
  701. else {
  702. out.append("char *");
  703. if(paramName) {
  704. out.append(paramNameText);
  705. nameappended = true;
  706. }
  707. out.append("[]");
  708. }
  709. }
  710. else
  711. {
  712. OwnedITypeInfo pointerType = makePointerType(LINK(childType));
  713. generateType(pointerType, NULL);
  714. }
  715. break;
  716. }
  717. // Other set types just fall through and will be treated like other types.
  718. case type_qstring: case type_string: case type_varstring: case type_data:
  719. default:
  720. {
  721. if (isConst)
  722. out.append("const ");
  723. Owned<ITypeInfo> argType = LINK(paramType);
  724. if (argType->getTypeCode() == type_function)
  725. argType.setown(makePointerType(LINK(argType)));
  726. if (isTypePassedByAddress(argType))
  727. argType.setown(makeReferenceModifier(LINK(argType)));
  728. generateType(argType, paramName->str());
  729. nameappended = true;
  730. if (isOut)
  731. out.append(" &");
  732. break;
  733. }
  734. }
  735. if (paramName && !nameappended)
  736. out.append(" ").append(paramNameText);
  737. }
  738. StringBuffer & HqlCppWriter::generateExprCpp(IHqlExpression * expr)
  739. {
  740. node_operator op = expr->getOperator();
  741. switch (op)
  742. {
  743. case no_constant:
  744. {
  745. unsigned prevLen = out.length();
  746. expr->queryValue()->generateCPP(out, compiler);
  747. outputLineNum += memcount(out.length()-prevLen,out.str()+prevLen,'\n');
  748. break;
  749. }
  750. case no_eq:
  751. case no_ne:
  752. case no_lt:
  753. case no_le:
  754. case no_gt:
  755. case no_ge:
  756. case no_mul:
  757. case no_div:
  758. case no_modulus:
  759. case no_add:
  760. case no_sub:
  761. case no_and:
  762. case no_or:
  763. case no_xor:
  764. case no_comma:
  765. case no_compound:
  766. case no_band:
  767. case no_bor:
  768. case no_bxor:
  769. case no_lshift:
  770. case no_rshift:
  771. {
  772. unsigned numArgs = expr->numChildren();
  773. for (unsigned index = 0; index < numArgs; index++)
  774. {
  775. if (index != 0)
  776. out.append(' ').append(getOpText(op)).append(' ');
  777. //would be nicer if it broke at PREFERRED_LINE_LIMIT if not inside a ()
  778. queryBreakLine();
  779. generateChildExpr(expr, index);
  780. }
  781. break;
  782. }
  783. case no_pselect:
  784. case no_select:
  785. generateExprCpp(expr->queryChild(0));
  786. out.append(getOpText(op));
  787. generateExprCpp(expr->queryChild(1));
  788. break;
  789. case no_if:
  790. {
  791. generateChildExpr(expr, 0);
  792. out.append(" ? ");
  793. queryBreakLine();
  794. generateChildExpr(expr, 1);
  795. out.append(" : ");
  796. queryBreakLine();
  797. generateChildExpr(expr, 2);
  798. break;
  799. }
  800. case no_list:
  801. {
  802. out.append('{');
  803. generateCommaChildren(expr);
  804. out.append('}');
  805. break;
  806. }
  807. case no_externalcall:
  808. {
  809. IHqlExpression *funcdef = expr->queryExternalDefinition();
  810. IHqlExpression *props = funcdef->queryChild(0);
  811. unsigned firstArg = 0;
  812. unsigned numArgs = expr->numChildren();
  813. if (props->hasProperty(ctxmethodAtom))
  814. {
  815. out.append("ctx->");
  816. }
  817. else if (props->hasProperty(gctxmethodAtom))
  818. {
  819. out.append("gctx->");
  820. }
  821. else if (props->hasProperty(methodAtom))
  822. {
  823. generateExprCpp(expr->queryChild(firstArg)).append("->");
  824. ++firstArg;
  825. }
  826. else if (props->hasProperty(omethodAtom))
  827. {
  828. generateExprCpp(expr->queryChild(firstArg)).append(".");
  829. ++firstArg;
  830. }
  831. getProperty(props, entrypointAtom, out);
  832. out.append('(');
  833. if (props->hasProperty(contextAtom))
  834. {
  835. out.append("ctx");
  836. if (numArgs)
  837. out.append(',');
  838. }
  839. else if (props->hasProperty(globalContextAtom))
  840. {
  841. out.append("gctx");
  842. if (numArgs)
  843. out.append(',');
  844. }
  845. for (unsigned index = firstArg; index < numArgs; index++)
  846. {
  847. if (index != firstArg) out.append(',');
  848. generateExprCpp(expr->queryChild(index));
  849. }
  850. out.append(')');
  851. break;
  852. }
  853. case no_cast:
  854. case no_implicitcast:
  855. {
  856. ITypeInfo * type = expr->queryType();
  857. IHqlExpression * child = expr->queryChild(0);
  858. if (hasWrapperModifier(child->queryType()))
  859. {
  860. generateChildExpr(expr, 0).append(".");
  861. switch (type->getTypeCode())
  862. {
  863. case type_string:
  864. case type_varstring:
  865. case type_qstring:
  866. case type_utf8:
  867. out.append("getstr()");
  868. break;
  869. case type_data:
  870. out.append("getdata()");
  871. break;
  872. case type_row:
  873. out.append("getbytes()");
  874. break;
  875. case type_set:
  876. case type_table:
  877. case type_groupedtable:
  878. if (hasLinkCountedModifier(type))
  879. out.append("queryrows()");
  880. else
  881. out.append("getbytes()");
  882. break;
  883. case type_unicode:
  884. case type_varunicode:
  885. out.append("getustr()");
  886. break;
  887. default:
  888. UNIMPLEMENTED;
  889. }
  890. break;
  891. }
  892. out.append("(");
  893. generateType(type, NULL);
  894. out.append(")");
  895. generateChildExpr(expr, 0);
  896. }
  897. break;
  898. case no_typetransfer:
  899. generateExprCpp(expr->queryChild(0));
  900. break;
  901. case no_translated:
  902. #ifdef _DEBUG
  903. out.append("$translated$");//Cause a compile error.
  904. #endif
  905. generateExprCpp(expr->queryChild(0));
  906. break;
  907. case no_order:
  908. generateOrderExpr(expr->queryChild(0), expr->queryChild(1));
  909. break;
  910. case no_index:
  911. generateChildExpr(expr, 0);
  912. out.append('[');
  913. generateChildExpr(expr, 1);
  914. out.append(']');
  915. break;
  916. case no_postinc:
  917. case no_postdec:
  918. generateChildExpr(expr, 0);
  919. out.append(getOpText(op));
  920. break;
  921. case no_reference:
  922. {
  923. IHqlExpression * child = expr->queryChild(0);
  924. generateChildExpr(expr, 0);
  925. if (hasWrapperModifier(child->queryType()))
  926. {
  927. out.append(".");
  928. ITypeInfo * type = expr->queryType();
  929. switch (type->getTypeCode())
  930. {
  931. case type_string:
  932. case type_varstring:
  933. case type_qstring:
  934. case type_utf8:
  935. out.append("refstr()");
  936. break;
  937. case type_data:
  938. out.append("refdata()");
  939. break;
  940. case type_row:
  941. out.append("getbytes()");
  942. break;
  943. case type_set:
  944. case type_table:
  945. case type_groupedtable:
  946. if (hasLinkCountedModifier(type))
  947. out.append("refrows()");
  948. else
  949. out.append("refdata()");
  950. break;
  951. case type_unicode:
  952. case type_varunicode:
  953. out.append("refustr()");
  954. break;
  955. }
  956. }
  957. break;
  958. }
  959. case no_address:
  960. {
  961. IHqlExpression * child = expr->queryChild(0);
  962. ITypeInfo * childType = child->queryType();
  963. if (hasWrapperModifier(childType))
  964. {
  965. generateChildExpr(expr, 0).append(".");
  966. switch (childType->getTypeCode())
  967. {
  968. case type_string:
  969. case type_varstring:
  970. case type_qstring:
  971. case type_utf8:
  972. out.append("addrstr()");
  973. break;
  974. case type_data:
  975. out.append("addrdata()");
  976. break;
  977. case type_row:
  978. throwUnexpected();
  979. out.append("getbytes()"); //????
  980. break;
  981. case type_set:
  982. case type_table:
  983. case type_groupedtable:
  984. if (hasLinkCountedModifier(childType))
  985. out.append("addrrows()");
  986. else
  987. out.append("addrdata()");
  988. break;
  989. case type_unicode:
  990. case type_varunicode:
  991. out.append("addrustr()");
  992. break;
  993. default:
  994. UNIMPLEMENTED;
  995. }
  996. }
  997. else
  998. {
  999. out.append(getOpText(op));
  1000. generateChildExpr(expr, 0);
  1001. }
  1002. break;
  1003. }
  1004. case no_negate:
  1005. case no_not:
  1006. case no_bnot:
  1007. case no_deref:
  1008. case no_preinc:
  1009. case no_predec:
  1010. out.append(getOpText(op));
  1011. generateChildExpr(expr, 0);
  1012. break;
  1013. case no_quoted:
  1014. case no_variable:
  1015. return expr->toString(out);
  1016. case no_field:
  1017. return expr->toString(out); //MORE!!!
  1018. case no_create_initializer:
  1019. generateInitializer(expr->queryChild(0));
  1020. break;
  1021. case no_pure:
  1022. case no_impure:
  1023. generateExprCpp(expr->queryChild(0));
  1024. break;
  1025. case no_param:
  1026. generateParamCpp(expr);
  1027. break;
  1028. case no_callback:
  1029. {
  1030. IHqlDelayedCodeGenerator * generator = (IHqlDelayedCodeGenerator *)expr->queryUnknownExtra();
  1031. generator->generateCpp(out);
  1032. break;
  1033. }
  1034. case no_funcdef:
  1035. {
  1036. IHqlExpression * body = expr->queryChild(0);
  1037. assertex(body->getOperator() == no_external);
  1038. IHqlExpression * entrypoint = queryPropertyChild(body, entrypointAtom, 0);
  1039. getStringValue(out, entrypoint);
  1040. break;
  1041. }
  1042. case no_nullptr:
  1043. out.append("NULL");
  1044. break;
  1045. // case no_self: return out.append("self");
  1046. default:
  1047. return expr->toString(out.append("<?")).append("?>");
  1048. }
  1049. return out;
  1050. }
  1051. StringBuffer & HqlCppWriter::generateChildExpr(IHqlExpression * expr, unsigned childIndex)
  1052. {
  1053. IHqlExpression * child = expr->queryChild(childIndex);
  1054. unsigned p = getPrecedence(expr);
  1055. unsigned cp = getPrecedence(child);
  1056. bool needBra = true;
  1057. if (p < cp)
  1058. needBra = false;
  1059. else if (p == cp)
  1060. {
  1061. if (isCast(expr) && isCast(child))
  1062. needBra = false;
  1063. node_operator op = expr->getOperator();
  1064. if (op == child->getOperator())
  1065. {
  1066. switch (op)
  1067. {
  1068. case no_and:
  1069. case no_or:
  1070. case no_add:
  1071. case no_band:
  1072. case no_bor:
  1073. needBra = false;
  1074. break;
  1075. }
  1076. }
  1077. }
  1078. if (!needBra)
  1079. return generateExprCpp(child);
  1080. out.append('(');
  1081. return generateExprCpp(child).append(')');
  1082. }
  1083. StringBuffer & HqlCppWriter::generateCommaChildren(IHqlExpression * expr)
  1084. {
  1085. unsigned numArgs = expr->numChildren();
  1086. unsigned startLength = out.length();
  1087. for (unsigned index = 0; index < numArgs; index++)
  1088. {
  1089. if (index != 0)
  1090. out.append(',');
  1091. unsigned newLength = out.length();
  1092. if (newLength - startLength > PREFERRED_LINE_LIMIT)
  1093. {
  1094. newline().append("\t");
  1095. startLength = out.length();
  1096. }
  1097. generateExprCpp(expr->queryChild(index));
  1098. }
  1099. return out;
  1100. }
  1101. StringBuffer & HqlCppWriter::generateExprAsChar(IHqlExpression * expr)
  1102. {
  1103. switch (expr->getOperator())
  1104. {
  1105. case no_constant:
  1106. {
  1107. StringBuffer temp;
  1108. IValue * value = expr->queryValue();
  1109. value->getStringValue(temp);
  1110. out.append((int)temp.charAt(0));
  1111. }
  1112. break;
  1113. default:
  1114. //create an indexed node and generate that - much better
  1115. generateExprCpp(expr).append("[0]");
  1116. break;
  1117. }
  1118. return out;
  1119. }
  1120. void HqlCppWriter::generateOrderExpr(IHqlExpression * left, IHqlExpression * right)
  1121. {
  1122. ITypeInfo * lType = left->queryType();
  1123. ITypeInfo * rType = right->queryType();
  1124. ITypeInfo * lBaseType = lType;
  1125. ITypeInfo * rBaseType = rType;
  1126. if (lType->getTypeCode() == type_pointer)
  1127. lBaseType = lType->queryChildType();
  1128. if (rType->getTypeCode() == type_pointer)
  1129. rBaseType = rType->queryChildType();
  1130. assertex(isSameBasicType(lBaseType, rBaseType));
  1131. switch (lBaseType->getTypeCode())
  1132. {
  1133. case type_string:
  1134. case type_data:
  1135. case type_qstring:
  1136. case type_varstring:
  1137. case type_unicode:
  1138. case type_varunicode:
  1139. case type_utf8:
  1140. {
  1141. throwUnexpectedType(lBaseType);
  1142. break;
  1143. }
  1144. default:
  1145. out.append("(");
  1146. generateExprCpp(left).append(" < ");
  1147. generateExprCpp(right).append(" ? -1 : ");
  1148. generateExprCpp(left).append(" > ");
  1149. generateExprCpp(right).append(" ? +1 : 0)");
  1150. break;
  1151. }
  1152. }
  1153. //---------------------------------------------------------------------------
  1154. HqlCppWriter::HqlCppWriter(StringBuffer & _out, CompilerType _compiler) : out(_out)
  1155. {
  1156. curIndent = 0;
  1157. startOffset = 0;
  1158. compiler = _compiler;
  1159. outputLineNum = 1;
  1160. }
  1161. HqlCppWriter::HqlCppWriter(CompilerType _compiler) : out(defaultOut)
  1162. {
  1163. curIndent = 0;
  1164. startOffset = 0;
  1165. compiler = _compiler;
  1166. outputLineNum = 1;
  1167. }
  1168. StringBuffer & HqlCppWriter::indent()
  1169. {
  1170. #ifdef INDENT_SOURCE
  1171. unsigned i = curIndent;
  1172. for (;i > 10;i-=10)
  1173. out.append("\t\t\t\t\t\t\t\t\t\t");
  1174. out.append(i, "\t\t\t\t\t\t\t\t\t\t");
  1175. #endif
  1176. return out;
  1177. }
  1178. void HqlCppWriter::flush()
  1179. {
  1180. if (target)
  1181. {
  1182. target->write(out.length(), out.toCharArray());
  1183. out.clear();
  1184. startOffset = 0;
  1185. }
  1186. }
  1187. void HqlCppWriter::generateStmtForPass(IHqlStmt * stmt, unsigned pass)
  1188. {
  1189. switch (stmt->getStmt())
  1190. {
  1191. case pass_stmt:
  1192. if (stmt->queryExpr(0)->queryValue()->getIntValue() == pass)
  1193. generateStmt(stmt);
  1194. break;
  1195. case indirect_stmt:
  1196. {
  1197. ForEachChild(i, stmt)
  1198. generateStmtForPass(stmt->queryChild(i), pass);
  1199. break;
  1200. }
  1201. default:
  1202. generateStmt(stmt);
  1203. break;
  1204. }
  1205. }
  1206. void HqlCppWriter::generateStatementsForPass(HqlStmts & stmts, unsigned delta, unsigned pass)
  1207. {
  1208. indent((int)delta);
  1209. ForEachItemIn(i, stmts)
  1210. generateStmtForPass(&stmts.item(i), pass);
  1211. indent(-(int)delta);
  1212. flush();
  1213. }
  1214. void HqlCppWriter::generate(HqlStmtArray & stmts)
  1215. {
  1216. ForEachItemIn(idx, stmts)
  1217. {
  1218. IHqlStmt & cur = stmts.item(idx);
  1219. generateStmt(&cur);
  1220. switch (cur.getStmt())
  1221. {
  1222. case break_stmt:
  1223. case return_stmt:
  1224. case goto_stmt:
  1225. case continue_stmt:
  1226. //After these, any other expressions are irrelevant..
  1227. return;
  1228. }
  1229. }
  1230. }
  1231. void HqlCppWriter::generateChildren(IHqlStmt * stmt, bool addBraces)
  1232. {
  1233. if (addBraces)
  1234. {
  1235. queryIndent().append("{");
  1236. newline();
  1237. indent(1);
  1238. }
  1239. unsigned count = stmt->numChildren();
  1240. for (unsigned index = 0; index < count; index++)
  1241. generateStmt(stmt->queryChild(index));
  1242. if (addBraces)
  1243. {
  1244. indent(-1);
  1245. indent().append("}");
  1246. newline();
  1247. }
  1248. }
  1249. void HqlCppWriter::generateStmt(IHqlStmt * stmt)
  1250. {
  1251. if (!stmt->isIncluded())
  1252. return;
  1253. unsigned kind = stmt->getStmt();
  1254. switch (kind)
  1255. {
  1256. case assign_stmt:
  1257. generateStmtAssign(stmt);
  1258. break;
  1259. case block_stmt:
  1260. generateChildren(stmt, true);
  1261. break;
  1262. case break_stmt:
  1263. indent().append("break;");
  1264. newline();
  1265. break;
  1266. case continue_stmt:
  1267. indent().append("continue;");
  1268. newline();
  1269. break;
  1270. case case_stmt:
  1271. generateStmtCase(stmt);
  1272. break;
  1273. case declare_stmt:
  1274. case external_stmt:
  1275. generateStmtDeclare(stmt);
  1276. break;
  1277. case default_stmt:
  1278. indent().append("default:");
  1279. generateChildren(stmt, true);
  1280. break;
  1281. case expr_stmt:
  1282. indent();
  1283. generateExprCpp(stmt->queryExpr(0)).append(';');
  1284. newline();
  1285. break;
  1286. case filter_stmt:
  1287. generateStmtFilter(stmt);
  1288. break;
  1289. case goto_stmt:
  1290. indent().append("goto ");
  1291. generateExprCpp(stmt->queryExpr(0)).append(';');
  1292. newline();
  1293. break;
  1294. case alias_stmt:
  1295. case group_stmt:
  1296. case pass_stmt:
  1297. case indirect_stmt:
  1298. generateChildren(stmt, false);
  1299. break;
  1300. case label_stmt:
  1301. generateExprCpp(stmt->queryExpr(0)).append(": ;");
  1302. newline();
  1303. break;
  1304. case loop_stmt:
  1305. generateStmtLoop(stmt);
  1306. break;
  1307. case line_stmt:
  1308. generateStmtLine(stmt);
  1309. break;
  1310. case quote_compoundopt_stmt:
  1311. case quote_stmt:
  1312. case quote_compound_stmt:
  1313. {
  1314. indent();
  1315. unsigned prevLen = out.length();
  1316. stmt->getTextExtra(out);
  1317. outputLineNum += memcount(out.length()-prevLen,out.str()+prevLen,'\n');
  1318. if (kind != quote_stmt)
  1319. {
  1320. out.append(" {");
  1321. newline();
  1322. indent(1);
  1323. generateChildren(stmt, false);
  1324. indent(-1);
  1325. indent().append("}");
  1326. IHqlExpression * extra = stmt->queryExpr(0);
  1327. if (extra)
  1328. generateExprCpp(extra);
  1329. newline();
  1330. }
  1331. else
  1332. newline();
  1333. break;
  1334. }
  1335. case return_stmt:
  1336. {
  1337. IHqlExpression * value = stmt->queryExpr(0);
  1338. if (value)
  1339. {
  1340. indent().append("return ");
  1341. generateExprCpp(stmt->queryExpr(0)).append(';');
  1342. }
  1343. else
  1344. indent().append("return;");
  1345. newline();
  1346. break;
  1347. }
  1348. case switch_stmt:
  1349. generateStmtSwitch(stmt);
  1350. break;
  1351. case assigninc_stmt:
  1352. case assigndec_stmt:
  1353. generateStmtAssignModify(stmt);
  1354. break;
  1355. }
  1356. }
  1357. void HqlCppWriter::generateSimpleAssign(IHqlExpression * target, IHqlExpression * source)
  1358. {
  1359. indent();
  1360. generateExprCpp(target).append(" = ");
  1361. generateExprCpp(source).append(";");
  1362. }
  1363. void HqlCppWriter::generateStmtAssign(IHqlStmt * assign)
  1364. {
  1365. IHqlExpression * target = assign->queryExpr(0);
  1366. IHqlExpression * source = assign->queryExpr(1);
  1367. ITypeInfo * type = target->queryType();
  1368. switch (type->getTypeCode())
  1369. {
  1370. case type_char:
  1371. case type_int:
  1372. case type_swapint:
  1373. case type_packedint:
  1374. case type_real:
  1375. case type_boolean:
  1376. case type_bitfield:
  1377. case type_pointer:
  1378. case type_enumerated:
  1379. case type_record:
  1380. generateSimpleAssign(target, source);
  1381. break;
  1382. case type_varstring:
  1383. case type_varunicode:
  1384. if (hasModifier(type, typemod_ref))
  1385. generateSimpleAssign(target, source);
  1386. else if (type->getSize() == UNKNOWN_LENGTH)
  1387. {
  1388. indent();
  1389. generateExprCpp(target).append(".setown(");
  1390. generateExprCpp(source).append(");");
  1391. }
  1392. else
  1393. throwUnexpected();
  1394. break;
  1395. case type_table:
  1396. case type_groupedtable:
  1397. if (hasWrapperModifier(type))
  1398. {
  1399. if (hasLinkCountedModifier(type))
  1400. {
  1401. assertex(source->getOperator() == no_complex);
  1402. indent();
  1403. generateExprCpp(target).append(".setown(");
  1404. generateExprCpp(source->queryChild(0)).append(",");
  1405. generateExprCpp(source->queryChild(1)).append(");");
  1406. }
  1407. else
  1408. {
  1409. indent();
  1410. generateExprCpp(target).append(".setown(");
  1411. generateExprCpp(source).append(");");
  1412. }
  1413. }
  1414. else
  1415. generateSimpleAssign(target, source);
  1416. break;
  1417. case type_set:
  1418. case type_row:
  1419. if (hasWrapperModifier(type))
  1420. {
  1421. indent();
  1422. generateExprCpp(target).append(".setown(");
  1423. generateExprCpp(source).append(");");
  1424. }
  1425. else
  1426. generateSimpleAssign(target, source);
  1427. break;
  1428. case type_qstring:
  1429. case type_string:
  1430. case type_data:
  1431. case type_unicode:
  1432. case type_utf8:
  1433. if (hasModifier(type, typemod_ref))
  1434. generateSimpleAssign(target, source);
  1435. else
  1436. throwUnexpected();
  1437. break;
  1438. default:
  1439. if (hasModifier(type, typemod_ref))
  1440. generateSimpleAssign(target, source);
  1441. else
  1442. {
  1443. type->getTypeCode();
  1444. assertex(!"Unexpected type assignment!");
  1445. generateSimpleAssign(target, source);
  1446. out.append("$$BadType$$");
  1447. }
  1448. break;
  1449. }
  1450. newline();
  1451. }
  1452. void HqlCppWriter::generateStmtAssignModify(IHqlStmt * assign)
  1453. {
  1454. IHqlExpression * target = assign->queryExpr(0);
  1455. IHqlExpression * source = assign->queryExpr(1);
  1456. ITypeInfo * type = target->queryType();
  1457. switch (type->getTypeCode())
  1458. {
  1459. case type_row:
  1460. case type_table:
  1461. case type_groupedtable:
  1462. //check it is a pointer increment
  1463. assertex(hasReferenceModifier(type));
  1464. case type_int:
  1465. case type_real:
  1466. case type_boolean:
  1467. case type_pointer:
  1468. indent();
  1469. generateExprCpp(target);
  1470. if (assign->getStmt() == assigninc_stmt)
  1471. out.append(" += ");
  1472. else
  1473. out.append(" -= ");
  1474. generateExprCpp(source).append(";");
  1475. break;
  1476. default:
  1477. throwUnexpected();
  1478. break;
  1479. }
  1480. newline();
  1481. }
  1482. void HqlCppWriter::generateStmtCase(IHqlStmt * stmt)
  1483. {
  1484. queryIndent().append("case ");
  1485. generateExprCpp(stmt->queryExpr(0)).append(":");
  1486. unsigned childCount = stmt->numChildren();
  1487. switch (childCount)
  1488. {
  1489. case 0:
  1490. //if case label contains nothing then it is commoned up with the next case
  1491. break;
  1492. case 1:
  1493. newline();
  1494. indent(1);
  1495. generateChildren(stmt, false);
  1496. if (stmt->queryChild(childCount-1)->getStmt() != return_stmt)
  1497. {
  1498. indent().append("break;");
  1499. newline();
  1500. }
  1501. indent(-1);
  1502. break;
  1503. default:
  1504. generateChildren(stmt, true);
  1505. if (stmt->queryChild(childCount-1)->getStmt() != return_stmt)
  1506. {
  1507. indent().append("break;");
  1508. newline();
  1509. }
  1510. }
  1511. }
  1512. void HqlCppWriter::generateStmtDeclare(IHqlStmt * declare)
  1513. {
  1514. IHqlExpression * name = declare->queryExpr(0);
  1515. IHqlExpression * value = declare->queryExpr(1);
  1516. ITypeInfo * type = name->queryType();
  1517. StringBuffer targetName;
  1518. assertex(name->getOperator() == no_variable);
  1519. name->toString(targetName);
  1520. if (declare->getStmt() == external_stmt)
  1521. out.append("extern ");
  1522. size32_t typeSize = type->getSize();
  1523. if (hasWrapperModifier(type))
  1524. {
  1525. if (hasModifier(type, typemod_builder))
  1526. indent().append("mutable rtlRowBuilder ").append(targetName);
  1527. else if (hasStreamedModifier(type))
  1528. {
  1529. indent().append("Owned<IRowStream> ").append(targetName);
  1530. }
  1531. else if (hasLinkCountedModifier(type))
  1532. {
  1533. if (type->getTypeCode() == type_row)
  1534. indent().append("rtlRowAttr ").append(targetName);
  1535. else
  1536. indent().append("rtlRowsAttr ").append(targetName);
  1537. }
  1538. else
  1539. indent().append("rtlDataAttr ").append(targetName);
  1540. }
  1541. else
  1542. {
  1543. indent();
  1544. generateType(type, targetName.str());
  1545. }
  1546. if (value)
  1547. {
  1548. out.append(" = ");
  1549. generateExprCpp(value);
  1550. }
  1551. out.append(";");
  1552. newline();
  1553. }
  1554. void HqlCppWriter::generateStmtFilter(IHqlStmt * stmt)
  1555. {
  1556. IHqlExpression * condition = stmt->queryExpr(0);
  1557. IValue * value = condition->queryValue();
  1558. //optimize generation of if (false) which can't be optimized earlier.
  1559. if (value)
  1560. {
  1561. IHqlStmt * folded = (value->getBoolValue()) ? stmt->queryChild(0) : stmt->queryChild(1);
  1562. if (folded)
  1563. {
  1564. if (folded->getStmt() == block_stmt)
  1565. generateChildren(folded, false);
  1566. else
  1567. generateStmt(folded);
  1568. }
  1569. }
  1570. else
  1571. {
  1572. indent().append("if (");
  1573. generateExprCpp(condition).append(")");
  1574. generateStmt(stmt->queryChild(0));
  1575. IHqlStmt * elseCode = stmt->queryChild(1);
  1576. if (elseCode)
  1577. {
  1578. indent().append("else");
  1579. generateStmt(elseCode);
  1580. }
  1581. }
  1582. }
  1583. void HqlCppWriter::generateStmtLoop(IHqlStmt * stmt)
  1584. {
  1585. IHqlExpression * cond = stmt->queryExpr(0);
  1586. IHqlExpression * inc = stmt->queryExpr(1);
  1587. bool atEnd = false;
  1588. if (inc)
  1589. {
  1590. if (inc->isAttribute())
  1591. {
  1592. atEnd = true;
  1593. inc = NULL;
  1594. }
  1595. else
  1596. {
  1597. if (stmt->queryExpr(2) != NULL)
  1598. atEnd = true;
  1599. }
  1600. }
  1601. if (atEnd)
  1602. {
  1603. indent().append("do {").newline();
  1604. indent(1);
  1605. generateChildren(stmt, false);
  1606. if (inc)
  1607. {
  1608. indent();
  1609. generateExprCpp(inc).append(";");
  1610. newline();
  1611. }
  1612. indent(-1);
  1613. indent().append("} while (");
  1614. generateExprCpp(cond);
  1615. out.append(");");
  1616. newline();
  1617. }
  1618. else
  1619. {
  1620. indent().append("for (;");
  1621. if (cond)
  1622. generateExprCpp(cond);
  1623. out.append(";");
  1624. if (inc)
  1625. generateExprCpp(inc);
  1626. out.append(")");
  1627. generateChildren(stmt, true);
  1628. }
  1629. }
  1630. void HqlCppWriter::generateStmtLine(IHqlStmt * stmt)
  1631. {
  1632. IHqlExpression * filename = stmt->queryExpr(0);
  1633. IHqlExpression * line = stmt->queryExpr(1);
  1634. if (filename && line)
  1635. {
  1636. out.append("#line ");
  1637. generateExprCpp(line).append(" ");
  1638. generateExprCpp(filename);
  1639. newline();
  1640. }
  1641. else
  1642. {
  1643. //NB: Sets the line number of the next line...
  1644. const char * targetFilename = targetFile->queryFilename();
  1645. out.append("#line ").append(outputLineNum+1).append(" \"");
  1646. appendStringAsCPP(out, strlen(targetFilename), targetFilename, false).append("\"");
  1647. newline();
  1648. }
  1649. }
  1650. void HqlCppWriter::generateStmtSwitch(IHqlStmt * stmt)
  1651. {
  1652. indent().append("switch (");
  1653. generateExprCpp(stmt->queryExpr(0)).append(")");
  1654. generateChildren(stmt, true);
  1655. }
  1656. StringBuffer & HqlCppWriter::newline()
  1657. {
  1658. outputLineNum++;
  1659. out.newline();
  1660. if (target && (out.length() > FILE_CHUNK_SIZE))
  1661. flush();
  1662. startOffset = out.length();
  1663. return out;
  1664. }
  1665. StringBuffer & HqlCppWriter::queryIndent()
  1666. {
  1667. if (out.length() - startOffset > REASONABLE_LINE_LIMIT)
  1668. newline();
  1669. if (out.length() == startOffset)
  1670. return indent();
  1671. return out.append(" ");
  1672. }
  1673. StringBuffer & HqlCppWriter::queryBreakLine()
  1674. {
  1675. if (out.length() - startOffset > REASONABLE_LINE_LIMIT)
  1676. {
  1677. newline();
  1678. indent().append("\t");
  1679. }
  1680. return out;
  1681. }
  1682. void HqlCppWriter::queryNewline()
  1683. {
  1684. if (out.length() != startOffset)
  1685. newline();
  1686. }
  1687. void HqlCppWriter::setOutput(IFile * _targetFile, IIOStream * _target)
  1688. {
  1689. flush();
  1690. targetFile.set(_targetFile);
  1691. target.set(_target);
  1692. out.ensureCapacity(FILE_CHUNK_SIZE + 2 * REASONABLE_LINE_LIMIT);
  1693. }
  1694. void HqlCppSectionWriter::generateSection(unsigned delta, _ATOM section, unsigned pass)
  1695. {
  1696. HqlStmts * match = instance.querySection(section);
  1697. if (match)
  1698. writer.generateStatementsForPass(*match, delta, pass);
  1699. }
  1700. //---------------------------------------------------------------------------
  1701. ITemplateExpander * createTemplateExpander(IFile * output, const char * filename, const char *dir)
  1702. {
  1703. Owned<CppWriterTemplate> expander = new CppWriterTemplate;
  1704. if (expander->loadTemplate(filename, dir) || expander->loadTemplate(filename, ""))
  1705. {
  1706. expander->setOutput(output);
  1707. return expander.getClear();
  1708. }
  1709. return NULL;
  1710. }
  1711. ISectionWriter * createCppWriter(IHqlCppInstance & _instance, CompilerType compiler)
  1712. {
  1713. return new HqlCppSectionWriter(_instance, compiler);
  1714. }
  1715. extern HQLCPP_API StringBuffer & generateExprCpp(StringBuffer & out, IHqlExpression * expr, CompilerType compiler)
  1716. {
  1717. HqlCppWriter writer(out, compiler);
  1718. writer.generateExprCpp(expr);
  1719. return out;
  1720. }
  1721. extern HQLCPP_API StringBuffer & generateTypeCpp(StringBuffer & out, ITypeInfo * type, const char * name, CompilerType compiler)
  1722. {
  1723. HqlCppWriter writer(out, compiler);
  1724. writer.generateType(type, name);
  1725. return out;
  1726. }