Platform Dependencies
OPEN_INFILE 1 '\me10\help'
So you might think the variable File1 is not really necessary. The advantage of using a variable such as File1 is that we can quickly modify our macro to read a file other than C:\Program Files\PTC\Creo Elements\Direct Drafting [version]\help. All we must do is alter the line:
LET File1 '\me10\help'
If we do not use a variable such as File1, then we must search through our macro and replace every occurrence of \me10\help with the full path name of the new file. Our macro is very short, so this would be easy. In a longer macro, this takes time.
OPEN_OUTFILE 2 DEL_OLD File2
Open File2 for writing. The file descriptor is 2. If the file already exists, it will be overwritten because of the DEL_OLD instruction.
LET Flag 0
Flag is a variable that will have a value of either 1 or 0, depending on which of two branches is taken on each pass through the macro. A variable that shows a state or condition is often called a flag, which is why we have named it Flag. The use of Flag will become clearer later. This line initializes the value of Flag to 0.
LOOP
Start a loop. This loop will continue until a later EXIT_IF statement is satisfied, or END_LOOP is executed.
READ_FILE 1 Filestring1
Read the file whose file descriptor is 1. This means read File1, which is /me10/help. If a file has been newly opened, but not read, the file pointer points to the first record in the file. The READ_FILE function treats each complete line as a record, so the READ_FILE command reads the first line of the file and then advances the file pointer so that it points to the next record. The next time the same file is read, the READ_FILE command reads the second line, and so on. If you are searching a file several times, and you want the macro to start the search at the beginning of the file each time, you must use the OPEN_INFILE statement before each READ_FILE statement so that the file pointer points to the first line of the file.
EXIT_IF (Filestring1='END-OF-FILE')
Every file has an end-of-file marker. The actual marker depends on the operating system, but is often the null character. If the macro detects this end of file marker, it will exit from the current loop.
LET First_char (SUBSTR Filestring1 1 1)
Find the substring that starts at position 1 in the line, and has length 1. In other words, find the first character in the line.
As an example of substrings, let's assume Filestring1 was:
Have a nice day!
If our program statement was:
LET Substring1 (SUBSTR Filestring1 3 6)
then Substring1 would be ve a n.
IF (First_char='^')
If the first character is ^, execute the following statements until the matching ELSE_IF, ELSE, or END_IF. (The matching ELSE occurs 14 program lines later.)
If the first character is not ^, jump to the first statement after the matching ELSE.
IF (Flag = 0)
If the value of Flag is 0, execute the following statements until the matching ELSE_IF, ELSE, or END_IF. There is no ELSE_IF or ELSE. The matching END_IF occurs 12 program lines later.
(We have not yet reached the point where we can explain the purpose of Flag.)
LET line_position (POS Filestring1 ' ')
As mentioned earlier, if a line starts with ^ and has only one keyword in the line, the line will contain no blanks. If there is more than one keyword, the keywords will be separated by blanks. (We use ' ' to indicate one blank. Two blanks would be ' ' and so on.) The purpose of the program statement is to find out if the line contains blanks. The POS function gives the position in a string (first argument) of the first occurrence of a substring (second argument). As an example, the current line from the help file could be:
^CURRENT_DIRECTORY CD CURRENT DIRECTORY TM_FILE_2 SM_FILE_2
Here, the first argument is the complete line beginning with ^CURRENT_DIRECTORY and ending with SM_FILE_2. The second argument is ' '. So, Line_pos will be 19.
The current line could be:
^AUTO_NEW_SCREEN
Here, the value of Line_pos is 0. Each line ends with a linefeed character so there can be no blanks in this line.
LET String_length (LEN Filestring1)
This statement computes the length of the complete line. If the line is:
^AUTO_NEW_SCREEN
then the value of String_length is 16.
When we look at the next program line, we will see why we need the length of the string.
LET First_string (SUBSTR Filestring1 2 (String_length-1))
We have seen SUBSTR before. This statement will extract the substring starting at position 2 in the string, and having length String_length-1. If the string is:
^AUTO_NEW_SCREEN
then First_string is AUTO_NEW_SCREEN. In other words, the ^ has been stripped from the beginning of the line. AUTO_NEW_SCREEN can now be written to a file.
WRITE_FILE 2 First_string
Append First_string to the file whose file descriptor is 2. This file is \john\keywords.out. First_string will be treated as a complete line in this file.
LET Flag 1
We see that if a line is written to the output file, we set Flag to 1. If you examine the rest of the code carefully, you will see that if a line is read from File1, but not written to File2, then Flag is set to 0.
Why do we want to do this? Remember that we want to extract, from each section, the first string that is preceded by ^. For example, in the next section from the help file, we want to extract CANCEL, but not ABORT or Meview_cancel:
=======================================================

