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), &regs);
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