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