PageRenderTime 53ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/tests/input/c/indent.cpp

http://github.com/bengardner/uncrustify
C++ | 1084 lines | 718 code | 100 blank | 266 comment | 270 complexity | e5feb46d62e0c7930e18a992d9128d34 MD5 | raw file
Possible License(s): GPL-2.0
  1. /**
  2. * @file indent.cpp
  3. * Does all the indenting stuff.
  4. *
  5. * $Id: indent.cpp 548 2006-10-21 02:31:55Z bengardner $
  6. */
  7. #include "uncrustify_types.h"
  8. #include "chunk_list.h"
  9. #include "prototypes.h"
  10. #include <cstdio>
  11. #include <cstdlib>
  12. #include <cstring>
  13. #include <cerrno>
  14. #include <cctype>
  15. /**
  16. * General indenting approach:
  17. * Indenting levels are put into a stack.
  18. *
  19. * The stack entries contain:
  20. * - opening type
  21. * - brace column
  22. * - continuation column
  23. *
  24. * Items that start a new stack item:
  25. * - preprocessor (new parse frame)
  26. * - Brace Open (Virtual brace also)
  27. * - Paren, Square, Angle open
  28. * - Assignments
  29. * - C++ '<<' operator (ie, cout << "blah")
  30. * - case
  31. * - class colon
  32. * - return
  33. * - types
  34. * - any other continued statement
  35. *
  36. * Note that the column of items marked 'PCF_WAS_ALIGNED' is not changed.
  37. *
  38. * For an open brace:
  39. * - indent increases by indent_columns
  40. * - if part of if/else/do/while/switch/etc, an extra indent may be applied
  41. * - if in a paren, then cont-col is set to column + 1, ie "({ some code })"
  42. *
  43. * Open paren/square/angle:
  44. * cont-col is set to the column of the item after the open paren, unless
  45. * followed by a newline, then it is set to (brace-col + indent_columns).
  46. * Examples:
  47. * a_really_long_funcion_name(
  48. * param1, param2);
  49. * a_really_long_funcion_name(param1,
  50. * param2);
  51. *
  52. * Assignments:
  53. * Assignments are continued aligned with the first item after the assignment,
  54. * unless the assign is followed by a newline.
  55. * Examples:
  56. * some.variable = asdf + asdf +
  57. * asdf;
  58. * some.variable =
  59. * asdf + asdf + asdf;
  60. *
  61. * C++ << operator:
  62. * Handled the same as assignment.
  63. * Examples:
  64. * cout << "this is test number: "
  65. * << test_number;
  66. *
  67. * case:
  68. * Started with case or default.
  69. * Terminated with close brace at level or another case or default.
  70. * Special indenting according to various rules.
  71. * - indent of case label
  72. * - indent of case body
  73. * - how to handle optional braces
  74. * Examples:
  75. * {
  76. * case x: {
  77. * a++;
  78. * break;
  79. * }
  80. * case y:
  81. * b--;
  82. * break;
  83. * default:
  84. * c++;
  85. * break;
  86. * }
  87. *
  88. * Class colon:
  89. * Indent continuation by indent_columns:
  90. * class my_class :
  91. * baseclass1,
  92. * baseclass2
  93. * {
  94. *
  95. * Return: same as assignemts
  96. * If the return statement is not fully paren'd, then the indent continues at
  97. * the column of the item after the return. If it is paren'd, then the paren
  98. * rules apply.
  99. * return somevalue +
  100. * othervalue;
  101. *
  102. * Type: pretty much the same as assignments
  103. * Examples:
  104. * int foo,
  105. * bar,
  106. * baz;
  107. *
  108. * Any other continued item:
  109. * There shouldn't be anything not covered by the above cases, but any other
  110. * continued item is indented by indent_columns:
  111. * Example:
  112. * somereallycrazylongname.with[lotsoflongstuff].
  113. * thatreallyannoysme.whenIhavetomaintain[thecode] = 3;
  114. */
  115. static void indent_comment(chunk_t *pc, int col);
  116. void indent_to_column(chunk_t *pc, int column)
  117. {
  118. if (column < pc->column)
  119. {
  120. column = pc->column;
  121. }
  122. reindent_line(pc, column);
  123. }
  124. /**
  125. * Changes the initial indent for a line to the given column
  126. *
  127. * @param pc The chunk at the start of the line
  128. * @param column The desired column
  129. */
  130. void reindent_line(chunk_t *pc, int column)
  131. {
  132. int col_delta;
  133. int min_col;
  134. LOG_FMT(LINDLINE, "%s: %d] col %d on %.*s [%s] => %d\n",
  135. __func__, pc->orig_line, pc->column, pc->len, pc->str,
  136. get_token_name(pc->type), column);
  137. if (column == pc->column)
  138. {
  139. return;
  140. }
  141. col_delta = column - pc->column;
  142. pc->column = column;
  143. min_col = pc->column;
  144. do
  145. {
  146. min_col += pc->len;
  147. pc = chunk_get_next(pc);
  148. if (pc != NULL)
  149. {
  150. if (chunk_is_comment(pc))
  151. {
  152. pc->column = pc->orig_col;
  153. if (pc->column < min_col)
  154. {
  155. pc->column = min_col + 1;
  156. }
  157. LOG_FMT(LINDLINE, "%s: set comment on line %d to col %d (orig %d)\n",
  158. __func__, pc->orig_line, pc->column, pc->orig_col);
  159. }
  160. else
  161. {
  162. pc->column += col_delta;
  163. if (pc->column < min_col)
  164. {
  165. pc->column = min_col;
  166. }
  167. }
  168. }
  169. } while ((pc != NULL) && (pc->nl_count == 0));
  170. }
  171. /**
  172. * Starts a new entry
  173. *
  174. * @param frm The parse frame
  175. * @param pc The chunk causing the push
  176. */
  177. static void indent_pse_push(struct parse_frame& frm, chunk_t *pc)
  178. {
  179. static int ref = 0;
  180. /* check the stack depth */
  181. if (frm.pse_tos < (int)ARRAY_SIZE(frm.pse))
  182. {
  183. /* Bump up the index and initialize it */
  184. frm.pse_tos++;
  185. memset(&frm.pse[frm.pse_tos], 0, sizeof(frm.pse[frm.pse_tos]));
  186. LOG_FMT(LINDPSE, "%4d] OPEN [%d,%s] level=%d\n",
  187. pc->orig_line, frm.pse_tos, get_token_name(pc->type), pc->level);
  188. frm.pse[frm.pse_tos].type = pc->type;
  189. frm.pse[frm.pse_tos].level = pc->level;
  190. frm.pse[frm.pse_tos].open_line = pc->orig_line;
  191. frm.pse[frm.pse_tos].ref = ++ref;
  192. frm.pse[frm.pse_tos].in_preproc = (pc->flags & PCF_IN_PREPROC) != 0;
  193. }
  194. }
  195. /**
  196. * Removes the top entry
  197. *
  198. * @param frm The parse frame
  199. * @param pc The chunk causing the push
  200. */
  201. static void indent_pse_pop(struct parse_frame& frm, chunk_t *pc)
  202. {
  203. /* Bump up the index and initialize it */
  204. if (frm.pse_tos > 0)
  205. {
  206. if (pc != NULL)
  207. {
  208. LOG_FMT(LINDPSE, "%4d] CLOSE [%d,%s] on %s, started on line %d, level=%d/%d\n",
  209. pc->orig_line, frm.pse_tos,
  210. get_token_name(frm.pse[frm.pse_tos].type),
  211. get_token_name(pc->type),
  212. frm.pse[frm.pse_tos].open_line,
  213. frm.pse[frm.pse_tos].level,
  214. pc->level);
  215. }
  216. else
  217. {
  218. LOG_FMT(LINDPSE, " EOF] CLOSE [%d,%s], started on line %d\n",
  219. frm.pse_tos, get_token_name(frm.pse[frm.pse_tos].type),
  220. frm.pse[frm.pse_tos].open_line);
  221. }
  222. frm.pse_tos--;
  223. }
  224. }
  225. static int token_indent(c_token_t type)
  226. {
  227. switch (type)
  228. {
  229. case CT_IF:
  230. case CT_DO:
  231. return(3);
  232. case CT_FOR:
  233. case CT_ELSE: // wacky, but that's what is wanted
  234. return(4);
  235. case CT_WHILE:
  236. return(6);
  237. case CT_SWITCH:
  238. return(7);
  239. case CT_ELSEIF:
  240. return(8);
  241. default:
  242. return(0); //cpd.settings[UO_indent_braces].n;
  243. }
  244. }
  245. /**
  246. * Change the top-level indentation only by changing the column member in
  247. * the chunk structures.
  248. * The level indicator must already be set.
  249. */
  250. void indent_text(void)
  251. {
  252. chunk_t *pc;
  253. chunk_t *next;
  254. chunk_t *prev = NULL;
  255. bool did_newline = true;
  256. int idx;
  257. int vardefcol = 0;
  258. int indent_size = cpd.settings[UO_indent_columns].n;
  259. int tmp;
  260. struct parse_frame frm;
  261. bool in_preproc = false, was_preproc = false;
  262. int indent_column;
  263. int cout_col = 0; // for aligning << stuff
  264. int cout_level = 0; // for aligning << stuff
  265. int parent_token_indent = 0;
  266. memset(&frm, 0, sizeof(frm));
  267. /* dummy top-level entry */
  268. frm.pse[0].indent = 1;
  269. frm.pse[0].indent_tmp = 1;
  270. frm.pse[0].type = CT_EOF;
  271. pc = chunk_get_head();
  272. while (pc != NULL)
  273. {
  274. /* Handle proprocessor transitions */
  275. was_preproc = in_preproc;
  276. in_preproc = (pc->flags & PCF_IN_PREPROC) != 0;
  277. if (cpd.settings[UO_indent_brace_parent].b)
  278. {
  279. parent_token_indent = token_indent(pc->parent_type);
  280. }
  281. /* Clean up after a #define */
  282. if (!in_preproc)
  283. {
  284. while ((frm.pse_tos > 0) && frm.pse[frm.pse_tos].in_preproc)
  285. {
  286. indent_pse_pop(frm, pc);
  287. }
  288. }
  289. else
  290. {
  291. pf_check(&frm, pc);
  292. if (!was_preproc)
  293. {
  294. /* Transition into a preproc by creating a dummy indent */
  295. frm.level++;
  296. indent_pse_push(frm, pc);
  297. frm.pse[frm.pse_tos].indent = 1 + indent_size;
  298. frm.pse[frm.pse_tos].indent_tmp = frm.pse[frm.pse_tos].indent;
  299. }
  300. }
  301. if ((cout_col > 0) &&
  302. (chunk_is_semicolon(pc) ||
  303. (pc->level < cout_level)))
  304. {
  305. cout_col = 0;
  306. cout_level = 0;
  307. }
  308. /**
  309. * Handle non-brace closures
  310. */
  311. int old_pse_tos;
  312. do
  313. {
  314. old_pse_tos = frm.pse_tos;
  315. /* End anything that drops a level
  316. * REVISIT: not sure about the preproc check
  317. */
  318. if (!chunk_is_newline(pc) &&
  319. !chunk_is_comment(pc) &&
  320. ((pc->flags & PCF_IN_PREPROC) == 0) &&
  321. (frm.pse[frm.pse_tos].level > pc->level))
  322. {
  323. indent_pse_pop(frm, pc);
  324. }
  325. if (frm.pse[frm.pse_tos].level == pc->level)
  326. {
  327. /* process virtual braces closes (no text output) */
  328. if ((pc->type == CT_VBRACE_CLOSE) &&
  329. (frm.pse[frm.pse_tos].type == CT_VBRACE_OPEN))
  330. {
  331. indent_pse_pop(frm, pc);
  332. frm.level--;
  333. pc = chunk_get_next(pc);
  334. }
  335. /* End any assign operations with a semicolon on the same level */
  336. if ((frm.pse[frm.pse_tos].type == CT_ASSIGN) &&
  337. (chunk_is_semicolon(pc) ||
  338. (pc->type == CT_COMMA) ||
  339. (pc->type == CT_BRACE_OPEN)))
  340. {
  341. indent_pse_pop(frm, pc);
  342. }
  343. /* End any CPP class colon crap */
  344. if ((frm.pse[frm.pse_tos].type == CT_CLASS_COLON) &&
  345. ((pc->type == CT_BRACE_OPEN) ||
  346. chunk_is_semicolon(pc)))
  347. {
  348. indent_pse_pop(frm, pc);
  349. }
  350. /* a case is ended with another case or a close brace */
  351. if ((frm.pse[frm.pse_tos].type == CT_CASE) &&
  352. ((pc->type == CT_BRACE_CLOSE) ||
  353. (pc->type == CT_CASE)))
  354. {
  355. indent_pse_pop(frm, pc);
  356. }
  357. /* a return is ended with a semicolon */
  358. if ((frm.pse[frm.pse_tos].type == CT_RETURN) &&
  359. chunk_is_semicolon(pc))
  360. {
  361. indent_pse_pop(frm, pc);
  362. }
  363. /* Close out parens and squares */
  364. if ((frm.pse[frm.pse_tos].type == (pc->type - 1)) &&
  365. ((pc->type == CT_PAREN_CLOSE) ||
  366. (pc->type == CT_SPAREN_CLOSE) ||
  367. (pc->type == CT_FPAREN_CLOSE) ||
  368. (pc->type == CT_SQUARE_CLOSE) ||
  369. (pc->type == CT_ANGLE_CLOSE)))
  370. {
  371. indent_pse_pop(frm, pc);
  372. frm.paren_count--;
  373. }
  374. }
  375. } while (old_pse_tos > frm.pse_tos);
  376. /* Grab a copy of the current indent */
  377. indent_column = frm.pse[frm.pse_tos].indent_tmp;
  378. if (!chunk_is_newline(pc) && !chunk_is_comment(pc))
  379. {
  380. LOG_FMT(LINDPC, " -=[ %.*s ]=- top=%d %s %d/%d\n",
  381. pc->len, pc->str,
  382. frm.pse_tos,
  383. get_token_name(frm.pse[frm.pse_tos].type),
  384. frm.pse[frm.pse_tos].indent_tmp,
  385. frm.pse[frm.pse_tos].indent);
  386. }
  387. /**
  388. * Handle stuff that can affect the current indent:
  389. * - brace close
  390. * - vbrace open
  391. * - brace open
  392. * - case (immediate)
  393. * - labels (immediate)
  394. * - class colons (immediate)
  395. *
  396. * And some stuff that can't
  397. * - open paren
  398. * - open square
  399. * - assignment
  400. * - return
  401. */
  402. if (pc->type == CT_BRACE_CLOSE)
  403. {
  404. if (frm.pse[frm.pse_tos].type == CT_BRACE_OPEN)
  405. {
  406. indent_pse_pop(frm, pc);
  407. frm.level--;
  408. /* Update the indent_column if needed */
  409. if (!cpd.settings[UO_indent_braces].b &&
  410. (parent_token_indent == 0))
  411. {
  412. indent_column = frm.pse[frm.pse_tos].indent_tmp;
  413. }
  414. if ((pc->parent_type == CT_IF) ||
  415. (pc->parent_type == CT_ELSE) ||
  416. (pc->parent_type == CT_ELSEIF) ||
  417. (pc->parent_type == CT_DO) ||
  418. (pc->parent_type == CT_WHILE) ||
  419. (pc->parent_type == CT_SWITCH) ||
  420. (pc->parent_type == CT_FOR))
  421. {
  422. indent_column += cpd.settings[UO_indent_brace].n;
  423. }
  424. }
  425. }
  426. else if (pc->type == CT_VBRACE_OPEN)
  427. {
  428. frm.level++;
  429. indent_pse_push(frm, pc);
  430. frm.pse[frm.pse_tos].indent = frm.pse[frm.pse_tos - 1].indent + indent_size;
  431. frm.pse[frm.pse_tos].indent_tmp = frm.pse[frm.pse_tos].indent;
  432. /* Always indent on virtual braces */
  433. indent_column = frm.pse[frm.pse_tos].indent_tmp;
  434. }
  435. else if (pc->type == CT_BRACE_OPEN)
  436. {
  437. frm.level++;
  438. indent_pse_push(frm, pc);
  439. if (frm.paren_count != 0)
  440. {
  441. /* We are inside ({ ... }) -- indent one tab from the paren */
  442. frm.pse[frm.pse_tos].indent = frm.pse[frm.pse_tos - 1].indent_tmp + indent_size;
  443. }
  444. else
  445. {
  446. /* Use the prev indent level + indent_size. */
  447. frm.pse[frm.pse_tos].indent = frm.pse[frm.pse_tos - 1].indent + indent_size;
  448. /* If this brace is part of a statement, bump it out by indent_brace */
  449. if ((pc->parent_type == CT_IF) ||
  450. (pc->parent_type == CT_ELSE) ||
  451. (pc->parent_type == CT_ELSEIF) ||
  452. (pc->parent_type == CT_DO) ||
  453. (pc->parent_type == CT_WHILE) ||
  454. (pc->parent_type == CT_SWITCH) ||
  455. (pc->parent_type == CT_FOR))
  456. {
  457. if (parent_token_indent != 0)
  458. {
  459. frm.pse[frm.pse_tos].indent += parent_token_indent - indent_size;
  460. }
  461. else
  462. {
  463. frm.pse[frm.pse_tos].indent += cpd.settings[UO_indent_brace].n;
  464. indent_column += cpd.settings[UO_indent_brace].n;
  465. }
  466. }
  467. else if (pc->parent_type == CT_CASE)
  468. {
  469. /* The indent_case_brace setting affects the parent CT_CASE */
  470. frm.pse[frm.pse_tos].indent_tmp += cpd.settings[UO_indent_case_brace].n;
  471. frm.pse[frm.pse_tos].indent += cpd.settings[UO_indent_case_brace].n;
  472. }
  473. else if ((pc->parent_type == CT_CLASS) && !cpd.settings[UO_indent_class].b)
  474. {
  475. frm.pse[frm.pse_tos].indent -= indent_size;
  476. }
  477. else if ((pc->parent_type == CT_NAMESPACE) && !cpd.settings[UO_indent_namespace].b)
  478. {
  479. frm.pse[frm.pse_tos].indent -= indent_size;
  480. }
  481. }
  482. if ((pc->flags & PCF_DONT_INDENT) != 0)
  483. {
  484. frm.pse[frm.pse_tos].indent = pc->column;
  485. indent_column = pc->column;
  486. }
  487. else
  488. {
  489. /**
  490. * If there isn't a newline between the open brace and the next
  491. * item, just indent to wherever the next token is.
  492. * This covers this sort of stuff:
  493. * { a++;
  494. * b--; };
  495. */
  496. next = chunk_get_next_ncnl(pc);
  497. if (!chunk_is_newline_between(pc, next))
  498. {
  499. frm.pse[frm.pse_tos].indent = next->column;
  500. }
  501. frm.pse[frm.pse_tos].indent_tmp = frm.pse[frm.pse_tos].indent;
  502. frm.pse[frm.pse_tos].open_line = pc->orig_line;
  503. /* Update the indent_column if needed */
  504. if (cpd.settings[UO_indent_braces].n ||
  505. (parent_token_indent != 0))
  506. {
  507. indent_column = frm.pse[frm.pse_tos].indent_tmp;
  508. }
  509. }
  510. }
  511. else if (pc->type == CT_CASE)
  512. {
  513. /* Start a case - indent UO_indent_switch_case from the switch level */
  514. tmp = frm.pse[frm.pse_tos].indent + cpd.settings[UO_indent_switch_case].n;
  515. indent_pse_push(frm, pc);
  516. frm.pse[frm.pse_tos].indent = tmp;
  517. frm.pse[frm.pse_tos].indent_tmp = tmp - indent_size;
  518. /* Always set on case statements */
  519. indent_column = frm.pse[frm.pse_tos].indent_tmp;
  520. }
  521. else if (pc->type == CT_LABEL)
  522. {
  523. /* Labels get sent to the left or backed up */
  524. if (cpd.settings[UO_indent_label].n > 0)
  525. {
  526. indent_column = cpd.settings[UO_indent_label].n;
  527. }
  528. else
  529. {
  530. indent_column = frm.pse[frm.pse_tos].indent +
  531. cpd.settings[UO_indent_label].n;
  532. }
  533. }
  534. else if (pc->type == CT_CLASS_COLON)
  535. {
  536. /* just indent one level */
  537. indent_pse_push(frm, pc);
  538. frm.pse[frm.pse_tos].indent = frm.pse[frm.pse_tos - 1].indent_tmp + indent_size;
  539. frm.pse[frm.pse_tos].indent_tmp = frm.pse[frm.pse_tos].indent;
  540. indent_column = frm.pse[frm.pse_tos].indent_tmp;
  541. if (cpd.settings[UO_indent_class_colon].b)
  542. {
  543. prev = chunk_get_prev(pc);
  544. if (chunk_is_newline(prev))
  545. {
  546. frm.pse[frm.pse_tos].indent += 2;
  547. /* don't change indent of current line */
  548. }
  549. }
  550. }
  551. else if ((pc->type == CT_PAREN_OPEN) ||
  552. (pc->type == CT_SPAREN_OPEN) ||
  553. (pc->type == CT_FPAREN_OPEN) ||
  554. (pc->type == CT_SQUARE_OPEN) ||
  555. (pc->type == CT_ANGLE_OPEN))
  556. {
  557. /* Open parens and squares - never update indent_column */
  558. indent_pse_push(frm, pc);
  559. frm.pse[frm.pse_tos].indent = pc->column + pc->len;
  560. if (cpd.settings[UO_indent_func_call_param].b &&
  561. (pc->type == CT_FPAREN_OPEN) &&
  562. (pc->parent_type == CT_FUNC_CALL))
  563. {
  564. frm.pse[frm.pse_tos].indent = frm.pse[frm.pse_tos - 1].indent + indent_size;
  565. }
  566. if ((chunk_is_str(pc, "(", 1) && !cpd.settings[UO_indent_paren_nl].b) ||
  567. (chunk_is_str(pc, "[", 1) && !cpd.settings[UO_indent_square_nl].b))
  568. {
  569. next = chunk_get_next_nc(pc);
  570. if (chunk_is_newline(next))
  571. {
  572. int sub = 1;
  573. if (frm.pse[frm.pse_tos - 1].type == CT_ASSIGN)
  574. {
  575. sub = 2;
  576. }
  577. frm.pse[frm.pse_tos].indent = frm.pse[frm.pse_tos - sub].indent + indent_size;
  578. }
  579. }
  580. frm.pse[frm.pse_tos].indent_tmp = frm.pse[frm.pse_tos].indent;
  581. frm.paren_count++;
  582. }
  583. else if (pc->type == CT_ASSIGN)
  584. {
  585. /**
  586. * if there is a newline after the '=', just indent one level,
  587. * otherwise align on the '='.
  588. * Never update indent_column.
  589. */
  590. next = chunk_get_next(pc);
  591. if (next != NULL)
  592. {
  593. indent_pse_push(frm, pc);
  594. if (chunk_is_newline(next))
  595. {
  596. frm.pse[frm.pse_tos].indent = frm.pse[frm.pse_tos - 1].indent_tmp + indent_size;
  597. }
  598. else
  599. {
  600. frm.pse[frm.pse_tos].indent = pc->column + pc->len + 1;
  601. }
  602. frm.pse[frm.pse_tos].indent_tmp = frm.pse[frm.pse_tos].indent;
  603. }
  604. }
  605. else if (pc->type == CT_RETURN)
  606. {
  607. /* don't count returns inside a () or [] */
  608. if (pc->level == pc->brace_level)
  609. {
  610. indent_pse_push(frm, pc);
  611. frm.pse[frm.pse_tos].indent = frm.pse[frm.pse_tos - 1].indent + pc->len + 1;
  612. frm.pse[frm.pse_tos].indent_tmp = frm.pse[frm.pse_tos - 1].indent;
  613. }
  614. }
  615. else if (chunk_is_str(pc, "<<", 2))
  616. {
  617. if (cout_col == 0)
  618. {
  619. cout_col = pc->column;
  620. cout_level = pc->level;
  621. }
  622. }
  623. else
  624. {
  625. /* anything else? */
  626. }
  627. /**
  628. * Indent the line if needed
  629. */
  630. if (did_newline && !chunk_is_newline(pc) && (pc->len != 0))
  631. {
  632. /**
  633. * Check for special continuations.
  634. * Note that some of these could be done as a stack item like
  635. * everything else
  636. */
  637. prev = chunk_get_prev_ncnl(pc);
  638. if ((pc->type == CT_MEMBER) ||
  639. (pc->type == CT_DC_MEMBER) ||
  640. ((prev != NULL) &&
  641. ((prev->type == CT_MEMBER) ||
  642. (prev->type == CT_DC_MEMBER))))
  643. {
  644. tmp = cpd.settings[UO_indent_member].n + indent_column;
  645. LOG_FMT(LINDENT, "%s: %d] member => %d\n",
  646. __func__, pc->orig_line, tmp);
  647. reindent_line(pc, tmp);
  648. }
  649. else if (chunk_is_str(pc, "<<", 2) && (cout_col > 0))
  650. {
  651. LOG_FMT(LINDENT, "%s: %d] cout_col => %d\n",
  652. __func__, pc->orig_line, cout_col);
  653. reindent_line(pc, cout_col);
  654. }
  655. else if ((vardefcol > 0) &&
  656. (pc->type == CT_WORD) &&
  657. ((pc->flags & PCF_VAR_DEF) != 0) &&
  658. (prev != NULL) && (prev->type == CT_COMMA))
  659. {
  660. LOG_FMT(LINDENT, "%s: %d] Vardefcol => %d\n",
  661. __func__, pc->orig_line, vardefcol);
  662. reindent_line(pc, vardefcol);
  663. }
  664. else if ((pc->type == CT_STRING) && (prev->type == CT_STRING) &&
  665. cpd.settings[UO_indent_align_string].b)
  666. {
  667. LOG_FMT(LINDENT, "%s: %d] String => %d\n",
  668. __func__, pc->orig_line, prev->column);
  669. reindent_line(pc, prev->column);
  670. }
  671. else if (chunk_is_comment(pc))
  672. {
  673. LOG_FMT(LINDENT, "%s: %d] comment => %d\n",
  674. __func__, pc->orig_line, frm.pse[frm.pse_tos].indent_tmp);
  675. indent_comment(pc, frm.pse[frm.pse_tos].indent_tmp);
  676. }
  677. else if (pc->type == CT_PREPROC)
  678. {
  679. /* Preprocs are always in column 1. See indent_preproc() */
  680. if (pc->column != 1)
  681. {
  682. reindent_line(pc, 1);
  683. }
  684. }
  685. else
  686. {
  687. if (pc->column != indent_column)
  688. {
  689. LOG_FMT(LINDENT, "%s: %d] indent => %d [%.*s]\n",
  690. __func__, pc->orig_line, indent_column, pc->len, pc->str);
  691. reindent_line(pc, indent_column);
  692. }
  693. }
  694. did_newline = false;
  695. }
  696. /**
  697. * Handle variable definition continuation indenting
  698. */
  699. if ((pc->type == CT_WORD) &&
  700. ((pc->flags & PCF_IN_FCN_DEF) == 0) &&
  701. ((pc->flags & PCF_VAR_1ST_DEF) == PCF_VAR_1ST_DEF))
  702. {
  703. vardefcol = pc->column;
  704. }
  705. if (chunk_is_semicolon(pc) ||
  706. ((pc->type == CT_BRACE_OPEN) && (pc->parent_type == CT_FUNCTION)))
  707. {
  708. vardefcol = 0;
  709. }
  710. /* if we hit a newline, reset indent_tmp */
  711. if (chunk_is_newline(pc) ||
  712. (pc->type == CT_COMMENT_MULTI) ||
  713. (pc->type == CT_COMMENT_CPP))
  714. {
  715. frm.pse[frm.pse_tos].indent_tmp = frm.pse[frm.pse_tos].indent;
  716. /**
  717. * Handle the case of a multi-line #define w/o anything on the
  718. * first line (indent_tmp will be 1 or 0)
  719. */
  720. if ((pc->type == CT_NL_CONT) &&
  721. (frm.pse[frm.pse_tos].indent_tmp <= indent_size))
  722. {
  723. frm.pse[frm.pse_tos].indent_tmp = indent_size + 1;
  724. }
  725. /* Get ready to indent the next item */
  726. did_newline = true;
  727. }
  728. if (!chunk_is_comment(pc) && !chunk_is_newline(pc))
  729. {
  730. prev = pc;
  731. }
  732. pc = chunk_get_next(pc);
  733. }
  734. /* Throw out any stuff inside a preprocessor - no need to warn */
  735. while ((frm.pse_tos > 0) && frm.pse[frm.pse_tos].in_preproc)
  736. {
  737. indent_pse_pop(frm, pc);
  738. }
  739. for (idx = 1; idx <= frm.pse_tos; idx++)
  740. {
  741. LOG_FMT(LWARN, "%s:%d Unmatched %s\n",
  742. cpd.filename, frm.pse[idx].open_line,
  743. get_token_name(frm.pse[idx].type));
  744. cpd.error_count++;
  745. }
  746. }
  747. /**
  748. * returns true if forward scan reveals only single newlines or comments
  749. * stops when hits code
  750. * false if next thing hit is a closing brace, also if 2 newlines in a row
  751. */
  752. static bool single_line_comment_indent_rule_applies(chunk_t *start)
  753. {
  754. chunk_t *pc = start;
  755. int nl_count = 0;
  756. if (!chunk_is_single_line_comment(pc))
  757. {
  758. return(false);
  759. }
  760. /* scan forward, if only single newlines and comments before next line of code, we want to apply */
  761. while ((pc = chunk_get_next(pc)) != NULL)
  762. {
  763. if (chunk_is_newline(pc))
  764. {
  765. if (nl_count > 0 || pc->nl_count > 1)
  766. {
  767. return(false);
  768. }
  769. nl_count++;
  770. }
  771. else
  772. {
  773. nl_count = 0;
  774. if (!chunk_is_single_line_comment(pc))
  775. {
  776. /* here we check for things to run into that we wouldn't want to indent the comment for */
  777. /* for example, non-single line comment, closing brace */
  778. if (chunk_is_comment(pc) || chunk_is_closing_brace(pc))
  779. {
  780. return(false);
  781. }
  782. return(true);
  783. }
  784. }
  785. }
  786. return(false);
  787. }
  788. /**
  789. * REVISIT: This needs to be re-checked, maybe cleaned up
  790. *
  791. * Indents comments in a (hopefully) smart manner.
  792. *
  793. * There are two type of comments that get indented:
  794. * - stand alone (ie, no tokens on the line before the comment)
  795. * - trailing comments (last token on the line apart from a linefeed)
  796. * + note that a stand-alone comment is a special case of a trailing
  797. *
  798. * The stand alone comments will get indented in one of three ways:
  799. * - column 1:
  800. * + There is an empty line before the comment AND the indent level is 0
  801. * + The comment was originally in column 1
  802. *
  803. * - Same column as trailing comment on previous line (ie, aligned)
  804. * + if originally within TBD (3) columns of the previous comment
  805. *
  806. * - syntax indent level
  807. * + doesn't fit in the previous categories
  808. *
  809. * Options modify this behavior:
  810. * - keep original column (don't move the comment, if possible)
  811. * - keep relative column (move out the same amount as first item on line)
  812. * - fix trailing comment in column TBD
  813. *
  814. * @param pc The comment, which is the first item on a line
  815. * @param col The column if this is to be put at indent level
  816. */
  817. static void indent_comment(chunk_t *pc, int col)
  818. {
  819. chunk_t *nl;
  820. chunk_t *prev;
  821. LOG_FMT(LCMTIND, "%s: line %d, col %d, level %d: ", __func__,
  822. pc->orig_line, pc->orig_col, pc->level);
  823. /* force column 1 comment to column 1 if not changing them */
  824. if ((pc->orig_col == 1) && !cpd.settings[UO_indent_col1_comment].b)
  825. {
  826. LOG_FMT(LCMTIND, "rule 1 - keep in col 1\n");
  827. pc->column = 1;
  828. return;
  829. }
  830. nl = chunk_get_prev(pc);
  831. /* outside of any expression or statement? */
  832. if (pc->level == 0)
  833. {
  834. if ((nl != NULL) && (nl->nl_count > 1))
  835. {
  836. LOG_FMT(LCMTIND, "rule 2 - level 0, nl before\n");
  837. pc->column = 1;
  838. return;
  839. }
  840. }
  841. prev = chunk_get_prev(nl);
  842. if (chunk_is_comment(prev) && (nl->nl_count == 1))
  843. {
  844. int coldiff = prev->orig_col - pc->orig_col;
  845. if ((coldiff <= 3) && (coldiff >= -3))
  846. {
  847. pc->column = prev->column;
  848. LOG_FMT(LCMTIND, "rule 3 - prev comment, coldiff = %d, now in %d\n",
  849. coldiff, pc->column);
  850. return;
  851. }
  852. }
  853. /* check if special single line comment rule applies */
  854. if (cpd.settings[UO_indent_sing_line_comments].n > 0 && single_line_comment_indent_rule_applies(pc))
  855. {
  856. pc->column = col + cpd.settings[UO_indent_sing_line_comments].n;
  857. LOG_FMT(LCMTIND, "rule 4 - single line comment indent, now in %d\n", pc->column);
  858. return;
  859. }
  860. LOG_FMT(LCMTIND, "rule 5 - fall-through, stay in %d\n", col);
  861. pc->column = col;
  862. }
  863. /**
  864. * Put spaces on either side of the preproc (#) symbol.
  865. * This is done by pointing pc->str into pp_str and adjusting the
  866. * length.
  867. */
  868. void indent_preproc(void)
  869. {
  870. chunk_t *pc;
  871. chunk_t *next;
  872. int pp_level;
  873. int pp_level_sub = 0;
  874. int tmp;
  875. /* Define a string of 16 spaces + # + 16 spaces */
  876. static const char *pp_str = " # ";
  877. static const char *alt_str = " %: ";
  878. /* Scan to see if the whole file is covered by one #ifdef */
  879. int stage = 0;
  880. for (pc = chunk_get_head(); pc != NULL; pc = chunk_get_next(pc))
  881. {
  882. if (chunk_is_comment(pc) || chunk_is_newline(pc))
  883. {
  884. continue;
  885. }
  886. if (stage == 0)
  887. {
  888. /* Check the first PP, make sure it is an #if type */
  889. if (pc->type != CT_PREPROC)
  890. {
  891. break;
  892. }
  893. next = chunk_get_next(pc);
  894. if ((next == NULL) || (next->type != CT_PP_IF))
  895. {
  896. break;
  897. }
  898. stage = 1;
  899. }
  900. else if (stage == 1)
  901. {
  902. /* Scan until a PP at level 0 is found - the close to the #if */
  903. if ((pc->type == CT_PREPROC) &&
  904. (pc->pp_level == 0))
  905. {
  906. stage = 2;
  907. }
  908. continue;
  909. }
  910. else if (stage == 2)
  911. {
  912. /* We should only see the rest of the preprocessor */
  913. if ((pc->type == CT_PREPROC) ||
  914. ((pc->flags & PCF_IN_PREPROC) == 0))
  915. {
  916. stage = 0;
  917. break;
  918. }
  919. }
  920. }
  921. if (stage == 2)
  922. {
  923. LOG_FMT(LINFO, "The whole file is covered by a #IF\n");
  924. pp_level_sub = 1;
  925. }
  926. for (pc = chunk_get_head(); pc != NULL; pc = chunk_get_next(pc))
  927. {
  928. if (pc->type != CT_PREPROC)
  929. {
  930. continue;
  931. }
  932. if (pc->column != 1)
  933. {
  934. /* Don't handle preprocessors that aren't in column 1 */
  935. LOG_FMT(LINFO, "%s: Line %d doesn't start in column 1 (%d)\n",
  936. __func__, pc->orig_line, pc->column);
  937. continue;
  938. }
  939. /* point into pp_str */
  940. if (pc->len == 2)
  941. {
  942. /* alternate token crap */
  943. pc->str = &alt_str[16];
  944. }
  945. else
  946. {
  947. pc->str = &pp_str[16];
  948. }
  949. pp_level = pc->pp_level - pp_level_sub;
  950. if (pp_level < 0)
  951. {
  952. pp_level = 0;
  953. }
  954. else if (pp_level > 16)
  955. {
  956. pp_level = 16;
  957. }
  958. /* Note that the indent is removed by default */
  959. if ((cpd.settings[UO_pp_indent].a & AV_ADD) != 0)
  960. {
  961. /* Need to add some spaces */
  962. pc->str -= pp_level;
  963. pc->len += pp_level;
  964. }
  965. else if (cpd.settings[UO_pp_indent].a == AV_IGNORE)
  966. {
  967. tmp = (pc->orig_col <= 16) ? pc->orig_col - 1 : 16;
  968. pc->str -= tmp;
  969. pc->len += tmp;
  970. }
  971. /* Add spacing by adjusting the length */
  972. if ((cpd.settings[UO_pp_space].a & AV_ADD) != 0)
  973. {
  974. pc->len += pp_level;
  975. }
  976. next = chunk_get_next(pc);
  977. if (next != NULL)
  978. {
  979. reindent_line(next, pc->len + 1);
  980. }
  981. LOG_FMT(LPPIS, "%s: Indent line %d to %d (len %d, next->col %d)\n",
  982. __func__, pc->orig_line, pp_level, pc->len, next->column);
  983. }
  984. }