1 2 /* This version of microEmacs is based on the public domain C 3 * version written by Dave G. Conroy. 4 * The D programming language version is written by Walter Bright. 5 * http://www.digitalmars.com/d/ 6 * This program is in the public domain. 7 */ 8 9 /* This is the C syntax highligher. 10 */ 11 12 module syntaxc; 13 14 import core.stdc.stdio; 15 import core.stdc.ctype; 16 17 import std.utf; 18 19 import ed; 20 import buffer; 21 import window; 22 import main; 23 import display; 24 import random; 25 26 /******************************** 27 * Returns: 28 * starting syntax state of next line 29 */ 30 SyntaxState syntaxHighlightC(SyntaxState syntaxState, const(char)[] text, attr_t[] attr) 31 { 32 size_t i = 0; 33 34 switch (syntaxState.syntax) 35 { 36 case Syntax..string: 37 case Syntax.singleString: 38 { 39 const quote = (syntaxState.syntax == Syntax..string) ? '"' : 40 '\''; 41 const istart = i; 42 bool escape; 43 while (i < text.length) 44 { 45 if (text[i] == quote && !escape) 46 { 47 ++i; 48 attr[istart .. i] = config..string; 49 goto Loop; 50 } 51 else if (text[i] == '\\') 52 escape ^= true; 53 else 54 escape = false; 55 ++i; 56 } 57 attr[istart .. i] = config..string; 58 return SyntaxState(syntaxState.syntax); 59 } 60 61 case Syntax.comment: 62 { 63 // it's /* */ comment 64 const istart = i; 65 while (i < text.length) 66 { 67 if (text[i] == '*' && i + 1 < text.length && text[i + 1] == '/') 68 { 69 i += 2; 70 attr[istart .. i] = config.comment; 71 goto Loop; 72 } 73 ++i; 74 } 75 attr[istart .. i] = config.comment; 76 return SyntaxState(Syntax.comment); 77 } 78 79 default: 80 break; 81 } 82 83 Loop: 84 while (i < text.length) 85 { 86 const c = text[i]; 87 switch (c) 88 { 89 case 'a': .. case 'z': 90 case 'A': .. case 'Z': 91 case '_': 92 Idstart: 93 { 94 const istart = i; 95 ++i; 96 while (i < text.length) 97 { 98 const ci = text[i]; 99 if (isalnum(ci) || ci == '_' || ci & 0x80) 100 { 101 ++i; 102 continue; 103 } 104 break; 105 } 106 const id = text[istart .. i]; 107 attr[istart .. i] = isCKeyword(id) ? config.keyword : config.normattr; 108 continue; 109 } 110 111 case '/': 112 { 113 const istart = i; 114 ++i; 115 if (i < text.length) 116 { 117 if (text[i] == '/') 118 { 119 attr[istart .. text.length] = config.comment; 120 return SyntaxState(Syntax.normal); 121 } 122 123 if (text[i] == '*') 124 { 125 ++i; 126 while (i < text.length) 127 { 128 if (text[i] == '*' && i + 1 < text.length && text[i + 1] == '/') 129 { 130 i += 2; 131 attr[istart .. i] = config.comment; 132 continue Loop; 133 } 134 ++i; 135 } 136 attr[istart .. i] = config.comment; 137 return SyntaxState(Syntax.comment); 138 } 139 } 140 continue; 141 } 142 143 case '"': 144 case '\'': 145 { 146 const istart = i; 147 bool escape; 148 ++i; 149 while (i < text.length) 150 { 151 if (text[i] == c && !escape) 152 { 153 ++i; 154 attr[istart .. i] = config..string; 155 continue Loop; 156 } 157 else if (text[i] == '\\') 158 escape ^= true; 159 else 160 escape = false; 161 ++i; 162 } 163 attr[istart .. i] = config..string; 164 return SyntaxState(c == '"' ? Syntax..string : 165 Syntax.singleString); 166 } 167 168 default: 169 if (text[i] & 0x80) 170 goto Idstart; 171 attr[i] = config.normattr; 172 ++i; 173 continue; 174 } 175 /* 176 switch (syntaxState.syntax) 177 { 178 case Syntax.normal: 179 break; 180 181 case Syntax.string: 182 case Syntax.singleString: 183 break; 184 185 case Syntax.comment: 186 break; 187 188 default: 189 assert(0); 190 } 191 */ 192 } 193 return SyntaxState(Syntax.normal); 194 } 195 196 private bool isCKeyword(const(char)[] s) 197 { 198 switch (s) 199 { 200 case "break": 201 case "inline": 202 case "void": 203 case "case": 204 case "if": 205 case "int": 206 case "volatile": 207 case "char": 208 case "long": 209 case "while ": 210 case "const": 211 case "register": 212 case "continue": 213 case "restrict": 214 case "default": 215 case "return": 216 case "do": 217 case "short": 218 case "double": 219 case "signed": 220 case "else": 221 case "sizeof": 222 case "enum": 223 case "static": 224 case "extern": 225 case "struct": 226 case "float": 227 case "switch": 228 case "for": 229 case "typedef": 230 case "goto": 231 case "union ": 232 case "_Alignas ": 233 case "_Alignof ": 234 case "_Atomic ": 235 case "_Bool ": 236 case "_Complex ": 237 case "_Generic ": 238 case "_Imaginary ": 239 case "_Noreturn ": 240 case "_Static_assert ": 241 case "_Thread_local ": 242 case "__FILE__": 243 case "__LINE__": 244 return true; 245 246 default: 247 return false; 248 } 249 }