├── .gitignore ├── README.md ├── boostlicense.txt ├── dub.json └── source └── ddmd ├── entity.d ├── errors.d ├── globals.d ├── id.d ├── identifier.d ├── lexer.d ├── root ├── array.d ├── file.d ├── filename.d ├── longdouble.d ├── outbuffer.d ├── port.d ├── rmem.d ├── rootobject.d └── stringtable.d ├── tokens.d └── utf.d /.gitignore: -------------------------------------------------------------------------------- 1 | .dub 2 | docs.json 3 | __dummy.html 4 | *.o 5 | *.obj 6 | ddmd.lib 7 | ddmd.a 8 | copyin.bat 9 | dub.selections.json 10 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | Overview: 3 | -------------------- 4 | 5 | This project is a port of the [DMD frontend](https://github.com/D-Programming-Language/dmd), automatically translated from C++ to D using [magicport2](https://github.com/yebblies/magicport2). The current version is based on dmd 2.067. 6 | 7 | This project is designed to be built with dub. ([dub package](http://code.dlang.org/packages/ddmd)) 8 | 9 | Currently only the lexer and some support modules are included. 10 | 11 | This project may eventually be merged into dmd upstream development. No stable API is provided. 12 | 13 | As the code is automatically generated, pull requests should be made against [upstream](https://github.com/D-Programming-Language/dmd). 14 | 15 | Warnings and deprecations currently need to be disabled for the code to compile successfully. 16 | 17 | Example: 18 | -------------------- 19 | 20 | ```json 21 | { 22 | "name": "ddmdlexertest", 23 | "dependencies": { 24 | "ddmd": ">=0.0.1" 25 | }, 26 | "buildRequirements": [ 27 | "silenceWarnings", 28 | "silenceDeprecations" 29 | ] 30 | } 31 | ``` 32 | 33 | ```d 34 | import std.stdio; 35 | import std.file; 36 | 37 | import ddmd.tokens; 38 | import ddmd.lexer; 39 | 40 | ///////////////////////// 41 | 42 | void main() 43 | { 44 | string data = "void blah() {} // stuff"; 45 | auto l = new Lexer("myfile", data.ptr, 0, data.length, 0, 0); 46 | l.nextToken(); 47 | do 48 | { 49 | printf("token: %s\n", l.token.toChars()); 50 | } 51 | while (l.nextToken() != TOKeof); 52 | } 53 | ``` 54 | -------------------------------------------------------------------------------- /boostlicense.txt: -------------------------------------------------------------------------------- 1 | Boost Software License - Version 1.0 - August 17th, 2003 2 | 3 | Permission is hereby granted, free of charge, to any person or organization 4 | obtaining a copy of the software and accompanying documentation covered by 5 | this license (the "Software") to use, reproduce, display, distribute, 6 | execute, and transmit the Software, and to prepare derivative works of the 7 | Software, and to permit third-parties to whom the Software is furnished to 8 | do so, all subject to the following: 9 | 10 | The copyright notices in the Software and this entire statement, including 11 | the above license grant, this restriction and the following disclaimer, 12 | must be included in all copies of the Software, in whole or in part, and 13 | all derivative works of the Software, unless such copies or derivative 14 | works are solely in the form of machine-executable object code generated by 15 | a source language processor. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT 20 | SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE 21 | FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, 22 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 23 | DEALINGS IN THE SOFTWARE. 24 | -------------------------------------------------------------------------------- /dub.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ddmd", 3 | "description": "DMD Compiler Frontend", 4 | "copyright": "Copyright © 1999-2015, Digital Mars", 5 | "authors": ["Walter Bright"], 6 | "license": "BSL-1.0", 7 | "configurations": [ 8 | { 9 | "name": "libddmd", 10 | "targetName": "ddmd", 11 | "targetType": "library", 12 | "sourcePaths": ["source/"], 13 | "importPaths": ["source/"] 14 | } 15 | ], 16 | "buildRequirements" : [ 17 | "silenceWarnings", 18 | "silenceDeprecations" 19 | ] 20 | } 21 | -------------------------------------------------------------------------------- /source/ddmd/errors.d: -------------------------------------------------------------------------------- 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 | } 291 | -------------------------------------------------------------------------------- /source/ddmd/globals.d: -------------------------------------------------------------------------------- 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.globals; 10 | 11 | import core.stdc.stdint; 12 | import core.stdc.stdio; 13 | import core.stdc.string; 14 | import ddmd.root.array; 15 | import ddmd.root.filename; 16 | import ddmd.root.outbuffer; 17 | 18 | template xversion(string s) 19 | { 20 | enum xversion = mixin(`{ version (` ~ s ~ `) return true; else return false; }`)(); 21 | } 22 | 23 | private string stripRight(string s) 24 | { 25 | while (s.length && (s[$ - 1] == ' ' || s[$ - 1] == '\n' || s[$ - 1] == '\r')) 26 | s = s[0 .. $ - 1]; 27 | return s; 28 | } 29 | 30 | enum __linux__ = xversion!`linux`; 31 | enum __APPLE__ = xversion!`OSX`; 32 | enum __FreeBSD__ = xversion!`FreeBSD`; 33 | enum __OpenBSD__ = xversion!`OpenBSD`; 34 | enum __sun = xversion!`Solaris`; 35 | 36 | enum IN_GCC = xversion!`IN_GCC`; 37 | 38 | enum TARGET_LINUX = xversion!`linux`; 39 | enum TARGET_OSX = xversion!`OSX`; 40 | enum TARGET_FREEBSD = xversion!`FreeBSD`; 41 | enum TARGET_OPENBSD = xversion!`OpenBSD`; 42 | enum TARGET_SOLARIS = xversion!`Solaris`; 43 | enum TARGET_WINDOS = xversion!`Windows`; 44 | 45 | enum BOUNDSCHECK : int 46 | { 47 | BOUNDSCHECKdefault, // initial value 48 | BOUNDSCHECKoff, // never do bounds checking 49 | BOUNDSCHECKon, // always do bounds checking 50 | BOUNDSCHECKsafeonly, // do bounds checking only in @safe functions 51 | } 52 | 53 | alias BOUNDSCHECKdefault = BOUNDSCHECK.BOUNDSCHECKdefault; 54 | alias BOUNDSCHECKoff = BOUNDSCHECK.BOUNDSCHECKoff; 55 | alias BOUNDSCHECKon = BOUNDSCHECK.BOUNDSCHECKon; 56 | alias BOUNDSCHECKsafeonly = BOUNDSCHECK.BOUNDSCHECKsafeonly; 57 | 58 | // Put command line switches in here 59 | struct Param 60 | { 61 | bool obj; // write object file 62 | bool link; // perform link 63 | bool dll; // generate shared dynamic library 64 | bool lib; // write library file instead of object file(s) 65 | bool multiobj; // break one object file into multiple ones 66 | bool oneobj; // write one object file instead of multiple ones 67 | bool trace; // insert profiling hooks 68 | bool tracegc; // instrument calls to 'new' 69 | bool verbose; // verbose compile 70 | bool showColumns; // print character (column) numbers in diagnostics 71 | bool vtls; // identify thread local variables 72 | bool vgc; // identify gc usage 73 | bool vfield; // identify non-mutable field variables 74 | bool vcomplex; // identify complex/imaginary type usage 75 | ubyte symdebug; // insert debug symbolic information 76 | bool alwaysframe; // always emit standard stack frame 77 | bool optimize; // run optimizer 78 | bool map; // generate linker .map file 79 | bool is64bit; // generate 64 bit code 80 | bool isLP64; // generate code for LP64 81 | bool isLinux; // generate code for linux 82 | bool isOSX; // generate code for Mac OSX 83 | bool isWindows; // generate code for Windows 84 | bool isFreeBSD; // generate code for FreeBSD 85 | bool isOpenBSD; // generate code for OpenBSD 86 | bool isSolaris; // generate code for Solaris 87 | bool mscoff; // for Win32: write COFF object files instead of OMF 88 | // 0: don't allow use of deprecated features 89 | // 1: silently allow use of deprecated features 90 | // 2: warn about the use of deprecated features 91 | byte useDeprecated; 92 | bool useAssert; // generate runtime code for assert()'s 93 | bool useInvariants; // generate class invariant checks 94 | bool useIn; // generate precondition checks 95 | bool useOut; // generate postcondition checks 96 | bool stackstomp; // add stack stomping code 97 | bool useSwitchError; // check for switches without a default 98 | bool useUnitTests; // generate unittest code 99 | bool useInline; // inline expand functions 100 | bool useDIP25; // implement http://wiki.dlang.org/DIP25 101 | bool release; // build release version 102 | bool preservePaths; // true means don't strip path from source file 103 | // 0: disable warnings 104 | // 1: warnings as errors 105 | // 2: informational warnings (no errors) 106 | byte warnings; 107 | bool pic; // generate position-independent-code for shared libs 108 | bool color; // use ANSI colors in console output 109 | bool cov; // generate code coverage data 110 | ubyte covPercent; // 0..100 code coverage percentage required 111 | bool nofloat; // code should not pull in floating point support 112 | bool ignoreUnsupportedPragmas; // rather than error on them 113 | bool enforcePropertySyntax; 114 | bool betterC; // be a "better C" compiler; no dependency on D runtime 115 | bool addMain; // add a default main() function 116 | bool allInst; // generate code for all template instantiations 117 | bool dwarfeh; // generate dwarf eh exception handling 118 | bool check10378; // check for issues transitioning to 10738 119 | bool bug10378; // use pre-bugzilla 10378 search strategy 120 | 121 | BOUNDSCHECK useArrayBounds; 122 | 123 | const(char)* argv0; // program name 124 | Array!(const(char)*)* imppath; // array of char*'s of where to look for import modules 125 | Array!(const(char)*)* fileImppath; // array of char*'s of where to look for file import modules 126 | const(char)* objdir; // .obj/.lib file output directory 127 | const(char)* objname; // .obj file output name 128 | const(char)* libname; // .lib file output name 129 | 130 | bool doDocComments; // process embedded documentation comments 131 | const(char)* docdir; // write documentation file to docdir directory 132 | const(char)* docname; // write documentation file to docname 133 | Array!(const(char)*)* ddocfiles; // macro include files for Ddoc 134 | 135 | bool doHdrGeneration; // process embedded documentation comments 136 | const(char)* hdrdir; // write 'header' file to docdir directory 137 | const(char)* hdrname; // write 'header' file to docname 138 | 139 | bool doJsonGeneration; // write JSON file 140 | const(char)* jsonfilename; // write JSON file to jsonfilename 141 | 142 | uint debuglevel; // debug level 143 | Array!(const(char)*)* debugids; // debug identifiers 144 | 145 | uint versionlevel; // version level 146 | Array!(const(char)*)* versionids; // version identifiers 147 | 148 | const(char)* defaultlibname; // default library for non-debug builds 149 | const(char)* debuglibname; // default library for debug builds 150 | 151 | const(char)* moduleDepsFile; // filename for deps output 152 | OutBuffer* moduleDeps; // contents to be written to deps file 153 | 154 | // Hidden debug switches 155 | bool debugb; 156 | bool debugc; 157 | bool debugf; 158 | bool debugr; 159 | bool debugx; 160 | bool debugy; 161 | 162 | bool run; // run resulting executable 163 | Strings runargs; // arguments for executable 164 | 165 | // Linker stuff 166 | Array!(const(char)*)* objfiles; 167 | Array!(const(char)*)* linkswitches; 168 | Array!(const(char)*)* libfiles; 169 | Array!(const(char)*)* dllfiles; 170 | const(char)* deffile; 171 | const(char)* resfile; 172 | const(char)* exefile; 173 | const(char)* mapfile; 174 | } 175 | 176 | struct Compiler 177 | { 178 | const(char)* vendor; // Compiler backend name 179 | } 180 | 181 | alias structalign_t = uint; 182 | 183 | // magic value means "match whatever the underlying C compiler does" 184 | // other values are all powers of 2 185 | enum STRUCTALIGN_DEFAULT = (cast(structalign_t)~0); 186 | 187 | struct Global 188 | { 189 | const(char)* inifilename; 190 | const(char)* mars_ext; 191 | const(char)* obj_ext; 192 | const(char)* lib_ext; 193 | const(char)* dll_ext; 194 | const(char)* doc_ext; // for Ddoc generated files 195 | const(char)* ddoc_ext; // for Ddoc macro include files 196 | const(char)* hdr_ext; // for D 'header' import files 197 | const(char)* json_ext; // for JSON files 198 | const(char)* map_ext; // for .map files 199 | bool run_noext; // allow -run sources without extensions. 200 | 201 | const(char)* copyright; 202 | const(char)* written; 203 | const(char)* main_d; // dummy filename for dummy main() 204 | Array!(const(char)*)* path; // Array of char*'s which form the import lookup path 205 | Array!(const(char)*)* filePath; // Array of char*'s which form the file import lookup path 206 | 207 | const(char)* _version; 208 | 209 | Compiler compiler; 210 | Param params; 211 | uint errors; // number of errors reported so far 212 | uint warnings; // number of warnings reported so far 213 | FILE* stdmsg; // where to send verbose messages 214 | uint gag; // !=0 means gag reporting of errors & warnings 215 | uint gaggedErrors; // number of errors reported while gagged 216 | 217 | uint errorLimit; 218 | 219 | /* Start gagging. Return the current number of gagged errors 220 | */ 221 | extern (C++) uint startGagging() 222 | { 223 | ++gag; 224 | return gaggedErrors; 225 | } 226 | 227 | /* End gagging, restoring the old gagged state. 228 | * Return true if errors occured while gagged. 229 | */ 230 | extern (C++) bool endGagging(uint oldGagged) 231 | { 232 | bool anyErrs = (gaggedErrors != oldGagged); 233 | --gag; 234 | // Restore the original state of gagged errors; set total errors 235 | // to be original errors + new ungagged errors. 236 | errors -= (gaggedErrors - oldGagged); 237 | gaggedErrors = oldGagged; 238 | return anyErrs; 239 | } 240 | 241 | /* Increment the error count to record that an error 242 | * has occured in the current context. An error message 243 | * may or may not have been printed. 244 | */ 245 | extern (C++) void increaseErrorCount() 246 | { 247 | if (gag) 248 | ++gaggedErrors; 249 | ++errors; 250 | } 251 | 252 | extern (C++) void _init() 253 | { 254 | inifilename = null; 255 | mars_ext = "d"; 256 | hdr_ext = "di"; 257 | doc_ext = "html"; 258 | ddoc_ext = "ddoc"; 259 | json_ext = "json"; 260 | map_ext = "map"; 261 | static if (TARGET_WINDOS) 262 | { 263 | obj_ext = "obj"; 264 | } 265 | else static if (TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_OPENBSD || TARGET_SOLARIS) 266 | { 267 | obj_ext = "o"; 268 | } 269 | else 270 | { 271 | static assert(0, "fix this"); 272 | } 273 | static if (TARGET_WINDOS) 274 | { 275 | lib_ext = "lib"; 276 | } 277 | else static if (TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_OPENBSD || TARGET_SOLARIS) 278 | { 279 | lib_ext = "a"; 280 | } 281 | else 282 | { 283 | static assert(0, "fix this"); 284 | } 285 | static if (TARGET_WINDOS) 286 | { 287 | dll_ext = "dll"; 288 | } 289 | else static if (TARGET_LINUX || TARGET_FREEBSD || TARGET_OPENBSD || TARGET_SOLARIS) 290 | { 291 | dll_ext = "so"; 292 | } 293 | else static if (TARGET_OSX) 294 | { 295 | dll_ext = "dylib"; 296 | } 297 | else 298 | { 299 | static assert(0, "fix this"); 300 | } 301 | static if (TARGET_WINDOS) 302 | { 303 | run_noext = false; 304 | } 305 | else static if (TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_OPENBSD || TARGET_SOLARIS) 306 | { 307 | // Allow 'script' D source files to have no extension. 308 | run_noext = true; 309 | } 310 | else 311 | { 312 | static assert(0, "fix this"); 313 | } 314 | copyright = "Copyright (c) 1999-2015 by Digital Mars"; 315 | written = "written by Walter Bright"; 316 | _version = "v2.071.0"; 317 | compiler.vendor = "Digital Mars D"; 318 | stdmsg = stdout; 319 | main_d = "__main.d"; 320 | errorLimit = 20; 321 | } 322 | } 323 | 324 | // Because int64_t and friends may be any integral type of the 325 | // correct size, we have to explicitly ask for the correct 326 | // integer type to get the correct mangling with ddmd 327 | 328 | // Be careful not to care about sign when using dinteger_t 329 | // use this instead of integer_t to 330 | // avoid conflicts with system #include's 331 | alias dinteger_t = ulong; 332 | // Signed and unsigned variants 333 | alias sinteger_t = long; 334 | alias uinteger_t = ulong; 335 | 336 | alias d_int8 = int8_t; 337 | alias d_uns8 = uint8_t; 338 | alias d_int16 = int16_t; 339 | alias d_uns16 = uint16_t; 340 | alias d_int32 = int32_t; 341 | alias d_uns32 = uint32_t; 342 | alias d_int64 = int64_t; 343 | alias d_uns64 = uint64_t; 344 | alias d_float32 = float; 345 | alias d_float64 = double; 346 | alias d_float80 = real; 347 | alias real_t = real; 348 | 349 | // file location 350 | struct Loc 351 | { 352 | const(char)* filename; 353 | uint linnum; 354 | uint charnum; 355 | 356 | extern (D) this(const(char)* filename, uint linnum, uint charnum) 357 | { 358 | this.linnum = linnum; 359 | this.charnum = charnum; 360 | this.filename = filename; 361 | } 362 | 363 | extern (C++) const(char)* toChars() const 364 | { 365 | OutBuffer buf; 366 | if (filename) 367 | { 368 | buf.printf("%s", filename); 369 | } 370 | if (linnum) 371 | { 372 | buf.printf("(%d", linnum); 373 | if (global.params.showColumns && charnum) 374 | buf.printf(",%d", charnum); 375 | buf.writeByte(')'); 376 | } 377 | return buf.extractString(); 378 | } 379 | 380 | extern (C++) bool equals(ref const(Loc) loc) 381 | { 382 | return (!global.params.showColumns || charnum == loc.charnum) && linnum == loc.linnum && FileName.equals(filename, loc.filename); 383 | } 384 | } 385 | 386 | enum LINK : int 387 | { 388 | def, // default 389 | d, 390 | c, 391 | cpp, 392 | windows, 393 | pascal, 394 | objc, 395 | } 396 | 397 | alias LINKdefault = LINK.def; 398 | alias LINKd = LINK.d; 399 | alias LINKc = LINK.c; 400 | alias LINKcpp = LINK.cpp; 401 | alias LINKwindows = LINK.windows; 402 | alias LINKpascal = LINK.pascal; 403 | alias LINKobjc = LINK.objc; 404 | 405 | enum DYNCAST : int 406 | { 407 | object, 408 | expression, 409 | dsymbol, 410 | type, 411 | identifier, 412 | tuple, 413 | parameter, 414 | } 415 | 416 | alias DYNCAST_OBJECT = DYNCAST.object; 417 | alias DYNCAST_EXPRESSION = DYNCAST.expression; 418 | alias DYNCAST_DSYMBOL = DYNCAST.dsymbol; 419 | alias DYNCAST_TYPE = DYNCAST.type; 420 | alias DYNCAST_IDENTIFIER = DYNCAST.identifier; 421 | alias DYNCAST_TUPLE = DYNCAST.tuple; 422 | alias DYNCAST_PARAMETER = DYNCAST.parameter; 423 | 424 | enum MATCH : int 425 | { 426 | nomatch, // no match 427 | convert, // match with conversions 428 | constant, // match with conversion to const 429 | exact, // exact match 430 | } 431 | 432 | alias MATCHnomatch = MATCH.nomatch; 433 | alias MATCHconvert = MATCH.convert; 434 | alias MATCHconst = MATCH.constant; 435 | alias MATCHexact = MATCH.exact; 436 | 437 | enum PINLINE : int 438 | { 439 | def, // as specified on the command line 440 | never, // never inline 441 | always, // always inline 442 | } 443 | 444 | alias PINLINEdefault = PINLINE.def; 445 | alias PINLINEnever = PINLINE.never; 446 | alias PINLINEalways = PINLINE.always; 447 | 448 | alias StorageClass = uinteger_t; 449 | 450 | extern (C++) __gshared Global global; 451 | -------------------------------------------------------------------------------- /source/ddmd/id.d: -------------------------------------------------------------------------------- 1 | // File generated by idgen.d 2 | 3 | module ddmd.id; 4 | 5 | import ddmd.identifier, ddmd.tokens; 6 | 7 | struct Id 8 | { 9 | extern (C++) static __gshared Identifier IUnknown; 10 | extern (C++) static __gshared Identifier Object; 11 | extern (C++) static __gshared Identifier object; 12 | extern (C++) static __gshared Identifier string; 13 | extern (C++) static __gshared Identifier wstring; 14 | extern (C++) static __gshared Identifier dstring; 15 | extern (C++) static __gshared Identifier max; 16 | extern (C++) static __gshared Identifier min; 17 | extern (C++) static __gshared Identifier This; 18 | extern (C++) static __gshared Identifier _super; 19 | extern (C++) static __gshared Identifier ctor; 20 | extern (C++) static __gshared Identifier dtor; 21 | extern (C++) static __gshared Identifier __xdtor; 22 | extern (C++) static __gshared Identifier __fieldDtor; 23 | extern (C++) static __gshared Identifier __aggrDtor; 24 | extern (C++) static __gshared Identifier postblit; 25 | extern (C++) static __gshared Identifier __xpostblit; 26 | extern (C++) static __gshared Identifier __fieldPostblit; 27 | extern (C++) static __gshared Identifier __aggrPostblit; 28 | extern (C++) static __gshared Identifier classInvariant; 29 | extern (C++) static __gshared Identifier unitTest; 30 | extern (C++) static __gshared Identifier require; 31 | extern (C++) static __gshared Identifier ensure; 32 | extern (C++) static __gshared Identifier _init; 33 | extern (C++) static __gshared Identifier __sizeof; 34 | extern (C++) static __gshared Identifier __xalignof; 35 | extern (C++) static __gshared Identifier _mangleof; 36 | extern (C++) static __gshared Identifier stringof; 37 | extern (C++) static __gshared Identifier _tupleof; 38 | extern (C++) static __gshared Identifier length; 39 | extern (C++) static __gshared Identifier remove; 40 | extern (C++) static __gshared Identifier ptr; 41 | extern (C++) static __gshared Identifier array; 42 | extern (C++) static __gshared Identifier funcptr; 43 | extern (C++) static __gshared Identifier dollar; 44 | extern (C++) static __gshared Identifier ctfe; 45 | extern (C++) static __gshared Identifier offset; 46 | extern (C++) static __gshared Identifier offsetof; 47 | extern (C++) static __gshared Identifier ModuleInfo; 48 | extern (C++) static __gshared Identifier ClassInfo; 49 | extern (C++) static __gshared Identifier classinfo; 50 | extern (C++) static __gshared Identifier typeinfo; 51 | extern (C++) static __gshared Identifier outer; 52 | extern (C++) static __gshared Identifier Exception; 53 | extern (C++) static __gshared Identifier RTInfo; 54 | extern (C++) static __gshared Identifier Throwable; 55 | extern (C++) static __gshared Identifier Error; 56 | extern (C++) static __gshared Identifier withSym; 57 | extern (C++) static __gshared Identifier result; 58 | extern (C++) static __gshared Identifier returnLabel; 59 | extern (C++) static __gshared Identifier line; 60 | extern (C++) static __gshared Identifier empty; 61 | extern (C++) static __gshared Identifier p; 62 | extern (C++) static __gshared Identifier q; 63 | extern (C++) static __gshared Identifier __vptr; 64 | extern (C++) static __gshared Identifier __monitor; 65 | extern (C++) static __gshared Identifier gate; 66 | extern (C++) static __gshared Identifier __c_long; 67 | extern (C++) static __gshared Identifier __c_ulong; 68 | extern (C++) static __gshared Identifier __c_long_double; 69 | extern (C++) static __gshared Identifier cpp_type_info_ptr; 70 | extern (C++) static __gshared Identifier TypeInfo; 71 | extern (C++) static __gshared Identifier TypeInfo_Class; 72 | extern (C++) static __gshared Identifier TypeInfo_Interface; 73 | extern (C++) static __gshared Identifier TypeInfo_Struct; 74 | extern (C++) static __gshared Identifier TypeInfo_Enum; 75 | extern (C++) static __gshared Identifier TypeInfo_Pointer; 76 | extern (C++) static __gshared Identifier TypeInfo_Vector; 77 | extern (C++) static __gshared Identifier TypeInfo_Array; 78 | extern (C++) static __gshared Identifier TypeInfo_StaticArray; 79 | extern (C++) static __gshared Identifier TypeInfo_AssociativeArray; 80 | extern (C++) static __gshared Identifier TypeInfo_Function; 81 | extern (C++) static __gshared Identifier TypeInfo_Delegate; 82 | extern (C++) static __gshared Identifier TypeInfo_Tuple; 83 | extern (C++) static __gshared Identifier TypeInfo_Const; 84 | extern (C++) static __gshared Identifier TypeInfo_Invariant; 85 | extern (C++) static __gshared Identifier TypeInfo_Shared; 86 | extern (C++) static __gshared Identifier TypeInfo_Wild; 87 | extern (C++) static __gshared Identifier elements; 88 | extern (C++) static __gshared Identifier _arguments_typeinfo; 89 | extern (C++) static __gshared Identifier _arguments; 90 | extern (C++) static __gshared Identifier _argptr; 91 | extern (C++) static __gshared Identifier destroy; 92 | extern (C++) static __gshared Identifier xopEquals; 93 | extern (C++) static __gshared Identifier xopCmp; 94 | extern (C++) static __gshared Identifier xtoHash; 95 | extern (C++) static __gshared Identifier LINE; 96 | extern (C++) static __gshared Identifier FILE; 97 | extern (C++) static __gshared Identifier MODULE; 98 | extern (C++) static __gshared Identifier FUNCTION; 99 | extern (C++) static __gshared Identifier PRETTY_FUNCTION; 100 | extern (C++) static __gshared Identifier DATE; 101 | extern (C++) static __gshared Identifier TIME; 102 | extern (C++) static __gshared Identifier TIMESTAMP; 103 | extern (C++) static __gshared Identifier VENDOR; 104 | extern (C++) static __gshared Identifier VERSIONX; 105 | extern (C++) static __gshared Identifier EOFX; 106 | extern (C++) static __gshared Identifier nan; 107 | extern (C++) static __gshared Identifier infinity; 108 | extern (C++) static __gshared Identifier dig; 109 | extern (C++) static __gshared Identifier epsilon; 110 | extern (C++) static __gshared Identifier mant_dig; 111 | extern (C++) static __gshared Identifier max_10_exp; 112 | extern (C++) static __gshared Identifier max_exp; 113 | extern (C++) static __gshared Identifier min_10_exp; 114 | extern (C++) static __gshared Identifier min_exp; 115 | extern (C++) static __gshared Identifier min_normal; 116 | extern (C++) static __gshared Identifier re; 117 | extern (C++) static __gshared Identifier im; 118 | extern (C++) static __gshared Identifier C; 119 | extern (C++) static __gshared Identifier D; 120 | extern (C++) static __gshared Identifier Windows; 121 | extern (C++) static __gshared Identifier Pascal; 122 | extern (C++) static __gshared Identifier System; 123 | extern (C++) static __gshared Identifier Objective; 124 | extern (C++) static __gshared Identifier exit; 125 | extern (C++) static __gshared Identifier success; 126 | extern (C++) static __gshared Identifier failure; 127 | extern (C++) static __gshared Identifier keys; 128 | extern (C++) static __gshared Identifier values; 129 | extern (C++) static __gshared Identifier rehash; 130 | extern (C++) static __gshared Identifier sort; 131 | extern (C++) static __gshared Identifier reverse; 132 | extern (C++) static __gshared Identifier property; 133 | extern (C++) static __gshared Identifier nogc; 134 | extern (C++) static __gshared Identifier safe; 135 | extern (C++) static __gshared Identifier trusted; 136 | extern (C++) static __gshared Identifier system; 137 | extern (C++) static __gshared Identifier disable; 138 | extern (C++) static __gshared Identifier ___out; 139 | extern (C++) static __gshared Identifier ___in; 140 | extern (C++) static __gshared Identifier __int; 141 | extern (C++) static __gshared Identifier _dollar; 142 | extern (C++) static __gshared Identifier __LOCAL_SIZE; 143 | extern (C++) static __gshared Identifier uadd; 144 | extern (C++) static __gshared Identifier neg; 145 | extern (C++) static __gshared Identifier com; 146 | extern (C++) static __gshared Identifier add; 147 | extern (C++) static __gshared Identifier add_r; 148 | extern (C++) static __gshared Identifier sub; 149 | extern (C++) static __gshared Identifier sub_r; 150 | extern (C++) static __gshared Identifier mul; 151 | extern (C++) static __gshared Identifier mul_r; 152 | extern (C++) static __gshared Identifier div; 153 | extern (C++) static __gshared Identifier div_r; 154 | extern (C++) static __gshared Identifier mod; 155 | extern (C++) static __gshared Identifier mod_r; 156 | extern (C++) static __gshared Identifier eq; 157 | extern (C++) static __gshared Identifier cmp; 158 | extern (C++) static __gshared Identifier iand; 159 | extern (C++) static __gshared Identifier iand_r; 160 | extern (C++) static __gshared Identifier ior; 161 | extern (C++) static __gshared Identifier ior_r; 162 | extern (C++) static __gshared Identifier ixor; 163 | extern (C++) static __gshared Identifier ixor_r; 164 | extern (C++) static __gshared Identifier shl; 165 | extern (C++) static __gshared Identifier shl_r; 166 | extern (C++) static __gshared Identifier shr; 167 | extern (C++) static __gshared Identifier shr_r; 168 | extern (C++) static __gshared Identifier ushr; 169 | extern (C++) static __gshared Identifier ushr_r; 170 | extern (C++) static __gshared Identifier cat; 171 | extern (C++) static __gshared Identifier cat_r; 172 | extern (C++) static __gshared Identifier assign; 173 | extern (C++) static __gshared Identifier addass; 174 | extern (C++) static __gshared Identifier subass; 175 | extern (C++) static __gshared Identifier mulass; 176 | extern (C++) static __gshared Identifier divass; 177 | extern (C++) static __gshared Identifier modass; 178 | extern (C++) static __gshared Identifier andass; 179 | extern (C++) static __gshared Identifier orass; 180 | extern (C++) static __gshared Identifier xorass; 181 | extern (C++) static __gshared Identifier shlass; 182 | extern (C++) static __gshared Identifier shrass; 183 | extern (C++) static __gshared Identifier ushrass; 184 | extern (C++) static __gshared Identifier catass; 185 | extern (C++) static __gshared Identifier postinc; 186 | extern (C++) static __gshared Identifier postdec; 187 | extern (C++) static __gshared Identifier index; 188 | extern (C++) static __gshared Identifier indexass; 189 | extern (C++) static __gshared Identifier slice; 190 | extern (C++) static __gshared Identifier sliceass; 191 | extern (C++) static __gshared Identifier call; 192 | extern (C++) static __gshared Identifier _cast; 193 | extern (C++) static __gshared Identifier opIn; 194 | extern (C++) static __gshared Identifier opIn_r; 195 | extern (C++) static __gshared Identifier opStar; 196 | extern (C++) static __gshared Identifier opDot; 197 | extern (C++) static __gshared Identifier opDispatch; 198 | extern (C++) static __gshared Identifier opDollar; 199 | extern (C++) static __gshared Identifier opUnary; 200 | extern (C++) static __gshared Identifier opIndexUnary; 201 | extern (C++) static __gshared Identifier opSliceUnary; 202 | extern (C++) static __gshared Identifier opBinary; 203 | extern (C++) static __gshared Identifier opBinaryRight; 204 | extern (C++) static __gshared Identifier opOpAssign; 205 | extern (C++) static __gshared Identifier opIndexOpAssign; 206 | extern (C++) static __gshared Identifier opSliceOpAssign; 207 | extern (C++) static __gshared Identifier pow; 208 | extern (C++) static __gshared Identifier pow_r; 209 | extern (C++) static __gshared Identifier powass; 210 | extern (C++) static __gshared Identifier classNew; 211 | extern (C++) static __gshared Identifier classDelete; 212 | extern (C++) static __gshared Identifier apply; 213 | extern (C++) static __gshared Identifier applyReverse; 214 | extern (C++) static __gshared Identifier Fempty; 215 | extern (C++) static __gshared Identifier Ffront; 216 | extern (C++) static __gshared Identifier Fback; 217 | extern (C++) static __gshared Identifier FpopFront; 218 | extern (C++) static __gshared Identifier FpopBack; 219 | extern (C++) static __gshared Identifier adReverse; 220 | extern (C++) static __gshared Identifier aaLen; 221 | extern (C++) static __gshared Identifier aaKeys; 222 | extern (C++) static __gshared Identifier aaValues; 223 | extern (C++) static __gshared Identifier aaRehash; 224 | extern (C++) static __gshared Identifier monitorenter; 225 | extern (C++) static __gshared Identifier monitorexit; 226 | extern (C++) static __gshared Identifier criticalenter; 227 | extern (C++) static __gshared Identifier criticalexit; 228 | extern (C++) static __gshared Identifier _ArrayEq; 229 | extern (C++) static __gshared Identifier _ArrayPostblit; 230 | extern (C++) static __gshared Identifier _ArrayDtor; 231 | extern (C++) static __gshared Identifier Pinline; 232 | extern (C++) static __gshared Identifier lib; 233 | extern (C++) static __gshared Identifier mangle; 234 | extern (C++) static __gshared Identifier msg; 235 | extern (C++) static __gshared Identifier startaddress; 236 | extern (C++) static __gshared Identifier tohash; 237 | extern (C++) static __gshared Identifier tostring; 238 | extern (C++) static __gshared Identifier getmembers; 239 | extern (C++) static __gshared Identifier __alloca; 240 | extern (C++) static __gshared Identifier main; 241 | extern (C++) static __gshared Identifier WinMain; 242 | extern (C++) static __gshared Identifier DllMain; 243 | extern (C++) static __gshared Identifier tls_get_addr; 244 | extern (C++) static __gshared Identifier entrypoint; 245 | extern (C++) static __gshared Identifier va_argsave_t; 246 | extern (C++) static __gshared Identifier va_argsave; 247 | extern (C++) static __gshared Identifier va_start; 248 | extern (C++) static __gshared Identifier std; 249 | extern (C++) static __gshared Identifier core; 250 | extern (C++) static __gshared Identifier attribute; 251 | extern (C++) static __gshared Identifier math; 252 | extern (C++) static __gshared Identifier sin; 253 | extern (C++) static __gshared Identifier cos; 254 | extern (C++) static __gshared Identifier tan; 255 | extern (C++) static __gshared Identifier _sqrt; 256 | extern (C++) static __gshared Identifier _pow; 257 | extern (C++) static __gshared Identifier atan2; 258 | extern (C++) static __gshared Identifier rndtol; 259 | extern (C++) static __gshared Identifier expm1; 260 | extern (C++) static __gshared Identifier exp2; 261 | extern (C++) static __gshared Identifier yl2x; 262 | extern (C++) static __gshared Identifier yl2xp1; 263 | extern (C++) static __gshared Identifier fabs; 264 | extern (C++) static __gshared Identifier bitop; 265 | extern (C++) static __gshared Identifier bsf; 266 | extern (C++) static __gshared Identifier bsr; 267 | extern (C++) static __gshared Identifier bswap; 268 | extern (C++) static __gshared Identifier isAbstractClass; 269 | extern (C++) static __gshared Identifier isArithmetic; 270 | extern (C++) static __gshared Identifier isAssociativeArray; 271 | extern (C++) static __gshared Identifier isFinalClass; 272 | extern (C++) static __gshared Identifier isTemplate; 273 | extern (C++) static __gshared Identifier isPOD; 274 | extern (C++) static __gshared Identifier isNested; 275 | extern (C++) static __gshared Identifier isFloating; 276 | extern (C++) static __gshared Identifier isIntegral; 277 | extern (C++) static __gshared Identifier isScalar; 278 | extern (C++) static __gshared Identifier isStaticArray; 279 | extern (C++) static __gshared Identifier isUnsigned; 280 | extern (C++) static __gshared Identifier isVirtualFunction; 281 | extern (C++) static __gshared Identifier isVirtualMethod; 282 | extern (C++) static __gshared Identifier isAbstractFunction; 283 | extern (C++) static __gshared Identifier isFinalFunction; 284 | extern (C++) static __gshared Identifier isOverrideFunction; 285 | extern (C++) static __gshared Identifier isStaticFunction; 286 | extern (C++) static __gshared Identifier isRef; 287 | extern (C++) static __gshared Identifier isOut; 288 | extern (C++) static __gshared Identifier isLazy; 289 | extern (C++) static __gshared Identifier hasMember; 290 | extern (C++) static __gshared Identifier identifier; 291 | extern (C++) static __gshared Identifier getProtection; 292 | extern (C++) static __gshared Identifier parent; 293 | extern (C++) static __gshared Identifier getMember; 294 | extern (C++) static __gshared Identifier getOverloads; 295 | extern (C++) static __gshared Identifier getVirtualFunctions; 296 | extern (C++) static __gshared Identifier getVirtualMethods; 297 | extern (C++) static __gshared Identifier classInstanceSize; 298 | extern (C++) static __gshared Identifier allMembers; 299 | extern (C++) static __gshared Identifier derivedMembers; 300 | extern (C++) static __gshared Identifier isSame; 301 | extern (C++) static __gshared Identifier compiles; 302 | extern (C++) static __gshared Identifier parameters; 303 | extern (C++) static __gshared Identifier getAliasThis; 304 | extern (C++) static __gshared Identifier getAttributes; 305 | extern (C++) static __gshared Identifier getFunctionAttributes; 306 | extern (C++) static __gshared Identifier getUnitTests; 307 | extern (C++) static __gshared Identifier getVirtualIndex; 308 | extern (C++) static __gshared Identifier getPointerBitmap; 309 | extern (C++) static __gshared Identifier allocator; 310 | extern (C++) static __gshared Identifier basic_string; 311 | extern (C++) static __gshared Identifier basic_istream; 312 | extern (C++) static __gshared Identifier basic_ostream; 313 | extern (C++) static __gshared Identifier basic_iostream; 314 | extern (C++) static __gshared Identifier char_traits; 315 | extern (C++) static __gshared Identifier udaSelector; 316 | 317 | extern (C++) static void initialize() 318 | { 319 | IUnknown = Identifier.idPool("IUnknown"); 320 | Object = Identifier.idPool("Object"); 321 | object = Identifier.idPool("object"); 322 | string = Identifier.idPool("string"); 323 | wstring = Identifier.idPool("wstring"); 324 | dstring = Identifier.idPool("dstring"); 325 | max = Identifier.idPool("max"); 326 | min = Identifier.idPool("min"); 327 | This = Identifier.idPool("this"); 328 | _super = Identifier.idPool("super"); 329 | ctor = Identifier.idPool("__ctor"); 330 | dtor = Identifier.idPool("__dtor"); 331 | __xdtor = Identifier.idPool("__xdtor"); 332 | __fieldDtor = Identifier.idPool("__fieldDtor"); 333 | __aggrDtor = Identifier.idPool("__aggrDtor"); 334 | postblit = Identifier.idPool("__postblit"); 335 | __xpostblit = Identifier.idPool("__xpostblit"); 336 | __fieldPostblit = Identifier.idPool("__fieldPostblit"); 337 | __aggrPostblit = Identifier.idPool("__aggrPostblit"); 338 | classInvariant = Identifier.idPool("__invariant"); 339 | unitTest = Identifier.idPool("__unitTest"); 340 | require = Identifier.idPool("__require"); 341 | ensure = Identifier.idPool("__ensure"); 342 | _init = Identifier.idPool("init"); 343 | __sizeof = Identifier.idPool("sizeof"); 344 | __xalignof = Identifier.idPool("alignof"); 345 | _mangleof = Identifier.idPool("mangleof"); 346 | stringof = Identifier.idPool("stringof"); 347 | _tupleof = Identifier.idPool("tupleof"); 348 | length = Identifier.idPool("length"); 349 | remove = Identifier.idPool("remove"); 350 | ptr = Identifier.idPool("ptr"); 351 | array = Identifier.idPool("array"); 352 | funcptr = Identifier.idPool("funcptr"); 353 | dollar = Identifier.idPool("__dollar"); 354 | ctfe = Identifier.idPool("__ctfe"); 355 | offset = Identifier.idPool("offset"); 356 | offsetof = Identifier.idPool("offsetof"); 357 | ModuleInfo = Identifier.idPool("ModuleInfo"); 358 | ClassInfo = Identifier.idPool("ClassInfo"); 359 | classinfo = Identifier.idPool("classinfo"); 360 | typeinfo = Identifier.idPool("typeinfo"); 361 | outer = Identifier.idPool("outer"); 362 | Exception = Identifier.idPool("Exception"); 363 | RTInfo = Identifier.idPool("RTInfo"); 364 | Throwable = Identifier.idPool("Throwable"); 365 | Error = Identifier.idPool("Error"); 366 | withSym = Identifier.idPool("__withSym"); 367 | result = Identifier.idPool("__result"); 368 | returnLabel = Identifier.idPool("__returnLabel"); 369 | line = Identifier.idPool("line"); 370 | empty = Identifier.idPool(""); 371 | p = Identifier.idPool("p"); 372 | q = Identifier.idPool("q"); 373 | __vptr = Identifier.idPool("__vptr"); 374 | __monitor = Identifier.idPool("__monitor"); 375 | gate = Identifier.idPool("__gate"); 376 | __c_long = Identifier.idPool("__c_long"); 377 | __c_ulong = Identifier.idPool("__c_ulong"); 378 | __c_long_double = Identifier.idPool("__c_long_double"); 379 | cpp_type_info_ptr = Identifier.idPool("__cpp_type_info_ptr"); 380 | TypeInfo = Identifier.idPool("TypeInfo"); 381 | TypeInfo_Class = Identifier.idPool("TypeInfo_Class"); 382 | TypeInfo_Interface = Identifier.idPool("TypeInfo_Interface"); 383 | TypeInfo_Struct = Identifier.idPool("TypeInfo_Struct"); 384 | TypeInfo_Enum = Identifier.idPool("TypeInfo_Enum"); 385 | TypeInfo_Pointer = Identifier.idPool("TypeInfo_Pointer"); 386 | TypeInfo_Vector = Identifier.idPool("TypeInfo_Vector"); 387 | TypeInfo_Array = Identifier.idPool("TypeInfo_Array"); 388 | TypeInfo_StaticArray = Identifier.idPool("TypeInfo_StaticArray"); 389 | TypeInfo_AssociativeArray = Identifier.idPool("TypeInfo_AssociativeArray"); 390 | TypeInfo_Function = Identifier.idPool("TypeInfo_Function"); 391 | TypeInfo_Delegate = Identifier.idPool("TypeInfo_Delegate"); 392 | TypeInfo_Tuple = Identifier.idPool("TypeInfo_Tuple"); 393 | TypeInfo_Const = Identifier.idPool("TypeInfo_Const"); 394 | TypeInfo_Invariant = Identifier.idPool("TypeInfo_Invariant"); 395 | TypeInfo_Shared = Identifier.idPool("TypeInfo_Shared"); 396 | TypeInfo_Wild = Identifier.idPool("TypeInfo_Inout"); 397 | elements = Identifier.idPool("elements"); 398 | _arguments_typeinfo = Identifier.idPool("_arguments_typeinfo"); 399 | _arguments = Identifier.idPool("_arguments"); 400 | _argptr = Identifier.idPool("_argptr"); 401 | destroy = Identifier.idPool("destroy"); 402 | xopEquals = Identifier.idPool("__xopEquals"); 403 | xopCmp = Identifier.idPool("__xopCmp"); 404 | xtoHash = Identifier.idPool("__xtoHash"); 405 | LINE = Identifier.idPool("__LINE__"); 406 | FILE = Identifier.idPool("__FILE__"); 407 | MODULE = Identifier.idPool("__MODULE__"); 408 | FUNCTION = Identifier.idPool("__FUNCTION__"); 409 | PRETTY_FUNCTION = Identifier.idPool("__PRETTY_FUNCTION__"); 410 | DATE = Identifier.idPool("__DATE__"); 411 | TIME = Identifier.idPool("__TIME__"); 412 | TIMESTAMP = Identifier.idPool("__TIMESTAMP__"); 413 | VENDOR = Identifier.idPool("__VENDOR__"); 414 | VERSIONX = Identifier.idPool("__VERSION__"); 415 | EOFX = Identifier.idPool("__EOF__"); 416 | nan = Identifier.idPool("nan"); 417 | infinity = Identifier.idPool("infinity"); 418 | dig = Identifier.idPool("dig"); 419 | epsilon = Identifier.idPool("epsilon"); 420 | mant_dig = Identifier.idPool("mant_dig"); 421 | max_10_exp = Identifier.idPool("max_10_exp"); 422 | max_exp = Identifier.idPool("max_exp"); 423 | min_10_exp = Identifier.idPool("min_10_exp"); 424 | min_exp = Identifier.idPool("min_exp"); 425 | min_normal = Identifier.idPool("min_normal"); 426 | re = Identifier.idPool("re"); 427 | im = Identifier.idPool("im"); 428 | C = Identifier.idPool("C"); 429 | D = Identifier.idPool("D"); 430 | Windows = Identifier.idPool("Windows"); 431 | Pascal = Identifier.idPool("Pascal"); 432 | System = Identifier.idPool("System"); 433 | Objective = Identifier.idPool("Objective"); 434 | exit = Identifier.idPool("exit"); 435 | success = Identifier.idPool("success"); 436 | failure = Identifier.idPool("failure"); 437 | keys = Identifier.idPool("keys"); 438 | values = Identifier.idPool("values"); 439 | rehash = Identifier.idPool("rehash"); 440 | sort = Identifier.idPool("sort"); 441 | reverse = Identifier.idPool("reverse"); 442 | property = Identifier.idPool("property"); 443 | nogc = Identifier.idPool("nogc"); 444 | safe = Identifier.idPool("safe"); 445 | trusted = Identifier.idPool("trusted"); 446 | system = Identifier.idPool("system"); 447 | disable = Identifier.idPool("disable"); 448 | ___out = Identifier.idPool("out"); 449 | ___in = Identifier.idPool("in"); 450 | __int = Identifier.idPool("int"); 451 | _dollar = Identifier.idPool("$"); 452 | __LOCAL_SIZE = Identifier.idPool("__LOCAL_SIZE"); 453 | uadd = Identifier.idPool("opPos"); 454 | neg = Identifier.idPool("opNeg"); 455 | com = Identifier.idPool("opCom"); 456 | add = Identifier.idPool("opAdd"); 457 | add_r = Identifier.idPool("opAdd_r"); 458 | sub = Identifier.idPool("opSub"); 459 | sub_r = Identifier.idPool("opSub_r"); 460 | mul = Identifier.idPool("opMul"); 461 | mul_r = Identifier.idPool("opMul_r"); 462 | div = Identifier.idPool("opDiv"); 463 | div_r = Identifier.idPool("opDiv_r"); 464 | mod = Identifier.idPool("opMod"); 465 | mod_r = Identifier.idPool("opMod_r"); 466 | eq = Identifier.idPool("opEquals"); 467 | cmp = Identifier.idPool("opCmp"); 468 | iand = Identifier.idPool("opAnd"); 469 | iand_r = Identifier.idPool("opAnd_r"); 470 | ior = Identifier.idPool("opOr"); 471 | ior_r = Identifier.idPool("opOr_r"); 472 | ixor = Identifier.idPool("opXor"); 473 | ixor_r = Identifier.idPool("opXor_r"); 474 | shl = Identifier.idPool("opShl"); 475 | shl_r = Identifier.idPool("opShl_r"); 476 | shr = Identifier.idPool("opShr"); 477 | shr_r = Identifier.idPool("opShr_r"); 478 | ushr = Identifier.idPool("opUShr"); 479 | ushr_r = Identifier.idPool("opUShr_r"); 480 | cat = Identifier.idPool("opCat"); 481 | cat_r = Identifier.idPool("opCat_r"); 482 | assign = Identifier.idPool("opAssign"); 483 | addass = Identifier.idPool("opAddAssign"); 484 | subass = Identifier.idPool("opSubAssign"); 485 | mulass = Identifier.idPool("opMulAssign"); 486 | divass = Identifier.idPool("opDivAssign"); 487 | modass = Identifier.idPool("opModAssign"); 488 | andass = Identifier.idPool("opAndAssign"); 489 | orass = Identifier.idPool("opOrAssign"); 490 | xorass = Identifier.idPool("opXorAssign"); 491 | shlass = Identifier.idPool("opShlAssign"); 492 | shrass = Identifier.idPool("opShrAssign"); 493 | ushrass = Identifier.idPool("opUShrAssign"); 494 | catass = Identifier.idPool("opCatAssign"); 495 | postinc = Identifier.idPool("opPostInc"); 496 | postdec = Identifier.idPool("opPostDec"); 497 | index = Identifier.idPool("opIndex"); 498 | indexass = Identifier.idPool("opIndexAssign"); 499 | slice = Identifier.idPool("opSlice"); 500 | sliceass = Identifier.idPool("opSliceAssign"); 501 | call = Identifier.idPool("opCall"); 502 | _cast = Identifier.idPool("opCast"); 503 | opIn = Identifier.idPool("opIn"); 504 | opIn_r = Identifier.idPool("opIn_r"); 505 | opStar = Identifier.idPool("opStar"); 506 | opDot = Identifier.idPool("opDot"); 507 | opDispatch = Identifier.idPool("opDispatch"); 508 | opDollar = Identifier.idPool("opDollar"); 509 | opUnary = Identifier.idPool("opUnary"); 510 | opIndexUnary = Identifier.idPool("opIndexUnary"); 511 | opSliceUnary = Identifier.idPool("opSliceUnary"); 512 | opBinary = Identifier.idPool("opBinary"); 513 | opBinaryRight = Identifier.idPool("opBinaryRight"); 514 | opOpAssign = Identifier.idPool("opOpAssign"); 515 | opIndexOpAssign = Identifier.idPool("opIndexOpAssign"); 516 | opSliceOpAssign = Identifier.idPool("opSliceOpAssign"); 517 | pow = Identifier.idPool("opPow"); 518 | pow_r = Identifier.idPool("opPow_r"); 519 | powass = Identifier.idPool("opPowAssign"); 520 | classNew = Identifier.idPool("new"); 521 | classDelete = Identifier.idPool("delete"); 522 | apply = Identifier.idPool("opApply"); 523 | applyReverse = Identifier.idPool("opApplyReverse"); 524 | Fempty = Identifier.idPool("empty"); 525 | Ffront = Identifier.idPool("front"); 526 | Fback = Identifier.idPool("back"); 527 | FpopFront = Identifier.idPool("popFront"); 528 | FpopBack = Identifier.idPool("popBack"); 529 | adReverse = Identifier.idPool("_adReverse"); 530 | aaLen = Identifier.idPool("_aaLen"); 531 | aaKeys = Identifier.idPool("_aaKeys"); 532 | aaValues = Identifier.idPool("_aaValues"); 533 | aaRehash = Identifier.idPool("_aaRehash"); 534 | monitorenter = Identifier.idPool("_d_monitorenter"); 535 | monitorexit = Identifier.idPool("_d_monitorexit"); 536 | criticalenter = Identifier.idPool("_d_criticalenter"); 537 | criticalexit = Identifier.idPool("_d_criticalexit"); 538 | _ArrayEq = Identifier.idPool("_ArrayEq"); 539 | _ArrayPostblit = Identifier.idPool("_ArrayPostblit"); 540 | _ArrayDtor = Identifier.idPool("_ArrayDtor"); 541 | Pinline = Identifier.idPool("inline"); 542 | lib = Identifier.idPool("lib"); 543 | mangle = Identifier.idPool("mangle"); 544 | msg = Identifier.idPool("msg"); 545 | startaddress = Identifier.idPool("startaddress"); 546 | tohash = Identifier.idPool("toHash"); 547 | tostring = Identifier.idPool("toString"); 548 | getmembers = Identifier.idPool("getMembers"); 549 | __alloca = Identifier.idPool("alloca"); 550 | main = Identifier.idPool("main"); 551 | WinMain = Identifier.idPool("WinMain"); 552 | DllMain = Identifier.idPool("DllMain"); 553 | tls_get_addr = Identifier.idPool("___tls_get_addr"); 554 | entrypoint = Identifier.idPool("__entrypoint"); 555 | va_argsave_t = Identifier.idPool("__va_argsave_t"); 556 | va_argsave = Identifier.idPool("__va_argsave"); 557 | va_start = Identifier.idPool("va_start"); 558 | std = Identifier.idPool("std"); 559 | core = Identifier.idPool("core"); 560 | attribute = Identifier.idPool("attribute"); 561 | math = Identifier.idPool("math"); 562 | sin = Identifier.idPool("sin"); 563 | cos = Identifier.idPool("cos"); 564 | tan = Identifier.idPool("tan"); 565 | _sqrt = Identifier.idPool("sqrt"); 566 | _pow = Identifier.idPool("pow"); 567 | atan2 = Identifier.idPool("atan2"); 568 | rndtol = Identifier.idPool("rndtol"); 569 | expm1 = Identifier.idPool("expm1"); 570 | exp2 = Identifier.idPool("exp2"); 571 | yl2x = Identifier.idPool("yl2x"); 572 | yl2xp1 = Identifier.idPool("yl2xp1"); 573 | fabs = Identifier.idPool("fabs"); 574 | bitop = Identifier.idPool("bitop"); 575 | bsf = Identifier.idPool("bsf"); 576 | bsr = Identifier.idPool("bsr"); 577 | bswap = Identifier.idPool("bswap"); 578 | isAbstractClass = Identifier.idPool("isAbstractClass"); 579 | isArithmetic = Identifier.idPool("isArithmetic"); 580 | isAssociativeArray = Identifier.idPool("isAssociativeArray"); 581 | isFinalClass = Identifier.idPool("isFinalClass"); 582 | isTemplate = Identifier.idPool("isTemplate"); 583 | isPOD = Identifier.idPool("isPOD"); 584 | isNested = Identifier.idPool("isNested"); 585 | isFloating = Identifier.idPool("isFloating"); 586 | isIntegral = Identifier.idPool("isIntegral"); 587 | isScalar = Identifier.idPool("isScalar"); 588 | isStaticArray = Identifier.idPool("isStaticArray"); 589 | isUnsigned = Identifier.idPool("isUnsigned"); 590 | isVirtualFunction = Identifier.idPool("isVirtualFunction"); 591 | isVirtualMethod = Identifier.idPool("isVirtualMethod"); 592 | isAbstractFunction = Identifier.idPool("isAbstractFunction"); 593 | isFinalFunction = Identifier.idPool("isFinalFunction"); 594 | isOverrideFunction = Identifier.idPool("isOverrideFunction"); 595 | isStaticFunction = Identifier.idPool("isStaticFunction"); 596 | isRef = Identifier.idPool("isRef"); 597 | isOut = Identifier.idPool("isOut"); 598 | isLazy = Identifier.idPool("isLazy"); 599 | hasMember = Identifier.idPool("hasMember"); 600 | identifier = Identifier.idPool("identifier"); 601 | getProtection = Identifier.idPool("getProtection"); 602 | parent = Identifier.idPool("parent"); 603 | getMember = Identifier.idPool("getMember"); 604 | getOverloads = Identifier.idPool("getOverloads"); 605 | getVirtualFunctions = Identifier.idPool("getVirtualFunctions"); 606 | getVirtualMethods = Identifier.idPool("getVirtualMethods"); 607 | classInstanceSize = Identifier.idPool("classInstanceSize"); 608 | allMembers = Identifier.idPool("allMembers"); 609 | derivedMembers = Identifier.idPool("derivedMembers"); 610 | isSame = Identifier.idPool("isSame"); 611 | compiles = Identifier.idPool("compiles"); 612 | parameters = Identifier.idPool("parameters"); 613 | getAliasThis = Identifier.idPool("getAliasThis"); 614 | getAttributes = Identifier.idPool("getAttributes"); 615 | getFunctionAttributes = Identifier.idPool("getFunctionAttributes"); 616 | getUnitTests = Identifier.idPool("getUnitTests"); 617 | getVirtualIndex = Identifier.idPool("getVirtualIndex"); 618 | getPointerBitmap = Identifier.idPool("getPointerBitmap"); 619 | allocator = Identifier.idPool("allocator"); 620 | basic_string = Identifier.idPool("basic_string"); 621 | basic_istream = Identifier.idPool("basic_istream"); 622 | basic_ostream = Identifier.idPool("basic_ostream"); 623 | basic_iostream = Identifier.idPool("basic_iostream"); 624 | char_traits = Identifier.idPool("char_traits"); 625 | udaSelector = Identifier.idPool("selector"); 626 | } 627 | } 628 | -------------------------------------------------------------------------------- /source/ddmd/identifier.d: -------------------------------------------------------------------------------- 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.identifier; 10 | 11 | import core.stdc.ctype; 12 | import core.stdc.stdio; 13 | import core.stdc.string; 14 | import ddmd.globals; 15 | import ddmd.id; 16 | import ddmd.root.outbuffer; 17 | import ddmd.root.rootobject; 18 | import ddmd.root.stringtable; 19 | import ddmd.tokens; 20 | import ddmd.utf; 21 | 22 | /*********************************************************** 23 | */ 24 | extern (C++) final class Identifier : RootObject 25 | { 26 | public: 27 | int value; 28 | const(char)* string; 29 | size_t len; 30 | 31 | extern (D) this(const(char)* string, int value) 32 | { 33 | //printf("Identifier('%s', %d)\n", string, value); 34 | this.string = string; 35 | this.value = value; 36 | this.len = strlen(string); 37 | } 38 | 39 | static Identifier create(const(char)* string, int value) 40 | { 41 | return new Identifier(string, value); 42 | } 43 | 44 | override bool equals(RootObject o) const 45 | { 46 | return this == o || strncmp(string, o.toChars(), len + 1) == 0; 47 | } 48 | 49 | override int compare(RootObject o) const 50 | { 51 | return strncmp(string, o.toChars(), len + 1); 52 | } 53 | 54 | override void print() const 55 | { 56 | fprintf(stderr, "%s", string); 57 | } 58 | 59 | override const(char)* toChars() const 60 | { 61 | return string; 62 | } 63 | 64 | const(char)* toHChars2() const 65 | { 66 | const(char)* p = null; 67 | if (this == Id.ctor) 68 | p = "this"; 69 | else if (this == Id.dtor) 70 | p = "~this"; 71 | else if (this == Id.unitTest) 72 | p = "unittest"; 73 | else if (this == Id.dollar) 74 | p = "$"; 75 | else if (this == Id.withSym) 76 | p = "with"; 77 | else if (this == Id.result) 78 | p = "result"; 79 | else if (this == Id.returnLabel) 80 | p = "return"; 81 | else 82 | { 83 | p = toChars(); 84 | if (*p == '_') 85 | { 86 | if (strncmp(p, "_staticCtor", 11) == 0) 87 | p = "static this"; 88 | else if (strncmp(p, "_staticDtor", 11) == 0) 89 | p = "static ~this"; 90 | else if (strncmp(p, "__invariant", 11) == 0) 91 | p = "invariant"; 92 | } 93 | } 94 | return p; 95 | } 96 | 97 | override int dyncast() const 98 | { 99 | return DYNCAST_IDENTIFIER; 100 | } 101 | 102 | extern (C++) static __gshared StringTable stringtable; 103 | 104 | static Identifier generateId(const(char)* prefix) 105 | { 106 | static __gshared size_t i; 107 | return generateId(prefix, ++i); 108 | } 109 | 110 | static Identifier generateId(const(char)* prefix, size_t i) 111 | { 112 | OutBuffer buf; 113 | buf.writestring(prefix); 114 | buf.printf("%llu", cast(ulong)i); 115 | return idPool(buf.peekSlice()); 116 | } 117 | 118 | /******************************************** 119 | * Create an identifier in the string table. 120 | */ 121 | extern (D) static Identifier idPool(const(char)[] s) 122 | { 123 | return idPool(s.ptr, s.length); 124 | } 125 | 126 | static Identifier idPool(const(char)* s, size_t len) 127 | { 128 | StringValue* sv = stringtable.update(s, len); 129 | Identifier id = cast(Identifier)sv.ptrvalue; 130 | if (!id) 131 | { 132 | id = new Identifier(sv.toDchars(), TOKidentifier); 133 | sv.ptrvalue = cast(char*)id; 134 | } 135 | return id; 136 | } 137 | 138 | /********************************** 139 | * Determine if string is a valid Identifier. 140 | * Returns: 141 | * 0 invalid 142 | */ 143 | final static bool isValidIdentifier(const(char)* p) 144 | { 145 | size_t len; 146 | size_t idx; 147 | if (!p || !*p) 148 | goto Linvalid; 149 | if (*p >= '0' && *p <= '9') // beware of isdigit() on signed chars 150 | goto Linvalid; 151 | len = strlen(p); 152 | idx = 0; 153 | while (p[idx]) 154 | { 155 | dchar dc; 156 | const q = utf_decodeChar(p, len, idx, dc); 157 | if (q) 158 | goto Linvalid; 159 | if (!((dc >= 0x80 && isUniAlpha(dc)) || isalnum(dc) || dc == '_')) 160 | goto Linvalid; 161 | } 162 | return true; 163 | Linvalid: 164 | return false; 165 | } 166 | 167 | static Identifier lookup(const(char)* s, size_t len) 168 | { 169 | StringValue* sv = stringtable.lookup(s, len); 170 | if (!sv) 171 | return null; 172 | return cast(Identifier)sv.ptrvalue; 173 | } 174 | 175 | static void initTable() 176 | { 177 | stringtable._init(28000); 178 | } 179 | } 180 | -------------------------------------------------------------------------------- /source/ddmd/root/array.d: -------------------------------------------------------------------------------- 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.root.array; 10 | 11 | import core.stdc.string; 12 | 13 | import ddmd.root.rmem; 14 | 15 | extern (C++) struct Array(T) 16 | { 17 | public: 18 | size_t dim; 19 | T* data; 20 | 21 | private: 22 | size_t allocdim; 23 | enum SMALLARRAYCAP = 1; 24 | T[SMALLARRAYCAP] smallarray; // inline storage for small arrays 25 | 26 | public: 27 | ~this() 28 | { 29 | if (data != &smallarray[0]) 30 | mem.xfree(data); 31 | } 32 | 33 | const(char)* toChars() 34 | { 35 | static if (is(typeof(T.init.toChars()))) 36 | { 37 | const(char)** buf = cast(const(char)**)mem.xmalloc(dim * (char*).sizeof); 38 | size_t len = 2; 39 | for (size_t u = 0; u < dim; u++) 40 | { 41 | buf[u] = data[u].toChars(); 42 | len += strlen(buf[u]) + 1; 43 | } 44 | char* str = cast(char*)mem.xmalloc(len); 45 | 46 | str[0] = '['; 47 | char* p = str + 1; 48 | for (size_t u = 0; u < dim; u++) 49 | { 50 | if (u) 51 | *p++ = ','; 52 | len = strlen(buf[u]); 53 | memcpy(p, buf[u], len); 54 | p += len; 55 | } 56 | *p++ = ']'; 57 | *p = 0; 58 | mem.xfree(buf); 59 | return str; 60 | } 61 | else 62 | { 63 | assert(0); 64 | } 65 | } 66 | 67 | void push(T ptr) 68 | { 69 | reserve(1); 70 | data[dim++] = ptr; 71 | } 72 | 73 | void append(typeof(this)* a) 74 | { 75 | insert(dim, a); 76 | } 77 | 78 | void reserve(size_t nentries) 79 | { 80 | //printf("Array::reserve: dim = %d, allocdim = %d, nentries = %d\n", (int)dim, (int)allocdim, (int)nentries); 81 | if (allocdim - dim < nentries) 82 | { 83 | if (allocdim == 0) 84 | { 85 | // Not properly initialized, someone memset it to zero 86 | if (nentries <= SMALLARRAYCAP) 87 | { 88 | allocdim = SMALLARRAYCAP; 89 | data = SMALLARRAYCAP ? smallarray.ptr : null; 90 | } 91 | else 92 | { 93 | allocdim = nentries; 94 | data = cast(T*)mem.xmalloc(allocdim * (*data).sizeof); 95 | } 96 | } 97 | else if (allocdim == SMALLARRAYCAP) 98 | { 99 | allocdim = dim + nentries; 100 | data = cast(T*)mem.xmalloc(allocdim * (*data).sizeof); 101 | memcpy(data, smallarray.ptr, dim * (*data).sizeof); 102 | } 103 | else 104 | { 105 | allocdim = dim + nentries; 106 | data = cast(T*)mem.xrealloc(data, allocdim * (*data).sizeof); 107 | } 108 | } 109 | } 110 | 111 | void remove(size_t i) 112 | { 113 | if (dim - i - 1) 114 | memmove(data + i, data + i + 1, (dim - i - 1) * (data[0]).sizeof); 115 | dim--; 116 | } 117 | 118 | void insert(size_t index, typeof(this)* a) 119 | { 120 | if (a) 121 | { 122 | size_t d = a.dim; 123 | reserve(d); 124 | if (dim != index) 125 | memmove(data + index + d, data + index, (dim - index) * (*data).sizeof); 126 | memcpy(data + index, a.data, d * (*data).sizeof); 127 | dim += d; 128 | } 129 | } 130 | 131 | void insert(size_t index, T ptr) 132 | { 133 | reserve(1); 134 | memmove(data + index + 1, data + index, (dim - index) * (*data).sizeof); 135 | data[index] = ptr; 136 | dim++; 137 | } 138 | 139 | void setDim(size_t newdim) 140 | { 141 | if (dim < newdim) 142 | { 143 | reserve(newdim - dim); 144 | } 145 | dim = newdim; 146 | } 147 | 148 | ref inout(T) opIndex(size_t i) inout 149 | { 150 | return data[i]; 151 | } 152 | 153 | inout(T)* tdata() inout 154 | { 155 | return data; 156 | } 157 | 158 | Array!T* copy() const 159 | { 160 | auto a = new Array!T(); 161 | a.setDim(dim); 162 | memcpy(a.data, data, dim * (void*).sizeof); 163 | return a; 164 | } 165 | 166 | void shift(T ptr) 167 | { 168 | reserve(1); 169 | memmove(data + 1, data, dim * (*data).sizeof); 170 | data[0] = ptr; 171 | dim++; 172 | } 173 | 174 | void zero() 175 | { 176 | data[0 .. dim] = T.init; 177 | } 178 | 179 | T pop() 180 | { 181 | return data[--dim]; 182 | } 183 | 184 | int apply(int function(T, void*) fp, void* param) 185 | { 186 | static if (is(typeof(T.init.apply(fp, null)))) 187 | { 188 | for (size_t i = 0; i < dim; i++) 189 | { 190 | T e = data[i]; 191 | if (e) 192 | { 193 | if (e.apply(fp, param)) 194 | return 1; 195 | } 196 | } 197 | return 0; 198 | } 199 | else 200 | assert(0); 201 | } 202 | 203 | extern (D) inout(T)[] opSlice() inout 204 | { 205 | return data[0 .. dim]; 206 | } 207 | 208 | extern (D) inout(T)[] opSlice(size_t a, size_t b) inout 209 | { 210 | assert(a <= b && b <= dim); 211 | return data[a .. b]; 212 | } 213 | } 214 | 215 | struct BitArray 216 | { 217 | size_t length() const 218 | { 219 | return len; 220 | } 221 | 222 | void length(size_t nlen) 223 | { 224 | immutable obytes = (len + 7) / 8; 225 | immutable nbytes = (nlen + 7) / 8; 226 | ptr = cast(size_t*)mem.xrealloc(ptr, nbytes); 227 | if (nbytes > obytes) 228 | (cast(ubyte*)ptr)[obytes .. nbytes] = 0; 229 | len = nlen; 230 | } 231 | 232 | bool opIndex(size_t idx) const 233 | { 234 | import core.bitop : bt; 235 | 236 | assert(idx < length); 237 | return !!bt(ptr, idx); 238 | } 239 | 240 | void opIndexAssign(bool val, size_t idx) 241 | { 242 | import core.bitop : btc, bts; 243 | 244 | assert(idx < length); 245 | if (val) 246 | bts(ptr, idx); 247 | else 248 | btc(ptr, idx); 249 | } 250 | 251 | @disable this(this); 252 | 253 | ~this() 254 | { 255 | mem.xfree(ptr); 256 | } 257 | 258 | private: 259 | size_t len; 260 | size_t *ptr; 261 | } 262 | -------------------------------------------------------------------------------- /source/ddmd/root/file.d: -------------------------------------------------------------------------------- 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.root.file; 10 | 11 | import core.stdc.errno, core.stdc.stdio, core.stdc.stdlib, core.stdc.string, core.sys.posix.fcntl, core.sys.posix.sys.types, core.sys.posix.unistd, core.sys.posix.utime, core.sys.windows.windows; 12 | import ddmd.root.array, ddmd.root.filename, ddmd.root.rmem; 13 | 14 | version (Windows) alias WIN32_FIND_DATAA = WIN32_FIND_DATA; 15 | 16 | /*********************************************************** 17 | */ 18 | struct File 19 | { 20 | int _ref; // != 0 if this is a reference to someone else's buffer 21 | ubyte* buffer; // data for our file 22 | size_t len; // amount of data in buffer[] 23 | const(FileName)* name; // name of our file 24 | 25 | extern (D) this(const(char)* n) 26 | { 27 | _ref = 0; 28 | buffer = null; 29 | len = 0; 30 | name = new FileName(n); 31 | } 32 | 33 | extern (C++) static File* create(const(char)* n) 34 | { 35 | return new File(n); 36 | } 37 | 38 | extern (D) this(const(FileName)* n) 39 | { 40 | _ref = 0; 41 | buffer = null; 42 | len = 0; 43 | name = n; 44 | } 45 | 46 | extern (C++) ~this() 47 | { 48 | if (buffer) 49 | { 50 | if (_ref == 0) 51 | mem.xfree(buffer); 52 | version (Windows) 53 | { 54 | if (_ref == 2) 55 | UnmapViewOfFile(buffer); 56 | } 57 | } 58 | } 59 | 60 | extern (C++) const(char)* toChars() 61 | { 62 | return name.toChars(); 63 | } 64 | 65 | /************************************* 66 | */ 67 | extern (C++) bool read() 68 | { 69 | if (len) 70 | return false; // already read the file 71 | version (Posix) 72 | { 73 | size_t size; 74 | stat_t buf; 75 | ssize_t numread; 76 | const(char)* name = this.name.toChars(); 77 | //printf("File::read('%s')\n",name); 78 | int fd = open(name, O_RDONLY); 79 | if (fd == -1) 80 | { 81 | //printf("\topen error, errno = %d\n",errno); 82 | goto err1; 83 | } 84 | if (!_ref) 85 | .free(buffer); 86 | _ref = 0; // we own the buffer now 87 | //printf("\tfile opened\n"); 88 | if (fstat(fd, &buf)) 89 | { 90 | printf("\tfstat error, errno = %d\n", errno); 91 | goto err2; 92 | } 93 | size = cast(size_t)buf.st_size; 94 | buffer = cast(ubyte*).malloc(size + 2); 95 | if (!buffer) 96 | { 97 | printf("\tmalloc error, errno = %d\n", errno); 98 | goto err2; 99 | } 100 | numread = .read(fd, buffer, size); 101 | if (numread != size) 102 | { 103 | printf("\tread error, errno = %d\n", errno); 104 | goto err2; 105 | } 106 | if (close(fd) == -1) 107 | { 108 | printf("\tclose error, errno = %d\n", errno); 109 | goto err; 110 | } 111 | len = size; 112 | // Always store a wchar ^Z past end of buffer so scanner has a sentinel 113 | buffer[size] = 0; // ^Z is obsolete, use 0 114 | buffer[size + 1] = 0; 115 | return false; 116 | err2: 117 | close(fd); 118 | err: 119 | .free(buffer); 120 | buffer = null; 121 | len = 0; 122 | err1: 123 | return true; 124 | } 125 | else version (Windows) 126 | { 127 | DWORD size; 128 | DWORD numread; 129 | const(char)* name = this.name.toChars(); 130 | HANDLE h = CreateFileA(name, GENERIC_READ, FILE_SHARE_READ, null, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, null); 131 | if (h == INVALID_HANDLE_VALUE) 132 | goto err1; 133 | if (!_ref) 134 | .free(buffer); 135 | _ref = 0; 136 | size = GetFileSize(h, null); 137 | buffer = cast(ubyte*).malloc(size + 2); 138 | if (!buffer) 139 | goto err2; 140 | if (ReadFile(h, buffer, size, &numread, null) != TRUE) 141 | goto err2; 142 | if (numread != size) 143 | goto err2; 144 | if (!CloseHandle(h)) 145 | goto err; 146 | len = size; 147 | // Always store a wchar ^Z past end of buffer so scanner has a sentinel 148 | buffer[size] = 0; // ^Z is obsolete, use 0 149 | buffer[size + 1] = 0; 150 | return 0; 151 | err2: 152 | CloseHandle(h); 153 | err: 154 | .free(buffer); 155 | buffer = null; 156 | len = 0; 157 | err1: 158 | return true; 159 | } 160 | else 161 | { 162 | assert(0); 163 | } 164 | } 165 | 166 | /********************************************* 167 | * Write a file. 168 | * Returns: 169 | * false success 170 | */ 171 | extern (C++) bool write() 172 | { 173 | version (Posix) 174 | { 175 | ssize_t numwritten; 176 | const(char)* name = this.name.toChars(); 177 | int fd = open(name, O_CREAT | O_WRONLY | O_TRUNC, (6 << 6) | (4 << 3) | 4); 178 | if (fd == -1) 179 | goto err; 180 | numwritten = .write(fd, buffer, len); 181 | if (len != numwritten) 182 | goto err2; 183 | if (close(fd) == -1) 184 | goto err; 185 | return false; 186 | err2: 187 | close(fd); 188 | .remove(name); 189 | err: 190 | return true; 191 | } 192 | else version (Windows) 193 | { 194 | DWORD numwritten; 195 | const(char)* name = this.name.toChars(); 196 | HANDLE h = CreateFileA(name, GENERIC_WRITE, 0, null, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, null); 197 | if (h == INVALID_HANDLE_VALUE) 198 | goto err; 199 | if (WriteFile(h, buffer, cast(DWORD)len, &numwritten, null) != TRUE) 200 | goto err2; 201 | if (len != numwritten) 202 | goto err2; 203 | if (!CloseHandle(h)) 204 | goto err; 205 | return false; 206 | err2: 207 | CloseHandle(h); 208 | DeleteFileA(name); 209 | err: 210 | return true; 211 | } 212 | else 213 | { 214 | assert(0); 215 | } 216 | } 217 | 218 | /* Set buffer 219 | */ 220 | extern (C++) void setbuffer(void* buffer, size_t len) 221 | { 222 | this.buffer = cast(ubyte*)buffer; 223 | this.len = len; 224 | } 225 | 226 | // delete file 227 | extern (C++) void remove() 228 | { 229 | version (Posix) 230 | { 231 | int dummy = .remove(this.name.toChars()); 232 | } 233 | else version (Windows) 234 | { 235 | DeleteFileA(this.name.toChars()); 236 | } 237 | else 238 | { 239 | assert(0); 240 | } 241 | } 242 | } 243 | -------------------------------------------------------------------------------- /source/ddmd/root/filename.d: -------------------------------------------------------------------------------- 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.root.filename; 10 | 11 | import core.stdc.ctype, core.stdc.errno, core.stdc.stdlib, core.stdc.string, core.sys.posix.stdlib, core.sys.posix.sys.stat, core.sys.windows.windows; 12 | import ddmd.root.array, ddmd.root.file, ddmd.root.outbuffer, ddmd.root.rmem, ddmd.root.rootobject; 13 | 14 | version (Windows) extern (C) int mkdir(const char*); 15 | version (Windows) alias _mkdir = mkdir; 16 | version (Posix) extern (C) char* canonicalize_file_name(const char*); 17 | version (Windows) extern (C) int stricmp(const char*, const char*); 18 | version (Windows) extern (Windows) DWORD GetFullPathNameA(LPCSTR lpFileName, DWORD nBufferLength, LPSTR lpBuffer, LPSTR* lpFilePart); 19 | 20 | alias Strings = Array!(const(char)*); 21 | alias Files = Array!(File*); 22 | 23 | /*********************************************************** 24 | */ 25 | struct FileName 26 | { 27 | const(char)* str; 28 | 29 | extern (D) this(const(char)* str) 30 | { 31 | this.str = mem.xstrdup(str); 32 | } 33 | 34 | extern (C++) bool equals(const RootObject obj) const 35 | { 36 | return compare(obj) == 0; 37 | } 38 | 39 | extern (C++) static bool equals(const(char)* name1, const(char)* name2) 40 | { 41 | return compare(name1, name2) == 0; 42 | } 43 | 44 | extern (C++) int compare(const RootObject obj) const 45 | { 46 | return compare(str, (cast(FileName*)obj).str); 47 | } 48 | 49 | extern (C++) static int compare(const(char)* name1, const(char)* name2) 50 | { 51 | version (Windows) 52 | { 53 | return stricmp(name1, name2); 54 | } 55 | else 56 | { 57 | return strcmp(name1, name2); 58 | } 59 | } 60 | 61 | /************************************ 62 | * Return !=0 if absolute path name. 63 | */ 64 | extern (C++) static bool absolute(const(char)* name) 65 | { 66 | version (Windows) 67 | { 68 | return (*name == '\\') || (*name == '/') || (*name && name[1] == ':'); 69 | } 70 | else version (Posix) 71 | { 72 | return (*name == '/'); 73 | } 74 | else 75 | { 76 | assert(0); 77 | } 78 | } 79 | 80 | /******************************** 81 | * Return filename extension (read-only). 82 | * Points past '.' of extension. 83 | * If there isn't one, return NULL. 84 | */ 85 | extern (C++) static const(char)* ext(const(char)* str) 86 | { 87 | size_t len = strlen(str); 88 | const(char)* e = str + len; 89 | for (;;) 90 | { 91 | switch (*e) 92 | { 93 | case '.': 94 | return e + 1; 95 | version (Posix) 96 | { 97 | case '/': 98 | break; 99 | } 100 | version (Windows) 101 | { 102 | case '\\': 103 | case ':': 104 | case '/': 105 | break; 106 | } 107 | default: 108 | if (e == str) 109 | break; 110 | e--; 111 | continue; 112 | } 113 | return null; 114 | } 115 | } 116 | 117 | extern (C++) const(char)* ext() const 118 | { 119 | return ext(str); 120 | } 121 | 122 | /******************************** 123 | * Return mem.xmalloc'd filename with extension removed. 124 | */ 125 | extern (C++) static const(char)* removeExt(const(char)* str) 126 | { 127 | const(char)* e = ext(str); 128 | if (e) 129 | { 130 | size_t len = (e - str) - 1; 131 | char* n = cast(char*)mem.xmalloc(len + 1); 132 | memcpy(n, str, len); 133 | n[len] = 0; 134 | return n; 135 | } 136 | return mem.xstrdup(str); 137 | } 138 | 139 | /******************************** 140 | * Return filename name excluding path (read-only). 141 | */ 142 | extern (C++) static const(char)* name(const(char)* str) 143 | { 144 | size_t len = strlen(str); 145 | const(char)* e = str + len; 146 | for (;;) 147 | { 148 | switch (*e) 149 | { 150 | version (Posix) 151 | { 152 | case '/': 153 | return e + 1; 154 | } 155 | version (Windows) 156 | { 157 | case '/': 158 | case '\\': 159 | return e + 1; 160 | case ':': 161 | /* The ':' is a drive letter only if it is the second 162 | * character or the last character, 163 | * otherwise it is an ADS (Alternate Data Stream) separator. 164 | * Consider ADS separators as part of the file name. 165 | */ 166 | if (e == str + 1 || e == str + len - 1) 167 | return e + 1; 168 | goto default; 169 | } 170 | default: 171 | if (e == str) 172 | break; 173 | e--; 174 | continue; 175 | } 176 | return e; 177 | } 178 | assert(0); 179 | } 180 | 181 | extern (C++) const(char)* name() const 182 | { 183 | return name(str); 184 | } 185 | 186 | /************************************** 187 | * Return path portion of str. 188 | * Path will does not include trailing path separator. 189 | */ 190 | extern (C++) static const(char)* path(const(char)* str) 191 | { 192 | const(char)* n = name(str); 193 | size_t pathlen; 194 | if (n > str) 195 | { 196 | version (Posix) 197 | { 198 | if (n[-1] == '/') 199 | n--; 200 | } 201 | else version (Windows) 202 | { 203 | if (n[-1] == '\\' || n[-1] == '/') 204 | n--; 205 | } 206 | else 207 | { 208 | assert(0); 209 | } 210 | } 211 | pathlen = n - str; 212 | char* path = cast(char*)mem.xmalloc(pathlen + 1); 213 | memcpy(path, str, pathlen); 214 | path[pathlen] = 0; 215 | return path; 216 | } 217 | 218 | /************************************** 219 | * Replace filename portion of path. 220 | */ 221 | extern (C++) static const(char)* replaceName(const(char)* path, const(char)* name) 222 | { 223 | size_t pathlen; 224 | size_t namelen; 225 | if (absolute(name)) 226 | return name; 227 | const(char)* n = FileName.name(path); 228 | if (n == path) 229 | return name; 230 | pathlen = n - path; 231 | namelen = strlen(name); 232 | char* f = cast(char*)mem.xmalloc(pathlen + 1 + namelen + 1); 233 | memcpy(f, path, pathlen); 234 | version (Posix) 235 | { 236 | if (path[pathlen - 1] != '/') 237 | { 238 | f[pathlen] = '/'; 239 | pathlen++; 240 | } 241 | } 242 | else version (Windows) 243 | { 244 | if (path[pathlen - 1] != '\\' && path[pathlen - 1] != '/' && path[pathlen - 1] != ':') 245 | { 246 | f[pathlen] = '\\'; 247 | pathlen++; 248 | } 249 | } 250 | else 251 | { 252 | assert(0); 253 | } 254 | memcpy(f + pathlen, name, namelen + 1); 255 | return f; 256 | } 257 | 258 | extern (C++) static const(char)* combine(const(char)* path, const(char)* name) 259 | { 260 | char* f; 261 | size_t pathlen; 262 | size_t namelen; 263 | if (!path || !*path) 264 | return cast(char*)name; 265 | pathlen = strlen(path); 266 | namelen = strlen(name); 267 | f = cast(char*)mem.xmalloc(pathlen + 1 + namelen + 1); 268 | memcpy(f, path, pathlen); 269 | version (Posix) 270 | { 271 | if (path[pathlen - 1] != '/') 272 | { 273 | f[pathlen] = '/'; 274 | pathlen++; 275 | } 276 | } 277 | else version (Windows) 278 | { 279 | if (path[pathlen - 1] != '\\' && path[pathlen - 1] != '/' && path[pathlen - 1] != ':') 280 | { 281 | f[pathlen] = '\\'; 282 | pathlen++; 283 | } 284 | } 285 | else 286 | { 287 | assert(0); 288 | } 289 | memcpy(f + pathlen, name, namelen + 1); 290 | return f; 291 | } 292 | 293 | // Split a path into an Array of paths 294 | extern (C++) static Strings* splitPath(const(char)* path) 295 | { 296 | char c = 0; // unnecessary initializer is for VC /W4 297 | const(char)* p; 298 | OutBuffer buf; 299 | Strings* array; 300 | array = new Strings(); 301 | if (path) 302 | { 303 | p = path; 304 | do 305 | { 306 | char instring = 0; 307 | while (isspace(cast(char)*p)) // skip leading whitespace 308 | p++; 309 | buf.reserve(strlen(p) + 1); // guess size of path 310 | for (;; p++) 311 | { 312 | c = *p; 313 | switch (c) 314 | { 315 | case '"': 316 | instring ^= 1; // toggle inside/outside of string 317 | continue; 318 | version (OSX) 319 | { 320 | case ',': 321 | } 322 | version (Windows) 323 | { 324 | case ';': 325 | } 326 | version (Posix) 327 | { 328 | case ':': 329 | } 330 | p++; 331 | break; 332 | // note that ; cannot appear as part 333 | // of a path, quotes won't protect it 334 | case 0x1A: 335 | // ^Z means end of file 336 | case 0: 337 | break; 338 | case '\r': 339 | continue; 340 | // ignore carriage returns 341 | version (Posix) 342 | { 343 | case '~': 344 | { 345 | char* home = getenv("HOME"); 346 | if (home) 347 | buf.writestring(home); 348 | else 349 | buf.writestring("~"); 350 | continue; 351 | } 352 | } 353 | version (none) 354 | { 355 | case ' ': 356 | case '\t': 357 | // tabs in filenames? 358 | if (!instring) // if not in string 359 | break; 360 | // treat as end of path 361 | } 362 | default: 363 | buf.writeByte(c); 364 | continue; 365 | } 366 | break; 367 | } 368 | if (buf.offset) // if path is not empty 369 | { 370 | array.push(buf.extractString()); 371 | } 372 | } 373 | while (c); 374 | } 375 | return array; 376 | } 377 | 378 | /*************************** 379 | * Free returned value with FileName::free() 380 | */ 381 | extern (C++) static const(char)* defaultExt(const(char)* name, const(char)* ext) 382 | { 383 | const(char)* e = FileName.ext(name); 384 | if (e) // if already has an extension 385 | return mem.xstrdup(name); 386 | size_t len = strlen(name); 387 | size_t extlen = strlen(ext); 388 | char* s = cast(char*)mem.xmalloc(len + 1 + extlen + 1); 389 | memcpy(s, name, len); 390 | s[len] = '.'; 391 | memcpy(s + len + 1, ext, extlen + 1); 392 | return s; 393 | } 394 | 395 | /*************************** 396 | * Free returned value with FileName::free() 397 | */ 398 | extern (C++) static const(char)* forceExt(const(char)* name, const(char)* ext) 399 | { 400 | const(char)* e = FileName.ext(name); 401 | if (e) // if already has an extension 402 | { 403 | size_t len = e - name; 404 | size_t extlen = strlen(ext); 405 | char* s = cast(char*)mem.xmalloc(len + extlen + 1); 406 | memcpy(s, name, len); 407 | memcpy(s + len, ext, extlen + 1); 408 | return s; 409 | } 410 | else 411 | return defaultExt(name, ext); // doesn't have one 412 | } 413 | 414 | extern (C++) static bool equalsExt(const(char)* name, const(char)* ext) 415 | { 416 | const(char)* e = FileName.ext(name); 417 | if (!e && !ext) 418 | return true; 419 | if (!e || !ext) 420 | return false; 421 | return FileName.compare(e, ext) == 0; 422 | } 423 | 424 | /****************************** 425 | * Return !=0 if extensions match. 426 | */ 427 | extern (C++) bool equalsExt(const(char)* ext) const 428 | { 429 | return equalsExt(str, ext); 430 | } 431 | 432 | /************************************* 433 | * Search Path for file. 434 | * Input: 435 | * cwd if true, search current directory before searching path 436 | */ 437 | extern (C++) static const(char)* searchPath(Strings* path, const(char)* name, bool cwd) 438 | { 439 | if (absolute(name)) 440 | { 441 | return exists(name) ? name : null; 442 | } 443 | if (cwd) 444 | { 445 | if (exists(name)) 446 | return name; 447 | } 448 | if (path) 449 | { 450 | for (size_t i = 0; i < path.dim; i++) 451 | { 452 | const(char)* p = (*path)[i]; 453 | const(char)* n = combine(p, name); 454 | if (exists(n)) 455 | return n; 456 | } 457 | } 458 | return null; 459 | } 460 | 461 | /************************************* 462 | * Search Path for file in a safe manner. 463 | * 464 | * Be wary of CWE-22: Improper Limitation of a Pathname to a Restricted Directory 465 | * ('Path Traversal') attacks. 466 | * http://cwe.mitre.org/data/definitions/22.html 467 | * More info: 468 | * https://www.securecoding.cert.org/confluence/display/seccode/FIO02-C.+Canonicalize+path+names+originating+from+untrusted+sources 469 | * Returns: 470 | * NULL file not found 471 | * !=NULL mem.xmalloc'd file name 472 | */ 473 | extern (C++) static const(char)* safeSearchPath(Strings* path, const(char)* name) 474 | { 475 | version (Windows) 476 | { 477 | /* Disallow % / \ : and .. in name characters 478 | */ 479 | for (const(char)* p = name; *p; p++) 480 | { 481 | char c = *p; 482 | if (c == '\\' || c == '/' || c == ':' || c == '%' || (c == '.' && p[1] == '.')) 483 | { 484 | return null; 485 | } 486 | } 487 | return FileName.searchPath(path, name, false); 488 | } 489 | else version (Posix) 490 | { 491 | /* Even with realpath(), we must check for // and disallow it 492 | */ 493 | for (const(char)* p = name; *p; p++) 494 | { 495 | char c = *p; 496 | if (c == '/' && p[1] == '/') 497 | { 498 | return null; 499 | } 500 | } 501 | if (path) 502 | { 503 | /* Each path is converted to a cannonical name and then a check is done to see 504 | * that the searched name is really a child one of the the paths searched. 505 | */ 506 | for (size_t i = 0; i < path.dim; i++) 507 | { 508 | const(char)* cname = null; 509 | const(char)* cpath = canonicalName((*path)[i]); 510 | //printf("FileName::safeSearchPath(): name=%s; path=%s; cpath=%s\n", 511 | // name, (char *)path->data[i], cpath); 512 | if (cpath is null) 513 | goto cont; 514 | cname = canonicalName(combine(cpath, name)); 515 | //printf("FileName::safeSearchPath(): cname=%s\n", cname); 516 | if (cname is null) 517 | goto cont; 518 | //printf("FileName::safeSearchPath(): exists=%i " 519 | // "strncmp(cpath, cname, %i)=%i\n", exists(cname), 520 | // strlen(cpath), strncmp(cpath, cname, strlen(cpath))); 521 | // exists and name is *really* a "child" of path 522 | if (exists(cname) && strncmp(cpath, cname, strlen(cpath)) == 0) 523 | { 524 | .free(cast(void*)cpath); 525 | const(char)* p = mem.xstrdup(cname); 526 | .free(cast(void*)cname); 527 | return p; 528 | } 529 | cont: 530 | if (cpath) 531 | .free(cast(void*)cpath); 532 | if (cname) 533 | .free(cast(void*)cname); 534 | } 535 | } 536 | return null; 537 | } 538 | else 539 | { 540 | assert(0); 541 | } 542 | } 543 | 544 | extern (C++) static int exists(const(char)* name) 545 | { 546 | version (Posix) 547 | { 548 | stat_t st; 549 | if (stat(name, &st) < 0) 550 | return 0; 551 | if (S_ISDIR(st.st_mode)) 552 | return 2; 553 | return 1; 554 | } 555 | else version (Windows) 556 | { 557 | DWORD dw; 558 | int result; 559 | dw = GetFileAttributesA(name); 560 | if (dw == -1) 561 | result = 0; 562 | else if (dw & FILE_ATTRIBUTE_DIRECTORY) 563 | result = 2; 564 | else 565 | result = 1; 566 | return result; 567 | } 568 | else 569 | { 570 | assert(0); 571 | } 572 | } 573 | 574 | extern (C++) static bool ensurePathExists(const(char)* path) 575 | { 576 | //printf("FileName::ensurePathExists(%s)\n", path ? path : ""); 577 | if (path && *path) 578 | { 579 | if (!exists(path)) 580 | { 581 | const(char)* p = FileName.path(path); 582 | if (*p) 583 | { 584 | version (Windows) 585 | { 586 | size_t len = strlen(path); 587 | if ((len > 2 && p[-1] == ':' && strcmp(path + 2, p) == 0) || len == strlen(p)) 588 | { 589 | mem.xfree(cast(void*)p); 590 | return 0; 591 | } 592 | } 593 | bool r = ensurePathExists(p); 594 | mem.xfree(cast(void*)p); 595 | if (r) 596 | return r; 597 | } 598 | version (Windows) 599 | { 600 | char sep = '\\'; 601 | } 602 | else version (Posix) 603 | { 604 | char sep = '/'; 605 | } 606 | if (path[strlen(path) - 1] != sep) 607 | { 608 | //printf("mkdir(%s)\n", path); 609 | version (Windows) 610 | { 611 | int r = _mkdir(path); 612 | } 613 | version (Posix) 614 | { 615 | int r = mkdir(path, (7 << 6) | (7 << 3) | 7); 616 | } 617 | if (r) 618 | { 619 | /* Don't error out if another instance of dmd just created 620 | * this directory 621 | */ 622 | if (errno != EEXIST) 623 | return true; 624 | } 625 | } 626 | } 627 | } 628 | return false; 629 | } 630 | 631 | /****************************************** 632 | * Return canonical version of name in a malloc'd buffer. 633 | * This code is high risk. 634 | */ 635 | extern (C++) static const(char)* canonicalName(const(char)* name) 636 | { 637 | version (Posix) 638 | { 639 | // NULL destination buffer is allowed and preferred 640 | return realpath(name, null); 641 | } 642 | else version (Windows) 643 | { 644 | /* Apparently, there is no good way to do this on Windows. 645 | * GetFullPathName isn't it, but use it anyway. 646 | */ 647 | DWORD result = GetFullPathNameA(name, 0, null, null); 648 | if (result) 649 | { 650 | char* buf = cast(char*)malloc(result); 651 | result = GetFullPathNameA(name, result, buf, null); 652 | if (result == 0) 653 | { 654 | .free(buf); 655 | return null; 656 | } 657 | return buf; 658 | } 659 | return null; 660 | } 661 | else 662 | { 663 | assert(0); 664 | } 665 | } 666 | 667 | /******************************** 668 | * Free memory allocated by FileName routines 669 | */ 670 | extern (C++) static void free(const(char)* str) 671 | { 672 | if (str) 673 | { 674 | assert(str[0] != cast(char)0xAB); 675 | memset(cast(void*)str, 0xAB, strlen(str) + 1); // stomp 676 | } 677 | mem.xfree(cast(void*)str); 678 | } 679 | 680 | extern (C++) const(char)* toChars() const 681 | { 682 | return cast(char*)str; // toChars() should really be const 683 | } 684 | } 685 | -------------------------------------------------------------------------------- /source/ddmd/root/longdouble.d: -------------------------------------------------------------------------------- 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.root.longdouble; 10 | 11 | real ldouble(T)(T x) 12 | { 13 | return cast(real)x; 14 | } 15 | 16 | -------------------------------------------------------------------------------- /source/ddmd/root/outbuffer.d: -------------------------------------------------------------------------------- 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.root.outbuffer; 10 | 11 | import core.stdc.stdarg, core.stdc.stdio, core.stdc.string; 12 | import ddmd.root.rmem, ddmd.root.rootobject; 13 | 14 | struct OutBuffer 15 | { 16 | ubyte* data; 17 | size_t offset; 18 | size_t size; 19 | int doindent; 20 | int level; 21 | int notlinehead; 22 | 23 | extern (C++) ~this() 24 | { 25 | mem.xfree(data); 26 | } 27 | 28 | extern (C++) char* extractData() 29 | { 30 | char* p; 31 | p = cast(char*)data; 32 | data = null; 33 | offset = 0; 34 | size = 0; 35 | return p; 36 | } 37 | 38 | extern (C++) void reserve(size_t nbytes) 39 | { 40 | //printf("OutBuffer::reserve: size = %d, offset = %d, nbytes = %d\n", size, offset, nbytes); 41 | if (size - offset < nbytes) 42 | { 43 | size = (offset + nbytes) * 2; 44 | size = (size + 15) & ~15; 45 | data = cast(ubyte*)mem.xrealloc(data, size); 46 | } 47 | } 48 | 49 | extern (C++) void setsize(size_t size) 50 | { 51 | offset = size; 52 | } 53 | 54 | extern (C++) void reset() 55 | { 56 | offset = 0; 57 | } 58 | 59 | extern (C++) void write(const(void)* data, size_t nbytes) 60 | { 61 | if (doindent && !notlinehead) 62 | { 63 | if (level) 64 | { 65 | reserve(level); 66 | for (size_t i = 0; i < level; i++) 67 | { 68 | this.data[offset] = '\t'; 69 | offset++; 70 | } 71 | } 72 | notlinehead = 1; 73 | } 74 | reserve(nbytes); 75 | memcpy(this.data + offset, data, nbytes); 76 | offset += nbytes; 77 | } 78 | 79 | extern (C++) void writebstring(char* string) 80 | { 81 | write(string, *string + 1); 82 | } 83 | 84 | extern (C++) void writestring(const(char)* string) 85 | { 86 | write(string, strlen(string)); 87 | } 88 | 89 | extern (C++) void prependstring(const(char)* string) 90 | { 91 | size_t len = strlen(string); 92 | reserve(len); 93 | memmove(data + len, data, offset); 94 | memcpy(data, string, len); 95 | offset += len; 96 | } 97 | 98 | // write newline 99 | extern (C++) void writenl() 100 | { 101 | version (Windows) 102 | { 103 | writeword(0x0A0D); // newline is CR,LF on Microsoft OS's 104 | } 105 | else 106 | { 107 | writeByte('\n'); 108 | } 109 | if (doindent) 110 | notlinehead = 0; 111 | } 112 | 113 | extern (C++) void writeByte(uint b) 114 | { 115 | if (doindent && !notlinehead && b != '\n') 116 | { 117 | if (level) 118 | { 119 | reserve(level); 120 | for (size_t i = 0; i < level; i++) 121 | { 122 | this.data[offset] = '\t'; 123 | offset++; 124 | } 125 | } 126 | notlinehead = 1; 127 | } 128 | reserve(1); 129 | this.data[offset] = cast(ubyte)b; 130 | offset++; 131 | } 132 | 133 | extern (C++) void writeUTF8(uint b) 134 | { 135 | reserve(6); 136 | if (b <= 0x7F) 137 | { 138 | this.data[offset] = cast(ubyte)b; 139 | offset++; 140 | } 141 | else if (b <= 0x7FF) 142 | { 143 | this.data[offset + 0] = cast(ubyte)((b >> 6) | 0xC0); 144 | this.data[offset + 1] = cast(ubyte)((b & 0x3F) | 0x80); 145 | offset += 2; 146 | } 147 | else if (b <= 0xFFFF) 148 | { 149 | this.data[offset + 0] = cast(ubyte)((b >> 12) | 0xE0); 150 | this.data[offset + 1] = cast(ubyte)(((b >> 6) & 0x3F) | 0x80); 151 | this.data[offset + 2] = cast(ubyte)((b & 0x3F) | 0x80); 152 | offset += 3; 153 | } 154 | else if (b <= 0x1FFFFF) 155 | { 156 | this.data[offset + 0] = cast(ubyte)((b >> 18) | 0xF0); 157 | this.data[offset + 1] = cast(ubyte)(((b >> 12) & 0x3F) | 0x80); 158 | this.data[offset + 2] = cast(ubyte)(((b >> 6) & 0x3F) | 0x80); 159 | this.data[offset + 3] = cast(ubyte)((b & 0x3F) | 0x80); 160 | offset += 4; 161 | } 162 | else if (b <= 0x3FFFFFF) 163 | { 164 | this.data[offset + 0] = cast(ubyte)((b >> 24) | 0xF8); 165 | this.data[offset + 1] = cast(ubyte)(((b >> 18) & 0x3F) | 0x80); 166 | this.data[offset + 2] = cast(ubyte)(((b >> 12) & 0x3F) | 0x80); 167 | this.data[offset + 3] = cast(ubyte)(((b >> 6) & 0x3F) | 0x80); 168 | this.data[offset + 4] = cast(ubyte)((b & 0x3F) | 0x80); 169 | offset += 5; 170 | } 171 | else if (b <= 0x7FFFFFFF) 172 | { 173 | this.data[offset + 0] = cast(ubyte)((b >> 30) | 0xFC); 174 | this.data[offset + 1] = cast(ubyte)(((b >> 24) & 0x3F) | 0x80); 175 | this.data[offset + 2] = cast(ubyte)(((b >> 18) & 0x3F) | 0x80); 176 | this.data[offset + 3] = cast(ubyte)(((b >> 12) & 0x3F) | 0x80); 177 | this.data[offset + 4] = cast(ubyte)(((b >> 6) & 0x3F) | 0x80); 178 | this.data[offset + 5] = cast(ubyte)((b & 0x3F) | 0x80); 179 | offset += 6; 180 | } 181 | else 182 | assert(0); 183 | } 184 | 185 | extern (C++) void prependbyte(uint b) 186 | { 187 | reserve(1); 188 | memmove(data + 1, data, offset); 189 | data[0] = cast(ubyte)b; 190 | offset++; 191 | } 192 | 193 | extern (C++) void writewchar(uint w) 194 | { 195 | version (Windows) 196 | { 197 | writeword(w); 198 | } 199 | else 200 | { 201 | write4(w); 202 | } 203 | } 204 | 205 | extern (C++) void writeword(uint w) 206 | { 207 | version (Windows) 208 | { 209 | uint newline = 0x0A0D; 210 | } 211 | else 212 | { 213 | uint newline = '\n'; 214 | } 215 | if (doindent && !notlinehead && w != newline) 216 | { 217 | if (level) 218 | { 219 | reserve(level); 220 | for (size_t i = 0; i < level; i++) 221 | { 222 | this.data[offset] = '\t'; 223 | offset++; 224 | } 225 | } 226 | notlinehead = 1; 227 | } 228 | reserve(2); 229 | *cast(ushort*)(this.data + offset) = cast(ushort)w; 230 | offset += 2; 231 | } 232 | 233 | extern (C++) void writeUTF16(uint w) 234 | { 235 | reserve(4); 236 | if (w <= 0xFFFF) 237 | { 238 | *cast(ushort*)(this.data + offset) = cast(ushort)w; 239 | offset += 2; 240 | } 241 | else if (w <= 0x10FFFF) 242 | { 243 | *cast(ushort*)(this.data + offset) = cast(ushort)((w >> 10) + 0xD7C0); 244 | *cast(ushort*)(this.data + offset + 2) = cast(ushort)((w & 0x3FF) | 0xDC00); 245 | offset += 4; 246 | } 247 | else 248 | assert(0); 249 | } 250 | 251 | extern (C++) void write4(uint w) 252 | { 253 | version (Windows) 254 | { 255 | bool notnewline = w != 0x000A000D; 256 | } 257 | else 258 | { 259 | bool notnewline = true; 260 | } 261 | if (doindent && !notlinehead && notnewline) 262 | { 263 | if (level) 264 | { 265 | reserve(level); 266 | for (size_t i = 0; i < level; i++) 267 | { 268 | this.data[offset] = '\t'; 269 | offset++; 270 | } 271 | } 272 | notlinehead = 1; 273 | } 274 | reserve(4); 275 | *cast(uint*)(this.data + offset) = w; 276 | offset += 4; 277 | } 278 | 279 | extern (C++) void write(const OutBuffer* buf) 280 | { 281 | if (buf) 282 | { 283 | reserve(buf.offset); 284 | memcpy(data + offset, buf.data, buf.offset); 285 | offset += buf.offset; 286 | } 287 | } 288 | 289 | extern (C++) void write(RootObject obj) 290 | { 291 | if (obj) 292 | { 293 | writestring(obj.toChars()); 294 | } 295 | } 296 | 297 | extern (C++) void fill0(size_t nbytes) 298 | { 299 | reserve(nbytes); 300 | memset(data + offset, 0, nbytes); 301 | offset += nbytes; 302 | } 303 | 304 | extern (C++) void vprintf(const(char)* format, va_list args) 305 | { 306 | int count; 307 | if (doindent) 308 | write(null, 0); // perform indent 309 | uint psize = 128; 310 | for (;;) 311 | { 312 | reserve(psize); 313 | version (Windows) 314 | { 315 | count = _vsnprintf(cast(char*)data + offset, psize, format, args); 316 | if (count != -1) 317 | break; 318 | psize *= 2; 319 | } 320 | else version (Posix) 321 | { 322 | va_list va; 323 | va_copy(va, args); 324 | /* 325 | The functions vprintf(), vfprintf(), vsprintf(), vsnprintf() 326 | are equivalent to the functions printf(), fprintf(), sprintf(), 327 | snprintf(), respectively, except that they are called with a 328 | va_list instead of a variable number of arguments. These 329 | functions do not call the va_end macro. Consequently, the value 330 | of ap is undefined after the call. The application should call 331 | va_end(ap) itself afterwards. 332 | */ 333 | count = vsnprintf(cast(char*)data + offset, psize, format, va); 334 | va_end(va); 335 | if (count == -1) 336 | psize *= 2; 337 | else if (count >= psize) 338 | psize = count + 1; 339 | else 340 | break; 341 | } 342 | else 343 | { 344 | assert(0); 345 | } 346 | } 347 | offset += count; 348 | } 349 | 350 | extern (C++) void printf(const(char)* format, ...) 351 | { 352 | va_list ap; 353 | va_start(ap, format); 354 | vprintf(format, ap); 355 | va_end(ap); 356 | } 357 | 358 | extern (C++) void bracket(char left, char right) 359 | { 360 | reserve(2); 361 | memmove(data + 1, data, offset); 362 | data[0] = left; 363 | data[offset + 1] = right; 364 | offset += 2; 365 | } 366 | 367 | /****************** 368 | * Insert left at i, and right at j. 369 | * Return index just past right. 370 | */ 371 | extern (C++) size_t bracket(size_t i, const(char)* left, size_t j, const(char)* right) 372 | { 373 | size_t leftlen = strlen(left); 374 | size_t rightlen = strlen(right); 375 | reserve(leftlen + rightlen); 376 | insert(i, left, leftlen); 377 | insert(j + leftlen, right, rightlen); 378 | return j + leftlen + rightlen; 379 | } 380 | 381 | extern (C++) void spread(size_t offset, size_t nbytes) 382 | { 383 | reserve(nbytes); 384 | memmove(data + offset + nbytes, data + offset, this.offset - offset); 385 | this.offset += nbytes; 386 | } 387 | 388 | /**************************************** 389 | * Returns: offset + nbytes 390 | */ 391 | extern (C++) size_t insert(size_t offset, const(void)* p, size_t nbytes) 392 | { 393 | spread(offset, nbytes); 394 | memmove(data + offset, p, nbytes); 395 | return offset + nbytes; 396 | } 397 | 398 | extern (C++) void remove(size_t offset, size_t nbytes) 399 | { 400 | memmove(data + offset, data + offset + nbytes, this.offset - (offset + nbytes)); 401 | this.offset -= nbytes; 402 | } 403 | 404 | extern (D) const(char)[] peekSlice() 405 | { 406 | return (cast(const char*)data)[0 .. offset]; 407 | } 408 | 409 | // Append terminating null if necessary and get view of internal buffer 410 | extern (C++) char* peekString() 411 | { 412 | if (!offset || data[offset - 1] != '\0') 413 | { 414 | writeByte(0); 415 | offset--; // allow appending more 416 | } 417 | return cast(char*)data; 418 | } 419 | 420 | // Append terminating null if necessary and take ownership of data 421 | extern (C++) char* extractString() 422 | { 423 | if (!offset || data[offset - 1] != '\0') 424 | writeByte(0); 425 | return extractData(); 426 | } 427 | } 428 | -------------------------------------------------------------------------------- /source/ddmd/root/port.d: -------------------------------------------------------------------------------- 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.root.port; 10 | 11 | import core.stdc.ctype; 12 | import core.stdc.string; 13 | import core.stdc.stdio; 14 | import core.stdc.errno; 15 | import core.math; 16 | 17 | version(CRuntime_DigitalMars) __gshared extern (C) extern const(char)* __locale_decpoint; 18 | version(CRuntime_Microsoft) extern(C++) struct longdouble { real r; } 19 | version(CRuntime_Microsoft) extern(C++) size_t ld_sprint(char* str, int fmt, longdouble x); 20 | 21 | extern (C) float strtof(const(char)* p, char** endp); 22 | extern (C) double strtod(const(char)* p, char** endp); 23 | 24 | version(CRuntime_Microsoft) 25 | extern (C++) longdouble strtold_dm(const(char)* p, char** endp); 26 | else 27 | extern (C) real strtold(const(char)* p, char** endp); 28 | 29 | version(CRuntime_Microsoft) 30 | { 31 | enum _OVERFLOW = 3; /* overflow range error */ 32 | enum _UNDERFLOW = 4; /* underflow range error */ 33 | 34 | extern (C) int _atoflt(float* value, const char * str); 35 | extern (C) int _atodbl(double* value, const char * str); 36 | } 37 | 38 | extern (C++) struct Port 39 | { 40 | enum nan = double.nan; 41 | enum infinity = double.infinity; 42 | enum ldbl_max = real.max; 43 | enum ldbl_nan = real.nan; 44 | enum ldbl_infinity = real.infinity; 45 | version(DigitalMars) 46 | { 47 | static __gshared bool yl2x_supported = true; 48 | static __gshared bool yl2xp1_supported = true; 49 | } 50 | else 51 | { 52 | static __gshared bool yl2x_supported = false; 53 | static __gshared bool yl2xp1_supported = false; 54 | } 55 | static __gshared real snan; 56 | static this() 57 | { 58 | /* 59 | * Use a payload which is different from the machine NaN, 60 | * so that uninitialised variables can be 61 | * detected even if exceptions are disabled. 62 | */ 63 | ushort* us = cast(ushort*)&snan; 64 | us[0] = 0; 65 | us[1] = 0; 66 | us[2] = 0; 67 | us[3] = 0xA000; 68 | us[4] = 0x7FFF; 69 | } 70 | 71 | static bool isNan(double r) 72 | { 73 | return !(r == r); 74 | } 75 | 76 | static real sqrt(real x) 77 | { 78 | return .sqrt(x); 79 | } 80 | 81 | static real fmodl(real a, real b) 82 | { 83 | return a % b; 84 | } 85 | 86 | static real fequal(real a, real b) 87 | { 88 | return memcmp(&a, &b, 10) == 0; 89 | } 90 | 91 | static int memicmp(const char* s1, const char* s2, size_t n) 92 | { 93 | int result = 0; 94 | 95 | for (int i = 0; i < n; i++) 96 | { 97 | char c1 = s1[i]; 98 | char c2 = s2[i]; 99 | 100 | result = c1 - c2; 101 | if (result) 102 | { 103 | result = toupper(c1) - toupper(c2); 104 | if (result) 105 | break; 106 | } 107 | } 108 | return result; 109 | } 110 | 111 | static char* strupr(char* s) 112 | { 113 | char* t = s; 114 | 115 | while (*s) 116 | { 117 | *s = cast(char)toupper(*s); 118 | s++; 119 | } 120 | 121 | return t; 122 | } 123 | 124 | static int isSignallingNan(double r) 125 | { 126 | return isNan(r) && !(((cast(ubyte*)&r)[6]) & 8); 127 | } 128 | 129 | static int isSignallingNan(real r) 130 | { 131 | return isNan(r) && !(((cast(ubyte*)&r)[7]) & 0x40); 132 | } 133 | 134 | version(CRuntime_Microsoft) 135 | { 136 | static int isSignallingNan(longdouble ld) 137 | { 138 | return isSignallingNan(*cast(real*)&ld); 139 | } 140 | } 141 | 142 | static int isInfinity(double r) 143 | { 144 | return r is double.infinity || r is -double.infinity; 145 | } 146 | 147 | static float strtof(const(char)* p, char** endp) 148 | { 149 | version (CRuntime_DigitalMars) 150 | { 151 | auto save = __locale_decpoint; 152 | __locale_decpoint = "."; 153 | } 154 | version (CRuntime_Microsoft) 155 | { 156 | float r; 157 | if(endp) 158 | { 159 | r = .strtod(p, endp); // does not set errno for underflows, but unused 160 | } 161 | else 162 | { 163 | int res = _atoflt(&r, p); 164 | if (res == _UNDERFLOW || res == _OVERFLOW) 165 | errno = ERANGE; 166 | } 167 | } 168 | else 169 | { 170 | auto r = .strtof(p, endp); 171 | } 172 | version (CRuntime_DigitalMars) __locale_decpoint = save; 173 | return r; 174 | } 175 | 176 | static double strtod(const(char)* p, char** endp) 177 | { 178 | version (CRuntime_DigitalMars) 179 | { 180 | auto save = __locale_decpoint; 181 | __locale_decpoint = "."; 182 | } 183 | version (CRuntime_Microsoft) 184 | { 185 | double r; 186 | if(endp) 187 | { 188 | r = .strtod(p, endp); // does not set errno for underflows, but unused 189 | } 190 | else 191 | { 192 | int res = _atodbl(&r, p); 193 | if (res == _UNDERFLOW || res == _OVERFLOW) 194 | errno = ERANGE; 195 | } 196 | } 197 | else 198 | { 199 | auto r = .strtod(p, endp); 200 | } 201 | version (CRuntime_DigitalMars) __locale_decpoint = save; 202 | return r; 203 | } 204 | 205 | static real strtold(const(char)* p, char** endp) 206 | { 207 | version (CRuntime_DigitalMars) 208 | { 209 | auto save = __locale_decpoint; 210 | __locale_decpoint = "."; 211 | } 212 | 213 | version (CRuntime_Microsoft) 214 | auto r = .strtold_dm(p, endp).r; 215 | else 216 | auto r = .strtold(p, endp); 217 | version (CRuntime_DigitalMars) __locale_decpoint = save; 218 | return r; 219 | } 220 | 221 | static size_t ld_sprint(char* str, int fmt, real x) 222 | { 223 | version(CRuntime_Microsoft) 224 | { 225 | return .ld_sprint(str, fmt, longdouble(x)); 226 | } 227 | else 228 | { 229 | if ((cast(real)cast(ulong)x) == x) 230 | { 231 | // ((1.5 -> 1 -> 1.0) == 1.5) is false 232 | // ((1.0 -> 1 -> 1.0) == 1.0) is true 233 | // see http://en.cppreference.com/w/cpp/io/c/fprintf 234 | char[5] sfmt = "%#Lg\0"; 235 | sfmt[3] = cast(char)fmt; 236 | return sprintf(str, sfmt.ptr, x); 237 | } 238 | else 239 | { 240 | char[4] sfmt = "%Lg\0"; 241 | sfmt[2] = cast(char)fmt; 242 | return sprintf(str, sfmt.ptr, x); 243 | } 244 | } 245 | } 246 | 247 | static void yl2x_impl(real* x, real* y, real* res) 248 | { 249 | version(DigitalMars) 250 | *res = yl2x(*x, *y); 251 | } 252 | 253 | static void yl2xp1_impl(real* x, real* y, real* res) 254 | { 255 | version(DigitalMars) 256 | *res = yl2xp1(*x, *y); 257 | } 258 | 259 | // Little endian 260 | static void writelongLE(uint value, void* buffer) 261 | { 262 | auto p = cast(ubyte*)buffer; 263 | p[3] = cast(ubyte)(value >> 24); 264 | p[2] = cast(ubyte)(value >> 16); 265 | p[1] = cast(ubyte)(value >> 8); 266 | p[0] = cast(ubyte)(value); 267 | } 268 | 269 | // Little endian 270 | static uint readlongLE(void* buffer) 271 | { 272 | auto p = cast(ubyte*)buffer; 273 | return (((((p[3] << 8) | p[2]) << 8) | p[1]) << 8) | p[0]; 274 | } 275 | 276 | // Big endian 277 | static void writelongBE(uint value, void* buffer) 278 | { 279 | auto p = cast(ubyte*)buffer; 280 | p[0] = cast(ubyte)(value >> 24); 281 | p[1] = cast(ubyte)(value >> 16); 282 | p[2] = cast(ubyte)(value >> 8); 283 | p[3] = cast(ubyte)(value); 284 | } 285 | 286 | // Big endian 287 | static uint readlongBE(void* buffer) 288 | { 289 | auto p = cast(ubyte*)buffer; 290 | return (((((p[0] << 8) | p[1]) << 8) | p[2]) << 8) | p[3]; 291 | } 292 | 293 | // Little endian 294 | static uint readwordLE(void* buffer) 295 | { 296 | auto p = cast(ubyte*)buffer; 297 | return (p[1] << 8) | p[0]; 298 | } 299 | 300 | // Big endian 301 | static uint readwordBE(void* buffer) 302 | { 303 | auto p = cast(ubyte*)buffer; 304 | return (p[0] << 8) | p[1]; 305 | } 306 | 307 | static void valcpy(void *dst, ulong val, size_t size) 308 | { 309 | switch (size) 310 | { 311 | case 1: *cast(ubyte *)dst = cast(ubyte)val; break; 312 | case 2: *cast(ushort *)dst = cast(ushort)val; break; 313 | case 4: *cast(uint *)dst = cast(uint)val; break; 314 | case 8: *cast(ulong *)dst = cast(ulong)val; break; 315 | default: assert(0); 316 | } 317 | } 318 | } 319 | -------------------------------------------------------------------------------- /source/ddmd/root/rmem.d: -------------------------------------------------------------------------------- 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.root.rmem; 10 | 11 | import core.stdc.string; 12 | 13 | version (GC) 14 | { 15 | import core.memory : GC; 16 | 17 | extern (C++) struct Mem 18 | { 19 | static char* xstrdup(const(char)* p) nothrow 20 | { 21 | return p[0 .. strlen(p) + 1].dup.ptr; 22 | } 23 | 24 | static void xfree(void* p) nothrow 25 | { 26 | } 27 | 28 | static void* xmalloc(size_t n) nothrow 29 | { 30 | return GC.malloc(n); 31 | } 32 | 33 | static void* xcalloc(size_t size, size_t n) nothrow 34 | { 35 | return GC.calloc(size * n); 36 | } 37 | 38 | static void* xrealloc(void* p, size_t size) nothrow 39 | { 40 | return GC.realloc(p, size); 41 | } 42 | } 43 | 44 | extern (C++) __gshared Mem mem; 45 | } 46 | else 47 | { 48 | import core.stdc.stdlib; 49 | import core.stdc.stdio; 50 | 51 | extern (C++) struct Mem 52 | { 53 | static char* xstrdup(const(char)* s) nothrow 54 | { 55 | if (s) 56 | { 57 | auto p = .strdup(s); 58 | if (p) 59 | return p; 60 | error(); 61 | } 62 | return null; 63 | } 64 | 65 | static void xfree(void* p) nothrow 66 | { 67 | if (p) 68 | .free(p); 69 | } 70 | 71 | static void* xmalloc(size_t size) nothrow 72 | { 73 | if (!size) 74 | return null; 75 | 76 | auto p = .malloc(size); 77 | if (!p) 78 | error(); 79 | return p; 80 | } 81 | 82 | static void* xcalloc(size_t size, size_t n) nothrow 83 | { 84 | if (!size || !n) 85 | return null; 86 | 87 | auto p = .calloc(size, n); 88 | if (!p) 89 | error(); 90 | return p; 91 | } 92 | 93 | static void* xrealloc(void* p, size_t size) nothrow 94 | { 95 | if (!size) 96 | { 97 | if (p) 98 | .free(p); 99 | return null; 100 | } 101 | 102 | if (!p) 103 | { 104 | p = .malloc(size); 105 | if (!p) 106 | error(); 107 | return p; 108 | } 109 | 110 | p = .realloc(p, size); 111 | if (!p) 112 | error(); 113 | return p; 114 | } 115 | 116 | static void error() nothrow 117 | { 118 | printf("Error: out of memory\n"); 119 | exit(EXIT_FAILURE); 120 | } 121 | } 122 | 123 | extern (C++) __gshared Mem mem; 124 | 125 | enum CHUNK_SIZE = (256 * 4096 - 64); 126 | 127 | __gshared size_t heapleft = 0; 128 | __gshared void* heapp; 129 | 130 | extern (C) void* allocmemory(size_t m_size) nothrow 131 | { 132 | // 16 byte alignment is better (and sometimes needed) for doubles 133 | m_size = (m_size + 15) & ~15; 134 | 135 | // The layout of the code is selected so the most common case is straight through 136 | if (m_size <= heapleft) 137 | { 138 | L1: 139 | heapleft -= m_size; 140 | auto p = heapp; 141 | heapp = cast(void*)(cast(char*)heapp + m_size); 142 | return p; 143 | } 144 | 145 | if (m_size > CHUNK_SIZE) 146 | { 147 | auto p = malloc(m_size); 148 | if (p) 149 | { 150 | return p; 151 | } 152 | printf("Error: out of memory\n"); 153 | exit(EXIT_FAILURE); 154 | } 155 | 156 | heapleft = CHUNK_SIZE; 157 | heapp = malloc(CHUNK_SIZE); 158 | if (!heapp) 159 | { 160 | printf("Error: out of memory\n"); 161 | exit(EXIT_FAILURE); 162 | } 163 | goto L1; 164 | } 165 | 166 | version(DigitalMars) 167 | { 168 | extern (C) void* _d_allocmemory(size_t m_size) nothrow 169 | { 170 | return allocmemory(m_size); 171 | } 172 | 173 | extern (C) Object _d_newclass(const ClassInfo ci) nothrow 174 | { 175 | auto p = allocmemory(ci.init.length); 176 | p[0 .. ci.init.length] = cast(void[])ci.init[]; 177 | return cast(Object)p; 178 | } 179 | 180 | extern (C) void* _d_newitemT(TypeInfo ti) nothrow 181 | { 182 | auto p = allocmemory(ti.tsize); 183 | (cast(ubyte*)p)[0 .. ti.init.length] = 0; 184 | return p; 185 | } 186 | 187 | extern (C) void* _d_newitemiT(TypeInfo ti) nothrow 188 | { 189 | auto p = allocmemory(ti.tsize); 190 | p[0 .. ti.init.length] = ti.init[]; 191 | return p; 192 | } 193 | } 194 | } 195 | -------------------------------------------------------------------------------- /source/ddmd/root/rootobject.d: -------------------------------------------------------------------------------- 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.root.rootobject; 10 | 11 | import core.stdc.stdio; 12 | 13 | import ddmd.root.outbuffer; 14 | 15 | /*********************************************************** 16 | */ 17 | extern (C++) class RootObject 18 | { 19 | this() 20 | { 21 | } 22 | 23 | bool equals(RootObject o) 24 | { 25 | return o is this; 26 | } 27 | 28 | int compare(RootObject) 29 | { 30 | assert(0); 31 | } 32 | 33 | void print() 34 | { 35 | printf("%s %p\n", toChars(), this); 36 | } 37 | 38 | const(char)* toChars() 39 | { 40 | assert(0); 41 | } 42 | 43 | void toBuffer(OutBuffer* buf) 44 | { 45 | assert(0); 46 | } 47 | 48 | int dyncast() 49 | { 50 | assert(0); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /source/ddmd/root/stringtable.d: -------------------------------------------------------------------------------- 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.root.stringtable; 10 | 11 | import core.stdc.string; 12 | import ddmd.root.rmem; 13 | 14 | enum POOL_BITS = 12; 15 | enum POOL_SIZE = (1U << POOL_BITS); 16 | 17 | // TODO: Merge with root.String 18 | // MurmurHash2 was written by Austin Appleby, and is placed in the public 19 | // domain. The author hereby disclaims copyright to this source code. 20 | // https://sites.google.com/site/murmurhash/ 21 | private uint calcHash(const(char)* key, size_t len) pure nothrow @nogc 22 | { 23 | // 'm' and 'r' are mixing constants generated offline. 24 | // They're not really 'magic', they just happen to work well. 25 | enum uint m = 0x5bd1e995; 26 | enum int r = 24; 27 | // Initialize the hash to a 'random' value 28 | uint h = cast(uint)len; 29 | // Mix 4 bytes at a time into the hash 30 | const(ubyte)* data = cast(const(ubyte)*)key; 31 | while (len >= 4) 32 | { 33 | uint k = data[3] << 24 | data[2] << 16 | data[1] << 8 | data[0]; 34 | k *= m; 35 | k ^= k >> r; 36 | h = (h * m) ^ (k * m); 37 | data += 4; 38 | len -= 4; 39 | } 40 | // Handle the last few bytes of the input array 41 | switch (len & 3) 42 | { 43 | case 3: 44 | h ^= data[2] << 16; 45 | goto case; 46 | case 2: 47 | h ^= data[1] << 8; 48 | goto case; 49 | case 1: 50 | h ^= data[0]; 51 | h *= m; 52 | goto default; 53 | default: 54 | break; 55 | } 56 | // Do a few final mixes of the hash to ensure the last few 57 | // bytes are well-incorporated. 58 | h ^= h >> 13; 59 | h *= m; 60 | h ^= h >> 15; 61 | return h; 62 | } 63 | 64 | private size_t nextpow2(size_t val) pure nothrow @nogc @safe 65 | { 66 | size_t res = 1; 67 | while (res < val) 68 | res <<= 1; 69 | return res; 70 | } 71 | 72 | enum loadFactor = 0.8; 73 | 74 | struct StringEntry 75 | { 76 | uint hash; 77 | uint vptr; 78 | } 79 | 80 | // StringValue is a variable-length structure. It has neither proper c'tors nor a 81 | // factory method because the only thing which should be creating these is StringTable. 82 | struct StringValue 83 | { 84 | void* ptrvalue; 85 | size_t length; 86 | 87 | extern (C++) char* lstring() 88 | { 89 | return cast(char*)(&this + 1); 90 | } 91 | 92 | extern (C++) size_t len() const 93 | { 94 | return length; 95 | } 96 | 97 | extern (C++) const(char)* toDchars() const 98 | { 99 | return cast(const(char)*)(&this + 1); 100 | } 101 | } 102 | 103 | struct StringTable 104 | { 105 | private: 106 | StringEntry* table; 107 | size_t tabledim; 108 | ubyte** pools; 109 | size_t npools; 110 | size_t nfill; 111 | size_t count; 112 | 113 | public: 114 | extern (C++) void _init(size_t size = 0) 115 | { 116 | size = nextpow2(cast(size_t)(size / loadFactor)); 117 | if (size < 32) 118 | size = 32; 119 | table = cast(StringEntry*)mem.xcalloc(size, (table[0]).sizeof); 120 | tabledim = size; 121 | pools = null; 122 | npools = nfill = 0; 123 | count = 0; 124 | } 125 | 126 | extern (C++) void reset(size_t size = 0) 127 | { 128 | for (size_t i = 0; i < npools; ++i) 129 | mem.xfree(pools[i]); 130 | mem.xfree(table); 131 | mem.xfree(pools); 132 | table = null; 133 | pools = null; 134 | _init(size); 135 | } 136 | 137 | extern (C++) ~this() 138 | { 139 | for (size_t i = 0; i < npools; ++i) 140 | mem.xfree(pools[i]); 141 | mem.xfree(table); 142 | mem.xfree(pools); 143 | table = null; 144 | pools = null; 145 | } 146 | 147 | extern (C++) StringValue* lookup(const(char)* s, size_t length) 148 | { 149 | const(hash_t) hash = calcHash(s, length); 150 | const(size_t) i = findSlot(hash, s, length); 151 | // printf("lookup %.*s %p\n", (int)length, s, table[i].value ?: NULL); 152 | return getValue(table[i].vptr); 153 | } 154 | 155 | extern (C++) StringValue* insert(const(char)* s, size_t length) 156 | { 157 | const(hash_t) hash = calcHash(s, length); 158 | size_t i = findSlot(hash, s, length); 159 | if (table[i].vptr) 160 | return null; // already in table 161 | if (++count > tabledim * loadFactor) 162 | { 163 | grow(); 164 | i = findSlot(hash, s, length); 165 | } 166 | table[i].hash = hash; 167 | table[i].vptr = allocValue(s, length); 168 | // printf("insert %.*s %p\n", (int)length, s, table[i].value ?: NULL); 169 | return getValue(table[i].vptr); 170 | } 171 | 172 | extern (C++) StringValue* update(const(char)* s, size_t length) 173 | { 174 | const(hash_t) hash = calcHash(s, length); 175 | size_t i = findSlot(hash, s, length); 176 | if (!table[i].vptr) 177 | { 178 | if (++count > tabledim * loadFactor) 179 | { 180 | grow(); 181 | i = findSlot(hash, s, length); 182 | } 183 | table[i].hash = hash; 184 | table[i].vptr = allocValue(s, length); 185 | } 186 | // printf("update %.*s %p\n", (int)length, s, table[i].value ?: NULL); 187 | return getValue(table[i].vptr); 188 | } 189 | 190 | /******************************** 191 | * Walk the contents of the string table, 192 | * calling fp for each entry. 193 | * Params: 194 | * fp = function to call. Returns !=0 to stop 195 | * Returns: 196 | * last return value of fp call 197 | */ 198 | extern (C++) int apply(int function(StringValue*) fp) 199 | { 200 | for (size_t i = 0; i < tabledim; ++i) 201 | { 202 | StringEntry* se = &table[i]; 203 | if (!se.vptr) 204 | continue; 205 | StringValue* sv = getValue(se.vptr); 206 | int result = (*fp)(sv); 207 | if (result) 208 | return result; 209 | } 210 | return 0; 211 | } 212 | 213 | private: 214 | extern (C++) uint allocValue(const(char)* s, size_t length) 215 | { 216 | const(size_t) nbytes = StringValue.sizeof + length + 1; 217 | if (!npools || nfill + nbytes > POOL_SIZE) 218 | { 219 | pools = cast(ubyte**)mem.xrealloc(pools, ++npools * (pools[0]).sizeof); 220 | pools[npools - 1] = cast(ubyte*)mem.xmalloc(nbytes > POOL_SIZE ? nbytes : POOL_SIZE); 221 | nfill = 0; 222 | } 223 | StringValue* sv = cast(StringValue*)&pools[npools - 1][nfill]; 224 | sv.ptrvalue = null; 225 | sv.length = length; 226 | .memcpy(sv.lstring(), s, length); 227 | sv.lstring()[length] = 0; 228 | const(uint) vptr = cast(uint)(npools << POOL_BITS | nfill); 229 | nfill += nbytes + (-nbytes & 7); // align to 8 bytes 230 | return vptr; 231 | } 232 | 233 | extern (C++) StringValue* getValue(uint vptr) 234 | { 235 | if (!vptr) 236 | return null; 237 | const(size_t) idx = (vptr >> POOL_BITS) - 1; 238 | const(size_t) off = vptr & POOL_SIZE - 1; 239 | return cast(StringValue*)&pools[idx][off]; 240 | } 241 | 242 | extern (C++) size_t findSlot(hash_t hash, const(char)* s, size_t length) 243 | { 244 | // quadratic probing using triangular numbers 245 | // http://stackoverflow.com/questions/2348187/moving-from-linear-probing-to-quadratic-probing-hash-collisons/2349774#2349774 246 | for (size_t i = hash & (tabledim - 1), j = 1;; ++j) 247 | { 248 | StringValue* sv; 249 | if (!table[i].vptr || table[i].hash == hash && (sv = getValue(table[i].vptr)).length == length && .memcmp(s, sv.lstring(), length) == 0) 250 | return i; 251 | i = (i + j) & (tabledim - 1); 252 | } 253 | } 254 | 255 | extern (C++) void grow() 256 | { 257 | const(size_t) odim = tabledim; 258 | StringEntry* otab = table; 259 | tabledim *= 2; 260 | table = cast(StringEntry*)mem.xcalloc(tabledim, (table[0]).sizeof); 261 | for (size_t i = 0; i < odim; ++i) 262 | { 263 | StringEntry* se = &otab[i]; 264 | if (!se.vptr) 265 | continue; 266 | StringValue* sv = getValue(se.vptr); 267 | table[findSlot(se.hash, sv.lstring(), sv.length)] = *se; 268 | } 269 | mem.xfree(otab); 270 | } 271 | } 272 | -------------------------------------------------------------------------------- /source/ddmd/tokens.d: -------------------------------------------------------------------------------- 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.tokens; 10 | 11 | import core.stdc.ctype; 12 | import core.stdc.stdio; 13 | import core.stdc.string; 14 | import ddmd.globals; 15 | import ddmd.id; 16 | import ddmd.identifier; 17 | import ddmd.root.port; 18 | import ddmd.root.outbuffer; 19 | import ddmd.root.rmem; 20 | import ddmd.utf; 21 | 22 | enum TOK : int 23 | { 24 | TOKreserved, 25 | 26 | // Other 27 | TOKlparen, 28 | TOKrparen, 29 | TOKlbracket, 30 | TOKrbracket, 31 | TOKlcurly, 32 | TOKrcurly, 33 | TOKcolon, 34 | TOKneg, 35 | TOKsemicolon, 36 | TOKdotdotdot, 37 | TOKeof, 38 | TOKcast, 39 | TOKnull, 40 | TOKassert, 41 | TOKtrue, 42 | TOKfalse, 43 | TOKarray, 44 | TOKcall, 45 | TOKaddress, 46 | TOKtype, 47 | TOKthrow, 48 | TOKnew, 49 | TOKdelete, 50 | TOKstar, 51 | TOKsymoff, 52 | TOKvar, 53 | TOKdotvar, 54 | TOKdotid, 55 | TOKdotti, 56 | TOKdottype, 57 | TOKslice, 58 | TOKarraylength, 59 | TOKversion, 60 | TOKmodule, 61 | TOKdollar, 62 | TOKtemplate, 63 | TOKdottd, 64 | TOKdeclaration, 65 | TOKtypeof, 66 | TOKpragma, 67 | TOKdsymbol, 68 | TOKtypeid, 69 | TOKuadd, 70 | TOKremove, 71 | TOKnewanonclass, 72 | TOKcomment, 73 | TOKarrayliteral, 74 | TOKassocarrayliteral, 75 | TOKstructliteral, 76 | TOKclassreference, 77 | TOKthrownexception, 78 | TOKdelegateptr, 79 | TOKdelegatefuncptr, 80 | 81 | // 54 82 | // Operators 83 | TOKlt, 84 | TOKgt, 85 | TOKle, 86 | TOKge, 87 | TOKequal, 88 | TOKnotequal, 89 | TOKidentity, 90 | TOKnotidentity, 91 | TOKindex, 92 | TOKis, 93 | TOKtobool, 94 | 95 | // 65 96 | // NCEG floating point compares 97 | // !<>= <> <>= !> !>= !< !<= !<> 98 | TOKunord, 99 | TOKlg, 100 | TOKleg, 101 | TOKule, 102 | TOKul, 103 | TOKuge, 104 | TOKug, 105 | TOKue, 106 | 107 | // 73 108 | TOKshl, 109 | TOKshr, 110 | TOKshlass, 111 | TOKshrass, 112 | TOKushr, 113 | TOKushrass, 114 | TOKcat, 115 | TOKcatass, // ~ ~= 116 | TOKadd, 117 | TOKmin, 118 | TOKaddass, 119 | TOKminass, 120 | TOKmul, 121 | TOKdiv, 122 | TOKmod, 123 | TOKmulass, 124 | TOKdivass, 125 | TOKmodass, 126 | TOKand, 127 | TOKor, 128 | TOKxor, 129 | TOKandass, 130 | TOKorass, 131 | TOKxorass, 132 | TOKassign, 133 | TOKnot, 134 | TOKtilde, 135 | TOKplusplus, 136 | TOKminusminus, 137 | TOKconstruct, 138 | TOKblit, 139 | TOKdot, 140 | TOKarrow, 141 | TOKcomma, 142 | TOKquestion, 143 | TOKandand, 144 | TOKoror, 145 | TOKpreplusplus, 146 | TOKpreminusminus, 147 | 148 | // 112 149 | // Numeric literals 150 | TOKint32v, 151 | TOKuns32v, 152 | TOKint64v, 153 | TOKuns64v, 154 | TOKint128v, 155 | TOKuns128v, 156 | TOKfloat32v, 157 | TOKfloat64v, 158 | TOKfloat80v, 159 | TOKimaginary32v, 160 | TOKimaginary64v, 161 | TOKimaginary80v, 162 | 163 | // Char constants 164 | TOKcharv, 165 | TOKwcharv, 166 | TOKdcharv, 167 | 168 | // Leaf operators 169 | TOKidentifier, 170 | TOKstring, 171 | TOKxstring, 172 | TOKthis, 173 | TOKsuper, 174 | TOKhalt, 175 | TOKtuple, 176 | TOKerror, 177 | 178 | // Basic types 179 | TOKvoid, 180 | TOKint8, 181 | TOKuns8, 182 | TOKint16, 183 | TOKuns16, 184 | TOKint32, 185 | TOKuns32, 186 | TOKint64, 187 | TOKuns64, 188 | TOKint128, 189 | TOKuns128, 190 | TOKfloat32, 191 | TOKfloat64, 192 | TOKfloat80, 193 | TOKimaginary32, 194 | TOKimaginary64, 195 | TOKimaginary80, 196 | TOKcomplex32, 197 | TOKcomplex64, 198 | TOKcomplex80, 199 | TOKchar, 200 | TOKwchar, 201 | TOKdchar, 202 | TOKbool, 203 | 204 | // 159 205 | // Aggregates 206 | TOKstruct, 207 | TOKclass, 208 | TOKinterface, 209 | TOKunion, 210 | TOKenum, 211 | TOKimport, 212 | TOKtypedef, 213 | TOKalias, 214 | TOKoverride, 215 | TOKdelegate, 216 | TOKfunction, 217 | TOKmixin, 218 | TOKalign, 219 | TOKextern, 220 | TOKprivate, 221 | TOKprotected, 222 | TOKpublic, 223 | TOKexport, 224 | TOKstatic, 225 | TOKfinal, 226 | TOKconst, 227 | TOKabstract, 228 | TOKvolatile, 229 | TOKdebug, 230 | TOKdeprecated, 231 | TOKin, 232 | TOKout, 233 | TOKinout, 234 | TOKlazy, 235 | TOKauto, 236 | TOKpackage, 237 | TOKmanifest, 238 | TOKimmutable, 239 | 240 | // Statements 241 | TOKif, 242 | TOKelse, 243 | TOKwhile, 244 | TOKfor, 245 | TOKdo, 246 | TOKswitch, 247 | TOKcase, 248 | TOKdefault, 249 | TOKbreak, 250 | TOKcontinue, 251 | TOKwith, 252 | TOKsynchronized, 253 | TOKreturn, 254 | TOKgoto, 255 | TOKtry, 256 | TOKcatch, 257 | TOKfinally, 258 | TOKasm, 259 | TOKforeach, 260 | TOKforeach_reverse, 261 | TOKscope, 262 | TOKon_scope_exit, 263 | TOKon_scope_failure, 264 | TOKon_scope_success, 265 | 266 | // Contracts 267 | TOKbody, 268 | TOKinvariant, 269 | 270 | // Testing 271 | TOKunittest, 272 | 273 | // Added after 1.0 274 | TOKargTypes, 275 | TOKref, 276 | TOKmacro, 277 | 278 | TOKparameters, 279 | TOKtraits, 280 | TOKoverloadset, 281 | TOKpure, 282 | TOKnothrow, 283 | TOKgshared, 284 | TOKline, 285 | TOKfile, 286 | TOKmodulestring, 287 | TOKfuncstring, 288 | TOKprettyfunc, 289 | TOKshared, 290 | TOKat, 291 | TOKpow, 292 | TOKpowass, 293 | TOKgoesto, 294 | TOKvector, 295 | TOKpound, 296 | 297 | TOKinterval, 298 | TOKvoidexp, 299 | TOKcantexp, 300 | 301 | TOKMAX, 302 | } 303 | 304 | alias TOKreserved = TOK.TOKreserved; 305 | alias TOKlparen = TOK.TOKlparen; 306 | alias TOKrparen = TOK.TOKrparen; 307 | alias TOKlbracket = TOK.TOKlbracket; 308 | alias TOKrbracket = TOK.TOKrbracket; 309 | alias TOKlcurly = TOK.TOKlcurly; 310 | alias TOKrcurly = TOK.TOKrcurly; 311 | alias TOKcolon = TOK.TOKcolon; 312 | alias TOKneg = TOK.TOKneg; 313 | alias TOKsemicolon = TOK.TOKsemicolon; 314 | alias TOKdotdotdot = TOK.TOKdotdotdot; 315 | alias TOKeof = TOK.TOKeof; 316 | alias TOKcast = TOK.TOKcast; 317 | alias TOKnull = TOK.TOKnull; 318 | alias TOKassert = TOK.TOKassert; 319 | alias TOKtrue = TOK.TOKtrue; 320 | alias TOKfalse = TOK.TOKfalse; 321 | alias TOKarray = TOK.TOKarray; 322 | alias TOKcall = TOK.TOKcall; 323 | alias TOKaddress = TOK.TOKaddress; 324 | alias TOKtype = TOK.TOKtype; 325 | alias TOKthrow = TOK.TOKthrow; 326 | alias TOKnew = TOK.TOKnew; 327 | alias TOKdelete = TOK.TOKdelete; 328 | alias TOKstar = TOK.TOKstar; 329 | alias TOKsymoff = TOK.TOKsymoff; 330 | alias TOKvar = TOK.TOKvar; 331 | alias TOKdotvar = TOK.TOKdotvar; 332 | alias TOKdotid = TOK.TOKdotid; 333 | alias TOKdotti = TOK.TOKdotti; 334 | alias TOKdottype = TOK.TOKdottype; 335 | alias TOKslice = TOK.TOKslice; 336 | alias TOKarraylength = TOK.TOKarraylength; 337 | alias TOKversion = TOK.TOKversion; 338 | alias TOKmodule = TOK.TOKmodule; 339 | alias TOKdollar = TOK.TOKdollar; 340 | alias TOKtemplate = TOK.TOKtemplate; 341 | alias TOKdottd = TOK.TOKdottd; 342 | alias TOKdeclaration = TOK.TOKdeclaration; 343 | alias TOKtypeof = TOK.TOKtypeof; 344 | alias TOKpragma = TOK.TOKpragma; 345 | alias TOKdsymbol = TOK.TOKdsymbol; 346 | alias TOKtypeid = TOK.TOKtypeid; 347 | alias TOKuadd = TOK.TOKuadd; 348 | alias TOKremove = TOK.TOKremove; 349 | alias TOKnewanonclass = TOK.TOKnewanonclass; 350 | alias TOKcomment = TOK.TOKcomment; 351 | alias TOKarrayliteral = TOK.TOKarrayliteral; 352 | alias TOKassocarrayliteral = TOK.TOKassocarrayliteral; 353 | alias TOKstructliteral = TOK.TOKstructliteral; 354 | alias TOKclassreference = TOK.TOKclassreference; 355 | alias TOKthrownexception = TOK.TOKthrownexception; 356 | alias TOKdelegateptr = TOK.TOKdelegateptr; 357 | alias TOKdelegatefuncptr = TOK.TOKdelegatefuncptr; 358 | alias TOKlt = TOK.TOKlt; 359 | alias TOKgt = TOK.TOKgt; 360 | alias TOKle = TOK.TOKle; 361 | alias TOKge = TOK.TOKge; 362 | alias TOKequal = TOK.TOKequal; 363 | alias TOKnotequal = TOK.TOKnotequal; 364 | alias TOKidentity = TOK.TOKidentity; 365 | alias TOKnotidentity = TOK.TOKnotidentity; 366 | alias TOKindex = TOK.TOKindex; 367 | alias TOKis = TOK.TOKis; 368 | alias TOKtobool = TOK.TOKtobool; 369 | alias TOKunord = TOK.TOKunord; 370 | alias TOKlg = TOK.TOKlg; 371 | alias TOKleg = TOK.TOKleg; 372 | alias TOKule = TOK.TOKule; 373 | alias TOKul = TOK.TOKul; 374 | alias TOKuge = TOK.TOKuge; 375 | alias TOKug = TOK.TOKug; 376 | alias TOKue = TOK.TOKue; 377 | alias TOKshl = TOK.TOKshl; 378 | alias TOKshr = TOK.TOKshr; 379 | alias TOKshlass = TOK.TOKshlass; 380 | alias TOKshrass = TOK.TOKshrass; 381 | alias TOKushr = TOK.TOKushr; 382 | alias TOKushrass = TOK.TOKushrass; 383 | alias TOKcat = TOK.TOKcat; 384 | alias TOKcatass = TOK.TOKcatass; 385 | alias TOKadd = TOK.TOKadd; 386 | alias TOKmin = TOK.TOKmin; 387 | alias TOKaddass = TOK.TOKaddass; 388 | alias TOKminass = TOK.TOKminass; 389 | alias TOKmul = TOK.TOKmul; 390 | alias TOKdiv = TOK.TOKdiv; 391 | alias TOKmod = TOK.TOKmod; 392 | alias TOKmulass = TOK.TOKmulass; 393 | alias TOKdivass = TOK.TOKdivass; 394 | alias TOKmodass = TOK.TOKmodass; 395 | alias TOKand = TOK.TOKand; 396 | alias TOKor = TOK.TOKor; 397 | alias TOKxor = TOK.TOKxor; 398 | alias TOKandass = TOK.TOKandass; 399 | alias TOKorass = TOK.TOKorass; 400 | alias TOKxorass = TOK.TOKxorass; 401 | alias TOKassign = TOK.TOKassign; 402 | alias TOKnot = TOK.TOKnot; 403 | alias TOKtilde = TOK.TOKtilde; 404 | alias TOKplusplus = TOK.TOKplusplus; 405 | alias TOKminusminus = TOK.TOKminusminus; 406 | alias TOKconstruct = TOK.TOKconstruct; 407 | alias TOKblit = TOK.TOKblit; 408 | alias TOKdot = TOK.TOKdot; 409 | alias TOKarrow = TOK.TOKarrow; 410 | alias TOKcomma = TOK.TOKcomma; 411 | alias TOKquestion = TOK.TOKquestion; 412 | alias TOKandand = TOK.TOKandand; 413 | alias TOKoror = TOK.TOKoror; 414 | alias TOKpreplusplus = TOK.TOKpreplusplus; 415 | alias TOKpreminusminus = TOK.TOKpreminusminus; 416 | alias TOKint32v = TOK.TOKint32v; 417 | alias TOKuns32v = TOK.TOKuns32v; 418 | alias TOKint64v = TOK.TOKint64v; 419 | alias TOKuns64v = TOK.TOKuns64v; 420 | alias TOKint128v = TOK.TOKint128v; 421 | alias TOKuns128v = TOK.TOKuns128v; 422 | alias TOKfloat32v = TOK.TOKfloat32v; 423 | alias TOKfloat64v = TOK.TOKfloat64v; 424 | alias TOKfloat80v = TOK.TOKfloat80v; 425 | alias TOKimaginary32v = TOK.TOKimaginary32v; 426 | alias TOKimaginary64v = TOK.TOKimaginary64v; 427 | alias TOKimaginary80v = TOK.TOKimaginary80v; 428 | alias TOKcharv = TOK.TOKcharv; 429 | alias TOKwcharv = TOK.TOKwcharv; 430 | alias TOKdcharv = TOK.TOKdcharv; 431 | alias TOKidentifier = TOK.TOKidentifier; 432 | alias TOKstring = TOK.TOKstring; 433 | alias TOKxstring = TOK.TOKxstring; 434 | alias TOKthis = TOK.TOKthis; 435 | alias TOKsuper = TOK.TOKsuper; 436 | alias TOKhalt = TOK.TOKhalt; 437 | alias TOKtuple = TOK.TOKtuple; 438 | alias TOKerror = TOK.TOKerror; 439 | alias TOKvoid = TOK.TOKvoid; 440 | alias TOKint8 = TOK.TOKint8; 441 | alias TOKuns8 = TOK.TOKuns8; 442 | alias TOKint16 = TOK.TOKint16; 443 | alias TOKuns16 = TOK.TOKuns16; 444 | alias TOKint32 = TOK.TOKint32; 445 | alias TOKuns32 = TOK.TOKuns32; 446 | alias TOKint64 = TOK.TOKint64; 447 | alias TOKuns64 = TOK.TOKuns64; 448 | alias TOKint128 = TOK.TOKint128; 449 | alias TOKuns128 = TOK.TOKuns128; 450 | alias TOKfloat32 = TOK.TOKfloat32; 451 | alias TOKfloat64 = TOK.TOKfloat64; 452 | alias TOKfloat80 = TOK.TOKfloat80; 453 | alias TOKimaginary32 = TOK.TOKimaginary32; 454 | alias TOKimaginary64 = TOK.TOKimaginary64; 455 | alias TOKimaginary80 = TOK.TOKimaginary80; 456 | alias TOKcomplex32 = TOK.TOKcomplex32; 457 | alias TOKcomplex64 = TOK.TOKcomplex64; 458 | alias TOKcomplex80 = TOK.TOKcomplex80; 459 | alias TOKchar = TOK.TOKchar; 460 | alias TOKwchar = TOK.TOKwchar; 461 | alias TOKdchar = TOK.TOKdchar; 462 | alias TOKbool = TOK.TOKbool; 463 | alias TOKstruct = TOK.TOKstruct; 464 | alias TOKclass = TOK.TOKclass; 465 | alias TOKinterface = TOK.TOKinterface; 466 | alias TOKunion = TOK.TOKunion; 467 | alias TOKenum = TOK.TOKenum; 468 | alias TOKimport = TOK.TOKimport; 469 | alias TOKtypedef = TOK.TOKtypedef; 470 | alias TOKalias = TOK.TOKalias; 471 | alias TOKoverride = TOK.TOKoverride; 472 | alias TOKdelegate = TOK.TOKdelegate; 473 | alias TOKfunction = TOK.TOKfunction; 474 | alias TOKmixin = TOK.TOKmixin; 475 | alias TOKalign = TOK.TOKalign; 476 | alias TOKextern = TOK.TOKextern; 477 | alias TOKprivate = TOK.TOKprivate; 478 | alias TOKprotected = TOK.TOKprotected; 479 | alias TOKpublic = TOK.TOKpublic; 480 | alias TOKexport = TOK.TOKexport; 481 | alias TOKstatic = TOK.TOKstatic; 482 | alias TOKfinal = TOK.TOKfinal; 483 | alias TOKconst = TOK.TOKconst; 484 | alias TOKabstract = TOK.TOKabstract; 485 | alias TOKvolatile = TOK.TOKvolatile; 486 | alias TOKdebug = TOK.TOKdebug; 487 | alias TOKdeprecated = TOK.TOKdeprecated; 488 | alias TOKin = TOK.TOKin; 489 | alias TOKout = TOK.TOKout; 490 | alias TOKinout = TOK.TOKinout; 491 | alias TOKlazy = TOK.TOKlazy; 492 | alias TOKauto = TOK.TOKauto; 493 | alias TOKpackage = TOK.TOKpackage; 494 | alias TOKmanifest = TOK.TOKmanifest; 495 | alias TOKimmutable = TOK.TOKimmutable; 496 | alias TOKif = TOK.TOKif; 497 | alias TOKelse = TOK.TOKelse; 498 | alias TOKwhile = TOK.TOKwhile; 499 | alias TOKfor = TOK.TOKfor; 500 | alias TOKdo = TOK.TOKdo; 501 | alias TOKswitch = TOK.TOKswitch; 502 | alias TOKcase = TOK.TOKcase; 503 | alias TOKdefault = TOK.TOKdefault; 504 | alias TOKbreak = TOK.TOKbreak; 505 | alias TOKcontinue = TOK.TOKcontinue; 506 | alias TOKwith = TOK.TOKwith; 507 | alias TOKsynchronized = TOK.TOKsynchronized; 508 | alias TOKreturn = TOK.TOKreturn; 509 | alias TOKgoto = TOK.TOKgoto; 510 | alias TOKtry = TOK.TOKtry; 511 | alias TOKcatch = TOK.TOKcatch; 512 | alias TOKfinally = TOK.TOKfinally; 513 | alias TOKasm = TOK.TOKasm; 514 | alias TOKforeach = TOK.TOKforeach; 515 | alias TOKforeach_reverse = TOK.TOKforeach_reverse; 516 | alias TOKscope = TOK.TOKscope; 517 | alias TOKon_scope_exit = TOK.TOKon_scope_exit; 518 | alias TOKon_scope_failure = TOK.TOKon_scope_failure; 519 | alias TOKon_scope_success = TOK.TOKon_scope_success; 520 | alias TOKbody = TOK.TOKbody; 521 | alias TOKinvariant = TOK.TOKinvariant; 522 | alias TOKunittest = TOK.TOKunittest; 523 | alias TOKargTypes = TOK.TOKargTypes; 524 | alias TOKref = TOK.TOKref; 525 | alias TOKmacro = TOK.TOKmacro; 526 | alias TOKparameters = TOK.TOKparameters; 527 | alias TOKtraits = TOK.TOKtraits; 528 | alias TOKoverloadset = TOK.TOKoverloadset; 529 | alias TOKpure = TOK.TOKpure; 530 | alias TOKnothrow = TOK.TOKnothrow; 531 | alias TOKgshared = TOK.TOKgshared; 532 | alias TOKline = TOK.TOKline; 533 | alias TOKfile = TOK.TOKfile; 534 | alias TOKmodulestring = TOK.TOKmodulestring; 535 | alias TOKfuncstring = TOK.TOKfuncstring; 536 | alias TOKprettyfunc = TOK.TOKprettyfunc; 537 | alias TOKshared = TOK.TOKshared; 538 | alias TOKat = TOK.TOKat; 539 | alias TOKpow = TOK.TOKpow; 540 | alias TOKpowass = TOK.TOKpowass; 541 | alias TOKgoesto = TOK.TOKgoesto; 542 | alias TOKvector = TOK.TOKvector; 543 | alias TOKpound = TOK.TOKpound; 544 | alias TOKinterval = TOK.TOKinterval; 545 | alias TOKvoidexp = TOK.TOKvoidexp; 546 | alias TOKcantexp = TOK.TOKcantexp; 547 | alias TOKMAX = TOK.TOKMAX; 548 | 549 | enum TOKwild = TOKinout; 550 | 551 | /*********************************************************** 552 | */ 553 | extern (C++) struct Token 554 | { 555 | Token* next; 556 | Loc loc; 557 | const(char)* ptr; // pointer to first character of this token within buffer 558 | TOK value; 559 | const(char)* blockComment; // doc comment string prior to this token 560 | const(char)* lineComment; // doc comment for previous token 561 | 562 | union 563 | { 564 | // Integers 565 | d_int64 int64value; 566 | d_uns64 uns64value; 567 | // Floats 568 | d_float80 float80value; 569 | 570 | struct 571 | { 572 | const(char)* ustring; // UTF8 string 573 | uint len; 574 | ubyte postfix; // 'c', 'w', 'd' 575 | } 576 | 577 | Identifier ident; 578 | } 579 | 580 | static __gshared const(char)*[TOKMAX] tochars; 581 | 582 | static this() 583 | { 584 | Identifier.initTable(); 585 | foreach (kw; keywords) 586 | { 587 | //printf("keyword[%d] = '%s'\n",u, keywords[u].name); 588 | const(char)* s = kw.name; 589 | TOK v = kw.value; 590 | auto id = Identifier.idPool(s, strlen(s)); 591 | id.value = v; 592 | //printf("tochars[%d] = '%s'\n",v, s); 593 | Token.tochars[v] = s; 594 | } 595 | Token.tochars[TOKeof] = "EOF"; 596 | Token.tochars[TOKlcurly] = "{"; 597 | Token.tochars[TOKrcurly] = "}"; 598 | Token.tochars[TOKlparen] = "("; 599 | Token.tochars[TOKrparen] = ")"; 600 | Token.tochars[TOKlbracket] = "["; 601 | Token.tochars[TOKrbracket] = "]"; 602 | Token.tochars[TOKsemicolon] = ";"; 603 | Token.tochars[TOKcolon] = ":"; 604 | Token.tochars[TOKcomma] = ","; 605 | Token.tochars[TOKdot] = "."; 606 | Token.tochars[TOKxor] = "^"; 607 | Token.tochars[TOKxorass] = "^="; 608 | Token.tochars[TOKassign] = "="; 609 | Token.tochars[TOKconstruct] = "="; 610 | Token.tochars[TOKblit] = "="; 611 | Token.tochars[TOKlt] = "<"; 612 | Token.tochars[TOKgt] = ">"; 613 | Token.tochars[TOKle] = "<="; 614 | Token.tochars[TOKge] = ">="; 615 | Token.tochars[TOKequal] = "=="; 616 | Token.tochars[TOKnotequal] = "!="; 617 | Token.tochars[TOKnotidentity] = "!is"; 618 | Token.tochars[TOKtobool] = "!!"; 619 | Token.tochars[TOKunord] = "!<>="; 620 | Token.tochars[TOKue] = "!<>"; 621 | Token.tochars[TOKlg] = "<>"; 622 | Token.tochars[TOKleg] = "<>="; 623 | Token.tochars[TOKule] = "!>"; 624 | Token.tochars[TOKul] = "!>="; 625 | Token.tochars[TOKuge] = "!<"; 626 | Token.tochars[TOKug] = "!<="; 627 | Token.tochars[TOKnot] = "!"; 628 | Token.tochars[TOKtobool] = "!!"; 629 | Token.tochars[TOKshl] = "<<"; 630 | Token.tochars[TOKshr] = ">>"; 631 | Token.tochars[TOKushr] = ">>>"; 632 | Token.tochars[TOKadd] = "+"; 633 | Token.tochars[TOKmin] = "-"; 634 | Token.tochars[TOKmul] = "*"; 635 | Token.tochars[TOKdiv] = "/"; 636 | Token.tochars[TOKmod] = "%"; 637 | Token.tochars[TOKslice] = ".."; 638 | Token.tochars[TOKdotdotdot] = "..."; 639 | Token.tochars[TOKand] = "&"; 640 | Token.tochars[TOKandand] = "&&"; 641 | Token.tochars[TOKor] = "|"; 642 | Token.tochars[TOKoror] = "||"; 643 | Token.tochars[TOKarray] = "[]"; 644 | Token.tochars[TOKindex] = "[i]"; 645 | Token.tochars[TOKaddress] = "&"; 646 | Token.tochars[TOKstar] = "*"; 647 | Token.tochars[TOKtilde] = "~"; 648 | Token.tochars[TOKdollar] = "$"; 649 | Token.tochars[TOKcast] = "cast"; 650 | Token.tochars[TOKplusplus] = "++"; 651 | Token.tochars[TOKminusminus] = "--"; 652 | Token.tochars[TOKpreplusplus] = "++"; 653 | Token.tochars[TOKpreminusminus] = "--"; 654 | Token.tochars[TOKtype] = "type"; 655 | Token.tochars[TOKquestion] = "?"; 656 | Token.tochars[TOKneg] = "-"; 657 | Token.tochars[TOKuadd] = "+"; 658 | Token.tochars[TOKvar] = "var"; 659 | Token.tochars[TOKaddass] = "+="; 660 | Token.tochars[TOKminass] = "-="; 661 | Token.tochars[TOKmulass] = "*="; 662 | Token.tochars[TOKdivass] = "/="; 663 | Token.tochars[TOKmodass] = "%="; 664 | Token.tochars[TOKshlass] = "<<="; 665 | Token.tochars[TOKshrass] = ">>="; 666 | Token.tochars[TOKushrass] = ">>>="; 667 | Token.tochars[TOKandass] = "&="; 668 | Token.tochars[TOKorass] = "|="; 669 | Token.tochars[TOKcatass] = "~="; 670 | Token.tochars[TOKcat] = "~"; 671 | Token.tochars[TOKcall] = "call"; 672 | Token.tochars[TOKidentity] = "is"; 673 | Token.tochars[TOKnotidentity] = "!is"; 674 | Token.tochars[TOKidentifier] = "identifier"; 675 | Token.tochars[TOKat] = "@"; 676 | Token.tochars[TOKpow] = "^^"; 677 | Token.tochars[TOKpowass] = "^^="; 678 | Token.tochars[TOKgoesto] = "=>"; 679 | Token.tochars[TOKpound] = "#"; 680 | 681 | // For debugging 682 | Token.tochars[TOKerror] = "error"; 683 | Token.tochars[TOKdotid] = "dotid"; 684 | Token.tochars[TOKdottd] = "dottd"; 685 | Token.tochars[TOKdotti] = "dotti"; 686 | Token.tochars[TOKdotvar] = "dotvar"; 687 | Token.tochars[TOKdottype] = "dottype"; 688 | Token.tochars[TOKsymoff] = "symoff"; 689 | Token.tochars[TOKarraylength] = "arraylength"; 690 | Token.tochars[TOKarrayliteral] = "arrayliteral"; 691 | Token.tochars[TOKassocarrayliteral] = "assocarrayliteral"; 692 | Token.tochars[TOKstructliteral] = "structliteral"; 693 | Token.tochars[TOKstring] = "string"; 694 | Token.tochars[TOKdsymbol] = "symbol"; 695 | Token.tochars[TOKtuple] = "tuple"; 696 | Token.tochars[TOKdeclaration] = "declaration"; 697 | Token.tochars[TOKon_scope_exit] = "scope(exit)"; 698 | Token.tochars[TOKon_scope_success] = "scope(success)"; 699 | Token.tochars[TOKon_scope_failure] = "scope(failure)"; 700 | } 701 | 702 | static __gshared Token* freelist = null; 703 | 704 | static Token* alloc() 705 | { 706 | if (Token.freelist) 707 | { 708 | Token* t = freelist; 709 | freelist = t.next; 710 | t.next = null; 711 | return t; 712 | } 713 | return new Token(); 714 | } 715 | 716 | void free() 717 | { 718 | next = freelist; 719 | freelist = &this; 720 | } 721 | 722 | int isKeyword() const 723 | { 724 | foreach (kw; keywords) 725 | { 726 | if (kw.value == value) 727 | return 1; 728 | } 729 | return 0; 730 | } 731 | 732 | debug 733 | { 734 | void print() 735 | { 736 | fprintf(stderr, "%s\n", toChars()); 737 | } 738 | } 739 | 740 | /**** 741 | * Set to contents of ptr[0..length] 742 | * Params: 743 | * ptr = pointer to string 744 | * length = length of string 745 | */ 746 | final void setString(const(char)* ptr, size_t length) 747 | { 748 | auto s = cast(char*)mem.xmalloc(length + 1); 749 | memcpy(s, ptr, length); 750 | s[length] = 0; 751 | ustring = s; 752 | len = cast(uint)length; 753 | postfix = 0; 754 | } 755 | 756 | /**** 757 | * Set to contents of buf 758 | * Params: 759 | * buf = string (not zero terminated) 760 | */ 761 | final void setString(const ref OutBuffer buf) 762 | { 763 | setString(cast(const(char)*)buf.data, buf.offset); 764 | } 765 | 766 | /**** 767 | * Set to empty string 768 | */ 769 | final void setString() 770 | { 771 | ustring = ""; 772 | len = 0; 773 | postfix = 0; 774 | } 775 | 776 | extern (C++) const(char)* toChars() const 777 | { 778 | __gshared char[3 + 3 * float80value.sizeof + 1] buffer; 779 | const(char)* p = &buffer[0]; 780 | switch (value) 781 | { 782 | case TOKint32v: 783 | sprintf(&buffer[0], "%d", cast(d_int32)int64value); 784 | break; 785 | case TOKuns32v: 786 | case TOKcharv: 787 | case TOKwcharv: 788 | case TOKdcharv: 789 | sprintf(&buffer[0], "%uU", cast(d_uns32)uns64value); 790 | break; 791 | case TOKint64v: 792 | sprintf(&buffer[0], "%lldL", cast(long)int64value); 793 | break; 794 | case TOKuns64v: 795 | sprintf(&buffer[0], "%lluUL", cast(ulong)uns64value); 796 | break; 797 | case TOKfloat32v: 798 | Port.ld_sprint(&buffer[0], 'g', float80value); 799 | strcat(&buffer[0], "f"); 800 | break; 801 | case TOKfloat64v: 802 | Port.ld_sprint(&buffer[0], 'g', float80value); 803 | break; 804 | case TOKfloat80v: 805 | Port.ld_sprint(&buffer[0], 'g', float80value); 806 | strcat(&buffer[0], "L"); 807 | break; 808 | case TOKimaginary32v: 809 | Port.ld_sprint(&buffer[0], 'g', float80value); 810 | strcat(&buffer[0], "fi"); 811 | break; 812 | case TOKimaginary64v: 813 | Port.ld_sprint(&buffer[0], 'g', float80value); 814 | strcat(&buffer[0], "i"); 815 | break; 816 | case TOKimaginary80v: 817 | Port.ld_sprint(&buffer[0], 'g', float80value); 818 | strcat(&buffer[0], "Li"); 819 | break; 820 | case TOKstring: 821 | { 822 | OutBuffer buf; 823 | buf.writeByte('"'); 824 | for (size_t i = 0; i < len;) 825 | { 826 | dchar c; 827 | utf_decodeChar(ustring, len, i, c); 828 | switch (c) 829 | { 830 | case 0: 831 | break; 832 | case '"': 833 | case '\\': 834 | buf.writeByte('\\'); 835 | goto default; 836 | default: 837 | if (c <= 0x7F) 838 | { 839 | if (isprint(c)) 840 | buf.writeByte(c); 841 | else 842 | buf.printf("\\x%02x", c); 843 | } 844 | else if (c <= 0xFFFF) 845 | buf.printf("\\u%04x", c); 846 | else 847 | buf.printf("\\U%08x", c); 848 | continue; 849 | } 850 | break; 851 | } 852 | buf.writeByte('"'); 853 | if (postfix) 854 | buf.writeByte(postfix); 855 | p = buf.extractString(); 856 | } 857 | break; 858 | case TOKxstring: 859 | { 860 | OutBuffer buf; 861 | buf.writeByte('x'); 862 | buf.writeByte('"'); 863 | foreach (size_t i; 0 .. len) 864 | { 865 | if (i) 866 | buf.writeByte(' '); 867 | buf.printf("%02x", ustring[i]); 868 | } 869 | buf.writeByte('"'); 870 | if (postfix) 871 | buf.writeByte(postfix); 872 | buf.writeByte(0); 873 | p = buf.extractData(); 874 | break; 875 | } 876 | case TOKidentifier: 877 | case TOKenum: 878 | case TOKstruct: 879 | case TOKimport: 880 | case TOKwchar: 881 | case TOKdchar: 882 | case TOKbool: 883 | case TOKchar: 884 | case TOKint8: 885 | case TOKuns8: 886 | case TOKint16: 887 | case TOKuns16: 888 | case TOKint32: 889 | case TOKuns32: 890 | case TOKint64: 891 | case TOKuns64: 892 | case TOKint128: 893 | case TOKuns128: 894 | case TOKfloat32: 895 | case TOKfloat64: 896 | case TOKfloat80: 897 | case TOKimaginary32: 898 | case TOKimaginary64: 899 | case TOKimaginary80: 900 | case TOKcomplex32: 901 | case TOKcomplex64: 902 | case TOKcomplex80: 903 | case TOKvoid: 904 | p = ident.toChars(); 905 | break; 906 | default: 907 | p = toChars(value); 908 | break; 909 | } 910 | return p; 911 | } 912 | 913 | static const(char)* toChars(TOK value) 914 | { 915 | static __gshared char[3 + 3 * value.sizeof + 1] buffer; 916 | const(char)* p = tochars[value]; 917 | if (!p) 918 | { 919 | sprintf(&buffer[0], "TOK%d", value); 920 | p = &buffer[0]; 921 | } 922 | return p; 923 | } 924 | } 925 | 926 | /**************************************** 927 | */ 928 | struct Keyword 929 | { 930 | immutable(char)* name; 931 | TOK value; 932 | } 933 | 934 | immutable Keyword[] keywords = 935 | [ 936 | Keyword("this", TOKthis), 937 | Keyword("super", TOKsuper), 938 | Keyword("assert", TOKassert), 939 | Keyword("null", TOKnull), 940 | Keyword("true", TOKtrue), 941 | Keyword("false", TOKfalse), 942 | Keyword("cast", TOKcast), 943 | Keyword("new", TOKnew), 944 | Keyword("delete", TOKdelete), 945 | Keyword("throw", TOKthrow), 946 | Keyword("module", TOKmodule), 947 | Keyword("pragma", TOKpragma), 948 | Keyword("typeof", TOKtypeof), 949 | Keyword("typeid", TOKtypeid), 950 | Keyword("template", TOKtemplate), 951 | Keyword("void", TOKvoid), 952 | Keyword("byte", TOKint8), 953 | Keyword("ubyte", TOKuns8), 954 | Keyword("short", TOKint16), 955 | Keyword("ushort", TOKuns16), 956 | Keyword("int", TOKint32), 957 | Keyword("uint", TOKuns32), 958 | Keyword("long", TOKint64), 959 | Keyword("ulong", TOKuns64), 960 | Keyword("cent", TOKint128), 961 | Keyword("ucent", TOKuns128), 962 | Keyword("float", TOKfloat32), 963 | Keyword("double", TOKfloat64), 964 | Keyword("real", TOKfloat80), 965 | Keyword("bool", TOKbool), 966 | Keyword("char", TOKchar), 967 | Keyword("wchar", TOKwchar), 968 | Keyword("dchar", TOKdchar), 969 | Keyword("ifloat", TOKimaginary32), 970 | Keyword("idouble", TOKimaginary64), 971 | Keyword("ireal", TOKimaginary80), 972 | Keyword("cfloat", TOKcomplex32), 973 | Keyword("cdouble", TOKcomplex64), 974 | Keyword("creal", TOKcomplex80), 975 | Keyword("delegate", TOKdelegate), 976 | Keyword("function", TOKfunction), 977 | Keyword("is", TOKis), 978 | Keyword("if", TOKif), 979 | Keyword("else", TOKelse), 980 | Keyword("while", TOKwhile), 981 | Keyword("for", TOKfor), 982 | Keyword("do", TOKdo), 983 | Keyword("switch", TOKswitch), 984 | Keyword("case", TOKcase), 985 | Keyword("default", TOKdefault), 986 | Keyword("break", TOKbreak), 987 | Keyword("continue", TOKcontinue), 988 | Keyword("synchronized", TOKsynchronized), 989 | Keyword("return", TOKreturn), 990 | Keyword("goto", TOKgoto), 991 | Keyword("try", TOKtry), 992 | Keyword("catch", TOKcatch), 993 | Keyword("finally", TOKfinally), 994 | Keyword("with", TOKwith), 995 | Keyword("asm", TOKasm), 996 | Keyword("foreach", TOKforeach), 997 | Keyword("foreach_reverse", TOKforeach_reverse), 998 | Keyword("scope", TOKscope), 999 | Keyword("struct", TOKstruct), 1000 | Keyword("class", TOKclass), 1001 | Keyword("interface", TOKinterface), 1002 | Keyword("union", TOKunion), 1003 | Keyword("enum", TOKenum), 1004 | Keyword("import", TOKimport), 1005 | Keyword("mixin", TOKmixin), 1006 | Keyword("static", TOKstatic), 1007 | Keyword("final", TOKfinal), 1008 | Keyword("const", TOKconst), 1009 | Keyword("typedef", TOKtypedef), 1010 | Keyword("alias", TOKalias), 1011 | Keyword("override", TOKoverride), 1012 | Keyword("abstract", TOKabstract), 1013 | Keyword("volatile", TOKvolatile), 1014 | Keyword("debug", TOKdebug), 1015 | Keyword("deprecated", TOKdeprecated), 1016 | Keyword("in", TOKin), 1017 | Keyword("out", TOKout), 1018 | Keyword("inout", TOKinout), 1019 | Keyword("lazy", TOKlazy), 1020 | Keyword("auto", TOKauto), 1021 | Keyword("align", TOKalign), 1022 | Keyword("extern", TOKextern), 1023 | Keyword("private", TOKprivate), 1024 | Keyword("package", TOKpackage), 1025 | Keyword("protected", TOKprotected), 1026 | Keyword("public", TOKpublic), 1027 | Keyword("export", TOKexport), 1028 | Keyword("body", TOKbody), 1029 | Keyword("invariant", TOKinvariant), 1030 | Keyword("unittest", TOKunittest), 1031 | Keyword("version", TOKversion), 1032 | Keyword("__argTypes", TOKargTypes), 1033 | Keyword("__parameters", TOKparameters), 1034 | Keyword("ref", TOKref), 1035 | Keyword("macro", TOKmacro), 1036 | Keyword("pure", TOKpure), 1037 | Keyword("nothrow", TOKnothrow), 1038 | Keyword("__gshared", TOKgshared), 1039 | Keyword("__traits", TOKtraits), 1040 | Keyword("__vector", TOKvector), 1041 | Keyword("__overloadset", TOKoverloadset), 1042 | Keyword("__FILE__", TOKfile), 1043 | Keyword("__LINE__", TOKline), 1044 | Keyword("__MODULE__", TOKmodulestring), 1045 | Keyword("__FUNCTION__", TOKfuncstring), 1046 | Keyword("__PRETTY_FUNCTION__", TOKprettyfunc), 1047 | Keyword("shared", TOKshared), 1048 | Keyword("immutable", TOKimmutable), 1049 | ]; 1050 | -------------------------------------------------------------------------------- /source/ddmd/utf.d: -------------------------------------------------------------------------------- 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.utf; 10 | 11 | nothrow pure @nogc: 12 | 13 | /// The Unicode code space is the range of code points [0x000000,0x10FFFF] 14 | /// except the UTF-16 surrogate pairs in the range [0xD800,0xDFFF] 15 | /// and non-characters (which end in 0xFFFE or 0xFFFF). 16 | bool utf_isValidDchar(dchar c) 17 | { 18 | // TODO: Whether non-char code points should be rejected is pending review 19 | // largest character code point 20 | if (c > 0x10FFFF) 21 | return false; 22 | // surrogate pairs 23 | if (0xD800 <= c && c <= 0xDFFF) 24 | return false; 25 | // non-characters 26 | if ((c & 0xFFFFFE) == 0x00FFFE) 27 | return false; 28 | return true; 29 | } 30 | 31 | /******************************* 32 | * Return !=0 if unicode alpha. 33 | * Use table from C99 Appendix D. 34 | */ 35 | bool isUniAlpha(dchar c) 36 | { 37 | static immutable wchar[2][] ALPHA_TABLE = 38 | [ 39 | [0x00AA, 0x00AA], 40 | [0x00B5, 0x00B5], 41 | [0x00B7, 0x00B7], 42 | [0x00BA, 0x00BA], 43 | [0x00C0, 0x00D6], 44 | [0x00D8, 0x00F6], 45 | [0x00F8, 0x01F5], 46 | [0x01FA, 0x0217], 47 | [0x0250, 0x02A8], 48 | [0x02B0, 0x02B8], 49 | [0x02BB, 0x02BB], 50 | [0x02BD, 0x02C1], 51 | [0x02D0, 0x02D1], 52 | [0x02E0, 0x02E4], 53 | [0x037A, 0x037A], 54 | [0x0386, 0x0386], 55 | [0x0388, 0x038A], 56 | [0x038C, 0x038C], 57 | [0x038E, 0x03A1], 58 | [0x03A3, 0x03CE], 59 | [0x03D0, 0x03D6], 60 | [0x03DA, 0x03DA], 61 | [0x03DC, 0x03DC], 62 | [0x03DE, 0x03DE], 63 | [0x03E0, 0x03E0], 64 | [0x03E2, 0x03F3], 65 | [0x0401, 0x040C], 66 | [0x040E, 0x044F], 67 | [0x0451, 0x045C], 68 | [0x045E, 0x0481], 69 | [0x0490, 0x04C4], 70 | [0x04C7, 0x04C8], 71 | [0x04CB, 0x04CC], 72 | [0x04D0, 0x04EB], 73 | [0x04EE, 0x04F5], 74 | [0x04F8, 0x04F9], 75 | [0x0531, 0x0556], 76 | [0x0559, 0x0559], 77 | [0x0561, 0x0587], 78 | [0x05B0, 0x05B9], 79 | [0x05BB, 0x05BD], 80 | [0x05BF, 0x05BF], 81 | [0x05C1, 0x05C2], 82 | [0x05D0, 0x05EA], 83 | [0x05F0, 0x05F2], 84 | [0x0621, 0x063A], 85 | [0x0640, 0x0652], 86 | [0x0660, 0x0669], 87 | [0x0670, 0x06B7], 88 | [0x06BA, 0x06BE], 89 | [0x06C0, 0x06CE], 90 | [0x06D0, 0x06DC], 91 | [0x06E5, 0x06E8], 92 | [0x06EA, 0x06ED], 93 | [0x06F0, 0x06F9], 94 | [0x0901, 0x0903], 95 | [0x0905, 0x0939], 96 | [0x093D, 0x094D], 97 | [0x0950, 0x0952], 98 | [0x0958, 0x0963], 99 | [0x0966, 0x096F], 100 | [0x0981, 0x0983], 101 | [0x0985, 0x098C], 102 | [0x098F, 0x0990], 103 | [0x0993, 0x09A8], 104 | [0x09AA, 0x09B0], 105 | [0x09B2, 0x09B2], 106 | [0x09B6, 0x09B9], 107 | [0x09BE, 0x09C4], 108 | [0x09C7, 0x09C8], 109 | [0x09CB, 0x09CD], 110 | [0x09DC, 0x09DD], 111 | [0x09DF, 0x09E3], 112 | [0x09E6, 0x09F1], 113 | [0x0A02, 0x0A02], 114 | [0x0A05, 0x0A0A], 115 | [0x0A0F, 0x0A10], 116 | [0x0A13, 0x0A28], 117 | [0x0A2A, 0x0A30], 118 | [0x0A32, 0x0A33], 119 | [0x0A35, 0x0A36], 120 | [0x0A38, 0x0A39], 121 | [0x0A3E, 0x0A42], 122 | [0x0A47, 0x0A48], 123 | [0x0A4B, 0x0A4D], 124 | [0x0A59, 0x0A5C], 125 | [0x0A5E, 0x0A5E], 126 | [0x0A66, 0x0A6F], 127 | [0x0A74, 0x0A74], 128 | [0x0A81, 0x0A83], 129 | [0x0A85, 0x0A8B], 130 | [0x0A8D, 0x0A8D], 131 | [0x0A8F, 0x0A91], 132 | [0x0A93, 0x0AA8], 133 | [0x0AAA, 0x0AB0], 134 | [0x0AB2, 0x0AB3], 135 | [0x0AB5, 0x0AB9], 136 | [0x0ABD, 0x0AC5], 137 | [0x0AC7, 0x0AC9], 138 | [0x0ACB, 0x0ACD], 139 | [0x0AD0, 0x0AD0], 140 | [0x0AE0, 0x0AE0], 141 | [0x0AE6, 0x0AEF], 142 | [0x0B01, 0x0B03], 143 | [0x0B05, 0x0B0C], 144 | [0x0B0F, 0x0B10], 145 | [0x0B13, 0x0B28], 146 | [0x0B2A, 0x0B30], 147 | [0x0B32, 0x0B33], 148 | [0x0B36, 0x0B39], 149 | [0x0B3D, 0x0B43], 150 | [0x0B47, 0x0B48], 151 | [0x0B4B, 0x0B4D], 152 | [0x0B5C, 0x0B5D], 153 | [0x0B5F, 0x0B61], 154 | [0x0B66, 0x0B6F], 155 | [0x0B82, 0x0B83], 156 | [0x0B85, 0x0B8A], 157 | [0x0B8E, 0x0B90], 158 | [0x0B92, 0x0B95], 159 | [0x0B99, 0x0B9A], 160 | [0x0B9C, 0x0B9C], 161 | [0x0B9E, 0x0B9F], 162 | [0x0BA3, 0x0BA4], 163 | [0x0BA8, 0x0BAA], 164 | [0x0BAE, 0x0BB5], 165 | [0x0BB7, 0x0BB9], 166 | [0x0BBE, 0x0BC2], 167 | [0x0BC6, 0x0BC8], 168 | [0x0BCA, 0x0BCD], 169 | [0x0BE7, 0x0BEF], 170 | [0x0C01, 0x0C03], 171 | [0x0C05, 0x0C0C], 172 | [0x0C0E, 0x0C10], 173 | [0x0C12, 0x0C28], 174 | [0x0C2A, 0x0C33], 175 | [0x0C35, 0x0C39], 176 | [0x0C3E, 0x0C44], 177 | [0x0C46, 0x0C48], 178 | [0x0C4A, 0x0C4D], 179 | [0x0C60, 0x0C61], 180 | [0x0C66, 0x0C6F], 181 | [0x0C82, 0x0C83], 182 | [0x0C85, 0x0C8C], 183 | [0x0C8E, 0x0C90], 184 | [0x0C92, 0x0CA8], 185 | [0x0CAA, 0x0CB3], 186 | [0x0CB5, 0x0CB9], 187 | [0x0CBE, 0x0CC4], 188 | [0x0CC6, 0x0CC8], 189 | [0x0CCA, 0x0CCD], 190 | [0x0CDE, 0x0CDE], 191 | [0x0CE0, 0x0CE1], 192 | [0x0CE6, 0x0CEF], 193 | [0x0D02, 0x0D03], 194 | [0x0D05, 0x0D0C], 195 | [0x0D0E, 0x0D10], 196 | [0x0D12, 0x0D28], 197 | [0x0D2A, 0x0D39], 198 | [0x0D3E, 0x0D43], 199 | [0x0D46, 0x0D48], 200 | [0x0D4A, 0x0D4D], 201 | [0x0D60, 0x0D61], 202 | [0x0D66, 0x0D6F], 203 | [0x0E01, 0x0E3A], 204 | [0x0E40, 0x0E5B], 205 | [0x0E81, 0x0E82], 206 | [0x0E84, 0x0E84], 207 | [0x0E87, 0x0E88], 208 | [0x0E8A, 0x0E8A], 209 | [0x0E8D, 0x0E8D], 210 | [0x0E94, 0x0E97], 211 | [0x0E99, 0x0E9F], 212 | [0x0EA1, 0x0EA3], 213 | [0x0EA5, 0x0EA5], 214 | [0x0EA7, 0x0EA7], 215 | [0x0EAA, 0x0EAB], 216 | [0x0EAD, 0x0EAE], 217 | [0x0EB0, 0x0EB9], 218 | [0x0EBB, 0x0EBD], 219 | [0x0EC0, 0x0EC4], 220 | [0x0EC6, 0x0EC6], 221 | [0x0EC8, 0x0ECD], 222 | [0x0ED0, 0x0ED9], 223 | [0x0EDC, 0x0EDD], 224 | [0x0F00, 0x0F00], 225 | [0x0F18, 0x0F19], 226 | [0x0F20, 0x0F33], 227 | [0x0F35, 0x0F35], 228 | [0x0F37, 0x0F37], 229 | [0x0F39, 0x0F39], 230 | [0x0F3E, 0x0F47], 231 | [0x0F49, 0x0F69], 232 | [0x0F71, 0x0F84], 233 | [0x0F86, 0x0F8B], 234 | [0x0F90, 0x0F95], 235 | [0x0F97, 0x0F97], 236 | [0x0F99, 0x0FAD], 237 | [0x0FB1, 0x0FB7], 238 | [0x0FB9, 0x0FB9], 239 | [0x10A0, 0x10C5], 240 | [0x10D0, 0x10F6], 241 | [0x1E00, 0x1E9B], 242 | [0x1EA0, 0x1EF9], 243 | [0x1F00, 0x1F15], 244 | [0x1F18, 0x1F1D], 245 | [0x1F20, 0x1F45], 246 | [0x1F48, 0x1F4D], 247 | [0x1F50, 0x1F57], 248 | [0x1F59, 0x1F59], 249 | [0x1F5B, 0x1F5B], 250 | [0x1F5D, 0x1F5D], 251 | [0x1F5F, 0x1F7D], 252 | [0x1F80, 0x1FB4], 253 | [0x1FB6, 0x1FBC], 254 | [0x1FBE, 0x1FBE], 255 | [0x1FC2, 0x1FC4], 256 | [0x1FC6, 0x1FCC], 257 | [0x1FD0, 0x1FD3], 258 | [0x1FD6, 0x1FDB], 259 | [0x1FE0, 0x1FEC], 260 | [0x1FF2, 0x1FF4], 261 | [0x1FF6, 0x1FFC], 262 | [0x203F, 0x2040], 263 | [0x207F, 0x207F], 264 | [0x2102, 0x2102], 265 | [0x2107, 0x2107], 266 | [0x210A, 0x2113], 267 | [0x2115, 0x2115], 268 | [0x2118, 0x211D], 269 | [0x2124, 0x2124], 270 | [0x2126, 0x2126], 271 | [0x2128, 0x2128], 272 | [0x212A, 0x2131], 273 | [0x2133, 0x2138], 274 | [0x2160, 0x2182], 275 | [0x3005, 0x3007], 276 | [0x3021, 0x3029], 277 | [0x3041, 0x3093], 278 | [0x309B, 0x309C], 279 | [0x30A1, 0x30F6], 280 | [0x30FB, 0x30FC], 281 | [0x3105, 0x312C], 282 | [0x4E00, 0x9FA5], 283 | [0xAC00, 0xD7A3] 284 | ]; 285 | 286 | size_t high = ALPHA_TABLE.length - 1; 287 | // Shortcut search if c is out of range 288 | size_t low = (c < ALPHA_TABLE[0][0] || ALPHA_TABLE[high][1] < c) ? high + 1 : 0; 289 | // Binary search 290 | while (low <= high) 291 | { 292 | size_t mid = (low + high) >> 1; 293 | if (c < ALPHA_TABLE[mid][0]) 294 | high = mid - 1; 295 | else if (ALPHA_TABLE[mid][1] < c) 296 | low = mid + 1; 297 | else 298 | { 299 | assert(ALPHA_TABLE[mid][0] <= c && c <= ALPHA_TABLE[mid][1]); 300 | return true; 301 | } 302 | } 303 | return false; 304 | } 305 | 306 | /** 307 | * Returns the code length of c in code units. 308 | */ 309 | int utf_codeLengthChar(dchar c) 310 | { 311 | return c <= 0x7F ? 1 : c <= 0x7FF ? 2 : c <= 0xFFFF ? 3 : c <= 0x10FFFF ? 4 : (assert(false), 6); 312 | } 313 | 314 | int utf_codeLengthWchar(dchar c) 315 | { 316 | return c <= 0xFFFF ? 1 : 2; 317 | } 318 | 319 | /** 320 | * Returns the code length of c in code units for the encoding. 321 | * sz is the encoding: 1 = utf8, 2 = utf16, 4 = utf32. 322 | */ 323 | int utf_codeLength(int sz, dchar c) 324 | { 325 | if (sz == 1) 326 | return utf_codeLengthChar(c); 327 | if (sz == 2) 328 | return utf_codeLengthWchar(c); 329 | assert(sz == 4); 330 | return 1; 331 | } 332 | 333 | void utf_encodeChar(char* s, dchar c) 334 | { 335 | assert(s !is null); 336 | assert(utf_isValidDchar(c)); 337 | if (c <= 0x7F) 338 | { 339 | s[0] = cast(char)c; 340 | } 341 | else if (c <= 0x07FF) 342 | { 343 | s[0] = cast(char)(0xC0 | (c >> 6)); 344 | s[1] = cast(char)(0x80 | (c & 0x3F)); 345 | } 346 | else if (c <= 0xFFFF) 347 | { 348 | s[0] = cast(char)(0xE0 | (c >> 12)); 349 | s[1] = cast(char)(0x80 | ((c >> 6) & 0x3F)); 350 | s[2] = cast(char)(0x80 | (c & 0x3F)); 351 | } 352 | else if (c <= 0x10FFFF) 353 | { 354 | s[0] = cast(char)(0xF0 | (c >> 18)); 355 | s[1] = cast(char)(0x80 | ((c >> 12) & 0x3F)); 356 | s[2] = cast(char)(0x80 | ((c >> 6) & 0x3F)); 357 | s[3] = cast(char)(0x80 | (c & 0x3F)); 358 | } 359 | else 360 | assert(0); 361 | } 362 | 363 | void utf_encodeWchar(wchar* s, dchar c) 364 | { 365 | assert(s !is null); 366 | assert(utf_isValidDchar(c)); 367 | if (c <= 0xFFFF) 368 | { 369 | s[0] = cast(wchar)c; 370 | } 371 | else 372 | { 373 | s[0] = cast(wchar)((((c - 0x010000) >> 10) & 0x03FF) + 0xD800); 374 | s[1] = cast(wchar)(((c - 0x010000) & 0x03FF) + 0xDC00); 375 | } 376 | } 377 | 378 | void utf_encode(int sz, void* s, dchar c) 379 | { 380 | if (sz == 1) 381 | utf_encodeChar(cast(char*)s, c); 382 | else if (sz == 2) 383 | utf_encodeWchar(cast(wchar*)s, c); 384 | else 385 | { 386 | assert(sz == 4); 387 | *(cast(dchar*)s) = c; 388 | } 389 | } 390 | 391 | /******************************************** 392 | * Decode a UTF-8 sequence as a single UTF-32 code point. 393 | * Params: 394 | * s = UTF-8 sequence 395 | * len = number of code units in s[] 396 | * ridx = starting index in s[], updated to reflect number of code units decoded 397 | * rresult = set to character decoded 398 | * Returns: 399 | * null on success, otherwise error message string 400 | */ 401 | immutable(char*) utf_decodeChar(const(char)* s, size_t len, ref size_t ridx, out dchar rresult) 402 | { 403 | // UTF-8 decoding errors 404 | static immutable char* UTF8_DECODE_OK = null; // no error 405 | static immutable char* UTF8_DECODE_OUTSIDE_CODE_SPACE = "Outside Unicode code space"; 406 | static immutable char* UTF8_DECODE_TRUNCATED_SEQUENCE = "Truncated UTF-8 sequence"; 407 | static immutable char* UTF8_DECODE_OVERLONG = "Overlong UTF-8 sequence"; 408 | static immutable char* UTF8_DECODE_INVALID_TRAILER = "Invalid trailing code unit"; 409 | static immutable char* UTF8_DECODE_INVALID_CODE_POINT = "Invalid code point decoded"; 410 | 411 | /* The following encodings are valid, except for the 5 and 6 byte 412 | * combinations: 413 | * 0xxxxxxx 414 | * 110xxxxx 10xxxxxx 415 | * 1110xxxx 10xxxxxx 10xxxxxx 416 | * 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx 417 | * 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 418 | * 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 419 | */ 420 | static immutable uint[] UTF8_STRIDE = 421 | [ 422 | 1, 423 | 1, 424 | 1, 425 | 1, 426 | 1, 427 | 1, 428 | 1, 429 | 1, 430 | 1, 431 | 1, 432 | 1, 433 | 1, 434 | 1, 435 | 1, 436 | 1, 437 | 1, 438 | 1, 439 | 1, 440 | 1, 441 | 1, 442 | 1, 443 | 1, 444 | 1, 445 | 1, 446 | 1, 447 | 1, 448 | 1, 449 | 1, 450 | 1, 451 | 1, 452 | 1, 453 | 1, 454 | 1, 455 | 1, 456 | 1, 457 | 1, 458 | 1, 459 | 1, 460 | 1, 461 | 1, 462 | 1, 463 | 1, 464 | 1, 465 | 1, 466 | 1, 467 | 1, 468 | 1, 469 | 1, 470 | 1, 471 | 1, 472 | 1, 473 | 1, 474 | 1, 475 | 1, 476 | 1, 477 | 1, 478 | 1, 479 | 1, 480 | 1, 481 | 1, 482 | 1, 483 | 1, 484 | 1, 485 | 1, 486 | 1, 487 | 1, 488 | 1, 489 | 1, 490 | 1, 491 | 1, 492 | 1, 493 | 1, 494 | 1, 495 | 1, 496 | 1, 497 | 1, 498 | 1, 499 | 1, 500 | 1, 501 | 1, 502 | 1, 503 | 1, 504 | 1, 505 | 1, 506 | 1, 507 | 1, 508 | 1, 509 | 1, 510 | 1, 511 | 1, 512 | 1, 513 | 1, 514 | 1, 515 | 1, 516 | 1, 517 | 1, 518 | 1, 519 | 1, 520 | 1, 521 | 1, 522 | 1, 523 | 1, 524 | 1, 525 | 1, 526 | 1, 527 | 1, 528 | 1, 529 | 1, 530 | 1, 531 | 1, 532 | 1, 533 | 1, 534 | 1, 535 | 1, 536 | 1, 537 | 1, 538 | 1, 539 | 1, 540 | 1, 541 | 1, 542 | 1, 543 | 1, 544 | 1, 545 | 1, 546 | 1, 547 | 1, 548 | 1, 549 | 1, 550 | 0xFF, 551 | 0xFF, 552 | 0xFF, 553 | 0xFF, 554 | 0xFF, 555 | 0xFF, 556 | 0xFF, 557 | 0xFF, 558 | 0xFF, 559 | 0xFF, 560 | 0xFF, 561 | 0xFF, 562 | 0xFF, 563 | 0xFF, 564 | 0xFF, 565 | 0xFF, 566 | 0xFF, 567 | 0xFF, 568 | 0xFF, 569 | 0xFF, 570 | 0xFF, 571 | 0xFF, 572 | 0xFF, 573 | 0xFF, 574 | 0xFF, 575 | 0xFF, 576 | 0xFF, 577 | 0xFF, 578 | 0xFF, 579 | 0xFF, 580 | 0xFF, 581 | 0xFF, 582 | 0xFF, 583 | 0xFF, 584 | 0xFF, 585 | 0xFF, 586 | 0xFF, 587 | 0xFF, 588 | 0xFF, 589 | 0xFF, 590 | 0xFF, 591 | 0xFF, 592 | 0xFF, 593 | 0xFF, 594 | 0xFF, 595 | 0xFF, 596 | 0xFF, 597 | 0xFF, 598 | 0xFF, 599 | 0xFF, 600 | 0xFF, 601 | 0xFF, 602 | 0xFF, 603 | 0xFF, 604 | 0xFF, 605 | 0xFF, 606 | 0xFF, 607 | 0xFF, 608 | 0xFF, 609 | 0xFF, 610 | 0xFF, 611 | 0xFF, 612 | 0xFF, 613 | 0xFF, 614 | 2, 615 | 2, 616 | 2, 617 | 2, 618 | 2, 619 | 2, 620 | 2, 621 | 2, 622 | 2, 623 | 2, 624 | 2, 625 | 2, 626 | 2, 627 | 2, 628 | 2, 629 | 2, 630 | 2, 631 | 2, 632 | 2, 633 | 2, 634 | 2, 635 | 2, 636 | 2, 637 | 2, 638 | 2, 639 | 2, 640 | 2, 641 | 2, 642 | 2, 643 | 2, 644 | 2, 645 | 2, 646 | 3, 647 | 3, 648 | 3, 649 | 3, 650 | 3, 651 | 3, 652 | 3, 653 | 3, 654 | 3, 655 | 3, 656 | 3, 657 | 3, 658 | 3, 659 | 3, 660 | 3, 661 | 3, 662 | 4, 663 | 4, 664 | 4, 665 | 4, 666 | 4, 667 | 4, 668 | 4, 669 | 4, 670 | 5, 671 | 5, 672 | 5, 673 | 5, 674 | 6, 675 | 6, 676 | 0xFF, 677 | 0xFF 678 | ]; 679 | 680 | assert(s !is null); 681 | size_t i = ridx++; 682 | assert(i < len); 683 | char u = s[i]; 684 | // Pre-stage results for ASCII and error cases 685 | rresult = u; 686 | //printf("utf_decodeChar(s = %02x, %02x, %02x len = %d)\n", u, s[1], s[2], len); 687 | // Get expected sequence length 688 | size_t n = UTF8_STRIDE[u]; 689 | switch (n) 690 | { 691 | case 1: 692 | // ASCII 693 | return UTF8_DECODE_OK; 694 | case 2: 695 | case 3: 696 | case 4: 697 | // multi-byte UTF-8 698 | break; 699 | default: 700 | // 5- or 6-byte sequence 701 | return UTF8_DECODE_OUTSIDE_CODE_SPACE; 702 | } 703 | if (len < i + n) // source too short 704 | return UTF8_DECODE_TRUNCATED_SEQUENCE; 705 | // Pick off 7 - n low bits from first code unit 706 | dchar c = u & ((1 << (7 - n)) - 1); 707 | /* The following combinations are overlong, and illegal: 708 | * 1100000x (10xxxxxx) 709 | * 11100000 100xxxxx (10xxxxxx) 710 | * 11110000 1000xxxx (10xxxxxx 10xxxxxx) 711 | * 11111000 10000xxx (10xxxxxx 10xxxxxx 10xxxxxx) 712 | * 11111100 100000xx (10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx) 713 | */ 714 | char u2 = s[++i]; 715 | // overlong combination 716 | if ((u & 0xFE) == 0xC0 || (u == 0xE0 && (u2 & 0xE0) == 0x80) || (u == 0xF0 && (u2 & 0xF0) == 0x80) || (u == 0xF8 && (u2 & 0xF8) == 0x80) || (u == 0xFC && (u2 & 0xFC) == 0x80)) 717 | return UTF8_DECODE_OVERLONG; 718 | // Decode remaining bits 719 | for (n += i - 1; i != n; ++i) 720 | { 721 | u = s[i]; 722 | if ((u & 0xC0) != 0x80) // trailing bytes are 10xxxxxx 723 | return UTF8_DECODE_INVALID_TRAILER; 724 | c = (c << 6) | (u & 0x3F); 725 | } 726 | if (!utf_isValidDchar(c)) 727 | return UTF8_DECODE_INVALID_CODE_POINT; 728 | ridx = i; 729 | rresult = c; 730 | return UTF8_DECODE_OK; 731 | } 732 | 733 | /******************************************** 734 | * Decode a UTF-16 sequence as a single UTF-32 code point. 735 | * Params: 736 | * s = UTF-16 sequence 737 | * len = number of code units in s[] 738 | * ridx = starting index in s[], updated to reflect number of code units decoded 739 | * rresult = set to character decoded 740 | * Returns: 741 | * null on success, otherwise error message string 742 | */ 743 | immutable(char*) utf_decodeWchar(const(wchar)* s, size_t len, ref size_t ridx, out dchar rresult) 744 | { 745 | // UTF-16 decoding errors 746 | static immutable char* UTF16_DECODE_OK = null; // no error 747 | static immutable char* UTF16_DECODE_TRUNCATED_SEQUENCE = "Truncated UTF-16 sequence"; 748 | static immutable char* UTF16_DECODE_INVALID_SURROGATE = "Invalid low surrogate"; 749 | static immutable char* UTF16_DECODE_UNPAIRED_SURROGATE = "Unpaired surrogate"; 750 | static immutable char* UTF16_DECODE_INVALID_CODE_POINT = "Invalid code point decoded"; 751 | 752 | assert(s !is null); 753 | size_t i = ridx++; 754 | assert(i < len); 755 | // Pre-stage results for ASCII and error cases 756 | dchar u = rresult = s[i]; 757 | if (u < 0x80) // ASCII 758 | return UTF16_DECODE_OK; 759 | if (0xD800 <= u && u <= 0xDBFF) // Surrogate pair 760 | { 761 | if (len <= i + 1) 762 | return UTF16_DECODE_TRUNCATED_SEQUENCE; 763 | wchar u2 = s[i + 1]; 764 | if (u2 < 0xDC00 || 0xDFFF < u) 765 | return UTF16_DECODE_INVALID_SURROGATE; 766 | u = ((u - 0xD7C0) << 10) + (u2 - 0xDC00); 767 | ++ridx; 768 | } 769 | else if (0xDC00 <= u && u <= 0xDFFF) 770 | return UTF16_DECODE_UNPAIRED_SURROGATE; 771 | if (!utf_isValidDchar(u)) 772 | return UTF16_DECODE_INVALID_CODE_POINT; 773 | rresult = u; 774 | return UTF16_DECODE_OK; 775 | } 776 | --------------------------------------------------------------------------------