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