Logo Search packages:      
Sourcecode: uncrustify version File versions

void indent_text ( void   ) 

Change the top-level indentation only by changing the column member in the chunk structures. The level indicator must already be set.

Handle non-brace closures

Handle stuff that can affect the current indent:

  • brace close
  • vbrace open
  • brace open
  • case (immediate)
  • labels (immediate)
  • class colons (immediate)

And some stuff that can't

  • open paren
  • open square
  • assignment
  • return

If there isn't a newline between the open brace and the next item, just indent to wherever the next token is. This covers this sort of stuff: { a++; b--; };

if there is a newline after the '=', just indent one level, otherwise align on the '='. Never update indent_column.

Indent the line if needed

Check for special continuations. Note that some of these could be done as a stack item like everything else

Handle variable definition continuation indenting

Handle the case of a multi-line define w/o anything on the first line (indent_tmp will be 1 or 0)

Definition at line 279 of file indent.cpp.

References chunk_t::brace_level, chunk_get_next_nc(), chunk_get_next_ncnl(), chunk_get_prev_ncnl(), chunk_is_newline_between(), chunk_t::column, chunk_t::column_indent, chunk_t::flags, chunk_t::len, chunk_t::level, chunk_t::orig_line, chunk_t::parent_type, pf_check(), chunk_t::str, and chunk_t::type.

