ppy.y 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645
  1. /*
  2. * Wrc preprocessor syntax analysis
  3. *
  4. * Copyright 1999-2000 Bertho A. Stultiens (BS)
  5. *
  6. * This library is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU Lesser General Public
  8. * License as published by the Free Software Foundation; either
  9. * version 2.1 of the License, or (at your option) any later version.
  10. *
  11. * This library is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * Lesser General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Lesser General Public
  17. * License along with this library; if not, write to the Free Software
  18. * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  19. *
  20. */
  21. %{
  22. #include "config.h"
  23. #include <stdio.h>
  24. #include <stdlib.h>
  25. #include <stdarg.h>
  26. #include <assert.h>
  27. #include <ctype.h>
  28. #include <string.h>
  29. #include "../tools.h"
  30. #include "utils.h"
  31. #include "wpp_private.h"
  32. #define UNARY_OP(r, v, OP) \
  33. switch(v.type) \
  34. { \
  35. case cv_sint: r.val.si = OP v.val.si; break; \
  36. case cv_uint: r.val.ui = OP v.val.ui; break; \
  37. case cv_slong: r.val.sl = OP v.val.sl; break; \
  38. case cv_ulong: r.val.ul = OP v.val.ul; break; \
  39. case cv_sll: r.val.sll = OP v.val.sll; break; \
  40. case cv_ull: r.val.ull = OP v.val.ull; break; \
  41. }
  42. #define cv_signed(v) ((v.type & FLAG_SIGNED) != 0)
  43. #define BIN_OP_INT(r, v1, v2, OP) \
  44. r.type = v1.type; \
  45. if(cv_signed(v1) && cv_signed(v2)) \
  46. r.val.si = v1.val.si OP v2.val.si; \
  47. else if(cv_signed(v1) && !cv_signed(v2)) \
  48. r.val.si = v1.val.si OP (signed) v2.val.ui; \
  49. else if(!cv_signed(v1) && cv_signed(v2)) \
  50. r.val.si = (signed) v1.val.ui OP v2.val.si; \
  51. else \
  52. r.val.ui = v1.val.ui OP v2.val.ui;
  53. #define BIN_OP_LONG(r, v1, v2, OP) \
  54. r.type = v1.type; \
  55. if(cv_signed(v1) && cv_signed(v2)) \
  56. r.val.sl = v1.val.sl OP v2.val.sl; \
  57. else if(cv_signed(v1) && !cv_signed(v2)) \
  58. r.val.sl = v1.val.sl OP (signed long) v2.val.ul; \
  59. else if(!cv_signed(v1) && cv_signed(v2)) \
  60. r.val.sl = (signed long) v1.val.ul OP v2.val.sl; \
  61. else \
  62. r.val.ul = v1.val.ul OP v2.val.ul;
  63. #define BIN_OP_LONGLONG(r, v1, v2, OP) \
  64. r.type = v1.type; \
  65. if(cv_signed(v1) && cv_signed(v2)) \
  66. r.val.sll = v1.val.sll OP v2.val.sll; \
  67. else if(cv_signed(v1) && !cv_signed(v2)) \
  68. r.val.sll = v1.val.sll OP (__int64) v2.val.ull; \
  69. else if(!cv_signed(v1) && cv_signed(v2)) \
  70. r.val.sll = (__int64) v1.val.ull OP v2.val.sll; \
  71. else \
  72. r.val.ull = v1.val.ull OP v2.val.ull;
  73. #define BIN_OP(r, v1, v2, OP) \
  74. switch(v1.type & SIZE_MASK) \
  75. { \
  76. case SIZE_INT: BIN_OP_INT(r, v1, v2, OP); break; \
  77. case SIZE_LONG: BIN_OP_LONG(r, v1, v2, OP); break; \
  78. case SIZE_LONGLONG: BIN_OP_LONGLONG(r, v1, v2, OP); break; \
  79. default: assert(0); \
  80. }
  81. /*
  82. * Prototypes
  83. */
  84. static int boolean(cval_t *v);
  85. static void promote_equal_size(cval_t *v1, cval_t *v2);
  86. static void cast_to_sint(cval_t *v);
  87. static void cast_to_uint(cval_t *v);
  88. static void cast_to_slong(cval_t *v);
  89. static void cast_to_ulong(cval_t *v);
  90. static void cast_to_sll(cval_t *v);
  91. static void cast_to_ull(cval_t *v);
  92. static char *add_new_marg(char *str);
  93. static int marg_index(char *id);
  94. static mtext_t *new_mtext(char *str, int idx, def_exp_t type);
  95. static mtext_t *combine_mtext(mtext_t *tail, mtext_t *mtp);
  96. static char *merge_text(char *s1, char *s2);
  97. /*
  98. * Local variables
  99. */
  100. static char **macro_args; /* Macro parameters array while parsing */
  101. static int nmacro_args;
  102. %}
  103. %union{
  104. int sint;
  105. unsigned int uint;
  106. long slong;
  107. unsigned long ulong;
  108. __int64 sll;
  109. unsigned __int64 ull;
  110. int *iptr;
  111. char *cptr;
  112. cval_t cval;
  113. char *marg;
  114. mtext_t *mtext;
  115. }
  116. %token tRCINCLUDE
  117. %token tIF tIFDEF tIFNDEF tELSE tELIF tENDIF tDEFINED tNL
  118. %token tINCLUDE tLINE tGCCLINE tERROR tWARNING tPRAGMA tPPIDENT
  119. %token tUNDEF tMACROEND tCONCAT tELLIPSIS tSTRINGIZE
  120. %token <cptr> tIDENT tLITERAL tMACRO tDEFINE
  121. %token <cptr> tDQSTRING tSQSTRING tIQSTRING
  122. %token <uint> tUINT
  123. %token <sint> tSINT
  124. %token <ulong> tULONG
  125. %token <slong> tSLONG
  126. %token <ull> tULONGLONG
  127. %token <sll> tSLONGLONG
  128. %token <cptr> tRCINCLUDEPATH
  129. %right '?' ':'
  130. %left tLOGOR
  131. %left tLOGAND
  132. %left '|'
  133. %left '^'
  134. %left '&'
  135. %left tEQ tNE
  136. %left '<' tLTE '>' tGTE
  137. %left tLSHIFT tRSHIFT
  138. %left '+' '-'
  139. %left '*' '/'
  140. %right '~' '!'
  141. %type <cval> pp_expr
  142. %type <marg> emargs margs
  143. %type <mtext> opt_mtexts mtexts mtext
  144. %type <sint> allmargs
  145. %type <cptr> opt_text text
  146. /*
  147. **************************************************************************
  148. * The parser starts here
  149. **************************************************************************
  150. */
  151. %%
  152. pp_file : /* Empty */
  153. | pp_file preprocessor
  154. ;
  155. preprocessor
  156. : tINCLUDE tDQSTRING tNL { pp_do_include($2, 1); }
  157. | tINCLUDE tIQSTRING tNL { pp_do_include($2, 0); }
  158. | tIF pp_expr tNL { pp_next_if_state(boolean(&$2)); }
  159. | tIFDEF tIDENT tNL { pp_next_if_state(pplookup($2) != NULL); free($2); }
  160. | tIFNDEF tIDENT tNL {
  161. int t = pplookup($2) == NULL;
  162. if(pp_incl_state.state == 0 && t && !pp_incl_state.seen_junk)
  163. {
  164. pp_incl_state.state = 1;
  165. pp_incl_state.ppp = $2;
  166. pp_incl_state.ifdepth = pp_get_if_depth();
  167. }
  168. else if(pp_incl_state.state != 1)
  169. {
  170. pp_incl_state.state = -1;
  171. free($2);
  172. }
  173. else
  174. free($2);
  175. pp_next_if_state(t);
  176. if(pp_status.debug)
  177. fprintf(stderr, "tIFNDEF: %s:%d: include_state=%d, include_ppp='%s', include_ifdepth=%d\n",
  178. pp_status.input, pp_status.line_number, pp_incl_state.state, pp_incl_state.ppp, pp_incl_state.ifdepth);
  179. }
  180. | tELIF pp_expr tNL {
  181. pp_if_state_t s = pp_pop_if();
  182. switch(s)
  183. {
  184. case if_true:
  185. case if_elif:
  186. pp_push_if(if_elif);
  187. break;
  188. case if_false:
  189. pp_push_if(boolean(&$2) ? if_true : if_false);
  190. break;
  191. case if_ignore:
  192. pp_push_if(if_ignore);
  193. break;
  194. case if_elsetrue:
  195. case if_elsefalse:
  196. ppy_error("#elif cannot follow #else");
  197. break;
  198. case if_error:
  199. break;
  200. }
  201. }
  202. | tELSE tNL {
  203. pp_if_state_t s = pp_pop_if();
  204. switch(s)
  205. {
  206. case if_true:
  207. pp_push_if(if_elsefalse);
  208. break;
  209. case if_elif:
  210. pp_push_if(if_elif);
  211. break;
  212. case if_false:
  213. pp_push_if(if_elsetrue);
  214. break;
  215. case if_ignore:
  216. pp_push_if(if_ignore);
  217. break;
  218. case if_elsetrue:
  219. case if_elsefalse:
  220. ppy_error("#else clause already defined");
  221. break;
  222. case if_error:
  223. break;
  224. }
  225. }
  226. | tENDIF tNL {
  227. if(pp_pop_if() != if_error)
  228. {
  229. if(pp_incl_state.ifdepth == pp_get_if_depth() && pp_incl_state.state == 1)
  230. {
  231. pp_incl_state.state = 2;
  232. pp_incl_state.seen_junk = 0;
  233. }
  234. else if(pp_incl_state.state != 1)
  235. {
  236. pp_incl_state.state = -1;
  237. }
  238. if(pp_status.debug)
  239. fprintf(stderr, "tENDIF: %s:%d: include_state=%d, include_ppp='%s', include_ifdepth=%d\n",
  240. pp_status.input, pp_status.line_number, pp_incl_state.state, pp_incl_state.ppp, pp_incl_state.ifdepth);
  241. }
  242. }
  243. | tUNDEF tIDENT tNL { pp_del_define($2); free($2); }
  244. | tDEFINE opt_text tNL { pp_add_define($1, $2); free($1); free($2); }
  245. | tMACRO res_arg allmargs tMACROEND opt_mtexts tNL {
  246. pp_add_macro($1, macro_args, nmacro_args, $5);
  247. }
  248. | tLINE tSINT tDQSTRING tNL { if($3) fprintf(ppy_out, "# %d %s\n", $2 , $3); free($3); }
  249. | tGCCLINE tSINT tDQSTRING tNL { if($3) fprintf(ppy_out, "# %d %s\n", $2 , $3); free($3); }
  250. | tGCCLINE tSINT tDQSTRING tSINT tNL
  251. { if($3) fprintf(ppy_out, "# %d %s %d\n", $2, $3, $4); free($3); }
  252. | tGCCLINE tSINT tDQSTRING tSINT tSINT tNL
  253. { if($3) fprintf(ppy_out, "# %d %s %d %d\n", $2 ,$3, $4, $5); free($3); }
  254. | tGCCLINE tSINT tDQSTRING tSINT tSINT tSINT tNL
  255. { if($3) fprintf(ppy_out, "# %d %s %d %d %d\n", $2 ,$3 ,$4 ,$5, $6); free($3); }
  256. | tGCCLINE tSINT tDQSTRING tSINT tSINT tSINT tSINT tNL
  257. { if($3) fprintf(ppy_out, "# %d %s %d %d %d %d\n", $2 ,$3 ,$4 ,$5, $6, $7); free($3); }
  258. | tGCCLINE tNL /* The null-token */
  259. | tERROR opt_text tNL { ppy_error("#error directive: '%s'", $2); free($2); }
  260. | tWARNING opt_text tNL { ppy_warning("#warning directive: '%s'", $2); free($2); }
  261. | tPRAGMA opt_text tNL { fprintf(ppy_out, "#pragma %s\n", $2 ? $2 : ""); free($2); }
  262. | tPPIDENT opt_text tNL { if(pedantic) ppy_warning("#ident ignored (arg: '%s')", $2); free($2); }
  263. | tRCINCLUDE tRCINCLUDEPATH {
  264. pp_do_include(strmake( "\"%s\"", $2 ),1);
  265. }
  266. | tRCINCLUDE tDQSTRING {
  267. pp_do_include($2,1);
  268. }
  269. /*| tNL*/
  270. ;
  271. opt_text: /* Empty */ { $$ = NULL; }
  272. | text { $$ = $1; }
  273. ;
  274. text : tLITERAL { $$ = $1; }
  275. | tDQSTRING { $$ = $1; }
  276. | tSQSTRING { $$ = $1; }
  277. | text tLITERAL { $$ = merge_text($1, $2); }
  278. | text tDQSTRING { $$ = merge_text($1, $2); }
  279. | text tSQSTRING { $$ = merge_text($1, $2); }
  280. ;
  281. res_arg : /* Empty */ { macro_args = NULL; nmacro_args = 0; }
  282. ;
  283. allmargs: /* Empty */ { $$ = 0; macro_args = NULL; nmacro_args = 0; }
  284. | emargs { $$ = nmacro_args; }
  285. ;
  286. emargs : margs { $$ = $1; }
  287. | margs ',' tELLIPSIS { nmacro_args *= -1; }
  288. | tELLIPSIS { macro_args = NULL; nmacro_args = 0; }
  289. ;
  290. margs : margs ',' tIDENT { $$ = add_new_marg($3); }
  291. | tIDENT { $$ = add_new_marg($1); }
  292. ;
  293. opt_mtexts
  294. : /* Empty */ { $$ = NULL; }
  295. | mtexts {
  296. for($$ = $1; $$ && $$->prev; $$ = $$->prev)
  297. ;
  298. }
  299. ;
  300. mtexts : mtext { $$ = $1; }
  301. | mtexts mtext { $$ = combine_mtext($1, $2); }
  302. ;
  303. mtext : tLITERAL { $$ = new_mtext($1, 0, exp_text); }
  304. | tDQSTRING { $$ = new_mtext($1, 0, exp_text); }
  305. | tSQSTRING { $$ = new_mtext($1, 0, exp_text); }
  306. | tCONCAT { $$ = new_mtext(NULL, 0, exp_concat); }
  307. | tSTRINGIZE tIDENT {
  308. int mat = marg_index($2);
  309. if(mat < 0)
  310. ppy_error("Stringification identifier must be an argument parameter");
  311. else
  312. $$ = new_mtext(NULL, mat, exp_stringize);
  313. }
  314. | tIDENT {
  315. int mat = marg_index($1);
  316. if(mat >= 0)
  317. $$ = new_mtext(NULL, mat, exp_subst);
  318. else if($1)
  319. $$ = new_mtext($1, 0, exp_text);
  320. }
  321. ;
  322. pp_expr : tSINT { $$.type = cv_sint; $$.val.si = $1; }
  323. | tUINT { $$.type = cv_uint; $$.val.ui = $1; }
  324. | tSLONG { $$.type = cv_slong; $$.val.sl = $1; }
  325. | tULONG { $$.type = cv_ulong; $$.val.ul = $1; }
  326. | tSLONGLONG { $$.type = cv_sll; $$.val.sll = $1; }
  327. | tULONGLONG { $$.type = cv_ull; $$.val.ull = $1; }
  328. | tDEFINED tIDENT { $$.type = cv_sint; $$.val.si = pplookup($2) != NULL; }
  329. | tDEFINED '(' tIDENT ')' { $$.type = cv_sint; $$.val.si = pplookup($3) != NULL; }
  330. | tIDENT { $$.type = cv_sint; $$.val.si = 0; }
  331. | pp_expr tLOGOR pp_expr { $$.type = cv_sint; $$.val.si = boolean(&$1) || boolean(&$3); }
  332. | pp_expr tLOGAND pp_expr { $$.type = cv_sint; $$.val.si = boolean(&$1) && boolean(&$3); }
  333. | pp_expr tEQ pp_expr { promote_equal_size(&$1, &$3); BIN_OP($$, $1, $3, ==); }
  334. | pp_expr tNE pp_expr { promote_equal_size(&$1, &$3); BIN_OP($$, $1, $3, !=); }
  335. | pp_expr '<' pp_expr { promote_equal_size(&$1, &$3); BIN_OP($$, $1, $3, <); }
  336. | pp_expr '>' pp_expr { promote_equal_size(&$1, &$3); BIN_OP($$, $1, $3, >); }
  337. | pp_expr tLTE pp_expr { promote_equal_size(&$1, &$3); BIN_OP($$, $1, $3, <=); }
  338. | pp_expr tGTE pp_expr { promote_equal_size(&$1, &$3); BIN_OP($$, $1, $3, >=); }
  339. | pp_expr '+' pp_expr { promote_equal_size(&$1, &$3); BIN_OP($$, $1, $3, +); }
  340. | pp_expr '-' pp_expr { promote_equal_size(&$1, &$3); BIN_OP($$, $1, $3, -); }
  341. | pp_expr '^' pp_expr { promote_equal_size(&$1, &$3); BIN_OP($$, $1, $3, ^); }
  342. | pp_expr '&' pp_expr { promote_equal_size(&$1, &$3); BIN_OP($$, $1, $3, &); }
  343. | pp_expr '|' pp_expr { promote_equal_size(&$1, &$3); BIN_OP($$, $1, $3, |); }
  344. | pp_expr '*' pp_expr { promote_equal_size(&$1, &$3); BIN_OP($$, $1, $3, *); }
  345. | pp_expr '/' pp_expr { promote_equal_size(&$1, &$3); BIN_OP($$, $1, $3, /); }
  346. | pp_expr tLSHIFT pp_expr { promote_equal_size(&$1, &$3); BIN_OP($$, $1, $3, <<); }
  347. | pp_expr tRSHIFT pp_expr { promote_equal_size(&$1, &$3); BIN_OP($$, $1, $3, >>); }
  348. | '+' pp_expr { $$ = $2; }
  349. | '-' pp_expr { UNARY_OP($$, $2, -); }
  350. | '~' pp_expr { UNARY_OP($$, $2, ~); }
  351. | '!' pp_expr { $$.type = cv_sint; $$.val.si = !boolean(&$2); }
  352. | '(' pp_expr ')' { $$ = $2; }
  353. | pp_expr '?' pp_expr ':' pp_expr { $$ = boolean(&$1) ? $3 : $5; }
  354. ;
  355. %%
  356. /*
  357. **************************************************************************
  358. * Support functions
  359. **************************************************************************
  360. */
  361. static void cast_to_sint(cval_t *v)
  362. {
  363. switch(v->type)
  364. {
  365. case cv_sint: break;
  366. case cv_uint: break;
  367. case cv_slong: v->val.si = v->val.sl; break;
  368. case cv_ulong: v->val.si = v->val.ul; break;
  369. case cv_sll: v->val.si = v->val.sll; break;
  370. case cv_ull: v->val.si = v->val.ull; break;
  371. }
  372. v->type = cv_sint;
  373. }
  374. static void cast_to_uint(cval_t *v)
  375. {
  376. switch(v->type)
  377. {
  378. case cv_sint: break;
  379. case cv_uint: break;
  380. case cv_slong: v->val.ui = v->val.sl; break;
  381. case cv_ulong: v->val.ui = v->val.ul; break;
  382. case cv_sll: v->val.ui = v->val.sll; break;
  383. case cv_ull: v->val.ui = v->val.ull; break;
  384. }
  385. v->type = cv_uint;
  386. }
  387. static void cast_to_slong(cval_t *v)
  388. {
  389. switch(v->type)
  390. {
  391. case cv_sint: v->val.sl = v->val.si; break;
  392. case cv_uint: v->val.sl = v->val.ui; break;
  393. case cv_slong: break;
  394. case cv_ulong: break;
  395. case cv_sll: v->val.sl = v->val.sll; break;
  396. case cv_ull: v->val.sl = v->val.ull; break;
  397. }
  398. v->type = cv_slong;
  399. }
  400. static void cast_to_ulong(cval_t *v)
  401. {
  402. switch(v->type)
  403. {
  404. case cv_sint: v->val.ul = v->val.si; break;
  405. case cv_uint: v->val.ul = v->val.ui; break;
  406. case cv_slong: break;
  407. case cv_ulong: break;
  408. case cv_sll: v->val.ul = v->val.sll; break;
  409. case cv_ull: v->val.ul = v->val.ull; break;
  410. }
  411. v->type = cv_ulong;
  412. }
  413. static void cast_to_sll(cval_t *v)
  414. {
  415. switch(v->type)
  416. {
  417. case cv_sint: v->val.sll = v->val.si; break;
  418. case cv_uint: v->val.sll = v->val.ui; break;
  419. case cv_slong: v->val.sll = v->val.sl; break;
  420. case cv_ulong: v->val.sll = v->val.ul; break;
  421. case cv_sll: break;
  422. case cv_ull: break;
  423. }
  424. v->type = cv_sll;
  425. }
  426. static void cast_to_ull(cval_t *v)
  427. {
  428. switch(v->type)
  429. {
  430. case cv_sint: v->val.ull = v->val.si; break;
  431. case cv_uint: v->val.ull = v->val.ui; break;
  432. case cv_slong: v->val.ull = v->val.sl; break;
  433. case cv_ulong: v->val.ull = v->val.ul; break;
  434. case cv_sll: break;
  435. case cv_ull: break;
  436. }
  437. v->type = cv_ull;
  438. }
  439. static void promote_equal_size(cval_t *v1, cval_t *v2)
  440. {
  441. #define cv_sizeof(v) ((int)(v->type & SIZE_MASK))
  442. int s1 = cv_sizeof(v1);
  443. int s2 = cv_sizeof(v2);
  444. #undef cv_sizeof
  445. if(s1 == s2)
  446. return;
  447. else if(s1 > s2)
  448. {
  449. switch(v1->type)
  450. {
  451. case cv_sint: cast_to_sint(v2); break;
  452. case cv_uint: cast_to_uint(v2); break;
  453. case cv_slong: cast_to_slong(v2); break;
  454. case cv_ulong: cast_to_ulong(v2); break;
  455. case cv_sll: cast_to_sll(v2); break;
  456. case cv_ull: cast_to_ull(v2); break;
  457. }
  458. }
  459. else
  460. {
  461. switch(v2->type)
  462. {
  463. case cv_sint: cast_to_sint(v1); break;
  464. case cv_uint: cast_to_uint(v1); break;
  465. case cv_slong: cast_to_slong(v1); break;
  466. case cv_ulong: cast_to_ulong(v1); break;
  467. case cv_sll: cast_to_sll(v1); break;
  468. case cv_ull: cast_to_ull(v1); break;
  469. }
  470. }
  471. }
  472. static int boolean(cval_t *v)
  473. {
  474. switch(v->type)
  475. {
  476. case cv_sint: return v->val.si != 0;
  477. case cv_uint: return v->val.ui != 0;
  478. case cv_slong: return v->val.sl != 0;
  479. case cv_ulong: return v->val.ul != 0;
  480. case cv_sll: return v->val.sll != 0;
  481. case cv_ull: return v->val.ull != 0;
  482. }
  483. return 0;
  484. }
  485. static char *add_new_marg(char *str)
  486. {
  487. char *ma;
  488. macro_args = xrealloc(macro_args, (nmacro_args+1) * sizeof(macro_args[0]));
  489. macro_args[nmacro_args++] = ma = xstrdup(str);
  490. return ma;
  491. }
  492. static int marg_index(char *id)
  493. {
  494. int t;
  495. if(!id)
  496. return -1;
  497. for(t = 0; t < nmacro_args; t++)
  498. {
  499. if(!strcmp(id, macro_args[t]))
  500. break;
  501. }
  502. return t < nmacro_args ? t : -1;
  503. }
  504. static mtext_t *new_mtext(char *str, int idx, def_exp_t type)
  505. {
  506. mtext_t *mt = xmalloc(sizeof(mtext_t));
  507. if(str == NULL)
  508. mt->subst.argidx = idx;
  509. else
  510. mt->subst.text = str;
  511. mt->type = type;
  512. mt->next = mt->prev = NULL;
  513. return mt;
  514. }
  515. static mtext_t *combine_mtext(mtext_t *tail, mtext_t *mtp)
  516. {
  517. if(!tail)
  518. return mtp;
  519. if(!mtp)
  520. return tail;
  521. if(tail->type == exp_text && mtp->type == exp_text)
  522. {
  523. tail->subst.text = xrealloc(tail->subst.text, strlen(tail->subst.text)+strlen(mtp->subst.text)+1);
  524. strcat(tail->subst.text, mtp->subst.text);
  525. free(mtp->subst.text);
  526. free(mtp);
  527. return tail;
  528. }
  529. if(tail->type == exp_concat && mtp->type == exp_concat)
  530. {
  531. free(mtp);
  532. return tail;
  533. }
  534. if(tail->type == exp_concat && mtp->type == exp_text)
  535. {
  536. int len = strlen(mtp->subst.text);
  537. while(len)
  538. {
  539. /* FIXME: should delete space from head of string */
  540. if(isspace(mtp->subst.text[len-1] & 0xff))
  541. mtp->subst.text[--len] = '\0';
  542. else
  543. break;
  544. }
  545. if(!len)
  546. {
  547. free(mtp->subst.text);
  548. free(mtp);
  549. return tail;
  550. }
  551. }
  552. if(tail->type == exp_text && mtp->type == exp_concat)
  553. {
  554. int len = strlen(tail->subst.text);
  555. while(len)
  556. {
  557. if(isspace(tail->subst.text[len-1] & 0xff))
  558. tail->subst.text[--len] = '\0';
  559. else
  560. break;
  561. }
  562. if(!len)
  563. {
  564. mtp->prev = tail->prev;
  565. mtp->next = tail->next;
  566. if(tail->prev)
  567. tail->prev->next = mtp;
  568. free(tail->subst.text);
  569. free(tail);
  570. return mtp;
  571. }
  572. }
  573. tail->next = mtp;
  574. mtp->prev = tail;
  575. return mtp;
  576. }
  577. static char *merge_text(char *s1, char *s2)
  578. {
  579. int l1 = strlen(s1);
  580. int l2 = strlen(s2);
  581. s1 = xrealloc(s1, l1+l2+1);
  582. memcpy(s1+l1, s2, l2+1);
  583. free(s2);
  584. return s1;
  585. }