1 /* $Id: jump.c,v 1.6 2000/09/21 17:28:29 amura Exp $ */
2 /*
3 * jump-to-error
4 *
5 * Written by bsh, Dec 1991.
6 */
7
8 /*
9 * $Log: jump.c,v $
10 * Revision 1.6 2000/09/21 17:28:29 amura
11 * replace macro _WIN32 to WIN32 for Cygwin
12 *
13 * Revision 1.5 2000/07/25 15:04:21 amura
14 * fix filevisit() args
15 *
16 * Revision 1.4 2000/07/22 20:47:32 amura
17 * do not use excline()
18 *
19 * Revision 1.3 2000/07/18 12:38:56 amura
20 * remove some compile warning
21 *
22 * Revision 1.2 2000/06/27 01:49:43 amura
23 * import to CVS
24 *
25 * Revision 1.1 2000/06/01 05:27:47 amura
26 * Initial revision
27 *
28 */
29
30 #include "config.h"
31 #ifdef JUMPERR
32
33 #include "def.h"
34 #ifndef BSD
35 # ifndef index
36 # define index(s,c) strchr(s,c)
37 # endif
38 #endif /* BSD */
39
40 #ifdef REGEX_JAPANESE
41 #include "regex_j.h"
42 #else
43 #include "regex_e.h"
44 #endif
45 #define BYTEWIDTH 8
46
47 #ifndef R_OK /* for access() */
48 # define R_OK 4
49 #endif
50
51 #define BUFLEN 100
52
53 static struct re_pattern_buffer re_buff;
54 static char fastmap[(1 << BYTEWIDTH)];
55 static char compile_command[NLINE] = "make";
56 /* "compile" command buffer. *
57 * This variable is *NOT* buffer local, this is *
58 * global. Y.Koyanagi */
59
60 /* Regular expression for filename/linenumber in error in compilation log.
61 * It mathes
62 * filename, line 1234 or
63 * filename: 1234 or
64 * filename 1234 or
65 * filename(1234) or
66 * 1234 of filename or
67 * filename at line 1234
68 */
69 #if defined(AMIGA)
70 #define DEFAULT_REGEXP "\\(\\([^ \n]+:\\)?[^ \n]+\\(:? *\\| at line \\|, line \\|(\\)[0-9]+\\)\\|\\([0-9]+ *of *[^ \n]+\\)"
71 #elif defined(MSDOS)||defined(HUMAN68K)||defined(WIN32)
72 #define DEFAULT_REGEXP "\\(\\([a-zA-Z]:\\)?[^ :\n]+\\(:? *\\| at line \\|, line \\|(\\)[0-9]+\\)\\|\\([0-9]+ *of *[^ \n]+\\)"
73 #else
74 #define DEFAULT_REGEXP "\\([^ :\n]+\\(:? *\\| at line \\|, line \\|(\\)[0-9]+\\)\\|\\([0-9]+ *of *[^ \n]+\\)"
75 #endif
76 /*
77 #define DEFAULT_REGEXP "\\([^ :\n]+\\(:? *\\|, line \\|(\\)[0-9]+\\)\\|\\([0-9]+ *of *[^ \n]+\\|[^ \n]+ \\(at \\)*line [0-9]+\\)"
78 */
79
80 static char *grab_filename();
81
82 /*
83 *
84 */
set_regexp(pat)85 set_regexp( pat )
86 char *pat;
87 {
88 char *message;
89
90 re_buff.allocated = 40;
91 re_buff.buffer = (char *) malloc (re_buff.allocated);
92 if( re_buff.buffer == NULL ){
93 ewprintf( "Can't get %d bytes", re_buff.allocated );
94 re_buff.allocated = 0;
95 return FALSE;
96 }
97 re_buff.fastmap = fastmap;
98 re_buff.translate = NULL;
99 message = re_compile_pattern (pat, strlen(pat), &re_buff);
100 if (message != '\0') {
101 ewprintf("Regex Error: %s", message);
102 free( re_buff.buffer );
103 re_buff.allocated = 0;
104 return(FALSE);
105 }
106 re_compile_fastmap (&re_buff);
107 return TRUE;
108 }
109
parse_error_message(clp,col,namebuf,ip,parse_end)110 parse_error_message( clp, col, namebuf, ip, parse_end )
111 LINE *clp;
112 char *namebuf;
113 int *ip, *parse_end;
114 {
115 struct re_registers regs;
116 char buf[BUFLEN+1];
117 int i, len;
118 char *filename;
119
120 if( re_buff.allocated == 0 && !set_regexp( DEFAULT_REGEXP ) )
121 return FALSE;
122
123 i = re_search (&re_buff, ltext(clp), llength(clp),
124 col, llength(clp), ®s);
125 if (i < 0)
126 return FALSE;
127
128 if( parse_end ) *parse_end = regs.end[0]+1;
129 len = regs.end[0] - regs.start[0];
130 if( len > BUFLEN ) len = BUFLEN;
131 strncpy( buf, ltext(clp) + regs.start[0], len );
132 buf[len] = '\0';
133
134 for(i=len; i>0 && ISDIGIT(buf[i-1]); --i )
135 ;
136 if( i < len ){
137 /* we are looking filename-first style. */
138 *ip = atoi( &buf[i] );
139 buf[i] = '\0';
140 filename = grab_filename( buf );
141 }
142 else {
143 /* line-number-first style */
144 *ip = atoi(buf);
145 while( ISDIGIT(buf[i]) || buf[i] == ' ' || buf[i] == '\t' )
146 ++i;
147 filename = grab_filename( buf );
148 }
149 if( *filename ){
150 strcpy( namebuf, filename );
151 return TRUE;
152 }
153 return FALSE;
154 }
155
156 /*
157 * jump-to-error
158 * Parse current line as a error message, then vist correspoding source code.
159 */
jumptoerror(f,n)160 jumptoerror(f,n)
161 {
162 int lineno;
163 char buf[BUFLEN+1];
164 char *p=buf;
165 int col;
166 LINE *dlp;
167 extern int access();
168 extern int gotoline();
169 extern int filevisit(), poptofile();
170
171 dlp = curwp->w_dotp;
172 while (dlp != curbp->b_linep)
173 {
174 /* get filename and line number to visit */
175 col = 0;
176 while (col < llength(dlp) &&
177 parse_error_message(dlp, col, buf, &lineno, &col ) )
178 {
179 if (0 == access( buf, R_OK )){
180 /* ewprintf( "file:`%s' line %d", buf, lineno ); */
181 /*
182 * All the hairly works to give filename to filevisit()
183 */
184 curwp->w_flag |= WFHARD;
185 curwp->w_doto = 0;
186 curwp->w_linep = dlp;
187 curwp->w_lines = 0;
188 if (lforw(dlp) != curbp->b_linep)
189 curwp->w_dotp = lforw(dlp);
190 eargset(buf);
191 if (f&FFARG) {
192 if (!filevisit(FFRAND,0)) return FALSE;
193 } else {
194 if (!poptofile(FFRAND,0)) return FALSE;
195 }
196 gotoline( FFARG, lineno );
197 return TRUE;
198 }
199 }
200
201 dlp = lforw(dlp);
202 }
203 curwp->w_flag |= WFHARD;
204 curwp->w_doto = 0;
205 curwp->w_dotp = lback(curbp->b_linep);
206 curwp->w_linep = lback(curbp->b_linep);
207 curwp->w_lines = 0;
208
209 ewprintf( "No more errors." );
210 return FALSE;
211 }
212
213 /*
214 * extract filename removing punctuations around.
215 */
216 static char *
grab_filename(buf)217 grab_filename( buf )
218 char *buf;
219 {
220 char *p;
221 #ifdef AMIGA
222 int colon_has = FALSE;
223 #endif
224
225 if( *buf == '"' ){
226 /* "filename" */
227 for(p=buf+1; *p && *p != '"'; ++p )
228 ;
229 *p = '\0';
230 return buf+1;
231 }
232
233 p = buf;
234 #ifdef AMIGA
235 for(;*p && !index(" \t,(", *p); ++p )
236 {
237 if (*p == ':')
238 {
239 if (colon_has)
240 break;
241 else
242 colon_has = TRUE;
243 }
244 }
245 *p = '\0';
246 #else
247 # if defined(MSDOS)||defined(HUMAN68K)||defined(WIN32)
248 if (buf[1]==':' && buf[2]!='\0' && (ISUPPER(buf[0])||ISLOWER(buf[0])))
249 p += 2;
250 # endif
251 for(;*p && !index(" \t:,(", *p); ++p )
252 ;
253 *p = '\0';
254 #endif
255 return buf;
256 }
257
258 /*
259 * COMMAND: compile
260 * 91.09.14 Modified by Y.Koyanagi
261 * "compile" command.
262 */
263 /*ARGSUSED*/
compile(f,n)264 compile(f, n)
265 {
266 register BUFFER *bp, *obp;
267 register WINDOW *wp, *owp;
268 register int s;
269 char buf[NLINE],*result;
270 extern char *call_process();
271 extern int isetmark(), gotobob();
272
273 if (compile_command[0] == '\0')
274 s=eread("compile: ", buf, NLINE, EFNEW);
275 else
276 s=eread("compile: (%s) ", buf, NLINE, EFNEW, compile_command);
277 if (s == ABORT) return s;
278 if (s == TRUE) strcpy(compile_command, buf);
279
280 if ((bp = bfind("*compilation*", TRUE)) == NULL) return FALSE;
281 if ((wp = popbuf(bp)) == NULL) return FALSE;
282 if (bclear(bp) != TRUE) return FALSE;
283 obp = curbp; owp = curwp;
284 curbp = bp; curwp = wp;
285 /* cmode(0,1) */
286 if (addline(bp, compile_command) == FALSE) return FALSE;
287 update();
288 if ((result = call_process(compile_command, NULL)) == NULL)
289 return FALSE;
290 isetmark();
291 s = insertfile(result, (char *)NULL);
292 (VOID) gotobob(0, 1);
293 bp->b_dotp = wp->w_dotp;
294 bp->b_doto = wp->w_doto;
295 curbp = obp;
296 curwp = owp;
297 bp->b_flag &= ~BFCHG;
298 unlink(result);
299 return s;
300 }
301
302
303 /*
304 * COMMAND: c-next-error
305 * 91.09.14 Modified by Y.Koyanagi
306 * 00.03.30 Modified by amura for jump.c
307 * goto next error using *compilation* buffer.
308 */
309 /*ARGSUSED*/
nexterror(f,n)310 nexterror(f, n)
311 {
312 register BUFFER *bp, *obp;
313 register WINDOW *wp, *owp;
314 register int s;
315
316 if (strcmp(curbp->b_bname,"*compilation*") == 0) {
317 nextwind(FFRAND,1);
318 }
319 if ((bp = bfind("*compilation*", TRUE)) == NULL) return FALSE;
320 if ((wp = popbuf(bp)) == NULL) return FALSE;
321 obp = curbp; owp = curwp;
322 curbp = bp; curwp = wp;
323 if ((s=jumptoerror(0, 1)) != TRUE) {
324 curbp = obp;
325 curwp = owp;
326 return s;
327 }
328 return TRUE;
329 }
330
331 #endif /* JUMPERR */
332