Example #1
0
/**
 * Removes superfluous semicolons:
 *  - after brace close whose parent is IF, ELSE, SWITCH, WHILE, FOR, NAMESPACE
 *  - after another semicolon where parent is not FOR
 *  - (D) after brace close whose parent is ENUM/STRUCT/UNION
 *  - after an open brace
 *  - when not in a #DEFINE
 */
void remove_extra_semicolons(void)
{
   LOG_FUNC_ENTRY();
   chunk_t *pc;
   chunk_t *next;
   chunk_t *prev;

   pc = chunk_get_head();
   while (pc != NULL)
   {
      next = chunk_get_next_ncnl(pc);

      if ((pc->type == CT_SEMICOLON) && !(pc->flags & PCF_IN_PREPROC) &&
          ((prev = chunk_get_prev_ncnl(pc)) != NULL))
      {
         LOG_FMT(LSCANSEMI, "Semi on %d:%d parent=%s, prev = '%s' [%s/%s]\n",
                 pc->orig_line, pc->orig_col, get_token_name(pc->parent_type),
                 prev->str.c_str(),
                 get_token_name(prev->type), get_token_name(prev->parent_type));

         if (pc->parent_type == CT_TYPEDEF)
         {
            /* keep it */
         }
         else if ((prev->type == CT_BRACE_CLOSE) &&
                  ((prev->parent_type == CT_IF) ||
                   (prev->parent_type == CT_ELSEIF) ||
                   (prev->parent_type == CT_ELSE) ||
                   (prev->parent_type == CT_SWITCH) ||
                   (prev->parent_type == CT_WHILE) ||
                   (prev->parent_type == CT_USING_STMT) ||
                   (prev->parent_type == CT_FOR) ||
                   (prev->parent_type == CT_FUNC_DEF) ||
                   (prev->parent_type == CT_OC_MSG_DECL) ||
                   (prev->parent_type == CT_FUNC_CLASS_DEF) ||
                   (prev->parent_type == CT_NAMESPACE)))
         {
            LOG_FUNC_CALL();
            remove_semicolon(pc);
         }
         else if ((prev->type == CT_BRACE_CLOSE) &&
                  (prev->parent_type == CT_NONE))
         {
            check_unknown_brace_close(pc, prev);
         }
         else if ((prev->type == CT_SEMICOLON) &&
                  (prev->parent_type != CT_FOR))
         {
            LOG_FUNC_CALL();
            remove_semicolon(pc);
         }
         else if ((cpd.lang_flags & LANG_D) &&
                  ((prev->parent_type == CT_ENUM) ||
                   (prev->parent_type == CT_UNION) ||
                   (prev->parent_type == CT_STRUCT)))
         {
            LOG_FUNC_CALL();
            remove_semicolon(pc);
         }
         else if (prev->type == CT_BRACE_OPEN)
         {
            LOG_FUNC_CALL();
            remove_semicolon(pc);
         }
      }

      pc = next;
   }
}
Example #2
0
/**
 * If there is nothing but CT_WORD and CT_MEMBER, then it's probably a
 * template thingy.  Otherwise, it's likely a comparison.
 */
