]> git.lyx.org Git - lyx.git/blob - lib/scripts/listerrors
326702b3f376556f96820ae6bdd8188d2ace7e92
[lyx.git] / lib / scripts / listerrors
1 #!/usr/bin/python
2 """reformat noweb and compiler errors for LyX.
3
4 Expects to read from stdin and output to stdout.
5 """
6
7 __author__ = "Kayvan A. Sylvan <kayvan@sylvan.com>"
8 __date__ = "$Date: 2002/03/25 23:29:30 $"
9 __version__ = "$Revision: 1.2 $"
10 __credits__ = """Edmar Wienskoski Jr. <edmar-w-jr@technologist.com>
11     original Literate support for LyX.
12 Bernard Michael Hurley <berhardh@westherts.ac.uk>
13     modifications to original listerrors."""
14 __copyright__ = "Copyright 2002 - The LyX team."
15
16 import sys, string
17
18 def write_error(msg, tool = "noweb", line_number = 1):
19   """Write out the given message in TeX error style.
20
21   called like: write_error(msg, tool, line_number)."""
22   print "! Build Error: ==> %s ==>\n" % (tool),
23   print " ...\n\nl.%d ...\n" % (line_number),
24   if type(msg) == type("str"): # simple string
25     print msg
26   else: # some kind of list (sequence or tuple)
27     for m in msg:
28         if m != "": print m,
29     print
30
31 __lines = [] # lines pushed back
32
33 def getline(file = sys.stdin):
34   """read a line from internal stack or from file.
35
36   optional file argument defaults to sys.stdin."""
37   global __lines
38   lines = __lines
39   if lines:
40     line = lines.pop()
41   else:
42     line = file.readline()
43   return line
44
45 def pushline(line):
46   "push a line onto the pushback stack."
47   global __lines
48   lines = __lines
49   lines.append(line)
50
51 def main():
52   """Entry point for listerrors. Takes no options.
53
54   Reads stdin and writes to stdout. Filter errors"""
55
56   while 1:
57     line = getline()
58     if line == "": break
59     try_patterns_dispatch = [ noweb_try, gcc_try, xlc_try ]
60     for predicate in try_patterns_dispatch:
61       if predicate(line): break
62 def noweb_try(line):
63   """see if line is a noweb error.
64
65   Returns 1 on success, 0 otherwise. Outputs on stdout."""
66   retval = 0
67   if string.find(line, ": unescaped << in documentation chunk") != -1:
68     line_parts = string.split(line, ':')
69     num_str = line_parts[1]
70     num_len = len(num_str)
71     i = 0
72     while i < num_len and (num_str[i] in string.digits): i = i + 1
73     if i == num_len:
74       write_error(":" + line_parts[2], "noweb", int(num_str))
75       retval = 1
76   if (not retval):
77     left = string.find(line, "<<")
78     if (left != -1) and ((left + 2) < len(line)) and \
79        (string.find(line[left+2:], ">>") != -1):
80       write_error(line, "noweb");
81       retval = 1;
82   if (not retval):
83     msgs_to_try = ("couldn't open file",
84       "couldn't open temporary file",
85       "error writing temporary file",
86       "ill-formed option",
87       "unknown option",
88       "Bad format sequence",
89       "Can't open output file",
90       "Can't open temporary file",
91       "Capacity exceeded:",
92       "Ignoring unknown option -",
93       "This can't happen:",
94       "non-numeric line number in")
95     for msg in msgs_to_try:
96       if string.find(line, msg) != -1:
97         write_error(line, "noweb")
98         retval = 1
99         break
100   return retval
101
102 def gcc_try(line):
103   """See if line is a gcc error. Read ahead to handle all the lines.
104
105   Returns 1 on success, 0 otherwise. Outputs on stdout."""
106   retval = 0
107   first_space = string.find(line, ' ')
108   if first_space > 1: # The smallest would be "X: "
109     if line[first_space - 1] == ':':
110       header_to_see = line[:first_space - 1]
111       next_line = getline()
112       if next_line and next_line[:first_space - 1] == header_to_see:
113         num_end = first_space
114         while next_line[num_end] in string.digits: num_end = num_end + 1
115         if num_end > first_space: # good!
116           num_str = next_line[first_space:num_end]
117           msgs = [line[first_space:]]
118           msgs.append(next_line[num_end + 1:])
119           header_to_see = next_line[:num_end]
120           next_line = getline()
121           while next_line and next_line[:num_end] == header_to_see:
122             msgs.append(next_line[num_end + 1:])
123             next_line = getline()
124           if next_line: pushline(next_line)
125           write_error(msgs, "gcc", int(num_str))
126           retval = 1
127         else: # oops! Not a gcc error.
128           pushline(next_line)
129       elif next_line:
130         pushline(next_line) # return this line to input stream
131   return retval
132
133 def xlc_try(line):
134   """see if line is an xlc error.
135
136   Returns 1 on success, 0 otherwise. Outputs on stdout."""
137   retval = 0
138   if line[0] == '"': # This is the first character of all xlc errors
139     next_quote = string.find(line, '"', 1)
140     first_space = string.find(line, ' ')
141     if (next_quote != -1) and (first_space > next_quote): # no space inisde quotes
142       if line[first_space - 1:first_space + 6] == ", line ":
143         num_start = num_end = first_space + 6
144         while line[num_end] in string.digits: num_end = num_end + 1
145         if num_end > num_start:
146           write_error(line, "xlc", int(line[num_start : num_end]))
147           retval = 1
148   return retval
149   
150
151 if __name__ == "__main__":
152   main()