blob: 00c9b45c1e6e691e51a575e6b3e9b202b72d1109 [file] [log] [blame]
edisonn@google.coma2fab9d2013-06-14 19:22:19 +00001
2
edisonn@google.com1a191c62013-06-11 21:44:08 +00003import sys
4
edisonn@google.coma2fab9d2013-06-14 19:22:19 +00005import datatypes
6import pdfspec_autogen
edisonn@google.comaf3daa02013-06-12 19:07:45 +00007
edisonn@google.com1a191c62013-06-11 21:44:08 +00008
edisonn@google.com45327112013-06-13 20:02:29 +00009
10
edisonn@google.com1a191c62013-06-11 21:44:08 +000011class PdfField:
12 def __init__(self, parent, name, abr):
13 self.fParent = parent
14 self.fName = name
15 self.fAbr = abr
16
17 self.fDefault = ''
18 self.fType = ''
edisonn@google.comaf3daa02013-06-12 19:07:45 +000019 self.fCppName = ''
20 self.fCppType = ''
21 self.fCppReader = ''
22 self.fValidOptions = []
23 self.fHasMust = False
24 self.fMustBe = ''
edisonn@google.com1a191c62013-06-11 21:44:08 +000025
26 def must(self, value):
edisonn@google.comaf3daa02013-06-12 19:07:45 +000027 self.fHasMust = True
28 self.fMustBe = value
29 return self
edisonn@google.com1a191c62013-06-11 21:44:08 +000030
31 def default(self, value):
32 self.fDefault = value
33 return self
34
edisonn@google.comaf3daa02013-06-12 19:07:45 +000035 def number(self, name):
edisonn@google.com1a191c62013-06-11 21:44:08 +000036 self.fType = 'number'
edisonn@google.comaf3daa02013-06-12 19:07:45 +000037 self.fCppName = name
38 self.fCppType = 'double'
39 self.fCppReader = 'DoubleFromDictionary'
edisonn@google.com1a191c62013-06-11 21:44:08 +000040 return self
41
edisonn@google.comaf3daa02013-06-12 19:07:45 +000042 def integer(self, name):
edisonn@google.com1a191c62013-06-11 21:44:08 +000043 self.fType = 'integer'
edisonn@google.comaf3daa02013-06-12 19:07:45 +000044 self.fCppName = name
45 self.fCppType = 'long'
46 self.fCppReader = 'LongFromDictionary'
edisonn@google.com1a191c62013-06-11 21:44:08 +000047 return self
48
edisonn@google.comaf3daa02013-06-12 19:07:45 +000049 def name(self, name):
edisonn@google.com1a191c62013-06-11 21:44:08 +000050 self.fType = 'name'
edisonn@google.comaf3daa02013-06-12 19:07:45 +000051 self.fCppName = name
52 self.fCppType = 'std::string'
53 self.fCppReader = 'NameFromDictionary'
edisonn@google.com1a191c62013-06-11 21:44:08 +000054 return self
55
edisonn@google.comaf3daa02013-06-12 19:07:45 +000056 def string(self, name):
edisonn@google.com1a191c62013-06-11 21:44:08 +000057 self.fType = 'string'
edisonn@google.comaf3daa02013-06-12 19:07:45 +000058 self.fCppName = name
59 self.fCppType = 'std::string'
60 self.fCppReader = 'StringFromDictionary'
edisonn@google.com1a191c62013-06-11 21:44:08 +000061 return self
62
edisonn@google.comaf3daa02013-06-12 19:07:45 +000063 def multiple(self, validOptions):
64 self.fValidOptions = validOptions
edisonn@google.com1a191c62013-06-11 21:44:08 +000065 return self
66
edisonn@google.com45327112013-06-13 20:02:29 +000067 def dictionary(self, name):
68 self.fType = 'dictionary'
69 self.fCppName = name
edisonn@google.coma2fab9d2013-06-14 19:22:19 +000070 self.fDictionaryType = 'Dictionary'
71 self.fCppType = 'SkPdfDictionary*'
edisonn@google.com45327112013-06-13 20:02:29 +000072 self.fCppReader = 'DictionaryFromDictionary'
edisonn@google.coma2fab9d2013-06-14 19:22:19 +000073 self.fDefault = datatypes.CppNull()
edisonn@google.com45327112013-06-13 20:02:29 +000074 return self
75
76 def type(self, type):
77 # TODO (edisonn): if simple type, use it, otherwise set it to Dictionary, and set a mask for valid types, like array or name
edisonn@google.coma2fab9d2013-06-14 19:22:19 +000078 type = type.replace('or', ' ')
79 type = type.replace(',', ' ')
80 type = type.replace('text', ' ') # TODO(edisonn): what is the difference between 'text string' and 'string'?
81
82 type = type.strip()
83 types = type.split()
84
85 if len(types) == 1:
86 if type == 'integer':
87 self.integer(self.fCppName)
88 self.default(datatypes.PdfInteger(0))
89 return self
90
91 if type == 'number':
92 self.number(self.fCppName)
93 self.default(datatypes.PdfNumber(0))
94 return self
95
96 if type == 'string':
97 self.string(self.fCppName)
98 self.default(datatypes.PdfString('""'))
99 return self
100
101 if type == 'name':
102 self.name(self.fCppName)
103 self.default(datatypes.PdfName('""'))
104 return self
105
106 if type == 'dictionary':
107 self.dictionary(self.fCppName)
108 self.default(datatypes.CppNull())
109 return self
110
111 self.fType = 'object'
112 self.fDictionaryType = 'Object'
113 self.fCppType = 'SkPdfObject*'
114 self.fCppReader = 'ObjectFromDictionary'
115 self.fDefault = datatypes.CppNull()
edisonn@google.com45327112013-06-13 20:02:29 +0000116 return self
117
118 def comment(self, comment):
119 return self
120
edisonn@google.com1a191c62013-06-11 21:44:08 +0000121 def done(self):
122 return self.fParent
123
124
125class PdfClassField:
edisonn@google.com45327112013-06-13 20:02:29 +0000126 def __init__(self, parent, required, version='', inheritable=False, comment=''):
edisonn@google.comaf3daa02013-06-12 19:07:45 +0000127 #self.fProp = ''
edisonn@google.com1a191c62013-06-11 21:44:08 +0000128 self.fParent = parent
129 self.fRequired = required
edisonn@google.com45327112013-06-13 20:02:29 +0000130 self.fVersion = version
131 self.fInheritable = inheritable
132 self.fComment = comment
edisonn@google.com1a191c62013-06-11 21:44:08 +0000133
edisonn@google.comaf3daa02013-06-12 19:07:45 +0000134 def field(self, name, abr=''):
135 self.fProp = PdfField(self, name, abr)
136 return self.fProp
edisonn@google.com1a191c62013-06-11 21:44:08 +0000137
138 def done(self):
139 return self.fParent
140
141class PdfClass:
edisonn@google.com45327112013-06-13 20:02:29 +0000142 def __init__(self, name, base, comment):
edisonn@google.com1a191c62013-06-11 21:44:08 +0000143 self.fFields = []
144 self.fIncludes = []
edisonn@google.comaf3daa02013-06-12 19:07:45 +0000145 self.fCCPublic = []
146 self.fCCPrivate = []
edisonn@google.com1a191c62013-06-11 21:44:08 +0000147 self.fName = name
148 self.fBase = base
edisonn@google.com45327112013-06-13 20:02:29 +0000149 self.fComment = comment
edisonn@google.com1a191c62013-06-11 21:44:08 +0000150
edisonn@google.comf7dd4912013-06-11 23:06:16 +0000151 self.fEnumSubclasses = []
152
153 self.fEnum = '!UNDEFINED'
154 self.fEnumEnd = '!UNDEFINED'
edisonn@google.coma2fab9d2013-06-14 19:22:19 +0000155 self.fCheck = ''
edisonn@google.comf7dd4912013-06-11 23:06:16 +0000156
edisonn@google.coma2fab9d2013-06-14 19:22:19 +0000157 def check(self, ifCheck):
158 self.fCheck = ifCheck
159 return self
160
edisonn@google.comaf3daa02013-06-12 19:07:45 +0000161 def required(self, badDefault):
edisonn@google.com1a191c62013-06-11 21:44:08 +0000162 field = PdfClassField(self, True)
edisonn@google.comaf3daa02013-06-12 19:07:45 +0000163 field.fBadDefault = badDefault
edisonn@google.com1a191c62013-06-11 21:44:08 +0000164 self.fFields.append(field)
165 return field
166
167 def optional(self):
168 field = PdfClassField(self, False)
169 self.fFields.append(field)
170 return field
edisonn@google.com45327112013-06-13 20:02:29 +0000171
172 #([Required] [;] [inheritable] [;] [version]; [comments])
173 # version: PDF [d].[d]
174 # ; separate props
175 #inheritable
176 #version
177 #required, if
178 #optional, if
edisonn@google.com1a191c62013-06-11 21:44:08 +0000179
180 def include(self, path):
181 self.fIncludes.append(path)
182 return self
183
edisonn@google.comaf3daa02013-06-12 19:07:45 +0000184 def carbonCopyPublic(self, cc):
185 self.fCCPublic.append(cc)
186 return self
187
188 def carbonCopyPrivate(self, cc):
189 self.fCCPrivate.append(cc)
edisonn@google.com1a191c62013-06-11 21:44:08 +0000190 return self
edisonn@google.com45327112013-06-13 20:02:29 +0000191
192 def done(self):
193 return
edisonn@google.com1a191c62013-06-11 21:44:08 +0000194
195class PdfClassManager:
196 def __init__(self):
edisonn@google.comf7dd4912013-06-11 23:06:16 +0000197 self.fClasses = {}
edisonn@google.comaf3daa02013-06-12 19:07:45 +0000198 self.fClassesNamesInOrder = []
edisonn@google.com1a191c62013-06-11 21:44:08 +0000199
edisonn@google.com45327112013-06-13 20:02:29 +0000200 def addClass(self, name, base='Object', comment=''):
edisonn@google.comaf3daa02013-06-12 19:07:45 +0000201 if name == 'Object':
edisonn@google.com45327112013-06-13 20:02:29 +0000202 cls = PdfClass(name, '', comment)
edisonn@google.comaf3daa02013-06-12 19:07:45 +0000203 else:
edisonn@google.com45327112013-06-13 20:02:29 +0000204 cls = PdfClass(name, base, comment)
edisonn@google.comf7dd4912013-06-11 23:06:16 +0000205 self.fClasses[name] = cls
edisonn@google.comaf3daa02013-06-12 19:07:45 +0000206 self.fClassesNamesInOrder.append(name)
edisonn@google.com1a191c62013-06-11 21:44:08 +0000207 return cls
208
edisonn@google.comf7dd4912013-06-11 23:06:16 +0000209 def longName(self, name):
edisonn@google.coma2fab9d2013-06-14 19:22:19 +0000210 #return name
211 # TODO(edisonn): we need the long name to nenerate and sort enums, but we can generate them recursively
edisonn@google.comf7dd4912013-06-11 23:06:16 +0000212 ret = ''
213 while name != '':
214 cls = self.fClasses[name]
215 ret = name + ret
216 name = cls.fBase
217
218 return ret
219
220
221 def writeEnum(self, enum, enumToCls):
222 print(' ' + enum + ',')
223 cls = enumToCls[enum]
224 cls.fEnumSubclasses.sort()
225
226 cnt = 0
227 for sub in cls.fEnumSubclasses:
228 self.writeEnum(cls.fEnumSubclasses[cnt], enumToCls)
229 cnt = cnt + 1
230
231 if cnt != 0:
232 print(' ' + cls.fEnumEnd + ',')
edisonn@google.comaf3daa02013-06-12 19:07:45 +0000233
234
235 def writeAsNull(self, cls, enumToCls):
236 print(' virtual SkPdf' + cls.fName +'* as' + cls.fName + '() {return NULL;}')
237 print(' virtual const SkPdf' + cls.fName +'* as' + cls.fName + '() const {return NULL;}')
238 print
239
240 cnt = 0
241 for sub in cls.fEnumSubclasses:
242 self.writeAsNull(enumToCls[cls.fEnumSubclasses[cnt]], enumToCls)
243 cnt = cnt + 1
244
245
246 def writeAsFoo(self, cls, enumToCls):
247 # TODO(edisonn): add a container, with sections, public, private, default, ...
248 # the end code will be grouped
249
250 # me
251 print('public:')
252 print(' virtual SkPdf' + cls.fName +'* as' + cls.fName + '() {return this;}')
253 print(' virtual const SkPdf' + cls.fName +'* as' + cls.fName + '() const {return this;}')
254 print
255
256 if cls.fName == 'Object':
257 cnt = 0
258 for sub in cls.fEnumSubclasses:
259 self.writeAsNull(enumToCls[cls.fEnumSubclasses[cnt]], enumToCls)
260 cnt = cnt + 1
261
262 if cls.fName != 'Object':
263 print('private:')
264 base = self.fClasses[cls.fBase]
265 cnt = 0
266 for sub in base.fEnumSubclasses:
267 if enumToCls[base.fEnumSubclasses[cnt]].fName != cls.fName:
268 self.writeAsNull(enumToCls[base.fEnumSubclasses[cnt]], enumToCls)
269 cnt = cnt + 1
270
271
edisonn@google.comf7dd4912013-06-11 23:06:16 +0000272
edisonn@google.com1a191c62013-06-11 21:44:08 +0000273 def write(self):
edisonn@google.comf7dd4912013-06-11 23:06:16 +0000274 # generate enum
275 enumsRoot = []
276
277 enumToCls = {}
278
279 for name in self.fClasses:
280 cls = self.fClasses[name]
281 enum = self.longName(name)
edisonn@google.comaf3daa02013-06-12 19:07:45 +0000282 cls.fEnum = 'k' + enum + '_SkPdfObjectType'
283 cls.fEnumEnd = 'k' + enum + '__End_SkPdfObjectType'
edisonn@google.comf7dd4912013-06-11 23:06:16 +0000284
285 if cls.fBase != '':
286 self.fClasses[cls.fBase].fEnumSubclasses.append(cls.fEnum)
287
288 if cls.fBase == '':
289 enumsRoot.append(cls.fEnum)
290
291 enumToCls[cls.fEnum] = cls
292
293 enumsRoot.sort()
294
edisonn@google.comaf3daa02013-06-12 19:07:45 +0000295
296 # TODO(edisonn): move each .h in it's own file
297 # write imports
298
edisonn@google.comf7dd4912013-06-11 23:06:16 +0000299 # write enums
edisonn@google.comaf3daa02013-06-12 19:07:45 +0000300 print('enum SkPdfObjectType {')
edisonn@google.comf7dd4912013-06-11 23:06:16 +0000301 for enum in enumsRoot:
302 self.writeEnum(enum, enumToCls)
303 print('};')
edisonn@google.comaf3daa02013-06-12 19:07:45 +0000304 print
305
306 # write forward class declaration
307 for name in self.fClassesNamesInOrder:
308 print('class SkPdf' + name + ';')
309 print
310
311 for name in self.fClassesNamesInOrder:
312 cls = self.fClasses[name]
313 enum = cls.fEnum
edisonn@google.comf7dd4912013-06-11 23:06:16 +0000314
edisonn@google.comaf3daa02013-06-12 19:07:45 +0000315 if cls.fBase == '':
316 print('class SkPdf' + cls.fName + ' {')
317 else:
318 print('class SkPdf' + cls.fName + ' : public SkPdf' + cls.fBase + ' {')
319
320 print('public:')
321 print(' virtual SkPdfObjectType getType() const { return ' + cls.fEnum + ';}')
322 if len(cls.fEnumSubclasses) == 0:
323 print(' virtual SkPdfObjectType getTypeEnd() const { return (SkPdfObjectType)(' + cls.fEnum + ' + 1);}')
324 else:
325 print(' virtual SkPdfObjectType getTypeEnd() const { return ' + cls.fEnumEnd + ';}')
326
327
328 self.writeAsFoo(cls, enumToCls)
329
330 print('public:')
331 for cc in cls.fCCPublic:
332 print(' ' + cc)
333
334 print('private:')
335 for cc in cls.fCCPrivate:
336 print(' ' + cc)
337
338 if cls.fBase == '':
339 print('protected:')
340 print(' const PdfMemDocument* fPodofoDoc;')
341 print(' const PdfObject* fPodofoObj;')
342 print
343 print('public:')
edisonn@google.com68d15c82013-06-17 20:46:27 +0000344 print(' SkPdf' + cls.fName + '(const PdfMemDocument* podofoDoc = NULL, const PdfObject* podofoObj = NULL) : fPodofoDoc(podofoDoc), fPodofoObj(podofoObj) {}')
345 print(' const PdfMemDocument* doc() const { return fPodofoDoc;}')
edisonn@google.comaf3daa02013-06-12 19:07:45 +0000346 print(' const PdfObject* podofo() const { return fPodofoObj;}')
347 else:
348 print('public:')
edisonn@google.com68d15c82013-06-17 20:46:27 +0000349 print(' SkPdf' + cls.fName + '(const PdfMemDocument* podofoDoc = NULL, const PdfObject* podofoObj = NULL) : SkPdf' + cls.fBase + '(podofoDoc, podofoObj) {}')
edisonn@google.com45327112013-06-13 20:02:29 +0000350 print
edisonn@google.comaf3daa02013-06-12 19:07:45 +0000351
352 #check required fieds, also, there should be an internal_valid() manually wrote for complex
353 # situations
354 # right now valid return true
355 print(' virtual bool valid() const {return true;}')
edisonn@google.com45327112013-06-13 20:02:29 +0000356 print
edisonn@google.comaf3daa02013-06-12 19:07:45 +0000357
edisonn@google.com68d15c82013-06-17 20:46:27 +0000358 print(' SkPdf' + cls.fName + '& operator=(const SkPdf' + cls.fName + '& from) {this->fPodofoDoc = from.fPodofoDoc; this->fPodofoObj = from.fPodofoObj; return *this;}')
359 print
360
edisonn@google.comaf3daa02013-06-12 19:07:45 +0000361 for field in cls.fFields:
362 prop = field.fProp
363 if prop.fCppName != '':
edisonn@google.coma2fab9d2013-06-14 19:22:19 +0000364 if prop.fCppName[0] == '[':
365 print('/*') # comment code of the atributes that can have any name
366
367 print(' ' + prop.fCppType + ' ' + prop.fCppName + '() const {')
368 print(' ' + prop.fCppType + ' ret;')
369 print(' if (' + prop.fCppReader + '(fPodofoDoc, fPodofoObj->GetDictionary(), \"' + prop.fName + '\", \"' + prop.fAbr + '\", &ret)) return ret;')
370 if field.fRequired == False:
371 print(' return ' + prop.fDefault.toCpp() + ';');
372 if field.fRequired == True:
373 print(' // TODO(edisonn): warn about missing required field, assert for known good pdfs')
374 print(' return ' + field.fBadDefault + ';');
375 print(' }')
376 print
edisonn@google.com45327112013-06-13 20:02:29 +0000377
edisonn@google.coma2fab9d2013-06-14 19:22:19 +0000378 if prop.fCppName[0] == '[':
379 print('*/') # comment code of the atributes that can have any name
edisonn@google.com45327112013-06-13 20:02:29 +0000380
edisonn@google.comaf3daa02013-06-12 19:07:45 +0000381
382 print('};')
383 print
384 print
385
386
387
388 # generate constructor when knowing the type
389 # later, p2, generate constructor when not knowing the type - very similar with parsing?
390
edisonn@google.comf7dd4912013-06-11 23:06:16 +0000391 # generate parser
edisonn@google.comaf3daa02013-06-12 19:07:45 +0000392
393 # TODO(edisonn): fast recognition based on must attributes.
394 print('class PodofoMapper {')
395 print('public:')
396 for name in self.fClassesNamesInOrder:
397 cls = self.fClasses[name]
398
edisonn@google.com68d15c82013-06-17 20:46:27 +0000399
400 print(' static bool map(const SkPdfObject& in, SkPdf' + name + '** out) {')
401 print(' return map(*in.doc(), *in.podofo(), out);')
402 print(' }')
403 print
404
405 print(' static bool map(const PdfMemDocument& podofoDoc, const PdfObject& podofoObj, SkPdf' + name + '** out) {')
edisonn@google.comaf3daa02013-06-12 19:07:45 +0000406 print(' if (!isA' + name + '(podofoDoc, podofoObj)) return false;')
407 print
408
409 for sub in cls.fEnumSubclasses:
edisonn@google.com68d15c82013-06-17 20:46:27 +0000410 print(' if (map(podofoDoc, podofoObj, (SkPdf' + enumToCls[sub].fName + '**)out)) return true;')
edisonn@google.comaf3daa02013-06-12 19:07:45 +0000411
412 print
413
414 print(' *out = new SkPdf' + name + '(&podofoDoc, &podofoObj);')
415 print(' return true;')
416 print(' }')
417 print
418
419 for name in self.fClassesNamesInOrder:
420 cls = self.fClasses[name]
421
422 print(' static bool isA' + name + '(const PdfMemDocument& podofoDoc, const PdfObject& podofoObj) {')
423
edisonn@google.coma2fab9d2013-06-14 19:22:19 +0000424 if cls.fCheck != '':
425 print(' return ' + cls.fCheck + ';')
edisonn@google.comaf3daa02013-06-12 19:07:45 +0000426 else:
edisonn@google.coma2fab9d2013-06-14 19:22:19 +0000427 cntMust = 0
428 for field in cls.fFields:
429 prop = field.fProp
430 if prop.fHasMust:
431 cntMust = cntMust + 1
432 print(' ' + prop.fCppType + ' ' + prop.fCppName + ';')
433 print(' if (!' + prop.fCppReader + '(&podofoDoc, podofoObj.GetDictionary(), \"' + prop.fName + '\", \"' + prop.fAbr + '\", &' + prop.fCppName + ')) return false;')
434 print(' if (' + prop.fCppName + ' != ' + prop.fMustBe.toCpp() + ') return false;')
435 print
436
edisonn@google.com68d15c82013-06-17 20:46:27 +0000437 print(' return true;')
edisonn@google.comaf3daa02013-06-12 19:07:45 +0000438
439 print(' }')
440 print
441
442 print('};')
443 print
444
edisonn@google.com1a191c62013-06-11 21:44:08 +0000445 return
446
447def generateCode():
edisonn@google.coma2fab9d2013-06-14 19:22:19 +0000448 manager = PdfClassManager()
edisonn@google.com1a191c62013-06-11 21:44:08 +0000449
edisonn@google.coma2fab9d2013-06-14 19:22:19 +0000450 manager.addClass('Object')
edisonn@google.com1a191c62013-06-11 21:44:08 +0000451
edisonn@google.coma2fab9d2013-06-14 19:22:19 +0000452 manager.addClass('Null').check('podofoObj.GetDataType() == ePdfDataType_Null')
453 manager.addClass('Boolean').check('podofoObj.GetDataType() == ePdfDataType_Bool')
454 manager.addClass('Integer').check('podofoObj.GetDataType() == ePdfDataType_Number')
455 manager.addClass('Number').check('podofoObj.GetDataType() == ePdfDataType_Real')
456 manager.addClass('Name').check('podofoObj.GetDataType() == ePdfDataType_Name')
457 #manager.addClass('Stream') - attached to a dictionary
458 manager.addClass('Reference').check('podofoObj.GetDataType() == ePdfDataType_Reference')
459 manager.addClass('Array').check('podofoObj.GetDataType() == ePdfDataType_Array')
460 manager.addClass('String').check('podofoObj.GetDataType() == ePdfDataType_String')
461 manager.addClass('HexString').check('podofoObj.GetDataType() == ePdfDataType_HexString')
462
463 manager.addClass('Dictionary').check('podofoObj.GetDataType() == ePdfDataType_Dictionary')
464
465 # these classes are not explicitely backed by a table in the pdf spec
466 manager.addClass('XObjectDictionary', 'Dictionary')
467
468 manager.addClass('FontDictionary', 'Dictionary')
469
470 manager.addClass('TrueTypeFontDictionary', 'FontDictionary')
471
472 pdfspec_autogen.buildPdfSpec(manager)
edisonn@google.com1a191c62013-06-11 21:44:08 +0000473
edisonn@google.coma2fab9d2013-06-14 19:22:19 +0000474 manager.addClass('MultiMasterFontDictionary', 'Type1FontDictionary')\
475 .required('NULL')\
476 .field('Subtype')\
477 .name('Subtype')\
edisonn@google.com45327112013-06-13 20:02:29 +0000478 .type('name')\
edisonn@google.coma2fab9d2013-06-14 19:22:19 +0000479 .comment('')\
480 .must(datatypes.PdfName('MMType1'))\
edisonn@google.com45327112013-06-13 20:02:29 +0000481 .done().done()\
edisonn@google.com45327112013-06-13 20:02:29 +0000482
483
edisonn@google.coma2fab9d2013-06-14 19:22:19 +0000484 manager.write()
edisonn@google.com1a191c62013-06-11 21:44:08 +0000485
486 return 1
487
488if '__main__' == __name__:
489 sys.exit(generateCode())
edisonn@google.com45327112013-06-13 20:02:29 +0000490
491