LexMake.cpp 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. // Scintilla source code edit control
  2. /** @file LexMake.cxx
  3. ** Lexer for make files.
  4. **/
  5. // Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org>
  6. // The License.txt file describes the conditions under which this software may be distributed.
  7. #include <stdlib.h>
  8. #include <string.h>
  9. #include <stdio.h>
  10. #include <stdarg.h>
  11. #include <assert.h>
  12. #include <ctype.h>
  13. #include "ILexer.h"
  14. #include "Scintilla.h"
  15. #include "SciLexer.h"
  16. #include "WordList.h"
  17. #include "LexAccessor.h"
  18. #include "Accessor.h"
  19. #include "StyleContext.h"
  20. #include "CharacterSet.h"
  21. #include "LexerModule.h"
  22. #ifdef SCI_NAMESPACE
  23. using namespace Scintilla;
  24. #endif
  25. static inline bool AtEOL(Accessor &styler, Sci_PositionU i) {
  26. return (styler[i] == '\n') ||
  27. ((styler[i] == '\r') && (styler.SafeGetCharAt(i + 1) != '\n'));
  28. }
  29. static void ColouriseMakeLine(
  30. char *lineBuffer,
  31. Sci_PositionU lengthLine,
  32. Sci_PositionU startLine,
  33. Sci_PositionU endPos,
  34. Accessor &styler) {
  35. Sci_PositionU i = 0;
  36. Sci_Position lastNonSpace = -1;
  37. unsigned int state = SCE_MAKE_DEFAULT;
  38. bool bSpecial = false;
  39. // check for a tab character in column 0 indicating a command
  40. bool bCommand = false;
  41. if ((lengthLine > 0) && (lineBuffer[0] == '\t'))
  42. bCommand = true;
  43. // Skip initial spaces
  44. while ((i < lengthLine) && isspacechar(lineBuffer[i])) {
  45. i++;
  46. }
  47. if (i < lengthLine) {
  48. if (lineBuffer[i] == '#') { // Comment
  49. styler.ColourTo(endPos, SCE_MAKE_COMMENT);
  50. return;
  51. }
  52. if (lineBuffer[i] == '!') { // Special directive
  53. styler.ColourTo(endPos, SCE_MAKE_PREPROCESSOR);
  54. return;
  55. }
  56. }
  57. int varCount = 0;
  58. while (i < lengthLine) {
  59. if (((i + 1) < lengthLine) && (lineBuffer[i] == '$' && lineBuffer[i + 1] == '(')) {
  60. styler.ColourTo(startLine + i - 1, state);
  61. state = SCE_MAKE_IDENTIFIER;
  62. varCount++;
  63. } else if (state == SCE_MAKE_IDENTIFIER && lineBuffer[i] == ')') {
  64. if (--varCount == 0) {
  65. styler.ColourTo(startLine + i, state);
  66. state = SCE_MAKE_DEFAULT;
  67. }
  68. }
  69. // skip identifier and target styling if this is a command line
  70. if (!bSpecial && !bCommand) {
  71. if (lineBuffer[i] == ':') {
  72. if (((i + 1) < lengthLine) && (lineBuffer[i + 1] == '=')) {
  73. // it's a ':=', so style as an identifier
  74. if (lastNonSpace >= 0)
  75. styler.ColourTo(startLine + lastNonSpace, SCE_MAKE_IDENTIFIER);
  76. styler.ColourTo(startLine + i - 1, SCE_MAKE_DEFAULT);
  77. styler.ColourTo(startLine + i + 1, SCE_MAKE_OPERATOR);
  78. } else {
  79. // We should check that no colouring was made since the beginning of the line,
  80. // to avoid colouring stuff like /OUT:file
  81. if (lastNonSpace >= 0)
  82. styler.ColourTo(startLine + lastNonSpace, SCE_MAKE_TARGET);
  83. styler.ColourTo(startLine + i - 1, SCE_MAKE_DEFAULT);
  84. styler.ColourTo(startLine + i, SCE_MAKE_OPERATOR);
  85. }
  86. bSpecial = true; // Only react to the first ':' of the line
  87. state = SCE_MAKE_DEFAULT;
  88. } else if (lineBuffer[i] == '=') {
  89. if (lastNonSpace >= 0)
  90. styler.ColourTo(startLine + lastNonSpace, SCE_MAKE_IDENTIFIER);
  91. styler.ColourTo(startLine + i - 1, SCE_MAKE_DEFAULT);
  92. styler.ColourTo(startLine + i, SCE_MAKE_OPERATOR);
  93. bSpecial = true; // Only react to the first '=' of the line
  94. state = SCE_MAKE_DEFAULT;
  95. }
  96. }
  97. if (!isspacechar(lineBuffer[i])) {
  98. lastNonSpace = i;
  99. }
  100. i++;
  101. }
  102. if (state == SCE_MAKE_IDENTIFIER) {
  103. styler.ColourTo(endPos, SCE_MAKE_IDEOL); // Error, variable reference not ended
  104. } else {
  105. styler.ColourTo(endPos, SCE_MAKE_DEFAULT);
  106. }
  107. }
  108. static void ColouriseMakeDoc(Sci_PositionU startPos, Sci_Position length, int, WordList *[], Accessor &styler) {
  109. char lineBuffer[1024];
  110. styler.StartAt(startPos);
  111. styler.StartSegment(startPos);
  112. Sci_PositionU linePos = 0;
  113. Sci_PositionU startLine = startPos;
  114. for (Sci_PositionU i = startPos; i < startPos + length; i++) {
  115. lineBuffer[linePos++] = styler[i];
  116. if (AtEOL(styler, i) || (linePos >= sizeof(lineBuffer) - 1)) {
  117. // End of line (or of line buffer) met, colourise it
  118. lineBuffer[linePos] = '\0';
  119. ColouriseMakeLine(lineBuffer, linePos, startLine, i, styler);
  120. linePos = 0;
  121. startLine = i + 1;
  122. }
  123. }
  124. if (linePos > 0) { // Last line does not have ending characters
  125. ColouriseMakeLine(lineBuffer, linePos, startLine, startPos + length - 1, styler);
  126. }
  127. }
  128. static const char *const emptyWordListDesc[] = {
  129. 0
  130. };
  131. LexerModule lmMake(SCLEX_MAKEFILE, ColouriseMakeDoc, "makefile", 0, emptyWordListDesc);