static void check_template(chunk_t *start)
{
   chunk_t *pc;
   chunk_t *end;
   chunk_t *prev;
   chunk_t *next;
   bool    in_if = false;

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

   prev = chunk_get_prev_ncnl(start, CNAV_PREPROC);
   if (prev == NULL)
   {
      return;
   }

   if (prev->type == CT_TEMPLATE)
   {
      LOG_FMT(LTEMPL, " CT_TEMPLATE:");

      /* We have: "template< ... >", which is a template declaration */
      int level = 1;
      for (pc = chunk_get_next_ncnl(start, CNAV_PREPROC);
           pc != NULL;
           pc = chunk_get_next_ncnl(pc, CNAV_PREPROC))
      {
         LOG_FMT(LTEMPL, " [%s,%d]", get_token_name(pc->type), level);

         if ((pc->str[0] == '>') && (pc->len() > 1))
         {
            LOG_FMT(LTEMPL, " {split '%s' at %d:%d}",
                    pc->str.c_str(), pc->orig_line, pc->orig_col);
            split_off_angle_close(pc);
         }

         if (chunk_is_str(pc, "<", 1))
         {
            level++;
         }
         else if (chunk_is_str(pc, ">", 1))
         {
            level--;
            if (level == 0)
            {
               break;
            }
         }
      }
      end = pc;
   }
   else
   {
      /* We may have something like "a< ... >", which is a template where
       * '...' may consist of anything except braces {}, a semicolon, and
       * unbalanced parens.
       * if we are inside an 'if' statement and hit a CT_BOOL, then it isn't a
       * template.
       */

      /* A template requires a word/type right before the open angle */
      if ((prev->type != CT_WORD) &&
          (prev->type != CT_TYPE) &&
          (prev->type != CT_COMMA) &&
          (prev->type != CT_OPERATOR_VAL) &&
          (prev->parent_type != CT_OPERATOR))
      {
         LOG_FMT(LTEMPL, " - after %s + ( - Not a template\n", get_token_name(prev->type));
         start->type = CT_COMPARE;
         return;
      }

      LOG_FMT(LTEMPL, " - prev %s -", get_token_name(prev->type));

      /* Scan back and make sure we aren't inside square parens */
      pc = start;
      while ((pc = chunk_get_prev_ncnl(pc, CNAV_PREPROC)) != NULL)
      {
         if ((pc->type == CT_SEMICOLON) ||
             (pc->type == CT_BRACE_OPEN) ||
             (pc->type == CT_BRACE_CLOSE) ||
             (pc->type == CT_SQUARE_CLOSE))
         {
            break;
         }
         if ((pc->type == CT_IF) || (pc->type == CT_RETURN))
         {
            in_if = true;
            break;
         }
         if (pc->type == CT_SQUARE_OPEN)
         {
            LOG_FMT(LTEMPL, " - Not a template: after a square open\n");
            start->type = CT_COMPARE;
            return;
         }
      }

      /* Scan forward to the angle close
       * If we have a comparison in there, then it can't be a template.
       */
      c_token_t tokens[1024];
      int       num_tokens = 1;

      tokens[0] = CT_ANGLE_OPEN;
      for (pc = chunk_get_next_ncnl(start, CNAV_PREPROC);
           pc != NULL;
           pc = chunk_get_next_ncnl(pc, CNAV_PREPROC))
      {
         LOG_FMT(LTEMPL, " [%s,%d]", get_token_name(pc->type), num_tokens);

         if ((tokens[num_tokens - 1] == CT_ANGLE_OPEN) &&
             (pc->str[0] == '>') && (pc->len() > 1) &&
             (cpd.settings[UO_tok_split_gte].b || chunk_is_str(pc, ">>", 2)))
         {
            LOG_FMT(LTEMPL, " {split '%s' at %d:%d}",
                    pc->str.c_str(), pc->orig_line, pc->orig_col);
            split_off_angle_close(pc);
         }

         if (chunk_is_str(pc, "<", 1))
         {
            tokens[num_tokens++] = CT_ANGLE_OPEN;
         }
         else if (chunk_is_str(pc, ">", 1))
         {
            if ((num_tokens > 0) && (tokens[num_tokens - 1] == CT_PAREN_OPEN))
            {
               handle_double_angle_close(pc);
            }
            else if (--num_tokens <= 0)
            {
               break;
            }
            else if (tokens[num_tokens] != CT_ANGLE_OPEN)
            {
               /* unbalanced parens */
               break;
            }
         }
         else if (in_if &&
                  ((pc->type == CT_BOOL) ||
                   (pc->type == CT_COMPARE)))
         {
            break;
         }
         else if ((pc->type == CT_BRACE_OPEN) ||
                  (pc->type == CT_BRACE_CLOSE) ||
                  (pc->type == CT_SEMICOLON))
         {
            break;
         }
         else if (pc->type == CT_PAREN_OPEN)
         {
            if (num_tokens >= (int)(ARRAY_SIZE(tokens) - 1))
            {
               break;
            }
            tokens[num_tokens++] = pc->type;
         }
         else if (pc->type == CT_PAREN_CLOSE)
         {
            num_tokens--;
            if (tokens[num_tokens] != (pc->type - 1))
            {
               /* unbalanced parens */
               break;
            }
         }
      }
      end = pc;
   }

   if ((end != NULL) && (end->type == CT_ANGLE_CLOSE))
   {
      pc = chunk_get_next_ncnl(end, CNAV_PREPROC);
      if ((pc != NULL) && (pc->type != CT_NUMBER))
      {
         LOG_FMT(LTEMPL, " - Template Detected\n");

         start->parent_type = CT_TEMPLATE;

         pc = start;
         while (pc != end)
         {
            next       = chunk_get_next_ncnl(pc, CNAV_PREPROC);
            pc->flags |= PCF_IN_TEMPLATE;
            if (next->type != CT_PAREN_OPEN)
            {
               make_type(pc);
            }
            pc = next;
         }
         end->parent_type = CT_TEMPLATE;
         end->flags      |= PCF_IN_TEMPLATE;
         return;
      }
   }

   LOG_FMT(LTEMPL, " - Not a template: end = %s\n",
           (end != NULL) ? get_token_name(end->type) : "<null>");
   start->type = CT_COMPARE;
}
Example #3
0
static bool split_line(chunk_t *start)
{
   LOG_FUNC_ENTRY();
   LOG_FMT(LSPLIT, "%s(%d): start->text() '%s', orig_line is %zu, orig_col is %zu, type is %s\n",
           __func__, __LINE__, start->text(), start->orig_line, start->orig_col, get_token_name(start->type));
   LOG_FMT(LSPLIT, "   start->flags ");
   log_pcf_flags(LSPLIT, start->flags);
   LOG_FMT(LSPLIT, "   start->parent_type %s, (PCF_IN_FCN_DEF is %s), (PCF_IN_FCN_CALL is %s)\n",
           get_token_name(start->parent_type),
           ((start->flags & (PCF_IN_FCN_DEF)) != 0) ? "TRUE" : "FALSE",
           ((start->flags & (PCF_IN_FCN_CALL)) != 0) ? "TRUE" : "FALSE");

   // break at maximum line length if ls_code_width is true
   if (start->flags & PCF_ONE_LINER)
   {
      LOG_FMT(LSPLIT, "%s(%d): ** ONCE LINER SPLIT **\n", __func__, __LINE__);
      undo_one_liner(start);
      newlines_cleanup_braces(false);
      // Issue #1352
      cpd.changes++;
      return(false);
   }

   LOG_FMT(LSPLIT, "%s(%d):\n", __func__, __LINE__);
   if (cpd.settings[UO_ls_code_width].b)
   {
   }
   // Check to see if we are in a for statement
   else if (start->flags & PCF_IN_FOR)
   {
      LOG_FMT(LSPLIT, " ** FOR SPLIT **\n");
      split_for_stmt(start);
      if (!is_past_width(start))
      {
         return(true);
      }
      LOG_FMT(LSPLIT, "%s(%d): for split didn't work\n", __func__, __LINE__);
   }

   /*
    * If this is in a function call or prototype, split on commas or right
    * after the open parenthesis
    */
   else if (  (start->flags & PCF_IN_FCN_DEF)
           || start->parent_type == CT_FUNC_PROTO            // Issue #1169
           || (  (start->level == (start->brace_level + 1))
              && (start->flags & PCF_IN_FCN_CALL)))
   {
      LOG_FMT(LSPLIT, " ** FUNC SPLIT **\n");

      if (cpd.settings[UO_ls_func_split_full].b)
      {
         split_fcn_params_full(start);
         if (!is_past_width(start))
         {
            return(true);
         }
      }
      split_fcn_params(start);
      return(true);
   }

   /*
    * If this is in a template, split on commas, Issue #1170
    */
   else if (start->flags & PCF_IN_TEMPLATE)
   {
      LOG_FMT(LSPLIT, " ** TEMPLATE SPLIT **\n");
      split_template(start);
      return(true);
   }

   LOG_FMT(LSPLIT, "%s(%d):\n", __func__, __LINE__);
   // Try to find the best spot to split the line
   cw_entry ent;

   memset(&ent, 0, sizeof(ent));
   chunk_t *pc = start;
   chunk_t *prev;

   while (((pc = chunk_get_prev(pc)) != nullptr) && !chunk_is_newline(pc))
   {
      LOG_FMT(LSPLIT, "%s(%d): at %s, orig_line=%zu, orig_col=%zu\n",
              __func__, __LINE__, pc->text(), pc->orig_line, pc->orig_col);
      if (pc->type != CT_SPACE)
      {
         try_split_here(ent, pc);
         // break at maximum line length
         if (ent.pc != nullptr && (cpd.settings[UO_ls_code_width].b))
         {
            break;
         }
      }
   }

   if (ent.pc == nullptr)
   {
      LOG_FMT(LSPLIT, "\n%s(%d):    TRY_SPLIT yielded NO SOLUTION for orig_line %zu at '%s' [%s]\n",
              __func__, __LINE__, start->orig_line, start->text(), get_token_name(start->type));
   }
   else
   {
      LOG_FMT(LSPLIT, "\n%s(%d):    TRY_SPLIT yielded '%s' [%s] on orig_line %zu\n",
              __func__, __LINE__, ent.pc->text(), get_token_name(ent.pc->type), ent.pc->orig_line);
      LOG_FMT(LSPLIT, "%s(%d): ent at '%s', orig_col is %zu\n",
              __func__, __LINE__, ent.pc->text(), ent.pc->orig_col);
   }

   // Break before the token instead of after it according to the pos_xxx rules
   if (ent.pc == nullptr)
   {
      pc = nullptr;
   }
   else
   {
      if (  (  (  chunk_is_token(ent.pc, CT_ARITH)
               || chunk_is_token(ent.pc, CT_CARET))
            && (cpd.settings[UO_pos_arith].tp & TP_LEAD))
         || (  chunk_is_token(ent.pc, CT_ASSIGN)
            && (cpd.settings[UO_pos_assign].tp & TP_LEAD))
         || (  chunk_is_token(ent.pc, CT_COMPARE)
            && (cpd.settings[UO_pos_compare].tp & TP_LEAD))
         || (  (  chunk_is_token(ent.pc, CT_COND_COLON)
               || chunk_is_token(ent.pc, CT_QUESTION))
            && (cpd.settings[UO_pos_conditional].tp & TP_LEAD))
         || (  chunk_is_token(ent.pc, CT_BOOL)
            && (cpd.settings[UO_pos_bool].tp & TP_LEAD)))
      {
         pc = ent.pc;
      }
      else
      {
         pc = chunk_get_next(ent.pc);
      }
      LOG_FMT(LSPLIT, "%s(%d): at '%s', orig_col is %zu\n",
              __func__, __LINE__, pc->text(), pc->orig_col);
   }

   if (pc == nullptr)
   {
      pc = start;
      // Don't break before a close, comma, or colon
      if (  start->type == CT_PAREN_CLOSE
         || start->type == CT_PAREN_OPEN
         || start->type == CT_FPAREN_CLOSE
         || start->type == CT_FPAREN_OPEN
         || start->type == CT_SPAREN_CLOSE
         || start->type == CT_SPAREN_OPEN
         || start->type == CT_ANGLE_CLOSE
         || start->type == CT_BRACE_CLOSE
         || start->type == CT_COMMA
         || start->type == CT_SEMICOLON
         || start->type == CT_VSEMICOLON
         || start->len() == 0)
      {
         LOG_FMT(LSPLIT, " ** NO GO **\n");

         // TODO: Add in logic to handle 'hard' limits by backing up a token
         return(true);
      }
   }

   // add a newline before pc
   prev = chunk_get_prev(pc);
   if (  prev != nullptr
      && !chunk_is_newline(pc)
      && !chunk_is_newline(prev))
   {
      //int plen = (pc->len() < 5) ? pc->len() : 5;
      //int slen = (start->len() < 5) ? start->len() : 5;
      //LOG_FMT(LSPLIT, " '%.*s' [%s], started on token '%.*s' [%s]\n",
      //        plen, pc->text(), get_token_name(pc->type),
      //        slen, start->text(), get_token_name(start->type));
      LOG_FMT(LSPLIT, "%s(%d): text() '%s', type [%s], started on token '%s', type [%s]\n",
              __func__, __LINE__, pc->text(), get_token_name(pc->type),
              start->text(), get_token_name(start->type));

      split_before_chunk(pc);
   }
   return(true);
} // split_line
Example #4
0
bool close_statement(parse_frame_t *frm, chunk_t *pc)
{
   LOG_FUNC_ENTRY();
   chunk_t *vbc = pc;

   LOG_FMT(LTOK, "%s:%zu] %s '%s' type %s stage %d\n", __func__,
           pc->orig_line,
           get_token_name(pc->type), pc->text(),
           get_token_name(frm->pse[frm->pse_tos].type),
           frm->pse[frm->pse_tos].stage);

   if (cpd.consumed)
   {
      frm->stmt_count = 0;
      frm->expr_count = 0;
      LOG_FMT(LSTMT, "%s: %zu> reset2 stmt on %s\n",
              __func__, pc->orig_line, pc->text());
   }

   /**
    * Insert a CT_VBRACE_CLOSE, if needed:
    * If we are in a virtual brace and we are not ON a CT_VBRACE_CLOSE add one
    */
   if (frm->pse[frm->pse_tos].type == CT_VBRACE_OPEN)
   {
      /* If the current token has already been consumed, then add after it */
      if (cpd.consumed)
      {
         insert_vbrace_close_after(pc, frm);
      }
      else
      {
         /* otherwise, add before it and consume the vbrace */
         vbc = chunk_get_prev_ncnl(pc);
         vbc = insert_vbrace_close_after(vbc, frm);
         set_chunk_parent(vbc, frm->pse[frm->pse_tos].parent);

         frm->level--;
         frm->brace_level--;
         frm->pse_tos--;

         /* Update the token level */
         pc->level       = frm->level;
         pc->brace_level = frm->brace_level;

         print_stack(LBCSPOP, "-CS VB  ", frm, pc);

         /* And repeat the close */
         close_statement(frm, pc);
         return(true);
      }
   }

   /* See if we are done with a complex statement */
   if (frm->pse[frm->pse_tos].stage != BS_NONE)
   {
      if (handle_complex_close(frm, vbc))
      {
         return(true);
      }
   }
   return(false);
} // close_statement
Example #5
0
static bool check_complex_statements(parse_frame_t *frm, chunk_t *pc)
{
   LOG_FUNC_ENTRY();
   c_token_t parent;

   /* Turn an optional paren into either a real paren or a brace */
   if (frm->pse[frm->pse_tos].stage == BS_OP_PAREN1)
   {
      frm->pse[frm->pse_tos].stage = (pc->type != CT_PAREN_OPEN) ? BS_BRACE2 : BS_PAREN1;
   }

   /* Check for CT_ELSE after CT_IF */
   while (frm->pse[frm->pse_tos].stage == BS_ELSE)
   {
      if (pc->type == CT_ELSE)
      {
         /* Replace CT_IF with CT_ELSE on the stack & we are done */
         frm->pse[frm->pse_tos].type  = CT_ELSE;
         frm->pse[frm->pse_tos].stage = BS_ELSEIF;
         print_stack(LBCSSWAP, "=Swap   ", frm, pc);
         return(true);
      }

      /* Remove the CT_IF and close the statement */
      frm->pse_tos--;
      print_stack(LBCSPOP, "-IF-CCS ", frm, pc);
      if (close_statement(frm, pc))
      {
         return(true);
      }
   }

   /* Check for CT_IF after CT_ELSE */
   if (frm->pse[frm->pse_tos].stage == BS_ELSEIF)
   {
      if (pc->type == CT_IF)
      {
         if (!cpd.settings[UO_indent_else_if].b ||
             !chunk_is_newline(chunk_get_prev_nc(pc)))
         {
            /* Replace CT_ELSE with CT_IF */
            set_chunk_type(pc, CT_ELSEIF);
            frm->pse[frm->pse_tos].type  = CT_ELSEIF;
            frm->pse[frm->pse_tos].stage = BS_PAREN1;
            return(true);
         }
      }

      /* Jump to the 'expecting brace' stage */
      frm->pse[frm->pse_tos].stage = BS_BRACE2;
   }

   /* Check for CT_CATCH or CT_FINALLY after CT_TRY or CT_CATCH */
   while (frm->pse[frm->pse_tos].stage == BS_CATCH)
   {
      if ((pc->type == CT_CATCH) || (pc->type == CT_FINALLY))
      {
         /* Replace CT_TRY with CT_CATCH on the stack & we are done */
         frm->pse[frm->pse_tos].type  = pc->type;
         frm->pse[frm->pse_tos].stage = (pc->type == CT_CATCH) ? BS_CATCH_WHEN : BS_BRACE2;
         print_stack(LBCSSWAP, "=Swap   ", frm, pc);
         return(true);
      }

      /* Remove the CT_TRY and close the statement */
      frm->pse_tos--;
      print_stack(LBCSPOP, "-TRY-CCS ", frm, pc);
      if (close_statement(frm, pc))
      {
         return(true);
      }
   }

   /* Check for optional paren and optional CT_WHEN after CT_CATCH */
   if (frm->pse[frm->pse_tos].stage == BS_CATCH_WHEN)
   {
      if (pc->type == CT_PAREN_OPEN) // this is for the paren after "catch"
      {
         /* Replace CT_PAREN_OPEN with CT_SPAREN_OPEN */
         set_chunk_type(pc, CT_SPAREN_OPEN);
         frm->pse[frm->pse_tos].type  = pc->type;
         frm->pse[frm->pse_tos].stage = BS_PAREN1;
         return(false);
      }
      else if (pc->type == CT_WHEN)
      {
         frm->pse[frm->pse_tos].type  = pc->type;
         frm->pse[frm->pse_tos].stage = BS_OP_PAREN1;
         return(true);
      }
      else if (pc->type == CT_BRACE_OPEN)
      {
         frm->pse[frm->pse_tos].stage = BS_BRACE2;
         return(false);
      }
   }

   /* Check for CT_WHILE after the CT_DO */
   if (frm->pse[frm->pse_tos].stage == BS_WHILE)
   {
      if (pc->type == CT_WHILE)
      {
         set_chunk_type(pc, CT_WHILE_OF_DO);
         frm->pse[frm->pse_tos].type  = CT_WHILE_OF_DO; //CT_WHILE;
         frm->pse[frm->pse_tos].stage = BS_WOD_PAREN;
         return(true);
      }

      LOG_FMT(LWARN, "%s:%zu Error: Expected 'while', got '%s'\n",
              cpd.filename, pc->orig_line, pc->text());
      frm->pse_tos--;
      print_stack(LBCSPOP, "-Error  ", frm, pc);
      cpd.error_count++;
   }

   /* Insert a CT_VBRACE_OPEN, if needed */
   if ((pc->type != CT_BRACE_OPEN) &&
       ((frm->pse[frm->pse_tos].stage == BS_BRACE2) ||
        (frm->pse[frm->pse_tos].stage == BS_BRACE_DO)))
   {
      if ((cpd.lang_flags & LANG_CS) &&
          (pc->type == CT_USING_STMT) &&
          (!cpd.settings[UO_indent_using_block].b))
      {
         // don't indent the using block
      }
      else
      {
         parent = frm->pse[frm->pse_tos].type;

         chunk_t *vbrace = insert_vbrace_open_before(pc, frm);
         set_chunk_parent(vbrace, parent);

         frm->level++;
         frm->brace_level++;

         push_fmr_pse(frm, vbrace, BS_NONE, "+VBrace ");
         frm->pse[frm->pse_tos].parent = parent;

         /* update the level of pc */
         pc->level       = frm->level;
         pc->brace_level = frm->brace_level;

         /* Mark as a start of a statement */
         frm->stmt_count = 0;
         frm->expr_count = 0;
         pc->flags      |= PCF_STMT_START | PCF_EXPR_START;
         frm->stmt_count = 1;
         frm->expr_count = 1;
         LOG_FMT(LSTMT, "%zu] 2.marked %s as stmt start\n", pc->orig_line, pc->text());
      }
   }

   /* Verify open paren in complex statement */
   if ((pc->type != CT_PAREN_OPEN) &&
       ((frm->pse[frm->pse_tos].stage == BS_PAREN1) ||
        (frm->pse[frm->pse_tos].stage == BS_WOD_PAREN)))
   {
      LOG_FMT(LWARN, "%s:%zu Error: Expected '(', got '%s' for '%s'\n",
              cpd.filename, pc->orig_line, pc->text(),
              get_token_name(frm->pse[frm->pse_tos].type));

      /* Throw out the complex statement */
      frm->pse_tos--;
      print_stack(LBCSPOP, "-Error  ", frm, pc);
      cpd.error_count++;
   }

   return(false);
} // check_complex_statements
Error ScriptClassParser::parse(const String &p_code) {

	code = p_code;
	idx = 0;
	line = 0;
	error_str = String();
	error = false;
	value = Variant();
	classes.clear();

	Token tk = get_token();

	Map<int, NameDecl> name_stack;
	int curly_stack = 0;
	int type_curly_stack = 0;

	while (!error && tk != TK_EOF) {
		if (tk == TK_IDENTIFIER && String(value) == "class") {
			tk = get_token();

			if (tk == TK_IDENTIFIER) {
				String name = value;
				int at_level = type_curly_stack;

				ClassDecl class_decl;

				for (Map<int, NameDecl>::Element *E = name_stack.front(); E; E = E->next()) {
					const NameDecl &name_decl = E->value();

					if (name_decl.type == NameDecl::NAMESPACE_DECL) {
						if (E != name_stack.front())
							class_decl.namespace_ += ".";
						class_decl.namespace_ += name_decl.name;
					} else {
						class_decl.name += name_decl.name + ".";
					}
				}

				class_decl.name += name;
				class_decl.nested = type_curly_stack > 0;

				bool generic = false;

				while (true) {
					tk = get_token();

					if (tk == TK_COLON) {
						Error err = _parse_class_base(class_decl.base);
						if (err)
							return err;

						curly_stack++;
						type_curly_stack++;

						break;
					} else if (tk == TK_CURLY_BRACKET_OPEN) {
						curly_stack++;
						type_curly_stack++;
						break;
					} else if (tk == TK_OP_LESS && !generic) {
						generic = true;

						Error err = _skip_generic_type_params();
						if (err)
							return err;
					} else if (tk == TK_IDENTIFIER && String(value) == "where") {
						Error err = _parse_type_constraints();
						if (err) {
							return err;
						}

						// An open curly bracket was parsed by _parse_type_constraints, so we can exit
						curly_stack++;
						type_curly_stack++;
						break;
					} else {
						error_str = "Unexpected token: " + get_token_name(tk);
						error = true;
						return ERR_PARSE_ERROR;
					}
				}

				NameDecl name_decl;
				name_decl.name = name;
				name_decl.type = NameDecl::CLASS_DECL;
				name_stack[at_level] = name_decl;

				if (!generic) { // no generics, thanks
					classes.push_back(class_decl);
				} else if (OS::get_singleton()->is_stdout_verbose()) {
					String full_name = class_decl.namespace_;
					if (full_name.length())
						full_name += ".";
					full_name += class_decl.name;
					OS::get_singleton()->print(String("Ignoring generic class declaration: " + class_decl.name).utf8());
				}
			}
		} else if (tk == TK_IDENTIFIER && String(value) == "struct") {
			String name;
			int at_level = type_curly_stack;
			while (true) {
				tk = get_token();
				if (tk == TK_IDENTIFIER && name.empty()) {
					name = String(value);
				} else if (tk == TK_CURLY_BRACKET_OPEN) {
					if (name.empty()) {
						error_str = "Expected " + get_token_name(TK_IDENTIFIER) + " after keyword `struct`, found " + get_token_name(TK_CURLY_BRACKET_OPEN);
						error = true;
						return ERR_PARSE_ERROR;
					}

					curly_stack++;
					type_curly_stack++;
					break;
				} else if (tk == TK_EOF) {
					error_str = "Expected " + get_token_name(TK_CURLY_BRACKET_OPEN) + " after struct decl, found " + get_token_name(TK_EOF);
					error = true;
					return ERR_PARSE_ERROR;
				}
			}

			NameDecl name_decl;
			name_decl.name = name;
			name_decl.type = NameDecl::STRUCT_DECL;
			name_stack[at_level] = name_decl;
		} else if (tk == TK_IDENTIFIER && String(value) == "namespace") {
			if (type_curly_stack > 0) {
				error_str = "Found namespace nested inside type.";
				error = true;
				return ERR_PARSE_ERROR;
			}

			String name;
			int at_level = curly_stack;

			Error err = _parse_namespace_name(name, curly_stack);
			if (err)
				return err;

			NameDecl name_decl;
			name_decl.name = name;
			name_decl.type = NameDecl::NAMESPACE_DECL;
			name_stack[at_level] = name_decl;
		} else if (tk == TK_CURLY_BRACKET_OPEN) {
			curly_stack++;
		} else if (tk == TK_CURLY_BRACKET_CLOSE) {
			curly_stack--;
			if (name_stack.has(curly_stack)) {
				if (name_stack[curly_stack].type != NameDecl::NAMESPACE_DECL)
					type_curly_stack--;
				name_stack.erase(curly_stack);
			}
		}

		tk = get_token();
	}

	if (!error && tk == TK_EOF && curly_stack > 0) {
		error_str = "Reached EOF with missing close curly brackets.";
		error = true;
	}

	if (error)
		return ERR_PARSE_ERROR;

	return OK;
}
void tokenize_cleanup(void)
{
   chunk_t *pc   = chunk_get_head();
   chunk_t *prev = NULL;
   chunk_t *next;
   chunk_t *tmp;
   chunk_t *tmp2;
   bool    in_type_cast = false;

   pc   = chunk_get_head();
   next = chunk_get_next_ncnl(pc);
   while ((pc != NULL) && (next != NULL))
   {
      /* Change '[' + ']' into '[]' */
      if ((pc->type == CT_SQUARE_OPEN) && (next->type == CT_SQUARE_CLOSE))
      {
         pc->type = CT_TSQUARE;
         pc->str  = "[]";
         pc->len  = 2;
         chunk_del(next);
         pc->orig_col_end += 1;
         next              = chunk_get_next_ncnl(pc);
      }

      if ((pc->type == CT_DOT) && ((cpd.lang_flags & LANG_ALLC) != 0))
      {
         pc->type = CT_MEMBER;
      }

      /* Determine the version stuff (D only) */
      if (pc->type == CT_VERSION)
      {
         if (next->type == CT_PAREN_OPEN)
         {
            pc->type = CT_IF;
         }
         else
         {
            if (next->type != CT_ASSIGN)
            {
               LOG_FMT(LERR, "%s:%d %s: version: Unexpected token %s\n",
                       cpd.filename, pc->orig_line, __func__, get_token_name(next->type));
               cpd.error_count++;
            }
            pc->type = CT_WORD;
         }
      }

      /**
       * Change CT_BASE before CT_PAREN_OPEN to CT_WORD.
       * public myclass() : base() {
       * }
       */
      if ((pc->type == CT_BASE) && (next->type == CT_PAREN_OPEN))
      {
         pc->type = CT_WORD;
      }

      /**
       * Change CT_WORD after CT_ENUM, CT_UNION, or CT_STRUCT to CT_TYPE
       * Change CT_WORD before CT_WORD to CT_TYPE
       */
      if (next->type == CT_WORD)
      {
         if ((pc->type == CT_ENUM) ||
             (pc->type == CT_UNION) ||
             (pc->type == CT_STRUCT))
         {
            next->type = CT_TYPE;
         }
         if (pc->type == CT_WORD)
         {
            pc->type = CT_TYPE;
         }
      }

      /* change extern to qualifier if extern isn't followed by a string or
       * an open paren
       */
      if (pc->type == CT_EXTERN)
      {
         if (next->type == CT_STRING)
         {
            /* Probably 'extern "C"' */
         }
         else if (next->type == CT_PAREN_OPEN)
         {
            /* Probably 'extern (C)' */
         }
         else
         {
            /* Something else followed by a open brace */
            tmp = chunk_get_next_ncnl(next);
            if ((tmp != NULL) || (tmp->type != CT_BRACE_OPEN))
            {
               pc->type = CT_QUALIFIER;
            }
         }
      }

      /**
       * Change CT_STAR to CT_PTR_TYPE if preceded by CT_TYPE,
       * CT_QUALIFIER, or CT_PTR_TYPE.
       */
      if ((next->type == CT_STAR) &&
          ((pc->type == CT_TYPE) ||
           (pc->type == CT_QUALIFIER) ||
           (pc->type == CT_PTR_TYPE)))
      {
         next->type = CT_PTR_TYPE;
      }

      if ((pc->type == CT_TYPE_CAST) &&
          (next->type == CT_ANGLE_OPEN))
      {
         next->parent_type = CT_TYPE_CAST;
         in_type_cast      = true;
      }

      /**
       * Change angle open/close to CT_COMPARE, if not a template thingy
       */
      if ((pc->type == CT_ANGLE_OPEN) && (pc->parent_type != CT_TYPE_CAST))
      {
         check_template(pc);
      }
      if ((pc->type == CT_ANGLE_CLOSE) && (pc->parent_type != CT_TEMPLATE))
      {
         if (in_type_cast)
         {
            in_type_cast    = false;
            pc->parent_type = CT_TYPE_CAST;
         }
         else
         {
            pc->type = CT_COMPARE;
         }
      }

      if ((cpd.lang_flags & LANG_D) != 0)
      {
         /* Check for the D string concat symbol '~' */
         if ((pc->type == CT_INV) &&
             ((prev->type == CT_STRING) ||
              (prev->type == CT_WORD) ||
              (next->type == CT_STRING)))
         {
            pc->type = CT_CONCAT;
         }

         /* Check for the D template symbol '!' */
         if ((pc->type == CT_NOT) &&
             (prev->type == CT_WORD) &&
             (next->type == CT_PAREN_OPEN))
         {
            pc->type = CT_D_TEMPLATE;
         }
      }

      if ((cpd.lang_flags & LANG_CPP) != 0)
      {
         /* Change Word before '::' into a type */
         if ((pc->type == CT_WORD) && (next->type == CT_DC_MEMBER))
         {
            pc->type = CT_TYPE;
         }
      }

      /* Change get/set to CT_WORD if not followed by a brace open */
      if ((pc->type == CT_GETSET) && (next->type != CT_BRACE_OPEN))
      {
         if ((next->type == CT_SEMICOLON) &&
             ((prev->type == CT_BRACE_CLOSE) ||
              (prev->type == CT_BRACE_OPEN) ||
              (prev->type == CT_SEMICOLON)))
         {
            pc->type          = CT_GETSET_EMPTY;
            next->parent_type = CT_GETSET;
         }
         else
         {
            pc->type = CT_WORD;
         }
      }

      /* Change item after operator (>=, ==, etc) to a CT_OPERATOR_VAL
       * Usually the next item is part of the operator.
       * In a few cases the next few tokens are part of it:
       *  operator +       - common case
       *  operator ()
       *  operator []      - already converted to TSQUARE
       *  operator new []
       *  operator delete []
       *  operator const char *
       *  operator std::allocator<U>
       *
       * In all cases except the last, this will put the entire operator value
       * in one chunk.
       */
      if (pc->type == CT_OPERATOR)
      {
         /* Handle special case of () operator -- [] already handled */
         if (next->type == CT_PAREN_OPEN)
         {
            tmp = chunk_get_next(next);
            if ((tmp != NULL) && (tmp->type == CT_PAREN_CLOSE))
            {
               next->str  = "()";
               next->len  = 2;
               next->type = CT_OPERATOR_VAL;
               chunk_del(tmp);
               next->orig_col_end += 1;
            }
         }
         else if (next->flags & PCF_PUNCTUATOR)
         {
            next->type = CT_OPERATOR_VAL;
         }
         else
         {
            next->type = CT_TYPE;

            /* Replace next with a collection of all tokens that are part of
             * the type.
             */
            char opbuf[256];
            int  len;

            len = snprintf(opbuf, sizeof(opbuf), "%.*s",
                           next->len, next->str);

            tmp2 = next;
            while ((tmp = chunk_get_next(tmp2)) != NULL)
            {
               if ((tmp->type != CT_WORD) &&
                   (tmp->type != CT_TYPE) &&
                   (tmp->type != CT_QUALIFIER) &&
                   (tmp->type != CT_STAR) &&
                   (tmp->type != CT_AMP) &&
                   (tmp->type != CT_TSQUARE))
               {
                  break;
               }
               len += snprintf(opbuf + len, sizeof(opbuf) - len, "%s%.*s",
                               space_needed(tmp2, tmp) ? " " : "",
                               tmp->len, tmp->str);
               tmp2 = tmp;
            }

            while ((tmp2 = chunk_get_next(next)) != tmp)
            {
               chunk_del(tmp2);
            }

            next->str    = strdup(opbuf);
            next->len    = len;
            next->flags |= PCF_OWN_STR;
            next->type   = CT_OPERATOR_VAL;

            next->orig_col_end = next->orig_col + next->len;
         }
         next->parent_type = CT_OPERATOR;

         LOG_FMT(LOPERATOR, "%s: %d:%d operator '%.*s'\n",
                 __func__, pc->orig_line, pc->orig_col,
                 next->len, next->str);
      }

      /* Change private, public, protected into either a qualifier or label */
      if (pc->type == CT_PRIVATE)
      {
         /* Handle Qt slots - maybe should just check for a CT_WORD? */
         if (chunk_is_str(next, "slots", 5))
         {
            tmp = chunk_get_next(next);
            if ((tmp != NULL) && (tmp->type == CT_COLON))
            {
               next = tmp;
            }
         }
         if (next->type == CT_COLON)
         {
            next->type = CT_PRIVATE_COLON;
            if ((tmp = chunk_get_next_ncnl(next)) != NULL)
            {
               tmp->flags |= PCF_STMT_START | PCF_EXPR_START;
            }
         }
         else
         {
            pc->type = chunk_is_str(pc, "signals", 7) ? CT_WORD : CT_QUALIFIER;
         }
      }

      /* Look for <newline> 'EXEC' 'SQL' */
      if (chunk_is_str(pc, "EXEC", 4) && chunk_is_str(next, "SQL", 3))
      {
         tmp = chunk_get_prev(pc);
         if (chunk_is_newline(tmp))
         {
            tmp = chunk_get_next(next);
            if (chunk_is_str_case(tmp, "BEGIN", 5))
            {
               pc->type = CT_SQL_BEGIN;
            }
            else if (chunk_is_str_case(tmp, "END", 3))
            {
               pc->type = CT_SQL_END;
            }
            else
            {
               pc->type = CT_SQL_EXEC;
            }

            /* Change words into CT_SQL_WORD until CT_SEMICOLON */
            while (tmp != NULL)
            {
               if (tmp->type == CT_SEMICOLON)
               {
                  break;
               }
               if ((tmp->len > 0) && isalpha(*tmp->str))
               {
                  tmp->type = CT_SQL_WORD;
               }
               tmp = chunk_get_next_ncnl(tmp);
            }
         }
      }

      /* Detect Objective C class name */
      if ((pc->type == CT_OC_IMPL) ||
          (pc->type == CT_OC_INTF) ||
          (pc->type == CT_OC_PROTOCOL))
      {
         if (next->type != CT_PAREN_OPEN)
         {
            next->type = CT_OC_CLASS;
         }
         next->parent_type = pc->type;

         tmp = chunk_get_next_ncnl(next);
         if (tmp != NULL)
         {
            tmp->flags |= PCF_STMT_START | PCF_EXPR_START;
         }

         tmp = chunk_get_next_type(pc, CT_OC_END, pc->level);
         if (tmp != NULL)
         {
            tmp->parent_type = pc->type;
         }
      }

      /* Detect Objective-C categories and class extensions */
      /* @interface ClassName (CategoryName) */
      /* @implementation ClassName (CategoryName) */
      /* @interface ClassName () */
      /* @implementation ClassName () */
      if (((pc->parent_type == CT_OC_IMPL) ||
           (pc->parent_type == CT_OC_INTF) ||
           (pc->type == CT_OC_CLASS)) &&
          (next->type == CT_PAREN_OPEN))
      {
         next->parent_type = pc->parent_type;

         tmp = chunk_get_next(next);
         if ((tmp != NULL) && (tmp->next != NULL))
         {
            if (tmp->type == CT_PAREN_CLOSE)
            {
               //tmp->type        = CT_OC_CLASS_EXT;
               tmp->parent_type = pc->parent_type;
            }
            else
            {
               tmp->type        = CT_OC_CATEGORY;
               tmp->parent_type = pc->parent_type;
            }
         }

         tmp = chunk_get_next_type(pc, CT_PAREN_CLOSE, pc->level);
         if (tmp != NULL)
         {
            tmp->parent_type = pc->parent_type;
         }
      }

      /**
       * Objective C @dynamic and @synthesize
       *  @dynamic xxx, yyy;
       *  @synthesize xxx, yyy;
       * Just find the semicolon and mark it.
       */
      if (pc->type == CT_OC_DYNAMIC)
      {
         tmp = chunk_get_next_type(pc, CT_SEMICOLON, pc->level);
         if (tmp != NULL)
         {
            tmp->parent_type = pc->type;
         }
      }

      /* Detect Objective C @property
       *  @property NSString *stringProperty;
       *  @property(nonatomic, retain) NSMutableDictionary *shareWith;
       */
      if (pc->type == CT_OC_PROPERTY)
      {
         if (next->type != CT_PAREN_OPEN)
         {
            next->flags |= PCF_STMT_START | PCF_EXPR_START;
         }
         else
         {
            next->parent_type = pc->type;

            tmp = chunk_get_next_type(pc, CT_PAREN_CLOSE, pc->level);
            if (tmp != NULL)
            {
               tmp->parent_type = pc->type;
               tmp = chunk_get_next_ncnl(tmp);
               if (tmp != NULL)
               {
                  tmp->flags |= PCF_STMT_START | PCF_EXPR_START;

                  tmp = chunk_get_next_type(tmp, CT_SEMICOLON, pc->level);
                  if (tmp != NULL)
                  {
                     tmp->parent_type = pc->type;
                  }
               }
            }
         }
      }

      /* Detect Objective C @selector
       *  @selector(msgNameWithNoArg)
       *  @selector(msgNameWith1Arg:)
       *  @selector(msgNameWith2Args:arg2Name:)
       */
      if ((pc->type == CT_OC_SEL) && (next->type == CT_PAREN_OPEN))
      {
         next->parent_type = pc->type;

         tmp = chunk_get_next(next);
         if (tmp != NULL)
         {
            tmp->type        = CT_OC_SEL_NAME;
            tmp->parent_type = pc->type;

            while ((tmp = chunk_get_next_ncnl(tmp)) != NULL)
            {
               if (tmp->type == CT_PAREN_CLOSE)
               {
                  tmp->parent_type = CT_OC_SEL;
                  break;
               }
               tmp->type        = CT_OC_SEL_NAME;
               tmp->parent_type = pc->type;
            }
         }
      }

      /* Mark Objective-C blocks (aka lambdas or closures)
       *  The syntax and usage is exactly like C function pointers with two exceptions:
       *  Instead of an asterisk they have a caret as pointer symbol.
       *  In method declarations which take a block as parameter, there can be anonymous blocks, e.g.: (^)
       *  1. block literal: ^{ ... };
       *  2. block declaration: return_t (^name) (int arg1, int arg2, ...) NB: return_t is optional and name can be optional if found as param in a method declaration.
       *  3. block expression: ^ return_t (int arg) { ... }; NB: return_t is optional
       *
       *  See http://developer.apple.com/mac/library/documentation/Cocoa/Conceptual/Blocks for more info...
       */
      if ((cpd.lang_flags & LANG_OC) &&
          (pc->type == CT_ARITH) &&
          (chunk_is_str(pc, "^", 1)) &&
          (prev->type != CT_NUMBER) &&
          (prev->type != CT_NUMBER_FP))
      {
         /* mark objc blocks caret so that we can process it later*/
         pc->type = CT_OC_BLOCK_CARET;

         if (prev->type == CT_PAREN_OPEN)
         {
            /* block declaration */
            pc->parent_type = CT_OC_BLOCK_TYPE;
         }
         else if ((next->type == CT_PAREN_OPEN) ||
                  (next->type == CT_BRACE_OPEN))
         {
            /* block expression without return type */
            /* block literal */
            pc->parent_type = CT_OC_BLOCK_EXPR;
         }
         else
         {
            /* block expression with return type (seldomly used) */
            if (prev->type == CT_ASSIGN)
            {
               /* shortcut to spare the peeking below
                * the XOR operator wouldn't be used directly
                * after an assign all by itself */
               pc->parent_type = CT_OC_BLOCK_EXPR;
            }
            else
            {
               /* this ones tricky because we don't know how many
                * stars the return type has - if there even is one */
               tmp = pc;
               while ((tmp = chunk_get_next(tmp)) != NULL)
               {
                  /* we just peek ahead and see if the line contains
                   * an open brace somewhere.
                   * FIXME: this check needs to be more thorough. */
                  if (tmp->type == CT_BRACE_OPEN)
                  {
                     pc->parent_type = CT_OC_BLOCK_EXPR;
                     break;
                  }
               }
            }
         }
      }

      /* Handle special preprocessor junk */
      if (pc->type == CT_PREPROC)
      {
         pc->parent_type = next->type;
      }

      /* Detect "pragma region" and "pragma endregion" */
      if ((pc->type == CT_PP_PRAGMA) && (next->type == CT_PREPROC_BODY))
      {
         if ((memcmp(next->str, "region", 6) == 0) ||
             (memcmp(next->str, "endregion", 9) == 0))
         {
            pc->type = (*next->str == 'r') ? CT_PP_REGION : CT_PP_ENDREGION;

            prev->parent_type = pc->type;
         }
      }

      /* Check for C# nullable types '?' is in next */
      if ((cpd.lang_flags & LANG_CS) &&
          (next->type == CT_QUESTION) &&
          (next->orig_col == (pc->orig_col + pc->len)))
      {
         tmp = chunk_get_next_ncnl(next);
         if (tmp != NULL)
         {
            bool doit = ((tmp->type == CT_PAREN_CLOSE) ||
                         (tmp->type == CT_ANGLE_CLOSE));

            if (tmp->type == CT_WORD)
            {
               tmp2 = chunk_get_next_ncnl(tmp);
               if ((tmp2 != NULL) &&
                   ((tmp2->type == CT_SEMICOLON) ||
                    (tmp2->type == CT_ASSIGN) ||
                    (tmp2->type == CT_COMMA)))
               {
                  doit = true;
               }
            }

            if (doit)
            {
               pc->len++;
               chunk_del(next);
               next = tmp;
            }
         }
      }

      /* Convert '>' + '>' into '>>' */
      if ((cpd.lang_flags & LANG_CS) &&
          (pc->type == CT_ANGLE_CLOSE) &&
          (next->type == CT_ANGLE_CLOSE) &&
          (pc->parent_type == CT_NONE) &&
          ((pc->orig_col + pc->len) == next->orig_col) &&
          (next->parent_type == CT_NONE))
      {
         pc->len++;
         pc->type = CT_ARITH;
         tmp      = chunk_get_next_ncnl(next);
         chunk_del(next);
         next = tmp;
      }

      /* Change 'default(' into a sizeof-like statement */
      if ((cpd.lang_flags & LANG_CS) &&
          (pc->type == CT_DEFAULT) &&
          (next->type == CT_PAREN_OPEN))
      {
         pc->type = CT_SIZEOF;
      }

      if ((pc->type == CT_UNSAFE) && (next->type != CT_BRACE_OPEN))
      {
         pc->type = CT_QUALIFIER;
      }

      /* TODO: determine other stuff here */

      prev = pc;
      pc   = next;
      next = chunk_get_next_ncnl(pc);
   }
}
Example #8
0
/**
 * Figures out where to split a function def/proto/call
 *
 * For fcn protos and defs. Also fcn calls where level == brace_level:
 *   - find the open fparen
 *     + if it doesn't have a newline right after it
 *       * see if all parameters will fit individually after the paren
 *       * if not, throw a newline after the open paren & return
 *   - scan backwards to the open fparen or comma
 *     + if there isn't a newline after that item, add one & return
 *     + otherwise, add a newline before the start token
 *
 * @param start   the offending token
 * @return        the token that should have a newline
 *                inserted before it
 */
