annotate roundup/cgi/TAL/TALInterpreter.py @ 2119:cc4667ef3f12

Added the ability to toggle where error messages go. They either go to the user (default, for backwards compatibility), the dispatcher, or both. These are able to be toggled via settings in config.py. Please refer to upgrading.txt for more details. (And Richard, let me know if I've done anything wrong with this checkin. :))
author Eddie Parker <eparker@users.sourceforge.net>
date Thu, 25 Mar 2004 19:27:15 +0000
parents fc52d57c6c3e
children 8c2402a78bb0
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
1049
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
1 ##############################################################################
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
2 #
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
3 # Copyright (c) 2001, 2002 Zope Corporation and Contributors.
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
4 # All Rights Reserved.
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
5 #
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
6 # This software is subject to the provisions of the Zope Public License,
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
7 # Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
8 # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
9 # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
10 # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
11 # FOR A PARTICULAR PURPOSE
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
12 #
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
13 ##############################################################################
2005
fc52d57c6c3e documentation cleanup
Richard Jones <richard@users.sourceforge.net>
parents: 1409
diff changeset
14 """Interpreter for a pre-compiled TAL program.
1049
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
15 """
2005
fc52d57c6c3e documentation cleanup
Richard Jones <richard@users.sourceforge.net>
parents: 1409
diff changeset
16 __docformat__ = 'restructuredtext'
1049
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
17
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
18 import sys
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
19 import getopt
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
20
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
21 from cgi import escape
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
22
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
23 try:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
24 from cStringIO import StringIO
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
25 except ImportError:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
26 from StringIO import StringIO
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
27
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
28 from TALDefs import quote, TAL_VERSION, TALError, METALError
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
29 from TALDefs import isCurrentVersion, getProgramVersion, getProgramMode
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
30 from TALGenerator import TALGenerator
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
31
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
32 BOOLEAN_HTML_ATTRS = [
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
33 # List of Boolean attributes in HTML that should be rendered in
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
34 # minimized form (e.g. <img ismap> rather than <img ismap="">)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
35 # From http://www.w3.org/TR/xhtml1/#guidelines (C.10)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
36 # XXX The problem with this is that this is not valid XML and
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
37 # can't be parsed back!
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
38 "compact", "nowrap", "ismap", "declare", "noshade", "checked",
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
39 "disabled", "readonly", "multiple", "selected", "noresize",
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
40 "defer"
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
41 ]
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
42
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
43 EMPTY_HTML_TAGS = [
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
44 # List of HTML tags with an empty content model; these are
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
45 # rendered in minimized form, e.g. <img />.
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
46 # From http://www.w3.org/TR/xhtml1/#dtds
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
47 "base", "meta", "link", "hr", "br", "param", "img", "area",
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
48 "input", "col", "basefont", "isindex", "frame",
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
49 ]
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
50
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
51 class AltTALGenerator(TALGenerator):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
52
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
53 def __init__(self, repldict, expressionCompiler=None, xml=0):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
54 self.repldict = repldict
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
55 self.enabled = 1
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
56 TALGenerator.__init__(self, expressionCompiler, xml)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
57
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
58 def enable(self, enabled):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
59 self.enabled = enabled
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
60
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
61 def emit(self, *args):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
62 if self.enabled:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
63 apply(TALGenerator.emit, (self,) + args)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
64
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
65 def emitStartElement(self, name, attrlist, taldict, metaldict,
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
66 position=(None, None), isend=0):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
67 metaldict = {}
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
68 taldict = {}
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
69 if self.enabled and self.repldict:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
70 taldict["attributes"] = "x x"
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
71 TALGenerator.emitStartElement(self, name, attrlist,
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
72 taldict, metaldict, position, isend)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
73
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
74 def replaceAttrs(self, attrlist, repldict):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
75 if self.enabled and self.repldict:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
76 repldict = self.repldict
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
77 self.repldict = None
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
78 return TALGenerator.replaceAttrs(self, attrlist, repldict)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
79
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
80
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
81 class TALInterpreter:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
82
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
83 def __init__(self, program, macros, engine, stream=None,
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
84 debug=0, wrap=60, metal=1, tal=1, showtal=-1,
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
85 strictinsert=1, stackLimit=100):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
86 self.program = program
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
87 self.macros = macros
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
88 self.engine = engine
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
89 self.Default = engine.getDefault()
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
90 self.stream = stream or sys.stdout
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
91 self._stream_write = self.stream.write
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
92 self.debug = debug
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
93 self.wrap = wrap
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
94 self.metal = metal
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
95 self.tal = tal
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
96 if tal:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
97 self.dispatch = self.bytecode_handlers_tal
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
98 else:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
99 self.dispatch = self.bytecode_handlers
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
100 assert showtal in (-1, 0, 1)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
101 if showtal == -1:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
102 showtal = (not tal)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
103 self.showtal = showtal
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
104 self.strictinsert = strictinsert
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
105 self.stackLimit = stackLimit
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
106 self.html = 0
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
107 self.endsep = "/>"
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
108 self.endlen = len(self.endsep)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
109 self.macroStack = []
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
110 self.popMacro = self.macroStack.pop
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
111 self.position = None, None # (lineno, offset)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
112 self.col = 0
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
113 self.level = 0
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
114 self.scopeLevel = 0
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
115 self.sourceFile = None
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
116
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
117 def saveState(self):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
118 return (self.position, self.col, self.stream,
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
119 self.scopeLevel, self.level)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
120
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
121 def restoreState(self, state):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
122 (self.position, self.col, self.stream, scopeLevel, level) = state
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
123 self._stream_write = self.stream.write
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
124 assert self.level == level
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
125 while self.scopeLevel > scopeLevel:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
126 self.engine.endScope()
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
127 self.scopeLevel = self.scopeLevel - 1
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
128 self.engine.setPosition(self.position)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
129
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
130 def restoreOutputState(self, state):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
131 (dummy, self.col, self.stream, scopeLevel, level) = state
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
132 self._stream_write = self.stream.write
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
133 assert self.level == level
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
134 assert self.scopeLevel == scopeLevel
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
135
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
136 def pushMacro(self, macroName, slots, entering=1):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
137 if len(self.macroStack) >= self.stackLimit:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
138 raise METALError("macro nesting limit (%d) exceeded "
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
139 "by %s" % (self.stackLimit, `macroName`))
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
140 self.macroStack.append([macroName, slots, entering])
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
141
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
142 def macroContext(self, what):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
143 macroStack = self.macroStack
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
144 i = len(macroStack)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
145 while i > 0:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
146 i = i-1
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
147 if macroStack[i][0] == what:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
148 return i
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
149 return -1
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
150
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
151 def __call__(self):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
152 assert self.level == 0
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
153 assert self.scopeLevel == 0
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
154 self.interpret(self.program)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
155 assert self.level == 0
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
156 assert self.scopeLevel == 0
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
157 if self.col > 0:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
158 self._stream_write("\n")
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
159 self.col = 0
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
160
1309
309f125f86cc removed use of string/strop from TAL/TALInterpreter
Richard Jones <richard@users.sourceforge.net>
parents: 1049
diff changeset
161 def stream_write(self, s, len=len):
1049
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
162 self._stream_write(s)
1309
309f125f86cc removed use of string/strop from TAL/TALInterpreter
Richard Jones <richard@users.sourceforge.net>
parents: 1049
diff changeset
163 i = s.rfind('\n')
1049
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
164 if i < 0:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
165 self.col = self.col + len(s)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
166 else:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
167 self.col = len(s) - (i + 1)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
168
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
169 bytecode_handlers = {}
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
170
1409
8dc60d87ab42 Fixed a backlog of bug reports, and worked on python 2.3 compatibility:
Richard Jones <richard@users.sourceforge.net>
parents: 1309
diff changeset
171 def interpret(self, program):
1049
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
172 oldlevel = self.level
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
173 self.level = oldlevel + 1
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
174 handlers = self.dispatch
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
175 try:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
176 if self.debug:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
177 for (opcode, args) in program:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
178 s = "%sdo_%s%s\n" % (" "*self.level, opcode,
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
179 repr(args))
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
180 if len(s) > 80:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
181 s = s[:76] + "...\n"
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
182 sys.stderr.write(s)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
183 handlers[opcode](self, args)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
184 else:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
185 for (opcode, args) in program:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
186 handlers[opcode](self, args)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
187 finally:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
188 self.level = oldlevel
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
189
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
190 def do_version(self, version):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
191 assert version == TAL_VERSION
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
192 bytecode_handlers["version"] = do_version
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
193
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
194 def do_mode(self, mode):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
195 assert mode in ("html", "xml")
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
196 self.html = (mode == "html")
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
197 if self.html:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
198 self.endsep = " />"
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
199 else:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
200 self.endsep = "/>"
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
201 self.endlen = len(self.endsep)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
202 bytecode_handlers["mode"] = do_mode
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
203
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
204 def do_setSourceFile(self, source_file):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
205 self.sourceFile = source_file
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
206 self.engine.setSourceFile(source_file)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
207 bytecode_handlers["setSourceFile"] = do_setSourceFile
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
208
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
209 def do_setPosition(self, position):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
210 self.position = position
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
211 self.engine.setPosition(position)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
212 bytecode_handlers["setPosition"] = do_setPosition
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
213
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
214 def do_startEndTag(self, stuff):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
215 self.do_startTag(stuff, self.endsep, self.endlen)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
216 bytecode_handlers["startEndTag"] = do_startEndTag
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
217
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
218 def do_startTag(self, (name, attrList),
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
219 end=">", endlen=1, _len=len):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
220 # The bytecode generator does not cause calls to this method
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
221 # for start tags with no attributes; those are optimized down
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
222 # to rawtext events. Hence, there is no special "fast path"
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
223 # for that case.
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
224 _stream_write = self._stream_write
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
225 _stream_write("<" + name)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
226 namelen = _len(name)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
227 col = self.col + namelen + 1
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
228 wrap = self.wrap
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
229 align = col + 1
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
230 if align >= wrap/2:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
231 align = 4 # Avoid a narrow column far to the right
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
232 attrAction = self.dispatch["<attrAction>"]
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
233 try:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
234 for item in attrList:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
235 if _len(item) == 2:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
236 name, s = item
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
237 else:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
238 ok, name, s = attrAction(self, item)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
239 if not ok:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
240 continue
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
241 slen = _len(s)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
242 if (wrap and
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
243 col >= align and
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
244 col + 1 + slen > wrap):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
245 _stream_write("\n" + " "*align)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
246 col = align + slen
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
247 else:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
248 s = " " + s
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
249 col = col + 1 + slen
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
250 _stream_write(s)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
251 _stream_write(end)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
252 col = col + endlen
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
253 finally:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
254 self.col = col
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
255 bytecode_handlers["startTag"] = do_startTag
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
256
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
257 def attrAction(self, item):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
258 name, value, action = item[:3]
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
259 if action == 1 or (action > 1 and not self.showtal):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
260 return 0, name, value
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
261 macs = self.macroStack
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
262 if action == 2 and self.metal and macs:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
263 if len(macs) > 1 or not macs[-1][2]:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
264 # Drop all METAL attributes at a use-depth above one.
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
265 return 0, name, value
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
266 # Clear 'entering' flag
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
267 macs[-1][2] = 0
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
268 # Convert or drop depth-one METAL attributes.
1309
309f125f86cc removed use of string/strop from TAL/TALInterpreter
Richard Jones <richard@users.sourceforge.net>
parents: 1049
diff changeset
269 i = name.rfind(":") + 1
1049
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
270 prefix, suffix = name[:i], name[i:]
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
271 if suffix == "define-macro":
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
272 # Convert define-macro as we enter depth one.
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
273 name = prefix + "use-macro"
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
274 value = macs[-1][0] # Macro name
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
275 elif suffix == "define-slot":
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
276 name = prefix + "slot"
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
277 elif suffix == "fill-slot":
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
278 pass
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
279 else:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
280 return 0, name, value
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
281
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
282 if value is None:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
283 value = name
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
284 else:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
285 value = "%s=%s" % (name, quote(value))
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
286 return 1, name, value
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
287
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
288 def attrAction_tal(self, item):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
289 name, value, action = item[:3]
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
290 if action > 1:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
291 return self.attrAction(item)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
292 ok = 1
1309
309f125f86cc removed use of string/strop from TAL/TALInterpreter
Richard Jones <richard@users.sourceforge.net>
parents: 1049
diff changeset
293 if self.html and name.lower() in BOOLEAN_HTML_ATTRS:
1049
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
294 evalue = self.engine.evaluateBoolean(item[3])
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
295 if evalue is self.Default:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
296 if action == 1: # Cancelled insert
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
297 ok = 0
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
298 elif evalue:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
299 value = None
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
300 else:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
301 ok = 0
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
302 else:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
303 evalue = self.engine.evaluateText(item[3])
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
304 if evalue is self.Default:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
305 if action == 1: # Cancelled insert
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
306 ok = 0
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
307 else:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
308 if evalue is None:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
309 ok = 0
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
310 value = evalue
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
311 if ok:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
312 if value is None:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
313 value = name
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
314 value = "%s=%s" % (name, quote(value))
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
315 return ok, name, value
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
316
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
317 bytecode_handlers["<attrAction>"] = attrAction
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
318
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
319 def no_tag(self, start, program):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
320 state = self.saveState()
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
321 self.stream = stream = StringIO()
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
322 self._stream_write = stream.write
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
323 self.interpret(start)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
324 self.restoreOutputState(state)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
325 self.interpret(program)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
326
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
327 def do_optTag(self, (name, cexpr, tag_ns, isend, start, program),
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
328 omit=0):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
329 if tag_ns and not self.showtal:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
330 return self.no_tag(start, program)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
331
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
332 self.interpret(start)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
333 if not isend:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
334 self.interpret(program)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
335 s = '</%s>' % name
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
336 self._stream_write(s)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
337 self.col = self.col + len(s)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
338
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
339 def do_optTag_tal(self, stuff):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
340 cexpr = stuff[1]
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
341 if cexpr is not None and (cexpr == '' or
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
342 self.engine.evaluateBoolean(cexpr)):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
343 self.no_tag(stuff[-2], stuff[-1])
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
344 else:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
345 self.do_optTag(stuff)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
346 bytecode_handlers["optTag"] = do_optTag
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
347
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
348 def dumpMacroStack(self, prefix, suffix, value):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
349 sys.stderr.write("+---- %s%s = %s\n" % (prefix, suffix, value))
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
350 for i in range(len(self.macroStack)):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
351 what, macroName, slots = self.macroStack[i]
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
352 sys.stderr.write("| %2d. %-12s %-12s %s\n" %
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
353 (i, what, macroName, slots and slots.keys()))
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
354 sys.stderr.write("+--------------------------------------\n")
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
355
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
356 def do_rawtextBeginScope(self, (s, col, position, closeprev, dict)):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
357 self._stream_write(s)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
358 self.col = col
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
359 self.do_setPosition(position)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
360 if closeprev:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
361 engine = self.engine
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
362 engine.endScope()
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
363 engine.beginScope()
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
364 else:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
365 self.engine.beginScope()
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
366 self.scopeLevel = self.scopeLevel + 1
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
367
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
368 def do_rawtextBeginScope_tal(self, (s, col, position, closeprev, dict)):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
369 self._stream_write(s)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
370 self.col = col
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
371 self.do_setPosition(position)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
372 engine = self.engine
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
373 if closeprev:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
374 engine.endScope()
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
375 engine.beginScope()
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
376 else:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
377 engine.beginScope()
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
378 self.scopeLevel = self.scopeLevel + 1
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
379 engine.setLocal("attrs", dict)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
380 bytecode_handlers["rawtextBeginScope"] = do_rawtextBeginScope
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
381
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
382 def do_beginScope(self, dict):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
383 self.engine.beginScope()
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
384 self.scopeLevel = self.scopeLevel + 1
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
385
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
386 def do_beginScope_tal(self, dict):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
387 engine = self.engine
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
388 engine.beginScope()
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
389 engine.setLocal("attrs", dict)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
390 self.scopeLevel = self.scopeLevel + 1
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
391 bytecode_handlers["beginScope"] = do_beginScope
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
392
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
393 def do_endScope(self, notused=None):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
394 self.engine.endScope()
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
395 self.scopeLevel = self.scopeLevel - 1
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
396 bytecode_handlers["endScope"] = do_endScope
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
397
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
398 def do_setLocal(self, notused):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
399 pass
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
400
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
401 def do_setLocal_tal(self, (name, expr)):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
402 self.engine.setLocal(name, self.engine.evaluateValue(expr))
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
403 bytecode_handlers["setLocal"] = do_setLocal
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
404
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
405 def do_setGlobal_tal(self, (name, expr)):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
406 self.engine.setGlobal(name, self.engine.evaluateValue(expr))
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
407 bytecode_handlers["setGlobal"] = do_setLocal
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
408
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
409 def do_insertText(self, stuff):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
410 self.interpret(stuff[1])
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
411
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
412 def do_insertText_tal(self, stuff):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
413 text = self.engine.evaluateText(stuff[0])
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
414 if text is None:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
415 return
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
416 if text is self.Default:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
417 self.interpret(stuff[1])
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
418 return
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
419 s = escape(text)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
420 self._stream_write(s)
1309
309f125f86cc removed use of string/strop from TAL/TALInterpreter
Richard Jones <richard@users.sourceforge.net>
parents: 1049
diff changeset
421 i = s.rfind('\n')
1049
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
422 if i < 0:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
423 self.col = self.col + len(s)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
424 else:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
425 self.col = len(s) - (i + 1)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
426 bytecode_handlers["insertText"] = do_insertText
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
427
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
428 def do_insertStructure(self, stuff):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
429 self.interpret(stuff[2])
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
430
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
431 def do_insertStructure_tal(self, (expr, repldict, block)):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
432 structure = self.engine.evaluateStructure(expr)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
433 if structure is None:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
434 return
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
435 if structure is self.Default:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
436 self.interpret(block)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
437 return
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
438 text = str(structure)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
439 if not (repldict or self.strictinsert):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
440 # Take a shortcut, no error checking
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
441 self.stream_write(text)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
442 return
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
443 if self.html:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
444 self.insertHTMLStructure(text, repldict)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
445 else:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
446 self.insertXMLStructure(text, repldict)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
447 bytecode_handlers["insertStructure"] = do_insertStructure
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
448
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
449 def insertHTMLStructure(self, text, repldict):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
450 from HTMLTALParser import HTMLTALParser
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
451 gen = AltTALGenerator(repldict, self.engine, 0)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
452 p = HTMLTALParser(gen) # Raises an exception if text is invalid
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
453 p.parseString(text)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
454 program, macros = p.getCode()
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
455 self.interpret(program)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
456
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
457 def insertXMLStructure(self, text, repldict):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
458 from TALParser import TALParser
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
459 gen = AltTALGenerator(repldict, self.engine, 0)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
460 p = TALParser(gen)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
461 gen.enable(0)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
462 p.parseFragment('<!DOCTYPE foo PUBLIC "foo" "bar"><foo>')
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
463 gen.enable(1)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
464 p.parseFragment(text) # Raises an exception if text is invalid
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
465 gen.enable(0)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
466 p.parseFragment('</foo>', 1)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
467 program, macros = gen.getCode()
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
468 self.interpret(program)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
469
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
470 def do_loop(self, (name, expr, block)):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
471 self.interpret(block)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
472
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
473 def do_loop_tal(self, (name, expr, block)):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
474 iterator = self.engine.setRepeat(name, expr)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
475 while iterator.next():
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
476 self.interpret(block)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
477 bytecode_handlers["loop"] = do_loop
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
478
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
479 def do_rawtextColumn(self, (s, col)):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
480 self._stream_write(s)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
481 self.col = col
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
482 bytecode_handlers["rawtextColumn"] = do_rawtextColumn
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
483
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
484 def do_rawtextOffset(self, (s, offset)):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
485 self._stream_write(s)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
486 self.col = self.col + offset
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
487 bytecode_handlers["rawtextOffset"] = do_rawtextOffset
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
488
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
489 def do_condition(self, (condition, block)):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
490 if not self.tal or self.engine.evaluateBoolean(condition):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
491 self.interpret(block)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
492 bytecode_handlers["condition"] = do_condition
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
493
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
494 def do_defineMacro(self, (macroName, macro)):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
495 macs = self.macroStack
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
496 if len(macs) == 1:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
497 entering = macs[-1][2]
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
498 if not entering:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
499 macs.append(None)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
500 self.interpret(macro)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
501 macs.pop()
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
502 return
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
503 self.interpret(macro)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
504 bytecode_handlers["defineMacro"] = do_defineMacro
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
505
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
506 def do_useMacro(self, (macroName, macroExpr, compiledSlots, block)):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
507 if not self.metal:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
508 self.interpret(block)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
509 return
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
510 macro = self.engine.evaluateMacro(macroExpr)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
511 if macro is self.Default:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
512 macro = block
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
513 else:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
514 if not isCurrentVersion(macro):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
515 raise METALError("macro %s has incompatible version %s" %
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
516 (`macroName`, `getProgramVersion(macro)`),
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
517 self.position)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
518 mode = getProgramMode(macro)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
519 if mode != (self.html and "html" or "xml"):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
520 raise METALError("macro %s has incompatible mode %s" %
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
521 (`macroName`, `mode`), self.position)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
522 self.pushMacro(macroName, compiledSlots)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
523 saved_source = self.sourceFile
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
524 saved_position = self.position # Used by Boa Constructor
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
525 self.interpret(macro)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
526 if self.sourceFile != saved_source:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
527 self.engine.setSourceFile(saved_source)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
528 self.sourceFile = saved_source
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
529 self.popMacro()
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
530 bytecode_handlers["useMacro"] = do_useMacro
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
531
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
532 def do_fillSlot(self, (slotName, block)):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
533 # This is only executed if the enclosing 'use-macro' evaluates
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
534 # to 'default'.
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
535 self.interpret(block)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
536 bytecode_handlers["fillSlot"] = do_fillSlot
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
537
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
538 def do_defineSlot(self, (slotName, block)):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
539 if not self.metal:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
540 self.interpret(block)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
541 return
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
542 macs = self.macroStack
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
543 if macs and macs[-1] is not None:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
544 saved_source = self.sourceFile
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
545 saved_position = self.position # Used by Boa Constructor
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
546 macroName, slots = self.popMacro()[:2]
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
547 slot = slots.get(slotName)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
548 if slot is not None:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
549 self.interpret(slot)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
550 if self.sourceFile != saved_source:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
551 self.engine.setSourceFile(saved_source)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
552 self.sourceFile = saved_source
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
553 self.pushMacro(macroName, slots, entering=0)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
554 return
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
555 self.pushMacro(macroName, slots)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
556 if len(macs) == 1:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
557 self.interpret(block)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
558 return
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
559 self.interpret(block)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
560 bytecode_handlers["defineSlot"] = do_defineSlot
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
561
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
562 def do_onError(self, (block, handler)):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
563 self.interpret(block)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
564
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
565 def do_onError_tal(self, (block, handler)):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
566 state = self.saveState()
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
567 self.stream = stream = StringIO()
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
568 self._stream_write = stream.write
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
569 try:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
570 self.interpret(block)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
571 except:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
572 exc = sys.exc_info()[1]
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
573 self.restoreState(state)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
574 engine = self.engine
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
575 engine.beginScope()
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
576 error = engine.createErrorInfo(exc, self.position)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
577 engine.setLocal('error', error)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
578 try:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
579 self.interpret(handler)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
580 finally:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
581 engine.endScope()
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
582 else:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
583 self.restoreOutputState(state)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
584 self.stream_write(stream.getvalue())
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
585 bytecode_handlers["onError"] = do_onError
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
586
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
587 bytecode_handlers_tal = bytecode_handlers.copy()
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
588 bytecode_handlers_tal["rawtextBeginScope"] = do_rawtextBeginScope_tal
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
589 bytecode_handlers_tal["beginScope"] = do_beginScope_tal
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
590 bytecode_handlers_tal["setLocal"] = do_setLocal_tal
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
591 bytecode_handlers_tal["setGlobal"] = do_setGlobal_tal
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
592 bytecode_handlers_tal["insertStructure"] = do_insertStructure_tal
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
593 bytecode_handlers_tal["insertText"] = do_insertText_tal
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
594 bytecode_handlers_tal["loop"] = do_loop_tal
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
595 bytecode_handlers_tal["onError"] = do_onError_tal
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
596 bytecode_handlers_tal["<attrAction>"] = attrAction_tal
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
597 bytecode_handlers_tal["optTag"] = do_optTag_tal
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
598
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
599
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
600 def test():
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
601 from driver import FILE, parsefile
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
602 from DummyEngine import DummyEngine
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
603 try:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
604 opts, args = getopt.getopt(sys.argv[1:], "")
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
605 except getopt.error, msg:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
606 print msg
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
607 sys.exit(2)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
608 if args:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
609 file = args[0]
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
610 else:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
611 file = FILE
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
612 doc = parsefile(file)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
613 compiler = TALCompiler(doc)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
614 program, macros = compiler()
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
615 engine = DummyEngine()
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
616 interpreter = TALInterpreter(program, macros, engine)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
617 interpreter()
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
618
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
619 if __name__ == "__main__":
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
620 test()

Roundup Issue Tracker: http://roundup-tracker.org/