]> git.donarmstrong.com Git - lilypond.git/blob - scripts/auxiliar/ref_check.py
Add '-dcrop' option to ps and svg backends
[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 "\\" in nodeName:
50       returnCode = 1
51       print "nodeName: ", nodeName, " in ", fileName, " contains backslash"
52     if manualName+"/"+nodeName in self.Nodes.keys():
53       print "Error: Duplicate nodename ",nodeName, " in ", fileName, " and ", self.Nodes[manualName+"/"+nodeName][1]
54       returnCode=1
55     self.Nodes[manualName + "/" + nodeName] = [manualName, fileName]
56     self.nodeNames[nodeName] = fileName
57
58   def addRef(self, toManualName, toHeading, inFileName):
59     global returnCode
60     if "\\" in toHeading:
61       returnCode = 1
62       print "ref to: ", toHeading, " in ", inFileName, " contains backslash"
63 #    if inFileName == "notation/vocal.itely":
64 #      print "Ref to ", toManualName, "/",toHeading, " found in ", inFileName
65     self.Refs.append([toManualName + "/" + toHeading, inFileName])
66
67   def check(self):
68     noErrors = True
69     for [refHeading, refFileName] in self.Refs:
70       try:
71         targetFileName = self.Nodes[refHeading]
72 #        if refFileName == "notation/vocal.itely":
73 #          print "ref to: ", refHeading, " in ", refFileName, " found in ", targetFileName
74       except KeyError:
75         noErrors = False
76         print "ref to: ", refHeading, " in ", refFileName, " not found"
77     if noErrors:
78       print " All references satisfied"
79     else:
80       returnCode=1
81
82 ##################################################
83 class File:
84   """ Process an included file """
85
86   # Class variables
87   CurrentManualName = ""
88   DefaultPath = ""
89   Excludes = []
90   Paths = {}
91
92   # Methods
93   def __init__(self, fileName):
94     self.fileName = fileName
95     try:
96       self.fullFileName = File.Paths[fileName] + fileName
97     except KeyError:
98       self.fullFileName = File.DefaultPath + fileName
99
100   def read(self, crossRefs):
101     """ Process File """
102
103     skip = False
104     try:
105       myfile = open(self.fullFileName, 'r')
106     except IOError:
107       print "File ", self.fullFileName, " referenced in ", File.CurrentManualName, " but not found"
108       return
109     remainderLine = ""
110     lineNo = 0
111     for line in myfile:
112       lineNo += 1
113       words = line.split()
114       if len(words) > 0:
115         if words[0] == "@ignore" or words[0] == "@macro":
116           skip = True
117         if skip and len(words) > 1:
118           if words[0] == "@end" and (words[1].find("ignore") >= 0 or words[1].find("macro") >= 0):
119             skip = False
120
121         if not skip and words[0] != "@c":
122           if words[0].find("@defManual") >= 0:
123             # Manual definition found - extract manual name and refManual string
124             manualName = words[1]
125             refManual = words[2]
126             crossRefs.addManual(manualName, refManual)
127 #            print manualName, refManual
128
129           elif words[0].find("@defaultPath") >=0:
130             File.DefaultPath = words[1]
131
132           elif words[0].find("@path") >=0:
133             File.Paths[words[1]] = words[2]
134
135           elif words[0].find("@setManual") >= 0:
136             File.CurrentManualName = words[1]
137 #            print " Checking ", File.CurrentManualName
138
139           elif words[0].find("@exclude") >=0:
140             File.Excludes.append(words[1])
141
142           elif words[0].find("@include") >= 0:
143             if words[1] not in File.Excludes:
144               currentFileName = words[1]
145 #              print "  File: ", currentFileName
146               currentFile = File(currentFileName)
147               currentFile.read(crossRefs)
148
149           elif words[0] == "@node":
150             nodeName = line[6:-1]
151             crossRefs.addNode(nodeName, File.CurrentManualName, self.fileName)
152
153           # Find references
154
155           twoLines = remainderLine + ' ' + line.strip()
156           manualRefStrings = crossRefs.getRefManuals()
157           refFound = False
158           for manualRefString in manualRefStrings:
159             toManualName = crossRefs.getManualName(manualRefString)
160             actualToManualName = toManualName
161             if toManualName == "this":
162               toManualName = File.CurrentManualName
163             refString = "@" + manualRefString + "{"
164             refStart = twoLines.find(refString)
165             if refStart >= 0:
166               refFound = True
167               if actualToManualName == File.CurrentManualName:
168                 print "Warning: should xref be internal around line ", lineNo, " in ", self.fileName, "?"
169               twoLines = twoLines[refStart:]
170               refNodeStart = twoLines.find("{") + 1
171               # TODO Need to check here for nested {}
172               refNodeEnd = twoLines.find("}")
173               refNodeEndComma = twoLines.find(",")
174               if refNodeEndComma > 0:
175                 refNodeEnd = min(refNodeEnd, refNodeEndComma)
176               if refNodeEnd >= 0:
177                 crossRefs.addRef(toManualName, twoLines[refNodeStart:refNodeEnd], self.fileName)
178                 remainderLine=twoLines[refNodeEnd+1:]
179             if refFound:
180               refFound = False
181               break
182           if not refFound:
183               remainderLine = ""
184
185     myfile.close()
186     return
187
188 topFile = File("scripts/auxiliar/ref_check.tely") # TODO get from input params
189 print "RefCheck ver 0.1"
190 returnCode=0
191 crossRefs = CrossRefs()
192 topFile.read(crossRefs)
193 crossRefs.check()
194 if returnCode > 0:
195   print "Errors found: status code: ",returnCode