static void split_fcn_params(chunk_t *start)
{
   LOG_FMT(LSPLIT, "  %s: ", __func__);

   chunk_t *next;
   chunk_t *prev;
   chunk_t *fpo;
   chunk_t *pc;

   /* Find the opening fparen */
   fpo = start;
   while (((fpo = chunk_get_prev(fpo)) != NULL) &&
          (fpo->type != CT_FPAREN_OPEN))
   {
      /* do nothing */
   }

   pc = chunk_get_next(fpo);
   if (!chunk_is_newline(pc))
   {
      int min_col   = pc->column;
      int max_width = 0;
      int cur_width = 0;
      int last_col  = -1;

      LOG_FMT(LSPLIT, " mincol=%d, max_width=%d ",
              min_col,
              cpd.settings[UO_code_width].n - min_col);

      while (pc != NULL)
      {
         if (chunk_is_newline(pc))
         {
            last_col = -1;
         }
         else
         {
            if (last_col < 0)
            {
               last_col = pc->column;
            }
            cur_width += (pc->column - last_col) + pc->len();
            last_col   = pc->column + pc->len();

            if ((pc->type == CT_COMMA) ||
                (pc->type == CT_FPAREN_CLOSE))
            {
               cur_width--;
               LOG_FMT(LSPLIT, " width=%d ", cur_width);
               if (cur_width > max_width)
               {
                  max_width = cur_width;
                  if ((max_width + min_col) > cpd.settings[UO_code_width].n)
                  {
                     break;
                  }
               }
               cur_width = 0;
               last_col  = -1;
               if (pc->type == CT_FPAREN_CLOSE)
               {
                  break;
               }
            }
         }
         pc = chunk_get_next(pc);
      }

      // don't split function w/o parameters
      next = chunk_get_next(fpo);
      if (((max_width + min_col) > cpd.settings[UO_code_width].n) &&
          next->type != CT_FPAREN_CLOSE)
      {
         LOG_FMT(LSPLIT, " - A param won't fit, nl after open paren.");
         split_before_chunk(chunk_get_next(fpo));
         return;
      }
   }

   /* back up until the prev is a comma */
   prev = pc;
   while ((prev = chunk_get_prev(prev)) != NULL)
   {
      if (chunk_is_newline(prev) ||
          (prev->type == CT_COMMA))
      {
         break;
      }
      if (prev->type == CT_FPAREN_OPEN)
      {
         /* Don't split "()" */
         pc = chunk_get_next(prev);
         if (pc->type != c_token_t(prev->type + 1))
         {
            break;
         }
      }
   }
   if (prev != NULL)
   {
      LOG_FMT(LSPLIT, " -- ended on [%s] -- ", get_token_name(prev->type));
   }
   if (prev != NULL)
   {
      split_before_chunk(chunk_get_next(prev));
   }
}
Example #9
0
/**
 * Traverse the if chain and see if all can be removed
 */
static void process_if_chain(chunk_t *br_start)
{
   chunk_t *braces[256];
   chunk_t *br_close;
   int     br_cnt = 0;
   chunk_t *pc;
   bool    must_have_braces = false;
   bool    tmp;

   pc = br_start;

   LOG_FMT(LBRCH, "%s: if starts on line %d\n", __func__, br_start->orig_line);

   while (pc != NULL)
   {
      if (pc->type == CT_BRACE_OPEN)
      {
         tmp = can_remove_braces(pc);
         LOG_FMT(LBRCH, "  [%d] line %d - can%s remove %s\n",
                 br_cnt, pc->orig_line, tmp ? "" : "not",
                 get_token_name(pc->type));
         if (!tmp)
         {
            must_have_braces = true;
         }
      }
      else
      {
         tmp = should_add_braces(pc);
         if (tmp)
         {
            must_have_braces = true;
         }
         LOG_FMT(LBRCH, "  [%d] line %d - %s %s\n",
                 br_cnt, pc->orig_line, tmp ? "should add" : "ignore",
                 get_token_name(pc->type));
      }

      braces[br_cnt++] = pc;
      br_close         = chunk_skip_to_match(pc, CNAV_PREPROC);
      if (br_close == NULL)
      {
         break;
      }
      braces[br_cnt++] = br_close;

      pc = chunk_get_next_ncnl(br_close, CNAV_PREPROC);
      if ((pc == NULL) || (pc->type != CT_ELSE))
      {
         break;
      }
      pc = chunk_get_next_ncnl(pc, CNAV_PREPROC);
      if ((pc != NULL) && (pc->type == CT_ELSEIF))
      {
         while ((pc != NULL) && (pc->type != CT_VBRACE_OPEN) && (pc->type != CT_BRACE_OPEN))
         {
            pc = chunk_get_next_ncnl(pc, CNAV_PREPROC);
         }
      }
      if (pc == NULL)
      {
         break;
      }
      if ((pc->type != CT_BRACE_OPEN) && (pc->type != CT_VBRACE_OPEN))
      {
         break;
      }
   }

   if (must_have_braces)
   {
      LOG_FMT(LBRCH, "%s: add braces on lines[%d]:", __func__, br_cnt);
      while (--br_cnt >= 0)
      {
         braces[br_cnt]->flags |= PCF_KEEP_BRACE;
         if ((braces[br_cnt]->type == CT_VBRACE_OPEN) ||
             (braces[br_cnt]->type == CT_VBRACE_CLOSE))
         {
            LOG_FMT(LBRCH, " %d", braces[br_cnt]->orig_line);
            convert_vbrace(braces[br_cnt]);
         }
         else
         {
            LOG_FMT(LBRCH, " {%d}", braces[br_cnt]->orig_line);
         }
         braces[br_cnt] = NULL;
      }
      LOG_FMT(LBRCH, "\n");
   }
   else
   {
      LOG_FMT(LBRCH, "%s: remove braces on lines[%d]:", __func__, br_cnt);
      while (--br_cnt >= 0)
      {
         if ((braces[br_cnt]->type == CT_BRACE_OPEN) ||
             (braces[br_cnt]->type == CT_BRACE_CLOSE))
         {
            LOG_FMT(LBRCH, " {%d}", braces[br_cnt]->orig_line);
            convert_brace(braces[br_cnt]);
         }
         else
         {
            LOG_FMT(LBRCH, " %d", braces[br_cnt]->orig_line);
         }
         braces[br_cnt] = NULL;
      }
      LOG_FMT(LBRCH, "\n");
   }
}
Example #10
0
/**
 * Adds an item to the align stack and adjust the nl_count and max_col.
 * Adjust max_col as needed
 *
 * @param pc         the item to add
 * @param max_col    pointer to the column variable
 * @param extra_pad  extra padding
 */
static void align_add(ChunkStack& cs, chunk_t *pc, int& max_col, int min_pad, bool squeeze)
{
   chunk_t *prev;
   int     min_col;

   prev = chunk_get_prev(pc);
   if ((prev == NULL) || chunk_is_newline(prev))
   {
      min_col = squeeze ? 1 : pc->column;
      LOG_FMT(LALADD, "%s: pc->col=%d max_col=%d min_pad=%d min_col=%d\n",
              __func__, pc->column, max_col, min_pad, min_col);
   }
   else
   {
      if (prev->type == CT_COMMENT_MULTI)
      {
         min_col = prev->orig_col_end + min_pad;
      }
      else
      {
         min_col = prev->column + prev->len + min_pad;
      }
      if (!squeeze)
      {
         if (min_col < pc->column)
         {
            min_col = pc->column;
         }
      }
      LOG_FMT(LALADD, "%s: pc->col=%d max_col=%d min_pad=%d min_col=%d multi:%s prev->col=%d prev->len=%d %s\n",
              __func__, pc->column, max_col, min_pad, min_col, (prev->type == CT_COMMENT_MULTI) ? "Y" : "N",
              (prev->type == CT_COMMENT_MULTI) ? prev->orig_col_end : prev->column, prev->len, get_token_name(prev->type));
   }

   if (cs.Empty())
   {
      max_col = 0;
   }

   cs.Push(pc);
   if (min_col > max_col)
   {
      max_col = min_col;
   }
}
Example #11
0
/**
 * Scan everything at the current level until the close brace and find the
 * variable def align column.  Also aligns bit-colons, but that assumes that
 * bit-types are the same! But that should always be the case...
 */
static chunk_t *align_var_def_brace(chunk_t *start, int span, int *p_nl_count)
{
   chunk_t    *pc;
   chunk_t    *next;
   chunk_t    *prev;
   UINT64     align_mask = PCF_IN_FCN_DEF | PCF_VAR_1ST;
   int        myspan     = span;
   int        mythresh   = 0;
   int        mygap      = 0;
   AlignStack as;    /* var/proto/def */
   AlignStack as_bc; /* bit-colon */
   AlignStack as_at; /* attribute */
   AlignStack as_br; /* one-liner brace open */
   bool       fp_active   = cpd.settings[UO_align_mix_var_proto].b;
   bool       fp_look_bro = false;


   if (start == NULL)
   {
      return(NULL);
   }

   /* Override the span, if this is a struct/union */
   if ((start->parent_type == CT_STRUCT) ||
       (start->parent_type == CT_UNION))
   {
      myspan   = cpd.settings[UO_align_var_struct_span].n;
      mythresh = cpd.settings[UO_align_var_struct_thresh].n;
      mygap    = cpd.settings[UO_align_var_struct_gap].n;
   }
   else
   {
      mythresh = cpd.settings[UO_align_var_def_thresh].n;
      mygap    = cpd.settings[UO_align_var_def_gap].n;
   }

   /* can't be any variable definitions in a "= {" block */
   prev = chunk_get_prev_ncnl(start);
   if ((prev != NULL) && (prev->type == CT_ASSIGN))
   {
      LOG_FMT(LAVDB, "%s: start=%.*s [%s] on line %d (abort due to assign)\n", __func__,
              start->len, start->str, get_token_name(start->type), start->orig_line);

      pc = chunk_get_next_type(start, CT_BRACE_CLOSE, start->level);
      return(chunk_get_next_ncnl(pc));
   }

   LOG_FMT(LAVDB, "%s: start=%.*s [%s] on line %d\n", __func__,
           start->len, start->str, get_token_name(start->type), start->orig_line);

   if (!cpd.settings[UO_align_var_def_inline].b)
   {
      align_mask |= PCF_VAR_INLINE;
   }

   /* Set up the var/proto/def aligner */
   as.Start(myspan, mythresh);
   as.m_gap        = mygap;
   as.m_star_style = (AlignStack::StarStyle)cpd.settings[UO_align_var_def_star_style].n;
   as.m_amp_style  = (AlignStack::StarStyle)cpd.settings[UO_align_var_def_amp_style].n;

   /* Set up the bit colon aligner */
   as_bc.Start(myspan, 0);
   as_bc.m_gap = cpd.settings[UO_align_var_def_colon_gap].n;

   as_at.Start(myspan, 0);

   /* Set up the brace open aligner */
   as_br.Start(myspan, mythresh);
   as_br.m_gap = cpd.settings[UO_align_single_line_brace_gap].n;

   bool did_this_line = false;
   pc = chunk_get_next(start);
   while ((pc != NULL) && ((pc->level >= start->level) || (pc->level == 0)))
   {
      if (chunk_is_comment(pc))
      {
         if (pc->nl_count > 0)
         {
            as.NewLines(pc->nl_count);
            as_bc.NewLines(pc->nl_count);
            as_at.NewLines(pc->nl_count);
            as_br.NewLines(pc->nl_count);
         }
         pc = chunk_get_next(pc);
         continue;
      }

      if (fp_active)
      {
         if ((pc->type == CT_FUNC_PROTO) ||
             ((pc->type == CT_FUNC_DEF) &&
              cpd.settings[UO_align_single_line_func].b))
         {
            LOG_FMT(LAVDB, "    add=[%.*s] line=%d col=%d level=%d\n",
                    pc->len, pc->str, pc->orig_line, pc->orig_col, pc->level);

            as.Add(pc);
            fp_look_bro = (pc->type == CT_FUNC_DEF) &&
                          cpd.settings[UO_align_single_line_brace].b;
         }
         else if (fp_look_bro &&
                  (pc->type == CT_BRACE_OPEN) &&
                  (pc->flags & PCF_ONE_LINER))
         {
            as_br.Add(pc);
            fp_look_bro = false;
         }
      }

      /* process nested braces */
      if (pc->type == CT_BRACE_OPEN)
      {
         int sub_nl_count = 0;

         pc = align_var_def_brace(pc, span, &sub_nl_count);
         if (sub_nl_count > 0)
         {
            fp_look_bro   = false;
            did_this_line = false;
            as.NewLines(sub_nl_count);
            as_bc.NewLines(sub_nl_count);
            as_at.NewLines(sub_nl_count);
            as_br.NewLines(sub_nl_count);
            if (p_nl_count != NULL)
            {
               *p_nl_count += sub_nl_count;
            }
         }
         continue;
      }

      /* Done with this brace set? */
      if (pc->type == CT_BRACE_CLOSE)
      {
         pc = chunk_get_next(pc);
         break;
      }

      if (chunk_is_newline(pc))
      {
         fp_look_bro   = false;
         did_this_line = false;
         as.NewLines(pc->nl_count);
         as_bc.NewLines(pc->nl_count);
         as_at.NewLines(pc->nl_count);
         as_br.NewLines(pc->nl_count);
         if (p_nl_count != NULL)
         {
            *p_nl_count += pc->nl_count;
         }
      }

      /* don't align stuff inside parens/squares/angles */
      if (pc->level > pc->brace_level)
      {
         pc = chunk_get_next(pc);
         continue;
      }

      /* If this is a variable def, update the max_col */
      if ((pc->type != CT_FUNC_CLASS) &&
          ((pc->flags & align_mask) == PCF_VAR_1ST) &&
          ((pc->level == (start->level + 1)) ||
           (pc->level == 0)))
      {
         if (!did_this_line)
         {
            LOG_FMT(LAVDB, "    add=[%.*s] line=%d col=%d level=%d\n",
                    pc->len, pc->str, pc->orig_line, pc->orig_col, pc->level);

            as.Add(pc);

            if (cpd.settings[UO_align_var_def_colon].b)
            {
               next = chunk_get_next_nc(pc);
               if (next->type == CT_BIT_COLON)
               {
                  as_bc.Add(next);
               }
            }
            if (cpd.settings[UO_align_var_def_attribute].b)
            {
               next = pc;
               while ((next = chunk_get_next_nc(next)) != NULL)
               {
                  if (next->type == CT_ATTRIBUTE)
                  {
                     as_at.Add(next);
                     break;
                  }
                  if ((next->type == CT_SEMICOLON) || chunk_is_newline(next))
                  {
                     break;
                  }
               }
            }
         }
         did_this_line = true;
      }
      else if (pc->type == CT_BIT_COLON)
      {
         if (!did_this_line)
         {
            as_bc.Add(pc);
            did_this_line = true;
         }
      }
      pc = chunk_get_next(pc);
   }

   as.End();
   as_bc.End();
   as_at.End();
   as_br.End();

   return(pc);
}
Example #12
0
/**
 * Generically aligns on '=', '{', '(' and item after ','
 * It scans the first line and picks up the location of those tags.
 * It then scans subsequent lines and adjusts the column.
 * Finally it does a second pass to align everything.
 *
 * Aligns all the '=' signs in stucture assignments.
 * a = {
 *    .a    = 1;
 *    .type = fast;
 * };
 *
 * And aligns on '{', numbers, strings, words.
 * colors[] = {
 *    {"red",   {255, 0,   0}}, {"blue",   {  0, 255, 0}},
 *    {"green", {  0, 0, 255}}, {"purple", {255, 255, 0}},
 * };
 *
 * For the C99 indexed array assignment, the leading []= is skipped (no aligning)
 * struct foo_t bars[] =
 * {
 *    [0] = { .name = "bar",
 *            .age  = 21 },
 *    [1] = { .name = "barley",
 *            .age  = 55 },
 * };
 *
 * NOTE: this assumes that spacing is at the minimum correct spacing (ie force)
 *       if it isn't, some extra spaces will be inserted.
 *
 * @param start   Points to the open brace chunk
 */