^CANCEL ESC STOP INTERRUPT BREAK
^ABORT
^Meview_cancel

CANCEL command
.
.
.
=======================================================
For clarity, here is a stripped-down version of our macro, containing only read and write statements, and statements referring to Flag:
LET Flag 0
LOOP
READ_FILE 1 Filestring1
...
IF (First_char='^')
IF (Flag = 0)
IF ...
...
WRITE_FILE 2 First_string
LET Flag 1
ELSE
...
WRITE_FILE 2 First_string
LET Flag 1
END_IF
END_IF
ELSE
LET Flag 0
END_IF
END_LOOP
After the READ_FILE statement, there are four possible conditions:
1. First_char equals ^, Flag equals 0.
A keyword is written to file. Flag set to 1.
2. First_char equals ^, Flag equals 1.
Nothing written to file. Flag set to 0.
3. First_char not equal to ^, Flag equals 0.
Nothing written to file. Flag set to 0.
4. First_char not equal to ^, Flag equals 1.
Nothing written to file. Flag set to 0.
So we see that if First_char is not ^, nothing gets written to file. This is fine. It means a string that is not a keyword cannot be written to file.
The only time anything gets written to file is when First_char is ^ and Flag is 0. Now, here is the important point: the only way Flag can be 0 is if the previous line did not begin with ^. If the previous line began with ^, then Flag would be 1. This means that if two or more consecutive lines begin with ^, only the keyword on the first of these lines will be written to file.
If Flag is 1, the only way it can be reset to 0 is to read a line that does not begin with ^.
Have you noticed that we only need one statement Let Flag 1? It would be placed after the first END_IF statement in the macro. By using two statements, and placing each statement after a WRITE_FILE statement, we are emphasizing that Flag is only set to 1 if something is written to the file.
ELSE
If there are blanks in the line, the code after the ELSE is executed.
LET First_string (SUBSTR Filestring1 2 (Line_pos-2))
In this branch, the first keyword in the line will have ^ in front of it, and a blank after it. The keyword therefore starts at position 2, and its length will be Line_pos-2. Let's assume the line is:
^CURRENT_DIRECTORY CD CURRENT DIRECTORY TM_FILE_2 SM_FILE_2
The keyword we want to extract is CURRENT_DIRECTORY. The position of the first blank in the line is 19. The length of CURRENT_DIRECTORY is 19-2 or 17.
WRITE_FILE 2 First_string
LET Flag 1
First_string is written to the output file, and Flag is set to 1.
END_IF
The closing END_IF for IF (Line_pos = 0).
END_IF
The closing END_IF for IF (Flag = 0).
ELSE
If First_char is not ^, the code after the ELSE is executed.
LET Flag 0
Flag is set to 0 if a line is read from the help file but not printed to the output file.
We're now getting to the end of our macro. The last few lines are:
END_IF
The closing END_IF for IF (First_char = '^').
END_LOOP
The closing statement for the loop.
CLOSE_FILE 1
CLOSE_FILE 2
The CLOSE_FILE statements correspond to the OPEN_INFILE and OPEN_OUTFILE statements at the start of the macro.
As a matter of good programming practice, close all files that are opened by your macro. If you don't close a file, it remains open until the next user does an OPEN_INFILE on this file. The operating system then closes the file before opening it for the next user. If no one uses the file, it remains open. However, each operating system has a limit on the number of files that can be open at one time. When this limit is reached, the system is unable to open more files for other users. So it's important to close unused files.
Was this helpful?