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