Changeset 102
- Timestamp:
- 06/02/05 00:02:29 (4 years ago)
- Files:
-
- trunk/doc/dsp-reference/tags.html (modified) (1 diff)
- trunk/dsp/DSPGrammar.d (modified) (3 diffs)
- trunk/dsp/DSPProcessor.d (modified) (1 diff)
- trunk/dsp/Register.d (added)
- trunk/dsp/Runtime.d (added)
- trunk/dsp/ServletCompiler.d (modified) (2 diffs)
- trunk/dsp/ServletGenerator.d (modified) (9 diffs)
- trunk/dsp/StandardTagLibrary.d (modified) (1 diff)
- trunk/dsp/Util.d (modified) (1 diff)
- trunk/dsp/servlet/DSPAttributes.d (modified) (1 diff)
- trunk/dsp/servlet/DSPLibrary.d (modified) (1 diff)
- trunk/dsp/servlet/DSPRequest.d (modified) (1 diff)
- trunk/dsp/servlet/DSPResponse.d (modified) (3 diffs)
- trunk/dsp/servlet/DSPServlet.d (modified) (1 diff)
- trunk/dsp/tags/Attribute.d (added)
- trunk/dsp/tags/Capture.d (added)
- trunk/dsp/tags/Import.d (added)
- trunk/dsp/tags/Include.d (modified) (1 diff)
- trunk/dsp/tags/all.d (modified) (1 diff)
- trunk/dspconf/config.xml (modified) (1 diff)
- trunk/dspconf/dsp_attribute.dsp (added)
- trunk/dspconf/dsp_capture.dsp (added)
- trunk/dspconf/dsp_import.dsp (added)
- trunk/dspconf/index.dsp (modified) (1 diff)
- trunk/dsptest.d (deleted)
- trunk/lib (moved) (moved from trunk/runtime)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/doc/dsp-reference/tags.html
r97 r102 267 267 <h3>Description:</h3> 268 268 <p> 269 The dsp:a rgumenttag is used when the servlet is invoked as a269 The dsp:attribute tag is used when the servlet is invoked as a 270 270 <a href='tags.html#custom'>custom tag</a> in another servlet. It defines a variable to hold the 271 271 value of the passed attribute, when the servlet is invoked in this manner. trunk/dsp/DSPGrammar.d
r100 r102 39 39 public static char[] newline = "\n"; 40 40 41 public static char[] standardInclude = "import dsp.servlet.IDSPResponse,dsp.servlet.IDSPRequest,std.string,std.boxer,mango.io.model.IWriter";42 41 public static char[] servletPrefix = "__servlet_"; 43 42 public static char[] servletDecl = "(IDSPRequest request, IDSPResponse response)"; 44 43 public static char[] outputVarDecl = "IWriter __writer = response.getWriter()"; 45 44 45 public static char[] writer = "__writer"; 46 46 public static char[] outputFunc = "__writer.put"; 47 47 public static char[] replaceFunc = "std.string.replace"; 48 48 public static char[] toStringFunc = "std.string.toString"; 49 49 50 public static char[] standardImports = 51 "dsp.servlet.IDSPResponse," 52 "dsp.servlet.IDSPRequest," 53 "dsp.servlet.DSPAttributes," 54 "dsp.Runtime," 55 "std.string," 56 "std.boxer," 57 "mango.io.model.IWriter" 58 ; 50 59 51 60 public static char[] pathToNamespace(char[] path){ … … 91 100 } 92 101 102 public static char[] runtimeFromString(char[] target,char[] source){ 103 return "fromString(" ~ target ~ "," ~ source ~ ")"; 104 } 105 93 106 /* 94 107 public static char[] expressionEscape(char[] from,char[] to){ … … 110 123 } 111 124 112 public static char[] servletHeader(char[] name,char[] modulePath){ 113 //TODO: rework to use servlet name instead of 'default' 125 public static char[] servletHeader(char[] name,char[] modulePath,char[][] servletImports){ 126 char[] imports = "import " ~ standardImports; 127 foreach(char[] imp; servletImports){ 128 imports ~= ("," ~ imp); 129 } 130 131 //TODO: rework to use servlet name instead of 'default' 114 132 return 115 133 "module " ~ pathToNamespace(modulePath) ~ ";" ~ newline ~ 116 standardInclude~ ";" ~ newline ~134 imports ~ ";" ~ newline ~ 117 135 `alias void function` ~ servletDecl ~ ` ServletHandle; 118 136 trunk/dsp/DSPProcessor.d
r100 r102 40 40 class DSPProcessor : SimpleConsumer{ 41 41 ServletCompilationContext context; 42 char[] content; 42 43 43 44 public this(ServletCompilationContext context){ trunk/dsp/ServletCompiler.d
r99 r102 31 31 private import dsp.ServletGenerator; 32 32 private import dsp.ServletCompilationContext; 33 private import dsp.DSPException; 33 34 34 35 private import xml.utf8all; … … 62 63 context.parser = parser; 63 64 64 parser.parse(new DSPProcessor(context), provider, source); 65 std.file.write( 66 context.requestConfig.dSourceFilename, 67 context.generator.getServletSource( 68 context.requestConfig.requestModule, 69 context.requestConfig.ext 70 ) 71 ); 65 try{ 66 parser.parse(new DSPProcessor(context), provider, source); 67 std.file.write( 68 context.requestConfig.dSourceFilename, 69 context.generator.getServletSource( 70 context.requestConfig.requestModule, 71 context.requestConfig.ext 72 ) 73 ); 74 } 75 catch(DSPException e){ 76 Position pos = parser.getPosition(); 77 throw new Exception(std.string.format("%s %s:<br />\n%s",context.requestConfig.name,pos.toString(),e.toString())); 78 } 72 79 } 73 80 74 81 private void RunCompiler(ServletCompilationContext context){ 75 char[] commandline = 76 "dmd " ~ context.requestConfig.dSourceFilename ~ 77 " " ~ context.requestConfig.options ~ 78 " -op" ~ 79 " -od" ~ context.requestConfig.tempDirectory ~ 80 " -of" ~ context.requestConfig.destServletFilename ~ 81 " mango.lib" ~ 82 " " ~ context.requestConfig.runtimeDirectory ~ "DllStub.obj" ~ 83 " " ~ context.requestConfig.runtimeDirectory ~ "IDSPRequest.obj" ~ 84 " " ~ context.requestConfig.runtimeDirectory ~ "IDSPResponse.obj" ~ 85 " " ~ context.requestConfig.runtimeDirectory ~ "servlet.def" ~ 86 " -version=dsp" ~ 87 " > " ~ context.requestConfig.tempDirectory ~ context.requestConfig.name ~ "_output.txt" 88 ; 89 90 /* //TODO: fix this so 'build' works correctly 91 char[] commandline = 92 "build " ~ context.requestConfig.dSourceFilename ~ 93 " -op" ~ 94 " -od" ~ context.requestConfig.tempDirectory ~ 95 " -of" ~ context.requestConfig.destServletFilename ~ 96 " mango.lib" ~ 97 " servlet.def" ~ 98 " -version=dsp" ~ 99 " > " ~ context.tempDirectory ~ context.requestConfig.name ~ "_output.txt" 100 ; 101 */ 102 debug writefln("command: %s",commandline); 103 104 if(std.process.system(commandline) != 0){ 105 throw new Exception(cast(char[])std.file.read(context.requestConfig.tempDirectory ~ context.requestConfig.name ~ "_output.txt")); 82 with(context){ 83 char[] commandline = 84 "dmd " ~ requestConfig.dSourceFilename ~ 85 " " ~ requestConfig.options ~ 86 " -op" ~ 87 " -od" ~ requestConfig.tempDirectory ~ 88 " -of" ~ requestConfig.destServletFilename ~ 89 " mango.lib" ~ 90 " -I" ~ requestConfig.runtimeDirectory ~ 91 " " ~ requestConfig.runtimeDirectory ~ "lib/DllStub.obj" ~ 92 " " ~ requestConfig.runtimeDirectory ~ "lib/IDSPRequest.obj" ~ 93 " " ~ requestConfig.runtimeDirectory ~ "lib/IDSPResponse.obj" ~ 94 " " ~ requestConfig.runtimeDirectory ~ "lib/DSPAttributes.obj" ~ 95 " " ~ requestConfig.runtimeDirectory ~ "lib/Runtime.obj" ~ 96 " " ~ requestConfig.runtimeDirectory ~ "lib/servlet.def" ~ 97 " -version=dsp" ~ 98 " > " ~ requestConfig.tempDirectory ~ requestConfig.name ~ "_output.txt" 99 ; 100 101 /* //TODO: fix this so 'build' works correctly 102 char[] commandline = 103 "build " ~ requestConfig.dSourceFilename ~ 104 " -op" ~ 105 " -od" ~ requestConfig.tempDirectory ~ 106 " -of" ~ requestConfig.destServletFilename ~ 107 " mango.lib" ~ 108 " servlet.def" ~ 109 " -version=dsp" ~ 110 " > " ~ tempDirectory ~ requestConfig.name ~ "_output.txt" 111 ; 112 */ 113 debug writefln("command: %s",commandline); 114 115 if(std.process.system(commandline) != 0){ 116 throw new Exception(cast(char[])std.file.read(requestConfig.tempDirectory ~ requestConfig.name ~ "_output.txt")); 117 } 106 118 } 107 119 } trunk/dsp/ServletGenerator.d
r100 r102 31 31 private import dsp.Register; 32 32 33 private import std.boxer; 34 35 /* 36 Shim to workaround template resolution issue in DMD 0.125. 37 Calls to template functions will not work due to a regression in this compiler version 38 The workaround here, using a struct template, allows for an alternate solution to the std.boxer.unbox template. 39 */ 40 struct unboxer(T){ 41 T opCall(Box value) 42 { 43 assert (value.type !== null); 44 45 if (typeid(T) is value.type) 46 return *cast(T*) value.data; 47 throw new UnboxException(value, typeid(T)); 48 } 49 } 50 51 unboxer!(Register) registerUnboxer; 52 unboxer!(char[]) stringUnboxer; 53 33 54 class ServletGenerator : RegisterSet{ 34 55 char[] servletCPIn; … … 37 58 char[] servletName; 38 59 char[] servletDependencies; 60 char[][] servletImports; 61 62 Box[] stack; 39 63 40 64 int contentMode; … … 119 143 } 120 144 145 public void pushRegister(Register ptr){ 146 stack ~= box(ptr); 147 } 148 149 public Register popRegister(){ 150 Register ptr = registerUnboxer(stack[$-1]); 151 stack.length = stack.length - 1; 152 return ptr; 153 } 154 155 public void pushString(char[] ptr){ 156 stack ~= box(ptr); 157 } 158 159 public char[] popString(){ 160 char[] ptr = stringUnboxer(stack[$-1]); 161 stack.length = stack.length - 1; 162 return ptr; 163 } 164 121 165 122 166 // parse and append expression-based bits … … 125 169 public Register evaluateExpression(char[] value,bit render=true){ 126 170 Register expr; 127 128 171 expr.home = this; 129 172 … … 133 176 } 134 177 135 char[][] parts = value.split(DSPGrammar.escapeStr);136 178 int pos = 0; 137 179 bit isText = true; 138 180 char[] expression = "``"; 139 140 // optimize for non-escaped value 141 if(parts.length == 1){ 142 expr.appendText(value); 143 goto evalEnd; 144 } 145 146 while(pos < parts.length){ 147 char[] thisPart = parts[pos]; 181 char[] thisPart; 182 uint delimPos; 183 uint nextPos; 184 185 while(pos < value.length){ 186 delimPos = find(value[pos..value.length],DSPGrammar.escapeStr); 187 if(delimPos == 0){ 188 thisPart = value[pos..pos+DSPGrammar.escapeStr.length]; 189 } 190 else if(delimPos == -1){ 191 thisPart = value[pos..value.length]; 192 } 193 else{ 194 thisPart = value[pos..pos+delimPos]; 195 } 196 197 debug printf("thispart: %.*s\n",thisPart); 148 198 149 199 // plain-text portion of expression 150 200 if(isText){ 151 201 if(thisPart == DSPGrammar.escapeStr){ 152 if(pos+1 < parts.length && parts[pos+1] == DSPGrammar.escapeStr){202 if(pos+1+DSPGrammar.escapeStr.length < value.length && value[pos+1..pos+1+DSPGrammar.escapeStr.length] == DSPGrammar.escapeStr){ 153 203 expr.appendText(DSPGrammar.escapeStr); 154 pos+ +;204 pos+=DSPGrammar.escapeStr.length; // extra advance for the additional escape token 155 205 } 156 206 else{ … … 166 216 else{ 167 217 if(thisPart == DSPGrammar.escapeStr){ 168 if(pos+1 < parts.length && parts[pos+1] == DSPGrammar.escapeStr){218 if(pos+1+DSPGrammar.escapeStr.length < value.length && value[pos+1..pos+1+DSPGrammar.escapeStr.length] == DSPGrammar.escapeStr){ 169 219 throw new DSPException("Double-escape not allowed here."); 170 220 } … … 177 227 } 178 228 } 179 pos+ +;229 pos+=thisPart.length; 180 230 } 181 231 … … 184 234 } 185 235 186 evalEnd: 236 evalEnd: 187 237 if(render) appendBody(expr.render()); 188 238 return expr; … … 193 243 } 194 244 245 public void addImport(char[] namespace){ 246 servletImports ~= namespace; 247 } 248 195 249 public char[] getServletSource(char[] modulePath,char[] fileExtension){ 196 250 return 197 DSPGrammar.servletHeader(servletName,modulePath ) ~251 DSPGrammar.servletHeader(servletName,modulePath,servletImports) ~ 198 252 DSPGrammar.dependenciesSection(servletDependencies,"/" ~ modulePath ~ "." ~ fileExtension) ~ 199 253 DSPGrammar.servletFunction(renderRegisterSet(),servletName,servletCPIn,servletBody,servletCPOut) trunk/dsp/StandardTagLibrary.d
r97 r102 42 42 tags["servlet"] = new Servlet(); 43 43 tags["include"] = new Include(); 44 tags["import"] = new Import(); 45 tags["capture"] = new Capture(); 46 tags["attribute"] = new Attribute(); 44 47 } 45 48 } trunk/dsp/Util.d
r99 r102 38 38 } 39 39 40 char[][] split(char[] src,char[] delim){41 char[][] result;42 int lastPos = 0;43 int pos = 0;44 45 debug printf("split: %.*s\n",src);46 debug printf("src: '%*.s'\n",src);47 while(lastPos < src.length){48 pos = find(src[lastPos..$],delim);49 if(pos == -1){50 result ~= src[lastPos..$];51 break;52 }53 else{54 pos += lastPos;55 debug printf("last %d, pos: %d\n",lastPos,pos);56 if(pos == 0) result ~= "";57 else result ~= src[lastPos..pos]; // get segment58 result ~= src[pos..pos + delim.length]; // keep the delimiter59 lastPos = pos + delim.length; // advance60 }61 }62 printf("\n");63 return result;64 }65 66 40 class CompleteBufferReader: Scanner{ 67 41 IBuffer buffer; trunk/dsp/servlet/DSPAttributes.d
r98 r102 39 39 return output; 40 40 } 41 42 Box get(DSPAttributes attribs,char[] name,Box defaultValue){ 43 if(name in attribs){ 44 return attribs[name]; 45 } 46 return defaultValue; 47 } trunk/dsp/servlet/DSPLibrary.d
r99 r102 47 47 public DSPLibrary next,last; 48 48 public char[] key; 49 50 public bit isLoaded(){ 51 return lib && lib.isLoaded; 52 } 49 53 50 54 public void unload(){ trunk/dsp/servlet/DSPRequest.d
r97 r102 44 44 } 45 45 46 public void reset(){ 47 attribs = null; 48 contentData = null; 49 super.reset(); 50 } 51 46 52 DSPAttributes attributes(){ 47 53 return attribs; trunk/dsp/servlet/DSPResponse.d
r99 r102 53 53 } 54 54 55 void reset(){ 56 writerStack.length = 0; 57 dspWriter = null; 58 customTagScopeStack.length = 0; 59 customTagScopeStack.length = 1; 60 tagStack.length = 0; 61 servlet = null; 62 super.reset(); 63 } 64 55 65 void setServlet(DSPServlet servlet){ 56 66 this.servlet = servlet; … … 76 86 //* save the current writer and use a new one in its place 77 87 void pushWriter(){ 78 HttpWriter newWriter = new HttpWriter(new Buffer());79 writerStack ~= newWriter;88 HttpWriter newWriter = new HttpWriter(new GrowableBuffer(256)); 89 writerStack ~= dspWriter; 80 90 dspWriter = newWriter; 81 91 } … … 90 100 91 101 char[] data = cast(char[])dspWriter.getBuffer().getContent(); 102 printf("popWriter: [%.*s]\n",data); 92 103 dspWriter = oldWriter; 93 104 trunk/dsp/servlet/DSPServlet.d
r99 r102 213 213 if(lib){ 214 214 lib.service(dspRequest,dspResponse); 215 216 if(dspResponse.isExceptionSet){ 217 throw new Exception(dspResponse.getException()); 218 } 215 219 } 216 220 else{ trunk/dsp/tags/Include.d
r100 r102 72 72 73 73 case "dsp": 74 //TODO: insert a #line pragma at the end of the filedata to reset the current file line 74 75 parser.insertText(filedata); 75 76 break; trunk/dsp/tags/all.d
r97 r102 32 32 import dsp.tags.Servlet; 33 33 import dsp.tags.Include; 34 import dsp.tags.Import; 35 import dsp.tags.Capture; 36 import dsp.tags.Attribute; trunk/dspconf/config.xml
r75 r102 4 4 <temp-directory value="_temp\"/> 5 5 <cache-size value="2"/> 6 <runtime-directory value=" .\runtime\"/>6 <runtime-directory value=""/> 7 7 <build-options value="-inline -release"/> 8 8 </config> trunk/dspconf/index.dsp
r100 r102 5 5 <h2>DSP Tag unittests</h2> 6 6 <ul> 7 <?dsp char[] filename = "dsp_include.dsp"; ?> 8 <li><a href='#filename#'>dsp:include</a></li> 7 <li><a href='dsp_include.dsp'>dsp:include</a></li> 8 <li><a href='dsp_import.dsp'>dsp:import</a></li> 9 <li><a href='dsp_capture.dsp'>dsp:capture</a></li> 10 <li><a href='dsp_attribute.dsp'>dsp:attribute</a></li> 9 11 </ul> 10 12 </body>
