1 /** 2 * Compiler implementation of the 3 * $(LINK2 http://www.dlang.org, D programming language). 4 * 5 * Copyright: Copyright (c) 1999-2016 by Digital Mars, All Rights Reserved 6 * Authors: $(LINK2 http://www.digitalmars.com, Walter Bright) 7 * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) 8 * Source: $(DMDSRC _errors.d) 9 */ 10 11 module ddmd.errors; 12 13 import core.stdc.stdarg; 14 import core.stdc.stdio; 15 import core.stdc.stdlib; 16 import core.stdc..string; 17 import core.sys.posix.unistd; 18 import core.sys.windows.windows; 19 import ddmd.globals; 20 import ddmd.root.outbuffer; 21 import ddmd.root.rmem; 22 23 version (Windows) extern (C) int isatty(int); 24 25 enum COLOR : int 26 { 27 COLOR_BLACK = 0, 28 COLOR_RED = 1, 29 COLOR_GREEN = 2, 30 COLOR_BLUE = 4, 31 COLOR_YELLOW = COLOR_RED | COLOR_GREEN, 32 COLOR_MAGENTA = COLOR_RED | COLOR_BLUE, 33 COLOR_CYAN = COLOR_GREEN | COLOR_BLUE, 34 COLOR_WHITE = COLOR_RED | COLOR_GREEN | COLOR_BLUE, 35 } 36 37 alias COLOR_BLACK = COLOR.COLOR_BLACK; 38 alias COLOR_RED = COLOR.COLOR_RED; 39 alias COLOR_GREEN = COLOR.COLOR_GREEN; 40 alias COLOR_BLUE = COLOR.COLOR_BLUE; 41 alias COLOR_YELLOW = COLOR.COLOR_YELLOW; 42 alias COLOR_MAGENTA = COLOR.COLOR_MAGENTA; 43 alias COLOR_CYAN = COLOR.COLOR_CYAN; 44 alias COLOR_WHITE = COLOR.COLOR_WHITE; 45 46 version (Windows) 47 { 48 extern (C++) static WORD consoleAttributes(HANDLE h) 49 { 50 static __gshared CONSOLE_SCREEN_BUFFER_INFO sbi; 51 static __gshared bool sbi_inited = false; 52 if (!sbi_inited) 53 sbi_inited = GetConsoleScreenBufferInfo(h, &sbi) != FALSE; 54 return sbi.wAttributes; 55 } 56 57 enum : int 58 { 59 FOREGROUND_WHITE = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE, 60 } 61 } 62 63 extern (C++) bool isConsoleColorSupported() 64 { 65 version (CRuntime_DigitalMars) 66 { 67 return isatty(stderr._file) != 0; 68 } 69 else version (CRuntime_Microsoft) 70 { 71 return isatty(fileno(stderr)) != 0; 72 } 73 else version (Posix) 74 { 75 const(char)* term = getenv("TERM"); 76 return isatty(STDERR_FILENO) && term && term[0] && 0 != strcmp(term, "dumb"); 77 } 78 else 79 { 80 return false; 81 } 82 } 83 84 extern (C++) void setConsoleColorBright(bool bright) 85 { 86 version (Windows) 87 { 88 HANDLE h = GetStdHandle(STD_ERROR_HANDLE); 89 WORD attr = consoleAttributes(h); 90 SetConsoleTextAttribute(h, attr | (bright ? FOREGROUND_INTENSITY : 0)); 91 } 92 else 93 { 94 fprintf(stderr, "\033[%dm", bright ? 1 : 0); 95 } 96 } 97 98 extern (C++) void setConsoleColor(COLOR color, bool bright) 99 { 100 version (Windows) 101 { 102 HANDLE h = GetStdHandle(STD_ERROR_HANDLE); 103 WORD attr = consoleAttributes(h); 104 attr = (attr & ~(FOREGROUND_WHITE | FOREGROUND_INTENSITY)) | ((color & COLOR_RED) ? FOREGROUND_RED : 0) | ((color & COLOR_GREEN) ? FOREGROUND_GREEN : 0) | ((color & COLOR_BLUE) ? FOREGROUND_BLUE : 0) | (bright ? FOREGROUND_INTENSITY : 0); 105 SetConsoleTextAttribute(h, attr); 106 } 107 else 108 { 109 fprintf(stderr, "\033[%d;%dm", bright ? 1 : 0, 30 + cast(int)color); 110 } 111 } 112 113 extern (C++) void resetConsoleColor() 114 { 115 version (Windows) 116 { 117 HANDLE h = GetStdHandle(STD_ERROR_HANDLE); 118 SetConsoleTextAttribute(h, consoleAttributes(h)); 119 } 120 else 121 { 122 fprintf(stderr, "\033[m"); 123 } 124 } 125 126 /************************************** 127 * Print error message 128 */ 129 extern (C++) void error(const ref Loc loc, const(char)* format, ...) 130 { 131 va_list ap; 132 va_start(ap, format); 133 verror(loc, format, ap); 134 va_end(ap); 135 } 136 137 extern (C++) void error(Loc loc, const(char)* format, ...) 138 { 139 va_list ap; 140 va_start(ap, format); 141 verror(loc, format, ap); 142 va_end(ap); 143 } 144 145 extern (C++) void error(const(char)* filename, uint linnum, uint charnum, const(char)* format, ...) 146 { 147 Loc loc; 148 loc.filename = filename; 149 loc.linnum = linnum; 150 loc.charnum = charnum; 151 va_list ap; 152 va_start(ap, format); 153 verror(loc, format, ap); 154 va_end(ap); 155 } 156 157 extern (C++) void errorSupplemental(const ref Loc loc, const(char)* format, ...) 158 { 159 va_list ap; 160 va_start(ap, format); 161 verrorSupplemental(loc, format, ap); 162 va_end(ap); 163 } 164 165 extern (C++) void warning(const ref Loc loc, const(char)* format, ...) 166 { 167 va_list ap; 168 va_start(ap, format); 169 vwarning(loc, format, ap); 170 va_end(ap); 171 } 172 173 extern (C++) void warningSupplemental(const ref Loc loc, const(char)* format, ...) 174 { 175 va_list ap; 176 va_start(ap, format); 177 vwarningSupplemental(loc, format, ap); 178 va_end(ap); 179 } 180 181 extern (C++) void deprecation(const ref Loc loc, const(char)* format, ...) 182 { 183 va_list ap; 184 va_start(ap, format); 185 vdeprecation(loc, format, ap); 186 va_end(ap); 187 } 188 189 extern (C++) void deprecationSupplemental(const ref Loc loc, const(char)* format, ...) 190 { 191 va_list ap; 192 va_start(ap, format); 193 vdeprecation(loc, format, ap); 194 va_end(ap); 195 } 196 197 // Just print, doesn't care about gagging 198 extern (C++) void verrorPrint(const ref Loc loc, COLOR headerColor, const(char)* header, const(char)* format, va_list ap, const(char)* p1 = null, const(char)* p2 = null) 199 { 200 const p = loc.toChars(); 201 if (global.params.color) 202 setConsoleColorBright(true); 203 if (*p) 204 fprintf(stderr, "%s: ", p); 205 mem.xfree(cast(void*)p); 206 if (global.params.color) 207 setConsoleColor(headerColor, true); 208 fputs(header, stderr); 209 if (global.params.color) 210 resetConsoleColor(); 211 if (p1) 212 fprintf(stderr, "%s ", p1); 213 if (p2) 214 fprintf(stderr, "%s ", p2); 215 OutBuffer tmp; 216 tmp.vprintf(format, ap); 217 fprintf(stderr, "%s\n", tmp.peekString()); 218 fflush(stderr); 219 } 220 221 // header is "Error: " by default (see errors.h) 222 extern (C++) void verror(const ref Loc loc, const(char)* format, va_list ap, const(char)* p1 = null, const(char)* p2 = null, const(char)* header = "Error: ") 223 { 224 global.errors++; 225 if (!global.gag) 226 { 227 verrorPrint(loc, COLOR_RED, header, format, ap, p1, p2); 228 if (global.errorLimit && global.errors >= global.errorLimit) 229 fatal(); // moderate blizzard of cascading messages 230 } 231 else 232 { 233 //fprintf(stderr, "(gag:%d) ", global.gag); 234 //verrorPrint(loc, COLOR_RED, header, format, ap, p1, p2); 235 global.gaggedErrors++; 236 } 237 } 238 239 // Doesn't increase error count, doesn't print "Error:". 240 extern (C++) void verrorSupplemental(const ref Loc loc, const(char)* format, va_list ap) 241 { 242 if (!global.gag) 243 verrorPrint(loc, COLOR_RED, " ", format, ap); 244 } 245 246 extern (C++) void vwarning(const ref Loc loc, const(char)* format, va_list ap) 247 { 248 if (global.params.warnings && !global.gag) 249 { 250 verrorPrint(loc, COLOR_YELLOW, "Warning: ", format, ap); 251 //halt(); 252 if (global.params.warnings == 1) 253 global.warnings++; // warnings don't count if gagged 254 } 255 } 256 257 extern (C++) void vwarningSupplemental(const ref Loc loc, const(char)* format, va_list ap) 258 { 259 if (global.params.warnings && !global.gag) 260 verrorPrint(loc, COLOR_YELLOW, " ", format, ap); 261 } 262 263 extern (C++) void vdeprecation(const ref Loc loc, const(char)* format, va_list ap, const(char)* p1 = null, const(char)* p2 = null) 264 { 265 static __gshared const(char)* header = "Deprecation: "; 266 if (global.params.useDeprecated == 0) 267 verror(loc, format, ap, p1, p2, header); 268 else if (global.params.useDeprecated == 2 && !global.gag) 269 verrorPrint(loc, COLOR_BLUE, header, format, ap, p1, p2); 270 } 271 272 extern (C++) void vdeprecationSupplemental(const ref Loc loc, const(char)* format, va_list ap) 273 { 274 if (global.params.useDeprecated == 0) 275 verrorSupplemental(loc, format, ap); 276 else if (global.params.useDeprecated == 2 && !global.gag) 277 verrorPrint(loc, COLOR_BLUE, " ", format, ap); 278 } 279 280 /*************************************** 281 * Call this after printing out fatal error messages to clean up and exit 282 * the compiler. 283 */ 284 extern (C++) void fatal() 285 { 286 version (none) 287 { 288 halt(); 289 } 290 exit(EXIT_FAILURE); 291 } 292 293 /************************************** 294 * Try to stop forgetting to remove the breakpoints from 295 * release builds. 296 */ 297 extern (C++) void halt() 298 { 299 assert(0); 300 }