static void align_init_brace(chunk_t *start)
{
   int     idx;
   chunk_t *pc;
   chunk_t *next;
   chunk_t *prev;
   chunk_t *num_token = NULL;

   cpd.al_cnt       = 0;
   cpd.al_c99_array = false;

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

   pc = chunk_get_next_ncnl(start);
   pc = scan_ib_line(pc, true);
   if ((pc == NULL) || ((pc->type == CT_BRACE_CLOSE) &&
                        (pc->parent_type == CT_ASSIGN)))
   {
      /* single line - nothing to do */
      return;
   }

   do
   {
      pc = scan_ib_line(pc, false);

      /* debug dump the current frame */
      align_log_al(LALBR, pc->orig_line);

      while (chunk_is_newline(pc))
      {
         pc = chunk_get_next(pc);
      }
   } while ((pc != NULL) && (pc->level > start->level));

   /* debug dump the current frame */
   align_log_al(LALBR, start->orig_line);

   if (cpd.settings[UO_align_on_tabstop].b && (cpd.al_cnt >= 1) &&
       (cpd.al[0].type == CT_ASSIGN))
   {
      int rem = (cpd.al[0].col - 1) % cpd.settings[UO_output_tab_size].n;
      if (rem != 0)
      {
         LOG_FMT(LALBR, "%s: col=%d rem=%d", __func__, cpd.al[0].col, rem);
         cpd.al[0].col += cpd.settings[UO_output_tab_size].n - rem;
      }
   }

   pc  = chunk_get_next(start);
   idx = 0;
   do
   {
      if ((idx == 0) && (pc->type == CT_SQUARE_OPEN))
      {
         pc = chunk_get_next_type(pc, CT_ASSIGN, pc->level);
         pc = chunk_get_next(pc);
         if (pc != NULL)
         {
            LOG_FMT(LALBR, " -%d- skipped '[] =' to %s\n",
                    pc->orig_line, get_token_name(pc->type));
         }
         continue;
      }

      next = pc;
      if (idx < cpd.al_cnt)
      {
         LOG_FMT(LALBR, " (%d) check %s vs %s -- ",
                 idx, get_token_name(pc->type), get_token_name(cpd.al[idx].type));
         if (pc->type == cpd.al[idx].type)
         {
            if ((idx == 0) && cpd.al_c99_array)
            {
               prev = chunk_get_prev(pc);
               if (chunk_is_newline(prev))
               {
                  pc->flags |= PCF_DONT_INDENT;
               }
            }
            LOG_FMT(LALBR, " [%.*s] to col %d\n", pc->len, pc->str, cpd.al[idx].col);

            if (num_token != NULL)
            {
               int col_diff = pc->column - num_token->column;

               reindent_line(num_token, cpd.al[idx].col - col_diff);
               //LOG_FMT(LSYS, "-= %d =- NUM indent [%.*s] col=%d diff=%d\n",
               //        num_token->orig_line,
               //        num_token->len, num_token->str, cpd.al[idx - 1].col, col_diff);

               num_token->flags |= PCF_WAS_ALIGNED;
               num_token         = NULL;
            }

            /* Comma's need to 'fall back' to the previous token */
            if (pc->type == CT_COMMA)
            {
               next = chunk_get_next(pc);
               if ((next != NULL) && !chunk_is_newline(next))
               {
                  //LOG_FMT(LSYS, "-= %d =- indent [%.*s] col=%d len=%d\n",
                  //        next->orig_line,
                  //        next->len, next->str, cpd.al[idx].col, cpd.al[idx].len);

                  if ((idx < (cpd.al_cnt - 1)) &&
                      cpd.settings[UO_align_number_left].b &&
                      ((next->type == CT_NUMBER_FP) ||
                       (next->type == CT_NUMBER) ||
                       (next->type == CT_POS) ||
                       (next->type == CT_NEG)))
                  {
                     /* Need to wait until the next match to indent numbers */
                     num_token = next;
                  }
                  else
                  {
                     reindent_line(next, cpd.al[idx].col + cpd.al[idx].len);
                     next->flags |= PCF_WAS_ALIGNED;
                  }
               }
            }
            else
            {
               /* first item on the line */
               reindent_line(pc, cpd.al[idx].col);
               pc->flags |= PCF_WAS_ALIGNED;

               /* see if we need to right-align a number */
               if ((idx < (cpd.al_cnt - 1)) &&
                   cpd.settings[UO_align_number_left].b)
               {
                  next = chunk_get_next(pc);
                  if ((next != NULL) && !chunk_is_newline(next) &&
                      ((next->type == CT_NUMBER_FP) ||
                       (next->type == CT_NUMBER) ||
                       (next->type == CT_POS) ||
                       (next->type == CT_NEG)))
                  {
                     /* Need to wait until the next match to indent numbers */
                     num_token = next;
                  }
               }
            }
            idx++;
         }
         else
         {
            LOG_FMT(LALBR, " no match\n");
         }
      }
      if (chunk_is_newline(pc) || chunk_is_newline(next))
      {
         idx = 0;
      }
      pc = chunk_get_next(pc);
   } while ((pc != NULL) && (pc->level > start->level));
}
Example #13
0
/**
 * Scans a line for stuff to align on.
 *
 * We trigger on BRACE_OPEN, FPAREN_OPEN, ASSIGN, and COMMA.
 * We want to align the NEXT item.
 */
static chunk_t *scan_ib_line(chunk_t *start, bool first_pass)
{
   chunk_t *pc;
   chunk_t *next;
   chunk_t *prev_match = NULL;
   int     token_width;
   int     idx = 0;
   bool    last_was_comment = false;

   /* Skip past C99 "[xx] =" stuff */
   if (start->type == CT_SQUARE_OPEN)
   {
      start->parent_type = CT_TSQUARE;
      start            = chunk_get_next_type(start, CT_ASSIGN, start->level);
      start            = chunk_get_next_ncnl(start);
      cpd.al_c99_array = true;
   }
   pc = start;

   if (pc != NULL)
   {
      LOG_FMT(LSIB, "%s: start=%s col %d/%d line %d\n", __func__,
              get_token_name(pc->type), pc->column, pc->orig_col, pc->orig_line);
   }

   while ((pc != NULL) && !chunk_is_newline(pc) &&
          (pc->level >= start->level))
   {
      //LOG_FMT(LSIB, "%s:     '%.*s'   col %d/%d line %d\n", __func__,
      //        pc->len, pc->str, pc->column, pc->orig_col, pc->orig_line);

      next = chunk_get_next(pc);
      if ((next == NULL) || chunk_is_comment(next))
      {
         /* do nothing */
      }
      else if ((pc->type == CT_ASSIGN) ||
               (pc->type == CT_BRACE_OPEN) ||
               (pc->type == CT_BRACE_CLOSE) ||
               (pc->type == CT_COMMA))
      {
         token_width = space_col_align(pc, next);

         /*TODO: need to handle missing structure defs? ie NULL vs { ... } ?? */

         /* Is this a new entry? */
         if (idx >= cpd.al_cnt)
         {
            LOG_FMT(LSIB, " - New   [%d] %.2d/%d - %10.10s\n", idx,
                    pc->column, token_width, get_token_name(pc->type));

            cpd.al[cpd.al_cnt].type = pc->type;
            cpd.al[cpd.al_cnt].col  = pc->column;
            cpd.al[cpd.al_cnt].len  = token_width;
            cpd.al_cnt++;
            idx++;
            last_was_comment = false;
         }
         else
         {
            /* expect to match stuff */
            if (cpd.al[idx].type == pc->type)
            {
               LOG_FMT(LSIB, " - Match [%d] %.2d/%d - %10.10s", idx,
                       pc->column, token_width, get_token_name(pc->type));

               /* Shift out based on column */
               if (prev_match == NULL)
               {
                  if (pc->column > cpd.al[idx].col)
                  {
                     LOG_FMT(LSIB, " [ pc->col(%d) > col(%d) ] ",
                             pc->column, cpd.al[idx].col);

                     ib_shift_out(idx, pc->column - cpd.al[idx].col);
                     cpd.al[idx].col = pc->column;
                  }
               }
               else if (idx > 0)
               {
                  int min_col_diff = pc->column - prev_match->column;
                  int cur_col_diff = cpd.al[idx].col - cpd.al[idx - 1].col;
                  if (cur_col_diff < min_col_diff)
                  {
                     LOG_FMT(LSIB, " [ min_col_diff(%d) > cur_col_diff(%d) ] ",
                             min_col_diff, cur_col_diff);
                     ib_shift_out(idx, min_col_diff - cur_col_diff);
                  }
               }
               LOG_FMT(LSIB, " - now col %d, len %d\n", cpd.al[idx].col, cpd.al[idx].len);
               idx++;
            }
         }
         prev_match = pc;
      }
      last_was_comment = chunk_is_comment(pc);
      pc = chunk_get_next_nc(pc);
   }

   //if (last_was_comment && (cpd.al[cpd.al_cnt - 1].type == CT_COMMA))
   //{
   //   cpd.al_cnt--;
   //}
   return(pc);
}
Example #14
0
/**
 * For a series of lines ending in a comment, align them.
 * The series ends when more than align_right_cmt_span newlines are found.
 *
 * Interesting info:
 *  - least pysically allowed column
 *  - intended column
 *  - least original cmt column
 *
 * min_col is the minimum allowed column (based on prev token col/size)
 * cmt_col less than
 *
 * @param start   Start point
 * @return        pointer the last item looked at
 */
chunk_t *align_trailing_comments(chunk_t *start)
{
   int          min_col  = 0;
   int          min_orig = -1;
   chunk_t      *pc      = start;
   int          nl_count = 0;
   ChunkStack   cs;
   CmtAlignType cmt_type_start, cmt_type_cur;
   int          col;
   int          intended_col = cpd.settings[UO_align_right_cmt_at_col].n;

   cmt_type_start = get_comment_align_type(pc);

   LOG_FMT(LALADD, "%s: start on line=%d\n", __func__, pc->orig_line);

   /* Find the max column */
   while ((pc != NULL) && (nl_count < cpd.settings[UO_align_right_cmt_span].n))
   {
      if (((pc->flags & PCF_RIGHT_COMMENT) != 0) && (pc->column > 1))
      {
         cmt_type_cur = get_comment_align_type(pc);

         if (cmt_type_cur == cmt_type_start)
         {
            col = 1 + (pc->brace_level * cpd.settings[UO_indent_columns].n);
            LOG_FMT(LALADD, "%s: line=%d col=%d max_col=%d pc->col=%d pc->len=%d %s\n",
                    __func__, pc->orig_line, col, min_col, pc->column, pc->len,
                    get_token_name(pc->type));
            if ((min_orig < 0) || (min_orig > pc->column))
            {
               min_orig = pc->column;
            }
            if (pc->column < col)
            {
               pc->column = col;
            }
            align_add(cs, pc, min_col, 1, true);//(intended_col < col));
            nl_count = 0;
         }
      }
      if (chunk_is_newline(pc))
      {
         nl_count += pc->nl_count;
      }
      pc = chunk_get_next(pc);
   }

   /* Start with the minimum original column */
   col = min_orig;
   /* fall back to the intended column */
   if ((intended_col > 0) && (col > intended_col))
   {
      col = intended_col;
   }
   /* if less than allowed, bump it out */
   if (col < min_col)
   {
      col = min_col;
   }
   /* bump out to the intended column */
   if (col < intended_col)
   {
      col = intended_col;
   }
   LOG_FMT(LALADD, "%s:  -- min_orig=%d intend=%d min_allowed=%d ==> col=%d\n", __func__,
           min_orig, intended_col, min_col, col);
   align_stack(cs, col, (intended_col != 0), LALTC);

   return(chunk_get_next(pc));
}
Example #15
0
static void examine_brace(chunk_t *bopen)
{
   LOG_FUNC_ENTRY();
   chunk_t *next;
   chunk_t *prev      = NULL;
   size_t  semi_count = 0;
   size_t  level      = bopen->level + 1;
   bool    hit_semi   = false;
   bool    was_fcn    = false;
   size_t  nl_max     = cpd.settings[UO_mod_full_brace_nl].u;
   size_t  nl_count   = 0;
   size_t  if_count   = 0;
   int     br_count   = 0;

   LOG_FMT(LBRDEL, "%s: start on %zu : ", __func__, bopen->orig_line);

   chunk_t *pc = chunk_get_next_nc(bopen);
   while ((pc != NULL) && (pc->level >= level))
   {
      if (pc->flags & PCF_IN_PREPROC)
      {
         LOG_FMT(LBRDEL, " PREPROC\n");
         return;
      }

      if (chunk_is_newline(pc))
      {
         nl_count += pc->nl_count;
         if ((nl_max > 0) && (nl_count > nl_max))
         {
            LOG_FMT(LBRDEL, " exceeded %zu newlines\n", nl_max);
            return;
         }
      }
      else
      {
         if (pc->type == CT_BRACE_OPEN)
         {
            br_count++;
         }
         else if (pc->type == CT_BRACE_CLOSE)
         {
            br_count--;
            if (br_count == 0)
            {
               next = chunk_get_next_ncnl(pc, CNAV_PREPROC);
               if ((next == NULL) || (next->type != CT_BRACE_CLOSE))
               {
                  LOG_FMT(LBRDEL, " junk after close brace\n");
                  return;
               }
            }
         }
         else if ((pc->type == CT_IF) || (pc->type == CT_ELSEIF))
         {
            if (br_count == 0)
            {
               if_count++;
            }
         }

         if (pc->level == level)
         {
            if ((semi_count > 0) && hit_semi)
            {
               /* should have bailed due to close brace level drop */
               LOG_FMT(LBRDEL, " no close brace\n");
               return;
            }

            LOG_FMT(LBRDEL, " [%s %zu-%zu]", pc->text(), pc->orig_line, semi_count);

            if (pc->type == CT_ELSE)
            {
               LOG_FMT(LBRDEL, " bailed on %s on line %zu\n",
                       pc->text(), pc->orig_line);
               return;
            }

            was_fcn = (prev != NULL) && (prev->type == CT_FPAREN_CLOSE);

            if (chunk_is_semicolon(pc) ||
                (pc->type == CT_IF) ||
                (pc->type == CT_ELSEIF) ||
                (pc->type == CT_FOR) ||
                (pc->type == CT_DO) ||
                (pc->type == CT_WHILE) ||
                (pc->type == CT_SWITCH) ||
                (pc->type == CT_USING_STMT) ||
                ((pc->type == CT_BRACE_OPEN) && was_fcn))
            {
               hit_semi |= chunk_is_semicolon(pc);
               if (++semi_count > 1)
               {
                  LOG_FMT(LBRDEL, " bailed on %zu because of %s on line %zu\n",
                          bopen->orig_line, pc->text(), pc->orig_line);
                  return;
               }
            }
         }
      }
      prev = pc;
      pc   = chunk_get_next_nc(pc);
   }

   if (pc == NULL)
   {
      LOG_FMT(LBRDEL, " NULL\n");
      return;
   }

   LOG_FMT(LBRDEL, " - end on '%s' on line %zu. if_count=%zu semi_count=%zu\n",
           get_token_name(pc->type), pc->orig_line, if_count, semi_count);

   if (pc->type == CT_BRACE_CLOSE)
   {
      next = chunk_get_next_ncnl(pc);
      while ((next != NULL) && (next->type == CT_VBRACE_CLOSE))
      {
         next = chunk_get_next_ncnl(next);
      }
      LOG_FMT(LBRDEL, " next is '%s'\n", get_token_name(next->type));
      if ((if_count > 0) &&
          ((next->type == CT_ELSE) || (next->type == CT_ELSEIF)))
      {
         LOG_FMT(LBRDEL, " bailed on because 'else' is next and %zu ifs\n", if_count);
         return;
      }

      if (semi_count > 0)
      {
         if (bopen->parent_type == CT_ELSE)
         {
            next = chunk_get_next_ncnl(bopen);
            if (next->type == CT_IF)
            {
               prev = chunk_get_prev_ncnl(bopen);
               LOG_FMT(LBRDEL, " else-if removing braces on line %zu and %zu\n",
                       bopen->orig_line, pc->orig_line);

               chunk_del(bopen);
               chunk_del(pc);
               newline_del_between(prev, next);
               if (cpd.settings[UO_nl_else_if].a & AV_ADD)
               {
                  newline_add_between(prev, next);
               }
               return;
            }
         }

         /* we have a pair of braces with only 1 statement inside */
         convert_brace(bopen);
         convert_brace(pc);

         LOG_FMT(LBRDEL, " removing braces on line %zu and %zu\n",
                 bopen->orig_line, pc->orig_line);
      }
      else
      {
         LOG_FMT(LBRDEL, " empty statement\n");
      }
   }
   else
   {
      LOG_FMT(LBRDEL, " not a close brace? - '%s'\n", pc->text());
   }
} // examine_brace
Example #16
0
File: scanner.c Project: tloch/vpcc
void print_token(int token) {
	printf("Token: %s (%d)\n", get_token_name(token), token);
	if(token == IDENTIFIER)	printf("\t'%ls'\n", identifier);
	if(token == INTEGER) 		printf("\t%d\n", integer);
}
Error ScriptClassParser::_parse_type_constraints() {
	Token tk = get_token();
	if (tk != TK_IDENTIFIER) {
		error_str = "Unexpected token: " + get_token_name(tk);
		error = true;
		return ERR_PARSE_ERROR;
	}

	tk = get_token();
	if (tk != TK_COLON) {
		error_str = "Unexpected token: " + get_token_name(tk);
		error = true;
		return ERR_PARSE_ERROR;
	}

	while (true) {
		tk = get_token();
		if (tk == TK_IDENTIFIER) {
			if (String(value) == "where") {
				return _parse_type_constraints();
			}

			tk = get_token();
			if (tk == TK_PERIOD) {
				while (true) {
					tk = get_token();

					if (tk != TK_IDENTIFIER) {
						error_str = "Expected " + get_token_name(TK_IDENTIFIER) + ", found: " + get_token_name(tk);
						error = true;
						return ERR_PARSE_ERROR;
					}

					tk = get_token();

					if (tk != TK_PERIOD)
						break;
				}
			}
		}

		if (tk == TK_COMMA) {
			continue;
		} else if (tk == TK_IDENTIFIER && String(value) == "where") {
			return _parse_type_constraints();
		} else if (tk == TK_SYMBOL && String(value) == "(") {
			tk = get_token();
			if (tk != TK_SYMBOL || String(value) != ")") {
				error_str = "Unexpected token: " + get_token_name(tk);
				error = true;
				return ERR_PARSE_ERROR;
			}
		} else if (tk == TK_OP_LESS) {
			Error err = _skip_generic_type_params();
			if (err)
				return err;
		} else if (tk == TK_CURLY_BRACKET_OPEN) {
			return OK;
		} else {
			error_str = "Unexpected token: " + get_token_name(tk);
			error = true;
			return ERR_PARSE_ERROR;
		}
	}
}
Example #18
0
/**
 * Scan backwards to find the most appropriate spot to split the line
 * and insert a newline.
 *
 * See if this needs special function handling.
 * Scan backwards and find the best token for the split.
 *
 * @param start The first chunk that exceeded the limit
 */
