Logo Search packages:      
Sourcecode: uncrustify version File versions

static void fix_casts ( chunk_t start  )  [static]

Checks to see if the current paren is part of a cast. We already verified that this doesn't follow function, TYPE, IF, FOR, SWITCH, or WHILE and is followed by WORD, TYPE, STRUCT, ENUM, or UNION.

Parameters:
start Pointer to the open paren

We are on a potential cast of the form "(word)". We don't know if the word is a type. So lets guess based on some simple rules:

  • if all caps, likely a type
  • if it ends in _t, likely a type

If the next item is a * or &, the next item after that can't be a number or string.

If the next item is a +, the next item has to be a number.

If the next item is a -, the next item can't be a string.

For this to be a cast, the close paren must be followed by:

  • constant (number or string)
  • paren open
  • word

Find the next non-open paren item.

Definition at line 844 of file combine.cpp.

References chunk_get_next_ncnl(), chunk_t::flags, chunk_t::len, chunk_t::orig_col, chunk_t::orig_line, chunk_t::parent_type, chunk_t::str, and chunk_t::type.

Referenced by fix_symbols().

{
   chunk_t    *pc;
   chunk_t    *first;
   chunk_t    *after;
   chunk_t    *last = NULL;
   chunk_t    *paren_close;
   const char *verb       = "likely";
   const char *detail     = "";
   int        count       = 0;
   int        word_count  = 0;
   int        word_consec = 0;
   bool       nope;
   bool       doubtful_cast = false;


   LOG_FMT(LCASTS, "%s:line %d, col %d:", __func__, start->orig_line, start->orig_col);

   /* Make sure there is only WORD, TYPE, and '*' before the close paren */
   pc    = chunk_get_next_ncnl(start);
   first = pc;
   while ((pc != NULL) && (chunk_is_type(pc) ||
                           (pc->type == CT_WORD) ||
                           (pc->type == CT_QUALIFIER) ||
                           (pc->type == CT_DC_MEMBER) ||
                           (pc->type == CT_STAR)))
   {
      LOG_FMT(LCASTS, " [%s]", get_token_name(pc->type));

      if (pc->type == CT_WORD)
      {
         word_count++;
         word_consec++;
      }
      else if (pc->type == CT_DC_MEMBER)
      {
         word_count--;
      }
      else
      {
         word_consec = 0;
      }

      last = pc;
      pc   = chunk_get_next_ncnl(pc);
      count++;
   }

   if ((pc == NULL) || (pc->type != CT_PAREN_CLOSE))
   {
      LOG_FMT(LCASTS, " -- not a cast, hit [%s]\n",
              pc == NULL ? "NULL"  : get_token_name(pc->type));
      return;
   }

   if (word_count > 1)
   {
      LOG_FMT(LCASTS, " -- too many words: %d\n", word_count);
      return;
   }
   paren_close = pc;

   /* If last is a type or star, we have a cast for sure */
   if ((last->type == CT_STAR) ||
       (last->type == CT_PTR_TYPE) ||
       (last->type == CT_TYPE))
   {
      verb = "for sure";
   }
   else if (count == 1)
   {
      /**
       * We are on a potential cast of the form "(word)".
       * We don't know if the word is a type. So lets guess based on some
       * simple rules:
       *  - if all caps, likely a type
       *  - if it ends in _t, likely a type
       */
      verb = "guessed";
      if ((last->len > 3) &&
          (last->str[last->len - 2] == '_') &&
          (last->str[last->len - 1] == 't'))
      {
         detail = " -- '_t'";
      }
      else if (is_ucase_str(last->str, last->len))
      {
         detail = " -- upper case";
      }
      else
      {
         /* If we can't tell for sure whether this is a cast, decide against it */
         detail        = " -- mixed case";
         doubtful_cast = true;
      }

      /**
       * If the next item is a * or &, the next item after that can't be a
       * number or string.
       *
       * If the next item is a +, the next item has to be a number.
       *
       * If the next item is a -, the next item can't be a string.
       *
       * For this to be a cast, the close paren must be followed by:
       *  - constant (number or string)
       *  - paren open
       *  - word
       *
       * Find the next non-open paren item.
       */
      pc    = chunk_get_next_ncnl(paren_close);
      after = pc;
      do
      {
         after = chunk_get_next_ncnl(after);
      } while ((after != NULL) && (after->type == CT_PAREN_OPEN));

      if (after == NULL)
      {
         LOG_FMT(LCASTS, " -- not a cast - hit NULL\n");
         return;
      }

      nope = false;
      if (chunk_is_star(pc) || chunk_is_addr(pc))
      {
         /* star (*) and addr (&) are ambiguous */
         if ((after->type == CT_NUMBER_FP) ||
             (after->type == CT_NUMBER) ||
             (after->type == CT_STRING) ||
             doubtful_cast)
         {
            nope = true;
         }
      }
      else if (pc->type == CT_MINUS)
      {
         /* (UINT8)-1 or (foo)-1 or (FOO)-'a' */
         if ((after->type == CT_STRING) || doubtful_cast)
         {
            nope = true;
         }
      }
      else if (pc->type == CT_PLUS)
      {
         /* (UINT8)+1 or (foo)+1 */
         if (((after->type != CT_NUMBER) &&
              (after->type != CT_NUMBER_FP)) || doubtful_cast)
         {
            nope = true;
         }
      }
      else if ((pc->type != CT_NUMBER_FP) &&
               (pc->type != CT_NUMBER) &&
               (pc->type != CT_WORD) &&
               (pc->type != CT_PAREN_OPEN) &&
               (pc->type != CT_STRING) &&
               (pc->type != CT_SIZEOF) &&
               (pc->type != CT_FUNC_CALL) &&
               (pc->type != CT_FUNCTION))
      {
         LOG_FMT(LCASTS, " -- not a cast - followed by '%.*s' %s\n",
                 pc->len, pc->str, get_token_name(pc->type));
         return;
      }

      if (nope)
      {
         LOG_FMT(LCASTS, " -- not a cast - '%.*s' followed by %s\n",
                 pc->len, pc->str, get_token_name(after->type));
         return;
      }
   }

   start->parent_type       = CT_CAST;
   paren_close->parent_type = CT_CAST;

   LOG_FMT(LCASTS, " -- %s cast: (", verb);

   for (pc = first; pc != paren_close; pc = chunk_get_next_ncnl(pc))
   {
      pc->parent_type = CT_CAST;
      make_type(pc);
      LOG_FMT(LCASTS, " %.*s", pc->len, pc->str);
   }
   LOG_FMT(LCASTS, " )%s\n", detail);

   /* Mark the next item as an expression start */
   pc = chunk_get_next_ncnl(paren_close);
   if (pc != NULL)
   {
      pc->flags |= PCF_EXPR_START;
   }
}


Generated by  Doxygen 1.6.0   Back to index