/*******************************************************************************
*
* MODULE: sourcify.c
*
********************************************************************************
*
* DESCRIPTION: C::B::C sourcify
*
********************************************************************************
*
* $Project: /Convert-Binary-C $
* $Author: mhx $
* $Date: 2011/04/10 12:32:16 +0200 $
* $Revision: 24 $
* $Source: /cbc/sourcify.c $
*
********************************************************************************
*
* Copyright (c) 2002-2011 Marcus Holland-Moritz. All rights reserved.
* This program is free software; you can redistribute it and/or modify
* it under the same terms as Perl itself.
*
*******************************************************************************/
/*===== GLOBAL INCLUDES ======================================================*/
#define PERL_NO_GET_CONTEXT
#include <EXTERN.h>
#include <perl.h>
#include <XSUB.h>
#include "ppport.h"
/*===== LOCAL INCLUDES =======================================================*/
#include "ctlib/cttype.h"
#include "cbc/cbc.h"
#include "cbc/idl.h"
#include "cbc/sourcify.h"
#include "cbc/util.h"
/*===== DEFINES ==============================================================*/
#define T_ALREADY_DUMPED T_USER_FLAG_1
#define F_NEWLINE 0x00000001
#define F_KEYWORD 0x00000002
#define F_DONT_EXPAND 0x00000004
#define F_PRAGMA_PACK_POP 0x00000008
#define SRC_INDENT \
STMT_START { \
if (level > 0) \
add_indent(aTHX_ s, level); \
} STMT_END
#define CHECK_SET_KEYWORD \
STMT_START { \
if (pSS->flags & F_KEYWORD) \
sv_catpvn(s, " ", 1); \
else \
SRC_INDENT; \
pSS->flags &= ~F_NEWLINE; \
pSS->flags |= F_KEYWORD; \
} STMT_END
#define SvGROW_early(s, granularity) \
STMT_START { \
if (SvCUR(s) + ((granularity)/2) > SvLEN(s)) \
SvGROW(s, SvCUR(s) + (granularity)); \
} STMT_END
#define SVG_STRUCT 512
#define SVG_ENUM 512
/*===== TYPEDEFS =============================================================*/
typedef struct {
U32 flags;
unsigned pack;
} SourcifyState;
/*===== STATIC FUNCTION PROTOTYPES ===========================================*/
static void check_define_type(pTHX_ SourcifyConfig *pSC, SV *str, TypeSpec *pTS);
static void add_type_spec_string_rec(pTHX_ SourcifyConfig *pSC, SV *str, SV *s,
TypeSpec *pTS, int level, SourcifyState *pSS);
static void add_enum_spec_string_rec(pTHX_ SourcifyConfig *pSC, SV *s,
EnumSpecifier *pES, int level, SourcifyState *pSS);
static void add_struct_spec_string_rec(pTHX_ SourcifyConfig *pSC, SV *str, SV *s,
Struct *pStruct, int level, SourcifyState *pSS);
static void add_typedef_list_decl_string(pTHX_ SV *str, TypedefList *pTDL);
static void add_typedef_list_spec_string(pTHX_ SourcifyConfig *pSC, SV *str, TypedefList *pTDL);
static void add_enum_spec_string(pTHX_ SourcifyConfig *pSC, SV *str, EnumSpecifier *pES);
static void add_struct_spec_string(pTHX_ SourcifyConfig *pSC, SV *str, Struct *pStruct);
static void pp_macro_callback(const CMacroInfo *pmi);
static void add_preprocessor_definitions(pTHX_ CParseInfo *pCPI, SV *str);
/*===== EXTERNAL VARIABLES ===================================================*/
/*===== GLOBAL VARIABLES =====================================================*/
/*===== STATIC VARIABLES =====================================================*/
/*===== STATIC FUNCTIONS =====================================================*/
/*******************************************************************************
*
* ROUTINE: check_define_type
*
* WRITTEN BY: Marcus Holland-Moritz ON: Oct 2002
* CHANGED BY: ON:
*
********************************************************************************
*
* DESCRIPTION:
*
* ARGUMENTS:
*
* RETURNS:
*
*******************************************************************************/
static void check_define_type(pTHX_ SourcifyConfig *pSC, SV *str, TypeSpec *pTS)
{
u_32 flags = pTS->tflags;
CT_DEBUG(MAIN, (XSCLASS "::check_define_type( pTS=(tflags=0x%08lX, ptr=%p) )",
(unsigned long) pTS->tflags, pTS->ptr));
if (flags & T_TYPE)
{
Typedef *pTypedef= (Typedef *) pTS->ptr;
while (!pTypedef->pDecl->pointer_flag && pTypedef->pType->tflags & T_TYPE)
pTypedef = (Typedef *) pTypedef->pType->ptr;
if (pTypedef->pDecl->pointer_flag)
return;
pTS = pTypedef->pType;
flags = pTS->tflags;
}
if (flags & T_ENUM)
{
EnumSpecifier *pES = (EnumSpecifier *) pTS->ptr;
if (pES && (pES->tflags & T_ALREADY_DUMPED) == 0)
add_enum_spec_string(aTHX_ pSC, str, pES);
}
else if (flags & T_COMPOUND)
{
Struct *pStruct = (Struct *) pTS->ptr;
if (pStruct && (pStruct->tflags & T_ALREADY_DUMPED) == 0)
add_struct_spec_string(aTHX_ pSC, str, pStruct);
}
}
/*******************************************************************************
*
* ROUTINE: add_type_spec_string_rec
*
* WRITTEN BY: Marcus Holland-Moritz ON: Oct 2002
* CHANGED BY: ON:
*
********************************************************************************
*
* DESCRIPTION:
*
* ARGUMENTS:
*
* RETURNS:
*
*******************************************************************************/
static void add_type_spec_string_rec(pTHX_ SourcifyConfig *pSC, SV *str, SV *s,
TypeSpec *pTS, int level, SourcifyState *pSS)
{
u_32 flags = pTS->tflags;
CT_DEBUG(MAIN, (XSCLASS "::add_type_spec_string_rec( pTS=(tflags=0x%08lX, ptr=%p"
"), level=%d, pSS->flags=0x%08lX, pSS->pack=%u )",
(unsigned long) pTS->tflags, pTS->ptr, level,
(unsigned long) pSS->flags, pSS->pack));
if (flags & T_TYPE)
{
Typedef *pTypedef= (Typedef *) pTS->ptr;
if (pTypedef && pTypedef->pDecl->identifier[0])
{
CHECK_SET_KEYWORD;
sv_catpv(s, pTypedef->pDecl->identifier);
}
}
else if (flags & T_ENUM)
{
EnumSpecifier *pES = (EnumSpecifier *) pTS->ptr;
if (pES)
{
if (pES->identifier[0] && ((pES->tflags & T_ALREADY_DUMPED) ||
(pSS->flags & F_DONT_EXPAND)))
{
CHECK_SET_KEYWORD;
sv_catpvf(s, "enum %s", pES->identifier);
}
else
add_enum_spec_string_rec(aTHX_ pSC, s, pES, level, pSS);
}
}
else if (flags & T_COMPOUND)
{
Struct *pStruct = (Struct *) pTS->ptr;
if (pStruct)
{
if (pStruct->identifier[0] && ((pStruct->tflags & T_ALREADY_DUMPED) ||
(pSS->flags & F_DONT_EXPAND)))
{
CHECK_SET_KEYWORD;
sv_catpvf(s, "%s %s", flags & T_UNION ? "union" : "struct",
pStruct->identifier);
}
else
add_struct_spec_string_rec(aTHX_ pSC, str, s, pStruct, level, pSS);
}
}
else
{
CHECK_SET_KEYWORD;
get_basic_type_spec_string(aTHX_ &s, flags);
}
}
/*******************************************************************************
*
* ROUTINE: add_enum_spec_string_rec
*
* WRITTEN BY: Marcus Holland-Moritz ON: Oct 2002
* CHANGED BY: ON:
*
********************************************************************************
*
* DESCRIPTION:\
* \
* ARGUMENTS:
*
* RETURNS:
*
*******************************************************************************/
static void add_enum_spec_string_rec(pTHX_ SourcifyConfig *pSC, SV *s,
EnumSpecifier *pES, int level, SourcifyState *pSS)
{
CT_DEBUG(MAIN, (XSCLASS "::add_enum_spec_string_rec( pES=(identifier=\"%s\"),"
" level=%d, pSS->flags=0x%08lX, pSS->pack=%u )",
pES->identifier, level, (unsigned long) pSS->flags, pSS->pack));
SvGROW_early(s, SVG_ENUM);
pES->tflags |= T_ALREADY_DUMPED;
if (pSC->context)
{
if ((pSS->flags & F_NEWLINE) == 0)
{
sv_catpvn(s, "\n", 1);
pSS->flags &= ~F_KEYWORD;
pSS->flags |= F_NEWLINE;
}
sv_catpvf(s, "#line %lu \"%s\"\n", pES->context.line,
pES->context.pFI->name);
}
if (pSS->flags & F_KEYWORD)
sv_catpvn(s, " ", 1);
else
SRC_INDENT;
pSS->flags &= ~(F_NEWLINE|F_KEYWORD);
sv_catpvn(s, "enum", 4);
if (pES->identifier[0])
sv_catpvf(s, " %s", pES->identifier);
if (pES->enumerators)
{
ListIterator ei;
Enumerator *pEnum;
int first = 1;
Value lastVal;
sv_catpvn(s, "\n", 1);
SRC_INDENT;
sv_catpvn(s, "{", 1);
LL_foreach(pEnum, ei, pES->enumerators)
{
if (!first)
sv_catpvn(s, ",", 1);
sv_catpvn(s, "\n", 1);
SRC_INDENT;
if (( first && pEnum->value.iv == 0) ||
(!first && pEnum->value.iv == lastVal.iv + 1))
sv_catpvf(s, "\t%s", pEnum->identifier);
else
sv_catpvf(s, "\t%s = %ld", pEnum->identifier, pEnum->value.iv);
if (first)
first = 0;
lastVal = pEnum->value;
}
sv_catpvn(s, "\n", 1);
SRC_INDENT;
sv_catpvn(s, "}", 1);
}
}
/*******************************************************************************
*
* ROUTINE: add_struct_spec_string_rec
*
* WRITTEN BY: Marcus Holland-Moritz ON: Oct 2002
* CHANGED BY: ON:
*
********************************************************************************
*
* DESCRIPTION:
*
* ARGUMENTS:
*
* RETURNS:
*
*******************************************************************************/
static void add_struct_spec_string_rec(pTHX_ SourcifyConfig *pSC, SV *str, SV *s,
Struct *pStruct, int level, SourcifyState *pSS)
{
int pack_pushed;
CT_DEBUG(MAIN, (XSCLASS "::add_struct_spec_string_rec( pStruct=(identifier="
"\"%s\", pack=%d, tflags=0x%08lX), level=%d"
" pSS->flags=0x%08lX, pSS->pack=%u )",
pStruct->identifier,
pStruct->pack, (unsigned long) pStruct->tflags,
level, (unsigned long) pSS->flags, pSS->pack));
SvGROW_early(s, SVG_STRUCT);
pStruct->tflags |= T_ALREADY_DUMPED;
pack_pushed = pStruct->declarations
&& pStruct->pack
&& pStruct->pack != pSS->pack;
if (pack_pushed)
{
if ((pSS->flags & F_NEWLINE) == 0)
{
sv_catpvn(s, "\n", 1);
pSS->flags &= ~F_KEYWORD;
pSS->flags |= F_NEWLINE;
}
sv_catpvf(s, "#pragma pack(push, %u)\n", pStruct->pack);
}
if (pSC->context)
{
if ((pSS->flags & F_NEWLINE) == 0)
{
sv_catpvn(s, "\n", 1);
pSS->flags &= ~F_KEYWORD;
pSS->flags |= F_NEWLINE;
}
sv_catpvf(s, "#line %lu \"%s\"\n", pStruct->context.line,
pStruct->context.pFI->name);
}
if (pSS->flags & F_KEYWORD)
sv_catpvn(s, " ", 1);
else
SRC_INDENT;
pSS->flags &= ~(F_NEWLINE|F_KEYWORD);
if(pStruct->tflags & T_STRUCT)
sv_catpvn(s, "struct", 6);
else
sv_catpvn(s, "union", 5);
if (pStruct->identifier[0])
sv_catpvf(s, " %s", pStruct->identifier);
if (pStruct->declarations)
{
ListIterator sdi;
StructDeclaration *pStructDecl;
sv_catpvn(s, "\n", 1);
SRC_INDENT;
sv_catpvn(s, "{\n", 2);
LL_foreach(pStructDecl, sdi, pStruct->declarations)
{
ListIterator di;
Declarator *pDecl;
int first = 1, need_def = 0;
SourcifyState ss;
ss.flags = F_NEWLINE;
ss.pack = pack_pushed ? pStruct->pack : 0;
LL_foreach(pDecl, di, pStructDecl->declarators)
if (pDecl->pointer_flag == 0)
{
need_def = 1;
break;
}
if (!need_def)
ss.flags |= F_DONT_EXPAND;
add_type_spec_string_rec(aTHX_ pSC, str, s, &pStructDecl->type, level+1, &ss);
ss.flags &= ~F_DONT_EXPAND;
if (ss.flags & F_NEWLINE)
add_indent(aTHX_ s, level+1);
else if (pStructDecl->declarators)
sv_catpvn(s, " ", 1);
LL_foreach(pDecl, di, pStructDecl->declarators)
{
Value *pValue;
if (first)
first = 0;
else
sv_catpvn(s, ", ", 2);
if (pDecl->bitfield_flag)
{
sv_catpvf(s, "%s:%d", pDecl->identifier, pDecl->ext.bitfield.bits);
}
else {
sv_catpvf(s, "%s%s", pDecl->pointer_flag ? "*" : "",
pDecl->identifier);
if (pDecl->array_flag)
{
ListIterator ai;
LL_foreach(pValue, ai, pDecl->ext.array)
{
if (pValue->flags & V_IS_UNDEF)
sv_catpvn(s, "[]", 2);
else
sv_catpvf(s, "[%ld]", pValue->iv);
}
}
}
}
sv_catpvn(s, ";\n", 2);
if (ss.flags & F_PRAGMA_PACK_POP)
sv_catpvn(s, "#pragma pack(pop)\n", 18);
if (need_def)
check_define_type(aTHX_ pSC, str, &pStructDecl->type);
}
SRC_INDENT;
sv_catpvn(s, "}", 1);
}
if (pack_pushed)
pSS->flags |= F_PRAGMA_PACK_POP;
}
/*******************************************************************************
*
* ROUTINE: add_typedef_list_decl_string
*
* WRITTEN BY: Marcus Holland-Moritz ON: Oct 2002
* CHANGED BY: ON:
*
********************************************************************************
*
* DESCRIPTION:
*
* ARGUMENTS:
*
* RETURNS:
*
*******************************************************************************/
static void add_typedef_list_decl_string(pTHX_ SV *str, TypedefList *pTDL)
{
ListIterator ti;
Typedef *pTypedef;
int first = 1;
CT_DEBUG(MAIN, (XSCLASS "::add_typedef_list_decl_string( pTDL=%p )", pTDL));
LL_foreach(pTypedef, ti, pTDL->typedefs)
{
Declarator *pDecl = pTypedef->pDecl;
Value *pValue;
if (first)
first = 0;
else
sv_catpvn(str, ", ", 2);
sv_catpvf(str, "%s%s", pDecl->pointer_flag ? "*" : "", pDecl->identifier);
if (pDecl->array_flag)
{
ListIterator ai;
LL_foreach(pValue, ai, pDecl->ext.array)
{
if (pValue->flags & V_IS_UNDEF)
sv_catpvn(str, "[]", 2);
else
sv_catpvf(str, "[%ld]", pValue->iv);
}
}
}
}
/*******************************************************************************
*
* ROUTINE: add_typedef_list_spec_string
*
* WRITTEN BY: Marcus Holland-Moritz ON: Oct 2002
* CHANGED BY: ON:
*
********************************************************************************
*
* DESCRIPTION:
*
* ARGUMENTS:
*
* RETURNS:
*
*******************************************************************************/
static void add_typedef_list_spec_string(pTHX_ SourcifyConfig *pSC, SV *str, TypedefList *pTDL)
{
SV *s = newSVpv("typedef", 0);
SourcifyState ss;
CT_DEBUG(MAIN, (XSCLASS "::add_typedef_list_spec_string( pTDL=%p )", pTDL));
ss.flags = F_KEYWORD;
ss.pack = 0;
add_type_spec_string_rec(aTHX_ pSC, str, s, &pTDL->type, 0, &ss);
if ((ss.flags & F_NEWLINE) == 0)
sv_catpvn(s, " ", 1);
add_typedef_list_decl_string(aTHX_ s, pTDL);
sv_catpvn(s, ";\n", 2);
if (ss.flags & F_PRAGMA_PACK_POP)
sv_catpvn(s, "#pragma pack(pop)\n", 18);
sv_catsv(str, s);
SvREFCNT_dec(s);
}
/*******************************************************************************
*
* ROUTINE: add_enum_spec_string
*
* WRITTEN BY: Marcus Holland-Moritz ON: Oct 2002
* CHANGED BY: ON:
*
********************************************************************************
*
* DESCRIPTION:
*
* ARGUMENTS:
*
* RETURNS:
*
*******************************************************************************/
static void add_enum_spec_string(pTHX_ SourcifyConfig *pSC, SV *str, EnumSpecifier *pES)
{
SV *s = newSVpvn("", 0);
SourcifyState ss;
CT_DEBUG(MAIN, (XSCLASS "::add_enum_spec_string( pES=%p )", pES));
ss.flags = 0;
ss.pack = 0;
add_enum_spec_string_rec(aTHX_ pSC, s, pES, 0, &ss);
sv_catpvn(s, ";\n", 2);
sv_catsv(str, s);
SvREFCNT_dec(s);
}
/*******************************************************************************
*
* ROUTINE: add_struct_spec_string
*
* WRITTEN BY: Marcus Holland-Moritz ON: Oct 2002
* CHANGED BY: ON:
*
********************************************************************************
*
* DESCRIPTION:
*
* ARGUMENTS:
*
* RETURNS:
*
*******************************************************************************/
static void add_struct_spec_string(pTHX_ SourcifyConfig *pSC, SV *str, Struct *pStruct)
{
SV *s = newSVpvn("", 0);
SourcifyState ss;
CT_DEBUG(MAIN, (XSCLASS "::add_struct_spec_string( pStruct=%p )", pStruct));
ss.flags = 0;
ss.pack = 0;
add_struct_spec_string_rec(aTHX_ pSC, str, s, pStruct, 0, &ss);
sv_catpvn(s, ";\n", 2);
if (ss.flags & F_PRAGMA_PACK_POP)
sv_catpvn(s, "#pragma pack(pop)\n", 18);
sv_catsv(str, s);
SvREFCNT_dec(s);
}
/*******************************************************************************
*
* ROUTINE: pp_macro_callback
*
* WRITTEN BY: Marcus Holland-Moritz ON: Feb 2006
* CHANGED BY: ON:
*
********************************************************************************
*
* DESCRIPTION:
*
* ARGUMENTS:
*
* RETURNS:
*
*******************************************************************************/
#define SvGROWexp(s, amount) \
BEGIN_STMT { \
if (SvCUR(s) + pmi->definition_len + 10 >= SvLEN(s)) \
SvGROW(s, 2*SvLEN(s)); \
} END_STMT
struct macro_cb_arg
{
#ifdef PERL_IMPLICIT_CONTEXT
void *interp;
#endif
SV *string;
};
static void pp_macro_callback(const CMacroInfo *pmi)
{
struct macro_cb_arg *a = pmi->arg;
SV *s = a->string;
dTHXa(a->interp);
if (SvCUR(s) + pmi->definition_len + 10 >= SvLEN(s))
SvGROW(s, 2*SvLEN(s));
sv_catpvn(s, "#define ", 8);
sv_catpvn(s, pmi->definition, pmi->definition_len);
sv_catpvn(s, "\n", 1);
}
/*******************************************************************************
*
* ROUTINE: add_preprocessor_definitions
*
* WRITTEN BY: Marcus Holland-Moritz ON: Feb 2006
* CHANGED BY: ON:
*
********************************************************************************
*
* DESCRIPTION:
*
* ARGUMENTS:
*
* RETURNS:
*
*******************************************************************************/
static void add_preprocessor_definitions(pTHX_ CParseInfo *pCPI, SV *str)
{
struct macro_cb_arg a;
SV *s = newSVpvn("", 0);
#ifdef PERL_IMPLICIT_CONTEXT
a.interp = aTHX;
#endif
a.string = s;
SvGROW(s, 512);
macro_iterate_defs(pCPI, pp_macro_callback, &a, CMIF_WITH_DEFINITION |
CMIF_NO_PREDEFINED);
if (SvCUR(s) > 0)
{
sv_catpv(str, "/* preprocessor defines */\n\n");
sv_catsv(str, s);
sv_catpvn(str, "\n", 1);
}
SvREFCNT_dec(s);
}
/*******************************************************************************
*
* ROUTINE: get_sourcify_config_option
*
* WRITTEN BY: Marcus Holland-Moritz ON: Aug 2003
* CHANGED BY: ON:
*
********************************************************************************
*
* DESCRIPTION:
*
* ARGUMENTS:
*
* RETURNS:
*
*******************************************************************************/
#include "token/t_sourcify.c"
/*===== FUNCTIONS ============================================================*/
/*******************************************************************************
*
* ROUTINE: get_sourcify_config
*
* WRITTEN BY: Marcus Holland-Moritz ON: Aug 2003
* CHANGED BY: ON:
*
********************************************************************************
*
* DESCRIPTION:
*
* ARGUMENTS:
*
* RETURNS:
*
*******************************************************************************/
void get_sourcify_config(pTHX_ HV *cfg, SourcifyConfig *pSC)
{
HE *opt;
(void) hv_iterinit(cfg);
while ((opt = hv_iternext(cfg)) != NULL)
{
const char *key;
I32 keylen;
SV *value;
key = hv_iterkey(opt, &keylen);
value = hv_iterval(cfg, opt);
switch (get_sourcify_config_option(key))
{
case SOURCIFY_OPTION_Context:
pSC->context = SvTRUE(value);
break;
case SOURCIFY_OPTION_Defines:
pSC->defines = SvTRUE(value);
break;
default:
Perl_croak(aTHX_ "Invalid option '%s'", key);
}
}
}
/*******************************************************************************
*
* ROUTINE: get_parsed_definitions_string
*
* WRITTEN BY: Marcus Holland-Moritz ON: Oct 2002
* CHANGED BY: ON:
*
********************************************************************************
*
* DESCRIPTION:
*
* ARGUMENTS:
*
* RETURNS:
*
*******************************************************************************/
SV *get_parsed_definitions_string(pTHX_ CParseInfo *pCPI, SourcifyConfig *pSC)
{
ListIterator li;
TypedefList *pTDL;
EnumSpecifier *pES;
Struct *pStruct;
int fTypedefPre = 0, fTypedef = 0, fEnum = 0,
fStruct = 0, fUndefEnum = 0, fUndefStruct = 0;
SV *s = newSVpvn("", 0);
CT_DEBUG(MAIN, (XSCLASS "::get_parsed_definitions_string( pCPI=%p, pSC=%p )", pCPI, pSC));
/* typedef predeclarations */
LL_foreach(pTDL, li, pCPI->typedef_lists)
{
u_32 tflags = pTDL->type.tflags;
if ((tflags & (T_ENUM|T_STRUCT|T_UNION|T_TYPE)) == 0)
{
if (!fTypedefPre)
{
sv_catpv(s, "/* typedef predeclarations */\n\n");
fTypedefPre = 1;
}
add_typedef_list_spec_string(aTHX_ pSC, s, pTDL);
}
else
{
const char *what = NULL, *ident;
if (tflags & T_ENUM)
{
EnumSpecifier *pES = (EnumSpecifier *) pTDL->type.ptr;
if (pES && pES->identifier[0] != '\0')
{
what = "enum";
ident = pES->identifier;
}
}
else if (tflags & T_COMPOUND)
{
Struct *pStruct = (Struct *) pTDL->type.ptr;
if (pStruct && pStruct->identifier[0] != '\0')
{
what = pStruct->tflags & T_STRUCT ? "struct" : "union";
ident = pStruct->identifier;
}
}
if (what != NULL)
{
if (!fTypedefPre)
{
sv_catpv(s, "/* typedef predeclarations */\n\n");
fTypedefPre = 1;
}
sv_catpvf(s, "typedef %s %s ", what, ident);
add_typedef_list_decl_string(aTHX_ s, pTDL);
sv_catpvn(s, ";\n", 2);
}
}
}
/* typedefs */
LL_foreach(pTDL, li, pCPI->typedef_lists)
if (pTDL->type.ptr != NULL)
if (((pTDL->type.tflags & T_ENUM) &&
((EnumSpecifier *) pTDL->type.ptr)->identifier[0] == '\0') ||
((pTDL->type.tflags & T_COMPOUND) &&
((Struct *) pTDL->type.ptr)->identifier[0] == '\0') ||
(pTDL->type.tflags & T_TYPE))
{
if (!fTypedef)
{
sv_catpv(s, "\n\n/* typedefs */\n\n");
fTypedef = 1;
}
add_typedef_list_spec_string(aTHX_ pSC, s, pTDL);
sv_catpvn(s, "\n", 1);
}
/* defined enums */
LL_foreach(pES, li, pCPI->enums)
if (pES->enumerators &&
pES->identifier[0] != '\0' &&
(pES->tflags & (T_ALREADY_DUMPED)) == 0)
{
if (!fEnum)
{
sv_catpv(s, "\n/* defined enums */\n\n");
fEnum = 1;
}
add_enum_spec_string(aTHX_ pSC, s, pES);
sv_catpvn(s, "\n", 1);
}
/* defined structs and unions */
LL_foreach(pStruct, li, pCPI->structs)
if(pStruct->declarations &&
pStruct->identifier[0] != '\0' &&
(pStruct->tflags & (T_ALREADY_DUMPED)) == 0)
{
if (!fStruct)
{
sv_catpv(s, "\n/* defined structs and unions */\n\n");
fStruct = 1;
}
add_struct_spec_string(aTHX_ pSC, s, pStruct);
sv_catpvn(s, "\n", 1);
}
/* undefined enums */
LL_foreach(pES, li, pCPI->enums)
{
if ((pES->tflags & T_ALREADY_DUMPED) == 0 && pES->refcount == 0)
{
if (pES->enumerators || pES->identifier[0] != '\0')
{
if (!fUndefEnum)
{
sv_catpv(s, "\n/* undefined enums */\n\n");
fUndefEnum = 1;
}
add_enum_spec_string(aTHX_ pSC, s, pES);
sv_catpvn(s, "\n", 1);
}
}
pES->tflags &= ~T_ALREADY_DUMPED;
}
/* undefined structs and unions */
LL_foreach(pStruct, li, pCPI->structs)
{
if ((pStruct->tflags & T_ALREADY_DUMPED) == 0 && pStruct->refcount == 0)
{
if (pStruct->declarations || pStruct->identifier[0] != '\0')
{
if (!fUndefStruct)
{
sv_catpv(s, "\n/* undefined/unnamed structs and unions */\n\n");
fUndefStruct = 1;
}
add_struct_spec_string(aTHX_ pSC, s, pStruct);
sv_catpvn(s, "\n", 1);
}
}
pStruct->tflags &= ~T_ALREADY_DUMPED;
}
/*
* preprocessor stuff
*
* NOTE: This _must_ be at the end, because, if placed at the top, some
* defines may already interfere with the C code.
*/
if (pSC->defines)
add_preprocessor_definitions(aTHX_ pCPI, s);
return s;
}