Hidl.cpp 54 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950
  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. //
  15. // HIDL compiler
  16. #define HIDLVER "1.0"
  17. #include "platform.h"
  18. #include <stdlib.h>
  19. #include <stdio.h>
  20. #include <ctype.h>
  21. #include <string.h>
  22. #include <stdarg.h>
  23. // TBD should have used yacc/lex - will do so when get time
  24. enum type_kind
  25. {
  26. TK_null,
  27. TK_CHAR,
  28. TK_UNSIGNEDCHAR,
  29. TK_SHORT,
  30. TK_UNSIGNEDSHORT,
  31. TK_INT,
  32. TK_UNSIGNED,
  33. TK_LONG,
  34. TK_UNSIGNEDLONG,
  35. TK_LONGLONG,
  36. TK_UNSIGNEDLONGLONG,
  37. TK_STRUCT,
  38. TK_VOID
  39. };
  40. #define PF_IN 1
  41. #define PF_OUT 2
  42. #define PF_VARSIZE 4
  43. #define PF_PTR 8
  44. #define PF_REF 0x10
  45. #define PF_CONST 0x40
  46. #define PF_SIMPLE 0x80
  47. #define PF_RETURN 0x100
  48. #define PF_STRING 0x200
  49. #define PF_MASK 0x7fff
  50. /*
  51. Allowed Parameter profiles
  52. in T - simple
  53. in T& - ref
  54. in size() T* - sized ptr
  55. inout T& - ref in/out
  56. inout size() T* - size is in only
  57. out T& - ref out only
  58. out size() T* - size is in only
  59. out size() T*& - size out only caller frees
  60. in string const char* - in string
  61. out string char *& - out string (caller frees)
  62. return (implied out):
  63. T - simple return
  64. size() T* - size out only caller frees
  65. */
  66. const char *type_name[] =
  67. {
  68. "??",
  69. "char",
  70. "unsigned char",
  71. "short",
  72. "unsigned short",
  73. "int",
  74. "unsigned",
  75. "long",
  76. "unsigned long",
  77. "long long",
  78. "unsigned long long",
  79. "",
  80. "void"
  81. };
  82. const char *clarion_type_name[] =
  83. {
  84. "??",
  85. "BYTE",
  86. "BYTE",
  87. "SHORT",
  88. "USHORT",
  89. "LONG",
  90. "ULONG",
  91. "LONG",
  92. "ULONG",
  93. "LONGLONG",
  94. "ULONGLONG",
  95. "",
  96. "BYTE"
  97. };
  98. const int type_size[] =
  99. {
  100. 1,
  101. 1,
  102. 1,
  103. 2,
  104. 2,
  105. 4,
  106. 4,
  107. 4,
  108. 4,
  109. 8,
  110. 8,
  111. 0,
  112. 1
  113. };
  114. #define RETURNNAME "_return"
  115. class ParamInfo
  116. {
  117. public:
  118. ParamInfo()
  119. {
  120. name = NULL;
  121. typname=NULL;
  122. size = NULL;
  123. flags = 0;
  124. next = NULL;
  125. kind = TK_null;
  126. sizebytes = NULL;
  127. }
  128. ~ParamInfo()
  129. {
  130. free(name);
  131. free(typname);
  132. free(size);
  133. free(sizebytes);
  134. }
  135. char *bytesize(int deref=0)
  136. {
  137. if (!size)
  138. return NULL;
  139. if (sizebytes)
  140. return sizebytes;
  141. char str[1024];
  142. if (type_size[kind]==1)
  143. if (deref) {
  144. strcpy(str,"*");
  145. strcat(str,size);
  146. sizebytes = strdup(str);
  147. return sizebytes;
  148. }
  149. else
  150. return size;
  151. strcpy(str,"sizeof(");
  152. if (kind==TK_STRUCT)
  153. strcat(str,typname);
  154. else
  155. strcat(str,type_name[kind]);
  156. strcat(str,")*(");
  157. if (deref)
  158. strcat(str,"*");
  159. strcat(str,size);
  160. strcat(str,")");
  161. sizebytes = strdup(str);
  162. return sizebytes;
  163. }
  164. int simpleneedsswap()
  165. {
  166. switch(kind) {
  167. case TK_SHORT:
  168. case TK_UNSIGNEDSHORT:
  169. case TK_INT:
  170. case TK_UNSIGNED:
  171. case TK_LONG:
  172. case TK_UNSIGNEDLONG:
  173. case TK_LONGLONG:
  174. case TK_UNSIGNEDLONGLONG:
  175. return 1;
  176. }
  177. return 0;
  178. }
  179. type_kind kind;
  180. char *name;
  181. char *typname;
  182. char *size;
  183. char *sizebytes;
  184. unsigned flags;
  185. ParamInfo *next;
  186. };
  187. #define ForEachParam(pr,pa,flagsset,flagsclear) for (pa=pr->params;pa;pa=pa->next) \
  188. if (((pa->flags&(flagsset))==(flagsset))&((pa->flags&(flagsclear))==0))
  189. #define INDIRECTSIZE(p) ((p->flags&(PF_PTR|PF_REF))==(PF_PTR|PF_REF))
  190. class ProcInfo
  191. {
  192. public:
  193. ProcInfo()
  194. {
  195. name = NULL;
  196. rettype = NULL;
  197. params = NULL;
  198. next = NULL;
  199. async = 0;
  200. virt = 0;
  201. callback = 0;
  202. }
  203. ~ProcInfo()
  204. {
  205. free(name);
  206. delete rettype;
  207. while (params) {
  208. ParamInfo *p=params;
  209. params = p->next;
  210. delete p;
  211. }
  212. }
  213. char * name;
  214. ParamInfo * rettype;
  215. ParamInfo * params;
  216. ProcInfo * next;
  217. int async;
  218. int virt;
  219. int callback;
  220. ParamInfo * firstin;
  221. ParamInfo * lastin;
  222. };
  223. class ModuleInfo
  224. {
  225. public:
  226. ModuleInfo(const char *n,size32_t l)
  227. {
  228. name = (char *)malloc(l+1);
  229. memcpy(name,n,l);
  230. name[l] = 0;
  231. version = 0;
  232. procs = NULL;
  233. next = NULL;
  234. }
  235. ~ModuleInfo()
  236. {
  237. free(name);
  238. while (procs) {
  239. ProcInfo *p=procs;
  240. procs = p->next;
  241. delete p;
  242. }
  243. }
  244. char *name;
  245. int version;
  246. ProcInfo *procs;
  247. ModuleInfo *next;
  248. };
  249. enum tok_kind {
  250. TOK_null,
  251. TOK_IDENT,
  252. TOK_NUMBER,
  253. TOK_CHARCONST,
  254. TOK_STRCONST,
  255. TOK_LPAREN,
  256. TOK_RPAREN,
  257. TOK_LBRACE,
  258. TOK_RBRACE,
  259. TOK_LBRACKET,
  260. TOK_RBRACKET,
  261. TOK_LANGLE,
  262. TOK_RANGLE,
  263. TOK_STAR,
  264. TOK_AMPERSAND,
  265. TOK_COMMA,
  266. TOK_EQUAL,
  267. TOK_COLON,
  268. TOK_SEMICOLON,
  269. TOK_CONST,
  270. TOK_INT,
  271. TOK_SHORT,
  272. TOK_LONG,
  273. TOK_UNSIGNED,
  274. TOK_FLOAT,
  275. TOK_DOUBLE,
  276. TOK_CHAR,
  277. TOK_VOID,
  278. TOK_MODULE,
  279. TOK_IN,
  280. TOK_INOUT,
  281. TOK_OUT,
  282. TOK_STRING,
  283. TOK_SIZE,
  284. TOK_ASYNC,
  285. TOK_CALLBACK,
  286. TOK_VIRTUAL,
  287. TOK_EOF
  288. };
  289. static const struct tokdef { tok_kind k; const char *n; } symbols[] =
  290. {
  291. {TOK_MODULE,"module"},
  292. {TOK_CONST, "const"},
  293. {TOK_VOID, "void"},
  294. {TOK_CHAR, "char"},
  295. {TOK_INT, "int"},
  296. {TOK_UNSIGNED, "unsigned"},
  297. {TOK_SHORT, "short"},
  298. {TOK_LONG, "long"},
  299. {TOK_FLOAT, "float"},
  300. {TOK_DOUBLE, "double"},
  301. {TOK_IN, "in"},
  302. {TOK_OUT, "out"},
  303. {TOK_INOUT, "inout"},
  304. {TOK_STRING, "string"},
  305. {TOK_SIZE,"size"},
  306. {TOK_ASYNC,"async"},
  307. {TOK_CALLBACK,"callback"},
  308. {TOK_VIRTUAL,"virtual"},
  309. {TOK_EOF, "??????"},
  310. };
  311. class token {
  312. public:
  313. tok_kind kind;
  314. const char *str; //in buffer
  315. size32_t len;
  316. char *copystr() { char *ret=(char *)malloc(len+1); memcpy(ret,str,len); ret[len] = 0; return ret; }
  317. int integer()
  318. {
  319. size32_t l=len;
  320. if (l>15)
  321. l = 15;
  322. char num[16];
  323. memcpy(num,str,l);
  324. num[l] = 0;
  325. return atoi(num);
  326. }
  327. };
  328. class HIDLcompiler
  329. {
  330. protected:
  331. const char *start;
  332. const char *s;
  333. int lineno;
  334. token t;
  335. int outfile;
  336. void error(const char *err)
  337. {
  338. printf("ERROR: line %d: %s\n",lineno,err);
  339. const char *sp=s;
  340. while ((sp!=start)&&((s-sp<10)||(*(sp-1)!='\n')))
  341. sp--;
  342. printf("Near the end of:\n-----\n");
  343. char *ln = (char *)malloc(s-sp+1);
  344. memcpy(ln,sp,s-sp);
  345. ln[s-sp] = 0;
  346. printf("%s\n-----\n",ln);
  347. free(ln);
  348. exit(1);
  349. }
  350. int parse_strconst()
  351. {
  352. t.str = s+1;
  353. do {
  354. s++;
  355. if (*s=='\\')
  356. s++;
  357. if (*s==0) {
  358. error("\" expected");
  359. return 0;
  360. }
  361. } while (*s!='"');
  362. t.kind = TOK_STRCONST;
  363. t.len = s-t.str;
  364. s++;
  365. return 1;
  366. }
  367. int parse_chrconst()
  368. {
  369. t.str = s+1;
  370. do {
  371. s++;
  372. if (*s=='\\')
  373. s++;
  374. if (*s==0)
  375. return 0;
  376. } while (*s!='\'');
  377. t.kind = TOK_CHARCONST;
  378. t.len = s-t.str;
  379. s++;
  380. return 1;
  381. }
  382. int parse_int()
  383. {
  384. t.str = s;
  385. do {
  386. s++;
  387. if (*s=='\\')
  388. s++;
  389. if (*s==0)
  390. return 0;
  391. } while (isalnum(*s));
  392. t.kind = TOK_NUMBER;
  393. t.len = s-t.str;
  394. return 1;
  395. }
  396. int parse_id()
  397. {
  398. t.str = s;
  399. do {
  400. s++;
  401. if (*s=='\\')
  402. s++;
  403. if (*s==0)
  404. return 0;
  405. } while (isalnum(*s)||(*s=='_'));
  406. t.len = s-t.str;
  407. for (int i=0;symbols[i].k!=TOK_EOF;i++) {
  408. if (memcmp(t.str,symbols[i].n,t.len)==0) {
  409. if (symbols[i].n[t.len]==0) {
  410. t.kind = symbols[i].k;
  411. return 1;
  412. }
  413. }
  414. }
  415. t.kind = TOK_IDENT;
  416. return 1;
  417. }
  418. char *parse_paren_str()
  419. {
  420. int pc = 1;
  421. const char *st=s;
  422. while (1) {
  423. if (*s==')')
  424. if (--pc==0)
  425. break;
  426. else if (*s=='(')
  427. pc++;
  428. else if (*s==0) {
  429. error(") expected");
  430. return NULL;
  431. }
  432. s++;
  433. }
  434. char *ret = (char *)malloc(s-st+1);
  435. memcpy(ret,st,s-st);
  436. ret[s-st] = 0;
  437. return ret;
  438. }
  439. int nexttoken()
  440. {
  441. t.kind = TOK_null;
  442. t.str = NULL;
  443. t.len = 0;
  444. while (1) {
  445. switch (*s) {
  446. case 0: return 0;
  447. case ':': t.kind = TOK_COLON; s++; return 1;
  448. case ';': t.kind = TOK_SEMICOLON; s++; return 1;
  449. case ',': t.kind = TOK_COMMA; s++; return 1;
  450. case '=': t.kind = TOK_EQUAL; s++; return 1;
  451. case '*': t.kind = TOK_STAR; s++; return 1;
  452. case '[': t.kind = TOK_LBRACKET; s++; return 1;
  453. case ']': t.kind = TOK_RBRACKET; s++; return 1;
  454. case '{': t.kind = TOK_LBRACE; s++; return 1;
  455. case '}': t.kind = TOK_RBRACE; s++; return 1;
  456. case '(': t.kind = TOK_LPAREN; s++; return 1;
  457. case ')': t.kind = TOK_RPAREN; s++; return 1;
  458. case '<': t.kind = TOK_LANGLE; s++; return 1;
  459. case '>': t.kind = TOK_RANGLE; s++; return 1;
  460. case '&': t.kind = TOK_AMPERSAND; s++; return 1;
  461. case '"': return parse_strconst();
  462. case '\'': return parse_chrconst();
  463. case ' ':
  464. case '\t':
  465. case '\r':
  466. break;
  467. case '\n':
  468. lineno++;
  469. break;
  470. case '/': if (s[1]=='/') {
  471. do {
  472. s++;
  473. } while ((s[1]!=0)&&(s[1]!='\n'));
  474. }
  475. else if (s[1]=='*') {
  476. do {
  477. s++;
  478. if (*s=='\n')
  479. lineno++;
  480. if (*s==0) {
  481. error("*/ expected");
  482. return 0;
  483. }
  484. } while ((s[0]!='*')||(s[1]!='/'));
  485. }
  486. break;
  487. case '-':
  488. case '0':
  489. case '1':
  490. case '2':
  491. case '3':
  492. case '4':
  493. case '5':
  494. case '6':
  495. case '7':
  496. case '8':
  497. case '9': return parse_int();
  498. default:
  499. if (isalpha(*s)||(*s=='_'))
  500. return parse_id();
  501. error("unexpected character");
  502. }
  503. s++;
  504. }
  505. return 0;
  506. }
  507. tok_kind gettoken()
  508. {
  509. if (nexttoken())
  510. return t.kind;
  511. error("Premature EOF");
  512. return TOK_null;
  513. }
  514. int expects(tok_kind k)
  515. {
  516. nexttoken();
  517. return (t.kind==k);
  518. }
  519. int skip_to_module()
  520. {
  521. int i=0;
  522. for (;symbols[i].k!=TOK_MODULE;i++);
  523. const char *m=symbols[i].n;
  524. size32_t l = strlen(m);
  525. while (*s) {
  526. while (isspace(*s))
  527. s++;
  528. if (memcmp(s,m,l)==0) {
  529. if (isspace(s[l])) {
  530. return 1;
  531. }
  532. }
  533. while (*s!='\n') {
  534. if (!*s) {
  535. return 0;
  536. }
  537. s++;
  538. }
  539. lineno++;
  540. s++;
  541. }
  542. return 0;
  543. }
  544. int check_param(ProcInfo *pi,ParamInfo *p)
  545. {
  546. if ((pi->async)&&(p->flags&(PF_OUT|PF_RETURN))) {
  547. error("out parameters not allowed on async procedure");
  548. return 0;
  549. }
  550. if ((p->flags&(PF_CONST&PF_OUT))==(PF_CONST|PF_OUT)) {
  551. error("const not allowed on out parameter");
  552. return 0;
  553. }
  554. switch (p->flags&(PF_IN|PF_OUT|PF_STRING|PF_VARSIZE|PF_PTR|PF_REF|PF_RETURN)) {
  555. case PF_IN: // int T
  556. case (PF_IN|PF_REF): // in T&
  557. case (PF_IN|PF_OUT|PF_REF): // inout T&
  558. case (PF_OUT|PF_REF): // out T&
  559. return 1;
  560. case (PF_IN|PF_PTR|PF_VARSIZE): // in size() T*
  561. case (PF_OUT|PF_PTR|PF_VARSIZE): // out size() T*
  562. case (PF_IN|PF_OUT|PF_PTR|PF_VARSIZE): // inout size() T*
  563. // should check size is in here
  564. return 1;
  565. case (PF_OUT|PF_PTR|PF_REF|PF_VARSIZE): // inout size() T*&
  566. // should check size is out here
  567. return 1;
  568. case (PF_IN|PF_PTR|PF_STRING): // in string const char *
  569. case (PF_OUT|PF_PTR|PF_REF|PF_STRING): // out string char *&
  570. // should check char or unsigned char
  571. return 1;
  572. case (PF_OUT|PF_RETURN): // return simple
  573. return 1;
  574. case (PF_OUT|PF_RETURN|PF_STRING|PF_PTR): // return char *
  575. return 1;
  576. case (PF_OUT|PF_PTR|PF_VARSIZE|PF_RETURN): // return size() T*
  577. // should check size is out here
  578. return 1;
  579. }
  580. printf("Parameter flags %x\n",p->flags);
  581. if (p->flags&PF_RETURN)
  582. error("Invalid return type");
  583. else
  584. error("Invalid parameter combination");
  585. return 0; // TBD
  586. }
  587. ParamInfo *parse_param(ProcInfo *pi,int rettype)
  588. {
  589. ParamInfo *p = new ParamInfo;
  590. while (1) {
  591. switch (t.kind) {
  592. case TOK_IN:
  593. p->flags |= PF_IN;
  594. break;
  595. case TOK_OUT:
  596. p->flags |= PF_OUT;
  597. break;
  598. case TOK_INOUT:
  599. p->flags |= (PF_IN|PF_OUT);
  600. break;
  601. case TOK_STRING:
  602. p->flags |= PF_STRING;
  603. break;
  604. case TOK_SIZE:
  605. if (!expects(TOK_LPAREN)) {
  606. error("( expected");
  607. Error:
  608. delete p;
  609. return NULL;
  610. }
  611. p->size = parse_paren_str();
  612. p->flags |= PF_VARSIZE;
  613. if (!expects(TOK_RPAREN)) {
  614. error(") expected");
  615. goto Error;
  616. }
  617. break;
  618. case TOK_IDENT:
  619. // assume it is a name until the second ID
  620. if (rettype) {
  621. if (p->kind==TK_null) {
  622. p->kind = TK_STRUCT;
  623. p->typname = t.copystr();
  624. }
  625. else if ((p->kind==TK_VOID)&&((p->flags&PF_PTR)==0)) {
  626. delete p;
  627. return NULL;
  628. }
  629. else {
  630. p->flags |= (PF_OUT|PF_RETURN);
  631. p->name = strdup(RETURNNAME);
  632. goto Exit;
  633. }
  634. break;
  635. }
  636. if (p->name) {
  637. if (p->kind==TK_null) {
  638. p->kind = TK_STRUCT;
  639. p->typname = p->name;
  640. }
  641. else {
  642. error("unknown/unexpected ID");
  643. goto Error;
  644. }
  645. }
  646. p->name = t.copystr();
  647. break;
  648. case TOK_COMMA:
  649. case TOK_RPAREN:
  650. if (p->kind==TK_null) {
  651. error("no type specified");
  652. goto Error;
  653. }
  654. if (!p->name) {
  655. error("no name specified");
  656. goto Error;
  657. }
  658. if ((p->flags&(PF_OUT|PF_IN))==0) {
  659. p->flags |= PF_IN;
  660. }
  661. Exit:
  662. if (!check_param(pi,p)) {
  663. goto Error;
  664. }
  665. return p;
  666. case TOK_CHAR:
  667. switch (p->kind) {
  668. case TK_UNSIGNED: p->kind = TK_UNSIGNEDCHAR; break;
  669. case TK_null: p->kind = TK_CHAR; break;
  670. default: {
  671. Error2:
  672. error("invalid type");
  673. goto Error;
  674. }
  675. }
  676. break;
  677. case TOK_SHORT:
  678. switch (p->kind) {
  679. case TK_UNSIGNED: p->kind = TK_UNSIGNEDSHORT; break;
  680. case TK_null: p->kind = TK_SHORT; break;
  681. default:
  682. goto Error2;
  683. }
  684. break;
  685. case TOK_VOID:
  686. p->kind = TK_VOID;
  687. break;
  688. case TOK_INT:
  689. switch (p->kind) {
  690. case TK_UNSIGNED: break;
  691. case TK_SHORT: p->kind = TK_SHORT; break;
  692. case TK_LONG: p->kind = TK_LONG; break;
  693. case TK_null: p->kind = TK_INT; break;
  694. default:
  695. goto Error2;
  696. }
  697. break;
  698. case TOK_UNSIGNED:
  699. switch (p->kind) {
  700. case TK_null: p->kind = TK_UNSIGNED; break;
  701. default:
  702. goto Error2;
  703. }
  704. break;
  705. case TOK_LONG:
  706. switch (p->kind) {
  707. case TK_LONG: p->kind = TK_LONGLONG; break;
  708. case TK_UNSIGNED: p->kind = TK_UNSIGNEDLONG; break;
  709. case TK_UNSIGNEDLONG: p->kind = TK_UNSIGNEDLONGLONG; break;
  710. case TK_null: p->kind = TK_LONG; break;
  711. default:
  712. goto Error2;
  713. }
  714. break;
  715. case TOK_STAR:
  716. if (p->flags&(PF_PTR|PF_REF)) {
  717. Error3:
  718. error("parameter type not supported");
  719. goto Error;
  720. }
  721. p->flags|=PF_PTR;
  722. break;
  723. case TOK_AMPERSAND:
  724. if (p->flags&PF_REF) {
  725. goto Error3;
  726. }
  727. p->flags|=PF_REF;
  728. break;
  729. case TOK_CONST:
  730. p->flags|=PF_CONST;
  731. break;
  732. default:
  733. error("unexpected symbol");
  734. goto Error;
  735. }
  736. gettoken();
  737. }
  738. return NULL;
  739. }
  740. ProcInfo *parse_proc()
  741. {
  742. ProcInfo *pi=new ProcInfo;
  743. while (1) {
  744. switch (t.kind) {
  745. case TOK_ASYNC:
  746. pi->async = 1;
  747. gettoken();
  748. continue;
  749. case TOK_CALLBACK:
  750. pi->callback = 1;
  751. gettoken();
  752. continue;
  753. case TOK_VIRTUAL:
  754. pi->virt = 1;
  755. gettoken();
  756. continue;
  757. }
  758. break;
  759. }
  760. pi->rettype = parse_param(pi,1);
  761. if (pi->async && pi->rettype) {
  762. error("Return not allowed");
  763. Error:
  764. delete pi;
  765. return NULL;
  766. }
  767. if (t.kind!=TOK_IDENT) {
  768. error("Identifier expected");
  769. goto Error;
  770. }
  771. pi->name = t.copystr();
  772. ParamInfo *last = NULL;
  773. if (!expects(TOK_LPAREN)) {
  774. error("parameter definition expected");
  775. goto Error;
  776. }
  777. gettoken();
  778. while (t.kind!=TOK_RPAREN) {
  779. ParamInfo *p=parse_param(pi,0);
  780. if (last)
  781. last->next = p;
  782. else
  783. pi->params = p;
  784. last = p;
  785. if (t.kind==TOK_COMMA)
  786. gettoken();
  787. }
  788. nexttoken();
  789. if (pi->virt&&(t.kind==TOK_EQUAL)) {
  790. if (!expects(TOK_NUMBER)) { // 0 actually
  791. goto Error;
  792. }
  793. nexttoken();
  794. pi->virt = 2;
  795. }
  796. if (t.kind!=TOK_SEMICOLON) {
  797. goto Error;
  798. }
  799. gettoken();
  800. return pi;
  801. }
  802. void out(const char *s,size32_t l)
  803. {
  804. write(outfile,s,l);
  805. }
  806. void outs(const char *s)
  807. {
  808. out(s,strlen(s));
  809. }
  810. void outf(const char *fmt, ...) __attribute__((format(printf, 2, 3)))
  811. {
  812. static char buf[0x4000];
  813. va_list args;
  814. va_start(args, fmt);
  815. vsprintf(buf, fmt, args);
  816. va_end(args);
  817. outs(buf);
  818. }
  819. void cat_type(char *s,ParamInfo *p,int deref=0,int var=0)
  820. {
  821. if (p==NULL) {
  822. strcat(s,"void");
  823. return;
  824. }
  825. if ((p->flags&PF_CONST)&&!var)
  826. strcat(s,"const ");
  827. if (p->typname)
  828. strcat(s,p->typname);
  829. else
  830. strcat(s,type_name[p->kind]);
  831. if (!deref) {
  832. if (p->flags&PF_PTR)
  833. strcat(s," *");
  834. if (p->flags&PF_REF)
  835. strcat(s," &");
  836. }
  837. }
  838. void out_type(ParamInfo *p,int deref=0,int var=0)
  839. {
  840. char s[256];
  841. s[0] = 0;
  842. cat_type(s,p,deref,var);
  843. outs(s);
  844. }
  845. void typesizeacc(ParamInfo *p,char *accstr,size32_t &acc)
  846. {
  847. if ((p->kind==TK_STRUCT)||(p->flags&(PF_PTR|PF_REF))) {
  848. acc = (acc+3)&~3;
  849. if (*accstr)
  850. strcat(accstr,"+");
  851. strcat(accstr,"sizeof(");
  852. cat_type(accstr,p);
  853. strcat(accstr,")");
  854. }
  855. else {
  856. size32_t sz=type_size[p->kind];
  857. if (sz==2)
  858. acc = (acc+1)&~1;
  859. else if (sz>=4)
  860. acc = (acc+3)&~3;
  861. acc += type_size[p->kind];
  862. }
  863. }
  864. size32_t typesizealign(ParamInfo *p,size32_t &ofs)
  865. {
  866. size32_t ret=0;
  867. if ((p->kind==TK_STRUCT)||(p->flags&(PF_PTR|PF_REF))) {
  868. if (ofs) {
  869. ret = 4-ofs;
  870. ofs = 0;
  871. }
  872. }
  873. else {
  874. size32_t sz=type_size[p->kind];
  875. if (sz==1) {
  876. ret = 0;
  877. ofs = (ofs+1)%4;
  878. }
  879. else if (sz==2) {
  880. ret = (ofs&1);
  881. ofs = (ofs+ret+2)%4;
  882. }
  883. else {
  884. if (ofs) {
  885. ret = 4-ofs;
  886. ofs = 0;
  887. }
  888. }
  889. }
  890. return ret;
  891. }
  892. enum clarion_special_type_enum { cte_normal,cte_longref,cte_constcstr,cte_cstr };
  893. clarion_special_type_enum clarion_special_type(ParamInfo *p)
  894. {
  895. if ((type_size[p->kind]==1)&&((p->flags&(PF_PTR|PF_REF))==PF_PTR)) {
  896. if ((p->flags&PF_CONST)==0)
  897. return cte_cstr;
  898. return cte_constcstr;
  899. }
  900. else if (p->flags&PF_PTR) { // no support - convert to long
  901. return cte_longref;
  902. }
  903. return cte_normal;
  904. }
  905. void out_clarion_type(ParamInfo *p)
  906. {
  907. clarion_special_type_enum cte = clarion_special_type(p);
  908. if (p->flags&PF_REF) {
  909. outs("*");
  910. }
  911. if (cte==cte_longref) {
  912. outs("LONG");
  913. }
  914. else if (cte==cte_cstr) {
  915. outs("*CSTRING");
  916. }
  917. else if (cte==cte_constcstr) {
  918. outs("CONST *CSTRING");
  919. }
  920. else if (p->typname) {
  921. outs(p->typname);
  922. }
  923. else {
  924. outs(clarion_type_name[p->kind]);
  925. }
  926. }
  927. void out_parameter_list(ParamInfo *p,const char *pfx,int forclarion=0)
  928. {
  929. outs("(");
  930. while (p) {
  931. if (forclarion && (clarion_special_type(p)==cte_cstr))
  932. outs("int, ");
  933. out_type(p);
  934. outf(" %s%s",pfx,p->name);
  935. p = p->next;
  936. if (p)
  937. outs(", ");
  938. }
  939. outs(")");
  940. }
  941. void out_clarion_parameter_list(ParamInfo *p)
  942. {
  943. outs("(");
  944. while (p) {
  945. out_clarion_type(p);
  946. outs(" ");
  947. if (clarion_special_type(p)==cte_longref)
  948. outs("REF_");
  949. outs(p->name);
  950. p = p->next;
  951. if (p)
  952. outs(", ");
  953. }
  954. outs(")");
  955. }
  956. void out_method(ProcInfo *pi,const char *classpfx=NULL)
  957. {
  958. if (pi->virt&&!classpfx)
  959. outf("HRPCvirtual%s ",pi->callback?"callback":"");
  960. out_type(pi->rettype);
  961. if (classpfx)
  962. outf(" %s::%s",classpfx,pi->name);
  963. else
  964. outf(" %s",pi->name);
  965. out_parameter_list(pi->params,"");
  966. if ((pi->virt==2)&&!classpfx)
  967. outf(" HRPCpure%s",pi->callback?"callback":"");
  968. }
  969. void write_header_class(ModuleInfo *mi)
  970. {
  971. int hasvirts = 0;
  972. ProcInfo *pi;
  973. for (pi=mi->procs; pi; pi=pi->next) {
  974. if (pi->virt) {
  975. hasvirts = 1;
  976. break;
  977. }
  978. }
  979. outf("#ifdef LOCAL_%s\n",mi->name);
  980. outf("#define %s STUB_%s\n",mi->name,mi->name);
  981. if (hasvirts) {
  982. outs("#define HRPCvirtual virtual\n");
  983. outs("#define HRPCpure =0\n");
  984. outs("#define HRPCvirtualcallback\n");
  985. outs("#define HRPCpurecallback\n");
  986. }
  987. outf("class %s : public HRPCstub\n",mi->name);
  988. outs("#else\n");
  989. if (hasvirts) {
  990. outs("#define HRPCvirtual\n");
  991. outs("#define HRPCpure\n");
  992. outs("#define HRPCvirtualcallback virtual\n");
  993. outs("#define HRPCpurecallback =0\n");
  994. }
  995. outf("class %s : public HRPCmodule\n",mi->name);
  996. outs("#endif\n");
  997. outs("{\npublic:\n");
  998. outf("\t%s();\n",mi->name);
  999. for (pi=mi->procs; pi; pi=pi->next) {
  1000. outs("\t");
  1001. out_method(pi);
  1002. outs(";\n");
  1003. }
  1004. outf("private:\n");
  1005. outf("#ifdef LOCAL_%s\n",mi->name);
  1006. outf("\tvoid _stub(HRPCbuffer &_b,HRPCbuffer &_rb,int fn);\n");
  1007. outs("#else\n");
  1008. outf("\tvoid _callbackstub(HRPCbuffer &_b,HRPCbuffer &_rb,int fn);\n");
  1009. outs("#endif\n");
  1010. if (hasvirts) {
  1011. outs("#undef HRPCvirtual\n");
  1012. outs("#undef HRPCpure\n");
  1013. outs("#undef HRPCvirtualcallback\n");
  1014. outs("#undef HRPCpurecallback\n");
  1015. }
  1016. outs("};\n");
  1017. }
  1018. void write_body_struct_elem(ParamInfo *p,int ref)
  1019. {
  1020. outs("\t");
  1021. out_type(p,ref,1);
  1022. if (ref&&(p->flags&(PF_REF|PF_PTR))) {
  1023. outs(" *");
  1024. if ((p->flags&(PF_REF|PF_PTR))==(PF_REF|PF_PTR)) {
  1025. outs(" *");
  1026. }
  1027. }
  1028. outf(" %s;\n",p->name);
  1029. }
  1030. void writeheadsize(ProcInfo *pi)
  1031. // used for simple types only at the head of the packet
  1032. {
  1033. if (pi->lastin) {
  1034. char sz[2048];
  1035. sz[0] = 0;
  1036. size32_t sza=0;
  1037. ParamInfo *p=pi->params;
  1038. while (1) {
  1039. if (p->flags&PF_SIMPLE) {
  1040. typesizeacc(p,sz,sza);
  1041. }
  1042. if(p==pi->lastin)
  1043. break;
  1044. p = p->next;
  1045. }
  1046. if (*sz) {
  1047. outs(sz);
  1048. if (sza)
  1049. outf("+%d",sza);
  1050. }
  1051. else
  1052. outf("%d",sza);
  1053. }
  1054. else
  1055. outs("0");
  1056. }
  1057. void write_offsetof(ModuleInfo *mi,ProcInfo *pi,ParamInfo *p,int inclusive,const char *pfx=NULL)
  1058. {
  1059. if (p) {
  1060. outf("offsetof(const struct HRPC_d_%s__%s,%s%s",mi->name,pi->name,pfx?pfx:"",p->name);
  1061. if (inclusive) {
  1062. outs(")+sizeof(");
  1063. out_type(p);
  1064. }
  1065. outs(")");
  1066. }
  1067. else
  1068. outf("0");
  1069. }
  1070. void write_param_convert(ParamInfo *p,int deref=0)
  1071. {
  1072. outs("(");
  1073. out_type(p,1,1);
  1074. if (p->flags&(PF_REF|PF_PTR)) {
  1075. if (!deref)
  1076. outs(" *");
  1077. if ((p->flags&(PF_REF|PF_PTR))==(PF_REF|PF_PTR)) {
  1078. outs(" *");
  1079. }
  1080. }
  1081. outs(")");
  1082. }
  1083. int write_body_swapparam(ModuleInfo *mi,ProcInfo *pi)
  1084. {
  1085. int ret=0;
  1086. ParamInfo *p;
  1087. ForEachParam(pi,p,PF_IN|PF_SIMPLE,PF_VARSIZE|PF_STRING) {
  1088. if(p->simpleneedsswap()) {
  1089. if (!ret) {
  1090. outs("\tvoid swapparams()\n\t{\n");
  1091. ret = 1;
  1092. }
  1093. outf("\t\t_WINREV%d(%s);\n",type_size[p->kind],p->name);
  1094. }
  1095. }
  1096. if (ret)
  1097. outs("\t}\n\n");
  1098. return ret;
  1099. }
  1100. void write_body_pushparam(ModuleInfo *mi,ProcInfo *pi,int swapp)
  1101. {
  1102. outs("\tvoid pushparams(HRPCbuffer &_b)\n\t{\n");
  1103. if (swapp)
  1104. outs("\t\t//swapparams();\n");
  1105. if (pi->lastin) {
  1106. outf("\t\t_b.write(&%s,",pi->firstin->name);
  1107. writeheadsize(pi);
  1108. outs(");\n");
  1109. }
  1110. ParamInfo *p;
  1111. ForEachParam(pi,p,PF_IN,PF_SIMPLE|PF_VARSIZE|PF_STRING) {
  1112. if (p->simpleneedsswap()) {
  1113. outf("\t\t//_b.writerev(%s,sizeof(*%s));\n",p->name,p->name);
  1114. outf("\t\t_b.write(%s,sizeof(*%s));\n",p->name,p->name);
  1115. }
  1116. else
  1117. outf("\t\t_b.write(%s,sizeof(*%s));\n",p->name,p->name);
  1118. }
  1119. ForEachParam(pi,p,PF_IN|PF_STRING,PF_SIMPLE|PF_VARSIZE) {
  1120. outf("\t\t_b.writestr(%s);\n",p->name);
  1121. }
  1122. // now dynamic sizes
  1123. ForEachParam(pi,p,PF_VARSIZE|PF_IN,0) {
  1124. if (INDIRECTSIZE(p)) {
  1125. // should handle size32_t* as well as ref
  1126. outf("\t\t_b.write(%s,%s);\n",p->name,p->bytesize());
  1127. }
  1128. else {
  1129. outf("\t\t_b.write(%s,%s);\n",p->name,p->bytesize());
  1130. }
  1131. }
  1132. outs("\t}\n\n");
  1133. }
  1134. void write_body_popparam(ModuleInfo *mi,ProcInfo *pi,int swapp)
  1135. {
  1136. outs("\tvoid popparams(HRPCbuffer &_b)\n\t{\n");
  1137. if (pi->lastin) {
  1138. outf("\t\t_b.read(&%s,",pi->firstin->name);
  1139. writeheadsize(pi);
  1140. outs(");\n");
  1141. }
  1142. int needensure=0;
  1143. ParamInfo *p;
  1144. ForEachParam(pi,p,PF_OUT,PF_IN|PF_SIMPLE) {
  1145. if (needensure) {
  1146. outs("\t\t\t+");
  1147. }
  1148. else {
  1149. outs("\t\t_b.ensure(\n");
  1150. outs("\t\t\t");
  1151. needensure = 1;
  1152. }
  1153. if ((p->flags&PF_VARSIZE)&&!(INDIRECTSIZE(p))) {
  1154. outf("(%s)\n",p->bytesize());
  1155. }
  1156. else {
  1157. outf("sizeof(*%s)\n",p->name);
  1158. }
  1159. }
  1160. if (needensure) {
  1161. outs("\t\t);\n");
  1162. }
  1163. ForEachParam(pi,p,PF_OUT,PF_IN|PF_SIMPLE|PF_VARSIZE|PF_STRING) {
  1164. outf("\t\t%s = ",p->name);
  1165. write_param_convert(p);
  1166. outf("_b.writeptr(sizeof(*%s));\n",p->name);
  1167. }
  1168. ForEachParam(pi,p,PF_OUT|PF_STRING,0) {
  1169. outf("\t\t%s = ",p->name);
  1170. write_param_convert(p);
  1171. outf("_b.writeptr(sizeof(*%s));\n",p->name);
  1172. outf("\t\t*%s = 0;\n",p->name);
  1173. }
  1174. ForEachParam(pi,p,PF_IN,PF_SIMPLE|PF_VARSIZE|PF_STRING) {
  1175. outf("\t\t%s = ",p->name);
  1176. write_param_convert(p);
  1177. outf("_b.readptr(sizeof(*%s));\n",p->name);
  1178. outf("\t\t\t//_b.readptrrev(sizeof(*%s));\n",p->name);
  1179. }
  1180. ForEachParam(pi,p,PF_IN|PF_STRING,PF_SIMPLE|PF_VARSIZE) {
  1181. outf("\t\t%s = _b.readstrptr();\n",p->name);
  1182. }
  1183. // now dynamic sizes
  1184. ForEachParam(pi,p,PF_VARSIZE|PF_IN,0) {
  1185. outf("\t\t%s = ",p->name);
  1186. write_param_convert(p);
  1187. if (INDIRECTSIZE(p)) {
  1188. // should handle size32_t* as well as ref
  1189. outs("_b.readptr(sizeof");
  1190. write_param_convert(p);
  1191. outs(")\n");
  1192. }
  1193. else {
  1194. outf("_b.readptr(%s);\n",p->bytesize());
  1195. }
  1196. }
  1197. ForEachParam(pi,p,PF_OUT|PF_VARSIZE,PF_IN|PF_SIMPLE) {
  1198. outf("\t\t%s = ",p->name);
  1199. write_param_convert(p);
  1200. outs("_b.writeptr(");
  1201. if ((p->flags&PF_VARSIZE)&&!(INDIRECTSIZE(p))) {
  1202. outf("%s);\n",p->bytesize());
  1203. }
  1204. else {
  1205. outf("sizeof(*%s));\n",p->name);
  1206. }
  1207. }
  1208. if (swapp)
  1209. outs("\t\t//swapparams();\n");
  1210. outs("\t}\n\n");
  1211. }
  1212. void write_body_pushreturn(ModuleInfo *mi,ProcInfo *pi)
  1213. {
  1214. if (!pi->async) {
  1215. outs("\tvoid pushreturn(HRPCbuffer &_b)\n\t{\n");
  1216. ParamInfo *p;
  1217. ForEachParam(pi,p,PF_OUT,PF_SIMPLE|PF_VARSIZE|PF_STRING) {
  1218. outf("\t\t_b.write(%s,sizeof(*%s));\n",p->name,p->name);
  1219. }
  1220. ForEachParam(pi,p,PF_OUT|PF_STRING,0) {
  1221. outf("\t\t_b.writestr(*%s);\n",p->name);
  1222. outf("\t\tfree(*%s);\n",p->name);
  1223. }
  1224. // now dynamic sizes
  1225. ForEachParam(pi,p,PF_VARSIZE|PF_OUT,0) {
  1226. if (INDIRECTSIZE(p)) {
  1227. // should handle size32_t* as well as ref
  1228. outf("\t\t_b.write(*%s,%s);\n",p->name,p->bytesize(1));
  1229. outf("\t\tfree(*%s);\n",p->name);
  1230. }
  1231. else {
  1232. outf("\t\t_b.write(%s,%s);\n",p->name,p->bytesize());
  1233. }
  1234. }
  1235. p = pi->rettype;
  1236. if (p) {
  1237. if ((p->flags&(PF_PTR|PF_STRING))==(PF_PTR|PF_STRING)) {
  1238. outf("\t\t_b.writestr(%s);\n",p->name);
  1239. outf("\t\tfree(%s);\n",p->name);
  1240. }
  1241. else if (p->flags&PF_PTR) {
  1242. outf("\t\t_b.write(%s,%s);\n",p->name,p->bytesize(1));
  1243. outf("\t\tfree(%s);\n",p->name);
  1244. }
  1245. else {
  1246. outf("\t\t_b.write(&%s,sizeof(%s));\n",p->name,p->name);
  1247. }
  1248. }
  1249. outs("\t}\n\n");
  1250. }
  1251. }
  1252. void write_body_popreturn(ModuleInfo *mi,ProcInfo *pi)
  1253. {
  1254. if (!pi->async) {
  1255. outs("\tvoid popreturn(HRPCbuffer &_b)\n\t{\n");
  1256. ParamInfo *p;
  1257. ForEachParam(pi,p,PF_OUT,PF_SIMPLE|PF_VARSIZE|PF_RETURN|PF_STRING) {
  1258. outf("\t\t_b.read(%s,sizeof(*%s));\n",p->name,p->name);
  1259. }
  1260. ForEachParam(pi,p,PF_OUT|PF_STRING,0) {
  1261. outf("\t\t*%s = _b.readstrdup();\n",p->name);
  1262. }
  1263. // now dynamic sizes
  1264. ForEachParam(pi,p,PF_VARSIZE|PF_OUT,0) {
  1265. if (INDIRECTSIZE(p)) {
  1266. outf("\t\t*%s = ",p->name);
  1267. write_param_convert(p,1);
  1268. outf("malloc(%s);\n",p->bytesize(1));
  1269. outf("\t\t_b.read(*%s,%s);\n",p->name,p->bytesize(1));
  1270. }
  1271. else {
  1272. outf("\t\t_b.read(%s,%s);\n",p->name,p->bytesize());
  1273. }
  1274. }
  1275. p = pi->rettype;
  1276. if (p) {
  1277. if ((p->flags&(PF_PTR|PF_STRING))==(PF_PTR|PF_STRING)) {
  1278. outf("\t\t%s = _b.readstrdup();\n",p->name);
  1279. }
  1280. else if (p->flags&PF_PTR) {
  1281. outf("\t\t%s = ",p->name);
  1282. write_param_convert(p);
  1283. outf("malloc(%s);\n",p->bytesize(1));
  1284. outf("\t\t_b.read(%s,%s);\n",p->name,p->bytesize(1));
  1285. }
  1286. else {
  1287. outf("\t\t_b.read(&%s,sizeof(%s));\n",p->name,p->name);
  1288. }
  1289. }
  1290. outs("\t}\n\n");
  1291. }
  1292. }
  1293. void write_body_method_structs2(int fn,ModuleInfo *mi,ProcInfo *pi) {
  1294. // buffer structure
  1295. outf("struct HRPC_d_%s__%s\n{\n",mi->name,pi->name);
  1296. ParamInfo *p;
  1297. pi->lastin=NULL;
  1298. pi->firstin=NULL;
  1299. ForEachParam(pi,p,0,0)
  1300. p->flags &= ~PF_SIMPLE;
  1301. size32_t align=0;
  1302. int dummy = 0;
  1303. ForEachParam(pi,p,PF_IN,PF_OUT|PF_REF|PF_PTR|PF_VARSIZE) {
  1304. p->flags |= PF_SIMPLE;
  1305. pi->lastin = p;
  1306. if (!pi->firstin)
  1307. pi->firstin = p;
  1308. size32_t a=typesizealign(p,align);
  1309. if (a>0) {
  1310. dummy++;
  1311. if (a>1)
  1312. outf("\tchar __dummy%d[%d];\n",dummy,a);
  1313. else
  1314. outf("\tchar __dummy%d;\n",dummy,a);
  1315. }
  1316. write_body_struct_elem(p,0);
  1317. }
  1318. if (align>0) {
  1319. dummy++;
  1320. outf("\tchar _dummy%d[%d];\n",dummy,4-align);
  1321. align = 0;
  1322. }
  1323. ForEachParam(pi,p,PF_IN,PF_OUT|PF_SIMPLE) {
  1324. write_body_struct_elem(p,1);
  1325. }
  1326. ForEachParam(pi,p,PF_IN|PF_OUT,PF_SIMPLE) {
  1327. write_body_struct_elem(p,1);
  1328. }
  1329. ForEachParam(pi,p,PF_OUT,PF_IN|PF_SIMPLE) {
  1330. write_body_struct_elem(p,1);
  1331. }
  1332. if (pi->rettype) {
  1333. typesizealign(pi->rettype,align);
  1334. write_body_struct_elem(pi->rettype,0);
  1335. if (align>0) {
  1336. dummy++;
  1337. outf("\tchar _dummy%d[%d];\n",dummy,4-align);
  1338. align = 0;
  1339. }
  1340. }
  1341. int swapp=write_body_swapparam(mi,pi);
  1342. write_body_pushparam(mi,pi,swapp);
  1343. write_body_popparam(mi,pi,swapp);
  1344. if (!pi->async) {
  1345. write_body_pushreturn(mi,pi);
  1346. write_body_popreturn(mi,pi);
  1347. }
  1348. // now constructors
  1349. outf("\tHRPC_d_%s__%s() {}\n",mi->name,pi->name);
  1350. if (pi->params) {
  1351. outf("\tHRPC_d_%s__%s",mi->name,pi->name);
  1352. out_parameter_list(pi->params,"_");
  1353. outs(": ");
  1354. ForEachParam(pi,p,0,0) {
  1355. outf("%s(",p->name);
  1356. if (p->flags&PF_REF) {
  1357. outs("&");
  1358. }
  1359. else if ((p->flags&(PF_PTR&PF_CONST))==(PF_PTR&PF_CONST)) {
  1360. write_param_convert(p);
  1361. }
  1362. outf("_%s)",p->name);
  1363. if (p->next)
  1364. outs(", ") ;
  1365. }
  1366. outs("\n\t{\n");
  1367. outs("\t};");
  1368. }
  1369. outs("\n};\n");
  1370. }
  1371. void write_body_class_stub(ModuleInfo *mi,int cb)
  1372. {
  1373. outf("void %s::_%sstub(HRPCbuffer &_b,HRPCbuffer &_br,int fn)\n{\n",mi->name,cb?"callback":"");
  1374. int fn=0;
  1375. int switchdone = 0;
  1376. ProcInfo *pi;
  1377. for (pi=mi->procs; pi; pi=pi->next) {
  1378. fn++;
  1379. if (cb!=pi->callback)
  1380. continue;
  1381. if (!switchdone) {
  1382. outs("\tswitch(fn) {\n");
  1383. switchdone = 1;
  1384. }
  1385. outf("\tcase %d: {\n",fn);
  1386. outf("\t\t\tHRPC_d_%s__%s _params;\n",mi->name,pi->name,mi->name,pi->name);
  1387. outs("\t\t\t_params.popparams(_b);\n");
  1388. if (pi->async) {
  1389. outs("\t\t\t_returnasync(_br);\n");
  1390. }
  1391. outs("\t\t\t");
  1392. if (pi->rettype) {
  1393. outf("_params.%s = ",RETURNNAME);
  1394. }
  1395. outf("%s(",pi->name);
  1396. ParamInfo *p;
  1397. ForEachParam(pi,p,0,0) {
  1398. if (p->flags&PF_REF)
  1399. outs("*");
  1400. outf("_params.%s",p->name);
  1401. if (p->next)
  1402. outs(", ");
  1403. }
  1404. outs(");\n");
  1405. if (!pi->async) {
  1406. outs("\t\t\t_returnOK(_br);\n");
  1407. outs("\t\t\t_params.pushreturn(_br);\n");
  1408. }
  1409. outs("\t\t\tbreak;\n");
  1410. outs("\t\t}\n");
  1411. }
  1412. if (switchdone) {
  1413. outs("\t}\n");
  1414. }
  1415. outs("}\n\n");
  1416. }
  1417. void write_body_class_proxy(ModuleInfo *mi,int cb)
  1418. {
  1419. int fn = 0;
  1420. ProcInfo *pi;
  1421. for (pi=mi->procs; pi; pi=pi->next) {
  1422. fn++;
  1423. if (cb!=pi->callback)
  1424. continue;
  1425. out_method(pi,mi->name);
  1426. outs("\n{\n");
  1427. if (pi->callback) {
  1428. outs("\tHRPCcallframe _callframe(&_server->Sync(),cbbuff);\n");
  1429. }
  1430. else {
  1431. outs("\tHRPCcallframe _callframe(sync,inbuff);\n");
  1432. }
  1433. outf("\tHRPC_d_%s__%s _params",mi->name,pi->name);
  1434. if (pi->params) {
  1435. outs("(");
  1436. ParamInfo *p;
  1437. ForEachParam(pi,p,0,0) {
  1438. outf("%s",p->name);
  1439. if (p->next)
  1440. outs(", ");
  1441. }
  1442. outs(")");
  1443. }
  1444. outs(";\n");
  1445. if (pi->callback) {
  1446. outs("\t_params.pushparams(cbbuff);\n");
  1447. outf("\t_callbackproxy(_callframe,%d);\n",fn);
  1448. if (!pi->async)
  1449. outs("\t_params.popreturn(cbbuff);\n");
  1450. }
  1451. else {
  1452. outs("\t_params.pushparams(inbuff);\n");
  1453. outf("\t_proxy(_callframe,%d);\n",fn);
  1454. if (!pi->async)
  1455. outs("\t_params.popreturn(inbuff);\n");
  1456. }
  1457. if (pi->rettype) {
  1458. outf("\treturn _params.%s;\n",RETURNNAME);
  1459. }
  1460. outs("}\n\n");
  1461. }
  1462. outs("\n\n");
  1463. }
  1464. void write_body_class(ModuleInfo *mi)
  1465. {
  1466. outf("// class %s \n\n",mi->name);
  1467. outf("static struct HRPCmoduleid _id_%s = { { ",mi->name);
  1468. char *mn = mi->name;
  1469. for (int i=0;i<8;i++) {
  1470. if (i)
  1471. outs(", ");
  1472. if (*mn) {
  1473. outf("'%c'",*mn);
  1474. mn++;
  1475. }
  1476. else
  1477. outs("0");
  1478. }
  1479. outf("}, %d };\n\n",mi->version);
  1480. ProcInfo *pi;
  1481. int fn=0;
  1482. for (pi=mi->procs; pi; pi=pi->next) {
  1483. fn++;
  1484. write_body_method_structs2(fn,mi,pi);
  1485. }
  1486. outs("\n");
  1487. outf("%s::%s() { _id = &_id_%s; }\n\n",mi->name,mi->name,mi->name);
  1488. outf("#ifdef LOCAL_%s // Stub(%s):\n\n",mi->name,mi->name);
  1489. write_body_class_stub(mi,0);
  1490. write_body_class_proxy(mi,1);
  1491. outf("#else // Proxy(%s):\n\n",mi->name);
  1492. write_body_class_proxy(mi,0);
  1493. write_body_class_stub(mi,1);
  1494. outf("#endif // end class %s\n",mi->name);
  1495. }
  1496. void write_clarion_interface_class(ModuleInfo *mi)
  1497. {
  1498. outs("extern \"C\" {\n\n");
  1499. outs("\n");
  1500. outf("// clarion interface class CIC_%s \n",mi->name);
  1501. outf("struct HRPCI_%s: public HRPCI_Clarion_Module // interface\n",mi->name);
  1502. ProcInfo *pi;
  1503. outs("{\n");
  1504. for (pi=mi->procs; pi; pi=pi->next) {
  1505. if (pi->callback)
  1506. continue;
  1507. outs("\tvirtual ");
  1508. out_type(pi->rettype);
  1509. outf(" _stdcall %s",pi->name);
  1510. out_parameter_list(pi->params,"",1);
  1511. outs("=0;\n");
  1512. }
  1513. outs("};\n");
  1514. outf("#ifndef LOCAL_%s\n\n",mi->name);
  1515. outf("class CIC_%s : public HRPCI_%s\n",mi->name,mi->name);
  1516. outs("{\n");
  1517. outs("public:\n");
  1518. outf("\t%s _o;\n",mi->name);
  1519. outs("\tmutable unsigned xxcount;\n");
  1520. for (pi=mi->procs; pi; pi=pi->next) {
  1521. if (pi->callback)
  1522. continue;
  1523. outs("\t");
  1524. out_type(pi->rettype);
  1525. outf(" _stdcall %s",pi->name);
  1526. out_parameter_list(pi->params,"",1);
  1527. outs("\n");
  1528. outs("\t{\n");
  1529. outs("\t\t");
  1530. if (pi->rettype) {
  1531. outs("return ");
  1532. }
  1533. outf("_o.%s(",pi->name);
  1534. ParamInfo *p;
  1535. ForEachParam(pi,p,0,0) {
  1536. outf("%s",p->name);
  1537. if (p->next)
  1538. outs(", ");
  1539. }
  1540. outs(");\n");
  1541. outs("\t}\n");
  1542. }
  1543. outf("\tCIC_%s() { xxcount = 0; }\n",mi->name);
  1544. outs("\tvoid _stdcall Link() const { ++xxcount; }\n");
  1545. outs("\tint _stdcall Release() const {if (xxcount == 0) { delete this; return 1; } --xxcount; return 0; }\n");
  1546. outs("\tvoid _stdcall FreeMem(void *p) { free(p); }\n");
  1547. outs("};\n");
  1548. outf("CIC_%s* PASCAL HRPC_Make_%s(HRPCI_Clarion_Transport *t)\n",mi->name,mi->name);
  1549. outs("{\n");
  1550. outf("\tCIC_%s *ret=new CIC_%s;\n",mi->name,mi->name);
  1551. outs("\tret->_o.UseTransport(t->GetTransport());\n");
  1552. outs("\treturn ret;\n");
  1553. outs("}\n");
  1554. outs("#endif\n");
  1555. outs("}\n");
  1556. }
  1557. void write_example_module(ModuleInfo *mi)
  1558. {
  1559. outf("void %s_Server()\n",mi->name);
  1560. outs("{\n");
  1561. outs("\tHRPCserver server(MakeTcpTransport(NULL,PORTNO)); // PORTNO TBD\n");
  1562. outf("\t%s stub;\n",mi->name);
  1563. outs("\tserver.AttachStub(&stub); // NB a server can service more than one module\n");
  1564. outs("\tserver.Listen();\n");
  1565. outs("}\n\n");
  1566. ProcInfo *pi;
  1567. for (pi=mi->procs; pi; pi=pi->next) {
  1568. out_method(pi,mi->name);
  1569. outs("\n{\n");
  1570. outf("\t // TBD\n");
  1571. if (pi->rettype) {
  1572. outs("\treturn TBD;\n");
  1573. }
  1574. outs("}\n\n");
  1575. }
  1576. }
  1577. void write_clarion_include_module(ModuleInfo *mi)
  1578. {
  1579. outf("HRPCI_%s INTERFACE(HRPCI_Clarion_Module)\r\n",mi->name);
  1580. ProcInfo *pi;
  1581. for (pi=mi->procs; pi; pi=pi->next) {
  1582. if (pi->callback)
  1583. continue;
  1584. outf("%-15s PROCEDURE",pi->name);
  1585. out_clarion_parameter_list(pi->params);
  1586. if (pi->rettype) {
  1587. outs(",");
  1588. out_clarion_type(pi->rettype);
  1589. }
  1590. outs(",PASCAL\r\n");
  1591. }
  1592. outs(" END\r\n\r\n");
  1593. }
  1594. public:
  1595. void ProcessHIDL(char *sp,int ho,int cppo,int xsvo,int clwo,const char *packagename)
  1596. {
  1597. lineno = 1;
  1598. outfile = ho;
  1599. ModuleInfo *first=NULL;
  1600. ModuleInfo *last;
  1601. ModuleInfo *mi;
  1602. outf("// *** Include file generated by HIDL Version %s from %s.hid ***\n",HIDLVER,packagename);
  1603. outf("// *** Not to be hand edited (changes will be lost on re-generation) ***\n\n");
  1604. outf("#include \"hrpc.hpp\"\n\n");
  1605. start = sp;
  1606. s = sp;
  1607. while (*s) {
  1608. const char *p=s;
  1609. int eof = !skip_to_module();
  1610. out(p,s-p);
  1611. if (eof)
  1612. break;
  1613. gettoken(); // skip module
  1614. if (!expects(TOK_IDENT)) {
  1615. error("Module name expected");
  1616. break;
  1617. }
  1618. mi = new ModuleInfo(t.str,t.len);
  1619. if (first)
  1620. last->next = mi;
  1621. else {
  1622. first = mi;
  1623. }
  1624. last = mi;
  1625. while (1) {
  1626. if (gettoken()==TOK_LBRACE)
  1627. break;
  1628. if (t.kind==TOK_LPAREN) {
  1629. if (expects(TOK_NUMBER)) {
  1630. mi->version = t.integer();
  1631. if ((mi->version>255)||(mi->version<0))
  1632. error("version must be in range 0-255");
  1633. if (!expects(TOK_RPAREN)) {
  1634. error(") expected");
  1635. }
  1636. }
  1637. else
  1638. error("Version number expected");
  1639. }
  1640. else {
  1641. error("{ expected");
  1642. return;
  1643. }
  1644. }
  1645. ProcInfo *last=NULL;
  1646. gettoken();
  1647. while (t.kind!=TOK_RBRACE) {
  1648. ProcInfo *pi = parse_proc();
  1649. if (!pi)
  1650. break;
  1651. if (last)
  1652. last->next = pi;
  1653. else
  1654. mi->procs = pi;
  1655. last = pi;
  1656. }
  1657. if (!expects(TOK_SEMICOLON)) {
  1658. error("; expected after }");
  1659. break;
  1660. }
  1661. write_header_class(mi);
  1662. }
  1663. outs("//end\r\n"); // CR for Clarion
  1664. outfile = cppo;
  1665. outf("// *** Source file generated by HIDL Version %s from %s.hid ***\n",HIDLVER,packagename);
  1666. outf("// *** Not to be hand edited (changes will be lost on re-generation) ***\n\n");
  1667. outf("#include \"%s.hpp\"\n\n",packagename);
  1668. for (mi=first;mi;mi=mi->next) {
  1669. write_body_class(mi);
  1670. write_clarion_interface_class(mi);
  1671. }
  1672. outs("//end\r\n"); // CR for Clarion
  1673. outfile = xsvo;
  1674. outs("// Example Server Implementation Template\n");
  1675. outf("// Source file generated by HIDL Version %s from %s.hid\n",HIDLVER,packagename);
  1676. outs("// *** You should copy this file before changing, as it will be overwritten next time HIDL is run ***\n\n");
  1677. outs("#include <stddef.h>\n");
  1678. outs("#include <stdlib.h>\n");
  1679. outs("#include <assert.h>\n\n");
  1680. outs("#include \"hrpcsock.hpp\"// default use TCP/IP sockets\n\n");
  1681. outs("// TBD - Add other includes here\n\n");
  1682. for (mi=first;mi;mi=mi->next) {
  1683. outf("#define LOCAL_%s // implementation of %s\n",mi->name,mi->name);
  1684. }
  1685. outf("#include \"%s.cpp\"\n\n",packagename);
  1686. for (mi=first;mi;mi=mi->next) {
  1687. write_example_module(mi);
  1688. }
  1689. outfile = clwo;
  1690. outs("! Clarion HRPC Interfaces\r\n");
  1691. outf("! Include file generated by HIDL Version %s from %s.hid\r\n",HIDLVER,packagename);
  1692. outs("! *** Not to be hand edited (changes will be lost on re-generation) ***\r\n\r\n");
  1693. outf(" OMIT('EndOfInclude',_%s_I_)\r\n",packagename);
  1694. outf("_%s_I_ EQUATE(1)\r\n\r\n",packagename);
  1695. outs(" INCLUDE('HRPC.INC'),ONCE\r\n\r\n");
  1696. for (mi=first;mi;mi=mi->next) {
  1697. write_clarion_include_module(mi);
  1698. }
  1699. outs("\r\n");
  1700. outs(" MAP\r\n");
  1701. outf(" MODULE('%s')\r\n",packagename);
  1702. for (mi=first;mi;mi=mi->next) {
  1703. outf(" HRPC_Make_%s(HRPCI_Clarion_Transport transport),*HRPCI_%s,PASCAL,NAME('_HRPC_Make_%s@4')\r\n",mi->name,mi->name,mi->name);
  1704. }
  1705. outs(" END\r\n\r\n");
  1706. outs(" END\r\n\r\n");
  1707. outf("\r\nEndOfInclude\r\n");
  1708. while (first) {
  1709. mi = first;
  1710. first = mi->next;
  1711. delete mi;
  1712. }
  1713. }
  1714. };
  1715. char *gettail(const char *fn)
  1716. {
  1717. const char *e=NULL;
  1718. const char *e1=fn;
  1719. while((e1=strchr(e1,'.'))!=NULL)
  1720. e = e1++;
  1721. const char *s=fn;
  1722. const char *s1;
  1723. #ifdef _WIN32
  1724. if (*s&&s[1]==':')
  1725. s+=2;
  1726. #endif
  1727. for (s1 = s;*s1&&(s1!=e);s1++)
  1728. #ifdef _WIN32
  1729. if (*s1=='\\')
  1730. #else
  1731. if (*s1=='/')
  1732. #endif
  1733. s = s1+1;
  1734. size32_t l = s1-s;
  1735. char *ret = (char *)malloc(l+1);
  1736. memcpy(ret,s,l);
  1737. ret[l] = 0;
  1738. return ret;
  1739. }
  1740. char *changeext(const char *fn,const char *ext)
  1741. {
  1742. char *ret=gettail(fn);
  1743. size32_t l = strlen(ret);
  1744. ret = (char *)realloc(ret,l+strlen(ext)+2);
  1745. ret[l] = '.';
  1746. strcpy(ret+l+1,ext);
  1747. return ret;
  1748. }
  1749. int main(int argc, char* argv[])
  1750. {
  1751. if (argc<2) {
  1752. printf("HIDL Compiler Version %s\n\n",HIDLVER);
  1753. printf("Usage: HIDL filename.hid [<outdir>] \n\n");
  1754. printf("Output: filename.cpp\n");
  1755. printf(" filename.hpp\n");
  1756. printf(" filename.xsv\n");
  1757. printf(" (the xsv file is an example server implementation template)\n");
  1758. return 1;
  1759. }
  1760. char *path=changeext(argv[1],"hid");
  1761. int hi = open(path,_O_RDONLY | _O_BINARY);
  1762. if (hi==-1) {
  1763. printf("Could not read %s\n",path);
  1764. return 1;
  1765. }
  1766. free(path);
  1767. size32_t l = lseek(hi,0,SEEK_END);
  1768. lseek(hi,0,SEEK_SET);
  1769. char *s = (char *)malloc(l+1);
  1770. l = read(hi,s,l);
  1771. close(hi);
  1772. if (argc>2)
  1773. _chdir(argv[2]);
  1774. s[l] = 0;
  1775. path=changeext(argv[1],"hpp");
  1776. int ho = open(path, _O_WRONLY | _O_CREAT | _O_TRUNC | _O_BINARY , S_IREAD|S_IWRITE);
  1777. if (ho==-1) {
  1778. printf("Could not write %s\n",path);
  1779. return 1;
  1780. }
  1781. free(path);
  1782. path=changeext(argv[1],"cpp");
  1783. int cppo = open(path,_O_WRONLY | _O_CREAT | _O_TRUNC | _O_BINARY , S_IREAD|S_IWRITE);
  1784. if (cppo==-1) {
  1785. printf("Could not write %s\n",path);
  1786. return 1;
  1787. }
  1788. free(path);
  1789. path=changeext(argv[1],"xsv");
  1790. int xsvo = open(path,_O_WRONLY | _O_CREAT | _O_TRUNC | _O_BINARY , S_IREAD|S_IWRITE);
  1791. if (xsvo==-1) {
  1792. printf("Could not write %s\n",path);
  1793. return 1;
  1794. }
  1795. free(path);
  1796. path=changeext(argv[1],"int");
  1797. int clwo = open(path,_O_WRONLY | _O_CREAT | _O_TRUNC | _O_BINARY , S_IREAD|S_IWRITE);
  1798. if (clwo==-1) {
  1799. printf("Could not write %s\n",path);
  1800. return 1;
  1801. }
  1802. free(path);
  1803. HIDLcompiler hc;
  1804. char *package = gettail(argv[1]);
  1805. hc.ProcessHIDL(s,ho,cppo,xsvo,clwo,package);
  1806. free(package);
  1807. free(s);
  1808. close(ho);
  1809. close(cppo);
  1810. close(xsvo);
  1811. close(clwo);
  1812. return 0;
  1813. }