1 /*******************************************************************************
2 *
3 * MODULE: ctparse.c
4 *
5 ********************************************************************************
6 *
7 * DESCRIPTION: Parser interface routines
8 *
9 ********************************************************************************
10 *
11 * Copyright (c) 2002-2020 Marcus Holland-Moritz. All rights reserved.
12 * This program is free software; you can redistribute it and/or modify
13 * it under the same terms as Perl itself.
14 *
15 *******************************************************************************/
16
17 /*===== GLOBAL INCLUDES ======================================================*/
18
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <stdarg.h>
22 #include <string.h>
23 #include <stddef.h>
24 #include <assert.h>
25
26
27 /*===== LOCAL INCLUDES =======================================================*/
28
29 #include "ctparse.h"
30 #include "cterror.h"
31 #include "ctdebug.h"
32 #include "fileinfo.h"
33 #include "parser.h"
34
35 #include "util/memalloc.h"
36
37 #include "ucpp/cpp.h"
38
39 #ifdef MEM_DEBUG
40 #include "ucpp/mem.h" /* for report_leaks() */
41 #endif
42
43 #include "cppreent.h"
44
45
46 /*===== DEFINES ==============================================================*/
47
48 #if defined MSDOS || defined WIN32
49 #define SYSTEM_DIRECTORY_DELIMITER '\\'
50 #define IS_NON_SYSTEM_DIR_DELIM( c ) ( (c) == '/' )
51 #else
52 #define SYSTEM_DIRECTORY_DELIMITER '/'
53 #define IS_NON_SYSTEM_DIR_DELIM( c ) ( (c) == '\\' )
54 #endif
55
56 #define IS_ANY_DIRECTORY_DELIMITER( c ) ( (c) == '/' || (c) == '\\' )
57
58 #define BUFFER_NAME "[buffer]"
59
60 /*===== TYPEDEFS =============================================================*/
61
62 /*===== STATIC FUNCTION PROTOTYPES ===========================================*/
63
64 static char *get_path_name(const char *dir, const char *file);
65 static void macro_callback(const struct macro_info *pmi);
66 static void add_predef_callback(const struct macro_info *pmi);
67 static void destroy_cpp(struct CPP *pp);
68
69
70 /*===== EXTERNAL VARIABLES ===================================================*/
71
72 /*===== GLOBAL VARIABLES =====================================================*/
73
74 /*===== STATIC VARIABLES =====================================================*/
75
76 #ifdef MEM_DEBUG
77 static int gs_num_cpp;
78 #endif
79
80 /*===== STATIC FUNCTIONS =====================================================*/
81
82 /*******************************************************************************
83 *
84 * ROUTINE: get_path_name
85 *
86 * WRITTEN BY: Marcus Holland-Moritz ON: Jan 2002
87 * CHANGED BY: ON:
88 *
89 ********************************************************************************
90 *
91 * DESCRIPTION:
92 *
93 * ARGUMENTS:
94 *
95 * RETURNS:
96 *
97 *******************************************************************************/
98
get_path_name(const char * dir,const char * file)99 static char *get_path_name(const char *dir, const char *file)
100 {
101 int dirlen = 0, filelen, append_delim = 0;
102 char *buf, *b;
103
104 if (dir != NULL)
105 {
106 dirlen = strlen(dir);
107 if (!IS_ANY_DIRECTORY_DELIMITER(dir[dirlen-1]))
108 append_delim = 1;
109 }
110
111 filelen = strlen(file);
112
113 AllocF(char *, buf, dirlen + append_delim + filelen + 1);
114
115 if (dir != NULL)
116 strcpy(buf, dir);
117
118 if (append_delim)
119 buf[dirlen++] = SYSTEM_DIRECTORY_DELIMITER;
120
121 strcpy(buf+dirlen, file);
122
123 for (b = buf; *b; b++)
124 if (IS_NON_SYSTEM_DIR_DELIM(*b))
125 *b = SYSTEM_DIRECTORY_DELIMITER;
126
127 return buf;
128 }
129
130 /*******************************************************************************
131 *
132 * ROUTINE: macro_callback
133 *
134 * WRITTEN BY: Marcus Holland-Moritz ON: Feb 2006
135 * CHANGED BY: ON:
136 *
137 ********************************************************************************
138 *
139 * DESCRIPTION:
140 *
141 * ARGUMENTS:
142 *
143 * RETURNS:
144 *
145 *******************************************************************************/
146
147 struct macro_cb_arg
148 {
149 HashTable predef;
150 void (*func)(const CMacroInfo *);
151 CMacroInfo info;
152 };
153
macro_callback(const struct macro_info * pmi)154 static void macro_callback(const struct macro_info *pmi)
155 {
156 struct macro_cb_arg *a = pmi->arg;
157 if (a->predef == NULL || !HT_exists(a->predef, pmi->name, 0, 0))
158 {
159 CMacroInfo *p = &a->info;
160
161 p->name = pmi->name;
162 p->definition = pmi->definition;
163 p->definition_len = pmi->definition_len;
164
165 a->func(p);
166 }
167 }
168
169 /*******************************************************************************
170 *
171 * ROUTINE: add_predef_callback
172 *
173 * WRITTEN BY: Marcus Holland-Moritz ON: Feb 2006
174 * CHANGED BY: ON:
175 *
176 ********************************************************************************
177 *
178 * DESCRIPTION:
179 *
180 * ARGUMENTS:
181 *
182 * RETURNS:
183 *
184 *******************************************************************************/
185
add_predef_callback(const struct macro_info * pmi)186 static void add_predef_callback(const struct macro_info *pmi)
187 {
188 HT_store(pmi->arg, pmi->name, 0, 0, NULL);
189 }
190
191 /*******************************************************************************
192 *
193 * ROUTINE: destroy_cpp
194 *
195 * WRITTEN BY: Marcus Holland-Moritz ON: Feb 2006
196 * CHANGED BY: ON:
197 *
198 ********************************************************************************
199 *
200 * DESCRIPTION:
201 *
202 * ARGUMENTS:
203 *
204 * RETURNS:
205 *
206 *******************************************************************************/
207
destroy_cpp(struct CPP * pp)208 static void destroy_cpp(struct CPP *pp)
209 {
210 assert(pp != 0);
211
212 wipeout(pp);
213
214 del_cpp(pp);
215
216 /* XXX: This cannot be used with concurrent preprocessor objects.
217 * Leak checking has to be done when all objects are gone.
218 */
219 #ifdef MEM_DEBUG
220 assert(gs_num_cpp > 0);
221
222 gs_num_cpp--;
223
224 if (gs_num_cpp == 0)
225 {
226 report_leaks();
227 }
228 #endif
229 }
230
231
232 /*===== FUNCTIONS ============================================================*/
233
234 /*******************************************************************************
235 *
236 * ROUTINE: macro_is_defined
237 *
238 * WRITTEN BY: Marcus Holland-Moritz ON: Feb 2006
239 * CHANGED BY: ON:
240 *
241 ********************************************************************************
242 *
243 * DESCRIPTION:
244 *
245 * ARGUMENTS:
246 *
247 * RETURNS:
248 *
249 *******************************************************************************/
250
macro_is_defined(CParseInfo * pCPI,const char * name)251 int macro_is_defined(CParseInfo *pCPI, const char *name)
252 {
253 assert(pCPI != NULL);
254
255 if (pCPI->pp)
256 return is_macro_defined(pCPI->pp, name);
257
258 return 0;
259 }
260
261 /*******************************************************************************
262 *
263 * ROUTINE: macro_get_def
264 *
265 * WRITTEN BY: Marcus Holland-Moritz ON: Feb 2006
266 * CHANGED BY: ON:
267 *
268 ********************************************************************************
269 *
270 * DESCRIPTION:
271 *
272 * ARGUMENTS:
273 *
274 * RETURNS:
275 *
276 *******************************************************************************/
277
macro_get_def(CParseInfo * pCPI,const char * name,size_t * plen)278 char *macro_get_def(CParseInfo *pCPI, const char *name, size_t *plen)
279 {
280 assert(pCPI != NULL);
281
282 if (pCPI->pp)
283 return get_macro_definition(pCPI->pp, name, plen);
284
285 return NULL;
286 }
287
288 /*******************************************************************************
289 *
290 * ROUTINE: macro_free_def
291 *
292 * WRITTEN BY: Marcus Holland-Moritz ON: Feb 2006
293 * CHANGED BY: ON:
294 *
295 ********************************************************************************
296 *
297 * DESCRIPTION:
298 *
299 * ARGUMENTS:
300 *
301 * RETURNS:
302 *
303 *******************************************************************************/
304
macro_free_def(char * p)305 void macro_free_def(char *p)
306 {
307 free_macro_definition(p);
308 }
309
310 /*******************************************************************************
311 *
312 * ROUTINE: macro_iterate_defs
313 *
314 * WRITTEN BY: Marcus Holland-Moritz ON: Feb 2006
315 * CHANGED BY: ON:
316 *
317 ********************************************************************************
318 *
319 * DESCRIPTION:
320 *
321 * ARGUMENTS:
322 *
323 * RETURNS:
324 *
325 *******************************************************************************/
326
macro_iterate_defs(CParseInfo * pCPI,void (* func)(const CMacroInfo *),void * arg,CMIFlags flags)327 void macro_iterate_defs(CParseInfo *pCPI, void (*func)(const CMacroInfo *),
328 void *arg, CMIFlags flags)
329 {
330 if (pCPI && pCPI->pp)
331 {
332 struct macro_cb_arg a;
333 unsigned long ppflags = 0;
334
335 if (flags & CMIF_WITH_DEFINITION)
336 ppflags |= MI_WITH_DEFINITION;
337
338 if (flags & CMIF_NO_PREDEFINED)
339 a.predef = pCPI->htPredefined;
340 else
341 a.predef = NULL;
342
343 a.func = func;
344 a.info.arg = arg;
345
346 iterate_macros(pCPI->pp, macro_callback, &a, ppflags);
347 }
348 }
349
350 /*******************************************************************************
351 *
352 * ROUTINE: parse_buffer
353 *
354 * WRITTEN BY: Marcus Holland-Moritz ON: Jan 2002
355 * CHANGED BY: ON:
356 *
357 ********************************************************************************
358 *
359 * DESCRIPTION:
360 *
361 * ARGUMENTS:
362 *
363 * RETURNS:
364 *
365 *******************************************************************************/
366
parse_buffer(const char * filename,const Buffer * pBuf,const CParseConfig * pCPC,CParseInfo * pCPI)367 int parse_buffer(const char *filename, const Buffer *pBuf,
368 const CParseConfig *pCPC, CParseInfo *pCPI)
369 {
370 int rval, pp_needs_init;
371 char *file, *str;
372 FILE *infile;
373 struct lexer_state lexer;
374 ParserState *pState;
375 struct CPP *pp;
376
377 CT_DEBUG(CTLIB, ("ctparse::parse_buffer( %s, %p, %p, %p )",
378 filename ? filename : BUFFER_NAME, pBuf, pCPI, pCPC));
379
380 /*----------------------------------*/
381 /* Initialize parse info structures */
382 /*----------------------------------*/
383
384 if (!pCPI->available)
385 {
386 assert(pCPI->enums == NULL);
387 assert(pCPI->structs == NULL);
388 assert(pCPI->typedef_lists == NULL);
389
390 assert(pCPI->htEnumerators == NULL);
391 assert(pCPI->htEnums == NULL);
392 assert(pCPI->htStructs == NULL);
393 assert(pCPI->htTypedefs == NULL);
394 assert(pCPI->htFiles == NULL);
395
396 CT_DEBUG(CTLIB, ("creating linked lists"));
397
398 pCPI->enums = LL_new();
399 pCPI->structs = LL_new();
400 pCPI->typedef_lists = LL_new();
401
402 pCPI->htEnumerators = HT_new_ex(5, HT_AUTOGROW);
403 pCPI->htEnums = HT_new_ex(4, HT_AUTOGROW);
404 pCPI->htStructs = HT_new_ex(4, HT_AUTOGROW);
405 pCPI->htTypedefs = HT_new_ex(4, HT_AUTOGROW);
406 pCPI->htFiles = HT_new_ex(3, HT_AUTOGROW);
407 pCPI->htPredefined = HT_new_ex(3, HT_AUTOGROW);
408
409 pCPI->errorStack = LL_new();
410
411 pCPI->available = 1;
412 }
413 else if (pCPI->enums != NULL && pCPI->structs != NULL &&
414 pCPI->typedef_lists != NULL)
415 {
416 CT_DEBUG(CTLIB, ("re-using linked lists"));
417 pop_all_errors(pCPI);
418 }
419 else
420 fatal_error("CParseInfo is inconsistent!");
421
422 /* make sure we trigger update_parse_info() afterwards */
423 pCPI->ready = 0;
424
425 /*----------------------------*/
426 /* Try to open the input file */
427 /*----------------------------*/
428
429 infile = NULL;
430
431 if (filename != NULL)
432 {
433 file = get_path_name(NULL, filename);
434
435 CT_DEBUG(CTLIB, ("Trying '%s'...", file));
436
437 infile = fopen(file, "r");
438
439 if (infile == NULL)
440 {
441 ListIterator li;
442
443 LL_foreach(str, li, pCPC->includes)
444 {
445 Free(file);
446
447 file = get_path_name(str, filename);
448
449 CT_DEBUG(CTLIB, ("Trying '%s'...", file));
450
451 if((infile = fopen(file, "r")) != NULL)
452 break;
453 }
454
455 if (infile == NULL)
456 {
457 Free(file);
458 push_error(pCPI, "Cannot find input file '%s'", filename);
459 return 0;
460 }
461 }
462 }
463
464 /*-------------------------*/
465 /* Set up new preprocessor */
466 /*-------------------------*/
467
468 CT_DEBUG(CTLIB, ("setting up preprocessor"));
469
470 pp_needs_init = pCPI->pp == NULL;
471
472 if (pp_needs_init)
473 {
474 #ifdef MEM_DEBUG
475 gs_num_cpp++;
476 #endif
477
478 pp = pCPI->pp = new_cpp();
479
480 CT_DEBUG(CTLIB, ("created preprocessor object @ %p", pp));
481
482 init_cpp(pp);
483
484 pp->ucpp_ouch = my_ucpp_ouch;
485 pp->ucpp_error = my_ucpp_error;
486 pp->ucpp_warning = my_ucpp_warning;
487 pp->callback_arg = (void *) pCPI;
488
489 r_no_special_macros = 0;
490 r_emit_defines = 0;
491 r_emit_assertions = 0;
492 r_emit_dependencies = 0;
493 r_c99_compliant = 0;
494 r_c99_hosted = 0;
495
496 init_tables(aUCPP_ 1);
497
498 CT_DEBUG(CTLIB, ("configuring preprocessor"));
499
500 init_include_path(aUCPP_ NULL);
501 }
502 else
503 {
504 pp = pCPI->pp;
505 }
506
507 if (filename != NULL)
508 {
509 set_init_filename(aUCPP_ file, 1);
510 Free(file);
511 }
512 else
513 {
514 set_init_filename(aUCPP_ BUFFER_NAME, 0);
515 }
516
517 init_lexer_state(&lexer);
518 init_lexer_mode(&lexer);
519
520 lexer.flags |= HANDLE_ASSERTIONS
521 | HANDLE_PRAGMA
522 | LINE_NUM;
523
524 if (pCPC->issue_warnings)
525 lexer.flags |= WARN_STANDARD
526 | WARN_ANNOYING
527 | WARN_TRIGRAPHS
528 | WARN_TRIGRAPHS_MORE;
529
530 if (pCPC->has_cpp_comments)
531 lexer.flags |= CPLUSPLUS_COMMENTS;
532
533 if (pCPC->has_macro_vaargs)
534 lexer.flags |= MACRO_VAARG;
535
536 if (infile != NULL)
537 {
538 lexer.input = infile;
539 }
540 else
541 {
542 lexer.input = NULL;
543 lexer.input_string = (unsigned char *) pBuf->buffer;
544 lexer.pbuf = pBuf->pos;
545 lexer.ebuf = pBuf->length;
546 }
547
548 if (pp_needs_init)
549 {
550 ListIterator li;
551
552 /* Configure standard C features */
553
554 if (pCPC->has_std_c)
555 {
556 char tmp[20 + 4*sizeof(pCPC->std_c_version)];
557 sprintf(tmp, "__STDC_VERSION__=%ldL", pCPC->std_c_version);
558 (void) define_macro(aUCPP_ &lexer, tmp);
559 }
560
561 if (pCPC->has_std_c_hosted)
562 {
563 char tmp[20];
564 sprintf(tmp, "__STDC_HOSTED__=%u", pCPC->is_std_c_hosted);
565 (void) define_macro(aUCPP_ &lexer, tmp);
566 }
567
568 /* Add includes */
569
570 LL_foreach(str, li, pCPC->includes)
571 {
572 CT_DEBUG(CTLIB, ("adding include path '%s'", str));
573 add_incpath(aUCPP_ str);
574 }
575
576 /* Make defines */
577
578 LL_foreach(str, li, pCPC->defines)
579 {
580 CT_DEBUG(CTLIB, ("defining macro '%s'", str));
581 (void) define_macro(aUCPP_ &lexer, str);
582 }
583
584 /* Make assertions */
585
586 LL_foreach(str, li, pCPC->assertions)
587 {
588 CT_DEBUG(CTLIB, ("making assertion '%s'", str));
589 (void) make_assertion(aUCPP_ str);
590 }
591
592 iterate_macros(aUCPP_ add_predef_callback, pCPI->htPredefined, 0);
593 }
594
595 enter_file(aUCPP_ &lexer, lexer.flags);
596
597 /*---------------------*/
598 /* Create the C parser */
599 /*---------------------*/
600
601 pState = c_parser_new(pCPC, pCPI, aUCPP_ &lexer);
602
603 /*-----------------*/
604 /* Parse the input */
605 /*-----------------*/
606
607 if (pCPC->disable_parser)
608 {
609 CT_DEBUG(CTLIB, ("parser is disabled, running only preprocessor"));
610 rval = 0;
611 }
612 else
613 {
614 CT_DEBUG(CTLIB, ("entering parser"));
615 rval = c_parser_run(pState);
616 CT_DEBUG(CTLIB, ("c_parse() returned %d", rval));
617 }
618
619 /*-------------------------------*/
620 /* Finish parsing (cleanup ucpp) */
621 /*-------------------------------*/
622
623 if (rval || pCPC->disable_parser)
624 while (lex(aUCPP_ &lexer) < CPPERR_EOF);
625
626 (void) check_cpp_errors(aUCPP_ &lexer);
627
628 if (DEBUG_FLAG(PREPROC))
629 {
630 pp->emit_output = stderr; /* the best we can get here... */
631 print_defines(pp);
632 print_assertions(pp);
633 }
634
635 free_lexer_state(&lexer);
636
637 /*----------------------*/
638 /* Cleanup the C parser */
639 /*----------------------*/
640
641 c_parser_delete(pState);
642
643 /* Invalidate the buffer name in the parsed files table */
644
645 if (filename == NULL)
646 ((FileInfo *) HT_get(pCPI->htFiles, BUFFER_NAME, 0, 0))->valid = 0;
647
648 #if !defined NDEBUG && defined CTLIB_DEBUGGING
649 if (DEBUG_FLAG(HASH))
650 {
651 HT_dump(pCPI->htEnumerators);
652 HT_dump(pCPI->htEnums);
653 HT_dump(pCPI->htStructs);
654 HT_dump(pCPI->htTypedefs);
655 HT_dump(pCPI->htFiles);
656 HT_dump(pCPI->htPredefined);
657 }
658 #endif
659
660 return rval ? 0 : 1;
661 }
662
663 /*******************************************************************************
664 *
665 * ROUTINE: init_parse_info
666 *
667 * WRITTEN BY: Marcus Holland-Moritz ON: Jan 2002
668 * CHANGED BY: ON:
669 *
670 ********************************************************************************
671 *
672 * DESCRIPTION:
673 *
674 * ARGUMENTS:
675 *
676 * RETURNS:
677 *
678 *******************************************************************************/
679
init_parse_info(CParseInfo * pCPI)680 void init_parse_info(CParseInfo *pCPI)
681 {
682 CT_DEBUG( CTLIB, ("ctparse::init_parse_info()") );
683
684 if (pCPI)
685 {
686 pCPI->typedef_lists = NULL;
687 pCPI->structs = NULL;
688 pCPI->enums = NULL;
689
690 pCPI->htEnumerators = NULL;
691 pCPI->htEnums = NULL;
692 pCPI->htStructs = NULL;
693 pCPI->htTypedefs = NULL;
694 pCPI->htFiles = NULL;
695 pCPI->htPredefined = NULL;
696
697 pCPI->errorStack = NULL;
698 pCPI->pp = NULL;
699
700 pCPI->available = 0;
701 pCPI->ready = 0;
702 }
703 }
704
705 /*******************************************************************************
706 *
707 * ROUTINE: reset_preprocessor
708 *
709 * WRITTEN BY: Marcus Holland-Moritz ON: Feb 2006
710 * CHANGED BY: ON:
711 *
712 ********************************************************************************
713 *
714 * DESCRIPTION:
715 *
716 * ARGUMENTS:
717 *
718 * RETURNS:
719 *
720 *******************************************************************************/
721
reset_preprocessor(CParseInfo * pCPI)722 void reset_preprocessor(CParseInfo *pCPI)
723 {
724 CT_DEBUG(CTLIB, ("ctparse::reset_preprocessor()"));
725
726 if (pCPI && pCPI->pp)
727 {
728 CT_DEBUG(CTLIB, ("destroying preprocessor object @ %p", pCPI->pp));
729
730 destroy_cpp(pCPI->pp);
731
732 pCPI->pp = NULL;
733 }
734 }
735
736 /*******************************************************************************
737 *
738 * ROUTINE: free_parse_info
739 *
740 * WRITTEN BY: Marcus Holland-Moritz ON: Jan 2002
741 * CHANGED BY: ON:
742 *
743 ********************************************************************************
744 *
745 * DESCRIPTION:
746 *
747 * ARGUMENTS:
748 *
749 * RETURNS:
750 *
751 *******************************************************************************/
752
free_parse_info(CParseInfo * pCPI)753 void free_parse_info(CParseInfo *pCPI)
754 {
755 CT_DEBUG(CTLIB, ("ctparse::free_parse_info()"));
756
757 if (pCPI)
758 {
759 if (pCPI->available)
760 {
761 LL_destroy(pCPI->enums, (LLDestroyFunc) enumspec_delete);
762 LL_destroy(pCPI->structs, (LLDestroyFunc) struct_delete);
763 LL_destroy(pCPI->typedef_lists, (LLDestroyFunc) typedef_list_delete);
764
765 HT_destroy(pCPI->htEnumerators, NULL);
766 HT_destroy(pCPI->htEnums, NULL);
767 HT_destroy(pCPI->htStructs, NULL);
768 HT_destroy(pCPI->htTypedefs, NULL);
769
770 HT_destroy(pCPI->htFiles, (LLDestroyFunc) fileinfo_delete);
771
772 HT_destroy(pCPI->htPredefined, NULL);
773
774 if (pCPI->errorStack)
775 {
776 pop_all_errors(pCPI);
777 LL_delete(pCPI->errorStack);
778 }
779 }
780
781 reset_preprocessor(pCPI);
782
783 init_parse_info(pCPI); /* make sure everything is NULL'd */
784 }
785 }
786
787 /*******************************************************************************
788 *
789 * ROUTINE: reset_parse_info
790 *
791 * WRITTEN BY: Marcus Holland-Moritz ON: Jan 2002
792 * CHANGED BY: ON:
793 *
794 ********************************************************************************
795 *
796 * DESCRIPTION:
797 *
798 * ARGUMENTS:
799 *
800 * RETURNS:
801 *
802 *******************************************************************************/
803
reset_parse_info(CParseInfo * pCPI)804 void reset_parse_info(CParseInfo *pCPI)
805 {
806 ListIterator li, ti;
807 Struct *pStruct;
808 TypedefList *pTDL;
809 Typedef *pTD;
810
811 CT_DEBUG(CTLIB, ("ctparse::reset_parse_info(): got %d struct(s)",
812 LL_count(pCPI->structs)));
813
814 /* clear size and align fields */
815 LL_foreach(pStruct, li, pCPI->structs)
816 {
817 CT_DEBUG(CTLIB, ("resetting struct '%s':", pStruct->identifier[0] ?
818 pStruct->identifier : "<no-identifier>"));
819
820 pStruct->align = 0;
821 pStruct->size = 0;
822 }
823
824 LL_foreach(pTDL, li, pCPI->typedef_lists)
825 LL_foreach(pTD, ti, pTDL->typedefs)
826 {
827 pTD->pDecl->size = -1;
828 pTD->pDecl->item_size = -1;
829 }
830
831 pCPI->ready = 0;
832 }
833
834 /*******************************************************************************
835 *
836 * ROUTINE: update_parse_info
837 *
838 * WRITTEN BY: Marcus Holland-Moritz ON: Jan 2002
839 * CHANGED BY: ON:
840 *
841 ********************************************************************************
842 *
843 * DESCRIPTION:
844 *
845 * ARGUMENTS:
846 *
847 * RETURNS:
848 *
849 *******************************************************************************/
850
update_parse_info(CParseInfo * pCPI,const CParseConfig * pCPC)851 void update_parse_info(CParseInfo *pCPI, const CParseConfig *pCPC)
852 {
853 ListIterator li, ti;
854 Struct *pStruct;
855 TypedefList *pTDL;
856 Typedef *pTD;
857
858 CT_DEBUG(CTLIB, ("ctparse::update_parse_info(): got %d struct(s)",
859 LL_count(pCPI->structs)));
860
861 /* compute size and alignment */
862 LL_foreach(pStruct, li, pCPI->structs)
863 {
864 CT_DEBUG(CTLIB, ("updating struct '%s':", pStruct->identifier[0] ?
865 pStruct->identifier : "<no-identifier>"));
866
867 if (pStruct->align == 0)
868 pCPC->layout_compound(&pCPC->layout, pStruct);
869 }
870
871 LL_foreach(pTDL, li, pCPI->typedef_lists)
872 LL_foreach(pTD, ti, pTDL->typedefs)
873 if (pTD->pDecl->size < 0)
874 {
875 unsigned size, item_size;
876
877 if (pCPC->get_type_info(&pCPC->layout, pTD->pType, pTD->pDecl,
878 "si", &size, &item_size) == GTI_NO_ERROR)
879 {
880 pTD->pDecl->size = (int) size;
881 pTD->pDecl->item_size = (int) item_size;
882 }
883 }
884
885 pCPI->ready = 1;
886 }
887
888 /*******************************************************************************
889 *
890 * ROUTINE: clone_parse_info
891 *
892 * WRITTEN BY: Marcus Holland-Moritz ON: Oct 2002
893 * CHANGED BY: ON:
894 *
895 ********************************************************************************
896 *
897 * DESCRIPTION:
898 *
899 * ARGUMENTS:
900 *
901 * RETURNS:
902 *
903 *******************************************************************************/
904
905 #define PTR_NOT_FOUND(ptr) \
906 fatal_error("FATAL: pointer " #ptr " (%p) not found! (%s:%d)\n", \
907 ptr, __FILE__, __LINE__)
908
909 #define REMAP_PTR(what, target) \
910 do { \
911 if (target != NULL) \
912 { \
913 void *ptr = HT_get(ptrmap, (const char *) &target, \
914 sizeof(void *), 0); \
915 \
916 CT_DEBUG(CTLIB, (#what ": %p => %p", target, ptr)); \
917 \
918 if (ptr) \
919 target = ptr; \
920 else \
921 PTR_NOT_FOUND((void *) target); \
922 } \
923 } while (0)
924
clone_parse_info(CParseInfo * pDest,const CParseInfo * pSrc)925 void clone_parse_info(CParseInfo *pDest, const CParseInfo *pSrc)
926 {
927 ListIterator li;
928 HashTable ptrmap;
929 EnumSpecifier *pES;
930 Struct *pStruct;
931 TypedefList *pTDL;
932
933 CT_DEBUG(CTLIB, ("ctparse::clone_parse_info()"));
934
935 if (!pSrc->available)
936 return; /* don't clone empty objects */
937
938 assert(pSrc->enums != NULL);
939 assert(pSrc->structs != NULL);
940 assert(pSrc->typedef_lists != NULL);
941
942 assert(pSrc->htEnumerators != NULL);
943 assert(pSrc->htEnums != NULL);
944 assert(pSrc->htStructs != NULL);
945 assert(pSrc->htTypedefs != NULL);
946 assert(pSrc->htFiles != NULL);
947 assert(pSrc->htPredefined != NULL);
948
949 if (pSrc->pp)
950 {
951 #ifdef MEM_DEBUG
952 gs_num_cpp++;
953 #endif
954
955 pDest->pp = clone_cpp(pSrc->pp);
956 assert(pDest->pp != NULL);
957
958 CT_DEBUG(CTLIB, ("cloned preprocessor object @ %p -> %p", pSrc->pp, pDest->pp));
959 }
960
961 ptrmap = HT_new_ex(3, HT_AUTOGROW);
962
963 pDest->enums = LL_new();
964 pDest->structs = LL_new();
965 pDest->typedef_lists = LL_new();
966 pDest->htEnumerators = HT_new_ex(HT_size(pSrc->htEnumerators), HT_AUTOGROW);
967 pDest->htEnums = HT_new_ex(HT_size(pSrc->htEnums), HT_AUTOGROW);
968 pDest->htStructs = HT_new_ex(HT_size(pSrc->htStructs), HT_AUTOGROW);
969 pDest->htTypedefs = HT_new_ex(HT_size(pSrc->htTypedefs), HT_AUTOGROW);
970 pDest->errorStack = LL_new();
971 pDest->available = pSrc->available;
972 pDest->ready = pSrc->ready;
973
974 CT_DEBUG(CTLIB, ("cloning enums"));
975
976 LL_foreach(pES, li, pSrc->enums)
977 {
978 ListIterator ei;
979 Enumerator *pEnum;
980 EnumSpecifier *pClone = enumspec_clone(pES);
981
982 CT_DEBUG(CTLIB, ("storing pointer to map: %p <=> %p", pES, pClone));
983 HT_store(ptrmap, (const char *) &pES, sizeof(pES), 0, pClone);
984 LL_push(pDest->enums, pClone);
985
986 if (pClone->identifier[0])
987 HT_store(pDest->htEnums, pClone->identifier, 0, 0, pClone);
988
989 LL_foreach(pEnum, ei, pClone->enumerators)
990 HT_store(pDest->htEnumerators, pEnum->identifier, 0, 0, pEnum);
991 }
992
993 CT_DEBUG(CTLIB, ("cloning structs"));
994
995 LL_foreach(pStruct, li, pSrc->structs)
996 {
997 Struct *pClone = struct_clone(pStruct);
998
999 CT_DEBUG(CTLIB, ("storing pointer to map: %p <=> %p", pStruct, pClone));
1000 HT_store(ptrmap, (const char *) &pStruct, sizeof(pStruct), 0, pClone);
1001 LL_push(pDest->structs, pClone);
1002
1003 if (pClone->identifier[0])
1004 HT_store(pDest->htStructs, pClone->identifier, 0, 0, pClone);
1005 }
1006
1007 CT_DEBUG(CTLIB, ("cloning typedefs"));
1008
1009 LL_foreach(pTDL, li, pSrc->typedef_lists)
1010 {
1011 ListIterator oi, ci;
1012 TypedefList *pClone = typedef_list_clone(pTDL);
1013
1014 LI_init(&oi, pTDL->typedefs);
1015 LI_init(&ci, pClone->typedefs);
1016
1017 while (LI_next(&oi) && LI_next(&ci))
1018 {
1019 Typedef *pOld = LI_curr(&oi), *pNew = LI_curr(&ci);
1020 CT_DEBUG(CTLIB, ("storing pointer to map: %p <=> %p", pOld, pNew));
1021 HT_store(ptrmap, (const char *) &pOld, sizeof(pOld), 0, pNew);
1022 HT_store(pDest->htTypedefs, pNew->pDecl->identifier, 0, 0, pNew);
1023 }
1024
1025 LL_push(pDest->typedef_lists, pClone);
1026 }
1027
1028 CT_DEBUG(CTLIB, ("cloning file information"));
1029
1030 {
1031 HashIterator isrc, idst;
1032 void *pOld, *pNew;
1033
1034 pDest->htFiles = HT_clone(pSrc->htFiles, (HTCloneFunc) fileinfo_clone);
1035
1036 HI_init(&isrc, pSrc->htFiles);
1037 HI_init(&idst, pDest->htFiles);
1038
1039 while (HI_next(&isrc, NULL, NULL, &pOld) &&
1040 HI_next(&idst, NULL, NULL, &pNew))
1041 {
1042 CT_DEBUG(CTLIB, ("storing pointer to map: %p <=> %p", pOld, pNew));
1043 HT_store(ptrmap, (const char *) &pOld, sizeof(pOld), 0, pNew);
1044 }
1045 }
1046
1047 CT_DEBUG(CTLIB, ("cloning predefined macros"));
1048
1049 pDest->htPredefined = HT_clone(pSrc->htPredefined, NULL);
1050
1051 CT_DEBUG(CTLIB, ("remapping pointers for enums"));
1052
1053 LL_foreach(pES, li, pDest->enums)
1054 REMAP_PTR(EnumSpec, pES->context.pFI);
1055
1056 CT_DEBUG(CTLIB, ("remapping pointers for structs"));
1057
1058 LL_foreach(pStruct, li, pDest->structs)
1059 {
1060 ListIterator sdi;
1061 StructDeclaration *pStructDecl;
1062
1063 CT_DEBUG(CTLIB, ("remapping pointers for struct @ %p ('%s')",
1064 pStruct, pStruct->identifier));
1065
1066 LL_foreach(pStructDecl, sdi, pStruct->declarations)
1067 REMAP_PTR(StructDecl, pStructDecl->type.ptr);
1068
1069 REMAP_PTR(Struct, pStruct->context.pFI);
1070 }
1071
1072 CT_DEBUG(CTLIB, ("remapping pointers for typedef lists"));
1073
1074 LL_foreach(pTDL, li, pDest->typedef_lists)
1075 REMAP_PTR(TypedefList, pTDL->type.ptr);
1076
1077 HT_destroy(ptrmap, NULL);
1078 }
1079
1080 #undef REMAP_PTR
1081 #undef PTR_NOT_FOUND
1082
1083