/* This extension was designed with Microsoft Visual C++ version 6 in mind. It may be * possible to modify this to work with other versions of VC, but I can't check that. * There's an option under Tools->Options, on the Build pane, called "Write Build * Log (.plg)". This appears to be checked by default, but you may want to check it. * What it does, is cause VC to create a file called "(name-of-project).plg" in your main * project directory. This file contains all listing of all the inputs to the compiler * and linker, and the entire list of build errors. What the commands in this module * do is to read this file into a buffer so that next-error can be used to navigate them. * * This also adds a line to the session file to remember the value of plg-file-name, and * modifies attaches to next_position and previous_position to get the next or previous * vc error, if next-vc-error was the last grep/make command run. Reading a session that * doesn't have a plg file save in it is harmless; reading one with a plg file into an epsilon * that doesn't have this extension in it is benign (the line that stores the plg file name * will appear at the top of the "-oldresp" buffer). * * Commands: * next-vc-error * Load in the file given by "plg-file-name" into the "-vc-error-file" buffer (if it's * been modified), then run next-error. This works just like next-error (you * can give it an argument to skip some messages, etc). If clear-process-buffer is * nonzero, will replace the contents of "-vc-error-file" with any modified content, * otherwise will just add it onto the end of that buffer. * change-vc-error-file * like find-file, but stores the filename into "plg-file-name" instead of loading * it. Doesn't call next-vc-error. Alternatively, you can just use set-variable * to change the value of "plg-file-name" to the file you want. * load-vc-error-file * runs change-vc-error-file, then next-vc-error. * view-vc-errors * View the list of errors from the PLG file (like view-process). * * * Glenn Dill * gdill@icubed.com * * Insert the usual legal-type disclaimer here. * * Version 1.00 Dec 1, 1998 * Initial release * Version 1.01 Dec 2, 1998 * Added in enhancements listed in v1.00, using some input from Lugaru. * Version 1.02 Dec 4, 1998 * Fixed bug where it wouldn't read in the plg file if PLG_BUFFER was killed. * Added in a modified version of view_process to be able to view the PLG_BUFFER * if that's where errors last came from. * Added view_vc_errors() command. */ #include "eel.h" #include "proc.h" // for clear_process_buffer user char plg_file_name[FNAMELEN]; zeroed struct file_info last_plg_time; #define PLG_BUFFER "-vc-error-file" #define GREP_WAS_VC_ERROR 101 // Value to store in _last_was_grep var command next_vc_error() { struct file_info new_plg_time; // Get the .plg file name if (*plg_file_name == 0) { change_vc_error_file(); if (*plg_file_name == 0) return 0; } // Read it in, automatically replacing what's here if (check_file(plg_file_name, &new_plg_time) == CHECK_FILE) { // The file exists. See if it changed. If the buffer we're using is gone, // always read it back in. if (!exist(PLG_BUFFER) || compare_dates(&last_plg_time, &new_plg_time) != 0) { // The file changed, read it in again. char *oldbuf = bufname; memcpy(&last_plg_time, &new_plg_time, sizeof(last_plg_time)); create(PLG_BUFFER); if (clear_process_buffer) zap(PLG_BUFFER); bufname = PLG_BUFFER; point = size(); // Go to end set_error_spot(); save_var point; if (do_insert_file(plg_file_name, FILETYPE_AUTO)) { error("Can't find %s", plg_file_name); return 0; } say("Modified %s read from disk.", plg_file_name); modified = 0; bufname = oldbuf; } do_next_error(iter); _last_was_grep = GREP_WAS_VC_ERROR; iter = 1; } else { // Else file isn't a file error("%s: Not a file or doesn't exist.", plg_file_name); } return 1; } command change_vc_error_file() { // Pretty much just copied from files.e::find_file() char fname[FNAMELEN]; strcpy(fname, plg_file_name); if (use_common_file_dialog()) { int flags = 0; *plg_file_name = 0; if (!use_common_open_file_dlg(fname, "Open VC Error file", &flags, 0)) return 0; } else get_file(fname, "VC error file", plg_file_name); check_abort(); last_plg_time.year = 0; // 1980 - force reading in the new file strcpy(plg_file_name, fname); return 1; } command load_vc_error_file() { if (change_vc_error_file()) next_vc_error(); return; } new_plg_make_session_hook(b) { buf_printf(b, "PLG: %s\n", plg_file_name); plg_make_session_hook(b); } REPLACE_FUNC("plg", "make-session-hook") new_plg_restore_session_hook(b) { int where_we_were = point; char file[FNAMELEN + 6]; grab_line(b, file); // Grab the newline that was left from previous operation in SESSION.E //if (curchar() == '\n') ++point; // Skip trailing newline that was left from prev operation in SESSION.E grab_line(b, file); if (!strncmp(file, "PLG: ", 5)) strcpy(plg_file_name, file + 5); else point = where_we_were; plg_restore_session_hook(b); } REPLACE_FUNC("plg", "restore-session-hook") #if 0 command next_position() /*on cx_tab[CTRL('N')]*/ { if (_last_was_grep == GREP_WAS_VC_ERROR) next_vc_error(); else if (_last_was_grep) next_match(); else next_error(); } command previous_position() /*on cx_tab[CTRL('P')]*/ { if (_last_was_grep == GREP_WAS_VC_ERROR) { iter = -iter; // Go backwards next_vc_error(); } else if (_last_was_grep) previous_match(); else previous_error(); } #else command new_plg_next_position() { if (_last_was_grep == GREP_WAS_VC_ERROR) next_vc_error(); else plg_next_position(); } command new_plg_previous_position() { if (_last_was_grep == GREP_WAS_VC_ERROR) { iter = -iter; // Go backwards next_vc_error(); } else plg_previous_position(); } REPLACE_FUNC("plg", "next-position") REPLACE_FUNC("plg", "previous-position") #endif #if 1 // Modified version of view_process - will view PLG_BUFFER if that was the last one used // // Possible enhancement: // Change this to view from wherever the error spot is (so that view_error_spot would be // a better name). // command view_process() /*on reg_tab[FSHIFT(3)]*/ // put up a list of errors, { // let user select one, and go there int w = window_handle, win, buf, pos; char *buf_to_view = PROCBUF; char restore_grep = 0; // View vc errors if that buffer exists and that's where the last error came from or there's // no process buffer. if (exist(PLG_BUFFER) && (_last_was_grep == GREP_WAS_VC_ERROR || !exist(PROCBUF))) { buf_to_view = PLG_BUFFER; restore_grep = 1; } tiled_only(); if (!exist(buf_to_view)) error("No process buffer to read errors from."); save_var menu_width = screen_cols - _view_left - _view_right; save_var _doing_input = DI_LINEINPUT; save_var bufname = buf_to_view; if (spot_to_buffer(error_spot) != bufnum) { pos = 0; set_error_spot(); } else pos = *error_spot; win = new_menu(buf = tmp_buf()); grab_buffer(name_to_bufnum(buf_to_view)); point = pos; to_begin_line(); window_title(win, BTOP, TITLECENTER, " Compiler Errors "); window_to_fit(screen_lines - 7); save_var _window_flags |= HIGHLIGHT_LINE; save_var search_in_menu = 0; save_var display_column = -1; // ensure all of msg is visible if (is_gui && want_gui_prompts) { one_window_to_dialog("Select an error message", win, "To Error", "Cancel", ""); } else say("Select an error message and press ."); set_read_only(1); select_menu_item(0, win, w, 0); bufnum = buf; pos = point; bufname = buf_to_view; buf_delete(buf); check_abort(); point = pos; set_error_spot(); ungot_key = -1; restore_vars(); do_next_error(0); if (restore_grep) _last_was_grep = GREP_WAS_VC_ERROR; } command view_vc_errors() { _last_was_grep = GREP_WAS_VC_ERROR; view_process(); } #endif