blob: 57ba6ef891ce196fc1f8a1b3da187c8cab6913c0 [file] [log] [blame]
Guido van Rossum95cd2ef1992-12-08 14:37:55 +00001#
2# partparse.py: parse a by-Guido-written-and-by-Jan-Hein-edited LaTeX file,
3# and generate texinfo source.
4#
5# This is *not* a good example of good programming practices. In fact, this
6# file could use a complete rewrite, in order to become faster, more
Guido van Rossum36f219d1996-09-11 21:30:40 +00007# easily extensible and maintainable.
Guido van Rossum95cd2ef1992-12-08 14:37:55 +00008#
9# However, I added some comments on a few places for the pityful person who
10# would ever need to take a look into this file.
11#
12# Have I been clear enough??
13#
14# -jh
Guido van Rossum36f219d1996-09-11 21:30:40 +000015#
16# Yup. I made some performance improvements and hope this lasts a while;
17# I don't want to be the schmuck who ends up re-writting it!
18#
19# -fld
Fred Drakee8b46131998-02-17 05:54:46 +000020#
21# (sometime later...)
22#
23# Ok, I've re-worked substantial chunks of this. It's only getting worse.
24# It just might be gone before the next source release. (Yeah!)
25#
26# -fld
Guido van Rossum95cd2ef1992-12-08 14:37:55 +000027
Guido van Rossum7a2dba21993-11-05 14:45:11 +000028import sys, string, regex, getopt, os
Guido van Rossum95cd2ef1992-12-08 14:37:55 +000029
Guido van Rossum49604d31996-09-10 22:19:51 +000030from types import IntType, ListType, StringType, TupleType
31
Fred Drakee87ab1f1998-05-19 19:37:55 +000032release_version = string.split(sys.version)[0]
Fred Drakee8b46131998-02-17 05:54:46 +000033
Guido van Rossum95cd2ef1992-12-08 14:37:55 +000034# Different parse modes for phase 1
35MODE_REGULAR = 0
36MODE_VERBATIM = 1
37MODE_CS_SCAN = 2
38MODE_COMMENT = 3
39MODE_MATH = 4
40MODE_DMATH = 5
41MODE_GOBBLEWHITE = 6
42
Guido van Rossum5f18d6c1996-09-10 22:34:20 +000043the_modes = (MODE_REGULAR, MODE_VERBATIM, MODE_CS_SCAN, MODE_COMMENT,
Guido van Rossum36f219d1996-09-11 21:30:40 +000044 MODE_MATH, MODE_DMATH, MODE_GOBBLEWHITE)
Guido van Rossum95cd2ef1992-12-08 14:37:55 +000045
46# Show the neighbourhood of the scanned buffer
47def epsilon(buf, where):
Guido van Rossum5f18d6c1996-09-10 22:34:20 +000048 wmt, wpt = where - 10, where + 10
49 if wmt < 0:
50 wmt = 0
51 if wpt > len(buf):
52 wpt = len(buf)
53 return ' Context ' + `buf[wmt:where]` + '.' + `buf[where:wpt]` + '.'
Guido van Rossum95cd2ef1992-12-08 14:37:55 +000054
55# Should return the line number. never worked
56def lin():
Guido van Rossum5f18d6c1996-09-10 22:34:20 +000057 global lineno
58 return ' Line ' + `lineno` + '.'
Guido van Rossum95cd2ef1992-12-08 14:37:55 +000059
60# Displays the recursion level.
61def lv(lvl):
Guido van Rossum5f18d6c1996-09-10 22:34:20 +000062 return ' Level ' + `lvl` + '.'
Guido van Rossum95cd2ef1992-12-08 14:37:55 +000063
64# Combine the three previous functions. Used often.
65def lle(lvl, buf, where):
Guido van Rossum5f18d6c1996-09-10 22:34:20 +000066 return lv(lvl) + lin() + epsilon(buf, where)
67
68
Guido van Rossum95cd2ef1992-12-08 14:37:55 +000069# This class is only needed for _symbolic_ representation of the parse mode.
70class Mode:
Guido van Rossum5f18d6c1996-09-10 22:34:20 +000071 def __init__(self, arg):
72 if arg not in the_modes:
73 raise ValueError, 'mode not in the_modes'
74 self.mode = arg
Guido van Rossum95cd2ef1992-12-08 14:37:55 +000075
Guido van Rossum5f18d6c1996-09-10 22:34:20 +000076 def __cmp__(self, other):
77 if type(self) != type(other):
Guido van Rossum36f219d1996-09-11 21:30:40 +000078 other = mode[other]
Guido van Rossum5f18d6c1996-09-10 22:34:20 +000079 return cmp(self.mode, other.mode)
Guido van Rossum95cd2ef1992-12-08 14:37:55 +000080
Guido van Rossum5f18d6c1996-09-10 22:34:20 +000081 def __repr__(self):
82 if self.mode == MODE_REGULAR:
83 return 'MODE_REGULAR'
84 elif self.mode == MODE_VERBATIM:
85 return 'MODE_VERBATIM'
86 elif self.mode == MODE_CS_SCAN:
87 return 'MODE_CS_SCAN'
88 elif self.mode == MODE_COMMENT:
89 return 'MODE_COMMENT'
90 elif self.mode == MODE_MATH:
91 return 'MODE_MATH'
92 elif self.mode == MODE_DMATH:
93 return 'MODE_DMATH'
94 elif self.mode == MODE_GOBBLEWHITE:
95 return 'MODE_GOBBLEWHITE'
96 else:
97 raise ValueError, 'mode not in the_modes'
Guido van Rossum95cd2ef1992-12-08 14:37:55 +000098
99# just a wrapper around a class initialisation
Guido van Rossum36f219d1996-09-11 21:30:40 +0000100mode = {}
101for t in the_modes:
102 mode[t] = Mode(t)
Guido van Rossum95cd2ef1992-12-08 14:37:55 +0000103
104
105# After phase 1, the text consists of chunks, with a certain type
106# this type will be assigned to the chtype member of the chunk
107# the where-field contains the file position where this is found
108# and the data field contains (1): a tuple describing start- end end
109# positions of the substring (can be used as slice for the buf-variable),
110# (2) just a string, mostly generated by the changeit routine,
111# or (3) a list, describing a (recursive) subgroup of chunks
112PLAIN = 0 # ASSUME PLAINTEXT, data = the text
113GROUP = 1 # GROUP ({}), data = [chunk, chunk,..]
114CSNAME = 2 # CONTROL SEQ TOKEN, data = the command
115COMMENT = 3 # data is the actual comment
116DMATH = 4 # DISPLAYMATH, data = [chunk, chunk,..]
117MATH = 5 # MATH, see DISPLAYMATH
118OTHER = 6 # CHAR WITH CATCODE OTHER, data = char
119ACTIVE = 7 # ACTIVE CHAR
120GOBBLEDWHITE = 8 # Gobbled LWSP, after CSNAME
121ENDLINE = 9 # END-OF-LINE, data = '\n'
122DENDLINE = 10 # DOUBLE EOL, data='\n', indicates \par
123ENV = 11 # LaTeX-environment
Guido van Rossum36f219d1996-09-11 21:30:40 +0000124 # data =(envname,[ch,ch,ch,.])
Guido van Rossum95cd2ef1992-12-08 14:37:55 +0000125CSLINE = 12 # for texi: next chunk will be one group
Guido van Rossum36f219d1996-09-11 21:30:40 +0000126 # of args. Will be set all on 1 line
Guido van Rossum95cd2ef1992-12-08 14:37:55 +0000127IGNORE = 13 # IGNORE this data
128ENDENV = 14 # TEMP END OF GROUP INDICATOR
129IF = 15 # IF-directive
Guido van Rossum36f219d1996-09-11 21:30:40 +0000130 # data = (flag,negate,[ch, ch, ch,...])
131
Guido van Rossum5f18d6c1996-09-10 22:34:20 +0000132the_types = (PLAIN, GROUP, CSNAME, COMMENT, DMATH, MATH, OTHER, ACTIVE,
Guido van Rossum36f219d1996-09-11 21:30:40 +0000133 GOBBLEDWHITE, ENDLINE, DENDLINE, ENV, CSLINE, IGNORE, ENDENV, IF)
Guido van Rossum95cd2ef1992-12-08 14:37:55 +0000134
135# class, just to display symbolic name
136class ChunkType:
Guido van Rossum5f18d6c1996-09-10 22:34:20 +0000137 def __init__(self, chunk_type):
138 if chunk_type not in the_types:
139 raise ValueError, 'chunk_type not in the_types'
140 self.chunk_type = chunk_type
Guido van Rossum95cd2ef1992-12-08 14:37:55 +0000141
Guido van Rossum5f18d6c1996-09-10 22:34:20 +0000142 def __cmp__(self, other):
143 if type(self) != type(other):
Guido van Rossum36f219d1996-09-11 21:30:40 +0000144 other = chunk_type[other]
Guido van Rossum5f18d6c1996-09-10 22:34:20 +0000145 return cmp(self.chunk_type, other.chunk_type)
Guido van Rossum95cd2ef1992-12-08 14:37:55 +0000146
Guido van Rossum5f18d6c1996-09-10 22:34:20 +0000147 def __repr__(self):
148 if self.chunk_type == PLAIN:
149 return 'PLAIN'
150 elif self.chunk_type == GROUP:
151 return 'GROUP'
152 elif self.chunk_type == CSNAME:
153 return 'CSNAME'
154 elif self.chunk_type == COMMENT:
155 return 'COMMENT'
156 elif self.chunk_type == DMATH:
157 return 'DMATH'
158 elif self.chunk_type == MATH:
159 return 'MATH'
160 elif self.chunk_type == OTHER:
161 return 'OTHER'
162 elif self.chunk_type == ACTIVE:
163 return 'ACTIVE'
164 elif self.chunk_type == GOBBLEDWHITE:
165 return 'GOBBLEDWHITE'
166 elif self.chunk_type == DENDLINE:
167 return 'DENDLINE'
168 elif self.chunk_type == ENDLINE:
169 return 'ENDLINE'
170 elif self.chunk_type == ENV:
171 return 'ENV'
172 elif self.chunk_type == CSLINE:
173 return 'CSLINE'
174 elif self.chunk_type == IGNORE:
175 return 'IGNORE'
176 elif self.chunk_type == ENDENV:
177 return 'ENDENV'
178 elif self.chunk_type == IF:
179 return 'IF'
180 else:
181 raise ValueError, 'chunk_type not in the_types'
Guido van Rossum95cd2ef1992-12-08 14:37:55 +0000182
183# ...and the wrapper
Guido van Rossum36f219d1996-09-11 21:30:40 +0000184chunk_type = {}
Guido van Rossum49604d31996-09-10 22:19:51 +0000185for t in the_types:
Guido van Rossum36f219d1996-09-11 21:30:40 +0000186 chunk_type[t] = ChunkType(t)
Guido van Rossum95cd2ef1992-12-08 14:37:55 +0000187
188# store a type object of the ChunkType-class-instance...
Guido van Rossum36f219d1996-09-11 21:30:40 +0000189chunk_type_type = type(chunk_type[PLAIN])
Guido van Rossum49604d31996-09-10 22:19:51 +0000190
Guido van Rossum95cd2ef1992-12-08 14:37:55 +0000191# this class contains a part of the parsed buffer
192class Chunk:
Guido van Rossum5f18d6c1996-09-10 22:34:20 +0000193 def __init__(self, chtype, where, data):
194 if type(chtype) != chunk_type_type:
Guido van Rossum36f219d1996-09-11 21:30:40 +0000195 chtype = chunk_type[chtype]
Guido van Rossum5f18d6c1996-09-10 22:34:20 +0000196 self.chtype = chtype
Guido van Rossum5f18d6c1996-09-10 22:34:20 +0000197 self.where = where
198 self.data = data
Guido van Rossum95cd2ef1992-12-08 14:37:55 +0000199
Fred Drakeb98cd391998-03-04 06:33:43 +0000200 __datatypes = [chunk_type[CSNAME], chunk_type[PLAIN], chunk_type[CSLINE]]
201
Guido van Rossum5f18d6c1996-09-10 22:34:20 +0000202 def __repr__(self):
Fred Drakeb98cd391998-03-04 06:33:43 +0000203 if self.chtype in self.__datatypes:
204 data = s(self.buf, self.data)
205 else:
206 data = self.data
207 return 'chunk' + `self.chtype, self.where, data`
Guido van Rossum95cd2ef1992-12-08 14:37:55 +0000208
209# and the wrapper
Guido van Rossum49604d31996-09-10 22:19:51 +0000210chunk = Chunk
Guido van Rossum95cd2ef1992-12-08 14:37:55 +0000211
212
213error = 'partparse.error'
214
215#
216# TeX's catcodes...
217#
218CC_ESCAPE = 0
219CC_LBRACE = 1
220CC_RBRACE = 2
221CC_MATHSHIFT = 3
222CC_ALIGNMENT = 4
223CC_ENDLINE = 5
224CC_PARAMETER = 6
225CC_SUPERSCRIPT = 7
226CC_SUBSCRIPT = 8
227CC_IGNORE = 9
228CC_WHITE = 10
229CC_LETTER = 11
230CC_OTHER = 12
231CC_ACTIVE = 13
232CC_COMMENT = 14
233CC_INVALID = 15
234
235# and the names
Guido van Rossum5f18d6c1996-09-10 22:34:20 +0000236cc_names = [
237 'CC_ESCAPE',
238 'CC_LBRACE',
239 'CC_RBRACE',
240 'CC_MATHSHIFT',
241 'CC_ALIGNMENT',
242 'CC_ENDLINE',
243 'CC_PARAMETER',
244 'CC_SUPERSCRIPT',
245 'CC_SUBSCRIPT',
246 'CC_IGNORE',
247 'CC_WHITE',
248 'CC_LETTER',
249 'CC_OTHER',
250 'CC_ACTIVE',
251 'CC_COMMENT',
252 'CC_INVALID',
Guido van Rossum95cd2ef1992-12-08 14:37:55 +0000253 ]
254
255# Show a list of catcode-name-symbols
256def pcl(codelist):
Guido van Rossum5f18d6c1996-09-10 22:34:20 +0000257 result = ''
258 for i in codelist:
259 result = result + cc_names[i] + ', '
260 return '[' + result[:-2] + ']'
Guido van Rossum95cd2ef1992-12-08 14:37:55 +0000261
262# the name of the catcode (ACTIVE, OTHER, etc.)
263def pc(code):
Guido van Rossum5f18d6c1996-09-10 22:34:20 +0000264 return cc_names[code]
265
Guido van Rossum95cd2ef1992-12-08 14:37:55 +0000266
267# Which catcodes make the parser stop parsing regular plaintext
Guido van Rossum5f18d6c1996-09-10 22:34:20 +0000268regular_stopcodes = [CC_ESCAPE, CC_LBRACE, CC_RBRACE, CC_MATHSHIFT,
269 CC_ALIGNMENT, CC_PARAMETER, CC_SUPERSCRIPT, CC_SUBSCRIPT,
Guido van Rossum95cd2ef1992-12-08 14:37:55 +0000270 CC_IGNORE, CC_ACTIVE, CC_COMMENT, CC_INVALID, CC_ENDLINE]
271
272# same for scanning a control sequence name
273csname_scancodes = [CC_LETTER]
274
275# same for gobbling LWSP
276white_scancodes = [CC_WHITE]
277##white_scancodes = [CC_WHITE, CC_ENDLINE]
278
279# make a list of all catcode id's, except for catcode ``other''
280all_but_other_codes = range(16)
281del all_but_other_codes[CC_OTHER]
282##print all_but_other_codes
283
284# when does a comment end
285comment_stopcodes = [CC_ENDLINE]
286
287# gather all characters together, specified by a list of catcodes
288def code2string(cc, codelist):
Guido van Rossum5f18d6c1996-09-10 22:34:20 +0000289 ##print 'code2string: codelist = ' + pcl(codelist),
290 result = ''
291 for category in codelist:
292 if cc[category]:
293 result = result + cc[category]
294 ##print 'result = ' + `result`
295 return result
Guido van Rossum95cd2ef1992-12-08 14:37:55 +0000296
297# automatically generate all characters of catcode other, being the
298# complement set in the ASCII range (128 characters)
299def make_other_codes(cc):
Guido van Rossum5f18d6c1996-09-10 22:34:20 +0000300 otherchars = range(256) # could be made 256, no problem
301 for category in all_but_other_codes:
302 if cc[category]:
303 for c in cc[category]:
304 otherchars[ord(c)] = None
305 result = ''
306 for i in otherchars:
307 if i != None:
308 result = result + chr(i)
309 return result
Guido van Rossum95cd2ef1992-12-08 14:37:55 +0000310
311# catcode dump (which characters have which catcodes).
312def dump_cc(name, cc):
Guido van Rossum5f18d6c1996-09-10 22:34:20 +0000313 ##print '\t' + name
314 ##print '=' * (8+len(name))
315 if len(cc) != 16:
316 raise TypeError, 'cc not good cat class'
Guido van Rossum7a2dba21993-11-05 14:45:11 +0000317## for i in range(16):
318## print pc(i) + '\t' + `cc[i]`
Guido van Rossum5f18d6c1996-09-10 22:34:20 +0000319
Guido van Rossum95cd2ef1992-12-08 14:37:55 +0000320
321# In the beginning,....
322epoch_cc = [None] * 16
323##dump_cc('epoch_cc', epoch_cc)
324
325
326# INITEX
327initex_cc = epoch_cc[:]
328initex_cc[CC_ESCAPE] = '\\'
329initex_cc[CC_ENDLINE], initex_cc[CC_IGNORE], initex_cc[CC_WHITE] = \
330 '\n', '\0', ' '
331initex_cc[CC_LETTER] = string.uppercase + string.lowercase
332initex_cc[CC_COMMENT], initex_cc[CC_INVALID] = '%', '\x7F'
333#initex_cc[CC_OTHER] = make_other_codes(initex_cc) I don't need them, anyway
334##dump_cc('initex_cc', initex_cc)
335
Guido van Rossum5f18d6c1996-09-10 22:34:20 +0000336
Guido van Rossum95cd2ef1992-12-08 14:37:55 +0000337# LPLAIN: LaTeX catcode setting (see lplain.tex)
338lplain_cc = initex_cc[:]
339lplain_cc[CC_LBRACE], lplain_cc[CC_RBRACE] = '{', '}'
340lplain_cc[CC_MATHSHIFT] = '$'
341lplain_cc[CC_ALIGNMENT] = '&'
342lplain_cc[CC_PARAMETER] = '#'
343lplain_cc[CC_SUPERSCRIPT] = '^\x0B' # '^' and C-k
344lplain_cc[CC_SUBSCRIPT] = '_\x01' # '_' and C-a
345lplain_cc[CC_WHITE] = lplain_cc[CC_WHITE] + '\t'
346lplain_cc[CC_ACTIVE] = '~\x0C' # '~' and C-l
347lplain_cc[CC_OTHER] = make_other_codes(lplain_cc)
348##dump_cc('lplain_cc', lplain_cc)
349
Guido van Rossum5f18d6c1996-09-10 22:34:20 +0000350
Guido van Rossum95cd2ef1992-12-08 14:37:55 +0000351# Guido's LaTeX environment catcoded '_' as ``other''
352# my own purpose catlist
353my_cc = lplain_cc[:]
354my_cc[CC_SUBSCRIPT] = my_cc[CC_SUBSCRIPT][1:] # remove '_' here
355my_cc[CC_OTHER] = my_cc[CC_OTHER] + '_' # add it to OTHER list
356dump_cc('my_cc', my_cc)
357
358
359
360# needed for un_re, my equivalent for regexp-quote in Emacs
361re_meaning = '\\[]^$'
362
363def un_re(str):
Guido van Rossum5f18d6c1996-09-10 22:34:20 +0000364 result = ''
365 for i in str:
366 if i in re_meaning:
367 result = result + '\\'
368 result = result + i
369 return result
370
Guido van Rossum95cd2ef1992-12-08 14:37:55 +0000371# NOTE the negate ('^') operator in *some* of the regexps below
372def make_rc_regular(cc):
Guido van Rossum5f18d6c1996-09-10 22:34:20 +0000373 # problems here if '[]' are included!!
374 return regex.compile('[' + code2string(cc, regular_stopcodes) + ']')
Guido van Rossum95cd2ef1992-12-08 14:37:55 +0000375
376def make_rc_cs_scan(cc):
Guido van Rossum5f18d6c1996-09-10 22:34:20 +0000377 return regex.compile('[^' + code2string(cc, csname_scancodes) + ']')
Guido van Rossum95cd2ef1992-12-08 14:37:55 +0000378
379def make_rc_comment(cc):
Guido van Rossum5f18d6c1996-09-10 22:34:20 +0000380 return regex.compile('[' + code2string(cc, comment_stopcodes) + ']')
Guido van Rossum95cd2ef1992-12-08 14:37:55 +0000381
382def make_rc_endwhite(cc):
Guido van Rossum5f18d6c1996-09-10 22:34:20 +0000383 return regex.compile('[^' + code2string(cc, white_scancodes) + ']')
384
Guido van Rossum95cd2ef1992-12-08 14:37:55 +0000385
386
387# regular: normal mode:
388rc_regular = make_rc_regular(my_cc)
389
390# scan: scan a command sequence e.g. `newlength' or `mbox' or `;', `,' or `$'
391rc_cs_scan = make_rc_cs_scan(my_cc)
392rc_comment = make_rc_comment(my_cc)
393rc_endwhite = make_rc_endwhite(my_cc)
394
395
Guido van Rossum36f219d1996-09-11 21:30:40 +0000396# parseit (BUF, PARSEMODE=mode[MODE_REGULAR], START=0, RECURSION-LEVEL=0)
Guido van Rossum95cd2ef1992-12-08 14:37:55 +0000397# RECURSION-LEVEL will is incremented on entry.
398# result contains the list of chunks returned
399# together with this list, the buffer position is returned
400
401# RECURSION-LEVEL will be set to zero *again*, when recursively a
402# {,D}MATH-mode scan has been enetered.
403# This has been done in order to better check for environment-mismatches
404
Guido van Rossum36f219d1996-09-11 21:30:40 +0000405def parseit(buf, parsemode=mode[MODE_REGULAR], start=0, lvl=0):
Guido van Rossum5f18d6c1996-09-10 22:34:20 +0000406 global lineno
Guido van Rossum95cd2ef1992-12-08 14:37:55 +0000407
Guido van Rossum5f18d6c1996-09-10 22:34:20 +0000408 result = []
409 end = len(buf)
Guido van Rossum36f219d1996-09-11 21:30:40 +0000410 if lvl == 0 and parsemode == mode[MODE_REGULAR]:
Guido van Rossum5f18d6c1996-09-10 22:34:20 +0000411 lineno = 1
412 lvl = lvl + 1
Guido van Rossum95cd2ef1992-12-08 14:37:55 +0000413
Guido van Rossum5f18d6c1996-09-10 22:34:20 +0000414 ##print 'parseit(' + epsilon(buf, start) + ', ' + `parsemode` + ', ' + `start` + ', ' + `lvl` + ')'
Guido van Rossum95cd2ef1992-12-08 14:37:55 +0000415
Guido van Rossum5f18d6c1996-09-10 22:34:20 +0000416 #
417 # some of the more regular modes...
418 #
Guido van Rossum95cd2ef1992-12-08 14:37:55 +0000419
Guido van Rossum36f219d1996-09-11 21:30:40 +0000420 if parsemode in (mode[MODE_REGULAR], mode[MODE_DMATH], mode[MODE_MATH]):
Guido van Rossum5f18d6c1996-09-10 22:34:20 +0000421 cstate = []
422 newpos = start
423 curpmode = parsemode
424 while 1:
425 where = newpos
426 #print '\tnew round: ' + epsilon(buf, where)
427 if where == end:
Guido van Rossum36f219d1996-09-11 21:30:40 +0000428 if lvl > 1 or curpmode != mode[MODE_REGULAR]:
Guido van Rossum5f18d6c1996-09-10 22:34:20 +0000429 # not the way we started...
430 raise EOFError, 'premature end of file.' + lle(lvl, buf, where)
431 # the real ending of lvl-1 parse
432 return end, result
Guido van Rossum95cd2ef1992-12-08 14:37:55 +0000433
Guido van Rossum5f18d6c1996-09-10 22:34:20 +0000434 pos = rc_regular.search(buf, where)
Guido van Rossum95cd2ef1992-12-08 14:37:55 +0000435
Guido van Rossum5f18d6c1996-09-10 22:34:20 +0000436 if pos < 0:
437 pos = end
Guido van Rossum95cd2ef1992-12-08 14:37:55 +0000438
Guido van Rossum5f18d6c1996-09-10 22:34:20 +0000439 if pos != where:
440 newpos, c = pos, chunk(PLAIN, where, (where, pos))
441 result.append(c)
442 continue
Guido van Rossum95cd2ef1992-12-08 14:37:55 +0000443
444
Guido van Rossum5f18d6c1996-09-10 22:34:20 +0000445 #
446 # ok, pos == where and pos != end
447 #
448 foundchar = buf[where]
449 if foundchar in my_cc[CC_LBRACE]:
450 # recursive subgroup parse...
451 newpos, data = parseit(buf, curpmode, where+1, lvl)
452 result.append(chunk(GROUP, where, data))
453
454 elif foundchar in my_cc[CC_RBRACE]:
455 if lvl <= 1:
456 raise error, 'ENDGROUP while in base level.' + lle(lvl, buf, where)
Guido van Rossum36f219d1996-09-11 21:30:40 +0000457 if lvl == 1 and mode != mode[MODE_REGULAR]:
Guido van Rossum5f18d6c1996-09-10 22:34:20 +0000458 raise error, 'endgroup while in math mode. +lin() + epsilon(buf, where)'
459 return where + 1, result
460
461 elif foundchar in my_cc[CC_ESCAPE]:
Guido van Rossum95cd2ef1992-12-08 14:37:55 +0000462 #
Guido van Rossum5f18d6c1996-09-10 22:34:20 +0000463 # call the routine that actually deals with
464 # this problem. If do_ret is None, than
465 # return the value of do_ret
Guido van Rossum95cd2ef1992-12-08 14:37:55 +0000466 #
Guido van Rossum5f18d6c1996-09-10 22:34:20 +0000467 # Note that handle_cs might call this routine
468 # recursively again...
469 #
470 do_ret, newpos = handlecs(buf, where,
471 curpmode, lvl, result, end)
472 if do_ret != None:
473 return do_ret
474
475 elif foundchar in my_cc[CC_COMMENT]:
476 newpos, data = parseit(buf,
Guido van Rossum36f219d1996-09-11 21:30:40 +0000477 mode[MODE_COMMENT], where+1, lvl)
Guido van Rossum5f18d6c1996-09-10 22:34:20 +0000478 result.append(chunk(COMMENT, where, data))
479
480 elif foundchar in my_cc[CC_MATHSHIFT]:
481 # note that recursive calls to math-mode
482 # scanning are called with recursion-level 0
483 # again, in order to check for bad mathend
484 #
485 if where + 1 != end and buf[where + 1] in my_cc[CC_MATHSHIFT]:
486 #
487 # double mathshift, e.g. '$$'
488 #
Guido van Rossum36f219d1996-09-11 21:30:40 +0000489 if curpmode == mode[MODE_REGULAR]:
490 newpos, data = parseit(buf, mode[MODE_DMATH],
491 where + 2, 0)
492 result.append(chunk(DMATH, where, data))
493 elif curpmode == mode[MODE_MATH]:
Guido van Rossum5f18d6c1996-09-10 22:34:20 +0000494 raise error, 'wrong math delimiiter' + lin() + epsilon(buf, where)
495 elif lvl != 1:
496 raise error, 'bad mathend.' + lle(lvl, buf, where)
497 else:
498 return where + 2, result
Guido van Rossum95cd2ef1992-12-08 14:37:55 +0000499 else:
Guido van Rossum5f18d6c1996-09-10 22:34:20 +0000500 #
501 # single math shift, e.g. '$'
502 #
Guido van Rossum36f219d1996-09-11 21:30:40 +0000503 if curpmode == mode[MODE_REGULAR]:
504 newpos, data = parseit(buf, mode[MODE_MATH],
505 where + 1, 0)
506 result.append(chunk(MATH, where, data))
507 elif curpmode == mode[MODE_DMATH]:
Guido van Rossum5f18d6c1996-09-10 22:34:20 +0000508 raise error, 'wrong math delimiiter' + lin() + epsilon(buf, where)
509 elif lvl != 1:
510 raise error, 'bad mathend.' + lv(lvl, buf, where)
511 else:
512 return where + 1, result
Guido van Rossum95cd2ef1992-12-08 14:37:55 +0000513
Guido van Rossum5f18d6c1996-09-10 22:34:20 +0000514 elif foundchar in my_cc[CC_IGNORE]:
515 print 'warning: ignored char', `foundchar`
516 newpos = where + 1
Guido van Rossum95cd2ef1992-12-08 14:37:55 +0000517
Guido van Rossum5f18d6c1996-09-10 22:34:20 +0000518 elif foundchar in my_cc[CC_ACTIVE]:
519 result.append(chunk(ACTIVE, where, foundchar))
520 newpos = where + 1
521
522 elif foundchar in my_cc[CC_INVALID]:
523 raise error, 'invalid char ' + `foundchar`
524 newpos = where + 1
525
526 elif foundchar in my_cc[CC_ENDLINE]:
527 #
528 # after an end of line, eat the rest of
529 # whitespace on the beginning of the next line
530 # this is what LaTeX more or less does
531 #
532 # also, try to indicate double newlines (\par)
533 #
Guido van Rossum95cd2ef1992-12-08 14:37:55 +0000534 lineno = lineno + 1
Guido van Rossum5f18d6c1996-09-10 22:34:20 +0000535 savedwhere = where
Guido van Rossum36f219d1996-09-11 21:30:40 +0000536 newpos, dummy = parseit(buf, mode[MODE_GOBBLEWHITE], where + 1, lvl)
Guido van Rossum5f18d6c1996-09-10 22:34:20 +0000537 if newpos != end and buf[newpos] in my_cc[CC_ENDLINE]:
538 result.append(chunk(DENDLINE, savedwhere, foundchar))
539 else:
540 result.append(chunk(ENDLINE, savedwhere, foundchar))
541 else:
542 result.append(chunk(OTHER, where, foundchar))
543 newpos = where + 1
Guido van Rossum95cd2ef1992-12-08 14:37:55 +0000544
Guido van Rossum36f219d1996-09-11 21:30:40 +0000545 elif parsemode == mode[MODE_CS_SCAN]:
Guido van Rossum5f18d6c1996-09-10 22:34:20 +0000546 #
547 # scan for a control sequence token. `\ape', `\nut' or `\%'
548 #
549 if start == end:
550 raise EOFError, 'can\'t find end of csname'
551 pos = rc_cs_scan.search(buf, start)
552 if pos < 0:
553 pos = end
554 if pos == start:
555 # first non-letter right where we started the search
556 # ---> the control sequence name consists of one single
557 # character. Also: don't eat white space...
558 if buf[pos] in my_cc[CC_ENDLINE]:
559 lineno = lineno + 1
560 pos = pos + 1
561 return pos, (start, pos)
Guido van Rossum95cd2ef1992-12-08 14:37:55 +0000562 else:
Guido van Rossum5f18d6c1996-09-10 22:34:20 +0000563 spos = pos
564 if buf[pos] == '\n':
565 lineno = lineno + 1
566 spos = pos + 1
Guido van Rossum36f219d1996-09-11 21:30:40 +0000567 pos2, dummy = parseit(buf, mode[MODE_GOBBLEWHITE], spos, lvl)
Guido van Rossum5f18d6c1996-09-10 22:34:20 +0000568 return pos2, (start, pos)
569
Guido van Rossum36f219d1996-09-11 21:30:40 +0000570 elif parsemode == mode[MODE_GOBBLEWHITE]:
Guido van Rossum5f18d6c1996-09-10 22:34:20 +0000571 if start == end:
572 return start, ''
573 pos = rc_endwhite.search(buf, start)
574 if pos < 0:
575 pos = start
576 return pos, (start, pos)
577
Guido van Rossum36f219d1996-09-11 21:30:40 +0000578 elif parsemode == mode[MODE_COMMENT]:
Guido van Rossum5f18d6c1996-09-10 22:34:20 +0000579 pos = rc_comment.search(buf, start)
580 lineno = lineno + 1
581 if pos < 0:
582 print 'no newline perhaps?'
583 raise EOFError, 'can\'t find end of comment'
584 pos = pos + 1
Guido van Rossum36f219d1996-09-11 21:30:40 +0000585 pos2, dummy = parseit(buf, mode[MODE_GOBBLEWHITE], pos, lvl)
Guido van Rossum5f18d6c1996-09-10 22:34:20 +0000586 return pos2, (start, pos)
587
Guido van Rossum5f18d6c1996-09-10 22:34:20 +0000588 else:
589 raise error, 'Unknown mode (' + `parsemode` + ')'
Guido van Rossum95cd2ef1992-12-08 14:37:55 +0000590
591
592#moreresult = cswitch(buf[x1:x2], buf, newpos, parsemode, lvl)
593
594#boxcommands = 'mbox', 'fbox'
595#defcommands = 'def', 'newcommand'
596
597endverbstr = '\\end{verbatim}'
598
599re_endverb = regex.compile(un_re(endverbstr))
600
601#
602# handlecs: helper function for parseit, for the special thing we might
603# wanna do after certain command control sequences
604# returns: None or return_data, newpos
605#
606# in the latter case, the calling function is instructed to immediately
607# return with the data in return_data
608#
609def handlecs(buf, where, curpmode, lvl, result, end):
Guido van Rossum5f18d6c1996-09-10 22:34:20 +0000610 global lineno
Guido van Rossum95cd2ef1992-12-08 14:37:55 +0000611
Guido van Rossum5f18d6c1996-09-10 22:34:20 +0000612 # get the control sequence name...
Guido van Rossum36f219d1996-09-11 21:30:40 +0000613 newpos, data = parseit(buf, mode[MODE_CS_SCAN], where+1, lvl)
Guido van Rossum5f18d6c1996-09-10 22:34:20 +0000614 saveddata = data
Guido van Rossum36f219d1996-09-11 21:30:40 +0000615 s_buf_data = s(buf, data)
Guido van Rossum95cd2ef1992-12-08 14:37:55 +0000616
Guido van Rossum36f219d1996-09-11 21:30:40 +0000617 if s_buf_data in ('begin', 'end'):
Guido van Rossum5f18d6c1996-09-10 22:34:20 +0000618 # skip the expected '{' and get the LaTeX-envname '}'
Guido van Rossum36f219d1996-09-11 21:30:40 +0000619 newpos, data = parseit(buf, mode[MODE_REGULAR], newpos+1, lvl)
Guido van Rossum5f18d6c1996-09-10 22:34:20 +0000620 if len(data) != 1:
Guido van Rossum36f219d1996-09-11 21:30:40 +0000621 raise error, 'expected 1 chunk of data.' + lle(lvl, buf, where)
Guido van Rossum49604d31996-09-10 22:19:51 +0000622
Guido van Rossum5f18d6c1996-09-10 22:34:20 +0000623 # yucky, we've got an environment
624 envname = s(buf, data[0].data)
Guido van Rossum36f219d1996-09-11 21:30:40 +0000625 s_buf_saveddata = s(buf, saveddata)
Guido van Rossum5f18d6c1996-09-10 22:34:20 +0000626 ##print 'FOUND ' + s(buf, saveddata) + '. Name ' + `envname` + '.' + lv(lvl)
Guido van Rossum36f219d1996-09-11 21:30:40 +0000627 if s_buf_saveddata == 'begin' and envname == 'verbatim':
Guido van Rossum5f18d6c1996-09-10 22:34:20 +0000628 # verbatim deserves special treatment
629 pos = re_endverb.search(buf, newpos)
630 if pos < 0:
Guido van Rossum36f219d1996-09-11 21:30:40 +0000631 raise error, "%s not found.%s" \
632 % (`endverbstr`, lle(lvl, buf, where))
Guido van Rossum5f18d6c1996-09-10 22:34:20 +0000633 result.append(chunk(ENV, where, (envname, [chunk(PLAIN, newpos, (newpos, pos))])))
634 newpos = pos + len(endverbstr)
Guido van Rossum95cd2ef1992-12-08 14:37:55 +0000635
Guido van Rossum36f219d1996-09-11 21:30:40 +0000636 elif s_buf_saveddata == 'begin':
Guido van Rossum5f18d6c1996-09-10 22:34:20 +0000637 # start parsing recursively... If that parse returns
638 # from an '\end{...}', then should the last item of
639 # the returned data be a string containing the ended
640 # environment
641 newpos, data = parseit(buf, curpmode, newpos, lvl)
642 if not data or type(data[-1]) is not StringType:
Guido van Rossum36f219d1996-09-11 21:30:40 +0000643 raise error, "missing 'end'" + lle(lvl, buf, where) \
644 + epsilon(buf, newpos)
Guido van Rossum5f18d6c1996-09-10 22:34:20 +0000645 retenv = data[-1]
646 del data[-1]
647 if retenv != envname:
648 #[`retenv`, `envname`]
Guido van Rossum36f219d1996-09-11 21:30:40 +0000649 raise error, 'environments do not match.%s%s' \
650 % (lle(lvl, buf, where), epsilon(buf, newpos))
Guido van Rossum5f18d6c1996-09-10 22:34:20 +0000651 result.append(chunk(ENV, where, (retenv, data)))
Guido van Rossum95cd2ef1992-12-08 14:37:55 +0000652 else:
Guido van Rossum5f18d6c1996-09-10 22:34:20 +0000653 # 'end'... append the environment name, as just
654 # pointed out, and order parsit to return...
655 result.append(envname)
656 ##print 'POINT of return: ' + epsilon(buf, newpos)
657 # the tuple will be returned by parseit
658 return (newpos, result), newpos
659
660 # end of \begin ... \end handling
661
Guido van Rossum36f219d1996-09-11 21:30:40 +0000662 elif s_buf_data[0:2] == 'if':
Guido van Rossum5f18d6c1996-09-10 22:34:20 +0000663 # another scary monster: the 'if' directive
Guido van Rossum36f219d1996-09-11 21:30:40 +0000664 flag = s_buf_data[2:]
Guido van Rossum5f18d6c1996-09-10 22:34:20 +0000665
666 # recursively call parseit, just like environment above..
667 # the last item of data should contain the if-termination
668 # e.g., 'else' of 'fi'
669 newpos, data = parseit(buf, curpmode, newpos, lvl)
670 if not data or data[-1] not in ('else', 'fi'):
671 raise error, 'wrong if... termination' + \
672 lle(lvl, buf, where) + epsilon(buf, newpos)
673
674 ifterm = data[-1]
675 del data[-1]
676 # 0 means dont_negate flag
677 result.append(chunk(IF, where, (flag, 0, data)))
678 if ifterm == 'else':
679 # do the whole thing again, there is only one way
680 # to end this one, by 'fi'
681 newpos, data = parseit(buf, curpmode, newpos, lvl)
682 if not data or data[-1] not in ('fi', ):
683 raise error, 'wrong if...else... termination' \
Guido van Rossum36f219d1996-09-11 21:30:40 +0000684 + lle(lvl, buf, where) \
685 + epsilon(buf, newpos)
Guido van Rossum5f18d6c1996-09-10 22:34:20 +0000686
687 ifterm = data[-1]
688 del data[-1]
689 result.append(chunk(IF, where, (flag, 1, data)))
690 #done implicitely: return None, newpos
691
Guido van Rossum36f219d1996-09-11 21:30:40 +0000692 elif s_buf_data in ('else', 'fi'):
Guido van Rossum5f18d6c1996-09-10 22:34:20 +0000693 result.append(s(buf, data))
694 # order calling party to return tuple
695 return (newpos, result), newpos
696
697 # end of \if, \else, ... \fi handling
698
699 elif s(buf, saveddata) == 'verb':
700 x2 = saveddata[1]
701 result.append(chunk(CSNAME, where, data))
702 if x2 == end:
703 raise error, 'premature end of command.' + lle(lvl, buf, where)
704 delimchar = buf[x2]
705 ##print 'VERB: delimchar ' + `delimchar`
706 pos = regex.compile(un_re(delimchar)).search(buf, x2 + 1)
707 if pos < 0:
708 raise error, 'end of \'verb\' argument (' + \
Guido van Rossum36f219d1996-09-11 21:30:40 +0000709 `delimchar` + ') not found.' + \
710 lle(lvl, buf, where)
Guido van Rossum5f18d6c1996-09-10 22:34:20 +0000711 result.append(chunk(GROUP, x2, [chunk(PLAIN, x2+1, (x2+1, pos))]))
712 newpos = pos + 1
713 else:
714 result.append(chunk(CSNAME, where, data))
715 return None, newpos
Guido van Rossum95cd2ef1992-12-08 14:37:55 +0000716
717# this is just a function to get the string value if the possible data-tuple
718def s(buf, data):
Guido van Rossum5f18d6c1996-09-10 22:34:20 +0000719 if type(data) is StringType:
720 return data
721 if len(data) != 2 or not (type(data[0]) is type(data[1]) is IntType):
722 raise TypeError, 'expected tuple of 2 integers'
723 x1, x2 = data
724 return buf[x1:x2]
Guido van Rossum49604d31996-09-10 22:19:51 +0000725
Guido van Rossum95cd2ef1992-12-08 14:37:55 +0000726
727##length, data1, i = getnextarg(length, buf, pp, i + 1)
728
729# make a deep-copy of some chunks
730def crcopy(r):
Guido van Rossum5f18d6c1996-09-10 22:34:20 +0000731 return map(chunkcopy, r)
Guido van Rossum49604d31996-09-10 22:19:51 +0000732
Guido van Rossum95cd2ef1992-12-08 14:37:55 +0000733
734# copy a chunk, would better be a method of class Chunk...
735def chunkcopy(ch):
Guido van Rossum36f219d1996-09-11 21:30:40 +0000736 if ch.chtype == chunk_type[GROUP]:
Guido van Rossum5f18d6c1996-09-10 22:34:20 +0000737 return chunk(GROUP, ch.where, map(chunkcopy, ch.data))
738 else:
739 return chunk(ch.chtype, ch.where, ch.data)
Guido van Rossum95cd2ef1992-12-08 14:37:55 +0000740
741
742# get next argument for TeX-macro, flatten a group (insert between)
743# or return Command Sequence token, or give back one character
744def getnextarg(length, buf, pp, item):
745
Guido van Rossum5f18d6c1996-09-10 22:34:20 +0000746 ##wobj = Wobj()
747 ##dumpit(buf, wobj.write, pp[item:min(length, item + 5)])
748 ##print 'GETNEXTARG, (len, item) =', `length, item` + ' ---> ' + wobj.data + ' <---'
Guido van Rossum95cd2ef1992-12-08 14:37:55 +0000749
Guido van Rossum36f219d1996-09-11 21:30:40 +0000750 while item < length and pp[item].chtype == chunk_type[ENDLINE]:
Guido van Rossum5f18d6c1996-09-10 22:34:20 +0000751 del pp[item]
752 length = length - 1
753 if item >= length:
754 raise error, 'no next arg.' + epsilon(buf, pp[-1].where)
Guido van Rossum36f219d1996-09-11 21:30:40 +0000755 if pp[item].chtype == chunk_type[GROUP]:
Guido van Rossum5f18d6c1996-09-10 22:34:20 +0000756 newpp = pp[item].data
757 del pp[item]
758 length = length - 1
759 changeit(buf, newpp)
760 length = length + len(newpp)
761 pp[item:item] = newpp
762 item = item + len(newpp)
763 if len(newpp) < 10:
764 wobj = Wobj()
765 dumpit(buf, wobj.write, newpp)
766 ##print 'GETNEXTARG: inserted ' + `wobj.data`
767 return length, item
Guido van Rossum36f219d1996-09-11 21:30:40 +0000768 elif pp[item].chtype == chunk_type[PLAIN]:
Guido van Rossum5f18d6c1996-09-10 22:34:20 +0000769 #grab one char
770 print 'WARNING: grabbing one char'
771 if len(s(buf, pp[item].data)) > 1:
772 pp.insert(item, chunk(PLAIN, pp[item].where, s(buf, pp[item].data)[:1]))
773 item, length = item+1, length+1
774 pp[item].data = s(buf, pp[item].data)[1:]
Guido van Rossum95cd2ef1992-12-08 14:37:55 +0000775 else:
Guido van Rossum5f18d6c1996-09-10 22:34:20 +0000776 item = item+1
777 return length, item
778 else:
779 ch = pp[item]
780 try:
781 str = `s(buf, ch.data)`
782 except TypeError:
783 str = `ch.data`
784 if len(str) > 400:
785 str = str[:400] + '...'
786 print 'GETNEXTARG:', ch.chtype, 'not handled, data ' + str
787 return length, item
Guido van Rossum95cd2ef1992-12-08 14:37:55 +0000788
789
790# this one is needed to find the end of LaTeX's optional argument, like
791# item[...]
792re_endopt = regex.compile(']')
793
794# get a LaTeX-optional argument, you know, the square braces '[' and ']'
795def getoptarg(length, buf, pp, item):
796
Guido van Rossum5f18d6c1996-09-10 22:34:20 +0000797 wobj = Wobj()
798 dumpit(buf, wobj.write, pp[item:min(length, item + 5)])
799 ##print 'GETOPTARG, (len, item) =', `length, item` + ' ---> ' + wobj.data + ' <---'
Guido van Rossum95cd2ef1992-12-08 14:37:55 +0000800
Guido van Rossum5f18d6c1996-09-10 22:34:20 +0000801 if item >= length or \
Guido van Rossum36f219d1996-09-11 21:30:40 +0000802 pp[item].chtype != chunk_type[PLAIN] or \
Guido van Rossum5f18d6c1996-09-10 22:34:20 +0000803 s(buf, pp[item].data)[0] != '[':
804 return length, item
805
806 pp[item].data = s(buf, pp[item].data)[1:]
807 if len(pp[item].data) == 0:
808 del pp[item]
809 length = length-1
810
811 while 1:
812 if item == length:
813 raise error, 'No end of optional arg found'
Guido van Rossum36f219d1996-09-11 21:30:40 +0000814 if pp[item].chtype == chunk_type[PLAIN]:
Guido van Rossum5f18d6c1996-09-10 22:34:20 +0000815 text = s(buf, pp[item].data)
816 pos = re_endopt.search(text)
817 if pos >= 0:
818 pp[item].data = text[:pos]
819 if pos == 0:
820 del pp[item]
821 length = length-1
822 else:
823 item=item+1
824 text = text[pos+1:]
825
826 while text and text[0] in ' \t':
827 text = text[1:]
828
829 if text:
830 pp.insert(item, chunk(PLAIN, 0, text))
831 length = length + 1
Guido van Rossum95cd2ef1992-12-08 14:37:55 +0000832 return length, item
833
Guido van Rossum5f18d6c1996-09-10 22:34:20 +0000834 item = item+1
Guido van Rossum95cd2ef1992-12-08 14:37:55 +0000835
836
837# Wobj just add write-requests to the ``data'' attribute
838class Wobj:
Guido van Rossum5f18d6c1996-09-10 22:34:20 +0000839 data = ''
Guido van Rossum49604d31996-09-10 22:19:51 +0000840
Guido van Rossum5f18d6c1996-09-10 22:34:20 +0000841 def write(self, data):
842 self.data = self.data + data
Guido van Rossumb819bdf1995-03-15 11:26:26 +0000843
Guido van Rossum95cd2ef1992-12-08 14:37:55 +0000844# ignore these commands
Fred Drake74a11e51998-02-26 05:52:37 +0000845ignoredcommands = ('hline', 'small', '/', 'tableofcontents', 'Large')
Guido van Rossum95cd2ef1992-12-08 14:37:55 +0000846# map commands like these to themselves as plaintext
Fred Drake74a11e51998-02-26 05:52:37 +0000847wordsselves = ('UNIX', 'ABC', 'C', 'ASCII', 'EOF', 'LaTeX', 'POSIX', 'TeX',
848 'SliTeX')
Guido van Rossum95cd2ef1992-12-08 14:37:55 +0000849# \{ --> {, \} --> }, etc
Guido van Rossum36f219d1996-09-11 21:30:40 +0000850themselves = ('{', '}', ',', '.', '@', ' ', '\n') + wordsselves
Guido van Rossum95cd2ef1992-12-08 14:37:55 +0000851# these ones also themselves (see argargs macro in myformat.sty)
852inargsselves = (',', '[', ']', '(', ')')
853# this is how *I* would show the difference between emph and strong
854# code 1 means: fold to uppercase
Guido van Rossum5f18d6c1996-09-10 22:34:20 +0000855markcmds = {'code': ('', ''), 'var': 1, 'emph': ('_', '_'),
Fred Drakee8b46131998-02-17 05:54:46 +0000856 'strong': ('*', '*')}
Guido van Rossum95cd2ef1992-12-08 14:37:55 +0000857
858# recognise patter {\FONTCHANGE-CMD TEXT} to \MAPPED-FC-CMD{TEXT}
859fontchanges = {'rm': 'r', 'it': 'i', 'em': 'emph', 'bf': 'b', 'tt': 't'}
860
Guido van Rossum95cd2ef1992-12-08 14:37:55 +0000861
862# try to remove macros and return flat text
863def flattext(buf, pp):
Guido van Rossum5f18d6c1996-09-10 22:34:20 +0000864 pp = crcopy(pp)
865 ##print '---> FLATTEXT ' + `pp`
866 wobj = Wobj()
Guido van Rossum95cd2ef1992-12-08 14:37:55 +0000867
Guido van Rossum5f18d6c1996-09-10 22:34:20 +0000868 i, length = 0, len(pp)
869 while 1:
870 if len(pp) != length:
871 raise 'FATAL', 'inconsistent length'
872 if i >= length:
873 break
874 ch = pp[i]
875 i = i+1
Guido van Rossum36f219d1996-09-11 21:30:40 +0000876 if ch.chtype == chunk_type[PLAIN]:
Guido van Rossum5f18d6c1996-09-10 22:34:20 +0000877 pass
Guido van Rossum36f219d1996-09-11 21:30:40 +0000878 elif ch.chtype == chunk_type[CSNAME]:
879 s_buf_data = s(buf, ch.data)
Fred Drake74a11e51998-02-26 05:52:37 +0000880 if convertible_csname(s_buf_data):
881 ch.chtype, ch.data, nix = conversion(s_buf_data)
882 if hist.inargs and s_buf_data in inargsselves:
Guido van Rossum36f219d1996-09-11 21:30:40 +0000883 ch.chtype = chunk_type[PLAIN]
Guido van Rossum36f219d1996-09-11 21:30:40 +0000884 elif len(s_buf_data) == 1 \
885 and s_buf_data in onlylatexspecial:
886 ch.chtype = chunk_type[PLAIN]
Guido van Rossum5f18d6c1996-09-10 22:34:20 +0000887 # if it is followed by an empty group,
888 # remove that group, it was needed for
889 # a true space
890 if i < length \
Guido van Rossum36f219d1996-09-11 21:30:40 +0000891 and pp[i].chtype==chunk_type[GROUP] \
Guido van Rossum5f18d6c1996-09-10 22:34:20 +0000892 and len(pp[i].data) == 0:
893 del pp[i]
894 length = length-1
895
Guido van Rossum36f219d1996-09-11 21:30:40 +0000896 elif s_buf_data in markcmds.keys():
Guido van Rossum5f18d6c1996-09-10 22:34:20 +0000897 length, newi = getnextarg(length, buf, pp, i)
898 str = flattext(buf, pp[i:newi])
899 del pp[i:newi]
900 length = length - (newi - i)
Guido van Rossum36f219d1996-09-11 21:30:40 +0000901 ch.chtype = chunk_type[PLAIN]
902 markcmd = s_buf_data
Guido van Rossum5f18d6c1996-09-10 22:34:20 +0000903 x = markcmds[markcmd]
904 if type(x) == TupleType:
905 pre, after = x
906 str = pre+str+after
907 elif x == 1:
908 str = string.upper(str)
909 else:
910 raise 'FATAL', 'corrupt markcmds'
911 ch.data = str
912 else:
Guido van Rossum36f219d1996-09-11 21:30:40 +0000913 if s_buf_data not in ignoredcommands:
914 print 'WARNING: deleting command ' + s_buf_data
Guido van Rossum5f18d6c1996-09-10 22:34:20 +0000915 print 'PP' + `pp[i-1]`
916 del pp[i-1]
917 i, length = i-1, length-1
Guido van Rossum36f219d1996-09-11 21:30:40 +0000918 elif ch.chtype == chunk_type[GROUP]:
Guido van Rossum5f18d6c1996-09-10 22:34:20 +0000919 length, newi = getnextarg(length, buf, pp, i-1)
920 i = i-1
Guido van Rossum95cd2ef1992-12-08 14:37:55 +0000921## str = flattext(buf, crcopy(pp[i-1:newi]))
922## del pp[i:newi]
923## length = length - (newi - i)
Guido van Rossum36f219d1996-09-11 21:30:40 +0000924## ch.chtype = chunk_type[PLAIN]
Guido van Rossum95cd2ef1992-12-08 14:37:55 +0000925## ch.data = str
Guido van Rossum5f18d6c1996-09-10 22:34:20 +0000926 else:
927 pass
928
929 dumpit(buf, wobj.write, pp)
930 ##print 'FLATTEXT: RETURNING ' + `wobj.data`
931 return wobj.data
Guido van Rossum95cd2ef1992-12-08 14:37:55 +0000932
933# try to generate node names (a bit shorter than the chapter title)
934# note that the \nodename command (see elsewhere) overules these efforts
935def invent_node_names(text):
Guido van Rossum5f18d6c1996-09-10 22:34:20 +0000936 words = string.split(text)
Guido van Rossum95cd2ef1992-12-08 14:37:55 +0000937
Guido van Rossum5f18d6c1996-09-10 22:34:20 +0000938 ##print 'WORDS ' + `words`
Guido van Rossum95cd2ef1992-12-08 14:37:55 +0000939
Guido van Rossum5f18d6c1996-09-10 22:34:20 +0000940 if len(words) == 2 \
Guido van Rossum36f219d1996-09-11 21:30:40 +0000941 and string.lower(words[0]) == 'built-in' \
942 and string.lower(words[1]) not in ('modules', 'functions'):
Guido van Rossum5f18d6c1996-09-10 22:34:20 +0000943 return words[1]
944 if len(words) == 3 and string.lower(words[1]) == 'module':
945 return words[2]
946 if len(words) == 3 and string.lower(words[1]) == 'object':
947 return string.join(words[0:2])
Guido van Rossum36f219d1996-09-11 21:30:40 +0000948 if len(words) > 4 \
949 and (string.lower(string.join(words[-4:])) \
950 == 'methods and data attributes'):
Guido van Rossum5f18d6c1996-09-10 22:34:20 +0000951 return string.join(words[:2])
952 return text
953
Guido van Rossum95cd2ef1992-12-08 14:37:55 +0000954re_commas_etc = regex.compile('[,`\'@{}]')
955
956re_whitespace = regex.compile('[ \t]*')
957
958
959##nodenamecmd = next_command_p(length, buf, pp, newi, 'nodename')
960
961# look if the next non-white stuff is also a command, resulting in skipping
962# double endlines (DENDLINE) too, and thus omitting \par's
963# Sometimes this is too much, maybe consider DENDLINE's as stop
964def next_command_p(length, buf, pp, i, cmdname):
965
Guido van Rossum5f18d6c1996-09-10 22:34:20 +0000966 while 1:
967 if i >= len(pp):
968 break
969 ch = pp[i]
970 i = i+1
Guido van Rossum36f219d1996-09-11 21:30:40 +0000971 if ch.chtype == chunk_type[ENDLINE]:
Guido van Rossum5f18d6c1996-09-10 22:34:20 +0000972 continue
Guido van Rossum36f219d1996-09-11 21:30:40 +0000973 if ch.chtype == chunk_type[DENDLINE]:
Guido van Rossum5f18d6c1996-09-10 22:34:20 +0000974 continue
Guido van Rossum36f219d1996-09-11 21:30:40 +0000975 if ch.chtype == chunk_type[PLAIN]:
Guido van Rossum5f18d6c1996-09-10 22:34:20 +0000976 if re_whitespace.search(s(buf, ch.data)) == 0 and \
977 re_whitespace.match(s(buf, ch.data)) == len(s(buf, ch.data)):
978 continue
979 return -1
Guido van Rossum36f219d1996-09-11 21:30:40 +0000980 if ch.chtype == chunk_type[CSNAME]:
Guido van Rossum5f18d6c1996-09-10 22:34:20 +0000981 if s(buf, ch.data) == cmdname:
982 return i # _after_ the command
983 return -1
984 return -1
985
986
Guido van Rossum95cd2ef1992-12-08 14:37:55 +0000987# things that are special to LaTeX, but not to texi..
988onlylatexspecial = '_~^$#&%'
989
Guido van Rossum23301a91993-05-24 14:19:37 +0000990class Struct: pass
Guido van Rossum95cd2ef1992-12-08 14:37:55 +0000991
992hist = Struct()
993out = Struct()
994
995def startchange():
Guido van Rossum5f18d6c1996-09-10 22:34:20 +0000996 global hist, out
Guido van Rossum95cd2ef1992-12-08 14:37:55 +0000997
Fred Drake74a11e51998-02-26 05:52:37 +0000998 hist.chaptertype = "chapter"
Guido van Rossum5f18d6c1996-09-10 22:34:20 +0000999 hist.inenv = []
1000 hist.nodenames = []
1001 hist.cindex = []
1002 hist.inargs = 0
1003 hist.enumeratenesting, hist.itemizenesting = 0, 0
Fred Drake4f6d6e41998-04-17 15:28:09 +00001004 hist.this_module = None
Guido van Rossum95cd2ef1992-12-08 14:37:55 +00001005
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00001006 out.doublenodes = []
1007 out.doublecindeces = []
1008
Guido van Rossum95cd2ef1992-12-08 14:37:55 +00001009
1010spacech = [chunk(PLAIN, 0, ' ')]
1011commach = [chunk(PLAIN, 0, ', ')]
1012cindexch = [chunk(CSLINE, 0, 'cindex')]
1013
1014# the standard variation in symbols for itemize
1015itemizesymbols = ['bullet', 'minus', 'dots']
1016
1017# same for enumerate
1018enumeratesymbols = ['1', 'A', 'a']
1019
Fred Drake74a11e51998-02-26 05:52:37 +00001020# Map of things that convert one-to-one. Each entry is a 3-tuple:
1021#
1022# new_chtype, new_data, nix_trailing_empty_group
1023#
Fred Drake9c7c6be1998-02-19 21:40:22 +00001024d = {}
Fred Drake74a11e51998-02-26 05:52:37 +00001025# add stuff that converts from one name to another:
Fred Drake9c7c6be1998-02-19 21:40:22 +00001026for name in ('url', 'module', 'function', 'cfunction',
1027 'keyword', 'method', 'exception', 'constant',
1028 'email', 'class', 'member', 'cdata', 'ctype',
Fred Drake4f6d6e41998-04-17 15:28:09 +00001029 'member', 'sectcode', 'verb',
1030 'cfunction', 'cdata', 'ctype',
1031 ):
Fred Drake74a11e51998-02-26 05:52:37 +00001032 d[name] = chunk_type[CSNAME], 'code', 0
1033for name in ('emph', 'var', 'strong', 'code', 'kbd', 'key',
1034 'dfn', 'samp', 'file', 'r', 'i', 't'):
1035 d[name] = chunk_type[CSNAME], name, 0
Fred Drake4f6d6e41998-04-17 15:28:09 +00001036d['character'] = chunk_type[CSNAME], 'samp', 0
1037d['url'] = chunk_type[CSNAME], 'code', 0
1038d['email'] = chunk_type[CSNAME], 'code', 0
1039d['mimetype'] = chunk_type[CSNAME], 'code', 0
1040d['newsgroup'] = chunk_type[CSNAME], 'code', 0
Fred Drake74a11e51998-02-26 05:52:37 +00001041d['program'] = chunk_type[CSNAME], 'strong', 0
1042d['\\'] = chunk_type[CSNAME], '*', 0
1043# add stuff that converts to text:
1044for name in themselves:
1045 d[name] = chunk_type[PLAIN], name, 0
1046for name in wordsselves:
1047 d[name] = chunk_type[PLAIN], name, 1
1048for name in ',[]()':
1049 d[name] = chunk_type[PLAIN], name, 0
1050# a lot of these are LaTeX2e additions
1051for name, value in [('quotedblbase', ',,'), ('quotesinglbase', ','),
1052 ('textquotedbl', '"'), ('LaTeXe', 'LaTeX2e'),
1053 ('e', '\\'), ('textquotedblleft', "``"),
1054 ('textquotedblright', "''"), ('textquoteleft', "`"),
1055 ('textquoteright', "'"), ('textbackslash', '\\'),
1056 ('textbar', '|'), ('textless', '<'),
1057 ('textgreater', '>'), ('textasciicircum', '^'),
1058 ('Cpp', 'C++'), ('copyright', '')]:
1059 d[name] = chunk_type[PLAIN], value, 1
Fred Drake9c7c6be1998-02-19 21:40:22 +00001060convertible_csname = d.has_key
1061conversion = d.get
Fred Drake74a11e51998-02-26 05:52:37 +00001062del d, name, value
Fred Drake9c7c6be1998-02-19 21:40:22 +00001063
Guido van Rossum95cd2ef1992-12-08 14:37:55 +00001064##
1065## \begin{ {func,data,exc}desc }{name}...
1066## the resulting texi-code is dependent on the contents of indexsubitem
1067##
1068
1069# indexsubitem: `['XXX', 'function']
1070# funcdesc:
1071# deffn {`idxsi`} NAME (FUNCARGS)
1072
1073# indexsubitem: `['XXX', 'method']`
1074# funcdesc:
1075# defmethod {`idxsi[0]`} NAME (FUNCARGS)
1076
1077# indexsubitem: `['in', 'module', 'MODNAME']'
1078# datadesc:
1079# defcv data {`idxsi[1:]`} NAME
1080# excdesc:
1081# defcv exception {`idxsi[1:]`} NAME
1082# funcdesc:
1083# deffn {function of `idxsi[1:]`} NAME (FUNCARGS)
1084
1085# indexsubitem: `['OBJECT', 'attribute']'
1086# datadesc
1087# defcv attribute {`OBJECT`} NAME
1088
1089
1090## this routine will be called on \begin{funcdesc}{NAME}{ARGS}
1091## or \funcline{NAME}{ARGS}
1092##
Fred Drakee8b46131998-02-17 05:54:46 +00001093def do_funcdesc(length, buf, pp, i, index=1):
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00001094 startpoint = i-1
1095 ch = pp[startpoint]
1096 wh = ch.where
1097 length, newi = getnextarg(length, buf, pp, i)
1098 funcname = chunk(GROUP, wh, pp[i:newi])
1099 del pp[i:newi]
1100 length = length - (newi-i)
1101 save = hist.inargs
1102 hist.inargs = 1
1103 length, newi = getnextarg(length, buf, pp, i)
1104 hist.inargs = save
1105 del save
1106 the_args = [chunk(PLAIN, wh, '()'[0])] + pp[i:newi] + \
Fred Drake7edd8d31996-10-09 16:11:26 +00001107 [chunk(PLAIN, wh, '()'[1])]
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00001108 del pp[i:newi]
1109 length = length - (newi-i)
Guido van Rossum95cd2ef1992-12-08 14:37:55 +00001110
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00001111 idxsi = hist.indexsubitem # words
Fred Drake4f6d6e41998-04-17 15:28:09 +00001112 command = 'deffn'
1113 if hist.this_module:
1114 cat_class = 'function of ' + hist.this_module
1115 else:
1116 cat_class = 'built-in function'
Guido van Rossum36f219d1996-09-11 21:30:40 +00001117 ch.chtype = chunk_type[CSLINE]
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00001118 ch.data = command
1119
1120 cslinearg = [chunk(GROUP, wh, [chunk(PLAIN, wh, cat_class)])]
1121 cslinearg.append(chunk(PLAIN, wh, ' '))
1122 cslinearg.append(funcname)
1123 cslinearg.append(chunk(PLAIN, wh, ' '))
1124 l = len(cslinearg)
1125 cslinearg[l:l] = the_args
1126
1127 pp.insert(i, chunk(GROUP, wh, cslinearg))
1128 i, length = i+1, length+1
1129 hist.command = command
1130 return length, i
1131
Guido van Rossum95cd2ef1992-12-08 14:37:55 +00001132
1133## this routine will be called on \begin{excdesc}{NAME}
1134## or \excline{NAME}
1135##
1136def do_excdesc(length, buf, pp, i):
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00001137 startpoint = i-1
1138 ch = pp[startpoint]
1139 wh = ch.where
1140 length, newi = getnextarg(length, buf, pp, i)
1141 excname = chunk(GROUP, wh, pp[i:newi])
1142 del pp[i:newi]
1143 length = length - (newi-i)
Guido van Rossum95cd2ef1992-12-08 14:37:55 +00001144
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00001145 idxsi = hist.indexsubitem # words
1146 command = ''
1147 cat_class = ''
1148 class_class = ''
Fred Drake4f6d6e41998-04-17 15:28:09 +00001149 if idxsi == ['built-in', 'exception', 'base', 'class']:
Fred Drakee8b46131998-02-17 05:54:46 +00001150 command = 'defvr'
1151 cat_class = 'exception base class'
Fred Drakea4541af1997-12-29 17:19:22 +00001152 else:
Fred Drake4f6d6e41998-04-17 15:28:09 +00001153 command = 'defcv'
1154 cat_class = 'exception'
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00001155
Guido van Rossum36f219d1996-09-11 21:30:40 +00001156 ch.chtype = chunk_type[CSLINE]
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00001157 ch.data = command
1158
1159 cslinearg = [chunk(GROUP, wh, [chunk(PLAIN, wh, cat_class)])]
1160 cslinearg.append(chunk(PLAIN, wh, ' '))
1161 if class_class:
1162 cslinearg.append(chunk(GROUP, wh, [chunk(PLAIN, wh, class_class)]))
Guido van Rossum95cd2ef1992-12-08 14:37:55 +00001163 cslinearg.append(chunk(PLAIN, wh, ' '))
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00001164 cslinearg.append(excname)
Guido van Rossum95cd2ef1992-12-08 14:37:55 +00001165
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00001166 pp.insert(i, chunk(GROUP, wh, cslinearg))
1167 i, length = i+1, length+1
1168 hist.command = command
1169 return length, i
Guido van Rossum95cd2ef1992-12-08 14:37:55 +00001170
1171## same for datadesc or dataline...
Fred Drakee8b46131998-02-17 05:54:46 +00001172def do_datadesc(length, buf, pp, i, index=1):
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00001173 startpoint = i-1
1174 ch = pp[startpoint]
1175 wh = ch.where
1176 length, newi = getnextarg(length, buf, pp, i)
1177 dataname = chunk(GROUP, wh, pp[i:newi])
1178 del pp[i:newi]
1179 length = length - (newi-i)
Guido van Rossum95cd2ef1992-12-08 14:37:55 +00001180
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00001181 idxsi = hist.indexsubitem # words
Fred Drakee8b46131998-02-17 05:54:46 +00001182 command = 'defcv'
1183 cat_class = 'data'
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00001184 class_class = ''
1185 if idxsi[-1] in ('attribute', 'option'):
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00001186 cat_class = idxsi[-1]
1187 class_class = string.join(idxsi[:-1])
1188 elif len(idxsi) == 3 and idxsi[:2] == ['in', 'module']:
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00001189 class_class = string.join(idxsi[1:])
1190 elif len(idxsi) == 4 and idxsi[:3] == ['data', 'in', 'module']:
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00001191 class_class = string.join(idxsi[2:])
Fred Drake11b6d241996-10-10 20:09:56 +00001192 else:
Fred Drake11b6d241996-10-10 20:09:56 +00001193 class_class = string.join(idxsi)
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00001194
Guido van Rossum36f219d1996-09-11 21:30:40 +00001195 ch.chtype = chunk_type[CSLINE]
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00001196 ch.data = command
1197
1198 cslinearg = [chunk(GROUP, wh, [chunk(PLAIN, wh, cat_class)])]
1199 cslinearg.append(chunk(PLAIN, wh, ' '))
1200 if class_class:
1201 cslinearg.append(chunk(GROUP, wh, [chunk(PLAIN, wh, class_class)]))
Guido van Rossum95cd2ef1992-12-08 14:37:55 +00001202 cslinearg.append(chunk(PLAIN, wh, ' '))
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00001203 cslinearg.append(dataname)
Guido van Rossum95cd2ef1992-12-08 14:37:55 +00001204
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00001205 pp.insert(i, chunk(GROUP, wh, cslinearg))
1206 i, length = i+1, length+1
1207 hist.command = command
1208 return length, i
1209
Guido van Rossum95cd2ef1992-12-08 14:37:55 +00001210
Fred Drakea4541af1997-12-29 17:19:22 +00001211def do_opcodedesc(length, buf, pp, i):
1212 startpoint = i-1
1213 ch = pp[startpoint]
1214 wh = ch.where
1215 length, newi = getnextarg(length, buf, pp, i)
1216 dataname = chunk(GROUP, wh, pp[i:newi])
1217 del pp[i:newi]
1218 length = length - (newi-i)
1219
Fred Drake43c93501997-12-29 21:40:35 +00001220 ch.chtype = CSLINE
1221 ch.data = "deffn"
Fred Drakea4541af1997-12-29 17:19:22 +00001222
Fred Drakee8b46131998-02-17 05:54:46 +00001223 cslinearg = [chunk(PLAIN, wh, 'byte\ code\ instruction'),
Fred Drakea4541af1997-12-29 17:19:22 +00001224 chunk(GROUP, wh, [chunk(PLAIN, wh, "byte code instruction")]),
1225 chunk(PLAIN, wh, ' '),
1226 dataname,
Fred Drake43c93501997-12-29 21:40:35 +00001227 chunk(PLAIN, wh, ' '),
1228 pp[i],
Fred Drakea4541af1997-12-29 17:19:22 +00001229 ]
1230
Fred Drake43c93501997-12-29 21:40:35 +00001231 pp[i] = chunk(GROUP, wh, cslinearg)
Fred Drakea4541af1997-12-29 17:19:22 +00001232 hist.command = ch.data
1233 return length, i
1234
1235
Fred Drake4f6d6e41998-04-17 15:28:09 +00001236def add_module_index(pp, length, i, buf, ch, extra, ref=1):
1237 ch.chtype = chunk_type[CSLINE]
1238 ch.data = 'pindex'
1239 length, newi = getnextarg(length, buf, pp, i)
1240 ingroupch = pp[i:newi]
1241 del pp[i:newi]
1242 length = length - (newi-i)
1243 if not ref:
1244 if len(ingroupch) == 1:
1245 hist.this_module = s(buf, ch.data)
1246 else:
1247 hist.this_module = None
1248 print 'add_module_index() error ==>', ingroupch
1249
1250 if extra:
1251 ingroupch.append(chunk(PLAIN, ch.where, ' '))
1252 ingroupch.append(chunk(CSNAME, ch.where, 'r'))
1253 ingroupch.append(chunk(GROUP, ch.where, [
1254 chunk(PLAIN, ch.where, extra)]))
1255
1256 pp.insert(i, chunk(GROUP, ch.where, ingroupch))
1257 return length+1, i+1
1258
1259
1260def yank_indexsubitem(pp, length, i, buf, ch, cmdname):
1261 stuff = pp[i].data
1262 if len(stuff) != 1:
1263 raise error, "first parameter to \\%s too long" % cmdname
1264 if pp[i].chtype != chunk_type[GROUP]:
1265 raise error, "bad chunk type following \\%s" \
1266 "\nexpected GROUP, got %s" + (cmdname, str(ch.chtype))
1267 text = s(buf, stuff[0].data)
1268 if text[:1] != '(' or text[-1:] != ')':
1269 raise error, \
1270 'expected indexsubitem enclosed in parenteses'
1271 hist.indexsubitem = string.split(text[1:-1])
1272 del pp[i-1:i+1]
1273 return length - 2, i - 1
1274
1275
Guido van Rossum95cd2ef1992-12-08 14:37:55 +00001276# regular indices: those that are not set in tt font by default....
1277regindices = ('cindex', )
1278
1279# remove illegal characters from node names
1280def rm_commas_etc(text):
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00001281 result = ''
1282 changed = 0
1283 while 1:
1284 pos = re_commas_etc.search(text)
1285 if pos >= 0:
1286 changed = 1
1287 result = result + text[:pos]
1288 text = text[pos+1:]
1289 else:
1290 result = result + text
1291 break
1292 if changed:
Fred Drake43c93501997-12-29 21:40:35 +00001293 print 'Warning: nodename changed to ' + `result`
Guido van Rossum95cd2ef1992-12-08 14:37:55 +00001294
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00001295 return result
1296
Guido van Rossum95cd2ef1992-12-08 14:37:55 +00001297# boolean flags
1298flags = {'texi': 1}
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00001299
Guido van Rossum95cd2ef1992-12-08 14:37:55 +00001300
Fred Drake43c93501997-12-29 21:40:35 +00001301# map of \label{} to node names
1302label_nodes = {}
1303
1304
Guido van Rossum95cd2ef1992-12-08 14:37:55 +00001305##
1306## changeit: the actual routine, that changes the contents of the parsed
1307## chunks
1308##
1309
1310def changeit(buf, pp):
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00001311 global onlylatexspecial, hist, out
Guido van Rossum95cd2ef1992-12-08 14:37:55 +00001312
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00001313 i, length = 0, len(pp)
1314 while 1:
1315 # sanity check: length should always equal len(pp)
1316 if len(pp) != length:
Fred Drake74a11e51998-02-26 05:52:37 +00001317 print i, pp[i]
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00001318 raise 'FATAL', 'inconsistent length. thought ' + `length` + ', but should really be ' + `len(pp)`
1319 if i >= length:
1320 break
1321 ch = pp[i]
1322 i = i + 1
Guido van Rossum95cd2ef1992-12-08 14:37:55 +00001323
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00001324 if type(ch) is StringType:
1325 #normally, only chunks are present in pp,
1326 # but in some cases, some extra info
1327 # has been inserted, e.g., the \end{...} clauses
1328 raise 'FATAL', 'got string, probably too many ' + `end`
Guido van Rossum95cd2ef1992-12-08 14:37:55 +00001329
Guido van Rossum36f219d1996-09-11 21:30:40 +00001330 if ch.chtype == chunk_type[GROUP]:
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00001331 # check for {\em ...} constructs
Fred Drakee8b46131998-02-17 05:54:46 +00001332 data = ch.data
1333 if data and \
1334 data[0].chtype == chunk_type[CSNAME] and \
1335 fontchanges.has_key(s(buf, data[0].data)):
1336 k = s(buf, data[0].data)
1337 del data[0]
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00001338 pp.insert(i-1, chunk(CSNAME, ch.where, fontchanges[k]))
1339 length, i = length+1, i+1
Guido van Rossum95cd2ef1992-12-08 14:37:55 +00001340
Fred Drakee8b46131998-02-17 05:54:46 +00001341 elif data:
1342 if len(data) \
1343 and data[0].chtype == chunk_type[GROUP] \
1344 and len(data[0].data) \
1345 and data[0].data[0].chtype == chunk_type[CSNAME] \
1346 and s(buf, data[0].data[0].data) == 'e':
1347 data[0] = data[0].data[0]
1348 print "invoking \\e magic group transform..."
1349 else:
1350## print "GROUP -- ch.data[0].data =", ch.data[0].data
1351 k = s(buf, data[0].data)
1352 if k == "fulllineitems":
1353 del data[0]
1354 pp[i-1:i] = data
1355 i = i - 1
1356 length = length + len(data) - 1
1357 continue
Fred Drake43c93501997-12-29 21:40:35 +00001358
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00001359 # recursively parse the contents of the group
Fred Drakee8b46131998-02-17 05:54:46 +00001360 changeit(buf, data)
Guido van Rossum95cd2ef1992-12-08 14:37:55 +00001361
Guido van Rossum36f219d1996-09-11 21:30:40 +00001362 elif ch.chtype == chunk_type[IF]:
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00001363 # \if...
1364 flag, negate, data = ch.data
1365 ##print 'IF: flag, negate = ' + `flag, negate`
1366 if flag not in flags.keys():
1367 raise error, 'unknown flag ' + `flag`
Guido van Rossum95cd2ef1992-12-08 14:37:55 +00001368
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00001369 value = flags[flag]
1370 if negate:
1371 value = (not value)
1372 del pp[i-1]
1373 length, i = length-1, i-1
1374 if value:
1375 pp[i:i] = data
1376 length = length + len(data)
Guido van Rossum95cd2ef1992-12-08 14:37:55 +00001377
1378
Guido van Rossum36f219d1996-09-11 21:30:40 +00001379 elif ch.chtype == chunk_type[ENV]:
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00001380 # \begin{...} ....
1381 envname, data = ch.data
Guido van Rossum95cd2ef1992-12-08 14:37:55 +00001382
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00001383 #push this environment name on stack
1384 hist.inenv.insert(0, envname)
Guido van Rossum95cd2ef1992-12-08 14:37:55 +00001385
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00001386 #append an endenv chunk after grouped data
1387 data.append(chunk(ENDENV, ch.where, envname))
1388 ##[`data`]
Guido van Rossum95cd2ef1992-12-08 14:37:55 +00001389
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00001390 #delete this object
1391 del pp[i-1]
1392 i, length = i-1, length-1
Guido van Rossum95cd2ef1992-12-08 14:37:55 +00001393
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00001394 #insert found data
1395 pp[i:i] = data
1396 length = length + len(data)
Guido van Rossum95cd2ef1992-12-08 14:37:55 +00001397
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00001398 if envname == 'verbatim':
1399 pp[i:i] = [chunk(CSLINE, ch.where, 'example'),
1400 chunk(GROUP, ch.where, [])]
1401 length, i = length+2, i+2
Guido van Rossum95cd2ef1992-12-08 14:37:55 +00001402
Fred Drakeef058031998-02-19 15:20:30 +00001403 elif envname in ('itemize', 'list', 'fulllineitems'):
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00001404 if hist.itemizenesting > len(itemizesymbols):
1405 raise error, 'too deep itemize nesting'
Fred Drakee8b46131998-02-17 05:54:46 +00001406 if envname == 'list':
1407 del pp[i:i+2]
1408 length = length - 2
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00001409 ingroupch = [chunk(CSNAME, ch.where,
Fred Drakee8b46131998-02-17 05:54:46 +00001410 itemizesymbols[hist.itemizenesting])]
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00001411 hist.itemizenesting = hist.itemizenesting + 1
1412 pp[i:i] = [chunk(CSLINE, ch.where, 'itemize'),
Fred Drakee8b46131998-02-17 05:54:46 +00001413 chunk(GROUP, ch.where, ingroupch)]
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00001414 length, i = length+2, i+2
Guido van Rossum95cd2ef1992-12-08 14:37:55 +00001415
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00001416 elif envname == 'enumerate':
1417 if hist.enumeratenesting > len(enumeratesymbols):
1418 raise error, 'too deep enumerate nesting'
1419 ingroupch = [chunk(PLAIN, ch.where,
Fred Drakee8b46131998-02-17 05:54:46 +00001420 enumeratesymbols[hist.enumeratenesting])]
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00001421 hist.enumeratenesting = hist.enumeratenesting + 1
1422 pp[i:i] = [chunk(CSLINE, ch.where, 'enumerate'),
Fred Drakee8b46131998-02-17 05:54:46 +00001423 chunk(GROUP, ch.where, ingroupch)]
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00001424 length, i = length+2, i+2
Guido van Rossum95cd2ef1992-12-08 14:37:55 +00001425
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00001426 elif envname == 'description':
1427 ingroupch = [chunk(CSNAME, ch.where, 'b')]
1428 pp[i:i] = [chunk(CSLINE, ch.where, 'table'),
1429 chunk(GROUP, ch.where, ingroupch)]
1430 length, i = length+2, i+2
Guido van Rossum95cd2ef1992-12-08 14:37:55 +00001431
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00001432 elif (envname == 'tableiii') or (envname == 'tableii'):
1433 if (envname == 'tableii'):
1434 ltable = 2
1435 else:
1436 ltable = 3
1437 wh = ch.where
1438 newcode = []
Guido van Rossum95cd2ef1992-12-08 14:37:55 +00001439
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00001440 #delete tabular format description
1441 # e.g., {|l|c|l|}
1442 length, newi = getnextarg(length, buf, pp, i)
1443 del pp[i:newi]
1444 length = length - (newi-i)
Guido van Rossum95cd2ef1992-12-08 14:37:55 +00001445
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00001446 newcode.append(chunk(CSLINE, wh, 'table'))
1447 ingroupch = [chunk(CSNAME, wh, 'asis')]
1448 newcode.append(chunk(GROUP, wh, ingroupch))
1449 newcode.append(chunk(CSLINE, wh, 'item'))
Guido van Rossum95cd2ef1992-12-08 14:37:55 +00001450
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00001451 #get the name of macro for @item
1452 # e.g., {code}
1453 length, newi = getnextarg(length, buf, pp, i)
Guido van Rossum95cd2ef1992-12-08 14:37:55 +00001454
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00001455 if newi-i != 1:
1456 raise error, 'Sorry, expected 1 chunk argument'
Guido van Rossum36f219d1996-09-11 21:30:40 +00001457 if pp[i].chtype != chunk_type[PLAIN]:
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00001458 raise error, 'Sorry, expected plain text argument'
1459 hist.itemargmacro = s(buf, pp[i].data)
Fred Drake9c7c6be1998-02-19 21:40:22 +00001460 if convertible_csname(hist.itemargmacro):
Fred Drake74a11e51998-02-26 05:52:37 +00001461 hist.itemargmacro = conversion(hist.itemargmacro)[1]
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00001462 del pp[i:newi]
1463 length = length - (newi-i)
Guido van Rossum95cd2ef1992-12-08 14:37:55 +00001464
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00001465 itembody = []
1466 for count in range(ltable):
1467 length, newi = getnextarg(length, buf, pp, i)
1468 emphgroup = [
1469 chunk(CSNAME, wh, 'emph'),
1470 chunk(GROUP, 0, pp[i:newi])]
1471 del pp[i:newi]
1472 length = length - (newi-i)
1473 if count == 0:
1474 itemarg = emphgroup
1475 elif count == ltable-1:
1476 itembody = itembody + \
1477 [chunk(PLAIN, wh, ' --- ')] + emphgroup
1478 else:
1479 itembody = emphgroup
1480 newcode.append(chunk(GROUP, wh, itemarg))
1481 newcode = newcode + itembody + [chunk(DENDLINE, wh, '\n')]
1482 pp[i:i] = newcode
1483 l = len(newcode)
1484 length, i = length+l, i+l
1485 del newcode, l
1486
1487 if length != len(pp):
1488 raise 'STILL, SOMETHING wrong', `i`
1489
Fred Drake4f6d6e41998-04-17 15:28:09 +00001490 elif envname in ('methoddesc', 'methoddescni'):
1491 length, newi = getoptarg(length, buf, pp, i)
1492 ingroupch = pp[i:newi]
1493 del pp[i:newi]
1494 length = length - (newi-i)
1495 #
1496 pp.insert(i, chunk(PLAIN, ch.where, ''))
1497 i, length = i+1, length+1
1498 length, i = do_funcdesc(length, buf, pp, i,
1499 envname[-2:] != "ni")
1500
1501 elif envname in ('memberdesc', 'memberdescni'):
1502 length, newi = getoptarg(length, buf, pp, i)
1503 ingroupch = pp[i:newi]
1504 del pp[i:newi]
1505 length = length - (newi-i)
1506 #
1507 pp.insert(i, chunk(PLAIN, ch.where, ''))
1508 i, length = i+1, length+1
1509 length, i = do_datadesc(length, buf, pp, i,
1510 envname[-2:] != "ni")
1511
Fred Drakeef058031998-02-19 15:20:30 +00001512 elif envname in ('funcdesc', 'funcdescni', 'classdesc'):
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00001513 pp.insert(i, chunk(PLAIN, ch.where, ''))
1514 i, length = i+1, length+1
Fred Drakee8b46131998-02-17 05:54:46 +00001515 length, i = do_funcdesc(length, buf, pp, i,
Fred Drakeef058031998-02-19 15:20:30 +00001516 envname[-2:] != "ni")
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00001517
1518 elif envname == 'excdesc':
1519 pp.insert(i, chunk(PLAIN, ch.where, ''))
1520 i, length = i+1, length+1
1521 length, i = do_excdesc(length, buf, pp, i)
1522
Fred Drakee8b46131998-02-17 05:54:46 +00001523 elif envname in ('datadesc', 'datadescni'):
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00001524 pp.insert(i, chunk(PLAIN, ch.where, ''))
1525 i, length = i+1, length+1
Fred Drakee8b46131998-02-17 05:54:46 +00001526 length, i = do_datadesc(length, buf, pp, i,
Fred Drakeef058031998-02-19 15:20:30 +00001527 envname[-2:] != "ni")
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00001528
Fred Drakea4541af1997-12-29 17:19:22 +00001529 elif envname == 'opcodedesc':
1530 pp.insert(i, chunk(PLAIN, ch.where, ''))
1531 i, length = i+1, length+1
1532 length, i = do_opcodedesc(length, buf, pp, i)
1533
1534 elif envname == 'seealso':
1535 chunks = [chunk(ENDLINE, ch.where, "\n"),
1536 chunk(CSNAME, ch.where, "b"),
1537 chunk(GROUP, ch.where, [
1538 chunk(PLAIN, ch.where, "See also: ")]),
1539 chunk(ENDLINE, ch.where, "\n"),
1540 chunk(ENDLINE, ch.where, "\n")]
1541 pp[i-1:i] = chunks
1542 length = length + len(chunks) - 1
1543 i = i + len(chunks) - 1
1544
Fred Drake74a11e51998-02-26 05:52:37 +00001545 elif envname in ('sloppypar', 'flushleft', 'document'):
Fred Drake43c93501997-12-29 21:40:35 +00001546 pass
1547
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00001548 else:
1549 print 'WARNING: don\'t know what to do with env ' + `envname`
1550
Guido van Rossum36f219d1996-09-11 21:30:40 +00001551 elif ch.chtype == chunk_type[ENDENV]:
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00001552 envname = ch.data
1553 if envname != hist.inenv[0]:
1554 raise error, '\'end\' does not match. Name ' + `envname` + ', expected ' + `hist.inenv[0]`
1555 del hist.inenv[0]
1556 del pp[i-1]
1557 i, length = i-1, length-1
1558
1559 if envname == 'verbatim':
Fred Drake43c93501997-12-29 21:40:35 +00001560 pp[i:i] = [chunk(CSLINE, ch.where, 'end'),
1561 chunk(GROUP, ch.where, [
1562 chunk(PLAIN, ch.where, 'example')])]
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00001563 i, length = i+2, length+2
Fred Drakeef058031998-02-19 15:20:30 +00001564 elif envname in ('itemize', 'list', 'fulllineitems'):
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00001565 hist.itemizenesting = hist.itemizenesting - 1
Fred Drake43c93501997-12-29 21:40:35 +00001566 pp[i:i] = [chunk(CSLINE, ch.where, 'end'),
1567 chunk(GROUP, ch.where, [
1568 chunk(PLAIN, ch.where, 'itemize')])]
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00001569 i, length = i+2, length+2
1570 elif envname == 'enumerate':
1571 hist.enumeratenesting = hist.enumeratenesting-1
Fred Drake43c93501997-12-29 21:40:35 +00001572 pp[i:i] = [chunk(CSLINE, ch.where, 'end'),
1573 chunk(GROUP, ch.where, [
1574 chunk(PLAIN, ch.where, 'enumerate')])]
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00001575 i, length = i+2, length+2
1576 elif envname == 'description':
Fred Drake43c93501997-12-29 21:40:35 +00001577 pp[i:i] = [chunk(CSLINE, ch.where, 'end'),
1578 chunk(GROUP, ch.where, [
1579 chunk(PLAIN, ch.where, 'table')])]
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00001580 i, length = i+2, length+2
1581 elif (envname == 'tableiii') or (envname == 'tableii'):
Fred Drake43c93501997-12-29 21:40:35 +00001582 pp[i:i] = [chunk(CSLINE, ch.where, 'end'),
1583 chunk(GROUP, ch.where, [
1584 chunk(PLAIN, ch.where, 'table')])]
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00001585 i, length = i+2, length + 2
1586 pp.insert(i, chunk(DENDLINE, ch.where, '\n'))
1587 i, length = i+1, length+1
1588
Fred Drakeef058031998-02-19 15:20:30 +00001589 elif envname in ('funcdesc', 'excdesc', 'datadesc', 'classdesc',
Fred Drake4f6d6e41998-04-17 15:28:09 +00001590 'funcdescni', 'datadescni',
1591 'methoddesc', 'memberdesc',
1592 'methoddescni', 'memberdescni',
1593 ):
Fred Drake43c93501997-12-29 21:40:35 +00001594 pp[i:i] = [chunk(CSLINE, ch.where, 'end'),
1595 chunk(GROUP, ch.where, [
1596 chunk(PLAIN, ch.where, hist.command)])]
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00001597 i, length = i+2, length+2
Fred Drakea4541af1997-12-29 17:19:22 +00001598
Fred Drake43c93501997-12-29 21:40:35 +00001599 elif envname == 'opcodedesc':
1600 pp[i:i] = [chunk(CSLINE, ch.where, 'end'),
1601 chunk(GROUP, ch.where, [
1602 chunk(PLAIN, ch.where, "deffn")])]
1603 i, length = i+2, length+2
1604
Fred Drake74a11e51998-02-26 05:52:37 +00001605 elif envname in ('seealso', 'sloppypar', 'flushleft', 'document'):
Fred Drakea4541af1997-12-29 17:19:22 +00001606 pass
1607
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00001608 else:
Fred Drakea4541af1997-12-29 17:19:22 +00001609 print 'WARNING: ending env %s has no actions' % `envname`
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00001610
Guido van Rossum36f219d1996-09-11 21:30:40 +00001611 elif ch.chtype == chunk_type[CSNAME]:
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00001612 # control name transformations
Guido van Rossum36f219d1996-09-11 21:30:40 +00001613 s_buf_data = s(buf, ch.data)
1614 if s_buf_data == 'optional':
1615 pp[i-1].chtype = chunk_type[PLAIN]
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00001616 pp[i-1].data = '['
1617 if (i < length) and \
Guido van Rossum36f219d1996-09-11 21:30:40 +00001618 (pp[i].chtype == chunk_type[GROUP]):
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00001619 cp=pp[i].data
1620 pp[i:i+1]=cp + [
1621 chunk(PLAIN, ch.where, ']')]
1622 length = length+len(cp)
Fred Drake74a11e51998-02-26 05:52:37 +00001623
Guido van Rossum36f219d1996-09-11 21:30:40 +00001624 elif s_buf_data in ignoredcommands:
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00001625 del pp[i-1]
1626 i, length = i-1, length-1
Fred Drake74a11e51998-02-26 05:52:37 +00001627
Guido van Rossum36f219d1996-09-11 21:30:40 +00001628 elif s_buf_data == '@' and \
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00001629 i != length and \
Guido van Rossum36f219d1996-09-11 21:30:40 +00001630 pp[i].chtype == chunk_type[PLAIN] and \
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00001631 s(buf, pp[i].data)[0] == '.':
1632 # \@. --> \. --> @.
1633 ch.data = '.'
1634 del pp[i]
Fred Drake74a11e51998-02-26 05:52:37 +00001635 length = length - 1
1636
1637 elif convertible_csname(s_buf_data):
1638 ch.chtype, ch.data, nix = conversion(s_buf_data)
1639 try:
1640 if nix and pp[i].chtype == chunk_type[GROUP] \
1641 and len(pp[i].data) == 0:
1642 del pp[i]
1643 length = length - 1
1644 except IndexError:
1645 pass
1646
Guido van Rossum36f219d1996-09-11 21:30:40 +00001647 elif s_buf_data == '\\':
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00001648 # \\ --> \* --> @*
1649 ch.data = '*'
Fred Drake74a11e51998-02-26 05:52:37 +00001650
Guido van Rossum36f219d1996-09-11 21:30:40 +00001651 elif len(s_buf_data) == 1 and \
1652 s_buf_data in onlylatexspecial:
1653 ch.chtype = chunk_type[PLAIN]
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00001654 # check if such a command is followed by
1655 # an empty group: e.g., `\%{}'. If so, remove
1656 # this empty group too
1657 if i < length and \
Guido van Rossum36f219d1996-09-11 21:30:40 +00001658 pp[i].chtype == chunk_type[GROUP] \
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00001659 and len(pp[i].data) == 0:
1660 del pp[i]
1661 length = length-1
1662
Fred Drake74a11e51998-02-26 05:52:37 +00001663 elif s_buf_data == "appendix":
1664 hist.chaptertype = "appendix"
1665 del pp[i-1]
1666 i, length = i-1, length-1
1667
Guido van Rossum36f219d1996-09-11 21:30:40 +00001668 elif hist.inargs and s_buf_data in inargsselves:
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00001669 # This is the special processing of the
1670 # arguments of the \begin{funcdesc}... or
1671 # \funcline... arguments
1672 # \, --> , \[ --> [, \] --> ]
Guido van Rossum36f219d1996-09-11 21:30:40 +00001673 ch.chtype = chunk_type[PLAIN]
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00001674
Fred Drakee8b46131998-02-17 05:54:46 +00001675 elif s_buf_data == 'setindexsubitem':
Fred Drake4f6d6e41998-04-17 15:28:09 +00001676 length, i = yank_indexsubitem(pp, length, i, buf, ch,
1677 'setindexsubitem')
1678
1679 elif s_buf_data == 'withsubitem':
1680 oldsubitem = hist.indexsubitem
1681 try:
1682 length, i = yank_indexsubitem(pp, length, i, buf, ch,
1683 'withsubitem')
1684 stuff = pp[i].data
1685 del pp[i]
1686 length = length - 1
1687 changeit(buf, stuff)
1688 stuff = None
1689 finally:
1690 hist.indexsubitem = oldsubitem
1691
1692 elif s_buf_data in ('textrm', 'pytype'):
1693 stuff = pp[i].data
1694 pp[i-1:i+1] = stuff
1695 length = length - 2 + len(stuff)
1696 stuff = None
1697 i = i - 1
Fred Drakee8b46131998-02-17 05:54:46 +00001698
1699 elif s_buf_data == 'newcommand':
1700 print "ignoring definition of \\" + s(buf, pp[i].data[0].data)
1701 del pp[i-1:i+2]
1702 i = i - 1
1703 length = length - 3
1704
Fred Drake74a11e51998-02-26 05:52:37 +00001705 elif s_buf_data == 'renewcommand':
1706 print "ignoring redefinition of \\" \
1707 + s(buf, pp[i].data[0].data)
1708 del pp[i-1:i+2]
1709 i = i - 1
1710 length = length - 3
1711
Fred Drakee8b46131998-02-17 05:54:46 +00001712 elif s_buf_data == 'mbox':
1713 stuff = pp[i].data
1714 pp[i-1:i+1] = stuff
1715 i = i - 1
1716 length = length + len(stuff) - 2
Fred Drake4f6d6e41998-04-17 15:28:09 +00001717 stuff = None
Fred Drakee8b46131998-02-17 05:54:46 +00001718
1719 elif s_buf_data == 'version':
1720 ch.chtype = chunk_type[PLAIN]
1721 ch.data = release_version
1722
Guido van Rossum36f219d1996-09-11 21:30:40 +00001723 elif s_buf_data == 'item':
1724 ch.chtype = chunk_type[CSLINE]
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00001725 length, newi = getoptarg(length, buf, pp, i)
1726 ingroupch = pp[i:newi]
1727 del pp[i:newi]
1728 length = length - (newi-i)
Fred Drake893e5e01996-10-25 22:13:10 +00001729 changeit(buf, ingroupch) # catch stuff inside the optional arg
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00001730 pp.insert(i, chunk(GROUP, ch.where, ingroupch))
1731 i, length = i+1, length+1
1732
Guido van Rossum36f219d1996-09-11 21:30:40 +00001733 elif s_buf_data == 'ttindex':
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00001734 idxsi = hist.indexsubitem
1735
1736 cat_class = ''
1737 if len(idxsi) >= 2 and idxsi[1] in \
1738 ('method', 'function', 'protocol'):
1739 command = 'findex'
1740 elif len(idxsi) >= 2 and idxsi[1] in \
1741 ('exception', 'object'):
1742 command = 'vindex'
Fred Drake7edd8d31996-10-09 16:11:26 +00001743 elif len(idxsi) == 3 and idxsi[:2] == ['in', 'module']:
1744 command = 'cindex'
Fred Drake4f6d6e41998-04-17 15:28:09 +00001745 elif len(idxsi) == 3 and idxsi[:2] == ['class', 'in']:
1746 command = 'findex'
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00001747 else:
Fred Drake7edd8d31996-10-09 16:11:26 +00001748 print 'WARNING: can\'t categorize ' + `idxsi` \
1749 + ' for \'ttindex\' command'
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00001750 command = 'cindex'
1751
1752 if not cat_class:
Fred Drake4f6d6e41998-04-17 15:28:09 +00001753 cat_class = '(%s)' % string.join(idxsi)
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00001754
Guido van Rossum36f219d1996-09-11 21:30:40 +00001755 ch.chtype = chunk_type[CSLINE]
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00001756 ch.data = command
1757
1758 length, newi = getnextarg(length, buf, pp, i)
1759 arg = pp[i:newi]
1760 del pp[i:newi]
1761 length = length - (newi-i)
1762
1763 cat_arg = [chunk(PLAIN, ch.where, cat_class)]
1764
1765 # determine what should be set in roman, and
1766 # what in tt-font
1767 if command in regindices:
1768
1769 arg = [chunk(CSNAME, ch.where, 't'),
Fred Drake9c7c6be1998-02-19 21:40:22 +00001770 chunk(GROUP, ch.where, arg)]
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00001771 else:
1772 cat_arg = [chunk(CSNAME, ch.where, 'r'),
Fred Drake9c7c6be1998-02-19 21:40:22 +00001773 chunk(GROUP, ch.where, cat_arg)]
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00001774
1775 ingroupch = arg + \
1776 [chunk(PLAIN, ch.where, ' ')] + \
1777 cat_arg
1778
1779 pp.insert(i, chunk(GROUP, ch.where, ingroupch))
1780 length, i = length+1, i+1
1781
Guido van Rossum36f219d1996-09-11 21:30:40 +00001782 elif s_buf_data == 'ldots':
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00001783 # \ldots --> \dots{} --> @dots{}
1784 ch.data = 'dots'
1785 if i == length \
Guido van Rossum36f219d1996-09-11 21:30:40 +00001786 or pp[i].chtype != chunk_type[GROUP] \
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00001787 or pp[i].data != []:
1788 pp.insert(i, chunk(GROUP, ch.where, []))
1789 i, length = i+1, length+1
Fred Drake74a11e51998-02-26 05:52:37 +00001790
Guido van Rossum36f219d1996-09-11 21:30:40 +00001791 elif s_buf_data in themselves:
Fred Drakee8b46131998-02-17 05:54:46 +00001792 # \UNIX --> &UNIX;
Guido van Rossum36f219d1996-09-11 21:30:40 +00001793 ch.chtype = chunk_type[PLAIN]
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00001794 if i != length \
Guido van Rossum36f219d1996-09-11 21:30:40 +00001795 and pp[i].chtype == chunk_type[GROUP] \
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00001796 and pp[i].data == []:
1797 del pp[i]
1798 length = length-1
Fred Drake74a11e51998-02-26 05:52:37 +00001799
Fred Drakee8b46131998-02-17 05:54:46 +00001800 elif s_buf_data == 'manpage':
1801 ch.data = 'emph'
1802 sect = s(buf, pp[i+1].data[0].data)
1803 pp[i+1].data = "(%s)" % sect
1804 pp[i+1].chtype = chunk_type[PLAIN]
1805
Fred Drake4f6d6e41998-04-17 15:28:09 +00001806 elif s_buf_data == 'envvar':
1807 # this should do stuff in the index, too...
1808 ch.data = "$"
1809 ch.chtype = chunk_type[PLAIN]
1810 pp[i] = pp[i].data[0]
1811
1812 elif s_buf_data == 'regexp':
1813 ch.data = 'code'
1814 pp.insert(i+1, chunk(PLAIN, ch.where, '"'))
1815 pp.insert(i-1, chunk(PLAIN, ch.where, '"'))
1816 length = length + 2
1817 i = i + 1
1818
Guido van Rossum36f219d1996-09-11 21:30:40 +00001819 elif s_buf_data in ('lineiii', 'lineii'):
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00001820 # This is the most tricky one
1821 # \lineiii{a1}{a2}[{a3}] -->
1822 # @item @<cts. of itemargmacro>{a1}
1823 # a2 [ -- a3]
1824 #
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00001825 if not hist.inenv:
1826 raise error, 'no environment for lineiii'
1827 if (hist.inenv[0] != 'tableiii') and \
1828 (hist.inenv[0] != 'tableii'):
1829 raise error, \
Guido van Rossum36f219d1996-09-11 21:30:40 +00001830 'wrong command (%s) in wrong environment (%s)' \
1831 % (s_buf_data, `hist.inenv[0]`)
1832 ch.chtype = chunk_type[CSLINE]
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00001833 ch.data = 'item'
1834 length, newi = getnextarg(length, buf, pp, i)
Guido van Rossum36f219d1996-09-11 21:30:40 +00001835 ingroupch = [chunk(CSNAME, 0, hist.itemargmacro),
1836 chunk(GROUP, 0, pp[i:newi])]
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00001837 del pp[i:newi]
1838 length = length - (newi-i)
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00001839 pp.insert(i, chunk(GROUP, ch.where, ingroupch))
1840 grouppos = i
1841 i, length = i+1, length+1
1842 length, i = getnextarg(length, buf, pp, i)
1843 length, newi = getnextarg(length, buf, pp, i)
1844 if newi > i:
1845 # we have a 3rd arg
1846 pp.insert(i, chunk(PLAIN, ch.where, ' --- '))
1847 i = newi + 1
1848 length = length + 1
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00001849 if length != len(pp):
1850 raise 'IN LINEIII IS THE ERR', `i`
Guido van Rossum95cd2ef1992-12-08 14:37:55 +00001851
Fred Drake74a11e51998-02-26 05:52:37 +00001852 elif s_buf_data in ('chapter', 'section',
1853 'subsection', 'subsubsection'):
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00001854 #\xxxsection{A} ---->
1855 # @node A, , ,
1856 # @xxxsection A
1857 ## also: remove commas and quotes
Fred Drake4f6d6e41998-04-17 15:28:09 +00001858 hist.this_module = None
Fred Drake74a11e51998-02-26 05:52:37 +00001859 if s_buf_data == "chapter":
1860 ch.data = hist.chaptertype
Guido van Rossum36f219d1996-09-11 21:30:40 +00001861 ch.chtype = chunk_type[CSLINE]
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00001862 length, newi = getnextarg(length, buf, pp, i)
Fred Drakee8b46131998-02-17 05:54:46 +00001863 afternodenamecmd = next_command_p(length, buf,
1864 pp, newi, 'nodename')
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00001865 if afternodenamecmd < 0:
1866 cp1 = crcopy(pp[i:newi])
Guido van Rossum36f219d1996-09-11 21:30:40 +00001867 pp[i:newi] = [chunk(GROUP, ch.where, pp[i:newi])]
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00001868 length, newi = length - (newi-i) + 1, i+1
1869 text = flattext(buf, cp1)
1870 text = invent_node_names(text)
1871 else:
Fred Drakee8b46131998-02-17 05:54:46 +00001872 length, endarg = getnextarg(length, buf,
1873 pp, afternodenamecmd)
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00001874 cp1 = crcopy(pp[afternodenamecmd:endarg])
1875 del pp[newi:endarg]
1876 length = length - (endarg-newi)
Guido van Rossum95cd2ef1992-12-08 14:37:55 +00001877
Guido van Rossum36f219d1996-09-11 21:30:40 +00001878 pp[i:newi] = [chunk(GROUP, ch.where, pp[i:newi])]
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00001879 length, newi = length - (newi-i) + 1, i + 1
1880 text = flattext(buf, cp1)
1881 if text[-1] == '.':
1882 text = text[:-1]
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00001883 if text in hist.nodenames:
1884 print 'WARNING: node name ' + `text` + ' already used'
1885 out.doublenodes.append(text)
1886 else:
1887 hist.nodenames.append(text)
1888 text = rm_commas_etc(text)
Guido van Rossum36f219d1996-09-11 21:30:40 +00001889 pp[i-1:i-1] = [chunk(CSLINE, ch.where, 'node'),
1890 chunk(GROUP, ch.where, [
1891 chunk(PLAIN, ch.where, text+', , ,')
1892 ])]
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00001893 i, length = newi+2, length+2
Guido van Rossum95cd2ef1992-12-08 14:37:55 +00001894
Guido van Rossum36f219d1996-09-11 21:30:40 +00001895 elif s_buf_data == 'funcline':
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00001896 # fold it to a very short environment
Guido van Rossum36f219d1996-09-11 21:30:40 +00001897 pp[i-1:i-1] = [chunk(CSLINE, ch.where, 'end'),
1898 chunk(GROUP, ch.where, [
1899 chunk(PLAIN, ch.where, hist.command)])]
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00001900 i, length = i+2, length+2
1901 length, i = do_funcdesc(length, buf, pp, i)
Guido van Rossum95cd2ef1992-12-08 14:37:55 +00001902
Guido van Rossum36f219d1996-09-11 21:30:40 +00001903 elif s_buf_data == 'dataline':
1904 pp[i-1:i-1] = [chunk(CSLINE, ch.where, 'end'),
1905 chunk(GROUP, ch.where, [
1906 chunk(PLAIN, ch.where, hist.command)])]
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00001907 i, length = i+2, length+2
1908 length, i = do_datadesc(length, buf, pp, i)
Guido van Rossum95cd2ef1992-12-08 14:37:55 +00001909
Guido van Rossum36f219d1996-09-11 21:30:40 +00001910 elif s_buf_data == 'excline':
1911 pp[i-1:i-1] = [chunk(CSLINE, ch.where, 'end'),
1912 chunk(GROUP, ch.where, [
1913 chunk(PLAIN, ch.where, hist.command)])]
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00001914 i, length = i+2, length+2
1915 length, i = do_excdesc(length, buf, pp, i)
Guido van Rossum95cd2ef1992-12-08 14:37:55 +00001916
Guido van Rossum36f219d1996-09-11 21:30:40 +00001917 elif s_buf_data == 'index':
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00001918 #\index{A} --->
1919 # @cindex A
Guido van Rossum36f219d1996-09-11 21:30:40 +00001920 ch.chtype = chunk_type[CSLINE]
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00001921 ch.data = 'cindex'
1922 length, newi = getnextarg(length, buf, pp, i)
Guido van Rossum95cd2ef1992-12-08 14:37:55 +00001923
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00001924 ingroupch = pp[i:newi]
1925 del pp[i:newi]
1926 length = length - (newi-i)
1927 pp.insert(i, chunk(GROUP, ch.where, ingroupch))
1928 length, i = length+1, i+1
Guido van Rossum95cd2ef1992-12-08 14:37:55 +00001929
Guido van Rossum36f219d1996-09-11 21:30:40 +00001930 elif s_buf_data == 'bifuncindex':
1931 ch.chtype = chunk_type[CSLINE]
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00001932 ch.data = 'findex'
1933 length, newi = getnextarg(length, buf, pp, i)
1934 ingroupch = pp[i:newi]
1935 del pp[i:newi]
1936 length = length - (newi-i)
Guido van Rossum95cd2ef1992-12-08 14:37:55 +00001937
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00001938 ingroupch.append(chunk(PLAIN, ch.where, ' '))
1939 ingroupch.append(chunk(CSNAME, ch.where, 'r'))
1940 ingroupch.append(chunk(GROUP, ch.where, [
1941 chunk(PLAIN, ch.where,
1942 '(built-in function)')]))
1943
1944 pp.insert(i, chunk(GROUP, ch.where, ingroupch))
1945 length, i = length+1, i+1
Guido van Rossum95cd2ef1992-12-08 14:37:55 +00001946
Guido van Rossum36f219d1996-09-11 21:30:40 +00001947 elif s_buf_data == 'obindex':
1948 ch.chtype = chunk_type[CSLINE]
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00001949 ch.data = 'findex'
1950 length, newi = getnextarg(length, buf, pp, i)
1951 ingroupch = pp[i:newi]
1952 del pp[i:newi]
1953 length = length - (newi-i)
Guido van Rossum95cd2ef1992-12-08 14:37:55 +00001954
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00001955 ingroupch.append(chunk(PLAIN, ch.where, ' '))
1956 ingroupch.append(chunk(CSNAME, ch.where, 'r'))
1957 ingroupch.append(chunk(GROUP, ch.where, [
1958 chunk(PLAIN, ch.where,
1959 '(object)')]))
Guido van Rossum95cd2ef1992-12-08 14:37:55 +00001960
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00001961 pp.insert(i, chunk(GROUP, ch.where, ingroupch))
1962 length, i = length+1, i+1
Guido van Rossum95cd2ef1992-12-08 14:37:55 +00001963
Guido van Rossum36f219d1996-09-11 21:30:40 +00001964 elif s_buf_data == 'opindex':
1965 ch.chtype = chunk_type[CSLINE]
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00001966 ch.data = 'findex'
1967 length, newi = getnextarg(length, buf, pp, i)
1968 ingroupch = pp[i:newi]
1969 del pp[i:newi]
1970 length = length - (newi-i)
Guido van Rossum95cd2ef1992-12-08 14:37:55 +00001971
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00001972 ingroupch.append(chunk(PLAIN, ch.where, ' '))
1973 ingroupch.append(chunk(CSNAME, ch.where, 'r'))
1974 ingroupch.append(chunk(GROUP, ch.where, [
1975 chunk(PLAIN, ch.where,
1976 '(operator)')]))
Guido van Rossum95cd2ef1992-12-08 14:37:55 +00001977
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00001978 pp.insert(i, chunk(GROUP, ch.where, ingroupch))
1979 length, i = length+1, i+1
Guido van Rossum95cd2ef1992-12-08 14:37:55 +00001980
Fred Drakea4541af1997-12-29 17:19:22 +00001981 elif s_buf_data in ('bimodindex', 'refbimodindex'):
Fred Drake4f6d6e41998-04-17 15:28:09 +00001982 length, i = add_module_index(
1983 pp, length, i, buf, ch, '(built-in)',
1984 (s_buf_data[:3] == 'ref'))
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00001985
Fred Drake4f6d6e41998-04-17 15:28:09 +00001986 elif s_buf_data in ('modindex', 'refmodindex'):
1987 length, i = add_module_index(
1988 pp, length, i, buf, ch, '',
1989 (s_buf_data[:3] == 'ref'))
Fred Drakea4541af1997-12-29 17:19:22 +00001990
Fred Drakea4541af1997-12-29 17:19:22 +00001991 elif s_buf_data in ('stmodindex', 'refstmodindex'):
Fred Drake4f6d6e41998-04-17 15:28:09 +00001992 length, i = add_module_index(
1993 pp, length, i, buf, ch, '(standard)',
1994 (s_buf_data[:3] == 'ref'))
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00001995
Fred Drake4f6d6e41998-04-17 15:28:09 +00001996 elif s_buf_data in ('exmodindex', 'refexmodindex'):
1997 length, i = add_module_index(
1998 pp, length, i, buf, ch, '(extension)',
1999 (s_buf_data[:3] == 'ref'))
Fred Drakea4541af1997-12-29 17:19:22 +00002000
Fred Drake74a11e51998-02-26 05:52:37 +00002001 elif s_buf_data == 'stindex':
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00002002 # XXX must actually go to newindex st
Fred Drakea4541af1997-12-29 17:19:22 +00002003 what = (s_buf_data[:2] == "st") and "statement" or "keyword"
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00002004 wh = ch.where
Guido van Rossum36f219d1996-09-11 21:30:40 +00002005 ch.chtype = chunk_type[CSLINE]
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00002006 ch.data = 'cindex'
2007 length, newi = getnextarg(length, buf, pp, i)
2008 ingroupch = [chunk(CSNAME, wh, 'code'),
Fred Drakee8b46131998-02-17 05:54:46 +00002009 chunk(GROUP, wh, pp[i:newi])]
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00002010
2011 del pp[i:newi]
2012 length = length - (newi-i)
2013
2014 t = ingroupch[:]
Fred Drakea4541af1997-12-29 17:19:22 +00002015 t.append(chunk(PLAIN, wh, ' ' + what))
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00002016
2017 pp.insert(i, chunk(GROUP, wh, t))
2018 i, length = i+1, length+1
2019
2020 pp.insert(i, chunk(CSLINE, wh, 'cindex'))
2021 i, length = i+1, length+1
2022
2023 t = ingroupch[:]
Fred Drakea4541af1997-12-29 17:19:22 +00002024 t.insert(0, chunk(PLAIN, wh, what + ', '))
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00002025
2026 pp.insert(i, chunk(GROUP, wh, t))
2027 i, length = i+1, length+1
2028
Guido van Rossum36f219d1996-09-11 21:30:40 +00002029 elif s_buf_data == 'indexii':
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00002030 #\indexii{A}{B} --->
2031 # @cindex A B
2032 # @cindex B, A
2033 length, newi = getnextarg(length, buf, pp, i)
2034 cp11 = pp[i:newi]
2035 cp21 = crcopy(pp[i:newi])
2036 del pp[i:newi]
2037 length = length - (newi-i)
2038 length, newi = getnextarg(length, buf, pp, i)
2039 cp12 = pp[i:newi]
2040 cp22 = crcopy(pp[i:newi])
2041 del pp[i:newi]
2042 length = length - (newi-i)
2043
Guido van Rossum36f219d1996-09-11 21:30:40 +00002044 ch.chtype = chunk_type[CSLINE]
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00002045 ch.data = 'cindex'
2046 pp.insert(i, chunk(GROUP, ch.where, cp11 + [
2047 chunk(PLAIN, ch.where, ' ')] + cp12))
2048 i, length = i+1, length+1
2049 pp[i:i] = [chunk(CSLINE, ch.where, 'cindex'),
2050 chunk(GROUP, ch.where, cp22 + [
2051 chunk(PLAIN, ch.where, ', ')]+ cp21)]
2052 i, length = i+2, length+2
2053
Guido van Rossum36f219d1996-09-11 21:30:40 +00002054 elif s_buf_data == 'indexiii':
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00002055 length, newi = getnextarg(length, buf, pp, i)
2056 cp11 = pp[i:newi]
2057 cp21 = crcopy(pp[i:newi])
2058 cp31 = crcopy(pp[i:newi])
2059 del pp[i:newi]
2060 length = length - (newi-i)
2061 length, newi = getnextarg(length, buf, pp, i)
2062 cp12 = pp[i:newi]
2063 cp22 = crcopy(pp[i:newi])
2064 cp32 = crcopy(pp[i:newi])
2065 del pp[i:newi]
2066 length = length - (newi-i)
2067 length, newi = getnextarg(length, buf, pp, i)
2068 cp13 = pp[i:newi]
2069 cp23 = crcopy(pp[i:newi])
2070 cp33 = crcopy(pp[i:newi])
2071 del pp[i:newi]
2072 length = length - (newi-i)
2073
Guido van Rossum36f219d1996-09-11 21:30:40 +00002074 ch.chtype = chunk_type[CSLINE]
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00002075 ch.data = 'cindex'
2076 pp.insert(i, chunk(GROUP, ch.where, cp11 + [
2077 chunk(PLAIN, ch.where, ' ')] + cp12
2078 + [chunk(PLAIN, ch.where, ' ')]
2079 + cp13))
2080 i, length = i+1, length+1
2081 pp[i:i] = [chunk(CSLINE, ch.where, 'cindex'),
2082 chunk(GROUP, ch.where, cp22 + [
2083 chunk(PLAIN, ch.where, ' ')]+ cp23
2084 + [chunk(PLAIN, ch.where, ', ')] +
2085 cp21)]
2086 i, length = i+2, length+2
2087 pp[i:i] = [chunk(CSLINE, ch.where, 'cindex'),
2088 chunk(GROUP, ch.where, cp33 + [
2089 chunk(PLAIN, ch.where, ', ')]+ cp31
2090 + [chunk(PLAIN, ch.where, ' ')] +
2091 cp32)]
2092 i, length = i+2, length+2
2093
Guido van Rossum36f219d1996-09-11 21:30:40 +00002094 elif s_buf_data == 'indexiv':
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00002095 length, newi = getnextarg(length, buf, pp, i)
2096 cp11 = pp[i:newi]
2097 cp21 = crcopy(pp[i:newi])
2098 cp31 = crcopy(pp[i:newi])
2099 cp41 = crcopy(pp[i:newi])
2100 del pp[i:newi]
2101 length = length - (newi-i)
2102 length, newi = getnextarg(length, buf, pp, i)
2103 cp12 = pp[i:newi]
2104 cp22 = crcopy(pp[i:newi])
2105 cp32 = crcopy(pp[i:newi])
2106 cp42 = crcopy(pp[i:newi])
2107 del pp[i:newi]
2108 length = length - (newi-i)
2109 length, newi = getnextarg(length, buf, pp, i)
2110 cp13 = pp[i:newi]
2111 cp23 = crcopy(pp[i:newi])
2112 cp33 = crcopy(pp[i:newi])
2113 cp43 = crcopy(pp[i:newi])
2114 del pp[i:newi]
2115 length = length - (newi-i)
2116 length, newi = getnextarg(length, buf, pp, i)
2117 cp14 = pp[i:newi]
2118 cp24 = crcopy(pp[i:newi])
2119 cp34 = crcopy(pp[i:newi])
2120 cp44 = crcopy(pp[i:newi])
2121 del pp[i:newi]
2122 length = length - (newi-i)
2123
Guido van Rossum36f219d1996-09-11 21:30:40 +00002124 ch.chtype = chunk_type[CSLINE]
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00002125 ch.data = 'cindex'
2126 ingroupch = cp11 + \
2127 spacech + cp12 + \
2128 spacech + cp13 + \
2129 spacech + cp14
2130 pp.insert(i, chunk(GROUP, ch.where, ingroupch))
2131 i, length = i+1, length+1
2132 ingroupch = cp22 + \
2133 spacech + cp23 + \
2134 spacech + cp24 + \
2135 commach + cp21
2136 pp[i:i] = cindexch + [
2137 chunk(GROUP, ch.where, ingroupch)]
2138 i, length = i+2, length+2
2139 ingroupch = cp33 + \
2140 spacech + cp34 + \
2141 commach + cp31 + \
2142 spacech + cp32
2143 pp[i:i] = cindexch + [
2144 chunk(GROUP, ch.where, ingroupch)]
2145 i, length = i+2, length+2
2146 ingroupch = cp44 + \
2147 commach + cp41 + \
2148 spacech + cp42 + \
2149 spacech + cp43
2150 pp[i:i] = cindexch + [
2151 chunk(GROUP, ch.where, ingroupch)]
2152 i, length = i+2, length+2
2153
Fred Drakea4541af1997-12-29 17:19:22 +00002154 elif s_buf_data == 'seemodule':
Fred Drake4f6d6e41998-04-17 15:28:09 +00002155 # discard optional arg first:
2156 length, newi = getoptarg(length, buf, pp, i)
2157 ingroupch = pp[i:newi]
2158 del pp[i:newi]
2159 length = length - (newi-i)
2160 #
Fred Drakea4541af1997-12-29 17:19:22 +00002161 ch.data = "code"
2162 data = pp[i+1].data
Fred Drake4f6d6e41998-04-17 15:28:09 +00002163 data.insert(0, chunk(PLAIN, ch.where, " ("))
Fred Drakea4541af1997-12-29 17:19:22 +00002164 data.append(chunk(PLAIN, ch.where, ")"))
2165 pp[i+1:i+2] = data
2166 length = length + len(data) - 1
2167
2168 elif s_buf_data == 'seetext':
2169 data = pp[i].data
2170 data.insert(0, chunk(ENDLINE, ch.where, "\n"))
2171 pp[i-1:i+1] = data
2172 i = i - 1
2173 length = length + len(data) - 2
2174
Fred Drakeb98cd391998-03-04 06:33:43 +00002175 elif s_buf_data == 'deprecated':
2176 length, newi = getnextarg(length, buf, pp, i)
2177 version = pp[i:newi][0]
Fred Drakeb98cd391998-03-04 06:33:43 +00002178 length, newi2 = getnextarg(length, buf, pp, newi)
2179 action = pp[newi:newi2]
Fred Drakeb98cd391998-03-04 06:33:43 +00002180 del pp[i-1:newi2]
2181 length = length - (newi2 - i) - 1
2182 stuff = [chunk(PLAIN, ch.where, 'Deprecated since release '),
2183 version,
2184 chunk(PLAIN, ch.where, '.')]
2185 chunks = [chunk(CSNAME, ch.where, 'strong'),
2186 chunk(GROUP, ch.where, stuff),
2187 chunk(PLAIN, ch.where, ' ')] + action \
2188 + [chunk(DENDLINE, ch.where, '\n')]
Fred Drake4f6d6e41998-04-17 15:28:09 +00002189 stuff = None
Fred Drakeb98cd391998-03-04 06:33:43 +00002190 i = i - 1
2191 pp[i:i] = chunks
2192 length = length + len(chunks)
2193
Fred Drake43c93501997-12-29 21:40:35 +00002194 elif s_buf_data == "quad":
2195 ch.chtype = PLAIN
2196 ch.data = " "
2197
Fred Drake74a11e51998-02-26 05:52:37 +00002198 elif s_buf_data in ('usepackage', 'input'):
2199 del pp[i-1:i+1]
2200 i, length = i-1, length-2
2201
Fred Drakee8b46131998-02-17 05:54:46 +00002202 elif s_buf_data in ('noindent', 'indexsubitem', 'footnote'):
Guido van Rossum36f219d1996-09-11 21:30:40 +00002203 pass
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00002204
Fred Drakea4541af1997-12-29 17:19:22 +00002205 elif s_buf_data == 'label':
Fred Drake43c93501997-12-29 21:40:35 +00002206 name = s(buf, pp[i].data[0].data)
Fred Drakea4541af1997-12-29 17:19:22 +00002207 del pp[i-1:i+1]
2208 length = length - 2
2209 i = i - 1
Fred Drake43c93501997-12-29 21:40:35 +00002210 label_nodes[name] = hist.nodenames[-1]
2211
Fred Drakee8b46131998-02-17 05:54:46 +00002212 elif s_buf_data == 'rfc':
2213 ch.chtype = chunk_type[PLAIN]
2214 ch.data = "RFC " + s(buf, pp[i].data[0].data)
2215 del pp[i]
2216 length = length - 1
2217
Fred Drake43c93501997-12-29 21:40:35 +00002218 elif s_buf_data == 'ref':
2219 name = s(buf, pp[i].data[0].data)
2220 if label_nodes.has_key(name):
2221 pp[i].data[0].data = label_nodes[name]
2222 else:
2223 pp[i-1:i+1] = [
2224 chunk(PLAIN, ch.where,
2225 "(unknown node reference: %s)" % name)]
2226 length = length - 1
2227 print "WARNING: unknown node label", `name`
Fred Drakea4541af1997-12-29 17:19:22 +00002228
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00002229 else:
Guido van Rossum36f219d1996-09-11 21:30:40 +00002230 print "don't know what to do with keyword " + s_buf_data
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00002231
2232
Guido van Rossum95cd2ef1992-12-08 14:37:55 +00002233re_atsign = regex.compile('[@{}]')
2234re_newline = regex.compile('\n')
2235
2236def dumpit(buf, wm, pp):
2237
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00002238 global out
Guido van Rossum95cd2ef1992-12-08 14:37:55 +00002239
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00002240 i, length = 0, len(pp)
2241
2242 addspace = 0
2243
2244 while 1:
2245 if len(pp) != length:
2246 raise 'FATAL', 'inconsistent length'
2247 if i == length:
2248 break
2249 ch = pp[i]
2250 i = i + 1
2251
Guido van Rossum36f219d1996-09-11 21:30:40 +00002252 dospace = addspace
2253 addspace = 0
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00002254
Guido van Rossum36f219d1996-09-11 21:30:40 +00002255 if ch.chtype == chunk_type[CSNAME]:
2256 s_buf_data = s(buf, ch.data)
Fred Drake74a11e51998-02-26 05:52:37 +00002257## if s_buf_data == 'e':
2258## wm('\\')
2259## continue
2260## if s_buf_data == '$':
2261## wm('$')
2262## continue
Guido van Rossum36f219d1996-09-11 21:30:40 +00002263 wm('@' + s_buf_data)
2264 if s_buf_data == 'node' and \
2265 pp[i].chtype == chunk_type[PLAIN] and \
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00002266 s(buf, pp[i].data) in out.doublenodes:
2267 ##XXX doesnt work yet??
2268 wm(' ZZZ-' + zfill(`i`, 4))
Guido van Rossum36f219d1996-09-11 21:30:40 +00002269 if s_buf_data[0] in string.letters:
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00002270 addspace = 1
Guido van Rossum36f219d1996-09-11 21:30:40 +00002271 elif ch.chtype == chunk_type[PLAIN]:
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00002272 if dospace and s(buf, ch.data) not in (' ', '\t'):
2273 wm(' ')
2274 text = s(buf, ch.data)
2275 while 1:
2276 pos = re_atsign.search(text)
2277 if pos < 0:
2278 break
2279 wm(text[:pos] + '@' + text[pos])
2280 text = text[pos+1:]
2281 wm(text)
Guido van Rossum36f219d1996-09-11 21:30:40 +00002282 elif ch.chtype == chunk_type[GROUP]:
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00002283 wm('{')
2284 dumpit(buf, wm, ch.data)
2285 wm('}')
Guido van Rossum36f219d1996-09-11 21:30:40 +00002286 elif ch.chtype == chunk_type[DENDLINE]:
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00002287 wm('\n\n')
2288 while i != length and pp[i].chtype in \
Guido van Rossum36f219d1996-09-11 21:30:40 +00002289 (chunk_type[DENDLINE], chunk_type[ENDLINE]):
Guido van Rossum95cd2ef1992-12-08 14:37:55 +00002290 i = i + 1
Guido van Rossum36f219d1996-09-11 21:30:40 +00002291 elif ch.chtype == chunk_type[OTHER]:
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00002292 wm(s(buf, ch.data))
Guido van Rossum36f219d1996-09-11 21:30:40 +00002293 elif ch.chtype == chunk_type[ACTIVE]:
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00002294 wm(s(buf, ch.data))
Guido van Rossum36f219d1996-09-11 21:30:40 +00002295 elif ch.chtype == chunk_type[ENDLINE]:
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00002296 wm('\n')
Guido van Rossum36f219d1996-09-11 21:30:40 +00002297 elif ch.chtype == chunk_type[CSLINE]:
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00002298 if i >= 2 and pp[i-2].chtype not in \
Guido van Rossum36f219d1996-09-11 21:30:40 +00002299 (chunk_type[ENDLINE], chunk_type[DENDLINE]) \
2300 and (pp[i-2].chtype != chunk_type[PLAIN]
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00002301 or s(buf, pp[i-2].data)[-1] != '\n'):
Guido van Rossum95cd2ef1992-12-08 14:37:55 +00002302
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00002303 wm('\n')
2304 wm('@' + s(buf, ch.data))
2305 if i == length:
2306 raise error, 'CSLINE expected another chunk'
Guido van Rossum36f219d1996-09-11 21:30:40 +00002307 if pp[i].chtype != chunk_type[GROUP]:
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00002308 raise error, 'CSLINE expected GROUP'
2309 if type(pp[i].data) != ListType:
2310 raise error, 'GROUP chould contain []-data'
Guido van Rossum95cd2ef1992-12-08 14:37:55 +00002311
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00002312 wobj = Wobj()
2313 dumpit(buf, wobj.write, pp[i].data)
2314 i = i + 1
2315 text = wobj.data
2316 del wobj
2317 if text:
2318 wm(' ')
2319 while 1:
2320 pos = re_newline.search(text)
2321 if pos < 0:
2322 break
Fred Drake4f6d6e41998-04-17 15:28:09 +00002323 # these seem to be completely harmless, so don't warn:
2324## print 'WARNING: found newline in csline arg (%s)' \
2325## % s(buf, ch.data)
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00002326 wm(text[:pos] + ' ')
2327 text = text[pos+1:]
2328 wm(text)
2329 if i >= length or \
Guido van Rossum36f219d1996-09-11 21:30:40 +00002330 pp[i].chtype not in (chunk_type[CSLINE],
2331 chunk_type[ENDLINE], chunk_type[DENDLINE]) \
2332 and (pp[i].chtype != chunk_type[PLAIN]
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00002333 or s(buf, pp[i].data)[0] != '\n'):
2334 wm('\n')
Guido van Rossum49604d31996-09-10 22:19:51 +00002335
Guido van Rossum36f219d1996-09-11 21:30:40 +00002336 elif ch.chtype == chunk_type[COMMENT]:
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00002337 if s(buf, ch.data) and \
2338 regex.match('^[ \t]*$', s(buf, ch.data)) < 0:
Guido van Rossum36f219d1996-09-11 21:30:40 +00002339 if i >= 2 \
Fred Drake74a11e51998-02-26 05:52:37 +00002340 and pp[i-2].chtype not in (chunk_type[ENDLINE],
2341 chunk_type[DENDLINE]) \
Guido van Rossum36f219d1996-09-11 21:30:40 +00002342 and not (pp[i-2].chtype == chunk_type[PLAIN]
2343 and regex.match('\\(.\\|\n\\)*[ \t]*\n$', s(buf, pp[i-2].data)) >= 0):
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00002344 wm('\n')
2345 wm('@c ' + s(buf, ch.data))
Guido van Rossum36f219d1996-09-11 21:30:40 +00002346 elif ch.chtype == chunk_type[IGNORE]:
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00002347 pass
2348 else:
2349 try:
2350 str = `s(buf, ch.data)`
2351 except TypeError:
2352 str = `ch.data`
2353 if len(str) > 400:
2354 str = str[:400] + '...'
2355 print 'warning:', ch.chtype, 'not handled, data ' + str
Guido van Rossum95cd2ef1992-12-08 14:37:55 +00002356
2357
2358
Guido van Rossum95cd2ef1992-12-08 14:37:55 +00002359def main():
Fred Drakee8b46131998-02-17 05:54:46 +00002360 global release_version
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00002361 outfile = None
2362 headerfile = 'texipre.dat'
2363 trailerfile = 'texipost.dat'
Guido van Rossum95cd2ef1992-12-08 14:37:55 +00002364
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00002365 try:
Fred Drakee8b46131998-02-17 05:54:46 +00002366 opts, args = getopt.getopt(sys.argv[1:], 'o:h:t:v:')
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00002367 except getopt.error:
2368 args = []
Guido van Rossum95cd2ef1992-12-08 14:37:55 +00002369
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00002370 if not args:
2371 print 'usage: partparse [-o outfile] [-h headerfile]',
2372 print '[-t trailerfile] file ...'
2373 sys.exit(2)
Guido van Rossum7a2dba21993-11-05 14:45:11 +00002374
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00002375 for opt, arg in opts:
2376 if opt == '-o': outfile = arg
2377 if opt == '-h': headerfile = arg
2378 if opt == '-t': trailerfile = arg
Fred Drakee8b46131998-02-17 05:54:46 +00002379 if opt == '-v': release_version = arg
Guido van Rossum7a2dba21993-11-05 14:45:11 +00002380
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00002381 if not outfile:
2382 root, ext = os.path.splitext(args[0])
2383 outfile = root + '.texi'
Guido van Rossum7a2dba21993-11-05 14:45:11 +00002384
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00002385 if outfile in args:
2386 print 'will not overwrite input file', outfile
2387 sys.exit(2)
Guido van Rossum7a2dba21993-11-05 14:45:11 +00002388
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00002389 outf = open(outfile, 'w')
2390 outf.write(open(headerfile, 'r').read())
Guido van Rossum7a2dba21993-11-05 14:45:11 +00002391
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00002392 for file in args:
2393 if len(args) > 1: print '='*20, file, '='*20
2394 buf = open(file, 'r').read()
Fred Drakeb98cd391998-03-04 06:33:43 +00002395 chunk.buf = buf
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00002396 w, pp = parseit(buf)
2397 startchange()
2398 changeit(buf, pp)
2399 dumpit(buf, outf.write, pp)
Guido van Rossum95cd2ef1992-12-08 14:37:55 +00002400
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00002401 outf.write(open(trailerfile, 'r').read())
Guido van Rossum95cd2ef1992-12-08 14:37:55 +00002402
Guido van Rossum5f18d6c1996-09-10 22:34:20 +00002403 outf.close()
Guido van Rossum95cd2ef1992-12-08 14:37:55 +00002404
Guido van Rossum49604d31996-09-10 22:19:51 +00002405if __name__ == "__main__":
2406 main()