1 /* Digital Mars DMDScript source code. 2 * Copyright (c) 2000-2002 by Chromium Communications 3 * D version Copyright (c) 2004-2010 by Digital Mars 4 * Distributed under the Boost Software License, Version 1.0. 5 * (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 6 * written by Walter Bright 7 * http://www.digitalmars.com 8 * 9 * D2 port by Dmitry Olshansky 10 * 11 * DMDScript is implemented in the D Programming Language, 12 * http://www.digitalmars.com/d/ 13 * 14 * For a C++ implementation of DMDScript, including COM support, see 15 * http://www.digitalmars.com/dscript/cppscript.html 16 */ 17 18 module testscript; 19 20 import std.path; 21 import std.file; 22 import std.stdio; 23 import std.exception; 24 import core.stdc.stdlib; 25 import core.memory; 26 27 import dmdscript.script; 28 import dmdscript.program; 29 import dmdscript.errmsgs; 30 31 enum 32 { 33 EXITCODE_INIT_ERROR = 1, 34 EXITCODE_INVALID_ARGS = 2, 35 EXITCODE_RUNTIME_ERROR = 3, 36 } 37 //Ehm, well, this fools VisualD, and of little convinience anyway 38 /*version (Windows) 39 { 40 pragma(lib, "dmdscript"); 41 }*/ 42 43 44 45 /************************************************** 46 Usage: 47 48 ds 49 will run test.ds 50 51 ds foo 52 will run foo.ds 53 54 ds foo.js 55 will run foo.js 56 57 ds foo1 foo2 foo.bar 58 will run foo1.ds, foo2.ds, foo.bar 59 60 The -iinc flag will prefix the source files with the contents of file inc. 61 There can be multiple -i's. The include list is reset to empty any time 62 a new -i is encountered that is not preceded by a -i. 63 64 ds -iinc foo 65 will prefix foo.ds with inc 66 67 ds -iinc1 -iinc2 foo bar 68 will prefix foo.ds with inc1+inc2, and will prefix bar.ds 69 with inc1+inc2 70 71 ds -iinc1 -iinc2 foo -iinc3 bar 72 will prefix foo.ds with inc1+inc2, and will prefix bar.ds 73 with inc3 74 75 ds -iinc1 -iinc2 foo -i bar 76 will prefix foo.ds with inc1+inc2, and will prefix bar.ds 77 with nothing 78 79 */ 80 81 int main(string[] args) 82 { 83 uint errors = 0; 84 string[] includes; 85 SrcFile[] srcfiles; 86 int result; 87 bool verbose; 88 ErrInfo errinfo; 89 //GC.disable(); 90 if(args.length == 1) 91 stderr.writefln(dmdscript.script.banner()); 92 for (size_t i = 1; i < args.length; i++) 93 { string p = args[i]; 94 95 if (p[0] == '-') 96 { 97 switch (p[1]) 98 { 99 case 'i': 100 if (p[2]) 101 includes ~= p[2 .. $]; 102 break; 103 104 case 'v': 105 verbose = 1; 106 break; 107 108 default: 109 writefln(errmsgtbl[ERR_BAD_SWITCH],p); 110 errors++; 111 break; 112 } 113 } 114 else 115 { 116 srcfiles ~= new SrcFile(p, includes); 117 includes = null; 118 } 119 } 120 if (errors) 121 return EXITCODE_INVALID_ARGS; 122 123 if (srcfiles.length == 0) 124 { 125 srcfiles ~= new SrcFile("test", null); 126 } 127 128 stderr.writefln("%d source files", srcfiles.length); 129 130 // Read files, parse them, execute them 131 foreach (SrcFile m; srcfiles) 132 { 133 if (verbose) 134 writefln("read %s:", m.srcfile); 135 m.read(); 136 if (verbose) 137 writefln("compile %s:", m.srcfile); 138 m.compile(); 139 if (verbose) 140 writefln("execute %s:", m.srcfile); 141 m.execute(); 142 } 143 return EXIT_SUCCESS; 144 } 145 146 147 class SrcFile 148 { 149 string srcfile; 150 string[] includes; 151 152 Program program; 153 tchar[] buffer; 154 155 this(string srcfilename, string[] includes) 156 { 157 /* DMDScript source files default to a '.ds' extension 158 */ 159 160 srcfile = defaultExtension(srcfilename, "ds"); 161 this.includes = includes; 162 } 163 164 void read() 165 { 166 /* Read the source file, prepend the include files, 167 * and put it all in buffer[]. Allocate an extra byte 168 * to buffer[] and terminate it with a 0x1A. 169 * (If the 0x1A isn't at the end, the lexer will put 170 * one there, forcing an extra copy to be made of the 171 * source text.) 172 */ 173 174 //writef("read file '%s'\n",srcfile); 175 176 // Read the includes[] files 177 size_t i; 178 void[] buf; 179 ulong len; 180 181 len = std.file.getSize(srcfile); 182 foreach (string filename; includes) 183 { 184 len += std.file.getSize(filename); 185 } 186 len++; // leave room for sentinal 187 188 assert(len < uint.max); 189 190 // Prefix the includes[] files 191 192 int sz = cast(int)len; 193 buffer = new tchar[sz]; 194 195 foreach (string filename; includes) 196 { 197 buf = std.file.read(filename); 198 buffer[i .. i + buf.length] = cast(string)buf[]; 199 i += buf.length; 200 } 201 202 buf = std.file.read(srcfile); 203 buffer[i .. i + buf.length] = cast(string)buf[]; 204 i += buf.length; 205 206 buffer[i] = 0x1A; // ending sentinal 207 i++; 208 assert(i == len); 209 } 210 211 void compile() 212 { 213 /* Create a DMDScript program, and compile our text buffer. 214 */ 215 216 program = new Program(); 217 program.compile(srcfile, assumeUnique(buffer), null); 218 } 219 220 void execute() 221 { 222 /* Execute the resulting program. 223 */ 224 225 program.execute(null); 226 } 227 }