srwhmdr@windy.dsir.govt.nz (Malcolm Robbins) (07/21/88)
I've either found a bug in VAXTPU when it does a search for an alphabetic character at the beginning of a line or, I lack some understanding about pattern matching. For example if I construct a TPU procedure to do a search for the following pattern I find it occaisionally matches an empty line. LINE_BEGIN & ANY ('ABCDEFGHIJKLMNOPQRSTUVWXYZ') In fact, given that a mismatch occurs, the problem can be restricted to searching for LINE_BEGIN & ANY ('G') say, (assuming that G is what is being matched by accident) and the same thing occurs. Furthermore if I cut the area affected and then repaste it in exactly the same position, so no difference is visible, then the problem disappears!! If, instead, I remove the ANY and search only for: LINE_BEGIN & ANY ('G') VAXTPU behaves correctly (but this is not what I want to do of course). Therefore the function ANY appears to be causing the problem. What I'd like to know is: o Is this problem caused by a lack of understanding on my part or is this a VAXTPU bug? Perhaps the mode of the search (Seek versus incremental) is causing the unexpected, but "valid" behaviour. o How can I do what I intended, which is to search for an alphabetic character at the start of a line, in a reliable way? For those of you who are raised to the challenge here's a sample TPU procedure that shows up the problem. Simply compile it and execute it from the top of a (largish) file with a number of empty lines in it. Hopefully at least one empty line will match in the unexpected way. Any replies would be greatly appreciated. In fact to show my appreciation I'll post a "detab" procedure for removing TABs in a file to this newsgroup shortly. ------------------------------ Cut Here ------------------------------ PROCEDURE any_bug LOCAL pat, rng; pat := LINE_BEGIN & ANY ('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'); LOOP ! ! Ensure we move off current position for multiple calls to any_bug ! MOVE_HORIZONTAL (1); rng := SEARCH (pat, FORWARD, EXACT); EXITIF rng = 0; ! ! If the search is successful move to it and see if an empty line has ! been matched. This should not occur but does. ! IF rng <> 0 THEN POSITION (rng); this_char := CURRENT_CHARACTER; IF this_char = "" THEN MESSAGE ('Here is an invalid match!'); RETURN; ENDIF; ENDIF; ENDLOOP; MESSAGE ('No match found'); ENDPROCEDURE ------------------------------ Cut Here ------------------------------ +-----------------------------------------------------------------------------+ | Malcolm Robbins, | | Department of Scientific and Industrial Research | | New Zealand. | | | | Internet: srwhmdr@wnv.dsir.govt.nz | | Pacnet: PSI%(05301)4600000060::SRWHMDR | +-----------------------------------------------------------------------------+
srwhmdr@windy.dsir.govt.nz (Malcolm Robbins) (07/21/88)
In article <1711@windy.dsir.govt.nz>, srwhmdr@windy.dsir.govt.nz (Malcolm Robbins) writes: > > What I'd like to know is: > > o How can I do what I intended, which is to search for an alphabetic > character at the start of a line, in a reliable way? > > Any replies would be greatly appreciated. In fact to show my appreciation > I'll post a "detab" procedure for removing TABs in a file to this newsgroup > shortly. OK, here's the detab procedure, but you can have it only if you've considered the problem I've been having :-). Simply extract the SHAR file, @ it to extract DETAB.TPU. To merge it with EVE load it, and enter EXTEND TPU. Now DETAB is an EVE command. Note that it works no matter what the tab settings are. e.g. It works for Command: SET TABS EVERY 13 Command: SET TABS AT 10 50 55 60 etc. ...................... Cut between dotted lines and save. ..................... $!............................................................................. $! VAX/VMS archive file created by VMS_SHARE V06.00 26-May-1988. $! $! VMS_SHARE was written by James Gray (Gray:OSBUSouth@Xerox.COM) from $! VMS_SHAR by Michael Bednarek (U3369429@ucsvc.dn.mu.oz.au). $! $! To unpack, simply save, concatinate all parts into one file and $! execute (@) that file. $! $! This archive was created by user SRWHMDR $! on 6-APR-1866 20:07:23.78. $! $! It contains the following 1 file: $! DETAB.TPU $! $!============================================================================== $ SET SYMBOL/SCOPE=( NOLOCAL, NOGLOBAL ) $ VERSION = F$GETSYI( "VERSION" ) $ IF VERSION .GES "V4.4" THEN GOTO VERSION_OK $ WRITE SYS$OUTPUT "You are running VMS ''VERSION'; ", - "VMS_SHARE V06.00 26-May-1988 requires VMS V4.4 or higher." $ EXIT 44 $VERSION_OK: $ GOTO START $ $UNPACK_FILE: $ WRITE SYS$OUTPUT "Creating ''FILE_IS'" $ DEFINE/USER_MODE SYS$OUTPUT NL: $ EDIT/TPU/COMMAND=SYS$INPUT/NODISPLAY/OUTPUT='FILE_IS'/NOSECTION - VMS_SHARE_DUMMY.DUMMY b_part := CREATE_BUFFER( "{Part}", GET_INFO( COMMAND_LINE, "file_name" ) ) ; s_file_spec := GET_INFO( COMMAND_LINE, "output_file" ); SET( OUTPUT_FILE , b_part, s_file_spec ); b_errors := CREATE_BUFFER( "{Errors}" ); i_errors := 0; pat_beg_1 := ANCHOR & "-+-+-+ Beginning"; pat_beg_2 := LINE_BEGIN & "+-+-+-+ Beginning"; pat_end := ANCHOR & "+-+-+-+-+ End"; POSITION ( BEGINNING_OF( b_part ) ); i_append_line := 0; LOOP EXITIF MARK( NONE ) = END_OF( b_part ); s_x := ERASE_CHARACTER( 1 ); IF s_x = "+" THEN r_skip := SEARCH( pat_beg_1, FORWARD, EXACT ); IF r_skip <> 0 THEN s_x := "" ; MOVE_HORIZONTAL( -CURRENT_OFFSET ); ERASE_LINE; ENDIF; ENDIF ; IF s_x = "-" THEN r_skip := SEARCH( pat_end, FORWARD, EXACT ); IF r_skip < > 0 THEN s_x := ""; MOVE_HORIZONTAL( -CURRENT_OFFSET ); m_skip := MARK( NONE ) ; r_skip := SEARCH( pat_beg_2, FORWARD, EXACT ); IF r_skip <> 0 THEN POSITION ( END_OF( r_skip ) ); MOVE_HORIZONTAL( -CURRENT_OFFSET ); MOVE_VERTICAL( 1 ) ; MOVE_HORIZONTAL( -1 ); ELSE POSITION( END_OF( b_part ) ); ENDIF; ERASE ( CREATE_RANGE( m_skip, MARK( NONE ), NONE ) ); ENDIF; ENDIF ; IF s_x = "V" THEN s_x := ""; IF i_append_line <> 0 THEN APPEND_LINE ; MOVE_HORIZONTAL( -CURRENT_OFFSET ); ENDIF; i_append_line := 1; MOVE_VERTICAL ( 1 ); ENDIF; IF s_x = "X" THEN s_x := ""; IF i_append_line < > 0 THEN APPEND_LINE; MOVE_HORIZONTAL( -CURRENT_OFFSET ); ENDIF ; i_append_line := 0; MOVE_VERTICAL( 1 ); ENDIF; IF s_x <> "" THEN i_errors := i_errors + 1; s_text := CURRENT_LINE; POSITION( b_errors ); COPY_TEXT ( "The following line could not be unpacked properly:" ); SPLIT_LINE ; COPY_TEXT( s_x ); COPY_TEXT( s_text ); POSITION( b_part ); MOVE_VERTICAL( 1 ); ENDIF; ENDLOOP; POSITION( BEGINNING_OF( b_part ) ); LOOP r_x := SEARCH( "`" , FORWARD, EXACT ); EXITIF r_x = 0; POSITION( r_x ); ERASE_CHARACTER( 1 ) ; IF CURRENT_CHARACTER = "`" THEN MOVE_HORIZONTAL( 1 ); ELSE COPY_TEXT( ASCII ( INT( ERASE_CHARACTER( 3 ) ) ) ); ENDIF; ENDLOOP; IF i_errors = 0 THEN SET ( NO_WRITE, b_errors, ON ); ELSE POSITION( BEGINNING_OF( b_errors ) ) ; COPY_TEXT( FAO( "The following !UL errors were detected while unpacking !AS" , i_errors, s_file_spec ) ); SPLIT_LINE; SET( OUTPUT_FILE, b_errors , "SYS$COMMAND" ); ENDIF; EXIT; $ DELETE VMS_SHARE_DUMMY.DUMMY;* $ CHECKSUM 'FILE_IS $ WRITE SYS$OUTPUT " CHECKSUM ", - F$ELEMENT( CHECKSUM_IS .EQ. CHECKSUM$CHECKSUM, ",", "failed!,passed." ) $ RETURN $ $START: $ FILE_IS = "DETAB.TPU" $ CHECKSUM_IS = 1750754036 $ COPY SYS$INPUT VMS_SHARE_DUMMY.DUMMY X! X! This procedure removes tabs and writes a message X! Xprocedure eve_detab X XLOCAL num_tabs; X XMESSAGE ("Detabbing buffer..."); Xnum_tabs := xeve$detab; XIF num_tabs = 0 THEN X MESSAGE ('No TABs in buffer') XELSE X MESSAGE (FAO ('Converted !UL tab!%S', num_tabs)) XENDIF; XENDPROCEDURE X X! X! Boolean function which returns TRUE if there are tabs in the buffer. X! This is extracted from the detab routine since it is called by the X! rectangular block cut/paste procedures and the sort procedure. X! XPROCEDURE xeve$tabs_present X XLOCAL my_tab; ! Range containing the tab character if found X X! disable messages X! XON_ERROR XENDON_ERROR; X Xmy_tab := SEARCH (ASCII(9), FORWARD); XIF my_tab = 0 THEN X my_tab := SEARCH (ASCII(9), REVERSE); XENDIF; X XIF my_tab = 0 THEN X RETURN 0; XELSE X RETURN 1; XENDIF; XENDPROCEDURE X X! X! This procedure replaces TABs with spaces and returns a count of the X! number of TABs replaced X! XPROCEDURE xeve$detab X XLOCAL dest_column, ! Column to insert spaces to X this_position, ! Save current position X count, ! A count of the number of tabs converted X timer_string, X my_tab; ! Range containing the tab character if found X XON_ERROR XENDON_ERROR; X XIF NOT xeve$tabs_present THEN X RETURN 0; XENDIF; X Xtimer_string := GET_INFO (SYSTEM, 'timed_message'); XSET (TIMER, ON, "Detabing..."); Xthis_position := MARK (NONE); XPOSITION (BEGINNING_OF (CURRENT_BUFFER)); Xcount := 0; Xtabs := GET_INFO (CURRENT_BUFFER, "tab_stops"); X XLOOP X my_tab := SEARCH (ASCII (9), FORWARD); X EXITIF my_tab = 0; X count := count + 1; X POSITION (my_tab); X ERASE (my_tab); X! X! If the tabs stops are set every n characters then tabs is an integer X! and expanding is easy. If tabs are set at differing positions the problem X! is a little more complicated X! X IF GET_INFO (tabs, "type") = INTEGER THEN X dest_column := (CURRENT_OFFSET / tabs + 1) * tabs + 1; X ELSE X dest_column := xeve$get_offset (tabs, CURRENT_OFFSET); X ENDIF; X eve$to_column (dest_column) XENDLOOP; X XPOSITION (this_position); XSET (TIMER, ON, timer_string); XRETURN count; XENDPROCEDURE X X! X! This function returns the column position of the next tab stop from X! the current position. i.e. "tabs" contains the tabs stop string and X! offset contains the current position. X! This function is used within xeve$detab so it can replace tabs with X! the right number of spaces. X! XPROCEDURE xeve$get_offset (tabs, offset) X XLOCAL end_pos, X tab_string, X local_tabs, X num; X Xlocal_tabs := tabs; XLOOP X end_pos := INDEX (local_tabs, ' '); X IF end_pos = 0 THEN X end_pos := LENGTH (local_tabs) + 1 X ENDIF; X tab_string := SUBSTR (local_tabs, 1, end_pos - 1); X num := INT (tab_string); X EXITIF num > offset; X local_tabs := SUBSTR (local_tabs, end_pos + 1, LENGTH (local_tabs)); X IF local_tabs = '' THEN X RETURN offset + 2 X ENDIF; XENDLOOP; X XRETURN num; XENDPROCEDURE X X XDEFINE_KEY ("eve_detab", KEY_NAME ("D", SHIFT_KEY)); $ GOSUB UNPACK_FILE $ EXIT +-----------------------------------------------------------------------------+ | Malcolm Robbins, | | Department of Scientific and Industrial Research | | New Zealand. | | | | Internet: srwhmdr@wnv.dsir.govt.nz | | Pacnet: PSI%(05301)4600000060::SRWHMDR | +-----------------------------------------------------------------------------+