Convert-Binary-C
view release on metacpan or search on metacpan
cbc/member.c view on Meta::CPAN
rval = append_member_string_rec(aTHX_ &pMI->type, NULL, offset, sv, pInfo);
if (pInfo)
HT_destroy(pInfo->htpad, NULL);
if (rval == GMS_NONE)
{
SvREFCNT_dec(sv);
sv = newSV(0);
}
return sv_2mortal(sv);
}
/*******************************************************************************
*
* ROUTINE: get_member
*
* WRITTEN BY: Marcus Holland-Moritz ON: Oct 2002
* CHANGED BY: ON:
*
********************************************************************************
*
* DESCRIPTION:
*
* ARGUMENTS:
*
* RETURNS:
*
*******************************************************************************/
#define TRUNC_NAME \
STMT_START { \
strncpy(trunc, name, 20); \
if (strlen(name) > 20) \
{ \
trunc[17] = trunc[18] = trunc[19] = '.'; \
trunc[20] = '\0'; \
} \
} STMT_END
#define PROPAGATE_FLAGS(from) \
STMT_START { \
if (pMIout) \
pMIout->flags |= (from) & (T_HASBITFIELD | T_UNSAFE_VAL); \
} STMT_END
#define CANNOT_ACCESS_MEMBER(type) \
STMT_START { \
assert(name != NULL); \
TRUNC_NAME; \
(void) sprintf(err = errbuf, \
"Cannot access member '%s' of " type " type", trunc); \
goto error; \
} STMT_END
int get_member(pTHX_ const MemberInfo *pMI, const char *member,
MemberInfo *pMIout, unsigned gm_flags)
{
unsigned accept_dotless_member = gm_flags & CBC_GM_ACCEPT_DOTLESS_MEMBER;
const unsigned do_calc = (gm_flags & CBC_GM_NO_OFFSET_SIZE_CALC) == 0;
const unsigned reject_oobi = gm_flags & CBC_GM_REJECT_OUT_OF_BOUNDS_INDEX;
const unsigned reject_offset = gm_flags & CBC_GM_REJECT_OFFSET;
const TypeSpec *pType;
int size, level, t_off;
int offset;
Struct *pStruct;
StructDeclaration *pSD;
Declarator *pDecl;
char *err, errbuf[128], trunc[32];
MemberExprWalker walker;
const char *name;
CT_DEBUG(MAIN, ("get_member( member=\"%s\", accept_dotless_member=%d, do_calc=%d, reject_oobi=%d )",
member, accept_dotless_member, do_calc, reject_oobi));
walker = member_expr_walker_new(aTHX_ member, 0);
if (pMIout)
pMIout->flags = 0;
pStruct = NULL;
pType = &pMI->type;
pDecl = pMI->pDecl;
if (pDecl == NULL && pType->tflags & T_TYPE)
{
Typedef *pTypedef = (Typedef *) pType->ptr;
pDecl = pTypedef->pDecl;
pType = pTypedef->pType;
}
name = NULL;
err = NULL;
offset = 0;
level = pMI->level;
size = do_calc ? -1 : 0;
if (do_calc && pDecl)
{
int i;
size = pDecl->size;
if (level > 0)
{
assert(pDecl->array_flag);
if (size < 0)
fatal("pDecl->size is not initialized in get_member()");
for (i = 0; i < level; i++)
size /= ((Value *) LL_get(pDecl->ext.array, i))->iv;
}
}
for (;;)
{
struct me_walk_info mei;
member_expr_walker_walk(aTHX_ walker, &mei);
CT_DEBUG(MAIN, ("(offset=%d, level=%d, size=%d) %s (%d)", offset, level, size,
cbc/member.c view on Meta::CPAN
goto error;
}
else if (index >= dim)
{
(void) sprintf(err = errbuf,
"Cannot use index %d into array of size %d",
index, dim);
goto error;
}
}
if (do_calc)
{
if (size < 0)
fatal("size is not initialized in get_member()");
size /= dim;
}
}
if (do_calc)
{
if (size < 0)
fatal("size is not initialized in get_member()");
offset += index * size;
}
level++;
}
}
break;
case MERV_OFFSET:
if (reject_offset)
{
err = "Cannot use offset in compound member expression";
goto error;
}
if (do_calc)
{
offset += mei.u.offset;
}
break;
default:
/* all error cases have been handled above */
fatal("unexpected retval (%d) in get_member()", (int) mei.retval);
break;
}
/* only accept dotless members at the very beginning */
accept_dotless_member = 0;
}
error:
member_expr_walker_delete(aTHX_ walker);
if (err != NULL)
{
if (gm_flags & CBC_GM_DONT_CROAK)
return 0;
Perl_croak(aTHX_ "%s", err);
}
CT_DEBUG(MAIN, ("FINISHED: typespec=[ptr=%p, flags=0x%lX], pDecl=%p[dim=%d], level=%d, offset=%d, size=%d, parent=%p",
pType->ptr, (unsigned long) pType->tflags, pDecl,
pDecl && pDecl->array_flag ? LL_count(pDecl->ext.array) : 0,
level, offset, size, pStruct));
if (pMIout)
{
pMIout->type = *pType;
pMIout->parent = pStruct;
pMIout->pDecl = pDecl;
pMIout->level = level;
pMIout->offset = offset;
pMIout->size = (unsigned) size;
}
return 1;
}
#undef TRUNC_NAME
#undef PROPAGATE_FLAGS
#undef CANNOT_ACCESS_MEMBER
/*******************************************************************************
*
* ROUTINE: member_expr_walker_new
*
* WRITTEN BY: Marcus Holland-Moritz ON: Mar 2006
* CHANGED BY: ON:
*
********************************************************************************
*
* DESCRIPTION:
*
* ARGUMENTS:
*
* RETURNS:
*
*******************************************************************************/
MemberExprWalker member_expr_walker_new(pTHX_ const char *expr, size_t len)
{
MemberExprWalker me;
assert(expr != NULL);
if (len == 0)
len = strlen(expr);
Newc(0, me, offsetof(struct member_expr, buf) + len + 1, char, struct member_expr);
me->state = ST_SEARCH;
me->p = expr;
me->startup = 1;
me->has_dot = 0;
CT_DEBUG(MAIN, ("(walk) created new walker @ %p", me));
return me;
}
/*******************************************************************************
*
* ROUTINE: member_expr_walker_retval_string
*
* WRITTEN BY: Marcus Holland-Moritz ON: Mar 2006
* CHANGED BY: ON:
*
********************************************************************************
*
* DESCRIPTION:
*
* ARGUMENTS:
*
* RETURNS:
*
*******************************************************************************/
const char *member_expr_walker_retval_string(enum me_walk_rv retval)
{
static const char *Sretval[] = {
"MERV_COMPOUND_MEMBER",
"MERV_ARRAY_INDEX",
"MERV_OFFSET",
"MERV_ERR_INVALID_MEMBER_START",
"MERV_ERR_INVALID_INDEX",
"MERV_ERR_INVALID_CHAR",
"MERV_ERR_INDEX_NOT_TERMINATED",
"MERV_ERR_INCOMPLETE",
"MERV_ERR_TERMINATED",
"MERV_END"
};
return Sretval[retval];
}
/*******************************************************************************
*
* ROUTINE: member_expr_walker_walk
*
* WRITTEN BY: Marcus Holland-Moritz ON: Mar 2006
* CHANGED BY: ON:
*
********************************************************************************
*
* DESCRIPTION:
*
* ARGUMENTS:
*
* RETURNS:
*
*******************************************************************************/
void member_expr_walker_walk(pTHX_ MemberExprWalker me, struct me_walk_info *info)
{
#ifdef CBC_DEBUGGING
static const char *Sstate[] = {
"ST_MEMBER",
"ST_INDEX",
"ST_FINISH_INDEX",
"ST_SEARCH",
"ST_TERM"
};
#endif
const char *c, *ixstr;
assert(me != NULL);
if (me->state == ST_TERM)
{
info->retval = MERV_ERR_TERMINATED;
return;
}
c = me->p;
for (;;)
{
CT_DEBUG(MAIN, ("(walk) state = %s (%d) \"%s\"%s%s", Sstate[me->state], me->state, c,
me->startup ? " [startup]" : "", me->has_dot ? " [dot]" : ""));
while (isSPACE(*c))
c++;
if (*c == '\0')
{
if (me->state != ST_SEARCH)
{
info->retval = MERV_ERR_INCOMPLETE;
goto error;
}
info->retval = MERV_END;
me->state = ST_TERM;
return;
}
switch (me->state)
{
case ST_MEMBER:
if(!(isALPHA(*c) || *c == '_'))
{
info->retval = MERV_ERR_INVALID_MEMBER_START;
goto error;
}
else
{
char *e = &me->buf[0];
do *e++ = *c++; while (isALNUM(*c) || *c == '_');
*e = '\0';
info->retval = MERV_COMPOUND_MEMBER;
info->u.compound_member.name = &me->buf[0];
info->u.compound_member.name_length = e - &me->buf[0];
info->u.compound_member.has_dot = me->has_dot;
( run in 0.556 second using v1.01-cache-2.11-cpan-e1769b4cff6 )