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