Update the comments at the head of various .py files
[dwarf-doc.git] / dwarf5 / tools / fileio.py
1 # Copyright 2012 DWARF Debugging Information Format Committee
2
3 # All the little classes used in storing latex source data.
4 # Reads in the tex source and builds internal lists of the
5 # tokenized source.  The tokenization is adequate
6 # for our purposes, but just barely adequate.
7
8 import sys
9
10 # Keep if  "k" 
11 # Otherwise delete.
12 global keepcomments
13 keepcomments = "k"
14
15 def isIdStart(c):
16   if isIndivid(c) == "y":
17     return "n"
18   if  ord(c) >= ord('a') and ord(c) <= ord('z'):
19     return "y"
20   if  ord(c) >= ord('A') and ord(c) <= ord('Z'):
21     return "y"
22   # It is tex/latex, so backslash starts a word.
23   if c == "\\":
24     return "y"
25   if c == "_":
26     return "y"
27   return "n"
28
29 def isIdNext(c):
30   if isIndivid(c) == "y":
31     return "n"
32   if  ord(c) >= ord('a') and ord(c) <= ord('z'):
33     return "y"
34   if  ord(c) >= ord('A') and ord(c) <= ord('Z'):
35     return "y"
36   if  ord(c) >= ord('0') and ord(c) <= ord('9'):
37     return "y"
38   # This is so we allow the colon in our tags
39   # Unfortunately, this gives trouble if we have a
40   # : at the end of a DW* name on input.
41   if c == ":":
42     return "y"
43   if c == "\\":
44     return "y"
45   if c == "-":
46     return "y"
47   if c == "_":
48     return "y"
49   return "n"
50 def isIndivid(c):
51   if c == "[":
52     return "y"
53   if c == "]":
54     return "y"
55   if c == "{":
56     return "y"
57   if c == "}":
58     return "y"
59   if c == " ":
60     return "y"
61   if c == "\t":
62     return "y"
63   return "n"
64
65 class dwtoken:
66   def __init__(self):
67     self._tex = []
68     self._underbar = []
69     self._std = []
70     self._label = []
71     # Class is "id", "ind","other","none"
72     self._class = "none"
73   def insertid(self,string):
74     self._class =  "id"
75     self._tex = list(string)
76     self._underbar = self._tex
77     self._std = self._tex
78     self._label = self._tex
79   def setIndivid(self,c):
80     self._tex = [c]
81     self._underbar = [c]
82     self._std = [c]
83     self._label = [c]
84     self._class =  "ind"
85   def setInitialIdChar(self,c):
86     self._tex = [c]
87     self._class =  "id"
88   def setNextIdChar(self,c):
89     self._tex += [c]
90
91   def setInitialOther(self,c):
92     self._tex = [c]
93     self._underbar = [c]
94     self._std = [c]
95     self._label = [c]
96     self._class =  "other"
97   def setNextOther(self,c):
98     self._tex += [c]
99     self._underbar += [c]
100     self._std += [c]
101     self._label += [c]
102     self._class =  "other"
103   def finishUpId(self):
104     """ This transforms the strings from the input form into
105         the internal forms we want.
106     """
107     self._underbar = []
108     self._std = []
109     self._label = []
110     n = 0
111     # Drop \-
112     while int(n) < len(self._tex):
113       c = self._tex[n]
114       if n < (len (self._tex) - 1) and c == "\\" and self._tex[n+1] == "-":
115         n = n +2
116         continue
117       self._underbar += [c]
118       n = n +1
119     # Drop \ from \_
120     n = 0
121     while int(n) < len(self._underbar):
122       c = self._underbar[n]
123       if n < (len (self._underbar) - 1) and c == "\\" and self._underbar[n+1] == "_":
124         n = n +1
125         continue
126       self._std += [c]
127       n = n +1
128     # Drop  underbar
129     n = 0
130     while int(n) < len(self._std):
131       c = self._std[n]
132       if  c == "_":
133         n = n +1
134         continue
135       self._label += [c]
136       n = n +1
137
138   def dwprintquotedshortform(self,d):
139       print "'",self.shortform(d),"'",
140   def shortform(self,d):
141       return ''.join(d)
142   def dwprint(self):
143     if self._class == "ind":
144       print self._class, 
145       self.dwprintquotedshortform(self._tex)
146       print ""
147     else:
148       # This prints the token with end-line oddly.
149       print self._class, 
150       self.dwprintquotedshortform(self._tex)
151       self.dwprintquotedshortform(self._underbar)
152       self.dwprintquotedshortform(self._std)
153       self.dwprintquotedshortform(self._label)
154       print ""
155   def dwwrite(self,outfile):
156     for x in self._tex:
157       outfile.write(x)
158
159 class  dwline:
160   """using an input line, create a list of tokens for the line.
161      Legal class transitions in tokenize() are:
162      none->other
163      none->id
164      none->ind
165      other->ind
166      other->id
167      id->ind
168      id->other
169   """
170   def __init__(self):
171     # list of dwtoken.
172     self._toks = []
173
174   
175   def tokenize(self,rec):
176     """using an input line, create a list of tokens for the line.
177        Legal class transitions in tokenize() are:
178        none->other
179        none->id
180        none->ind
181        other->ind
182        other->id
183        id->ind
184        id->other
185     """
186     dwclass = "none"
187     combotok = dwtoken()
188     charnum= -1 
189     global keepcomments
190     for c in rec:
191       charnum = charnum +1
192       if keepcomments == "d" and c == "%" and ( charnum == 0 or rec[charnum - 1] != "\\" ):  
193         # Not keeping comments. We drop % and following to end of line 
194         # unless preceeded by \ 
195         break
196
197       if c == "\n" or c == "\r":
198           # Just drop these for now. Allowing them
199           # would not be harmful.
200           continue
201       elif dwclass == "none" or dwclass == "ind":
202         if isIndivid(c) == "y":
203           a = dwtoken()
204           a.setIndivid(c);
205           self._toks += [a]
206           continue
207         if isIdStart(c) == "y":
208           combotok.setInitialIdChar(c)
209           dwclass = "id"
210           continue
211         # is "other"
212         combotok.setInitialOther(c)
213         dwclass = "other"
214         continue
215       elif dwclass == "id": 
216         if isIdNext(c) == "y":
217           combotok.setNextIdChar(c)
218           continue
219         if isIndivid(c) == "y":
220           combotok.finishUpId()
221           self._toks += [combotok]
222           combotok = dwtoken()
223           a = dwtoken()
224           a.setIndivid(c);
225           dwclass = "ind"
226           self._toks += [a]
227           continue
228         # Other class input, other starts here.
229         combotok.finishUpId()
230         self._toks += [combotok]
231         combotok = dwtoken()
232         combotok.setInitialOther(c);
233         dwclass = "other"
234         continue
235       elif dwclass == "other":
236         if isIndivid(c) == "y":
237           self._toks += [combotok]
238           combotok = dwtoken()
239           a = dwtoken()
240           a.setIndivid(c);
241           dwclass = "ind"
242           self._toks += [a]
243           continue
244         if isIdStart(c) == "y":
245           self._toks += [combotok]
246           combotok = dwtoken()
247           combotok.setInitialIdChar(c);
248           dwclass = "id"
249           continue
250         combotok.setNextOther(c);
251         continue
252       # Else case impossible.
253      
254     #Finish up final non-empty other or id token
255     if dwclass == "id":
256       combotok.finishUpId()
257       self._toks += [combotok]
258       dwclass = "none"
259     if dwclass == "other":
260       self._toks += [combotok]
261       dwclass = "none"
262   def dwprint(self,linenum):
263     print "Number of tokens in line ",linenum," : ",len(self._toks)
264     if len(self._toks) == 0:
265       #Just print an empty line.
266       print ""
267     else:
268       for t in self._toks:
269         t.dwprint()
270   def dwwrite(self, outfile, linenum):
271     for t in self._toks:
272       t.dwwrite(outfile)
273     outfile.write("\n")
274   def dwtransformline(self,callfunc,myfile,lnum):
275     toks = callfunc(self._toks,myfile,lnum)
276     self._toks = toks
277     
278
279 class dwfile:
280   def __init__(self,name):
281     # list of dwline.
282     self._name = name
283     # Name of the file.
284     self._lines = []
285     try:
286       file = open(name,"r");
287     except IOError, message:
288       print >> sys.stderr , "File could not be opened: ", name
289       sys.exit(1)
290     while 1:
291       try:
292         rec = file.readline()
293       except EOFError:
294         break
295       if len(rec) < 1:
296         # eof
297         break
298
299       aline = dwline()
300       aline.tokenize(rec)
301       self._lines += [aline]
302
303   def dwprint(self):
304     print "Number of lines in ", self._name, ":  ",len(self._lines)
305     lnum = 1
306     for l in self._lines:
307        l.dwprint(lnum)
308        lnum = lnum + 1
309   def dwwrite(self):
310     # The lnum is just for debugging messages.
311
312     outname = self._name + ".out"
313     print outname
314     try:
315       outfile = open(outname,"w");
316     except IOError, message:
317       print >> sys.stderr , "Output File could not be opened: ", name
318       sys.exit(1)
319     lnum = 1
320     for l in self._lines:
321       l.dwwrite(outfile,lnum)
322       lnum = lnum + 1
323   def dwtransformline(self,callfunc,myfile):
324     lnum=1
325     for l in self._lines:
326       l.dwtransformline(callfunc,myfile,lnum)
327       lnum = lnum + 1
328     
329
330
331 class dwfiles:
332   def __init__(self):
333     # list of dwfile.
334     self._files = []
335
336   def addFile(self,name):
337     f = dwfile(name)
338     self._files += [f]
339     
340   def dwprint(self):
341     print "Number of files: ",len(self._files);
342     for f in self._files:
343       f.dwprint()
344   def dwwrite(self):
345     for f in self._files:
346       f.dwwrite()
347   def dwtransformline(self,callfunc):
348     for f in self._files:
349       f.dwtransformline(callfunc,f)
350
351
352 def setkeepordeletecomments(val):
353   """ Pass in "k" or "d" to keep or delete comments, respectively """
354   global keepcomments
355   keepcomments = val
356
357 def readFilelist(filelist):
358   dwf = dwfiles()
359   for f in filelist:
360     dwf.addFile(f)
361   return dwf
362