static void split_line(chunk_t *start)
{
   LOG_FMT(LSPLIT, "%s: line %d, col %d token:%s[%s] (IN_FUNC=%d) ",
           __func__, start->orig_line, start->column, start->str.c_str(),
           get_token_name(start->type),
           (start->flags & (PCF_IN_FCN_DEF | PCF_IN_FCN_CALL)) != 0);

   /**
    * break at maximum line length if ls_code_width is true
    */
   if (cpd.settings[UO_ls_code_width].b)
   {
   }
   /* Check to see if we are in a for statement */
   else if ((start->flags & PCF_IN_FOR) != 0)
   {
      LOG_FMT(LSPLIT, " ** FOR SPLIT **\n");
      split_for_stmt(start);
      if (!is_past_width(start))
      {
         return;
      }
      LOG_FMT(LSPLIT, "%s: for split didn't work\n", __func__);
   }

   /* If this is in a function call or prototype, split on commas or right
    * after the open paren
    */
   else if (((start->flags & PCF_IN_FCN_DEF) != 0) ||
            ((start->level == (start->brace_level + 1)) &&
             ((start->flags & PCF_IN_FCN_CALL) != 0)))
   {
      LOG_FMT(LSPLIT, " ** FUNC SPLIT **\n");

      if (cpd.settings[UO_ls_func_split_full].b)
      {
         split_fcn_params_full(start);
         if (!is_past_width(start))
         {
            return;
         }
      }
      split_fcn_params(start);
      return;
   }

   /**
    * Try to find the best spot to split the line
    */
   cw_entry ent;

   memset(&ent, 0, sizeof(ent));
   chunk_t *pc = start;
   chunk_t *prev;

   while (((pc = chunk_get_prev(pc)) != NULL) && !chunk_is_newline(pc))
   {
      if (pc->type != CT_SPACE)
      {
         try_split_here(ent, pc);
         /*  break at maximum line length */
         if ((ent.pc != NULL) && (cpd.settings[UO_ls_code_width].b))
             break;
      }
   }

   if (ent.pc == NULL)
   {
      LOG_FMT(LSPLIT, "%s: TRY_SPLIT yielded NO SOLUTION for line %d at %s [%s]\n",
              __func__, start->orig_line, start->str.c_str(), get_token_name(start->type));
   }
   else
   {
      LOG_FMT(LSPLIT, "%s: TRY_SPLIT yielded '%s' [%s] on line %d\n", __func__,
              ent.pc->str.c_str(), get_token_name(ent.pc->type), ent.pc->orig_line);
   }

   /* Break before the token instead of after it according to the pos_xxx rules */
   if (((chunk_is_token(ent.pc, CT_ARITH) || chunk_is_token(ent.pc, CT_CARET)) &&
        (cpd.settings[UO_pos_arith].tp & TP_LEAD)) ||
       (chunk_is_token(ent.pc, CT_ASSIGN) &&
        (cpd.settings[UO_pos_assign].tp & TP_LEAD)) ||
       (chunk_is_token(ent.pc, CT_COMPARE) &&
        (cpd.settings[UO_pos_compare].tp & TP_LEAD)) ||
       ((chunk_is_token(ent.pc, CT_COND_COLON) ||
         chunk_is_token(ent.pc, CT_QUESTION)) &&
        (cpd.settings[UO_pos_conditional].tp & TP_LEAD)) ||
       (chunk_is_token(ent.pc, CT_BOOL) &&
        (cpd.settings[UO_pos_bool].tp & TP_LEAD)))
   {
      pc = ent.pc;
   }
   else
   {
      pc = chunk_get_next(ent.pc);
   }
   if (pc == NULL)
   {
      pc = start;
      /* Don't break before a close, comma, or colon */
      if ((start->type == CT_PAREN_CLOSE) ||
          (start->type == CT_PAREN_OPEN) ||
          (start->type == CT_FPAREN_CLOSE) ||
          (start->type == CT_FPAREN_OPEN) ||
          (start->type == CT_SPAREN_CLOSE) ||
          (start->type == CT_SPAREN_OPEN) ||
          (start->type == CT_ANGLE_CLOSE) ||
          (start->type == CT_BRACE_CLOSE) ||
          (start->type == CT_COMMA) ||
          (start->type == CT_SEMICOLON) ||
          (start->type == CT_VSEMICOLON) ||
          (start->len() == 0))
      {
         LOG_FMT(LSPLIT, " ** NO GO **\n");

         /*TODO: Add in logic to handle 'hard' limits by backing up a token */
         return;
      }
   }

   /* add a newline before pc */
   prev = chunk_get_prev(pc);
   if ((prev != NULL) && !chunk_is_newline(pc) && !chunk_is_newline(prev))
   {
      int plen = (pc->len() < 5) ? pc->len() : 5;
      int slen = (start->len() < 5) ? start->len() : 5;
      LOG_FMT(LSPLIT, " '%.*s' [%s], started on token '%.*s' [%s]\n",
              plen, pc->str.c_str(), get_token_name(pc->type),
              slen, start->str.c_str(), get_token_name(start->type));

      split_before_chunk(pc);
   }
}
Example #19
0
/**
 * Scans between two parens and adds additional parens if needed.
 * This function is recursive. If it hits another open paren, it'll call itself
 * with the new bounds.
 *
 * Adds optional parens in an IF or SWITCH conditional statement.
 *
 * This basically just checks for a CT_COMPARE that isn't surrounded by parens.
 * The edges for the compare are the open, close and any CT_BOOL tokens.
 *
 * This only handleds VERY simple patterns:
 *   (!a && b)         => (!a && b)          -- no change
 *   (a && b == 1)     => (a && (b == 1))
 *   (a == 1 || b > 2) => ((a == 1) || (b > 2))
 *
 * FIXME: we really should bail if we transition between a preprocessor and
 *        a non-preprocessor
 */
static void check_bool_parens(chunk_t *popen, chunk_t *pclose, int nest)
{
    LOG_FUNC_ENTRY();
    chunk_t *pc;
    chunk_t *ref = popen;
    chunk_t *next;
    bool    hit_compare = false;

    LOG_FMT(LPARADD, "%s(%d): popen on %d, col %d, pclose on %d, col %d, level=%d\n",
            __func__, nest,
            popen->orig_line, popen->orig_col,
            pclose->orig_line, pclose->orig_col,
            popen->level);

    pc = popen;
    while (((pc = chunk_get_next_ncnl(pc)) != NULL) && (pc != pclose))
    {
        if (pc->flags & PCF_IN_PREPROC)
        {
            LOG_FMT(LPARADD2, " -- bail on PP %s [%s] at line %d col %d, level %d\n",
                    get_token_name(pc->type),
                    pc->str.c_str(), pc->orig_line, pc->orig_col, pc->level);
            return;
        }

        if ((pc->type == CT_BOOL) ||
                (pc->type == CT_QUESTION) ||
                (pc->type == CT_COND_COLON) ||
                (pc->type == CT_COMMA))
        {
            LOG_FMT(LPARADD2, " -- %s [%s] at line %d col %d, level %d\n",
                    get_token_name(pc->type),
                    pc->str.c_str(), pc->orig_line, pc->orig_col, pc->level);
            if (hit_compare)
            {
                hit_compare = false;
                add_parens_between(ref, pc);
            }
            ref = pc;
        }
        else if (pc->type == CT_COMPARE)
        {
            LOG_FMT(LPARADD2, " -- compare [%s] at line %d col %d, level %d\n",
                    pc->str.c_str(), pc->orig_line, pc->orig_col, pc->level);
            hit_compare = true;
        }
        else if (chunk_is_paren_open(pc))
        {
            next = chunk_skip_to_match(pc);
            if (next != NULL)
            {
                check_bool_parens(pc, next, nest + 1);
                pc = next;
            }
        }
        else if ((pc->type == CT_BRACE_OPEN) ||
                 (pc->type == CT_SQUARE_OPEN) ||
                 (pc->type == CT_ANGLE_OPEN))
        {
            /* Skip [], {}, and <> */
            pc = chunk_skip_to_match(pc);
        }
    }

    if (hit_compare && (ref != popen))
    {
        add_parens_between(ref, pclose);
    }
}
Example #20
0
/**
 * Figures out where to split a function def/proto/call
 *
 * For fcn protos and defs. Also fcn calls where level == brace_level:
 *   - find the open fparen
 *     + if it doesn't have a newline right after it
 *       * see if all parameters will fit individually after the paren
 *       * if not, throw a newline after the open paren & return
 *   - scan backwards to the open fparen or comma
 *     + if there isn't a newline after that item, add one & return
 *     + otherwise, add a newline before the start token
 *
 * @param start   the offending token
 * @return        the token that should have a newline
 *                inserted before it
 */
static void split_fcn_params(chunk_t *start)
{
   LOG_FMT(LSPLIT, "  %s: ", __func__);

   chunk_t *prev;
   chunk_t *fpo;
   chunk_t *pc;
   int     cur_width = 0;
   int     last_col  = -1;
   int     min_col;

   /* Find the opening fparen */
   fpo = start;
   while (((fpo = chunk_get_prev(fpo)) != NULL) &&
          (fpo->type != CT_FPAREN_OPEN))
   {
      /* do nothing */
   }

   pc = chunk_get_next_ncnl(fpo);
   min_col = pc->column;

   LOG_FMT(LSPLIT, " mincol=%d, max_width=%d ",
           min_col, cpd.settings[UO_code_width].n - min_col);

   while (pc != NULL)
   {
      if (chunk_is_newline(pc))
      {
         cur_width = 0;
         last_col = -1;
      }
      else
      {
         if (last_col < 0)
         {
            last_col = pc->column;
         }
         cur_width += (pc->column - last_col) + pc->len();
         last_col   = pc->column + pc->len();

         if ((pc->type == CT_COMMA) ||
             (pc->type == CT_FPAREN_CLOSE))
         {
            cur_width--;
            LOG_FMT(LSPLIT, " width=%d ", cur_width);
            if (((last_col - 1) > cpd.settings[UO_code_width].n) ||
                (pc->type == CT_FPAREN_CLOSE))
            {
               break;
            }
         }
      }
      pc = chunk_get_next(pc);
   }

   /* back up until the prev is a comma */
   prev = pc;
   while ((prev = chunk_get_prev(prev)) != NULL)
   {
      if (chunk_is_newline(prev) || (prev->type == CT_COMMA))
      {
         break;
      }
      last_col -= pc->len();
      if (prev->type == CT_FPAREN_OPEN)
      {
         pc = chunk_get_next(prev);
         if (!cpd.settings[UO_indent_paren_nl].b)
         {
            min_col = pc->brace_level * cpd.settings[UO_indent_columns].n + 1;
            if (cpd.settings[UO_indent_continue].n == 0)
            {
                min_col += cpd.settings[UO_indent_columns].n;
            }
            else
            {
                min_col += abs(cpd.settings[UO_indent_continue].n);
            }
         }
         /* Don't split "()" */
         if (pc->type != c_token_t(prev->type + 1))
         {
            break;
         }
      }
   }
   if ((prev != NULL) && !chunk_is_newline(prev))
   {
      LOG_FMT(LSPLIT, " -- ended on [%s] -- ", get_token_name(prev->type));
      pc = chunk_get_next(prev);
      newline_add_before(pc);
      reindent_line(pc, min_col);
      cpd.changes++;
   }
}
Example #21
0
/**
 * This function parses or tokenizes the whole buffer into a list.
 * It has to do some tricks to parse preprocessors.
 *
 * If output_text() were called immediately after, two things would happen:
 *  - trailing whitespace are removed.
 *  - leading space & tabs are converted to the appropriate format.
 *
 * All the tokens are inserted before ref. If ref is NULL, they are inserted
 * at the end of the list.  Line numbers are relative to the start of the data.
 */
void tokenize(const deque<int> &data, chunk_t *ref)
{
   tok_ctx            ctx(data);
   chunk_t            chunk;
   chunk_t            *pc    = NULL;
   chunk_t            *rprev = NULL;
   struct parse_frame frm;
   bool               last_was_tab = false;
   int                prev_sp      = 0;

   cpd.unc_stage = US_TOKENIZE;

   memset(&frm, 0, sizeof(frm));

   while (ctx.more())
   {
      chunk.reset();
      if (!parse_next(ctx, chunk))
      {
         LOG_FMT(LERR, "%s:%d Bailed before the end?\n",
                 cpd.filename, ctx.c.row);
         cpd.error_count++;
         break;
      }

      /* Don't create an entry for whitespace */
      if (chunk.type == CT_WHITESPACE)
      {
         last_was_tab = chunk.after_tab;
         prev_sp      = chunk.orig_prev_sp;
         continue;
      }
      chunk.orig_prev_sp = prev_sp;
      prev_sp            = 0;

      if (chunk.type == CT_NEWLINE)
      {
         last_was_tab    = chunk.after_tab;
         chunk.after_tab = false;
         chunk.str.clear();
      }
      else if (chunk.type == CT_NL_CONT)
      {
         last_was_tab    = chunk.after_tab;
         chunk.after_tab = false;
         chunk.str       = "\\\n";
      }
      else
      {
         chunk.after_tab = last_was_tab;
         last_was_tab    = false;
      }

      /* Strip trailing whitespace (for CPP comments and PP blocks) */
      while ((chunk.str.size() > 0) &&
             ((chunk.str[chunk.str.size() - 1] == ' ') ||
              (chunk.str[chunk.str.size() - 1] == '\t')))
      {
         // If comment contains backslash '\' followed by whitespace chars, keep last one;
         // this will prevent it from turning '\' into line continuation.
         if ((chunk.str.size() > 1) && (chunk.str[chunk.str.size() - 2] == '\\'))
         {
            break;
         }
         chunk.str.pop_back();
      }

      /* Store off the end column */
      chunk.orig_col_end = ctx.c.col;

      /* Add the chunk to the list */
      rprev = pc;
      if (rprev != NULL)
      {
         chunk_flags_set(pc, rprev->flags & PCF_COPY_FLAGS);

         /* a newline can't be in a preprocessor */
         if (pc->type == CT_NEWLINE)
         {
            chunk_flags_clr(pc, PCF_IN_PREPROC);
         }
      }
      if (ref != NULL)
      {
         chunk.flags |= PCF_INSERTED;
      }
      else
      {
         chunk.flags &= ~PCF_INSERTED;
      }
      pc = chunk_add_before(&chunk, ref);

      /* A newline marks the end of a preprocessor */
      if (pc->type == CT_NEWLINE) // || (pc->type == CT_COMMENT_MULTI))
      {
         cpd.in_preproc         = CT_NONE;
         cpd.preproc_ncnl_count = 0;
      }

      /* Special handling for preprocessor stuff */
      if (cpd.in_preproc != CT_NONE)
      {
         chunk_flags_set(pc, PCF_IN_PREPROC);

         /* Count words after the preprocessor */
         if (!chunk_is_comment(pc) && !chunk_is_newline(pc))
         {
            cpd.preproc_ncnl_count++;
         }

         /* Figure out the type of preprocessor for #include parsing */
         if (cpd.in_preproc == CT_PREPROC)
         {
            if ((pc->type < CT_PP_DEFINE) || (pc->type > CT_PP_OTHER))
            {
               set_chunk_type(pc, CT_PP_OTHER);
            }
            cpd.in_preproc = pc->type;
         }
      }
      else
      {
         /* Check for a preprocessor start */
         if ((pc->type == CT_POUND) &&
             ((rprev == NULL) || (rprev->type == CT_NEWLINE)))
         {
            set_chunk_type(pc, CT_PREPROC);
            pc->flags     |= PCF_IN_PREPROC;
            cpd.in_preproc = CT_PREPROC;
         }
      }
      if (pc->type == CT_NEWLINE)
      {
         LOG_FMT(LGUY, "%s(%d): (%d)<NL> col=%d\n",
                 __func__, __LINE__, pc->orig_line, pc->orig_col);
      }
      else
      {
         LOG_FMT(LGUY, "%s(%d): text():%s, type:%s, orig_col=%d, orig_col_end=%d\n",
                 __func__, __LINE__, pc->text(), get_token_name(pc->type), pc->orig_col, pc->orig_col_end);
      }
   }

   /* Set the cpd.newline string for this file */
   if ((cpd.settings[UO_newlines].le == LE_LF) ||
       ((cpd.settings[UO_newlines].le == LE_AUTO) &&
        (cpd.le_counts[LE_LF] >= cpd.le_counts[LE_CRLF]) &&
        (cpd.le_counts[LE_LF] >= cpd.le_counts[LE_CR])))
   {
      /* LF line ends */
      cpd.newline = "\n";
      LOG_FMT(LLINEENDS, "Using LF line endings\n");
   }
   else if ((cpd.settings[UO_newlines].le == LE_CRLF) ||
            ((cpd.settings[UO_newlines].le == LE_AUTO) &&
             (cpd.le_counts[LE_CRLF] >= cpd.le_counts[LE_LF]) &&
             (cpd.le_counts[LE_CRLF] >= cpd.le_counts[LE_CR])))
   {
      /* CRLF line ends */
      cpd.newline = "\r\n";
      LOG_FMT(LLINEENDS, "Using CRLF line endings\n");
   }
   else
   {
      /* CR line ends */
      cpd.newline = "\r";
      LOG_FMT(LLINEENDS, "Using CR line endings\n");
   }
} // tokenize
Example #22
0
Error ScriptClassParser::_skip_generic_type_params() {

	Token tk;

	while (true) {
		tk = get_token();

		if (tk == TK_IDENTIFIER) {
			tk = get_token();
			// Type specifications can end with "?" to denote nullable types, such as IList<int?>
			if (tk == TK_SYMBOL) {
				tk = get_token();
				if (value.operator String() != "?") {
					error_str = "Expected " + get_token_name(TK_IDENTIFIER) + ", found unexpected symbol '" + value + "'";
					error = true;
					return ERR_PARSE_ERROR;
				}
				if (tk != TK_OP_GREATER && tk != TK_COMMA) {
					error_str = "Nullable type symbol '?' is only allowed after an identifier, but found " + get_token_name(tk) + " next.";
					error = true;
					return ERR_PARSE_ERROR;
				}
			}

			if (tk == TK_PERIOD) {
				while (true) {
					tk = get_token();

					if (tk != TK_IDENTIFIER) {
						error_str = "Expected " + get_token_name(TK_IDENTIFIER) + ", found: " + get_token_name(tk);
						error = true;
						return ERR_PARSE_ERROR;
					}

					tk = get_token();

					if (tk != TK_PERIOD)
						break;
				}
			}

			if (tk == TK_OP_LESS) {
				Error err = _skip_generic_type_params();
				if (err)
					return err;
				continue;
			} else if (tk == TK_OP_GREATER) {
				return OK;
			} else if (tk != TK_COMMA) {
				error_str = "Unexpected token: " + get_token_name(tk);
				error = true;
				return ERR_PARSE_ERROR;
			}
		} else if (tk == TK_OP_LESS) {
			error_str = "Expected " + get_token_name(TK_IDENTIFIER) + ", found " + get_token_name(TK_OP_LESS);
			error = true;
			return ERR_PARSE_ERROR;
		} else if (tk == TK_OP_GREATER) {
			return OK;
		} else {
			error_str = "Unexpected token: " + get_token_name(tk);
			error = true;
			return ERR_PARSE_ERROR;
		}
	}
}
Example #23
0
/**
 * At the heart of this algorithm are two stacks.
 * There is the Paren Stack (PS) and the Frame stack.
 *
 * The PS (pse in the code) keeps track of braces, parens,
 * if/else/switch/do/while/etc items -- anything that is nestable.
 * Complex statements go through stages.
 * Take this simple if statement as an example:
 *   if ( x ) { x--; }
 *
 * The stack would change like so: 'token' stack afterwards
 * 'if' [IF - 1]
 * '('  [IF - 1] [PAREN OPEN]
 * 'x'  [IF - 1] [PAREN OPEN]
 * ')'  [IF - 2]       <- note that the state was incremented
 * '{'  [IF - 2] [BRACE OPEN]
 * 'x'  [IF - 2] [BRACE OPEN]
 * '--' [IF - 2] [BRACE OPEN]
 * ';'  [IF - 2] [BRACE OPEN]
 * '}'  [IF - 3]
 *                             <- lack of else kills the IF, closes statement
 *
 * Virtual braces example:
 *   if ( x ) x--; else x++;
 *
 * 'if'   [IF - 1]
 * '('    [IF - 1] [PAREN OPEN]
 * 'x'    [IF - 1] [PAREN OPEN]
 * ')'    [IF - 2]
 * 'x'    [IF - 2] [VBRACE OPEN]   <- VBrace open inserted before because '{' was not next
 * '--'   [IF - 2] [VBRACE OPEN]
 * ';'    [IF - 3]                 <- VBrace close inserted after semicolon
 * 'else' [ELSE - 0]               <- IF changed into ELSE
 * 'x'    [ELSE - 0] [VBRACE OPEN] <- lack of '{' -> VBrace
 * '++'   [ELSE - 0] [VBRACE OPEN]
 * ';'    [ELSE - 0]               <- VBrace close inserted after semicolon
 *                                 <- ELSE removed after statement close
 *
 * The pse stack is kept on a frame stack.
 * The frame stack is need for languages that support preprocessors (C, C++, C#)
 * that can arbitrarily change code flow. It also isolates #define macros so
 * that they are indented independently and do not affect the rest of the program.
 *
 * When an #if is hit, a copy of the current frame is push on the frame stack.
 * When an #else/#elif is hit, a copy of the current stack is pushed under the
 * #if frame and the original (pre-#if) frame is copied to the current frame.
 * When #endif is hit, the top frame is popped.
 * This has the following effects:
 *  - a simple #if / #endif does not affect program flow
 *  - #if / #else /#endif - continues from the #if clause
 *
 * When a #define is entered, the current frame is pushed and cleared.
 * When a #define is exited, the frame is popped.
 */
