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 )