add a CVS snapshot, to thoroughly test on the Debian side
[alioth/jupp.git] / uerror.c
1 /* $MirOS: contrib/code/jupp/uerror.c,v 1.3 2008/05/13 13:08:27 tg Exp $ */
2 /*
3  *      Compiler error handler
4  *      Copyright
5  *              (C) 1992 Joseph H. Allen
6  *
7  *      This file is part of JOE (Joe's Own Editor)
8  */
9 #include "config.h"
10 #include "types.h"
11
12 #include <stdio.h>
13
14 #include "b.h"
15 #include "bw.h"
16 #include "main.h"
17 #include "queue.h"
18 #include "tw.h"
19 #include "ufile.h"
20 #include "utils.h"
21 #include "vs.h"
22 #include "charmap.h"
23 #include "w.h"
24
25 /* Error database */
26
27 typedef struct error ERROR;
28
29 struct error {
30         LINK(ERROR) link;       /* Linked list of errors */
31         long line;              /* Target line number */
32         long org;               /* Original target line number */
33         unsigned char *file;            /* Target file name */
34         long src;               /* Error-file line number */
35         unsigned char *msg;             /* The message */
36 } errors = { { &errors, &errors} };
37 ERROR *errptr = &errors;        /* Current error row */
38
39 B *errbuf = NULL;               /* Buffer with error messages */
40
41 /* Insert and delete notices */
42
43 void inserr(unsigned char *name, long int where, long int n, int bol)
44 {
45         ERROR *e;
46
47         if (name) {
48                 for (e = errors.link.next; e != &errors; e = e->link.next) {
49                         if (!strcmp(e->file, name)) {
50                                 if (e->line > where)
51                                         e->line += n;
52                                 else if (e->line == where && bol)
53                                         e->line += n;
54                         }
55                 }
56         }
57 }
58
59 void delerr(unsigned char *name, long int where, long int n)
60 {
61         ERROR *e;
62
63         if (name) {
64                 for (e = errors.link.next; e != &errors; e = e->link.next) {
65                         if (!strcmp(e->file, name)) {
66                                 if (e->line > where + n)
67                                         e->line -= n;
68                                 else if (e->line > where)
69                                         e->line = where;
70                         }
71                 }
72         }
73 }
74
75 /* Abort notice */
76
77 void abrerr(unsigned char *name)
78 {
79         ERROR *e;
80
81         if (name)
82                 for (e = errors.link.next; e != &errors; e = e->link.next)
83                         if (!strcmp(e->file, name))
84                                 e->line = e->org;
85 }
86
87 /* Save notice */
88
89 void saverr(unsigned char *name)
90 {
91         ERROR *e;
92
93         if (name)
94                 for (e = errors.link.next; e != &errors; e = e->link.next)
95                         if (!strcmp(e->file, name))
96                                 e->org = e->line;
97 }
98
99 /* Pool of free error nodes */
100 ERROR errnodes = { {&errnodes, &errnodes} };
101
102 /* Free an error node */
103
104 static void freeerr(ERROR *n)
105 {
106         vsrm(n->file);
107         vsrm(n->msg);
108         enquef(ERROR, link, &errnodes, n);
109 }
110
111 /* Free all errors */
112
113 static void freeall(void)
114 {
115         while (!qempty(ERROR, link, &errors))
116                 freeerr(deque_f(ERROR, link, errors.link.next));
117         errptr = &errors;
118 }
119
120 /* Parse error messages into database */
121
122 /* From joe's joe 2.9 */
123
124 /* First word on line with a '.' in it.  This is the file name.  The next number after that is the line number. */
125
126 static int parseit(struct charmap *map,unsigned char *s, long int row)
127 {
128         int x, y, flg;
129         unsigned char *name = NULL;
130         long line = -1;
131         ERROR *err;
132
133         y=0;
134         flg=0;
135
136         do {
137                 /* Skip to first word */
138                 for (x = y; s[x] && !(joe_isalnum_(map,s[x]) || s[x] == '.' || s[x] == '/'); ++x) ;
139
140                 /* Skip to end of first word */
141                 for (y = x; joe_isalnum_(map,s[y]) || s[y] == '.' || s[y] == '/'; ++y)
142                         if (s[y] == '.')
143                                 flg = 1;
144         } while (!flg && x!=y);
145
146         /* Save file name */
147         if (x != y)
148                 name = vsncpy(NULL, 0, s + x, y - x);
149
150         /* Skip to first number */
151         for (x = y; s[x] && (s[x] < '0' || s[x] > '9'); ++x) ;
152
153         /* Skip to end of first number */
154         for (y = x; s[y] >= '0' && s[y] <= '9'; ++y) ;
155
156         /* Save line number */
157         if (x != y)
158                 sscanf((char *)(s + x), "%ld", &line);
159         if (line != -1)
160                 --line;
161
162         /* Look for ':' */
163         flg = 0;
164         while (s[y]) {
165                 if (s[y]==':') {
166                         flg = 1;
167                         break;
168                 }
169                 ++y;
170         }
171
172         if (name) {
173                 if (line != -1 && flg) {
174                         /* We have an error */
175                         err = (ERROR *) alitem(&errnodes, sizeof(ERROR));
176                         err->file = name;
177                         err->org = err->line = line;
178                         err->src = row;
179                         err->msg = vsncpy(NULL, 0, sc("\\i"));
180                         err->msg = vsncpy(sv(err->msg), sv(s));
181                         enqueb(ERROR, link, &errors, err);
182                         return 1;
183                 } else
184                         vsrm(name);
185         }
186         return 0;
187 }
188
189 /* Parse the error output contained in a buffer */
190
191 static long parserr(B *b)
192 {
193         P *p = pdup(b->bof);
194         P *q = pdup(p);
195         long nerrs = 0;
196
197         freeall();
198         do {
199                 unsigned char *s;
200
201                 pset(q, p);
202                 p_goto_eol(p);
203                 s = brvs(q, (int) (p->byte - q->byte));
204                 if (s) {
205                         nerrs += parseit(b->o.charmap, s, q->line);
206                         vsrm(s);
207                 }
208         } while (pgetc(p) != NO_MORE_DATA);
209         prm(p);
210         prm(q);
211         return nerrs;
212 }
213
214 BW *find_a_good_bw(B *b)
215 {
216         W *w;
217         BW *bw = 0;
218         /* Find lowest window with buffer */
219         if ((w = maint->topwin) != NULL) {
220                 do {
221                         if ((w->watom->what&TYPETW) && ((BW *)w->object)->b==b && w->y>=0)
222                                 bw = (BW *)w->object;
223                         w = w->link.next;
224                 } while (w != maint->topwin);
225         }
226         if (bw)
227                 return bw;
228         /* Otherwise just find lowest window */
229         if ((w = maint->topwin) != NULL) {
230                 do {
231                         if ((w->watom->what&TYPETW) && w->y>=0)
232                                 bw = (BW *)w->object;
233                         w = w->link.next;
234                 } while (w != maint->topwin);
235         }
236         return bw;
237 }
238
239 int parserrb(B *b)
240 {
241         BW *bw;
242         long n;
243         errbuf = b;
244         freeall();
245         n = parserr(b);
246         bw = find_a_good_bw(b);
247         if (n)
248                 joe_snprintf_1((char *)msgbuf, JOE_MSGBUFSIZE, "%ld messages found", n);
249         else
250                 joe_snprintf_0((char *)msgbuf, JOE_MSGBUFSIZE, "No messages found");
251         msgnw(bw->parent, msgbuf);
252         return 0;
253 }
254
255 int uparserr(BW *bw)
256 {
257         long n;
258         errbuf = bw->b;
259         freeall();
260         n = parserr(bw->b);
261         if (n)
262                 joe_snprintf_1((char *)msgbuf, JOE_MSGBUFSIZE, "%ld messages found", n);
263         else
264                 joe_snprintf_0((char *)msgbuf, JOE_MSGBUFSIZE, "No messages found");
265         msgnw(bw->parent, msgbuf);
266         return 0;
267 }
268
269 int unxterr(BW *bw)
270 {
271         int omid;
272
273         if (errptr->link.next == &errors) {
274                 msgnw(bw->parent, US "No more errors");
275                 return -1;
276         }
277         errptr = errptr->link.next;
278         if (!bw->b->name || strcmp(errptr->file, bw->b->name)) {
279                 if (doedit(bw, vsdup(errptr->file), NULL, NULL))
280                         return -1;
281                 bw = (BW *) maint->curwin->object;
282         }
283         omid = mid;
284         mid = 1;
285         pline(bw->cursor, errptr->line);
286         setline(errbuf, errptr->src);
287         dofollows();
288         mid = omid;
289         bw->cursor->xcol = piscol(bw->cursor);
290         msgnw(bw->parent, errptr->msg);
291         return 0;
292 }
293
294 int uprverr(BW *bw)
295 {
296         int omid;
297
298         if (errptr->link.prev == &errors) {
299                 msgnw(bw->parent, US "No more errors");
300                 return -1;
301         }
302         errptr = errptr->link.prev;
303         if (!bw->b->name || strcmp(errptr->file, bw->b->name)) {
304                 if (doedit(bw, vsdup(errptr->file), NULL, NULL))
305                         return -1;
306                 bw = (BW *) maint->curwin->object;
307         }
308         omid = mid;
309         mid = 1;
310         pline(bw->cursor, errptr->line);
311         setline(errbuf, errptr->src);
312         dofollows();
313         mid = omid;
314         bw->cursor->xcol = piscol(bw->cursor);
315         msgnw(bw->parent, errptr->msg);
316         return 0;
317 }