{
   chunk_t            *pc;
   chunk_t            *next;
   chunk_t            *prev       = NULL;
   bool               did_newline = true;
   int                idx;
   int                vardefcol   = 0;
   int                indent_size = cpd.settings[UO_indent_columns].n;
   int                tmp;
   struct parse_frame frm;
   bool               in_preproc = false, was_preproc = false;
   int                indent_column;
   int                cout_col            = 0; // for aligning << stuff
   int                cout_level          = 0; // for aligning << stuff
   int                parent_token_indent = 0;
   int                xml_indent          = 0;
   bool               token_used;

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

   /* dummy top-level entry */
   frm.pse[0].indent     = 1;
   frm.pse[0].indent_tmp = 1;
   frm.pse[0].type       = CT_EOF;

   pc = chunk_get_head();
   while (pc != NULL)
   {
      /* Handle proprocessor transitions */
      was_preproc = in_preproc;
      in_preproc  = (pc->flags & PCF_IN_PREPROC) != 0;

      if (cpd.settings[UO_indent_brace_parent].b)
      {
         parent_token_indent = token_indent(pc->parent_type);
      }

      /* Clean up after a #define */
      if (!in_preproc)
      {
         while ((frm.pse_tos > 0) && frm.pse[frm.pse_tos].in_preproc)
         {
            indent_pse_pop(frm, pc);
         }
      }
      else
      {
         pf_check(&frm, pc);

         if (!was_preproc)
         {
            /* Transition into a preproc by creating a dummy indent */
            frm.level++;
            indent_pse_push(frm, pc);

            frm.pse[frm.pse_tos].indent     = 1 + indent_size;
            frm.pse[frm.pse_tos].indent_tmp = frm.pse[frm.pse_tos].indent;
         }
      }

      if ((cout_col > 0) &&
          (chunk_is_semicolon(pc) ||
           (pc->level < cout_level)))
      {
         cout_col   = 0;
         cout_level = 0;
      }

      /* Check for close XML tags "</..." */
      if (cpd.settings[UO_indent_xml_string].n > 0)
      {
         if (pc->type == CT_STRING)
         {
            if ((pc->len > 4) &&
                (xml_indent > 0) &&
                (pc->str[1] == '<') &&
                (pc->str[2] == '/'))
            {
               xml_indent -= cpd.settings[UO_indent_xml_string].n;
            }
         }
         else
         {
            if (!chunk_is_comment(pc) && !chunk_is_newline(pc))
            {
               xml_indent = 0;
            }
         }
      }

      /**
       * Handle non-brace closures
       */

      token_used = false;
      int old_pse_tos;
      do
      {
         old_pse_tos = frm.pse_tos;

         /* End anything that drops a level
          * REVISIT: not sure about the preproc check
          */
         if (!chunk_is_newline(pc) &&
             !chunk_is_comment(pc) &&
             ((pc->flags & PCF_IN_PREPROC) == 0) &&
             (frm.pse[frm.pse_tos].level > pc->level))
         {
            indent_pse_pop(frm, pc);
         }

         if (frm.pse[frm.pse_tos].level == pc->level)
         {
            /* process virtual braces closes (no text output) */
            if ((pc->type == CT_VBRACE_CLOSE) &&
                (frm.pse[frm.pse_tos].type == CT_VBRACE_OPEN))
            {
               indent_pse_pop(frm, pc);
               frm.level--;
               pc = chunk_get_next(pc);
            }

            /* End any assign operations with a semicolon on the same level */
            if ((frm.pse[frm.pse_tos].type == CT_ASSIGN) &&
                (chunk_is_semicolon(pc) ||
                 (pc->type == CT_COMMA) ||
                 (pc->type == CT_BRACE_OPEN)))
            {
               indent_pse_pop(frm, pc);
            }

            /* End any custom macro-based open/closes */
            if (!token_used &&
                (frm.pse[frm.pse_tos].type == CT_MACRO_OPEN) &&
                (pc->type == CT_MACRO_CLOSE))
            {
               token_used = true;
               indent_pse_pop(frm, pc);
            }

            /* End any CPP class colon crap */
            if ((frm.pse[frm.pse_tos].type == CT_CLASS_COLON) &&
                ((pc->type == CT_BRACE_OPEN) ||
                 chunk_is_semicolon(pc)))
            {
               indent_pse_pop(frm, pc);
            }

            /* a case is ended with another case or a close brace */
            if ((frm.pse[frm.pse_tos].type == CT_CASE) &&
                ((pc->type == CT_BRACE_CLOSE) ||
                 (pc->type == CT_CASE)))
            {
               indent_pse_pop(frm, pc);
            }

            /* a return is ended with a semicolon */
            if ((frm.pse[frm.pse_tos].type == CT_RETURN) &&
                chunk_is_semicolon(pc))
            {
               indent_pse_pop(frm, pc);
            }

            /* an SQL EXEC is ended with a semicolon */
            if ((frm.pse[frm.pse_tos].type == CT_SQL_EXEC) &&
                chunk_is_semicolon(pc))
            {
               indent_pse_pop(frm, pc);
            }

            /* Close out parens and squares */
            if ((frm.pse[frm.pse_tos].type == (pc->type - 1)) &&
                ((pc->type == CT_PAREN_CLOSE) ||
                 (pc->type == CT_SPAREN_CLOSE) ||
                 (pc->type == CT_FPAREN_CLOSE) ||
                 (pc->type == CT_SQUARE_CLOSE) ||
                 (pc->type == CT_ANGLE_CLOSE)))
            {
               indent_pse_pop(frm, pc);
               frm.paren_count--;
            }
         }
      } while (old_pse_tos > frm.pse_tos);

      /* Grab a copy of the current indent */
      indent_column = frm.pse[frm.pse_tos].indent_tmp;

      if (!chunk_is_newline(pc) && !chunk_is_comment(pc))
      {
         LOG_FMT(LINDPC, " -=[ %.*s ]=- top=%d %s %d/%d\n",
                 pc->len, pc->str,
                 frm.pse_tos,
                 get_token_name(frm.pse[frm.pse_tos].type),
                 frm.pse[frm.pse_tos].indent_tmp,
                 frm.pse[frm.pse_tos].indent);
      }

      /**
       * Handle stuff that can affect the current indent:
       *  - brace close
       *  - vbrace open
       *  - brace open
       *  - case         (immediate)
       *  - labels       (immediate)
       *  - class colons (immediate)
       *
       * And some stuff that can't
       *  - open paren
       *  - open square
       *  - assignment
       *  - return
       */

      bool brace_indent = false;
      if ((pc->type == CT_BRACE_CLOSE) || (pc->type == CT_BRACE_OPEN))
      {
         brace_indent = (cpd.settings[UO_indent_braces].b &&
                         (!cpd.settings[UO_indent_braces_no_func].b ||
                          (pc->parent_type != CT_FUNC_DEF)));
      }

      if (pc->type == CT_BRACE_CLOSE)
      {
         if (frm.pse[frm.pse_tos].type == CT_BRACE_OPEN)
         {
            /* Indent the brace to match the open brace */
            indent_column = frm.pse[frm.pse_tos].brace_indent;

            indent_pse_pop(frm, pc);
            frm.level--;
         }
      }
      else if (pc->type == CT_VBRACE_OPEN)
      {
         frm.level++;
         indent_pse_push(frm, pc);

         frm.pse[frm.pse_tos].indent     = frm.pse[frm.pse_tos - 1].indent + indent_size;
         frm.pse[frm.pse_tos].indent_tmp = frm.pse[frm.pse_tos].indent;
         frm.pse[frm.pse_tos].indent_tab = frm.pse[frm.pse_tos].indent;

         /* Always indent on virtual braces */
         indent_column = frm.pse[frm.pse_tos].indent_tmp;
      }
      else if (pc->type == CT_BRACE_OPEN)
      {
         frm.level++;
         indent_pse_push(frm, pc);

         if (frm.paren_count != 0)
         {
            /* We are inside ({ ... }) -- indent one tab from the paren */
            frm.pse[frm.pse_tos].indent = frm.pse[frm.pse_tos - 1].indent_tmp + indent_size;
         }
         else
         {
            /* Use the prev indent level + indent_size. */
            frm.pse[frm.pse_tos].indent = frm.pse[frm.pse_tos - 1].indent + indent_size;

            /* If this brace is part of a statement, bump it out by indent_brace */
            if ((pc->parent_type == CT_IF) ||
                (pc->parent_type == CT_ELSE) ||
                (pc->parent_type == CT_ELSEIF) ||
                (pc->parent_type == CT_DO) ||
                (pc->parent_type == CT_WHILE) ||
                (pc->parent_type == CT_SWITCH) ||
                (pc->parent_type == CT_FOR))
            {
               if (parent_token_indent != 0)
               {
                  frm.pse[frm.pse_tos].indent += parent_token_indent - indent_size;
               }
               else
               {
                  frm.pse[frm.pse_tos].indent += cpd.settings[UO_indent_brace].n;
                  indent_column += cpd.settings[UO_indent_brace].n;
               }
            }
            else if (pc->parent_type == CT_CASE)
            {
               /* An open brace with the parent of case does not indent by default
                * UO_indent_case_brace can be used to indent the brace.
                * So we need to take the CASE indent, subtract off the
                * indent_size that was added above and then add indent_case_brace.
                */
               indent_column = frm.pse[frm.pse_tos - 1].indent - indent_size +
                               cpd.settings[UO_indent_case_brace].n;

               /* Stuff inside the brace still needs to be indented */
               frm.pse[frm.pse_tos].indent     = indent_column + indent_size;
               frm.pse[frm.pse_tos].indent_tmp = frm.pse[frm.pse_tos].indent;
            }
            else if ((pc->parent_type == CT_CLASS) && !cpd.settings[UO_indent_class].b)
            {
               frm.pse[frm.pse_tos].indent -= indent_size;
            }
            else if ((pc->parent_type == CT_NAMESPACE) && !cpd.settings[UO_indent_namespace].b)
            {
               frm.pse[frm.pse_tos].indent -= indent_size;
            }

            frm.pse[frm.pse_tos].indent_tab = frm.pse[frm.pse_tos].indent;
         }

         if ((pc->flags & PCF_DONT_INDENT) != 0)
         {
            frm.pse[frm.pse_tos].indent = pc->column;
            indent_column = pc->column;
         }
         else
         {
            /**
             * If there isn't a newline between the open brace and the next
             * item, just indent to wherever the next token is.
             * This covers this sort of stuff:
             * { a++;
             *   b--; };
             */
            next = chunk_get_next_ncnl(pc);
            if (!chunk_is_newline_between(pc, next))
            {
               frm.pse[frm.pse_tos].indent = next->column;
            }
            frm.pse[frm.pse_tos].indent_tmp = frm.pse[frm.pse_tos].indent;
            frm.pse[frm.pse_tos].open_line  = pc->orig_line;

            /* Update the indent_column if needed */
            if (brace_indent || (parent_token_indent != 0))
            {
               indent_column = frm.pse[frm.pse_tos].indent_tmp;
            }
         }

         /* Save the brace indent */
         frm.pse[frm.pse_tos].brace_indent = indent_column;
      }
      else if (pc->type == CT_SQL_END)
      {
         if (frm.pse[frm.pse_tos].type == CT_SQL_BEGIN)
         {
            indent_pse_pop(frm, pc);
            frm.level--;
            indent_column = frm.pse[frm.pse_tos].indent_tmp;
         }
      }
      else if (pc->type == CT_SQL_BEGIN)
      {
         frm.level++;
         indent_pse_push(frm, pc);
         frm.pse[frm.pse_tos].indent     = frm.pse[frm.pse_tos - 1].indent + indent_size;
         frm.pse[frm.pse_tos].indent_tmp = frm.pse[frm.pse_tos].indent;
         frm.pse[frm.pse_tos].indent_tab = frm.pse[frm.pse_tos].indent;
      }
      else if (pc->type == CT_SQL_EXEC)
      {
         frm.level++;
         indent_pse_push(frm, pc);
         frm.pse[frm.pse_tos].indent     = frm.pse[frm.pse_tos - 1].indent + indent_size;
         frm.pse[frm.pse_tos].indent_tmp = frm.pse[frm.pse_tos].indent;
      }
      else if (pc->type == CT_MACRO_OPEN)
      {
         frm.level++;
         indent_pse_push(frm, pc);
         frm.pse[frm.pse_tos].indent     = frm.pse[frm.pse_tos - 1].indent + indent_size;
         frm.pse[frm.pse_tos].indent_tmp = frm.pse[frm.pse_tos].indent;
         frm.pse[frm.pse_tos].indent_tab = frm.pse[frm.pse_tos].indent;
      }
      else if (pc->type == CT_MACRO_ELSE)
      {
         if (frm.pse[frm.pse_tos].type == CT_MACRO_OPEN)
         {
            indent_column = frm.pse[frm.pse_tos - 1].indent;
         }
      }
      else if (pc->type == CT_CASE)
      {
         /* Start a case - indent UO_indent_switch_case from the switch level */
         tmp = frm.pse[frm.pse_tos].indent + cpd.settings[UO_indent_switch_case].n;

         indent_pse_push(frm, pc);

         frm.pse[frm.pse_tos].indent     = tmp;
         frm.pse[frm.pse_tos].indent_tmp = tmp - indent_size;
         frm.pse[frm.pse_tos].indent_tab = tmp;

         /* Always set on case statements */
         indent_column = frm.pse[frm.pse_tos].indent_tmp;
      }
      else if (pc->type == CT_LABEL)
      {
         /* Labels get sent to the left or backed up */
         if (cpd.settings[UO_indent_label].n > 0)
         {
            indent_column = cpd.settings[UO_indent_label].n;
         }
         else
         {
            indent_column = frm.pse[frm.pse_tos].indent +
                            cpd.settings[UO_indent_label].n;
         }
      }
      else if (pc->type == CT_PRIVATE)
      {
         /* Labels get sent to the left or backed up */
         if (cpd.settings[UO_indent_access_spec].n > 0)
         {
            indent_column = cpd.settings[UO_indent_access_spec].n;
         }
         else
         {
            indent_column = frm.pse[frm.pse_tos].indent +
                            cpd.settings[UO_indent_access_spec].n;
         }
      }
      else if (pc->type == CT_CLASS_COLON)
      {
         /* just indent one level */
         indent_pse_push(frm, pc);
         frm.pse[frm.pse_tos].indent     = frm.pse[frm.pse_tos - 1].indent_tmp + indent_size;
         frm.pse[frm.pse_tos].indent_tmp = frm.pse[frm.pse_tos].indent;
         frm.pse[frm.pse_tos].indent_tab = frm.pse[frm.pse_tos].indent;

         indent_column = frm.pse[frm.pse_tos].indent_tmp;

         if (cpd.settings[UO_indent_class_colon].b)
         {
            prev = chunk_get_prev(pc);
            if (chunk_is_newline(prev))
            {
               frm.pse[frm.pse_tos].indent += 2;
               /* don't change indent of current line */
            }
         }
      }
      else if ((pc->type == CT_PAREN_OPEN) ||
               (pc->type == CT_SPAREN_OPEN) ||
               (pc->type == CT_FPAREN_OPEN) ||
               (pc->type == CT_SQUARE_OPEN) ||
               (pc->type == CT_ANGLE_OPEN))
      {
         /* Open parens and squares - never update indent_column */
         indent_pse_push(frm, pc);
         frm.pse[frm.pse_tos].indent = pc->column + pc->len;

         if (cpd.settings[UO_indent_func_call_param].b &&
             (pc->type == CT_FPAREN_OPEN) &&
             (pc->parent_type == CT_FUNC_CALL))
         {
            frm.pse[frm.pse_tos].indent = frm.pse[frm.pse_tos - 1].indent + indent_size;
         }

         if ((chunk_is_str(pc, "(", 1) && !cpd.settings[UO_indent_paren_nl].b) ||
             (chunk_is_str(pc, "[", 1) && !cpd.settings[UO_indent_square_nl].b))
         {
            next = chunk_get_next_nc(pc);
            if (chunk_is_newline(next))
            {
               int sub = 1;
               if (frm.pse[frm.pse_tos - 1].type == CT_ASSIGN)
               {
                  sub = 2;
               }
               frm.pse[frm.pse_tos].indent = frm.pse[frm.pse_tos - sub].indent + indent_size;
            }
         }
         frm.pse[frm.pse_tos].indent_tmp = frm.pse[frm.pse_tos].indent;
         frm.paren_count++;
      }
      else if (pc->type == CT_ASSIGN)
      {
         /**
          * if there is a newline after the '=', just indent one level,
          * otherwise align on the '='.
          * Never update indent_column.
          */
         next = chunk_get_next(pc);
         if (next != NULL)
         {
            indent_pse_push(frm, pc);
            if (chunk_is_newline(next))
            {
               frm.pse[frm.pse_tos].indent = frm.pse[frm.pse_tos - 1].indent_tmp + indent_size;
            }
            else
            {
               frm.pse[frm.pse_tos].indent = pc->column + pc->len + 1;
            }
            frm.pse[frm.pse_tos].indent_tmp = frm.pse[frm.pse_tos].indent;
         }
      }
      else if (pc->type == CT_RETURN)
      {
         /* don't count returns inside a () or [] */
         if (pc->level == pc->brace_level)
         {
            indent_pse_push(frm, pc);
            frm.pse[frm.pse_tos].indent     = frm.pse[frm.pse_tos - 1].indent + pc->len + 1;
            frm.pse[frm.pse_tos].indent_tmp = frm.pse[frm.pse_tos - 1].indent;
         }
      }
      else if (chunk_is_str(pc, "<<", 2))
      {
         if (cout_col == 0)
         {
            cout_col   = pc->column;
            cout_level = pc->level;
         }
      }
      else
      {
         /* anything else? */
      }


      /**
       * Indent the line if needed
       */
      if (did_newline && !chunk_is_newline(pc) && (pc->len != 0))
      {
         pc->column_indent = frm.pse[frm.pse_tos].indent_tab;

         LOG_FMT(LINDENT2, "%s: %d] %d for %.*s\n",
                 __func__, pc->orig_line, pc->column_indent, pc->len, pc->str);


         /**
          * Check for special continuations.
          * Note that some of these could be done as a stack item like
          * everything else
          */

         prev = chunk_get_prev_ncnl(pc);
         if ((pc->type == CT_MEMBER) ||
             (pc->type == CT_DC_MEMBER) ||
             ((prev != NULL) &&
              ((prev->type == CT_MEMBER) ||
               (prev->type == CT_DC_MEMBER))))
         {
            tmp = cpd.settings[UO_indent_member].n + indent_column;
            LOG_FMT(LINDENT, "%s: %d] member => %d\n",
                    __func__, pc->orig_line, tmp);
            reindent_line(pc, tmp);
         }
         else if (chunk_is_str(pc, "<<", 2) && (cout_col > 0))
         {
            LOG_FMT(LINDENT, "%s: %d] cout_col => %d\n",
                    __func__, pc->orig_line, cout_col);
            reindent_line(pc, cout_col);
         }
         else if ((vardefcol > 0) &&
                  (pc->type == CT_WORD) &&
                  ((pc->flags & PCF_VAR_DEF) != 0) &&
                  (prev != NULL) && (prev->type == CT_COMMA))
         {
            LOG_FMT(LINDENT, "%s: %d] Vardefcol => %d\n",
                    __func__, pc->orig_line, vardefcol);
            reindent_line(pc, vardefcol);
         }
         else if ((pc->type == CT_STRING) && (prev->type == CT_STRING) &&
                  cpd.settings[UO_indent_align_string].b)
         {
            tmp = (xml_indent != 0) ? xml_indent : prev->column;

            LOG_FMT(LINDENT, "%s: %d] String => %d\n",
                    __func__, pc->orig_line, tmp);
            reindent_line(pc, tmp);
         }
         else if (chunk_is_comment(pc))
         {
            LOG_FMT(LINDENT, "%s: %d] comment => %d\n",
                    __func__, pc->orig_line, frm.pse[frm.pse_tos].indent_tmp);
            indent_comment(pc, frm.pse[frm.pse_tos].indent_tmp);
         }
         else if (pc->type == CT_PREPROC)
         {
            /* Preprocs are always in column 1. See indent_preproc() */
            if (pc->column != 1)
            {
               reindent_line(pc, 1);
            }
         }
         else
         {
            if (pc->column != indent_column)
            {
               LOG_FMT(LINDENT, "%s: %d] indent => %d [%.*s]\n",
                       __func__, pc->orig_line, indent_column, pc->len, pc->str);
               reindent_line(pc, indent_column);
            }
         }
         did_newline = false;
      }

      /**
       * Handle variable definition continuation indenting
       */
      if ((pc->type == CT_WORD) &&
          ((pc->flags & PCF_IN_FCN_DEF) == 0) &&
          ((pc->flags & PCF_VAR_1ST_DEF) == PCF_VAR_1ST_DEF))
      {
         vardefcol = pc->column;
      }
      if (chunk_is_semicolon(pc) ||
          ((pc->type == CT_BRACE_OPEN) && (pc->parent_type == CT_FUNCTION)))
      {
         vardefcol = 0;
      }

      /* if we hit a newline, reset indent_tmp */
      if (chunk_is_newline(pc) ||
          (pc->type == CT_COMMENT_MULTI) ||
          (pc->type == CT_COMMENT_CPP))
      {
         frm.pse[frm.pse_tos].indent_tmp = frm.pse[frm.pse_tos].indent;

         /**
          * Handle the case of a multi-line #define w/o anything on the
          * first line (indent_tmp will be 1 or 0)
          */
         if ((pc->type == CT_NL_CONT) &&
             (frm.pse[frm.pse_tos].indent_tmp <= indent_size))
         {
            frm.pse[frm.pse_tos].indent_tmp = indent_size + 1;
         }

         /* Get ready to indent the next item */
         did_newline = true;
      }

      /* Check for open XML tags "</..." */
      if (cpd.settings[UO_indent_xml_string].n > 0)
      {
         if (pc->type == CT_STRING)
         {
            if ((pc->len > 4) &&
                (pc->str[1] == '<') &&
                (pc->str[2] != '/') &&
                (pc->str[pc->len - 3] != '/'))
            {
               if (xml_indent <= 0)
               {
                  xml_indent = pc->column;
               }
               xml_indent += cpd.settings[UO_indent_xml_string].n;
            }
         }
      }

      if (!chunk_is_comment(pc) && !chunk_is_newline(pc))
      {
         prev = pc;
      }
      pc = chunk_get_next(pc);
   }

   /* Throw out any stuff inside a preprocessor - no need to warn */
   while ((frm.pse_tos > 0) && frm.pse[frm.pse_tos].in_preproc)
   {
      indent_pse_pop(frm, pc);
   }

   for (idx = 1; idx <= frm.pse_tos; idx++)
   {
      LOG_FMT(LWARN, "%s:%d Unmatched %s\n",
              cpd.filename, frm.pse[idx].open_line,
              get_token_name(frm.pse[idx].type));
      cpd.error_count++;
   }
}


Generated by  Doxygen 1.6.0   Back to index