1 /*******************************************************************************
2 *
3 * MODULE: sourcify.c
4 *
5 ********************************************************************************
6 *
7 * DESCRIPTION: C::B::C sourcify
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 #define PERL_NO_GET_CONTEXT
20 #include <EXTERN.h>
21 #include <perl.h>
22 #include <XSUB.h>
23
24 #include "ppport.h"
25
26
27 /*===== LOCAL INCLUDES =======================================================*/
28
29 #include "ctlib/cttype.h"
30
31 #include "cbc/cbc.h"
32 #include "cbc/idl.h"
33 #include "cbc/sourcify.h"
34 #include "cbc/util.h"
35
36
37 /*===== DEFINES ==============================================================*/
38
39 #define T_ALREADY_DUMPED T_USER_FLAG_1
40
41 #define F_NEWLINE 0x00000001
42 #define F_KEYWORD 0x00000002
43 #define F_DONT_EXPAND 0x00000004
44 #define F_PRAGMA_PACK_POP 0x00000008
45
46 #define SRC_INDENT \
47 STMT_START { \
48 if (level > 0) \
49 add_indent(aTHX_ s, level); \
50 } STMT_END
51
52 #define CHECK_SET_KEYWORD \
53 STMT_START { \
54 if (pSS->flags & F_KEYWORD) \
55 sv_catpvn(s, " ", 1); \
56 else \
57 SRC_INDENT; \
58 pSS->flags &= ~F_NEWLINE; \
59 pSS->flags |= F_KEYWORD; \
60 } STMT_END
61
62 #define SvGROW_early(s, granularity) \
63 STMT_START { \
64 if (SvCUR(s) + ((granularity)/2) > SvLEN(s)) \
65 SvGROW(s, SvCUR(s) + (granularity)); \
66 } STMT_END
67
68 #define SVG_STRUCT 512
69 #define SVG_ENUM 512
70
71 /*===== TYPEDEFS =============================================================*/
72
73 typedef struct {
74 U32 flags;
75 unsigned pack;
76 } SourcifyState;
77
78
79 /*===== STATIC FUNCTION PROTOTYPES ===========================================*/
80
81 static void check_define_type(pTHX_ SourcifyConfig *pSC, SV *str, TypeSpec *pTS);
82
83 static void add_type_spec_string_rec(pTHX_ SourcifyConfig *pSC, SV *str, SV *s,
84 TypeSpec *pTS, int level, SourcifyState *pSS);
85 static void add_enum_spec_string_rec(pTHX_ SourcifyConfig *pSC, SV *s,
86 EnumSpecifier *pES, int level, SourcifyState *pSS);
87 static void add_struct_spec_string_rec(pTHX_ SourcifyConfig *pSC, SV *str, SV *s,
88 Struct *pStruct, int level, SourcifyState *pSS);
89
90 static void add_typedef_list_decl_string(pTHX_ SV *str, TypedefList *pTDL);
91 static void add_typedef_list_spec_string(pTHX_ SourcifyConfig *pSC, SV *str, TypedefList *pTDL);
92 static void add_enum_spec_string(pTHX_ SourcifyConfig *pSC, SV *str, EnumSpecifier *pES);
93 static void add_struct_spec_string(pTHX_ SourcifyConfig *pSC, SV *str, Struct *pStruct);
94
95 static void pp_macro_callback(const CMacroInfo *pmi);
96 static void add_preprocessor_definitions(pTHX_ CParseInfo *pCPI, SV *str);
97
98
99 /*===== EXTERNAL VARIABLES ===================================================*/
100
101 /*===== GLOBAL VARIABLES =====================================================*/
102
103 /*===== STATIC VARIABLES =====================================================*/
104
105 /*===== STATIC FUNCTIONS =====================================================*/
106
107 /*******************************************************************************
108 *
109 * ROUTINE: check_define_type
110 *
111 * WRITTEN BY: Marcus Holland-Moritz ON: Oct 2002
112 * CHANGED BY: ON:
113 *
114 ********************************************************************************
115 *
116 * DESCRIPTION:
117 *
118 * ARGUMENTS:
119 *
120 * RETURNS:
121 *
122 *******************************************************************************/
123
check_define_type(pTHX_ SourcifyConfig * pSC,SV * str,TypeSpec * pTS)124 static void check_define_type(pTHX_ SourcifyConfig *pSC, SV *str, TypeSpec *pTS)
125 {
126 u_32 flags = pTS->tflags;
127
128 CT_DEBUG(MAIN, (XSCLASS "::check_define_type( pTS=(tflags=0x%08lX, ptr=%p) )",
129 (unsigned long) pTS->tflags, pTS->ptr));
130
131 if (flags & T_TYPE)
132 {
133 Typedef *pTypedef= (Typedef *) pTS->ptr;
134
135 while (!pTypedef->pDecl->pointer_flag && pTypedef->pType->tflags & T_TYPE)
136 pTypedef = (Typedef *) pTypedef->pType->ptr;
137
138 if (pTypedef->pDecl->pointer_flag)
139 return;
140
141 pTS = pTypedef->pType;
142 flags = pTS->tflags;
143 }
144
145 if (flags & T_ENUM)
146 {
147 EnumSpecifier *pES = (EnumSpecifier *) pTS->ptr;
148
149 if (pES && (pES->tflags & T_ALREADY_DUMPED) == 0)
150 add_enum_spec_string(aTHX_ pSC, str, pES);
151 }
152 else if (flags & T_COMPOUND)
153 {
154 Struct *pStruct = (Struct *) pTS->ptr;
155
156 if (pStruct && (pStruct->tflags & T_ALREADY_DUMPED) == 0)
157 add_struct_spec_string(aTHX_ pSC, str, pStruct);
158 }
159 }
160
161 /*******************************************************************************
162 *
163 * ROUTINE: add_type_spec_string_rec
164 *
165 * WRITTEN BY: Marcus Holland-Moritz ON: Oct 2002
166 * CHANGED BY: ON:
167 *
168 ********************************************************************************
169 *
170 * DESCRIPTION:
171 *
172 * ARGUMENTS:
173 *
174 * RETURNS:
175 *
176 *******************************************************************************/
177
add_type_spec_string_rec(pTHX_ SourcifyConfig * pSC,SV * str,SV * s,TypeSpec * pTS,int level,SourcifyState * pSS)178 static void add_type_spec_string_rec(pTHX_ SourcifyConfig *pSC, SV *str, SV *s,
179 TypeSpec *pTS, int level, SourcifyState *pSS)
180 {
181 u_32 flags = pTS->tflags;
182
183 CT_DEBUG(MAIN, (XSCLASS "::add_type_spec_string_rec( pTS=(tflags=0x%08lX, ptr=%p"
184 "), level=%d, pSS->flags=0x%08lX, pSS->pack=%u )",
185 (unsigned long) pTS->tflags, pTS->ptr, level,
186 (unsigned long) pSS->flags, pSS->pack));
187
188 if (flags & T_TYPE)
189 {
190 Typedef *pTypedef= (Typedef *) pTS->ptr;
191
192 if (pTypedef && pTypedef->pDecl->identifier[0])
193 {
194 CHECK_SET_KEYWORD;
195 sv_catpv(s, pTypedef->pDecl->identifier);
196 }
197 }
198 else if (flags & T_ENUM)
199 {
200 EnumSpecifier *pES = (EnumSpecifier *) pTS->ptr;
201
202 if (pES)
203 {
204 if (pES->identifier[0] && ((pES->tflags & T_ALREADY_DUMPED) ||
205 (pSS->flags & F_DONT_EXPAND)))
206 {
207 CHECK_SET_KEYWORD;
208 sv_catpvf(s, "enum %s", pES->identifier);
209 }
210 else
211 add_enum_spec_string_rec(aTHX_ pSC, s, pES, level, pSS);
212 }
213 }
214 else if (flags & T_COMPOUND)
215 {
216 Struct *pStruct = (Struct *) pTS->ptr;
217
218 if (pStruct)
219 {
220 if (pStruct->identifier[0] && ((pStruct->tflags & T_ALREADY_DUMPED) ||
221 (pSS->flags & F_DONT_EXPAND)))
222 {
223 CHECK_SET_KEYWORD;
224 sv_catpvf(s, "%s %s", flags & T_UNION ? "union" : "struct",
225 pStruct->identifier);
226 }
227 else
228 add_struct_spec_string_rec(aTHX_ pSC, str, s, pStruct, level, pSS);
229 }
230 }
231 else
232 {
233 CHECK_SET_KEYWORD;
234 get_basic_type_spec_string(aTHX_ &s, flags);
235 }
236 }
237
238 /*******************************************************************************
239 *
240 * ROUTINE: add_enum_spec_string_rec
241 *
242 * WRITTEN BY: Marcus Holland-Moritz ON: Oct 2002
243 * CHANGED BY: ON:
244 *
245 ********************************************************************************
246 *
247 * DESCRIPTION:\
248 * \
249 * ARGUMENTS:
250 *
251 * RETURNS:
252 *
253 *******************************************************************************/
254
add_enum_spec_string_rec(pTHX_ SourcifyConfig * pSC,SV * s,EnumSpecifier * pES,int level,SourcifyState * pSS)255 static void add_enum_spec_string_rec(pTHX_ SourcifyConfig *pSC, SV *s,
256 EnumSpecifier *pES, int level, SourcifyState *pSS)
257 {
258 CT_DEBUG(MAIN, (XSCLASS "::add_enum_spec_string_rec( pES=(identifier=\"%s\"),"
259 " level=%d, pSS->flags=0x%08lX, pSS->pack=%u )",
260 pES->identifier, level, (unsigned long) pSS->flags, pSS->pack));
261
262 SvGROW_early(s, SVG_ENUM);
263
264 pES->tflags |= T_ALREADY_DUMPED;
265
266 if (pSC->context)
267 {
268 if ((pSS->flags & F_NEWLINE) == 0)
269 {
270 sv_catpvn(s, "\n", 1);
271 pSS->flags &= ~F_KEYWORD;
272 pSS->flags |= F_NEWLINE;
273 }
274 sv_catpvf(s, "#line %lu \"%s\"\n", pES->context.line,
275 pES->context.pFI->name);
276 }
277
278 if (pSS->flags & F_KEYWORD)
279 sv_catpvn(s, " ", 1);
280 else
281 SRC_INDENT;
282
283 pSS->flags &= ~(F_NEWLINE|F_KEYWORD);
284
285 sv_catpvn(s, "enum", 4);
286 if (pES->identifier[0])
287 sv_catpvf(s, " %s", pES->identifier);
288
289 if (pES->enumerators)
290 {
291 ListIterator ei;
292 Enumerator *pEnum;
293 int first = 1;
294 Value lastVal;
295
296 sv_catpvn(s, "\n", 1);
297 SRC_INDENT;
298 sv_catpvn(s, "{", 1);
299
300 LL_foreach(pEnum, ei, pES->enumerators)
301 {
302 if (!first)
303 sv_catpvn(s, ",", 1);
304
305 sv_catpvn(s, "\n", 1);
306 SRC_INDENT;
307
308 if (( first && pEnum->value.iv == 0) ||
309 (!first && pEnum->value.iv == lastVal.iv + 1))
310 sv_catpvf(s, "\t%s", pEnum->identifier);
311 else
312 sv_catpvf(s, "\t%s = %ld", pEnum->identifier, pEnum->value.iv);
313
314 if (first)
315 first = 0;
316
317 lastVal = pEnum->value;
318 }
319
320 sv_catpvn(s, "\n", 1);
321 SRC_INDENT;
322 sv_catpvn(s, "}", 1);
323 }
324 }
325
326 /*******************************************************************************
327 *
328 * ROUTINE: add_struct_spec_string_rec
329 *
330 * WRITTEN BY: Marcus Holland-Moritz ON: Oct 2002
331 * CHANGED BY: ON:
332 *
333 ********************************************************************************
334 *
335 * DESCRIPTION:
336 *
337 * ARGUMENTS:
338 *
339 * RETURNS:
340 *
341 *******************************************************************************/
342
add_struct_spec_string_rec(pTHX_ SourcifyConfig * pSC,SV * str,SV * s,Struct * pStruct,int level,SourcifyState * pSS)343 static void add_struct_spec_string_rec(pTHX_ SourcifyConfig *pSC, SV *str, SV *s,
344 Struct *pStruct, int level, SourcifyState *pSS)
345 {
346 int pack_pushed;
347
348 CT_DEBUG(MAIN, (XSCLASS "::add_struct_spec_string_rec( pStruct=(identifier="
349 "\"%s\", pack=%d, tflags=0x%08lX), level=%d"
350 " pSS->flags=0x%08lX, pSS->pack=%u )",
351 pStruct->identifier,
352 pStruct->pack, (unsigned long) pStruct->tflags,
353 level, (unsigned long) pSS->flags, pSS->pack));
354
355 SvGROW_early(s, SVG_STRUCT);
356
357 pStruct->tflags |= T_ALREADY_DUMPED;
358
359 pack_pushed = pStruct->declarations
360 && pStruct->pack
361 && pStruct->pack != pSS->pack;
362
363 if (pack_pushed)
364 {
365 if ((pSS->flags & F_NEWLINE) == 0)
366 {
367 sv_catpvn(s, "\n", 1);
368 pSS->flags &= ~F_KEYWORD;
369 pSS->flags |= F_NEWLINE;
370 }
371 sv_catpvf(s, "#pragma pack(push, %u)\n", pStruct->pack);
372 }
373
374 if (pSC->context)
375 {
376 if ((pSS->flags & F_NEWLINE) == 0)
377 {
378 sv_catpvn(s, "\n", 1);
379 pSS->flags &= ~F_KEYWORD;
380 pSS->flags |= F_NEWLINE;
381 }
382 sv_catpvf(s, "#line %lu \"%s\"\n", pStruct->context.line,
383 pStruct->context.pFI->name);
384 }
385
386 if (pSS->flags & F_KEYWORD)
387 sv_catpvn(s, " ", 1);
388 else
389 SRC_INDENT;
390
391 pSS->flags &= ~(F_NEWLINE|F_KEYWORD);
392
393 if(pStruct->tflags & T_STRUCT)
394 sv_catpvn(s, "struct", 6);
395 else
396 sv_catpvn(s, "union", 5);
397
398 if (pStruct->identifier[0])
399 sv_catpvf(s, " %s", pStruct->identifier);
400
401 if (pStruct->declarations)
402 {
403 ListIterator sdi;
404 StructDeclaration *pStructDecl;
405
406 sv_catpvn(s, "\n", 1);
407 SRC_INDENT;
408 sv_catpvn(s, "{\n", 2);
409
410 LL_foreach(pStructDecl, sdi, pStruct->declarations)
411 {
412 ListIterator di;
413 Declarator *pDecl;
414 int first = 1, need_def = 0;
415 SourcifyState ss;
416
417 ss.flags = F_NEWLINE;
418 ss.pack = pack_pushed ? pStruct->pack : 0;
419
420 LL_foreach(pDecl, di, pStructDecl->declarators)
421 if (pDecl->pointer_flag == 0)
422 {
423 need_def = 1;
424 break;
425 }
426
427 if (!need_def)
428 ss.flags |= F_DONT_EXPAND;
429
430 add_type_spec_string_rec(aTHX_ pSC, str, s, &pStructDecl->type, level+1, &ss);
431
432 ss.flags &= ~F_DONT_EXPAND;
433
434 if (ss.flags & F_NEWLINE)
435 add_indent(aTHX_ s, level+1);
436 else if (pStructDecl->declarators)
437 sv_catpvn(s, " ", 1);
438
439 LL_foreach(pDecl, di, pStructDecl->declarators)
440 {
441 Value *pValue;
442
443 if (first)
444 first = 0;
445 else
446 sv_catpvn(s, ", ", 2);
447
448 if (pDecl->bitfield_flag)
449 {
450 sv_catpvf(s, "%s:%d", pDecl->identifier, pDecl->ext.bitfield.bits);
451 }
452 else {
453 sv_catpvf(s, "%s%s", pDecl->pointer_flag ? "*" : "",
454 pDecl->identifier);
455
456 if (pDecl->array_flag)
457 {
458 ListIterator ai;
459
460 LL_foreach(pValue, ai, pDecl->ext.array)
461 {
462 if (pValue->flags & V_IS_UNDEF)
463 sv_catpvn(s, "[]", 2);
464 else
465 sv_catpvf(s, "[%ld]", pValue->iv);
466 }
467 }
468 }
469 }
470
471 sv_catpvn(s, ";\n", 2);
472
473 if (ss.flags & F_PRAGMA_PACK_POP)
474 sv_catpvn(s, "#pragma pack(pop)\n", 18);
475
476 if (need_def)
477 check_define_type(aTHX_ pSC, str, &pStructDecl->type);
478 }
479
480 SRC_INDENT;
481 sv_catpvn(s, "}", 1);
482 }
483
484 if (pack_pushed)
485 pSS->flags |= F_PRAGMA_PACK_POP;
486 }
487
488 /*******************************************************************************
489 *
490 * ROUTINE: add_typedef_list_decl_string
491 *
492 * WRITTEN BY: Marcus Holland-Moritz ON: Oct 2002
493 * CHANGED BY: ON:
494 *
495 ********************************************************************************
496 *
497 * DESCRIPTION:
498 *
499 * ARGUMENTS:
500 *
501 * RETURNS:
502 *
503 *******************************************************************************/
504
add_typedef_list_decl_string(pTHX_ SV * str,TypedefList * pTDL)505 static void add_typedef_list_decl_string(pTHX_ SV *str, TypedefList *pTDL)
506 {
507 ListIterator ti;
508 Typedef *pTypedef;
509 int first = 1;
510
511 CT_DEBUG(MAIN, (XSCLASS "::add_typedef_list_decl_string( pTDL=%p )", pTDL));
512
513 LL_foreach(pTypedef, ti, pTDL->typedefs)
514 {
515 Declarator *pDecl = pTypedef->pDecl;
516 Value *pValue;
517
518 if (first)
519 first = 0;
520 else
521 sv_catpvn(str, ", ", 2);
522
523 sv_catpvf(str, "%s%s", pDecl->pointer_flag ? "*" : "", pDecl->identifier);
524
525 if (pDecl->array_flag)
526 {
527 ListIterator ai;
528
529 LL_foreach(pValue, ai, pDecl->ext.array)
530 {
531 if (pValue->flags & V_IS_UNDEF)
532 sv_catpvn(str, "[]", 2);
533 else
534 sv_catpvf(str, "[%ld]", pValue->iv);
535 }
536 }
537 }
538 }
539
540 /*******************************************************************************
541 *
542 * ROUTINE: add_typedef_list_spec_string
543 *
544 * WRITTEN BY: Marcus Holland-Moritz ON: Oct 2002
545 * CHANGED BY: ON:
546 *
547 ********************************************************************************
548 *
549 * DESCRIPTION:
550 *
551 * ARGUMENTS:
552 *
553 * RETURNS:
554 *
555 *******************************************************************************/
556
add_typedef_list_spec_string(pTHX_ SourcifyConfig * pSC,SV * str,TypedefList * pTDL)557 static void add_typedef_list_spec_string(pTHX_ SourcifyConfig *pSC, SV *str, TypedefList *pTDL)
558 {
559 SV *s = newSVpv("typedef", 0);
560 SourcifyState ss;
561
562 CT_DEBUG(MAIN, (XSCLASS "::add_typedef_list_spec_string( pTDL=%p )", pTDL));
563
564 ss.flags = F_KEYWORD;
565 ss.pack = 0;
566
567 add_type_spec_string_rec(aTHX_ pSC, str, s, &pTDL->type, 0, &ss);
568
569 if ((ss.flags & F_NEWLINE) == 0)
570 sv_catpvn(s, " ", 1);
571
572 add_typedef_list_decl_string(aTHX_ s, pTDL);
573
574 sv_catpvn(s, ";\n", 2);
575
576 if (ss.flags & F_PRAGMA_PACK_POP)
577 sv_catpvn(s, "#pragma pack(pop)\n", 18);
578
579 sv_catsv(str, s);
580
581 SvREFCNT_dec(s);
582 }
583
584 /*******************************************************************************
585 *
586 * ROUTINE: add_enum_spec_string
587 *
588 * WRITTEN BY: Marcus Holland-Moritz ON: Oct 2002
589 * CHANGED BY: ON:
590 *
591 ********************************************************************************
592 *
593 * DESCRIPTION:
594 *
595 * ARGUMENTS:
596 *
597 * RETURNS:
598 *
599 *******************************************************************************/
600
add_enum_spec_string(pTHX_ SourcifyConfig * pSC,SV * str,EnumSpecifier * pES)601 static void add_enum_spec_string(pTHX_ SourcifyConfig *pSC, SV *str, EnumSpecifier *pES)
602 {
603 SV *s = newSVpvn("", 0);
604 SourcifyState ss;
605
606 CT_DEBUG(MAIN, (XSCLASS "::add_enum_spec_string( pES=%p )", pES));
607
608 ss.flags = 0;
609 ss.pack = 0;
610
611 add_enum_spec_string_rec(aTHX_ pSC, s, pES, 0, &ss);
612 sv_catpvn(s, ";\n", 2);
613 sv_catsv(str, s);
614
615 SvREFCNT_dec(s);
616 }
617
618 /*******************************************************************************
619 *
620 * ROUTINE: add_struct_spec_string
621 *
622 * WRITTEN BY: Marcus Holland-Moritz ON: Oct 2002
623 * CHANGED BY: ON:
624 *
625 ********************************************************************************
626 *
627 * DESCRIPTION:
628 *
629 * ARGUMENTS:
630 *
631 * RETURNS:
632 *
633 *******************************************************************************/
634
add_struct_spec_string(pTHX_ SourcifyConfig * pSC,SV * str,Struct * pStruct)635 static void add_struct_spec_string(pTHX_ SourcifyConfig *pSC, SV *str, Struct *pStruct)
636 {
637 SV *s = newSVpvn("", 0);
638 SourcifyState ss;
639
640 CT_DEBUG(MAIN, (XSCLASS "::add_struct_spec_string( pStruct=%p )", pStruct));
641
642 ss.flags = 0;
643 ss.pack = 0;
644
645 add_struct_spec_string_rec(aTHX_ pSC, str, s, pStruct, 0, &ss);
646 sv_catpvn(s, ";\n", 2);
647
648 if (ss.flags & F_PRAGMA_PACK_POP)
649 sv_catpvn(s, "#pragma pack(pop)\n", 18);
650
651 sv_catsv(str, s);
652
653 SvREFCNT_dec(s);
654 }
655
656 /*******************************************************************************
657 *
658 * ROUTINE: pp_macro_callback
659 *
660 * WRITTEN BY: Marcus Holland-Moritz ON: Feb 2006
661 * CHANGED BY: ON:
662 *
663 ********************************************************************************
664 *
665 * DESCRIPTION:
666 *
667 * ARGUMENTS:
668 *
669 * RETURNS:
670 *
671 *******************************************************************************/
672
673 #define SvGROWexp(s, amount) \
674 BEGIN_STMT { \
675 if (SvCUR(s) + pmi->definition_len + 10 >= SvLEN(s)) \
676 SvGROW(s, 2*SvLEN(s)); \
677 } END_STMT
678
679 struct macro_cb_arg
680 {
681 #ifdef PERL_IMPLICIT_CONTEXT
682 void *interp;
683 #endif
684 SV *string;
685 };
686
pp_macro_callback(const CMacroInfo * pmi)687 static void pp_macro_callback(const CMacroInfo *pmi)
688 {
689 struct macro_cb_arg *a = pmi->arg;
690 SV *s = a->string;
691 dTHXa(a->interp);
692
693 if (SvCUR(s) + pmi->definition_len + 10 >= SvLEN(s))
694 SvGROW(s, 2*SvLEN(s));
695
696 sv_catpvn(s, "#define ", 8);
697 sv_catpvn(s, pmi->definition, pmi->definition_len);
698 sv_catpvn(s, "\n", 1);
699 }
700
701 /*******************************************************************************
702 *
703 * ROUTINE: add_preprocessor_definitions
704 *
705 * WRITTEN BY: Marcus Holland-Moritz ON: Feb 2006
706 * CHANGED BY: ON:
707 *
708 ********************************************************************************
709 *
710 * DESCRIPTION:
711 *
712 * ARGUMENTS:
713 *
714 * RETURNS:
715 *
716 *******************************************************************************/
717
add_preprocessor_definitions(pTHX_ CParseInfo * pCPI,SV * str)718 static void add_preprocessor_definitions(pTHX_ CParseInfo *pCPI, SV *str)
719 {
720 struct macro_cb_arg a;
721 SV *s = newSVpvn("", 0);
722
723 #ifdef PERL_IMPLICIT_CONTEXT
724 a.interp = aTHX;
725 #endif
726 a.string = s;
727
728 SvGROW(s, 512);
729
730 macro_iterate_defs(pCPI, pp_macro_callback, &a, CMIF_WITH_DEFINITION |
731 CMIF_NO_PREDEFINED);
732
733 if (SvCUR(s) > 0)
734 {
735 sv_catpv(str, "/* preprocessor defines */\n\n");
736 sv_catsv(str, s);
737 sv_catpvn(str, "\n", 1);
738 }
739
740 SvREFCNT_dec(s);
741 }
742
743 /*******************************************************************************
744 *
745 * ROUTINE: get_sourcify_config_option
746 *
747 * WRITTEN BY: Marcus Holland-Moritz ON: Aug 2003
748 * CHANGED BY: ON:
749 *
750 ********************************************************************************
751 *
752 * DESCRIPTION:
753 *
754 * ARGUMENTS:
755 *
756 * RETURNS:
757 *
758 *******************************************************************************/
759
760 #include "token/t_sourcify.c"
761
762
763 /*===== FUNCTIONS ============================================================*/
764
765 /*******************************************************************************
766 *
767 * ROUTINE: get_sourcify_config
768 *
769 * WRITTEN BY: Marcus Holland-Moritz ON: Aug 2003
770 * CHANGED BY: ON:
771 *
772 ********************************************************************************
773 *
774 * DESCRIPTION:
775 *
776 * ARGUMENTS:
777 *
778 * RETURNS:
779 *
780 *******************************************************************************/
781
get_sourcify_config(pTHX_ HV * cfg,SourcifyConfig * pSC)782 void get_sourcify_config(pTHX_ HV *cfg, SourcifyConfig *pSC)
783 {
784 HE *opt;
785
786 (void) hv_iterinit(cfg);
787
788 while ((opt = hv_iternext(cfg)) != NULL)
789 {
790 const char *key;
791 I32 keylen;
792 SV *value;
793
794 key = hv_iterkey(opt, &keylen);
795 value = hv_iterval(cfg, opt);
796
797 switch (get_sourcify_config_option(key))
798 {
799 case SOURCIFY_OPTION_Context:
800 pSC->context = SvTRUE(value);
801 break;
802
803 case SOURCIFY_OPTION_Defines:
804 pSC->defines = SvTRUE(value);
805 break;
806
807 default:
808 Perl_croak(aTHX_ "Invalid option '%s'", key);
809 }
810 }
811 }
812
813 /*******************************************************************************
814 *
815 * ROUTINE: get_parsed_definitions_string
816 *
817 * WRITTEN BY: Marcus Holland-Moritz ON: Oct 2002
818 * CHANGED BY: ON:
819 *
820 ********************************************************************************
821 *
822 * DESCRIPTION:
823 *
824 * ARGUMENTS:
825 *
826 * RETURNS:
827 *
828 *******************************************************************************/
829
get_parsed_definitions_string(pTHX_ CParseInfo * pCPI,SourcifyConfig * pSC)830 SV *get_parsed_definitions_string(pTHX_ CParseInfo *pCPI, SourcifyConfig *pSC)
831 {
832 ListIterator li;
833 TypedefList *pTDL;
834 EnumSpecifier *pES;
835 Struct *pStruct;
836 int fTypedefPre = 0, fTypedef = 0, fEnum = 0,
837 fStruct = 0, fUndefEnum = 0, fUndefStruct = 0;
838
839 SV *s = newSVpvn("", 0);
840
841 CT_DEBUG(MAIN, (XSCLASS "::get_parsed_definitions_string( pCPI=%p, pSC=%p )", pCPI, pSC));
842
843 /* typedef predeclarations */
844
845 LL_foreach(pTDL, li, pCPI->typedef_lists)
846 {
847 u_32 tflags = pTDL->type.tflags;
848
849 if ((tflags & (T_ENUM|T_STRUCT|T_UNION|T_TYPE)) == 0)
850 {
851 if (!fTypedefPre)
852 {
853 sv_catpv(s, "/* typedef predeclarations */\n\n");
854 fTypedefPre = 1;
855 }
856 add_typedef_list_spec_string(aTHX_ pSC, s, pTDL);
857 }
858 else
859 {
860 const char *what = NULL, *ident;
861
862 if (tflags & T_ENUM)
863 {
864 EnumSpecifier *pES = (EnumSpecifier *) pTDL->type.ptr;
865 if (pES && pES->identifier[0] != '\0')
866 {
867 what = "enum";
868 ident = pES->identifier;
869 }
870 }
871 else if (tflags & T_COMPOUND)
872 {
873 Struct *pStruct = (Struct *) pTDL->type.ptr;
874 if (pStruct && pStruct->identifier[0] != '\0')
875 {
876 what = pStruct->tflags & T_STRUCT ? "struct" : "union";
877 ident = pStruct->identifier;
878 }
879 }
880
881 if (what != NULL)
882 {
883 if (!fTypedefPre)
884 {
885 sv_catpv(s, "/* typedef predeclarations */\n\n");
886 fTypedefPre = 1;
887 }
888 sv_catpvf(s, "typedef %s %s ", what, ident);
889 add_typedef_list_decl_string(aTHX_ s, pTDL);
890 sv_catpvn(s, ";\n", 2);
891 }
892 }
893 }
894
895 /* typedefs */
896
897 LL_foreach(pTDL, li, pCPI->typedef_lists)
898 if (pTDL->type.ptr != NULL)
899 if (((pTDL->type.tflags & T_ENUM) &&
900 ((EnumSpecifier *) pTDL->type.ptr)->identifier[0] == '\0') ||
901 ((pTDL->type.tflags & T_COMPOUND) &&
902 ((Struct *) pTDL->type.ptr)->identifier[0] == '\0') ||
903 (pTDL->type.tflags & T_TYPE))
904 {
905 if (!fTypedef)
906 {
907 sv_catpv(s, "\n\n/* typedefs */\n\n");
908 fTypedef = 1;
909 }
910 add_typedef_list_spec_string(aTHX_ pSC, s, pTDL);
911 sv_catpvn(s, "\n", 1);
912 }
913
914 /* defined enums */
915
916 LL_foreach(pES, li, pCPI->enums)
917 if (pES->enumerators &&
918 pES->identifier[0] != '\0' &&
919 (pES->tflags & (T_ALREADY_DUMPED)) == 0)
920 {
921 if (!fEnum)
922 {
923 sv_catpv(s, "\n/* defined enums */\n\n");
924 fEnum = 1;
925 }
926 add_enum_spec_string(aTHX_ pSC, s, pES);
927 sv_catpvn(s, "\n", 1);
928 }
929
930 /* defined structs and unions */
931
932 LL_foreach(pStruct, li, pCPI->structs)
933 if(pStruct->declarations &&
934 pStruct->identifier[0] != '\0' &&
935 (pStruct->tflags & (T_ALREADY_DUMPED)) == 0)
936 {
937 if (!fStruct)
938 {
939 sv_catpv(s, "\n/* defined structs and unions */\n\n");
940 fStruct = 1;
941 }
942 add_struct_spec_string(aTHX_ pSC, s, pStruct);
943 sv_catpvn(s, "\n", 1);
944 }
945
946 /* undefined enums */
947
948 LL_foreach(pES, li, pCPI->enums)
949 {
950 if ((pES->tflags & T_ALREADY_DUMPED) == 0 && pES->refcount == 0)
951 {
952 if (pES->enumerators || pES->identifier[0] != '\0')
953 {
954 if (!fUndefEnum)
955 {
956 sv_catpv(s, "\n/* undefined enums */\n\n");
957 fUndefEnum = 1;
958 }
959 add_enum_spec_string(aTHX_ pSC, s, pES);
960 sv_catpvn(s, "\n", 1);
961 }
962 }
963
964 pES->tflags &= ~T_ALREADY_DUMPED;
965 }
966
967 /* undefined structs and unions */
968
969 LL_foreach(pStruct, li, pCPI->structs)
970 {
971 if ((pStruct->tflags & T_ALREADY_DUMPED) == 0 && pStruct->refcount == 0)
972 {
973 if (pStruct->declarations || pStruct->identifier[0] != '\0')
974 {
975 if (!fUndefStruct)
976 {
977 sv_catpv(s, "\n/* undefined/unnamed structs and unions */\n\n");
978 fUndefStruct = 1;
979 }
980 add_struct_spec_string(aTHX_ pSC, s, pStruct);
981 sv_catpvn(s, "\n", 1);
982 }
983 }
984
985 pStruct->tflags &= ~T_ALREADY_DUMPED;
986 }
987
988 /*
989 * preprocessor stuff
990 *
991 * NOTE: This _must_ be at the end, because, if placed at the top, some
992 * defines may already interfere with the C code.
993 */
994
995 if (pSC->defines)
996 add_preprocessor_definitions(aTHX_ pCPI, s);
997
998 return s;
999 }
1000
1001