static void parse_cleanup(parse_frame_t *frm, chunk_t *pc)
{
   LOG_FUNC_ENTRY();

   LOG_FMT(LTOK, "%s:%zu] %16s - tos:%zu/%16s stg:%d\n",
           __func__, pc->orig_line, get_token_name(pc->type),
           frm->pse_tos, get_token_name(frm->pse[frm->pse_tos].type),
           frm->pse[frm->pse_tos].stage);

   /* Mark statement starts */
   if (((frm->stmt_count == 0) || (frm->expr_count == 0)) &&
       !chunk_is_semicolon(pc) &&
       (pc->type != CT_BRACE_CLOSE) &&
       (pc->type != CT_VBRACE_CLOSE) &&
       !chunk_is_str(pc, ")", 1) &&
       !chunk_is_str(pc, "]", 1))
   {
      chunk_flags_set(pc, PCF_EXPR_START | ((frm->stmt_count == 0) ? PCF_STMT_START : 0));
      LOG_FMT(LSTMT, "%zu] 1.marked %s as %s start st:%d ex:%d\n",
              pc->orig_line, pc->text(), (pc->flags & PCF_STMT_START) ? "stmt" : "expr",
              frm->stmt_count, frm->expr_count);
   }
   frm->stmt_count++;
   frm->expr_count++;

   if (frm->sparen_count > 0)
   {
      chunk_flags_set(pc, PCF_IN_SPAREN);

      /* Mark everything in the a for statement */
      for (int tmp = frm->pse_tos - 1; tmp >= 0; tmp--)
      {
         if (frm->pse[tmp].type == CT_FOR)
         {
            chunk_flags_set(pc, PCF_IN_FOR);
            break;
         }
      }

      /* Mark the parent on semicolons in for() stmts */
      if ((pc->type == CT_SEMICOLON) &&
          (frm->pse_tos > 1) &&
          (frm->pse[frm->pse_tos - 1].type == CT_FOR))
      {
         set_chunk_parent(pc, CT_FOR);
      }
   }

   /* Check the progression of complex statements */
   if (frm->pse[frm->pse_tos].stage != BS_NONE)
   {
      if (check_complex_statements(frm, pc))
      {
         return;
      }
   }

   /**
    * Check for a virtual brace statement close due to a semicolon.
    * The virtual brace will get handled the next time through.
    * The semicolon isn't handled at all.
    * TODO: may need to float VBRACE past comments until newline?
    */
   if (frm->pse[frm->pse_tos].type == CT_VBRACE_OPEN)
   {
      if (chunk_is_semicolon(pc))
      {
         cpd.consumed = true;
         close_statement(frm, pc);
      }
      else if (cpd.lang_flags & LANG_PAWN)
      {
         if (pc->type == CT_BRACE_CLOSE)
         {
            close_statement(frm, pc);
         }
      }
   }

   /* Handle close paren, vbrace, brace, and square */
   if ((pc->type == CT_PAREN_CLOSE) ||
       (pc->type == CT_BRACE_CLOSE) ||
       (pc->type == CT_VBRACE_CLOSE) ||
       (pc->type == CT_ANGLE_CLOSE) ||
       (pc->type == CT_MACRO_CLOSE) ||
       (pc->type == CT_SQUARE_CLOSE))
   {
      /* Change CT_PAREN_CLOSE into CT_SPAREN_CLOSE or CT_FPAREN_CLOSE */
      if ((pc->type == CT_PAREN_CLOSE) &&
          ((frm->pse[frm->pse_tos].type == CT_FPAREN_OPEN) ||
           (frm->pse[frm->pse_tos].type == CT_SPAREN_OPEN)))
      {
         set_chunk_type(pc, (c_token_t)(frm->pse[frm->pse_tos].type + 1));
         if (pc->type == CT_SPAREN_CLOSE)
         {
            frm->sparen_count--;
            chunk_flags_clr(pc, PCF_IN_SPAREN);
         }
      }

      /* Make sure the open / close match */
      if (pc->type != (frm->pse[frm->pse_tos].type + 1))
      {
         if ((frm->pse[frm->pse_tos].type != CT_NONE) &&
             (frm->pse[frm->pse_tos].type != CT_PP_DEFINE))
         {
            LOG_FMT(LWARN, "%s: %s:%zu Error: Unexpected '%s' for '%s', which was on line %zu\n",
                    __func__, cpd.filename, pc->orig_line, pc->text(),
                    get_token_name(frm->pse[frm->pse_tos].pc->type),
                    frm->pse[frm->pse_tos].pc->orig_line);
            print_stack(LBCSPOP, "=Error  ", frm, pc);
            cpd.error_count++;
         }
      }
      else
      {
         cpd.consumed = true;

         /* Copy the parent, update the paren/brace levels */
         set_chunk_parent(pc, frm->pse[frm->pse_tos].parent);
         frm->level--;
         if ((pc->type == CT_BRACE_CLOSE) ||
             (pc->type == CT_VBRACE_CLOSE) ||
             (pc->type == CT_MACRO_CLOSE))
         {
            frm->brace_level--;
         }
         pc->level       = frm->level;
         pc->brace_level = frm->brace_level;

         /* Pop the entry */
         frm->pse_tos--;
         print_stack(LBCSPOP, "-Close  ", frm, pc);

         /* See if we are in a complex statement */
         if (frm->pse[frm->pse_tos].stage != BS_NONE)
         {
            handle_complex_close(frm, pc);
         }
      }
   }

   /* In this state, we expect a semicolon, but we'll also hit the closing
    * sparen, so we need to check cpd.consumed to see if the close sparen was
    * aleady handled.
    */
   if (frm->pse[frm->pse_tos].stage == BS_WOD_SEMI)
   {
      chunk_t *tmp = pc;

      if (cpd.consumed)
      {
         /* If consumed, then we are on the close sparen.
          * PAWN: Check the next chunk for a semicolon. If it isn't, then
          * add a virtual semicolon, which will get handled on the next pass.
          */
         if (cpd.lang_flags & LANG_PAWN)
         {
            tmp = chunk_get_next_ncnl(pc);

            if ((tmp->type != CT_SEMICOLON) && (tmp->type != CT_VSEMICOLON))
            {
               pawn_add_vsemi_after(pc);
            }
         }
      }
      else
      {
         /* Complain if this ISN'T a semicolon, but close out WHILE_OF_DO anyway */
         if ((pc->type == CT_SEMICOLON) || (pc->type == CT_VSEMICOLON))
         {
            cpd.consumed = true;
            set_chunk_parent(pc, CT_WHILE_OF_DO);
         }
         else
         {
            LOG_FMT(LWARN, "%s:%zu: Error: Expected a semicolon for WHILE_OF_DO, but got '%s'\n",
                    cpd.filename, pc->orig_line, get_token_name(pc->type));
            cpd.error_count++;
         }
         handle_complex_close(frm, pc);
      }
   }

   /* Get the parent type for brace and paren open */
   c_token_t parent = pc->parent_type;
   if ((pc->type == CT_PAREN_OPEN) ||
       (pc->type == CT_FPAREN_OPEN) ||
       (pc->type == CT_SPAREN_OPEN) ||
       (pc->type == CT_BRACE_OPEN))
   {
      chunk_t *prev = chunk_get_prev_ncnl(pc);
      if (prev != NULL)
      {
         if ((pc->type == CT_PAREN_OPEN) ||
             (pc->type == CT_FPAREN_OPEN) ||
             (pc->type == CT_SPAREN_OPEN))
         {
            /* Set the parent for parens and change paren type */
            if (frm->pse[frm->pse_tos].stage != BS_NONE)
            {
               set_chunk_type(pc, CT_SPAREN_OPEN);
               parent = frm->pse[frm->pse_tos].type;
               frm->sparen_count++;
            }
            else if (prev->type == CT_FUNCTION)
            {
               set_chunk_type(pc, CT_FPAREN_OPEN);
               parent = CT_FUNCTION;
            }
            /* NS_ENUM and NS_OPTIONS are followed by a (type, name) pair */
            else if ((prev->type == CT_ENUM) &&
                     (cpd.lang_flags & LANG_OC))
            {
               /* Treat both as CT_ENUM since the syntax is identical */
               set_chunk_type(pc, CT_FPAREN_OPEN);
               parent = CT_ENUM;
            }
            else
            {
               /* no need to set parent */
            }
         }
         else  /* must be CT_BRACE_OPEN */
         {
            /* Set the parent for open braces */
            if (frm->pse[frm->pse_tos].stage != BS_NONE)
            {
               parent = frm->pse[frm->pse_tos].type;
            }
            else if ((prev->type == CT_ASSIGN) && (prev->str[0] == '='))
            {
               parent = CT_ASSIGN;
            }
            /*  Carry through CT_ENUM parent in NS_ENUM (type, name) { */
            else if ((prev->type == CT_FPAREN_CLOSE) &&
                     (cpd.lang_flags & LANG_OC) &&
                     (prev->parent_type == CT_ENUM))
            {
               parent = CT_ENUM;
            }
            else if (prev->type == CT_FPAREN_CLOSE)
            {
               parent = CT_FUNCTION;
            }
            else
            {
               /* no need to set parent */
            }
         }
      }
   }

   /**
    * Adjust the level for opens & create a stack entry
    * Note that CT_VBRACE_OPEN has already been handled.
    */
   if ((pc->type == CT_BRACE_OPEN) ||
       (pc->type == CT_PAREN_OPEN) ||
       (pc->type == CT_FPAREN_OPEN) ||
       (pc->type == CT_SPAREN_OPEN) ||
       (pc->type == CT_ANGLE_OPEN) ||
       (pc->type == CT_MACRO_OPEN) ||
       (pc->type == CT_SQUARE_OPEN))
   {
      frm->level++;
      if ((pc->type == CT_BRACE_OPEN) ||
          (pc->type == CT_MACRO_OPEN))
      {
         frm->brace_level++;
      }
      push_fmr_pse(frm, pc, BS_NONE, "+Open   ");
      frm->pse[frm->pse_tos].parent = parent;
      set_chunk_parent(pc, parent);
   }

   pattern_class patcls = get_token_pattern_class(pc->type);

   /** Create a stack entry for complex statements: */
   /** if, elseif, switch, for, while, synchronized, using, lock, with, version, CT_D_SCOPE_IF */
   if (patcls == PATCLS_BRACED)
   {
      push_fmr_pse(frm, pc,
                   (pc->type == CT_DO) ? BS_BRACE_DO : BS_BRACE2,
                   "+ComplexBraced");
   }
   else if (patcls == PATCLS_PBRACED)
   {
      brstage_e bs = BS_PAREN1;

      if ((pc->type == CT_WHILE) && maybe_while_of_do(pc))
      {
         set_chunk_type(pc, CT_WHILE_OF_DO);
         bs = BS_WOD_PAREN;
      }
      push_fmr_pse(frm, pc, bs, "+ComplexParenBraced");
   }
   else if (patcls == PATCLS_OPBRACED)
   {
      push_fmr_pse(frm, pc, BS_OP_PAREN1, "+ComplexOpParenBraced");
   }
   else if (patcls == PATCLS_ELSE)
   {
      push_fmr_pse(frm, pc, BS_ELSEIF, "+ComplexElse");
   }

   /* Mark simple statement/expression starts
    *  - after { or }
    *  - after ';', but not if the paren stack top is a paren
    *  - after '(' that has a parent type of CT_FOR
    */
   if ((pc->type == CT_SQUARE_OPEN) ||
       ((pc->type == CT_BRACE_OPEN) && (pc->parent_type != CT_ASSIGN)) ||
       (pc->type == CT_BRACE_CLOSE) ||
       (pc->type == CT_VBRACE_CLOSE) ||
       ((pc->type == CT_SPAREN_OPEN) && (pc->parent_type == CT_FOR)) ||
       (pc->type == CT_COLON) ||
       (pc->type == CT_OC_END) ||
       (chunk_is_semicolon(pc) &&
        (frm->pse[frm->pse_tos].type != CT_PAREN_OPEN) &&
        (frm->pse[frm->pse_tos].type != CT_FPAREN_OPEN) &&
        (frm->pse[frm->pse_tos].type != CT_SPAREN_OPEN)))
   {
      LOG_FMT(LSTMT, "%s: %zu> reset1 stmt on %s\n",
              __func__, pc->orig_line, pc->text());
      frm->stmt_count = 0;
      frm->expr_count = 0;
   }

   /* Mark expression starts */
   chunk_t *tmp = chunk_get_next_ncnl(pc);
   if ((pc->type == CT_ARITH) ||
       (pc->type == CT_ASSIGN) ||
       (pc->type == CT_CASE) ||
       (pc->type == CT_COMPARE) ||
       ((pc->type == CT_STAR) && tmp && (tmp->type != CT_STAR)) ||
       (pc->type == CT_BOOL) ||
       (pc->type == CT_MINUS) ||
       (pc->type == CT_PLUS) ||
       (pc->type == CT_CARET) ||
       (pc->type == CT_ANGLE_OPEN) ||
       (pc->type == CT_ANGLE_CLOSE) ||
       (pc->type == CT_RETURN) ||
       (pc->type == CT_THROW) ||
       (pc->type == CT_GOTO) ||
       (pc->type == CT_CONTINUE) ||
       (pc->type == CT_PAREN_OPEN) ||
       (pc->type == CT_FPAREN_OPEN) ||
       (pc->type == CT_SPAREN_OPEN) ||
       (pc->type == CT_BRACE_OPEN) ||
       chunk_is_semicolon(pc) ||
       (pc->type == CT_COMMA) ||
       (pc->type == CT_NOT) ||
       (pc->type == CT_INV) ||
       (pc->type == CT_COLON) ||
       (pc->type == CT_QUESTION))
   {
      frm->expr_count = 0;
      LOG_FMT(LSTMT, "%s: %zu> reset expr on %s\n",
              __func__, pc->orig_line, pc->text());
   }
   else if (pc->type == CT_BRACE_CLOSE)
   {
      if (!cpd.consumed)
      {
         if (!cpd.unc_off_used)
         {
            /* fatal error */
            fprintf(stderr, "Unmatched BRACE_CLOSE\nat line=%zu, column=%zu\n",
                    pc->orig_line, pc->orig_col);
            exit(EXIT_FAILURE);
         }
      }
   }
} // parse_cleanup
Example #24
0
void SSceneSummary::FillProp(PropItemVec& items)
{
    // fill items
    ButtonValue* B =PHelper().CreateButton (items,"Common\\File","Export...",0);
    B->OnBtnClickEvent.bind(this,&SSceneSummary::OnFileClick);
    // fill items
    PHelper().CreateCaption(items,"Common\\Level Name",			Scene->m_LevelOp.m_FNLevelPath.c_str());
    PHelper().CreateCaption(items,"Geometry\\Bounding\\Min", 	shared_str().printf("{%3.2f, %3.2f, %3.2f}",VPUSH(bbox.min)));
    PHelper().CreateCaption(items,"Geometry\\Bounding\\Max", 	shared_str().printf("{%3.2f, %3.2f, %3.2f}",VPUSH(bbox.max)));
    PHelper().CreateCaption(items,"Geometry\\Mesh\\Total Faces",   	shared_str().printf("%d",face_cnt));
    PHelper().CreateCaption(items,"Geometry\\Mesh\\Total Vertices",	shared_str().printf("%d",vert_cnt));
    PHelper().CreateCaption(items,"Geometry\\MU\\Objects",	   	shared_str().printf("%d",mu_objects.size()));
    PHelper().CreateCaption(items,"Geometry\\MU\\References",   shared_str().printf("%d",object_mu_ref_cnt));
    PHelper().CreateCaption(items,"Geometry\\LOD\\Objects",		shared_str().printf("%d",lod_objects.size()));
    PHelper().CreateCaption(items,"Geometry\\LOD\\References",	shared_str().printf("%d",object_lod_ref_cnt));
    PHelper().CreateCaption(items,"Visibility\\HOM\\Faces",		shared_str().printf("%d",hom_face_cnt));
    PHelper().CreateCaption(items,"Visibility\\HOM\\Vertices",	shared_str().printf("%d",hom_vert_cnt));
    PHelper().CreateCaption(items,"Visibility\\Sectors",		shared_str().printf("%d",sector_cnt));
    PHelper().CreateCaption(items,"Visibility\\Portals",		shared_str().printf("%d",portal_cnt));
    PHelper().CreateCaption(items,"Lights\\Count",				shared_str().printf("%d",light_point_cnt+light_spot_cnt));
    PHelper().CreateCaption(items,"Lights\\By Type\\Point",		shared_str().printf("%d",light_point_cnt));
    PHelper().CreateCaption(items,"Lights\\By Type\\Spot",		shared_str().printf("%d",light_spot_cnt));
    PHelper().CreateCaption(items,"Lights\\By Usage\\Dynamic",	shared_str().printf("%d",light_dynamic_cnt));
    PHelper().CreateCaption(items,"Lights\\By Usage\\Static",	shared_str().printf("%d",light_static_cnt));
    PHelper().CreateCaption(items,"Lights\\By Usage\\Breakable",shared_str().printf("%d",light_breakable_cnt));
    PHelper().CreateCaption(items,"Lights\\By Usage\\Procedural",shared_str().printf("%d",light_procedural_cnt));
    PHelper().CreateCaption(items,"Glows\\Count",				shared_str().printf("%d",glow_cnt));
    // objects
    for (OISetIt o_it=objects.begin(); o_it!=objects.end(); o_it++){
    	SObjectInfo* info= (SObjectInfo*)(&(*o_it));
        info->FillProp		(items,"Objects");
    }
    // textures
    CaptionValue* total_count=PHelper().CreateCaption	(items,"Textures\\Count","");
    CaptionValue* total_mem	= PHelper().CreateCaption	(items,"Textures\\Memory Usage","");
    u32 total_mem_usage		= 0; 
    ButtonValue* BB			= PHelper().CreateButton	(items,"Textures\\Highlight Textures\\Command", "Pixel Density,Clear", ButtonValue::flFirstOnly);
    BB->OnBtnClickEvent.bind(this,&SSceneSummary::OnHighlightClick);
    for (PDVecIt pd_it=pm_colors.begin(); pd_it!=pm_colors.end(); pd_it++){
    	string128 tmp;		
        sprintf				(tmp,"Textures\\Highlight Textures\\Color Legend\\Item #%d",pd_it-pm_colors.begin());
    	PHelper().CreateColor(items,PrepareKey(tmp,"Color").c_str(),&pd_it->color);
    	FloatValue* V		= PHelper().CreateFloat(items,PrepareKey(tmp,"Weight (p/m)").c_str(),&pd_it->pm,0,1000000,1,0);
        V->OnAfterEditEvent.bind(this,&SSceneSummary::OnWeightAfterEditClick);
        V->tag				= pd_it-pm_colors.begin();
    }
    for (u32 stt=sttFirst; stt<sttLast; stt++){
        LPCSTR nm			= get_token_name(summary_texture_type_tokens,stt);
        if (nm&&nm[0]){
            u32 cur_mem_usage	= 0; 
            float cur_area		= 0; 
            shared_str pref		= PrepareKey("Textures",nm);
            CaptionValue* mem 	= PHelper().CreateCaption(items,PrepareKey(pref.c_str(),"Memory Usage").c_str(), "");
            CaptionValue* area 	= PHelper().CreateCaption(items,PrepareKey(pref.c_str(),"Effective Area").c_str(), "");
            for (TISetIt it=textures.begin(); it!=textures.end(); it++){
                STextureInfo* info= (STextureInfo*)(&(*it));
                if (info->type==stt){ 
                    cur_area	+= info->effective_area;
                    info->FillProp(items,pref.c_str(),cur_mem_usage);
                }
            }
            mem->ApplyValue		(shared_str().printf("%d Kb",iFloor(cur_mem_usage/1024)));
            area->ApplyValue 	(shared_str().printf("%3.2f m^2",cur_area));
            total_mem_usage		+= cur_mem_usage;
        }
    }
    total_count->ApplyValue	(shared_str().printf("%d",		textures.size()));
    total_mem->ApplyValue	(shared_str().printf("%d Kb",	iFloor(total_mem_usage/1024)));
	// sound
    PHelper().CreateCaption	(items,"Sounds\\Occluder\\Faces",		shared_str().printf("%d",snd_occ_face_cnt));
    PHelper().CreateCaption	(items,"Sounds\\Occluder\\Vertices",	shared_str().printf("%d",snd_occ_vert_cnt));
    PHelper().CreateCaption	(items,"Sounds\\Sources",				shared_str().printf("%d",sound_source_cnt));
    PHelper().CreateCaption	(items,"Sounds\\Waves\\Count",			shared_str().printf("%d",waves.size()));
    for (RStringSetIt w_it=waves.begin(); w_it!=waves.end(); w_it++)
        PHelper().CreateCaption(items,PrepareKey("Sounds\\Waves",w_it->c_str()),"-");
    // particles
    PHelper().CreateCaption	(items,"Particle System\\Sources",		shared_str().printf("%d",pe_static_cnt));
    PHelper().CreateCaption	(items,"Particle System\\Refs\\Count",	shared_str().printf("%d",pe_static.size()));
    for (RStringSetIt pe_it=pe_static.begin(); pe_it!=pe_static.end(); pe_it++)
        PHelper().CreateCaption(items,PrepareKey("Particle System\\Refs",pe_it->c_str()),"-");
}
Example #25
0
static bool handle_complex_close(parse_frame_t *frm, chunk_t *pc)
{
   LOG_FUNC_ENTRY();
   chunk_t *next;

   if (frm->pse[frm->pse_tos].stage == BS_PAREN1)
   {
      if ((pc->next != NULL) && (pc->next->type == CT_WHEN))
      {
         frm->pse[frm->pse_tos].type  = pc->type;
         frm->pse[frm->pse_tos].stage = BS_CATCH_WHEN;
         return(true);
      }
      else
      {
         /* PAREN1 always => BRACE2 */
         frm->pse[frm->pse_tos].stage = BS_BRACE2;
      }
   }
   else if (frm->pse[frm->pse_tos].stage == BS_BRACE2)
   {
      /* BRACE2: IF => ELSE, anyting else => close */
      if ((frm->pse[frm->pse_tos].type == CT_IF) ||
          (frm->pse[frm->pse_tos].type == CT_ELSEIF))
      {
         frm->pse[frm->pse_tos].stage = BS_ELSE;

         /* If the next chunk isn't CT_ELSE, close the statement */
         next = chunk_get_next_ncnl(pc);
         if ((next != NULL) && (next->type != CT_ELSE))
         {
            frm->pse_tos--;
            print_stack(LBCSPOP, "-IF-HCS ", frm, pc);
            if (close_statement(frm, pc))
            {
               return(true);
            }
         }
      }
      else if ((frm->pse[frm->pse_tos].type == CT_TRY) ||
               (frm->pse[frm->pse_tos].type == CT_CATCH))
      {
         frm->pse[frm->pse_tos].stage = BS_CATCH;

         /* If the next chunk isn't CT_CATCH or CT_FINALLY, close the statement */
         next = chunk_get_next_ncnl(pc);
         if ((next != NULL) &&
             (next->type != CT_CATCH) &&
             (next->type != CT_FINALLY))
         {
            frm->pse_tos--;
            print_stack(LBCSPOP, "-TRY-HCS ", frm, pc);
            if (close_statement(frm, pc))
            {
               return(true);
            }
         }
      }
      else
      {
         LOG_FMT(LNOTE, "%s: close_statement on %s BS_BRACE2\n", __func__,
                 get_token_name(frm->pse[frm->pse_tos].type));
         frm->pse_tos--;
         print_stack(LBCSPOP, "-HCC B2 ", frm, pc);
         if (close_statement(frm, pc))
         {
            return(true);
         }
      }
   }
   else if (frm->pse[frm->pse_tos].stage == BS_BRACE_DO)
   {
      frm->pse[frm->pse_tos].stage = BS_WHILE;
   }
   else if (frm->pse[frm->pse_tos].stage == BS_WOD_PAREN)
   {
      LOG_FMT(LNOTE, "%s: close_statement on %s BS_WOD_PAREN\n", __func__,
              get_token_name(frm->pse[frm->pse_tos].type));
      frm->pse[frm->pse_tos].stage = BS_WOD_SEMI;
      print_stack(LBCSPOP, "-HCC WoDP ", frm, pc);
   }
   else if (frm->pse[frm->pse_tos].stage == BS_WOD_SEMI)
   {
      LOG_FMT(LNOTE, "%s: close_statement on %s BS_WOD_SEMI\n", __func__,
              get_token_name(frm->pse[frm->pse_tos].type));
      frm->pse_tos--;
      print_stack(LBCSPOP, "-HCC WoDS ", frm, pc);

      if (close_statement(frm, pc))
      {
         return(true);
      }
   }
   else
   {
      /* PROBLEM */
      LOG_FMT(LWARN, "%s:%zu Error: TOS.type='%s' TOS.stage=%d\n",
              cpd.filename, pc->orig_line,
              get_token_name(frm->pse[frm->pse_tos].type),
              frm->pse[frm->pse_tos].stage);
      cpd.error_count++;
   }
   return(false);
} // handle_complex_close
Example #26
0
static void process_if_chain(chunk_t *br_start)
{
   LOG_FUNC_ENTRY();
   chunk_t *braces[256];
   int     br_cnt           = 0;
   bool    must_have_braces = false;

   chunk_t *pc = br_start;

   LOG_FMT(LBRCH, "%s: if starts on line %zu\n", __func__, br_start->orig_line);

   while (pc != NULL)
   {
      if (pc->type == CT_BRACE_OPEN)
      {
         bool tmp = can_remove_braces(pc);
         LOG_FMT(LBRCH, "  [%d] line %zu - can%s remove %s\n",
                 br_cnt, pc->orig_line, tmp ? "" : "not",
                 get_token_name(pc->type));
         if (!tmp)
         {
            must_have_braces = true;
         }
      }
      else
      {
         bool tmp = should_add_braces(pc);
         if (tmp)
         {
            must_have_braces = true;
         }
         LOG_FMT(LBRCH, "  [%d] line %zu - %s %s\n",
                 br_cnt, pc->orig_line, tmp ? "should add" : "ignore",
                 get_token_name(pc->type));
      }

      braces[br_cnt++] = pc;
      chunk_t *br_close = chunk_skip_to_match(pc, CNAV_PREPROC);
      if (br_close == NULL)
      {
         break;
      }
      braces[br_cnt++] = br_close;

      pc = chunk_get_next_ncnl(br_close, CNAV_PREPROC);
      if ((pc == NULL) || (pc->type != CT_ELSE))
      {
         break;
      }

      if (cpd.settings[UO_mod_full_brace_if_chain_only].b)
      {
         // There is an 'else' - we want full braces.
         must_have_braces = true;
      }

      pc = chunk_get_next_ncnl(pc, CNAV_PREPROC);
      if ((pc != NULL) && (pc->type == CT_ELSEIF))
      {
         while ((pc != NULL) && (pc->type != CT_VBRACE_OPEN) && (pc->type != CT_BRACE_OPEN))
         {
            pc = chunk_get_next_ncnl(pc, CNAV_PREPROC);
         }
      }
      if (pc == NULL)
      {
         break;
      }
      if ((pc->type != CT_BRACE_OPEN) && (pc->type != CT_VBRACE_OPEN))
      {
         break;
      }
   }

   if (must_have_braces)
   {
      LOG_FMT(LBRCH, "%s: add braces on lines[%d]:", __func__, br_cnt);
      while (--br_cnt >= 0)
      {
         chunk_flags_set(braces[br_cnt], PCF_KEEP_BRACE);
         if ((braces[br_cnt]->type == CT_VBRACE_OPEN) ||
             (braces[br_cnt]->type == CT_VBRACE_CLOSE))
         {
            LOG_FMT(LBRCH, " %zu", braces[br_cnt]->orig_line);
            convert_vbrace(braces[br_cnt]);
         }
         else
         {
            LOG_FMT(LBRCH, " {%zu}", braces[br_cnt]->orig_line);
         }
         braces[br_cnt] = NULL;
      }
      LOG_FMT(LBRCH, "\n");
   }
   else if (cpd.settings[UO_mod_full_brace_if_chain].b)
   {
      // This might run because either UO_mod_full_brace_if_chain or UO_mod_full_brace_if_chain_only is used.
      // We only want to remove braces if the first one is active.

      LOG_FMT(LBRCH, "%s: remove braces on lines[%d]:", __func__, br_cnt);
      while (--br_cnt >= 0)
      {
         if ((braces[br_cnt]->type == CT_BRACE_OPEN) ||
             (braces[br_cnt]->type == CT_BRACE_CLOSE))
         {
            LOG_FMT(LBRCH, " {%zu}", braces[br_cnt]->orig_line);
            convert_brace(braces[br_cnt]);
         }
         else
         {
            LOG_FMT(LBRCH, " %zu", braces[br_cnt]->orig_line);
         }
         braces[br_cnt] = NULL;
      }
      LOG_FMT(LBRCH, "\n");
   }
} // process_if_chain
Example #27
0
void tokenize_cleanup(void)
{
   chunk_t *pc   = chunk_get_head();
   chunk_t *prev = NULL;
   chunk_t *next;
   chunk_t *tmp;
   chunk_t *tmp2;
   bool    in_type_cast = false;

   /* Since [] is expected to be TSQUARE for the 'operator', we need to make
    * this change in the first pass.
    */
   for (pc = chunk_get_head(); pc != NULL; pc = chunk_get_next_ncnl(pc))
   {
      if (pc->type == CT_SQUARE_OPEN)
      {
         next = chunk_get_next_ncnl(pc);
         if (chunk_is_token(next, CT_SQUARE_CLOSE))
         {
            /* Change '[' + ']' into '[]' */
            pc->type = CT_TSQUARE;
            pc->str  = "[]";
            chunk_del(next);
            pc->orig_col_end += 1;
         }
      }
      if ((pc->type == CT_SEMICOLON) &&
          (pc->flags & PCF_IN_PREPROC) &&
          !chunk_get_next_ncnl(pc, CNAV_PREPROC))
      {
         LOG_FMT(LNOTE, "%s:%d Detected a macro that ends with a semicolon. Possible failures if used.\n",
                 cpd.filename, pc->orig_line);
      }
   }

   /* We can handle everything else in the second pass */
   pc   = chunk_get_head();
   next = chunk_get_next_ncnl(pc);
   while ((pc != NULL) && (next != NULL))
   {
      if ((pc->type == CT_DOT) && ((cpd.lang_flags & LANG_ALLC) != 0))
      {
         pc->type = CT_MEMBER;
      }

      /* Determine the version stuff (D only) */
      if (pc->type == CT_D_VERSION)
      {
         if (next->type == CT_PAREN_OPEN)
         {
            pc->type = CT_D_VERSION_IF;
         }
         else
         {
            if (next->type != CT_ASSIGN)
            {
               LOG_FMT(LERR, "%s:%d %s: version: Unexpected token %s\n",
                       cpd.filename, pc->orig_line, __func__, get_token_name(next->type));
               cpd.error_count++;
            }
            pc->type = CT_WORD;
         }
      }

      /* Determine the scope stuff (D only) */
      if (pc->type == CT_D_SCOPE)
      {
         if (next->type == CT_PAREN_OPEN)
         {
            pc->type = CT_D_SCOPE_IF;
         }
         else
         {
            pc->type = CT_TYPE;
         }
      }

      /**
       * Change CT_BASE before CT_PAREN_OPEN to CT_WORD.
       * public myclass() : base() {
       * }
       */
      if ((pc->type == CT_BASE) && (next->type == CT_PAREN_OPEN))
      {
         pc->type = CT_WORD;
      }

      if ((pc->type == CT_ENUM) && (next->type == CT_CLASS))
      {
         next->type = CT_ENUM_CLASS;
      }

      /**
       * Change CT_WORD after CT_ENUM, CT_UNION, or CT_STRUCT to CT_TYPE
       * Change CT_WORD before CT_WORD to CT_TYPE
       */
      if (next->type == CT_WORD)
      {
         if ((pc->type == CT_ENUM) ||
             (pc->type == CT_ENUM_CLASS) ||
             (pc->type == CT_UNION) ||
             (pc->type == CT_STRUCT))
         {
            next->type = CT_TYPE;
         }
         if (pc->type == CT_WORD)
         {
            pc->type = CT_TYPE;
         }
      }

      /* change extern to qualifier if extern isn't followed by a string or
       * an open paren
       */
      if (pc->type == CT_EXTERN)
      {
         if (next->type == CT_STRING)
         {
            /* Probably 'extern "C"' */
         }
         else if (next->type == CT_PAREN_OPEN)
         {
            /* Probably 'extern (C)' */
         }
         else
         {
            /* Something else followed by a open brace */
            tmp = chunk_get_next_ncnl(next);
            if ((tmp == NULL) || (tmp->type != CT_BRACE_OPEN))
            {
               pc->type = CT_QUALIFIER;
            }
         }
      }

      /**
       * Change CT_STAR to CT_PTR_TYPE if preceded by CT_TYPE,
       * CT_QUALIFIER, or CT_PTR_TYPE.
       */
      if ((next->type == CT_STAR) &&
          ((pc->type == CT_TYPE) ||
           (pc->type == CT_QUALIFIER) ||
           (pc->type == CT_PTR_TYPE)))
      {
         next->type = CT_PTR_TYPE;
      }

      if ((pc->type == CT_TYPE_CAST) &&
          (next->type == CT_ANGLE_OPEN))
      {
         next->parent_type = CT_TYPE_CAST;
         in_type_cast      = true;
      }

      /**
       * Change angle open/close to CT_COMPARE, if not a template thingy
       */
      if ((pc->type == CT_ANGLE_OPEN) && (pc->parent_type != CT_TYPE_CAST))
      {
         /* pretty much all languages except C use <> for something other than
          * comparisons.  "#include<xxx>" is handled elsewhere.
          */
         if (cpd.lang_flags & (LANG_CPP | LANG_CS | LANG_JAVA | LANG_VALA | LANG_OC))
         {
            check_template(pc);
         }
         else
         {
            /* convert CT_ANGLE_OPEN to CT_COMPARE */
            pc->type = CT_COMPARE;
         }
      }
      if ((pc->type == CT_ANGLE_CLOSE) && (pc->parent_type != CT_TEMPLATE))
      {
         if (in_type_cast)
         {
            in_type_cast    = false;
            pc->parent_type = CT_TYPE_CAST;
         }
         else
         {
            next = handle_double_angle_close(pc);
         }
      }

      if ((cpd.lang_flags & LANG_D) != 0)
      {
         /* Check for the D string concat symbol '~' */
         if ((pc->type == CT_INV) &&
             ((prev->type == CT_STRING) ||
              (prev->type == CT_WORD) ||
              (next->type == CT_STRING)))
         {
            pc->type = CT_CONCAT;
         }

         /* Check for the D template symbol '!' (word + '!' + word or '(') */
         if ((pc->type == CT_NOT) &&
             (prev->type == CT_WORD) &&
             ((next->type == CT_PAREN_OPEN) ||
              (next->type == CT_WORD) ||
              (next->type == CT_TYPE)))
         {
            pc->type = CT_D_TEMPLATE;
         }

         /* handle "version(unittest) { }" vs "unittest { }" */
         if (prev && (pc->type == CT_UNITTEST) && (prev->type == CT_PAREN_OPEN))
         {
            pc->type = CT_WORD;
         }
      }

      if ((cpd.lang_flags & LANG_CPP) != 0)
      {
         /* Change Word before '::' into a type */
         if ((pc->type == CT_WORD) && (next->type == CT_DC_MEMBER))
         {
            pc->type = CT_TYPE;
         }
      }

      /* Change get/set to CT_WORD if not followed by a brace open */
      if ((pc->type == CT_GETSET) && (next->type != CT_BRACE_OPEN))
      {
         if ((next->type == CT_SEMICOLON) &&
             ((prev->type == CT_BRACE_CLOSE) ||
              (prev->type == CT_BRACE_OPEN) ||
              (prev->type == CT_SEMICOLON)))
         {
            pc->type          = CT_GETSET_EMPTY;
            next->parent_type = CT_GETSET;
         }
         else
         {
            pc->type = CT_WORD;
         }
      }

      /* Interface is only a keyword in MS land if followed by 'class' or 'struct'
       * likewise, 'class' may be a member name in Java.
       */
      if ((pc->type == CT_CLASS) && !CharTable::IsKw1(next->str[0]))
      {
         pc->type = CT_WORD;
      }

      /* Change item after operator (>=, ==, etc) to a CT_OPERATOR_VAL
       * Usually the next item is part of the operator.
       * In a few cases the next few tokens are part of it:
       *  operator +       - common case
       *  operator >>      - need to combine '>' and '>'
       *  operator ()
       *  operator []      - already converted to TSQUARE
       *  operator new []
       *  operator delete []
       *  operator const char *
       *  operator const B&
       *  operator std::allocator<U>
       *
       * In all cases except the last, this will put the entire operator value
       * in one chunk.
       */
      if (pc->type == CT_OPERATOR)
      {
         tmp2 = chunk_get_next(next);
         /* Handle special case of () operator -- [] already handled */
         if (next->type == CT_PAREN_OPEN)
         {
            tmp = chunk_get_next(next);
            if ((tmp != NULL) && (tmp->type == CT_PAREN_CLOSE))
            {
               next->str  = "()";
               next->type = CT_OPERATOR_VAL;
               chunk_del(tmp);
               next->orig_col_end += 1;
            }
         }
         else if ((next->type == CT_ANGLE_CLOSE) &&
                  tmp2 && (tmp2->type == CT_ANGLE_CLOSE) &&
                  (tmp2->orig_col == next->orig_col_end))
         {
            next->str.append('>');
            next->orig_col_end++;
            next->type = CT_OPERATOR_VAL;
            chunk_del(tmp2);
         }
         else if (next->flags & PCF_PUNCTUATOR)
         {
            next->type = CT_OPERATOR_VAL;
         }
         else
         {
            next->type = CT_TYPE;

            /* Replace next with a collection of all tokens that are part of
             * the type.
             */
            tmp2 = next;
            while ((tmp = chunk_get_next(tmp2)) != NULL)
            {
               if ((tmp->type != CT_WORD) &&
                   (tmp->type != CT_TYPE) &&
                   (tmp->type != CT_QUALIFIER) &&
                   (tmp->type != CT_STAR) &&
                   (tmp->type != CT_AMP) &&
                   (tmp->type != CT_TSQUARE))
               {
                  break;
               }
               /* Change tmp into a type so that space_needed() works right */
               make_type(tmp);
               int num_sp = space_needed(tmp2, tmp);
               while (num_sp-- > 0)
               {
                  next->str.append(" ");
               }
               next->str.append(tmp->str);
               tmp2 = tmp;
            }

            while ((tmp2 = chunk_get_next(next)) != tmp)
            {
               chunk_del(tmp2);
            }

            next->type = CT_OPERATOR_VAL;

            next->orig_col_end = next->orig_col + next->len();
         }
         next->parent_type = CT_OPERATOR;

         LOG_FMT(LOPERATOR, "%s: %d:%d operator '%s'\n",
                 __func__, pc->orig_line, pc->orig_col, next->str.c_str());
      }

      /* Change private, public, protected into either a qualifier or label */
      if (pc->type == CT_PRIVATE)
      {
         /* Handle Qt slots - maybe should just check for a CT_WORD? */
         if (chunk_is_str(next, "slots", 5) || chunk_is_str(next, "Q_SLOTS", 7))
         {
            tmp = chunk_get_next(next);
            if ((tmp != NULL) && (tmp->type == CT_COLON))
            {
               next = tmp;
            }
         }
         if (next->type == CT_COLON)
         {
            next->type = CT_PRIVATE_COLON;
            if ((tmp = chunk_get_next_ncnl(next)) != NULL)
            {
               tmp->flags |= PCF_STMT_START | PCF_EXPR_START;
            }
         }
         else
         {
            pc->type = (chunk_is_str(pc, "signals", 7) || chunk_is_str(pc, "Q_SIGNALS", 9)) ? CT_WORD : CT_QUALIFIER;
         }
      }

      /* Look for <newline> 'EXEC' 'SQL' */
      if (chunk_is_str(pc, "EXEC", 4) && chunk_is_str(next, "SQL", 3))
      {
         tmp = chunk_get_prev(pc);
         if (chunk_is_newline(tmp))
         {
            tmp = chunk_get_next(next);
            if (chunk_is_str_case(tmp, "BEGIN", 5))
            {
               pc->type = CT_SQL_BEGIN;
            }
            else if (chunk_is_str_case(tmp, "END", 3))
            {
               pc->type = CT_SQL_END;
            }
            else
            {
               pc->type = CT_SQL_EXEC;
            }

            /* Change words into CT_SQL_WORD until CT_SEMICOLON */
            while (tmp != NULL)
            {
               if (tmp->type == CT_SEMICOLON)
               {
                  break;
               }
               if ((tmp->len() > 0) && unc_isalpha(*tmp->str))
               {
                  tmp->type = CT_SQL_WORD;
               }
               tmp = chunk_get_next_ncnl(tmp);
            }
         }
      }

      /* handle MS abomination 'for each' */
      if ((pc->type == CT_FOR) && chunk_is_str(next, "each", 4) &&
          (next == chunk_get_next(pc)))
      {
         /* merge the two with a space between */
         pc->str.append(' ');
         pc->str += next->str;
         pc->orig_col_end = next->orig_col_end;
         chunk_del(next);
         next = chunk_get_next_ncnl(pc);
         /* label the 'in' */
         if (next && (next->type == CT_PAREN_OPEN))
         {
            tmp = chunk_get_next_ncnl(next);
            while (tmp && (tmp->type != CT_PAREN_CLOSE))
            {
               if (chunk_is_str(tmp, "in", 2))
               {
                  tmp->type = CT_IN;
                  break;
               }
               tmp = chunk_get_next_ncnl(tmp);
            }
         }
      }

      /* ObjectiveC allows keywords to be used as identifiers in some situations
       * This is a dirty hack to allow some of the more common situations.
       */
      if (cpd.lang_flags & LANG_OC)
      {
         if (((pc->type == CT_IF) ||
              (pc->type == CT_FOR) ||
              (pc->type == CT_WHILE)) &&
             !chunk_is_token(next, CT_PAREN_OPEN))
         {
            pc->type = CT_WORD;
         }
         if ((pc->type == CT_DO) &&
             (chunk_is_token(prev, CT_MINUS) ||
              chunk_is_token(next, CT_SQUARE_CLOSE)))
         {
            pc->type = CT_WORD;
         }
      }

      /* Another hack to clean up more keyword abuse */
      if ((pc->type == CT_CLASS) &&
          (chunk_is_token(prev, CT_DOT) ||
           chunk_is_token(next, CT_DOT)))
      {
         pc->type = CT_WORD;
      }

      /* Detect Objective C class name */
      if ((pc->type == CT_OC_IMPL) ||
          (pc->type == CT_OC_INTF) ||
          (pc->type == CT_OC_PROTOCOL))
      {
         if (next->type != CT_PAREN_OPEN)
         {
            next->type = CT_OC_CLASS;
         }
         next->parent_type = pc->type;

         tmp = chunk_get_next_ncnl(next);
         if (tmp != NULL)
         {
            tmp->flags |= PCF_STMT_START | PCF_EXPR_START;
         }

         tmp = chunk_get_next_type(pc, CT_OC_END, pc->level);
         if (tmp != NULL)
         {
            tmp->parent_type = pc->type;
         }
      }

      if (pc->type == CT_OC_INTF)
      {
         tmp = chunk_get_next_ncnl(pc, CNAV_PREPROC);
         while ((tmp != NULL) && (tmp->type != CT_OC_END))
         {
            if (get_token_pattern_class(tmp->type) != PATCLS_NONE)
            {
               LOG_FMT(LOBJCWORD, "@interface %d:%d change '%s' (%s) to CT_WORD\n",
                       pc->orig_line, pc->orig_col, tmp->str.c_str(),
                       get_token_name(tmp->type));
               tmp->type = CT_WORD;
            }
            tmp = chunk_get_next_ncnl(tmp, CNAV_PREPROC);
         }
      }

      /* Detect Objective-C categories and class extensions */
      /* @interface ClassName (CategoryName) */
      /* @implementation ClassName (CategoryName) */
      /* @interface ClassName () */
      /* @implementation ClassName () */
      if (((pc->parent_type == CT_OC_IMPL) ||
           (pc->parent_type == CT_OC_INTF) ||
           (pc->type == CT_OC_CLASS)) &&
          (next->type == CT_PAREN_OPEN))
      {
         next->parent_type = pc->parent_type;

         tmp = chunk_get_next(next);
         if ((tmp != NULL) && (tmp->next != NULL))
         {
            if (tmp->type == CT_PAREN_CLOSE)
            {
               //tmp->type        = CT_OC_CLASS_EXT;
               tmp->parent_type = pc->parent_type;
            }
            else
            {
               tmp->type        = CT_OC_CATEGORY;
               tmp->parent_type = pc->parent_type;
            }
         }

         tmp = chunk_get_next_type(pc, CT_PAREN_CLOSE, pc->level);
         if (tmp != NULL)
         {
            tmp->parent_type = pc->parent_type;
         }
      }

      /* Detect Objective C @property
       *  @property NSString *stringProperty;
       *  @property(nonatomic, retain) NSMutableDictionary *shareWith;
       */
      if (pc->type == CT_OC_PROPERTY)
      {
         if (next->type != CT_PAREN_OPEN)
         {
            next->flags |= PCF_STMT_START | PCF_EXPR_START;
         }
         else
         {
            next->parent_type = pc->type;

            tmp = chunk_get_next_type(pc, CT_PAREN_CLOSE, pc->level);
            if (tmp != NULL)
            {
               tmp->parent_type = pc->type;
               tmp = chunk_get_next_ncnl(tmp);
               if (tmp != NULL)
               {
                  tmp->flags |= PCF_STMT_START | PCF_EXPR_START;

                  tmp = chunk_get_next_type(tmp, CT_SEMICOLON, pc->level);
                  if (tmp != NULL)
                  {
                     tmp->parent_type = pc->type;
                  }
               }
            }
         }
      }

      /* Detect Objective C @selector
       *  @selector(msgNameWithNoArg)
       *  @selector(msgNameWith1Arg:)
       *  @selector(msgNameWith2Args:arg2Name:)
       */
      if ((pc->type == CT_OC_SEL) && (next->type == CT_PAREN_OPEN))
      {
         next->parent_type = pc->type;

         tmp = chunk_get_next(next);
         if (tmp != NULL)
         {
            tmp->type        = CT_OC_SEL_NAME;
            tmp->parent_type = pc->type;

            while ((tmp = chunk_get_next_ncnl(tmp)) != NULL)
            {
               if (tmp->type == CT_PAREN_CLOSE)
               {
                  tmp->parent_type = CT_OC_SEL;
                  break;
               }
               tmp->type        = CT_OC_SEL_NAME;
               tmp->parent_type = pc->type;
            }
         }
      }

      /* Handle special preprocessor junk */
      if (pc->type == CT_PREPROC)
      {
         pc->parent_type = next->type;
      }

      /* Detect "pragma region" and "pragma endregion" */
      if ((pc->type == CT_PP_PRAGMA) && (next->type == CT_PREPROC_BODY))
      {
         if ((memcmp(next->str, "region", 6) == 0) ||
             (memcmp(next->str, "endregion", 9) == 0))
         {
            pc->type = (*next->str == 'r') ? CT_PP_REGION : CT_PP_ENDREGION;

            prev->parent_type = pc->type;
         }
      }

      /* Check for C# nullable types '?' is in next */
      if ((cpd.lang_flags & LANG_CS) &&
          (next->type == CT_QUESTION) &&
          (next->orig_col == (pc->orig_col + pc->len())))
      {
         tmp = chunk_get_next_ncnl(next);
         if (tmp != NULL)
         {
            bool doit = ((tmp->type == CT_PAREN_CLOSE) ||
                         (tmp->type == CT_ANGLE_CLOSE));

            if (tmp->type == CT_WORD)
            {
               tmp2 = chunk_get_next_ncnl(tmp);
               if ((tmp2 != NULL) &&
                   ((tmp2->type == CT_SEMICOLON) ||
                    (tmp2->type == CT_ASSIGN) ||
                    (tmp2->type == CT_COMMA)))
               {
                  doit = true;
               }
            }

            if (doit)
            {
               pc->str += next->str;
               chunk_del(next);
               next = tmp;
            }
         }
      }

      /* Change 'default(' into a sizeof-like statement */
      if ((cpd.lang_flags & LANG_CS) &&
          (pc->type == CT_DEFAULT) &&
          (next->type == CT_PAREN_OPEN))
      {
         pc->type = CT_SIZEOF;
      }

      if ((pc->type == CT_UNSAFE) && (next->type != CT_BRACE_OPEN))
      {
         pc->type = CT_QUALIFIER;
      }

      if (((pc->type == CT_USING) ||
           ((pc->type == CT_TRY) && (cpd.lang_flags & LANG_JAVA))) &&
          (next->type == CT_PAREN_OPEN))
      {
         pc->type = CT_USING_STMT;
      }

      /* Add minimal support for C++0x rvalue references */
      if ((pc->type == CT_BOOL) && chunk_is_str(pc, "&&", 2))
      {
         if (prev->type == CT_TYPE)
         {
            pc->type = CT_BYREF;
         }
      }

      /* HACK: treat try followed by a colon as a qualifier to handle this:
       *   A::A(int) try : B() { } catch (...) { }
       */
      if ((pc->type == CT_TRY) && chunk_is_str(pc, "try", 3) &&
          (next != NULL) && (next->type == CT_COLON))
      {
         pc->type = CT_QUALIFIER;
      }

      /* TODO: determine other stuff here */

      prev = pc;
      pc   = next;
      next = chunk_get_next_ncnl(pc);
   }
}
Example #28
0
static bool can_remove_braces(chunk_t *bopen)
{
   LOG_FUNC_ENTRY();

   chunk_t *prev      = NULL;
   size_t  semi_count = 0;
   size_t  level      = bopen->level + 1;
   bool    hit_semi   = false;
   bool    was_fcn    = false;
   size_t  nl_max     = cpd.settings[UO_mod_full_brace_nl].u;
   size_t  nl_count   = 0;
   size_t  if_count   = 0;
   int     br_count   = 0;

   /* Cannot remove braces inside a preprocessor */
   if (bopen->flags & PCF_IN_PREPROC)
   {
      return(false);
   }
   chunk_t *pc = chunk_get_next_ncnl(bopen, CNAV_PREPROC);
   if ((pc != NULL) && (pc->type == CT_BRACE_CLOSE))
   {
      /* Can't remove empty statement */
      return(false);
   }

   LOG_FMT(LBRDEL, "%s: start on %zu : ", __func__, bopen->orig_line);

   pc = chunk_get_next_nc(bopen, CNAV_ALL);
   while ((pc != NULL) && (pc->level >= level))
   {
      if (pc->flags & PCF_IN_PREPROC)
      {
         /* Cannot remove braces that contain a preprocessor */
         return(false);
      }

      if (chunk_is_newline(pc))
      {
         nl_count += pc->nl_count;
         if ((nl_max > 0) && (nl_count > nl_max))
         {
            LOG_FMT(LBRDEL, " exceeded %zu newlines\n", nl_max);
            return(false);
         }
      }
      else
      {
         if (pc->type == CT_BRACE_OPEN)
         {
            br_count++;
         }
         else if (pc->type == CT_BRACE_CLOSE)
         {
            br_count--;
         }
         else if ((pc->type == CT_IF) || (pc->type == CT_ELSEIF))
         {
            if (br_count == 0)
            {
               if_count++;
            }
         }

         if (pc->level == level)
         {
            if ((semi_count > 0) && hit_semi)
            {
               /* should have bailed due to close brace level drop */
               LOG_FMT(LBRDEL, " no close brace\n");
               return(false);
            }

            LOG_FMT(LBRDEL, " [%s %zu-%zu]", pc->text(), pc->orig_line, semi_count);

            if (pc->type == CT_ELSE)
            {
               LOG_FMT(LBRDEL, " bailed on %s on line %zu\n",
                       pc->text(), pc->orig_line);
               return(false);
            }

            was_fcn = (prev != NULL) && (prev->type == CT_FPAREN_CLOSE);

            if (chunk_is_semicolon(pc) ||
                (pc->type == CT_IF) ||
                (pc->type == CT_ELSEIF) ||
                (pc->type == CT_FOR) ||
                (pc->type == CT_DO) ||
                (pc->type == CT_WHILE) ||
                (pc->type == CT_USING_STMT) ||
                ((pc->type == CT_BRACE_OPEN) && was_fcn))
            {
               hit_semi |= chunk_is_semicolon(pc);
               if (++semi_count > 1)
               {
                  LOG_FMT(LBRDEL, " bailed on %zu because of %s on line %zu\n",
                          bopen->orig_line, pc->text(), pc->orig_line);
                  return(false);
               }
            }
         }
      }
      prev = pc;
      pc   = chunk_get_next_nc(pc);
   }

   if (pc == NULL)
   {
      LOG_FMT(LBRDEL, " NULL\n");
      return(false);
   }

   if ((pc->type == CT_BRACE_CLOSE) && (pc->parent_type == CT_IF))
   {
      chunk_t *next = chunk_get_next_ncnl(pc, CNAV_PREPROC);

      prev = chunk_get_prev_ncnl(pc, CNAV_PREPROC);

      if ((next != NULL) && (next->type == CT_ELSE) &&
          ((prev->type == CT_BRACE_CLOSE) || (prev->type == CT_VBRACE_CLOSE)) &&
          (prev->parent_type == CT_IF))
      {
         LOG_FMT(LBRDEL, " - bailed on '%s'[%s] on line %zu due to 'if' and 'else' sequence\n",
                 get_token_name(pc->type), get_token_name(pc->parent_type),
                 pc->orig_line);
         return(false);
      }
   }

   LOG_FMT(LBRDEL, " - end on '%s' on line %zu. if_count=%zu semi_count=%zu\n",
           get_token_name(pc->type), pc->orig_line, if_count, semi_count);

   return((pc->type == CT_BRACE_CLOSE) && (pc->pp_level == bopen->pp_level));
} // can_remove_braces
Example #29
0
static void split_fcn_params(chunk_t *start)
{
   LOG_FUNC_ENTRY();
   LOG_FMT(LSPLIT, "%s(%d): '%s'\n", __func__, __LINE__, start->text());

   // Find the opening function parenthesis
   chunk_t *fpo = start;
   LOG_FMT(LSPLIT, "%s(%d): Find the opening function parenthesis\n", __func__, __LINE__);
   while (  ((fpo = chunk_get_prev(fpo)) != nullptr)
         && fpo->type != CT_FPAREN_OPEN)
   {
      // do nothing
      LOG_FMT(LSPLIT, "%s(%d): '%s', orig_col is %zu, level is %zu\n",
              __func__, __LINE__, fpo->text(), fpo->orig_col, fpo->level);
   }

   chunk_t *pc     = chunk_get_next_ncnl(fpo);
   size_t  min_col = pc->column;

   LOG_FMT(LSPLIT, "    mincol is %zu, max_width is %zu\n",
           min_col, cpd.settings[UO_code_width].u - min_col);

   int cur_width = 0;
   int last_col  = -1;
   LOG_FMT(LSPLIT, "%s(%d):look forward until CT_COMMA or CT_FPAREN_CLOSE\n", __func__, __LINE__);
   while (pc != nullptr)
   {
      LOG_FMT(LSPLIT, "%s(%d): pc->text() '%s', type is %s\n",
              __func__, __LINE__, pc->text(), get_token_name(pc->type));
      if (chunk_is_newline(pc))
      {
         cur_width = 0;
         last_col  = -1;
      }
      else
      {
         if (last_col < 0)
         {
            last_col = pc->column;
            LOG_FMT(LSPLIT, "%s(%d): last_col is %d\n",
                    __func__, __LINE__, last_col);
         }
         cur_width += (pc->column - last_col) + pc->len();
         last_col   = pc->column + pc->len();

         LOG_FMT(LSPLIT, "%s(%d): last_col is %d\n",
                 __func__, __LINE__, last_col);
         if (pc->type == CT_COMMA || pc->type == CT_FPAREN_CLOSE)
         {
            cur_width--;
            LOG_FMT(LSPLIT, "%s(%d): cur_width is %d\n",
                    __func__, __LINE__, cur_width);
            if (  ((last_col - 1) > static_cast<int>(cpd.settings[UO_code_width].u))
               || pc->type == CT_FPAREN_CLOSE)
            {
               break;
            }
         }
      }
      pc = chunk_get_next(pc);
   }

   // back up until the prev is a comma
   chunk_t *prev = pc;
   LOG_FMT(LSPLIT, "  %s(%d): back up until the prev is a comma\n", __func__, __LINE__);
   while ((prev = chunk_get_prev(prev)) != nullptr)
   {
      LOG_FMT(LSPLIT, "%s(%d): pc '%s', pc->level is %zu, prev '%s', prev->type is %s\n",
              __func__, __LINE__, pc->text(), pc->level, prev->text(), get_token_name(prev->type));
      if (chunk_is_newline(prev) || prev->type == CT_COMMA)
      {
         LOG_FMT(LSPLIT, "%s(%d): found at %zu\n",
                 __func__, __LINE__, prev->orig_col);
         break;
      }
      LOG_FMT(LSPLIT, "%s(%d): last_col is %d\n",
              __func__, __LINE__, last_col);
      last_col -= pc->len();
      LOG_FMT(LSPLIT, "%s(%d): last_col is %d\n",
              __func__, __LINE__, last_col);
      if (prev->type == CT_FPAREN_OPEN)
      {
         pc = chunk_get_next(prev);
         if (!cpd.settings[UO_indent_paren_nl].b)
         {
            min_col = pc->brace_level * cpd.settings[UO_indent_columns].u + 1;
            LOG_FMT(LSPLIT, "%s(%d): min_col is %zu\n",
                    __func__, __LINE__, min_col);
            if (cpd.settings[UO_indent_continue].n == 0)
            {
               min_col += cpd.settings[UO_indent_columns].u;
            }
            else
            {
               min_col += abs(cpd.settings[UO_indent_continue].n);
            }
            LOG_FMT(LSPLIT, "%s(%d): min_col is %zu\n",
                    __func__, __LINE__, min_col);
         }

         // Don't split "()"
         if (pc->type != c_token_t(prev->type + 1))
         {
            break;
         }
      }
   }
   if (prev != nullptr && !chunk_is_newline(prev))
   {
      LOG_FMT(LSPLIT, "%s(%d): -- ended on [%s] --\n",
              __func__, __LINE__, get_token_name(prev->type));
      LOG_FMT(LSPLIT, "%s(%d): min_col is %zu\n",
              __func__, __LINE__, min_col);
      pc = chunk_get_next(prev);
      newline_add_before(pc);
      reindent_line(pc, min_col);
      cpd.changes++;
   }
} // split_fcn_params
Example #30
0
LPCSTR STextureParams::FormatString	()
{
	return get_token_name(tfmt_token,fmt);
}