Clone of mesa.
您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

glcpp-parse.y 32KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484
  1. %{
  2. /*
  3. * Copyright © 2010 Intel Corporation
  4. *
  5. * Permission is hereby granted, free of charge, to any person obtaining a
  6. * copy of this software and associated documentation files (the "Software"),
  7. * to deal in the Software without restriction, including without limitation
  8. * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  9. * and/or sell copies of the Software, and to permit persons to whom the
  10. * Software is furnished to do so, subject to the following conditions:
  11. *
  12. * The above copyright notice and this permission notice (including the next
  13. * paragraph) shall be included in all copies or substantial portions of the
  14. * Software.
  15. *
  16. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  19. * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  21. * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  22. * DEALINGS IN THE SOFTWARE.
  23. */
  24. #include <stdio.h>
  25. #include <stdlib.h>
  26. #include <assert.h>
  27. #include <inttypes.h>
  28. #include "glcpp.h"
  29. static void
  30. yyerror (void *scanner, const char *error);
  31. static void
  32. _define_object_macro (glcpp_parser_t *parser,
  33. const char *macro,
  34. token_list_t *replacements);
  35. static void
  36. _define_function_macro (glcpp_parser_t *parser,
  37. const char *macro,
  38. string_list_t *parameters,
  39. token_list_t *replacements);
  40. static string_list_t *
  41. _string_list_create (void *ctx);
  42. static void
  43. _string_list_append_item (string_list_t *list, const char *str);
  44. static void
  45. _string_list_append_list (string_list_t *list, string_list_t *tail);
  46. static void
  47. _string_list_push (string_list_t *list, const char *str);
  48. static void
  49. _string_list_pop (string_list_t *list);
  50. static int
  51. _string_list_contains (string_list_t *list, const char *member, int *index);
  52. static int
  53. _string_list_length (string_list_t *list);
  54. static argument_list_t *
  55. _argument_list_create (void *ctx);
  56. static void
  57. _argument_list_append (argument_list_t *list, token_list_t *argument);
  58. static int
  59. _argument_list_length (argument_list_t *list);
  60. static token_list_t *
  61. _argument_list_member_at (argument_list_t *list, int index);
  62. /* Note: This function talloc_steal()s the str pointer. */
  63. static token_t *
  64. _token_create_str (void *ctx, int type, char *str);
  65. static token_t *
  66. _token_create_ival (void *ctx, int type, int ival);
  67. static token_list_t *
  68. _token_list_create (void *ctx);
  69. /* Note: This function adds a talloc_reference() to token.
  70. *
  71. * You may want to talloc_unlink any current reference if you no
  72. * longer need it. */
  73. static void
  74. _token_list_append (token_list_t *list, token_t *token);
  75. static void
  76. _token_list_append_list (token_list_t *list, token_list_t *tail);
  77. static void
  78. _glcpp_parser_evaluate_defined (glcpp_parser_t *parser,
  79. token_list_t *list);
  80. static void
  81. _glcpp_parser_print_expanded_token_list (glcpp_parser_t *parser,
  82. token_list_t *list);
  83. static void
  84. _glcpp_parser_expand_token_list_onto (glcpp_parser_t *parser,
  85. token_list_t *list,
  86. token_list_t *result);
  87. static void
  88. _glcpp_parser_skip_stack_push_if (glcpp_parser_t *parser, int condition);
  89. static void
  90. _glcpp_parser_skip_stack_change_if (glcpp_parser_t *parser, const char *type,
  91. int condition);
  92. static void
  93. _glcpp_parser_skip_stack_pop (glcpp_parser_t *parser);
  94. #define yylex glcpp_parser_lex
  95. static int
  96. glcpp_parser_lex (glcpp_parser_t *parser);
  97. static void
  98. glcpp_parser_lex_from (glcpp_parser_t *parser, token_list_t *list);
  99. %}
  100. %parse-param {glcpp_parser_t *parser}
  101. %lex-param {glcpp_parser_t *parser}
  102. %token COMMA_FINAL DEFINED ELIF_EXPANDED HASH HASH_DEFINE_FUNC HASH_DEFINE_OBJ HASH_ELIF HASH_ELSE HASH_ENDIF HASH_IF HASH_IFDEF HASH_IFNDEF HASH_UNDEF IDENTIFIER IF_EXPANDED INTEGER NEWLINE OTHER SPACE
  103. %token PASTE
  104. %type <ival> expression INTEGER operator SPACE
  105. %type <str> IDENTIFIER OTHER
  106. %type <string_list> identifier_list
  107. %type <token> preprocessing_token
  108. %type <token_list> pp_tokens replacement_list text_line
  109. %left OR
  110. %left AND
  111. %left '|'
  112. %left '^'
  113. %left '&'
  114. %left EQUAL NOT_EQUAL
  115. %left '<' '>' LESS_OR_EQUAL GREATER_OR_EQUAL
  116. %left LEFT_SHIFT RIGHT_SHIFT
  117. %left '+' '-'
  118. %left '*' '/' '%'
  119. %right UNARY
  120. %%
  121. input:
  122. /* empty */
  123. | input line
  124. ;
  125. line:
  126. control_line {
  127. if (parser->skip_stack == NULL ||
  128. parser->skip_stack->type == SKIP_NO_SKIP)
  129. {
  130. printf ("\n");
  131. }
  132. }
  133. | text_line {
  134. if (parser->skip_stack == NULL ||
  135. parser->skip_stack->type == SKIP_NO_SKIP)
  136. {
  137. _glcpp_parser_print_expanded_token_list (parser, $1);
  138. printf ("\n");
  139. }
  140. talloc_free ($1);
  141. }
  142. | expanded_line
  143. | HASH non_directive
  144. ;
  145. expanded_line:
  146. IF_EXPANDED expression NEWLINE {
  147. _glcpp_parser_skip_stack_push_if (parser, $2);
  148. }
  149. | ELIF_EXPANDED expression NEWLINE {
  150. _glcpp_parser_skip_stack_change_if (parser, "elif", $2);
  151. }
  152. ;
  153. control_line:
  154. HASH_DEFINE_OBJ IDENTIFIER replacement_list NEWLINE {
  155. _define_object_macro (parser, $2, $3);
  156. }
  157. | HASH_DEFINE_FUNC IDENTIFIER '(' ')' replacement_list NEWLINE {
  158. _define_function_macro (parser, $2, NULL, $5);
  159. }
  160. | HASH_DEFINE_FUNC IDENTIFIER '(' identifier_list ')' replacement_list NEWLINE {
  161. _define_function_macro (parser, $2, $4, $6);
  162. }
  163. | HASH_UNDEF IDENTIFIER NEWLINE {
  164. macro_t *macro = hash_table_find (parser->defines, $2);
  165. if (macro) {
  166. /* XXX: Need hash table to support a real way
  167. * to remove an element rather than prefixing
  168. * a new node with data of NULL like this. */
  169. hash_table_insert (parser->defines, NULL, $2);
  170. talloc_free (macro);
  171. }
  172. talloc_free ($2);
  173. }
  174. | HASH_IF pp_tokens NEWLINE {
  175. token_list_t *expanded;
  176. token_t *token;
  177. expanded = _token_list_create (parser);
  178. token = _token_create_ival (parser, IF_EXPANDED, IF_EXPANDED);
  179. _token_list_append (expanded, token);
  180. talloc_unlink (parser, token);
  181. _glcpp_parser_evaluate_defined (parser, $2);
  182. _glcpp_parser_expand_token_list_onto (parser, $2, expanded);
  183. glcpp_parser_lex_from (parser, expanded);
  184. }
  185. | HASH_IFDEF IDENTIFIER NEWLINE {
  186. macro_t *macro = hash_table_find (parser->defines, $2);
  187. talloc_free ($2);
  188. _glcpp_parser_skip_stack_push_if (parser, macro != NULL);
  189. }
  190. | HASH_IFNDEF IDENTIFIER NEWLINE {
  191. macro_t *macro = hash_table_find (parser->defines, $2);
  192. talloc_free ($2);
  193. _glcpp_parser_skip_stack_push_if (parser, macro == NULL);
  194. }
  195. | HASH_ELIF pp_tokens NEWLINE {
  196. token_list_t *expanded;
  197. token_t *token;
  198. expanded = _token_list_create (parser);
  199. token = _token_create_ival (parser, ELIF_EXPANDED, ELIF_EXPANDED);
  200. _token_list_append (expanded, token);
  201. talloc_unlink (parser, token);
  202. _glcpp_parser_evaluate_defined (parser, $2);
  203. _glcpp_parser_expand_token_list_onto (parser, $2, expanded);
  204. glcpp_parser_lex_from (parser, expanded);
  205. }
  206. | HASH_ELSE NEWLINE {
  207. _glcpp_parser_skip_stack_change_if (parser, "else", 1);
  208. }
  209. | HASH_ENDIF NEWLINE {
  210. _glcpp_parser_skip_stack_pop (parser);
  211. }
  212. | HASH NEWLINE
  213. ;
  214. expression:
  215. INTEGER {
  216. $$ = $1;
  217. }
  218. | expression OR expression {
  219. $$ = $1 || $3;
  220. }
  221. | expression AND expression {
  222. $$ = $1 && $3;
  223. }
  224. | expression '|' expression {
  225. $$ = $1 | $3;
  226. }
  227. | expression '^' expression {
  228. $$ = $1 ^ $3;
  229. }
  230. | expression '&' expression {
  231. $$ = $1 & $3;
  232. }
  233. | expression NOT_EQUAL expression {
  234. $$ = $1 != $3;
  235. }
  236. | expression EQUAL expression {
  237. $$ = $1 == $3;
  238. }
  239. | expression GREATER_OR_EQUAL expression {
  240. $$ = $1 >= $3;
  241. }
  242. | expression LESS_OR_EQUAL expression {
  243. $$ = $1 <= $3;
  244. }
  245. | expression '>' expression {
  246. $$ = $1 > $3;
  247. }
  248. | expression '<' expression {
  249. $$ = $1 < $3;
  250. }
  251. | expression RIGHT_SHIFT expression {
  252. $$ = $1 >> $3;
  253. }
  254. | expression LEFT_SHIFT expression {
  255. $$ = $1 << $3;
  256. }
  257. | expression '-' expression {
  258. $$ = $1 - $3;
  259. }
  260. | expression '+' expression {
  261. $$ = $1 + $3;
  262. }
  263. | expression '%' expression {
  264. $$ = $1 % $3;
  265. }
  266. | expression '/' expression {
  267. $$ = $1 / $3;
  268. }
  269. | expression '*' expression {
  270. $$ = $1 * $3;
  271. }
  272. | '!' expression %prec UNARY {
  273. $$ = ! $2;
  274. }
  275. | '~' expression %prec UNARY {
  276. $$ = ~ $2;
  277. }
  278. | '-' expression %prec UNARY {
  279. $$ = - $2;
  280. }
  281. | '+' expression %prec UNARY {
  282. $$ = + $2;
  283. }
  284. | '(' expression ')' {
  285. $$ = $2;
  286. }
  287. ;
  288. identifier_list:
  289. IDENTIFIER {
  290. $$ = _string_list_create (parser);
  291. _string_list_append_item ($$, $1);
  292. talloc_steal ($$, $1);
  293. }
  294. | identifier_list ',' IDENTIFIER {
  295. $$ = $1;
  296. _string_list_append_item ($$, $3);
  297. talloc_steal ($$, $3);
  298. }
  299. ;
  300. text_line:
  301. NEWLINE { $$ = NULL; }
  302. | pp_tokens NEWLINE
  303. ;
  304. non_directive:
  305. pp_tokens NEWLINE
  306. ;
  307. replacement_list:
  308. /* empty */ { $$ = NULL; }
  309. | pp_tokens
  310. ;
  311. pp_tokens:
  312. preprocessing_token {
  313. parser->space_tokens = 1;
  314. $$ = _token_list_create (parser);
  315. _token_list_append ($$, $1);
  316. talloc_unlink (parser, $1);
  317. }
  318. | pp_tokens preprocessing_token {
  319. $$ = $1;
  320. _token_list_append ($$, $2);
  321. talloc_unlink (parser, $2);
  322. }
  323. ;
  324. preprocessing_token:
  325. IDENTIFIER {
  326. $$ = _token_create_str (parser, IDENTIFIER, $1);
  327. }
  328. | INTEGER {
  329. $$ = _token_create_ival (parser, INTEGER, $1);
  330. }
  331. | operator {
  332. $$ = _token_create_ival (parser, $1, $1);
  333. }
  334. | OTHER {
  335. $$ = _token_create_str (parser, OTHER, $1);
  336. }
  337. | SPACE {
  338. $$ = _token_create_ival (parser, SPACE, SPACE);
  339. }
  340. ;
  341. operator:
  342. '[' { $$ = '['; }
  343. | ']' { $$ = ']'; }
  344. | '(' { $$ = '('; }
  345. | ')' { $$ = ')'; }
  346. | '{' { $$ = '{'; }
  347. | '}' { $$ = '}'; }
  348. | '.' { $$ = '.'; }
  349. | '&' { $$ = '&'; }
  350. | '*' { $$ = '*'; }
  351. | '+' { $$ = '+'; }
  352. | '-' { $$ = '-'; }
  353. | '~' { $$ = '~'; }
  354. | '!' { $$ = '!'; }
  355. | '/' { $$ = '/'; }
  356. | '%' { $$ = '%'; }
  357. | LEFT_SHIFT { $$ = LEFT_SHIFT; }
  358. | RIGHT_SHIFT { $$ = RIGHT_SHIFT; }
  359. | '<' { $$ = '<'; }
  360. | '>' { $$ = '>'; }
  361. | LESS_OR_EQUAL { $$ = LESS_OR_EQUAL; }
  362. | GREATER_OR_EQUAL { $$ = GREATER_OR_EQUAL; }
  363. | EQUAL { $$ = EQUAL; }
  364. | NOT_EQUAL { $$ = NOT_EQUAL; }
  365. | '^' { $$ = '^'; }
  366. | '|' { $$ = '|'; }
  367. | AND { $$ = AND; }
  368. | OR { $$ = OR; }
  369. | ';' { $$ = ';'; }
  370. | ',' { $$ = ','; }
  371. | PASTE { $$ = PASTE; }
  372. | DEFINED { $$ = DEFINED; }
  373. ;
  374. %%
  375. string_list_t *
  376. _string_list_create (void *ctx)
  377. {
  378. string_list_t *list;
  379. list = xtalloc (ctx, string_list_t);
  380. list->head = NULL;
  381. list->tail = NULL;
  382. return list;
  383. }
  384. void
  385. _string_list_append_list (string_list_t *list, string_list_t *tail)
  386. {
  387. if (list->head == NULL) {
  388. list->head = tail->head;
  389. } else {
  390. list->tail->next = tail->head;
  391. }
  392. list->tail = tail->tail;
  393. }
  394. void
  395. _string_list_append_item (string_list_t *list, const char *str)
  396. {
  397. string_node_t *node;
  398. node = xtalloc (list, string_node_t);
  399. node->str = xtalloc_strdup (node, str);
  400. node->next = NULL;
  401. if (list->head == NULL) {
  402. list->head = node;
  403. } else {
  404. list->tail->next = node;
  405. }
  406. list->tail = node;
  407. }
  408. void
  409. _string_list_push (string_list_t *list, const char *str)
  410. {
  411. string_node_t *node;
  412. node = xtalloc (list, string_node_t);
  413. node->str = xtalloc_strdup (node, str);
  414. node->next = list->head;
  415. if (list->tail == NULL) {
  416. list->tail = node;
  417. }
  418. list->head = node;
  419. }
  420. void
  421. _string_list_pop (string_list_t *list)
  422. {
  423. string_node_t *node;
  424. node = list->head;
  425. if (node == NULL) {
  426. fprintf (stderr, "Internal error: _string_list_pop called on an empty list.\n");
  427. exit (1);
  428. }
  429. list->head = node->next;
  430. if (list->tail == node) {
  431. assert (node->next == NULL);
  432. list->tail = NULL;
  433. }
  434. talloc_free (node);
  435. }
  436. int
  437. _string_list_contains (string_list_t *list, const char *member, int *index)
  438. {
  439. string_node_t *node;
  440. int i;
  441. if (list == NULL)
  442. return 0;
  443. for (i = 0, node = list->head; node; i++, node = node->next) {
  444. if (strcmp (node->str, member) == 0) {
  445. if (index)
  446. *index = i;
  447. return 1;
  448. }
  449. }
  450. return 0;
  451. }
  452. int
  453. _string_list_length (string_list_t *list)
  454. {
  455. int length = 0;
  456. string_node_t *node;
  457. if (list == NULL)
  458. return 0;
  459. for (node = list->head; node; node = node->next)
  460. length++;
  461. return length;
  462. }
  463. argument_list_t *
  464. _argument_list_create (void *ctx)
  465. {
  466. argument_list_t *list;
  467. list = xtalloc (ctx, argument_list_t);
  468. list->head = NULL;
  469. list->tail = NULL;
  470. return list;
  471. }
  472. void
  473. _argument_list_append (argument_list_t *list, token_list_t *argument)
  474. {
  475. argument_node_t *node;
  476. node = xtalloc (list, argument_node_t);
  477. node->argument = argument;
  478. node->next = NULL;
  479. if (list->head == NULL) {
  480. list->head = node;
  481. } else {
  482. list->tail->next = node;
  483. }
  484. list->tail = node;
  485. }
  486. int
  487. _argument_list_length (argument_list_t *list)
  488. {
  489. int length = 0;
  490. argument_node_t *node;
  491. if (list == NULL)
  492. return 0;
  493. for (node = list->head; node; node = node->next)
  494. length++;
  495. return length;
  496. }
  497. token_list_t *
  498. _argument_list_member_at (argument_list_t *list, int index)
  499. {
  500. argument_node_t *node;
  501. int i;
  502. if (list == NULL)
  503. return NULL;
  504. node = list->head;
  505. for (i = 0; i < index; i++) {
  506. node = node->next;
  507. if (node == NULL)
  508. break;
  509. }
  510. if (node)
  511. return node->argument;
  512. return NULL;
  513. }
  514. /* Note: This function talloc_steal()s the str pointer. */
  515. token_t *
  516. _token_create_str (void *ctx, int type, char *str)
  517. {
  518. token_t *token;
  519. token = xtalloc (ctx, token_t);
  520. token->type = type;
  521. token->value.str = talloc_steal (token, str);
  522. return token;
  523. }
  524. token_t *
  525. _token_create_ival (void *ctx, int type, int ival)
  526. {
  527. token_t *token;
  528. token = xtalloc (ctx, token_t);
  529. token->type = type;
  530. token->value.ival = ival;
  531. return token;
  532. }
  533. token_list_t *
  534. _token_list_create (void *ctx)
  535. {
  536. token_list_t *list;
  537. list = xtalloc (ctx, token_list_t);
  538. list->head = NULL;
  539. list->tail = NULL;
  540. list->non_space_tail = NULL;
  541. return list;
  542. }
  543. void
  544. _token_list_append (token_list_t *list, token_t *token)
  545. {
  546. token_node_t *node;
  547. node = xtalloc (list, token_node_t);
  548. node->token = xtalloc_reference (list, token);
  549. node->next = NULL;
  550. if (list->head == NULL) {
  551. list->head = node;
  552. } else {
  553. list->tail->next = node;
  554. }
  555. list->tail = node;
  556. if (token->type != SPACE)
  557. list->non_space_tail = node;
  558. }
  559. void
  560. _token_list_append_list (token_list_t *list, token_list_t *tail)
  561. {
  562. if (tail == NULL || tail->head == NULL)
  563. return;
  564. if (list->head == NULL) {
  565. list->head = tail->head;
  566. } else {
  567. list->tail->next = tail->head;
  568. }
  569. list->tail = tail->tail;
  570. list->non_space_tail = tail->non_space_tail;
  571. }
  572. void
  573. _token_list_trim_trailing_space (token_list_t *list)
  574. {
  575. token_node_t *tail, *next;
  576. if (list->non_space_tail) {
  577. tail = list->non_space_tail->next;
  578. list->non_space_tail->next = NULL;
  579. list->tail = list->non_space_tail;
  580. while (tail) {
  581. next = tail->next;
  582. talloc_free (tail);
  583. tail = next;
  584. }
  585. }
  586. }
  587. static void
  588. _token_print (token_t *token)
  589. {
  590. if (token->type < 256) {
  591. printf ("%c", token->type);
  592. return;
  593. }
  594. switch (token->type) {
  595. case INTEGER:
  596. printf ("%" PRIxMAX, token->value.ival);
  597. break;
  598. case IDENTIFIER:
  599. case OTHER:
  600. printf ("%s", token->value.str);
  601. break;
  602. case SPACE:
  603. printf (" ");
  604. break;
  605. case LEFT_SHIFT:
  606. printf ("<<");
  607. break;
  608. case RIGHT_SHIFT:
  609. printf (">>");
  610. break;
  611. case LESS_OR_EQUAL:
  612. printf ("<=");
  613. break;
  614. case GREATER_OR_EQUAL:
  615. printf (">=");
  616. break;
  617. case EQUAL:
  618. printf ("==");
  619. break;
  620. case NOT_EQUAL:
  621. printf ("!=");
  622. break;
  623. case AND:
  624. printf ("&&");
  625. break;
  626. case OR:
  627. printf ("||");
  628. break;
  629. case PASTE:
  630. printf ("##");
  631. break;
  632. case COMMA_FINAL:
  633. printf (",");
  634. break;
  635. default:
  636. fprintf (stderr, "Error: Don't know how to print token type %d\n", token->type);
  637. break;
  638. }
  639. }
  640. /* Change 'token' into a new token formed by pasting 'other'. */
  641. static void
  642. _token_paste (token_t *token, token_t *other)
  643. {
  644. /* A very few single-character punctuators can be combined
  645. * with another to form a multi-character punctuator. */
  646. switch (token->type) {
  647. case '<':
  648. if (other->type == '<') {
  649. token->type = LEFT_SHIFT;
  650. token->value.ival = LEFT_SHIFT;
  651. return;
  652. } else if (other->type == '=') {
  653. token->type = LESS_OR_EQUAL;
  654. token->value.ival = LESS_OR_EQUAL;
  655. return;
  656. }
  657. break;
  658. case '>':
  659. if (other->type == '>') {
  660. token->type = RIGHT_SHIFT;
  661. token->value.ival = RIGHT_SHIFT;
  662. return;
  663. } else if (other->type == '=') {
  664. token->type = GREATER_OR_EQUAL;
  665. token->value.ival = GREATER_OR_EQUAL;
  666. return;
  667. }
  668. break;
  669. case '=':
  670. if (other->type == '=') {
  671. token->type = EQUAL;
  672. token->value.ival = EQUAL;
  673. return;
  674. }
  675. break;
  676. case '!':
  677. if (other->type == '=') {
  678. token->type = NOT_EQUAL;
  679. token->value.ival = NOT_EQUAL;
  680. return;
  681. }
  682. break;
  683. case '&':
  684. if (other->type == '&') {
  685. token->type = AND;
  686. token->value.ival = AND;
  687. return;
  688. }
  689. break;
  690. case '|':
  691. if (other->type == '|') {
  692. token->type = OR;
  693. token->value.ival = OR;
  694. return;
  695. }
  696. break;
  697. }
  698. /* Two string-valued tokens can usually just be mashed
  699. * together.
  700. *
  701. * XXX: Since our 'OTHER' case is currently so loose, this may
  702. * allow some things thruogh that should be treated as
  703. * errors. */
  704. if ((token->type == IDENTIFIER || token->type == OTHER) &&
  705. (other->type == IDENTIFIER || other->type == OTHER))
  706. {
  707. token->value.str = talloc_strdup_append (token->value.str,
  708. other->value.str);
  709. return;
  710. }
  711. printf ("Error: Pasting \"");
  712. _token_print (token);
  713. printf ("\" and \"");
  714. _token_print (other);
  715. printf ("\" does not give a valid preprocessing token.\n");
  716. }
  717. static void
  718. _token_list_print (token_list_t *list)
  719. {
  720. token_node_t *node;
  721. if (list == NULL)
  722. return;
  723. for (node = list->head; node; node = node->next)
  724. _token_print (node->token);
  725. }
  726. void
  727. yyerror (void *scanner, const char *error)
  728. {
  729. fprintf (stderr, "Parse error: %s\n", error);
  730. }
  731. glcpp_parser_t *
  732. glcpp_parser_create (void)
  733. {
  734. glcpp_parser_t *parser;
  735. parser = xtalloc (NULL, glcpp_parser_t);
  736. glcpp_lex_init_extra (parser, &parser->scanner);
  737. parser->defines = hash_table_ctor (32, hash_table_string_hash,
  738. hash_table_string_compare);
  739. parser->active = _string_list_create (parser);
  740. parser->space_tokens = 1;
  741. parser->newline_as_space = 0;
  742. parser->in_control_line = 0;
  743. parser->paren_count = 0;
  744. parser->skip_stack = NULL;
  745. parser->lex_from_list = NULL;
  746. parser->lex_from_node = NULL;
  747. return parser;
  748. }
  749. int
  750. glcpp_parser_parse (glcpp_parser_t *parser)
  751. {
  752. return yyparse (parser);
  753. }
  754. void
  755. glcpp_parser_destroy (glcpp_parser_t *parser)
  756. {
  757. if (parser->skip_stack)
  758. fprintf (stderr, "Error: Unterminated #if\n");
  759. glcpp_lex_destroy (parser->scanner);
  760. hash_table_dtor (parser->defines);
  761. talloc_free (parser);
  762. }
  763. /* Replace any occurences of DEFINED tokens in 'list' with either a
  764. * '0' or '1' INTEGER token depending on whether the next token in the
  765. * list is defined or not. */
  766. static void
  767. _glcpp_parser_evaluate_defined (glcpp_parser_t *parser,
  768. token_list_t *list)
  769. {
  770. token_node_t *node, *next;
  771. macro_t *macro;
  772. if (list == NULL)
  773. return;
  774. for (node = list->head; node; node = node->next) {
  775. if (node->token->type != DEFINED)
  776. continue;
  777. next = node->next;
  778. while (next && next->token->type == SPACE)
  779. next = next->next;
  780. if (next == NULL || next->token->type != IDENTIFIER) {
  781. fprintf (stderr, "Error: operator \"defined\" requires an identifier\n");
  782. exit (1);
  783. }
  784. macro = hash_table_find (parser->defines,
  785. next->token->value.str);
  786. node->token->type = INTEGER;
  787. node->token->value.ival = (macro != NULL);
  788. node->next = next->next;
  789. }
  790. }
  791. /* Appends onto 'expansion' a non-macro token or the expansion of an
  792. * object-like macro.
  793. *
  794. * Returns 0 if this token is completely processed.
  795. *
  796. * Returns 1 in the case that 'token' is a function-like macro that
  797. * needs further expansion.
  798. */
  799. static int
  800. _expand_token_onto (glcpp_parser_t *parser,
  801. token_t *token,
  802. token_list_t *result)
  803. {
  804. const char *identifier;
  805. macro_t *macro;
  806. token_list_t *expansion;
  807. /* We only expand identifiers */
  808. if (token->type != IDENTIFIER) {
  809. /* We change any COMMA into a COMMA_FINAL to prevent
  810. * it being mistaken for an argument separator
  811. * later. */
  812. if (token->type == ',') {
  813. token_t *new_token;
  814. new_token = _token_create_ival (result, COMMA_FINAL,
  815. COMMA_FINAL);
  816. _token_list_append (result, new_token);
  817. } else {
  818. _token_list_append (result, token);
  819. }
  820. return 0;
  821. }
  822. /* Look up this identifier in the hash table. */
  823. identifier = token->value.str;
  824. macro = hash_table_find (parser->defines, identifier);
  825. /* Not a macro, so just append. */
  826. if (macro == NULL) {
  827. _token_list_append (result, token);
  828. return 0;
  829. }
  830. /* Finally, don't expand this macro if we're already actively
  831. * expanding it, (to avoid infinite recursion). */
  832. if (_string_list_contains (parser->active, identifier, NULL))
  833. {
  834. /* We change the token type here from IDENTIFIER to
  835. * OTHER to prevent any future expansion of this
  836. * unexpanded token. */
  837. char *str;
  838. token_t *new_token;
  839. str = xtalloc_strdup (result, token->value.str);
  840. new_token = _token_create_str (result, OTHER, str);
  841. _token_list_append (result, new_token);
  842. return 0;
  843. }
  844. /* For function-like macros return 1 for further processing. */
  845. if (macro->is_function) {
  846. return 1;
  847. }
  848. _string_list_push (parser->active, identifier);
  849. _glcpp_parser_expand_token_list_onto (parser,
  850. macro->replacements,
  851. result);
  852. _string_list_pop (parser->active);
  853. return 0;
  854. }
  855. typedef enum function_status
  856. {
  857. FUNCTION_STATUS_SUCCESS,
  858. FUNCTION_NOT_A_FUNCTION,
  859. FUNCTION_UNBALANCED_PARENTHESES
  860. } function_status_t;
  861. /* Find a set of function-like macro arguments by looking for a
  862. * balanced set of parentheses. Upon return *node will be the last
  863. * consumed node, such that further processing can continue with
  864. * node->next.
  865. *
  866. * Return values:
  867. *
  868. * FUNCTION_STATUS_SUCCESS:
  869. *
  870. * Successfully parsed a set of function arguments.
  871. *
  872. * FUNCTION_NOT_A_FUNCTION:
  873. *
  874. * Macro name not followed by a '('. This is not an error, but
  875. * simply that the macro name should be treated as a non-macro.
  876. *
  877. * FUNCTION_UNBLANCED_PARENTHESES
  878. *
  879. * Macro name is not followed by a balanced set of parentheses.
  880. */
  881. static function_status_t
  882. _arguments_parse (argument_list_t *arguments, token_node_t **node_ret)
  883. {
  884. token_list_t *argument;
  885. token_node_t *node = *node_ret, *last;
  886. int paren_count;
  887. last = node;
  888. node = node->next;
  889. /* Ignore whitespace before first parenthesis. */
  890. while (node && node->token->type == SPACE)
  891. node = node->next;
  892. if (node == NULL || node->token->type != '(')
  893. return FUNCTION_NOT_A_FUNCTION;
  894. last = node;
  895. node = node->next;
  896. argument = NULL;
  897. for (paren_count = 1; node; last = node, node = node->next) {
  898. if (node->token->type == '(')
  899. {
  900. paren_count++;
  901. }
  902. else if (node->token->type == ')')
  903. {
  904. paren_count--;
  905. if (paren_count == 0) {
  906. last = node;
  907. node = node->next;
  908. break;
  909. }
  910. }
  911. if (node->token->type == ',' &&
  912. paren_count == 1)
  913. {
  914. if (argument)
  915. _token_list_trim_trailing_space (argument);
  916. argument = NULL;
  917. }
  918. else {
  919. if (argument == NULL) {
  920. /* Don't treat initial whitespace as
  921. * part of the arguement. */
  922. if (node->token->type == SPACE)
  923. continue;
  924. argument = _token_list_create (arguments);
  925. _argument_list_append (arguments, argument);
  926. }
  927. _token_list_append (argument, node->token);
  928. }
  929. }
  930. if (node && paren_count)
  931. return FUNCTION_UNBALANCED_PARENTHESES;
  932. *node_ret = last;
  933. return FUNCTION_STATUS_SUCCESS;
  934. }
  935. /* Prints the expansion of *node (consuming further tokens from the
  936. * list as necessary). Upon return *node will be the last consumed
  937. * node, such that further processing can continue with node->next. */
  938. static function_status_t
  939. _expand_function_onto (glcpp_parser_t *parser,
  940. token_node_t **node_ret,
  941. token_list_t *result)
  942. {
  943. macro_t *macro;
  944. token_node_t *node;
  945. const char *identifier;
  946. argument_list_t *arguments;
  947. function_status_t status;
  948. token_list_t *substituted;
  949. int parameter_index;
  950. node = *node_ret;
  951. identifier = node->token->value.str;
  952. macro = hash_table_find (parser->defines, identifier);
  953. assert (macro->is_function);
  954. arguments = _argument_list_create (parser);
  955. status = _arguments_parse (arguments, node_ret);
  956. switch (status) {
  957. case FUNCTION_STATUS_SUCCESS:
  958. break;
  959. case FUNCTION_NOT_A_FUNCTION:
  960. _token_list_append (result, node->token);
  961. return FUNCTION_NOT_A_FUNCTION;
  962. case FUNCTION_UNBALANCED_PARENTHESES:
  963. fprintf (stderr, "Error: Macro %s call has unbalanced parentheses\n",
  964. identifier);
  965. exit (1);
  966. }
  967. if (macro->replacements == NULL) {
  968. talloc_free (arguments);
  969. return FUNCTION_STATUS_SUCCESS;
  970. }
  971. if (_argument_list_length (arguments) !=
  972. _string_list_length (macro->parameters))
  973. {
  974. fprintf (stderr,
  975. "Error: macro %s invoked with %d arguments (expected %d)\n",
  976. identifier,
  977. _argument_list_length (arguments),
  978. _string_list_length (macro->parameters));
  979. exit (1);
  980. }
  981. /* Perform argument substitution on the replacement list. */
  982. substituted = _token_list_create (arguments);
  983. for (node = macro->replacements->head; node; node = node->next)
  984. {
  985. if (node->token->type == IDENTIFIER &&
  986. _string_list_contains (macro->parameters,
  987. node->token->value.str,
  988. &parameter_index))
  989. {
  990. token_list_t *argument;
  991. argument = _argument_list_member_at (arguments,
  992. parameter_index);
  993. /* Before substituting, we expand the argument
  994. * tokens. */
  995. _glcpp_parser_expand_token_list_onto (parser,
  996. argument,
  997. substituted);
  998. } else {
  999. _token_list_append (substituted, node->token);
  1000. }
  1001. }
  1002. /* After argument substitution, and before further expansion
  1003. * below, implement token pasting. */
  1004. node = substituted->head;
  1005. while (node)
  1006. {
  1007. token_node_t *next_non_space;
  1008. /* Look ahead for a PASTE token, skipping space. */
  1009. next_non_space = node->next;
  1010. while (next_non_space && next_non_space->token->type == SPACE)
  1011. next_non_space = next_non_space->next;
  1012. if (next_non_space == NULL)
  1013. break;
  1014. if (next_non_space->token->type != PASTE) {
  1015. node = next_non_space;
  1016. continue;
  1017. }
  1018. /* Now find the next non-space token after the PASTE. */
  1019. next_non_space = next_non_space->next;
  1020. while (next_non_space && next_non_space->token->type == SPACE)
  1021. next_non_space = next_non_space->next;
  1022. if (next_non_space == NULL) {
  1023. fprintf (stderr, "Error: '##' cannot appear at either end of a macro expansion\n");
  1024. exit (1);
  1025. }
  1026. _token_paste (node->token, next_non_space->token);
  1027. node->next = next_non_space->next;
  1028. node = node->next;
  1029. }
  1030. _string_list_push (parser->active, identifier);
  1031. _glcpp_parser_expand_token_list_onto (parser, substituted, result);
  1032. _string_list_pop (parser->active);
  1033. talloc_free (arguments);
  1034. return FUNCTION_STATUS_SUCCESS;
  1035. }
  1036. static void
  1037. _glcpp_parser_expand_token_list_onto (glcpp_parser_t *parser,
  1038. token_list_t *list,
  1039. token_list_t *result)
  1040. {
  1041. token_node_t *node;
  1042. token_list_t *intermediate, *list_orig = list;
  1043. int i, need_rescan = 0;
  1044. if (list == NULL || list->head == NULL)
  1045. return;
  1046. intermediate = _token_list_create (parser);
  1047. /* XXX: The two-pass expansion here is really ugly. The
  1048. * problem this is solving is that we can expand a macro into
  1049. * a function-like macro name, and then we need to recognize
  1050. * that as a function-like macro, but perhaps the parentheses
  1051. * and arguments aren't on the token list yet, (since they are
  1052. * in the actual content so they are part of what we are
  1053. * expanding.
  1054. *
  1055. * This ugly hack works, but is messy, fragile, and hard to
  1056. * maintain. I think a cleaner solution would separate the
  1057. * notions of expanding and appending and avoid this problem
  1058. * altogether.
  1059. */
  1060. for (i = 0; i < 2; i++) {
  1061. if (i == 1) {
  1062. list = intermediate;
  1063. intermediate = _token_list_create (parser);
  1064. }
  1065. for (node = list->head; node; node = node->next)
  1066. {
  1067. if (_expand_token_onto (parser, node->token,
  1068. intermediate))
  1069. {
  1070. if (_expand_function_onto (parser, &node,
  1071. intermediate))
  1072. {
  1073. need_rescan = 1;
  1074. }
  1075. }
  1076. }
  1077. if (list != list_orig)
  1078. talloc_free (list);
  1079. }
  1080. _token_list_append_list (result, intermediate);
  1081. }
  1082. void
  1083. _glcpp_parser_print_expanded_token_list (glcpp_parser_t *parser,
  1084. token_list_t *list)
  1085. {
  1086. token_list_t *expanded;
  1087. token_node_t *node;
  1088. function_status_t function_status;
  1089. if (list == NULL)
  1090. return;
  1091. expanded = _token_list_create (parser);
  1092. _glcpp_parser_expand_token_list_onto (parser, list, expanded);
  1093. _token_list_trim_trailing_space (expanded);
  1094. _token_list_print (expanded);
  1095. talloc_free (expanded);
  1096. }
  1097. void
  1098. _define_object_macro (glcpp_parser_t *parser,
  1099. const char *identifier,
  1100. token_list_t *replacements)
  1101. {
  1102. macro_t *macro;
  1103. macro = xtalloc (parser, macro_t);
  1104. macro->is_function = 0;
  1105. macro->parameters = NULL;
  1106. macro->identifier = talloc_strdup (macro, identifier);
  1107. macro->replacements = talloc_steal (macro, replacements);
  1108. hash_table_insert (parser->defines, macro, identifier);
  1109. }
  1110. void
  1111. _define_function_macro (glcpp_parser_t *parser,
  1112. const char *identifier,
  1113. string_list_t *parameters,
  1114. token_list_t *replacements)
  1115. {
  1116. macro_t *macro;
  1117. macro = xtalloc (parser, macro_t);
  1118. macro->is_function = 1;
  1119. macro->parameters = talloc_steal (macro, parameters);
  1120. macro->identifier = talloc_strdup (macro, identifier);
  1121. macro->replacements = talloc_steal (macro, replacements);
  1122. hash_table_insert (parser->defines, macro, identifier);
  1123. }
  1124. static int
  1125. glcpp_parser_lex (glcpp_parser_t *parser)
  1126. {
  1127. token_node_t *node;
  1128. int ret;
  1129. if (parser->lex_from_list == NULL) {
  1130. ret = glcpp_lex (parser->scanner);
  1131. /* XXX: This ugly block of code exists for the sole
  1132. * purpose of converting a NEWLINE token into a SPACE
  1133. * token, but only in the case where we have seen a
  1134. * function-like macro name, but have not yet seen its
  1135. * closing parenthesis.
  1136. *
  1137. * There's perhaps a more compact way to do this with
  1138. * mid-rule actions in the grammar.
  1139. *
  1140. * I'm definitely not pleased with the complexity of
  1141. * this code here.
  1142. */
  1143. if (parser->newline_as_space)
  1144. {
  1145. if (ret == '(') {
  1146. parser->paren_count++;
  1147. } else if (ret == ')') {
  1148. parser->paren_count--;
  1149. if (parser->paren_count == 0)
  1150. parser->newline_as_space = 0;
  1151. } else if (ret == NEWLINE) {
  1152. ret = SPACE;
  1153. } else if (ret != SPACE) {
  1154. if (parser->paren_count == 0)
  1155. parser->newline_as_space = 0;
  1156. }
  1157. }
  1158. else if (parser->in_control_line)
  1159. {
  1160. if (ret == NEWLINE)
  1161. parser->in_control_line = 0;
  1162. }
  1163. else if (ret == HASH_DEFINE_OBJ || ret == HASH_DEFINE_FUNC ||
  1164. ret == HASH_UNDEF || ret == HASH_IF ||
  1165. ret == HASH_IFDEF || ret == HASH_IFNDEF ||
  1166. ret == HASH_ELIF || ret == HASH_ELSE ||
  1167. ret == HASH_ENDIF || ret == HASH)
  1168. {
  1169. parser->in_control_line = 1;
  1170. }
  1171. else if (ret == IDENTIFIER)
  1172. {
  1173. macro_t *macro;
  1174. macro = hash_table_find (parser->defines,
  1175. yylval.str);
  1176. if (macro && macro->is_function) {
  1177. parser->newline_as_space = 1;
  1178. parser->paren_count = 0;
  1179. }
  1180. }
  1181. return ret;
  1182. }
  1183. node = parser->lex_from_node;
  1184. if (node == NULL) {
  1185. talloc_free (parser->lex_from_list);
  1186. parser->lex_from_list = NULL;
  1187. return NEWLINE;
  1188. }
  1189. yylval = node->token->value;
  1190. ret = node->token->type;
  1191. parser->lex_from_node = node->next;
  1192. return ret;
  1193. }
  1194. static void
  1195. glcpp_parser_lex_from (glcpp_parser_t *parser, token_list_t *list)
  1196. {
  1197. token_node_t *node;
  1198. assert (parser->lex_from_list == NULL);
  1199. /* Copy list, eliminating any space tokens. */
  1200. parser->lex_from_list = _token_list_create (parser);
  1201. for (node = list->head; node; node = node->next) {
  1202. if (node->token->type == SPACE)
  1203. continue;
  1204. _token_list_append (parser->lex_from_list, node->token);
  1205. }
  1206. talloc_free (list);
  1207. parser->lex_from_node = parser->lex_from_list->head;
  1208. /* It's possible the list consisted of nothing but whitespace. */
  1209. if (parser->lex_from_node == NULL) {
  1210. talloc_free (parser->lex_from_list);
  1211. parser->lex_from_list = NULL;
  1212. }
  1213. }
  1214. static void
  1215. _glcpp_parser_skip_stack_push_if (glcpp_parser_t *parser, int condition)
  1216. {
  1217. skip_type_t current = SKIP_NO_SKIP;
  1218. skip_node_t *node;
  1219. if (parser->skip_stack)
  1220. current = parser->skip_stack->type;
  1221. node = xtalloc (parser, skip_node_t);
  1222. if (current == SKIP_NO_SKIP) {
  1223. if (condition)
  1224. node->type = SKIP_NO_SKIP;
  1225. else
  1226. node->type = SKIP_TO_ELSE;
  1227. } else {
  1228. node->type = SKIP_TO_ENDIF;
  1229. }
  1230. node->next = parser->skip_stack;
  1231. parser->skip_stack = node;
  1232. }
  1233. static void
  1234. _glcpp_parser_skip_stack_change_if (glcpp_parser_t *parser, const char *type,
  1235. int condition)
  1236. {
  1237. if (parser->skip_stack == NULL) {
  1238. fprintf (stderr, "Error: %s without #if\n", type);
  1239. exit (1);
  1240. }
  1241. if (parser->skip_stack->type == SKIP_TO_ELSE) {
  1242. if (condition)
  1243. parser->skip_stack->type = SKIP_NO_SKIP;
  1244. } else {
  1245. parser->skip_stack->type = SKIP_TO_ENDIF;
  1246. }
  1247. }
  1248. static void
  1249. _glcpp_parser_skip_stack_pop (glcpp_parser_t *parser)
  1250. {
  1251. skip_node_t *node;
  1252. if (parser->skip_stack == NULL) {
  1253. fprintf (stderr, "Error: #endif without #if\n");
  1254. exit (1);
  1255. }
  1256. node = parser->skip_stack;
  1257. parser->skip_stack = node->next;
  1258. talloc_free (node);
  1259. }