]> git.donarmstrong.com Git - lilypond.git/blob - scripts/auxiliar/ref_check.py
Add newlines at EOF where appropriate.
[lilypond.git] / scripts / auxiliar / ref_check.py
1
2 """
3 *** RefCheck
4
5 Flow
6   Read files
7     On @defManual manual refManual eg @defManual LM rlearning
8       Associate manual name 'manual' with reference @'refManual'{ ... }
9       Add 'refManual' to list of keywords
10     On @setManual manual set current manual name to 'manual'
11     On @include open and process new file
12     On @node add node to Nodes list with current manual name and current file name
13     On @ref add contents to References list with refManual, current manual name and current file name
14     On one of refManual keywords add contents to References list with ditto
15   Match refs and nodes
16     Process References list:
17       Check reference is contained in Nodes list with refManual in Nodes = refManual in References
18     Print results
19     
20 Known issues
21   Node names containing commas are only checked up to the comma
22   Spurious warnings "Xref should be internal" for files in /included
23
24 """
25
26
27 ##################################################
28 class CrossRefs:
29   """ Holds References and Nodes """
30   def __init__(self):
31     self.Manuals = {}
32     self.Nodes = {}
33     self.nodeNames = {}  # used to check for duplicates only
34     self.Refs = []
35     self.nodeCount = 0
36
37   def addManual(self, manualName, refManual):
38     self.Manuals[refManual] = manualName
39
40   def getRefManuals(self):
41     return self.Manuals.keys()
42
43   def getManualName(self, refManual):
44     return self.Manuals[refManual]
45
46   def addNode(self, nodeName, manualName, fileName):
47     global returnCode
48 #    print "Node: ", nodeName, " in ", manualName, " found in ", fileName
49     if manualName+"/"+nodeName in self.Nodes.keys():
50       print "Error: Duplicate nodename ",nodeName, " in ", fileName, " and ", self.Nodes[manualName+"/"+nodeName][1]
51       returnCode=1
52     self.Nodes[manualName + "/" + nodeName] = [manualName, fileName]
53     self.nodeNames[nodeName] = fileName
54
55   def addRef(self, toManualName, toHeading, inFileName):
56 #    if inFileName == "notation/vocal.itely":
57 #      print "Ref to ", toManualName, "/",toHeading, " found in ", inFileName
58     self.Refs.append([toManualName + "/" + toHeading, inFileName])
59
60   def check(self):
61     noErrors = True
62     for [refHeading, refFileName] in self.Refs:
63       try:
64         targetFileName = self.Nodes[refHeading]
65 #        if refFileName == "notation/vocal.itely":
66 #          print "ref to: ", refHeading, " in ", refFileName, " found in ", targetFileName
67       except KeyError:
68         noErrors = False
69         print "ref to: ", refHeading, " in ", refFileName, " not found"
70     if noErrors:
71       print " All references satisfied"
72     else:
73       returnCode=1
74
75 ##################################################
76 class File:
77   """ Process an included file """
78
79   # Class variables
80   CurrentManualName = ""
81   DefaultPath = ""
82   Excludes = []
83   Paths = {}
84
85   # Methods
86   def __init__(self, fileName):
87     self.fileName = fileName
88     try:
89       self.fullFileName = File.Paths[fileName] + fileName
90     except KeyError:
91       self.fullFileName = File.DefaultPath + fileName
92
93   def read(self, crossRefs):
94     """ Process File """
95
96     skip = False
97     try:
98       myfile = open(self.fullFileName, 'r')
99     except IOError:
100       print "File ", self.fullFileName, " referenced in ", File.CurrentManualName, " but not found"
101       return
102     remainderLine = ""
103     lineNo = 0
104     for line in myfile:
105       lineNo += 1
106       words = line.split()
107       if len(words) > 0:
108         if words[0] == "@ignore" or words[0] == "@macro":
109           skip = True
110         if skip and len(words) > 1:
111           if words[0] == "@end" and (words[1].find("ignore") >= 0 or words[1].find("macro") >= 0):
112             skip = False
113
114         if not skip and words[0] != "@c":
115           if words[0].find("@defManual") >= 0:
116             # Manual definition found - extract manual name and refManual string
117             manualName = words[1]
118             refManual = words[2]
119             crossRefs.addManual(manualName, refManual)
120 #            print manualName, refManual
121
122           elif words[0].find("@defaultPath") >=0:
123             File.DefaultPath = words[1]
124
125           elif words[0].find("@path") >=0:
126             File.Paths[words[1]] = words[2]
127
128           elif words[0].find("@setManual") >= 0:
129             File.CurrentManualName = words[1]
130 #            print " Checking ", File.CurrentManualName
131
132           elif words[0].find("@exclude") >=0:
133             File.Excludes.append(words[1])
134
135           elif words[0].find("@include") >= 0:
136             if words[1] not in File.Excludes:
137               currentFileName = words[1]
138 #              print "  File: ", currentFileName
139               currentFile = File(currentFileName)
140               currentFile.read(crossRefs)
141
142           elif words[0] == "@node":
143             nodeName = line[6:-1]
144             crossRefs.addNode(nodeName, File.CurrentManualName, self.fileName)
145
146           # Find references
147
148           twoLines = remainderLine + ' ' + line.strip()
149           manualRefStrings = crossRefs.getRefManuals()
150           refFound = False
151           for manualRefString in manualRefStrings:
152             toManualName = crossRefs.getManualName(manualRefString)
153             actualToManualName = toManualName
154             if toManualName == "this":
155               toManualName = File.CurrentManualName
156             refString = "@" + manualRefString + "{"
157             refStart = twoLines.find(refString)
158             if refStart >= 0:
159               refFound = True
160               if actualToManualName == File.CurrentManualName:
161                 print "Warning: should xref be internal around line ", lineNo, " in ", self.fileName, "?"
162               twoLines = twoLines[refStart:]
163               refNodeStart = twoLines.find("{") + 1
164               # TODO Need to check here for nested {}
165               refNodeEnd = twoLines.find("}")
166               refNodeEndComma = twoLines.find(",")
167               if refNodeEndComma > 0:
168                 refNodeEnd = min(refNodeEnd, refNodeEndComma)
169               if refNodeEnd >= 0:
170                 crossRefs.addRef(toManualName, twoLines[refNodeStart:refNodeEnd], self.fileName)
171                 remainderLine=twoLines[refNodeEnd+1:]
172             if refFound:
173               refFound = False
174               break
175           if not refFound:
176               remainderLine = ""
177
178     myfile.close()
179     return
180
181 topFile = File("scripts/auxiliar/ref_check.tely") # TODO get from input params
182 print "RefCheck ver 0.1"
183 returnCode=0
184 crossRefs = CrossRefs()
185 topFile.read(crossRefs)
186 crossRefs.check()
187 if returnCode > 0:
188   print "Errors found: status code: ",returnCode