! EVE$BUILD.TPU 31-DEC-1992 10:10 Page 1 module eve$build ident "V03-007" ! ! COPYRIGHT © 1987,1992 BY ! DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASSACHUSETTS ! ALL RIGHTS RESERVED ! ! THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED AND COPIED ! ONLY IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE AND WITH THE ! INCLUSION OF THE ABOVE COPYRIGHT NOTICE. THIS SOFTWARE OR ANY OTHER ! COPIES THEREOF MAY NOT BE PROVIDED OR OTHERWISE MADE AVAILABLE TO ANY ! OTHER PERSON. NO TITLE TO AND OWNERSHIP OF THE SOFTWARE IS HEREBY ! TRANSFERRED. ! ! THE INFORMATION IN THIS SOFTWARE IS SUBJECT TO CHANGE WITHOUT NOTICE ! AND SHOULD NOT BE CONSTRUED AS A COMMITMENT BY DIGITAL EQUIPMENT ! CORPORATION. ! ! DIGITAL ASSUMES NO RESPONSIBILITY FOR THE USE OR RELIABILITY OF ITS ! SOFTWARE ON EQUIPMENT WHICH IS NOT SUPPLIED BY DIGITAL. ! !++ ! FACILITY: ! DECTPU - Text Processing Utility ! EVE - Extensible Versatile Editor ! ! ABSTRACT: ! This is the EVE interface source program for building EVE or ! layering other products on EVE. ! ! ENVIRONMENT: ! OpenVMS VAX, OpenVMS AXP, RISC/ULTRIX ! ! Author: Jim Burrows ! ! CREATION DATE: 5-Jun-1986 ! ! MODIFIED BY: ! !-- ! EVE$BUILD.TPU Page 2 !++ ! Table of Contents ! ! EVE$BUILD.TPU ! 31-DEC-1992 10:10 ! ! Procedure name Page Description ! -------------- ---- ------------ ! ! eve$insert_option_list 4 Dump the options ! eve$insert_module_summary 5 Dump the module history ! eve$$require 6 Require another module ! eve$$conditional_compile 7 TPU "conditional compilation" ! eve$$sub_conditional_compile 8 Recursive routine for nesting ! eve$defined_procedure 9 See if a procedure is defined ! eve$build_synonym 10 Build a new EVE command synonym ! eve$$build 11 Main-line build routine !-- ! EVE$BUILD.TPU Page 3 ! I. This module, EVE$BUILD, is a tool for modifying EVE or ! layering other products on EVE. EVE$BUILD compiles DECTPU code ! with an existing EVE section file to produce a new section ! file. This new file can define either a new version of EVE or a ! new product. Both customers and in-house DIGITAL developers may ! use EVE$BUILD. ! ! In these comments, uppercase strings represent expressions that ! must be typed exactly as they appear here. Lowercase strings in ! angle brackets indicate elements that you must replace ! according to the description in the text. For example, in the ! expression ! ! _MASTER.FILE ! ! the string "" indicates that you should substitute the ! product name of your choice. The string "_MASTER.FILE" must ! be appended to the product name exactly as it appears in these ! comments. ! ! These comments cover the following: ! ! - How to prepare code for use with EVE$BUILD ! ! - How to use EVE$BUILD ! ! - How to incorporate user help libraries ! ! ! II. HOW TO PREPARE CODE FOR USE WITH EVE$BUILD ! ! ! For purposes of this section, it is assumed you have DECTPU ! code modifying EVE or layering another product on EVE. To turn ! this code into a section file using EVE$BUILD, follow the ! guidelines in this section. ! ! There are seven (7) areas in which you must observe special ! coding conventions: ! ! 1. Module Identifiers ! ! 2. Parsers ! ! 3. Initialization ! ! 4. Synonyms ! ! 5. Status Line Fields ! ! 6. Exit Handlers ! ! 7. Quit Handlers ! ! ! A. Module Identifiers ! ! ! Organize the DECTPU code into one or more modules. (This ! section defines "module" in more detail below.) Once you set ! up one or more modules, EVE$BUILD provides an audit trail ! showing what version of each module was used to build each new ! section file. All the code that you intend to build with ! EVE$BUILD must be placed in a module. ! ! To define a module, create a file containing one or more DECTPU ! procedures and (if appropriate) one or more executable ! statements. All procedures and statements in a module should ! be related to the same task or subject. Use your own judgment ! to decide what should be grouped in the same file. Then insert ! a new procedure at the beginning of the file. This procedure ! will return an "ident", or module identifier, which EVE$BUILD ! tracks during the build process. Use the following format for ! this procedure: ! ! procedure _MODULE_IDENT ! ! return ""; ! ! endprocedure; ! ! In place of , use a unique module identifier of ! up to 15 characters. If the DECTPU code in the module is part ! of a DIGITAL product, begin the identifier with the registered ! product facility code such as EVE or NOTES, followed by a dollar ! sign and the specific module name. For example, the ! used in the major EVE module is EVE$CORE. As a result, the ! module containing EVE$CORE has the identifier EVE$CORE_MODULE_IDENT. ! ! If the code is not part of a DIGITAL product, do not use a ! dollar sign in the module identifier. ! ! In place of "" use any string of up to 15 ! characters identifying the version number of the module. ! ! EVE$BUILD keeps a list showing the ident of each module it uses ! in a build. The list is kept in a file referred to as the ! .LIST file. This file is discussed in the third section ! of these comments, HOW TO USE EVE$BUILD. In EVE, the ! format used for the version number string is: ! ! Vnn-mmm ! ! The characters "nn" represent the major version number of the ! version of EVE to which the module belongs. The characters "mmm" ! represent the edit number, which we update each time the module ! is replaced in the CMS library. ! ! ! An example of a _MODULE_IDENT procedure is shown below, taken ! from module EVE$CORE.TPU: ! ! procedure eve$core_module_ident ! ! return "V02-242"; ! ! endprocedure; ! ! B. Parsers ! ! ! EVE$BUILD can accomodate one or more user-written parsing ! routines in addition to the parser included in EVE. If you ! choose to include a parser in your product, the parser can ! either supplement or replace EVE's parser. ! ! If you include one or more parsers in your product, the module ! containing the parser should define a variable of the form: ! ! EVE$X_ENABLE_PARSER_ ! ! Replace the term with the name of the module in which ! the parsing routine appears. For example, if the parser occurred ! in the module EVE$CORE, the variable would be called: ! ! EVE$X_ENABLE_PARSER_EVE$CORE ! ! Next, name the procedure implementing the parser. ! If the product is not a DIGITAL product, use this format: ! ! _PROCESS_COMMAND ! ! Replace the term with the name of the module in ! which the parsing routine appears. For example, if the parser ! occurred in the module with the ident SCHEDULER_MODULE_IDENT, ! the procedure would be called: ! ! SCHEDULER_PROCESS_COMMAND ! ! If the product is a DIGITAL product, name the procedure using ! this format: ! ! $PROCESS_COMMAND ! ! EVE has a procedure named EVE$PARSER_DISPATCH which defaults ! to the following code: ! ! procedure eve$parser_dispatch (the_command) ! ! return (eve$process_command (the_command)); ! ! endprocedure; ! ! If you do not define a parser-related variable, then the ! default EVE$PARSER_DISPATCH is put into the .INIT file. ! ! If you do define one or more parser-related variables, ! EVE$BUILD verifies that a corresponding ! _PROCESS_COMMAND procedure exists for each ! variable. If not, the build fails. If the corresponding ! procedure does exist, EVE$BUILD then adds the following code ! to EVE$PARSER_DISPATCH, just before the call to ! EVE$PROCESS_COMMAND: ! ! IF EVE$X_ENABLE_PARSER_ ! THEN ! STATUS := _PROCESS_COMMAND (THE_COMMAND); ! IF STATUS ! THEN ! IF STATUS = EVE$K_INFORMATIONAL ! THEN ! RETURN (FALSE); ! ELSE ! RETURN (TRUE); ! ENDIF; ! ENDIF; ! ENDIF; ! ! If you want a particular module's parser to supersede EVE's ! parser, your parser should return a status of either ! EVE$K_SUCCESS (1) or EVE$K_INFORMATIONAL (3) whether or not ! it can parse and execute a command. EVE$K_INFORMATIONAL should be ! returned if you want the execution of a initialization file ! (@file) to stop when a command either fails to parse or fails to ! execute. If you want your parser to supplement ! EVE's parser, your parser should return a FALSE status when it ! cannot parse a command. The FALSE status allows the parsers ! in other modules, and finally EVE's parser, to try to parse ! the command. The parsers are called in the order in which ! they appear in the master file. (The master file is ! discussed in the third section of these comments, ! HOW TO USE EVE$BUILD.) ! ! ! C. Initialization ! ! ! EVE$BUILD allows module-specific initialization. To perform ! initialization in a module, put an initializing procedure ! in the module and name the procedure using the following ! format: ! ! _MODULE_INIT ! ! Replace the term with the name of the module in ! which the procedure appears. For example, if it occurred in the ! module SCHEDULER, the procedure would be called: ! ! SCHEDULER_MODULE_INIT ! ! The EVE module EVE$CORE.TPU contains a null procedure called ! EVE$$INIT_MODULES. EVE$BUILD replaces EVE$$INIT_MODULES with ! a procedure that calls each procedure whose name ends with ! _MODULE_INIT. The initialization procedures are called in the ! order in which they are found in the master file. (The master ! file is discussed in the third section of these comments, ! HOW TO USE EVE$BUILD.) ! ! EVE's initialization takes place in the following order with ! respect to DECTPU initialization: ! ! 1. TPU$INIT_PROCEDURE ! This procedure is called by DECTPU after DECTPU has ! processed the /DEBUG qualifier. It performs the following: ! ! - Initialization of EVE's variables and settings ! ! - Module pre-initialization (including user-written modules) ! ! - Initialization of EVE's buffers, windows, and ! files ! ! - Module Initialization (including user-written modules) ! ! - Call to the end-user's initialization procedure ! TPU$LOCAL_INIT ! ! 2. /COMMAND ! DECTPU then processes the command file qualifier. ! ! 3. TPU$INIT_POSTPROCEDURE ! This procedure is called by DECTPU after /COMMAND processing. ! It performs the following: ! ! - Execution of EVE commands in the /INITIALIZATION file. ! ! - Creation of the $DEFAULTS$ buffer from which all new ! user buffers obtain their attributes like margin settings, ! end of buffer text, and the like. ! ! During the "pre-initialization" phase, you can redefine ! EVE's variables and settings to be compatible with your ! product. ! ! DO NOT redefine any EVE variable or setting unless you are sure ! you understand all the possible side effects on EVE and on your ! product. Use of this option is recommended only for very ! experienced EVE programmers. ! ! To use pre-initialization, put an initializing ! procedure in a module and name the procedure using the ! following format: ! ! _MODULE_PRE_INIT ! ! Replace the term with the name of the module in ! which the initializing procedure appears. For example, if it ! occurred in the module SCHEDULER, the procedure ! would be called: ! ! SCHEDULER_MODULE_PRE_INIT ! ! The EVE module EVE$CORE.TPU contains a null procedure called ! EVE$$PRE_INIT_MODULES. EVE$BUILD replaces EVE$$PRE_INIT_MODULES ! with a procedure that calls each procedure whose name ends with ! _MODULE_PRE_INIT. The initialization procedures are called in ! the order in which they are found in the master file. (The ! master file is discussed further in the third section of these ! comments, HOW TO USE EVE$BUILD.) ! ! Most programmers who are layering a product onto EVE should ! initialize modules by using procedures of the type ! _MODULE_INIT. Use of TPU$LOCAL_INIT should be ! reserved for the end user. Use of procedures of the type ! _MODULE_PRE_INIT should be reserved for experienced ! EVE programmers. ! ! ! D. Synonyms ! ! ! EVE$BUILD allows module-specific command synonym initialization. ! To initialize command synonyms in a module, put an initializing ! procedure in the module and name the procedure using the following ! format: ! ! _DECLARE_SYNONYM ! ! Replace the term with the name of the module in ! which the procedure appears. For example, if it occurred in the ! module SCHEDULER, the procedure would be called: ! ! SCHEDULER_DECLARE_SYNONYM ! ! For each _DECLARE_SYNONYM procedure found, EVE$BUILD ! creates a procedure _SYNONYM_INIT. This procedure ! initializes any synonym argument variables (of the form ! eve$argN_synonym) as well as the eve$$x_synonym_array elements ! corresponding to the synonyms just declared. ! ! To declare synonyms for EVE commands, put statements like the ! following in a _DECLARE_SYNONYM procedure: ! ! eve$build_synonym ("next_screen", "nästa_bild", 1); ! ! This statement creates a Swedish synonym for the NEXT SCREEN ! command. The "1" argument tells EVE$BUILD to create: ! (1) the synonym procedure that simply calls the corresponding ! EVE procedure with the correct number of arguments ! (2) the argument variable(s) for the synonym command (if any). ! A "0" would indicate the user will create the procedure and ! variable(s) when, for example, simply calling the EVE command ! is not correct for the application. A "2" would indicate that ! the first argument is not an EVE command, but just a phrase for ! which synonyms are needed. EVE makes the SET TABS command arguments ! all synonyms this way (INSERT, SPACES, VISIBLE, and so on). ! ! The EVE module EVE$SYNONYMS.TPU contains a EVE$SYNONYMS_MODULE_INIT ! procedure that calls a null procedure EVE$$INIT_ALL_SYNONYMS. ! EVE$BUILD replaces EVE$$INIT_ALL_SYNONYMS with a procedure ! that calls each dynamically created _SYNONYM_INIT. ! These initialization procedures are called in the order in which ! the _DECLARE_SYNONYM procedures are found in the ! master file. (The master file is discussed in the next section ! of these comments.) ! ! Some EVE commands are also terminators, that is, a key bound to the ! command will terminate a prompting function. If the synonym should ! also be a terminator, then include in the _MODULE_INIT ! procedure the following statement: ! ! eve$$make_synonym_a_terminator ("next_screen", "nästa_bild"); ! ! Note that modules that declare synonyms should be last in the ! master file to insure all the root EVE commands are valid before ! synonyms are made for them. ! ! ! E. Status Line Fields ! ! ! EVE$BUILD allows the user to add fields to the EVE status line ! displayed under each window. A default EVE status line contains ! the following right-justified fields showing the current mode ! (insert/overstrike) and direction (forward/reverse) of the buffer ! mapped to the window: ! ! | Insert | Forward ! ! To add user status fields, put a procedure in the module using ! the following format: ! ! _STATUS_FIELD ! ! Replace the term with a recognizable name of the field. ! For example, if the field is an EVE field for showing if the buffer ! is not to be written, the procedure name would be called: ! ! EVE$NOWRITE_STATUS_FIELD ! ! The _STATUS_FIELD procedure should take two input ! arguments and return the resulting formatted status field: ! ! result_field := _STATUS_FIELD (max_size, ! the_format) ! ! where: ! max_size = The length of the status line that is still ! unused. This is useful if you want to insure ! your field will fit in the status line. ! the_format = The FAO format to be used to format the field. ! This format is specified by EVE. ! result_field = The output of the procedure equal to the ! formatted status field. ! ! Module EVE$CORE.TPU contains a base procedure EVE$GET_STATUS_FIELDS ! that simply returns the null string. EVE$BUILD replaces ! EVE$GET_STATUS_FIELDS with the following procedure: ! ! procedure eve$get_status_fields (the_length, the_format) ! ! local remaining, ! the_fields, ! the_field; ! ! the_fields := ""; ! remaining := the_length; ! ! return the_fields ! ! endprocedure ! ! For each _STATUS_FIELD procedure declared , EVE$BUILD inserts the ! following code just before the "return" statement: ! ! the_field := _STATUS_FIELD (remaining, the_format); ! if length (the_field) <= remaining ! then ! the_fields := the_field + the_fields; ! remaining := remaining - length (the_field); ! endif; ! ! Module EVE$FILE.TPU contains procedure EVE$NOWRITE_STATUS_FIELD ! that displays "Read-only" in the status line. This procedure can ! be used as an example of procedures that add fields to the ! status line but do not do any length checking. The status field ! it creates is added to the existing fields to give the following ! right-justified status fields: ! ! | Read-only | Insert | Forward ! ! ! F. Exit Handlers ! ! ! EVE$BUILD can accomodate one or more user-written exit ! handlers in addition to the exit handler provided by EVE. ! You can choose to have your exit handler either supplement ! or replace EVE's exit handler. ! ! Name the procedure implementing the exit handler using the ! following format for a non-DIGITAL product: ! ! _EXIT_HANDLER ! ! Replace the term with the name of the module in ! which the handler appears. For example, if the handler ! occurred in the module with the ident SCHEDULER_MODULE_IDENT, ! the procedure would be called: ! ! SCHEDULER_EXIT_HANDLER ! ! If the product is a DIGITAL product, name the procedure using ! this format: ! ! $EXIT_HANDLER ! ! EVE has a procedure named EVE$EXIT_DISPATCH which defaults ! to the following code: ! ! procedure eve$exit_dispatch (the_command) ! ! eve$exit; ! ! endprocedure; ! ! If you do not create an exit handler procedure, then the ! default EVE$EXIT_DISPATCH is put into the .INIT file. ! If you do create an exit handler procedure, then EVE$BUILD ! adds the following code to EVE$EXIT_DISPATCH, just before the ! call to EVE$EXIT: ! ! IF _EXIT_HANDLER ! THEN ! RETURN; ! ENDIF; ! ! If you want a particular module's exit handler to supersede EVE's ! handler, your handler should return a TRUE status. If you want ! your handler to supplement EVE's, your handler should return a ! FALSE status. The FALSE status allows the exit handlers ! in other modules, and finally EVE's exit handler, to be called. ! The exit handlers are called in the order in which ! they appear in the master file. (The master file is ! discussed in the third section of these comments, ! HOW TO USE EVE$BUILD.) ! ! ! ! G. Quit Handlers ! ! ! EVE$BUILD can accomodate one or more user-written quit ! handlers in addition to the quit handler provided by EVE. ! You can choose to have your quit handler either supplement ! or replace EVE's quit handler. ! ! Declaring a quit handler follows the same outline given above ! concerning declaring an exit handler. Re-read that section, ! substituting "quit" for "exit", to learn how to incorporate a ! user-written quit handler into the interface ! ! ! III. HOW TO USE EVE$BUILD ! ! Once you have observed EVE$BUILD's conventions for ! initialization, parsers, module identification, synonyms, ! status fields, and exit and quit handlers, you have ! finished preparing the code for building. ! ! A. HOW TO INVOKE EVE$BUILD ! ! ! To prepare to use EVE$BUILD, define the following foreign ! command: ! ! $ BUILD == "EDIT/TPU/NODISPLAY/SECTION=EVE$SECTION- ! /COMMAND=:<[dir]>EVE$BUILD/NOINITIALIZATION ! ! If you specify /SECTION=EVE$SECTION, EVE$BUILD will build your ! product with the standard EVE section file. To build ! your product with a different version of EVE, specify ! a different section file with the /SECTION= qualifier. ! ! In most circumstances, you will specify either the standard ! EVE section file or your own enhanced EVE section file. ! No matter which section file you specify, you must ! use the /NODISPLAY qualifier if you use the /SECTION= ! qualifier. ! ! After defining the foreign command, create a master file. ! This file tells EVE$BUILD what modules to compile. If your ! product is a DIGITAL product, name your master file using ! the following format: ! ! $MASTER.FILE ! ! Replace with the name of your product. For example, ! a valid name for a DIGITAL product's master file might be: ! ! NOTES$MASTER.FILE ! ! If your product is not a DIGITAL product, name your master ! file using the following format: ! ! _MASTER.FILE ! ! For example, a valid name for a non-DIGITAL product's master ! file might be: ! ! SCHEDULER_MASTER.FILE ! ! When you have created and named the master file, type into it ! the name of each file whose contents you want to compile. ! Usually this means you type in the name of each file containing ! a module that is part of your product. If the files containing ! the modules are not in the same directory as the master file, ! then you must specify the directory name of each module file. ! ! If for some reason you wish to rebuild EVE from scratch, you ! would build it /NOSECTION, and use a modified version of the ! EVE$MASTER.FILE that came with the EVE sources. The modified ! version would include your modules at the end of the file. ! ! Once you have completed the master file, create a version file ! in the same directory that contains the master file. If your ! product is DIGITAL product, name the version file using ! the following format: ! ! $VERSION.DAT ! ! If your product is not a DIGITAL product, name the version ! file as follows: ! ! _VERSION.DAT ! ! The version file is a text file containing only the version ! number for the product. This version number will be built into ! the section file as part of the value of the procedure ! EVE$VERSION. ! ! When you have a foreign command, a master file, and a version ! file, you can invoke EVE$BUILD with the following ! command: ! ! $ BUILD ! ! For example, if the name of your product was SCHEDULER, you ! would build it by typing: ! ! $ BUILD SCHEDULER ! ! You can use the /OUTPUT qualifier to specify the name of the ! section file to create. If you do not use the qualifier, ! EVE$BUILD prompts for a file name. If you respond with a ! null file name, EVE$BUILD will give the output file the ! same name as the product. ! ! The next section of these comments describes what happens when ! you use EVE$BUILD. ! ! ! B. WHAT HAPPENS WHEN YOU USE EVE$BUILD ! ! ! Each file specified in the master file is read in and ! compiled. If there are any executable statements after ! the procedure definitions, the statements are compiled ! and executed. Any SAVE or QUIT statements or calls to ! DEBUGON (this procedure is defined in TPU$DEBUG.TPU) are ! removed before execution. ! ! EVE$BUILD creates three output files: ! ! - a file type of .TPU$SECTION, the new section file ! ! - a file type of .INIT, preserving the dynamically-generated code ! ! - a file type of .LIST, listing the results of the build ! ! All three files have the same device, directory, and file name. ! The file name is the facility, or product name, entered on the build ! command line, for example, SCHEDULER. ! ! By default a .TPU$SECTION file contains all procedure's procedure ! name and debug names. By setting the variable EVE$$X_SAVE_NAMES ! to one of following values, the .TPU$SECTION file can have one or ! more catagories of names removed. This makes the .TPU$SECTION ! file smaller. ! ! Value SAVE paramter used Effect ! ! -1 NO_DEBUG_NAMES Removes only the debug names ! ! 1 NO_PROCEDURE_NAMES Removes both the debug names ! and the procedure name ! ! 0 Leaves all of the names ! ! Digital Internal Use Only Feature: ! ! By default a .TPU$SECTION file contains all of the procedures, key ! maps, key map lists, constants and variables that have been defined ! during a session. Starting with VAXTPU V2.0, DECTPU will read any ! section file created by any version of DECTPU from VAXTPU V2.0 ! forward. (VAXTPU V3.0 is now referred to as DECTPU since it is ! not limited to running on the VAX.) ! ! VAXTPU V2.0 has also introduced the concept of a 'changes only' ! section file. A changes only section file contains only those ! things that have changed during the session that creates the ! section file, along with a reference to the EXACT section file that ! the new file was created from. Changes only section files can be ! significantly smaller than a 'full' section file. Note however ! that there are no provisions to allow access to newer section files ! in place of the 'base' section file, for example, a newer version ! of EVE in place of the one that was used to create the changes only ! section file. ! ! By setting the variable EVE$$X_SAVE_CHANGES to 1, EVE$BUILD will ! create a changes only section file. Digital recommends that ! customers do NOT set this variable. ! ! *** Changes only section files are for DIGITAL internal use only *** ! ! The .INIT file contains the following: ! ! - EVE$DYNAMIC_MODULE_IDENT ! ! - EVE$PARSER_DISPATCH ! ! - EVE$$PRE_INIT_MODULES ! ! - EVE$$INIT_MODULES ! ! - EVE$GET_STATUS_FIELDS ! ! - _SYNONYM_INIT procedures ! ! - EVE$$INIT_ALL_SYNONYMS ! ! - EVE$EXIT_DISPATCH ! ! - EVE$QUIT_DISPATCH ! ! - EVE$VERSION ! ! - routines that preserve the order of the special ! identifiers that EVE$BUILD recognizes when /SECTION= ! is specified on the command line ! ! The .LIST file contains the following: ! ! - the time and date of the build ! ! - the version of EVE used ! ! - the full file specification of the master file, .TPU$SECTION ! file, .LIST file, and .INIT file ! ! - a synopsis on each source module, including the ! module ident, the number of lines in the module, ! and the full file specification of the file ! containing the module ! ! - partial output from the TPU SHOW(SUMMARY) command ! ! - a list of all global variables used in the build ! ! - a list of all procedures used in the build ! ! ! ! IV. HOW TO INCORPORATE USER HELP LIBRARIES ! ! ! This section describes how to incorporate and invoke a user ! or facility) help library in EVE V2 for getting help on user ! defined commands, keys, and informational topics. ! ! A. Build a private interface on top of EVE: ! ! ! 1. Put the following call in one of your _MODULE_INIT procedures: ! ! EVE$DECLARE_HELP_LIBRARY (facility, ! library; ! major_topic, ! how_to_invoke) ! ! where: ! facility = Facility code (product name), e.g., EVE, TPU, NOTES ! (lower or uppercase) ! library = File spec for facility help library (don't include ! dev:[dir] if you want logical names to work) ! major_topic = ! Top level help topic(s) above the facility help topics, ! An optional argument, either a string or message code, ! made null if not specified. For example, all your ! facility topics may be at level 2 below a level 1 topic ! of "EDITOR". ! how_to_invoke = ! The string or message code to be added as a bulleted list ! to "commands" topics telling the user how to invoke the ! other facility's help libraries. It will be added only ! when the "commands" topic is for facilities other than ! its own. An optional argument, made null if not specified. ! ! Each library should contain a help topic called "commands" ! which contains the list of topics for the facility. ! EVE will insert all other facilitys' how_to_invoke ! strings as a bulleted list starting where it finds a ! special string: ~I~. The line containing the special ! string is removed, and each how_to_invoke string ! is inserted two spaces after the bullet ("o"). ! The bullet is column-aligned with the ! leading ~ character. If there is no ~I~ string, then the ! list will be inserted at the beginning of the help buffer ! with "o" indented 6 spaces and followed by 2 spaces. ! ! The start of the "commands" topic should ! be modeled after EVE's for consistency (the following is ! the output from help showing the actual indentation level ! for EVE's level 1 topic "command"): !---------------------- ! List of Topics ! ! For help on EVE topics, type the name of a topic and press RETURN. ! ! ~I~ ! o To exit from help and resume editing, press RETURN. ! .... !---------------------- ! ! For example, the following is the call in EVE declaring the EVE ! library: ! ! EVE$DECLARE_HELP_LIBRARY ("eve", ! "eve$help", ! "", ! "For help on the editor, type EVE and press RETURN."); ! ! ! EVE also provides a new procedure and four new constants for ! obtaining any of a facility's four help items: ! ! string := EVE$GET_HELP_ITEM (item_code, a_facility); ! ! where ! item_code = 0 = eve$k_help_facility, return the facility's ! facility name ! = 1 = eve$k_help_library, return the facility's ! library filespec ! = 2 = eve$k_help_topic, return the facility's major ! help topic(s) ! = 3 = eve$k_help_invoke, return the facility's ! how-to-invoke string ! a_facility = the facility name, e.g., EVE, TPU, NOTES (lower or ! uppercase) ! ! 2. For each user defined command, write a procedure with the name ! EVE_some_command, and define any required argument variables ! of the form EVE$ARG1_some_command, EVE$ARG2_some_command, and so on. ! (Only integer arguments require these variables.) ! ! 3. For each user key, define them using the following format for the ! key comment (the third parameter in the DEFINE_KEY builtin): ! ! "facility topic (legend)" ! ! where: ! facility = the facility name, for example, NOTES. This is ! optional, and defaults to EVE if absent. ! topic = the help topic (the command name). The topic ! should have underscores if it contains multiple ! words, for example, "one_window". ! legend = the optional string to be displayed for the key ! definition. Parentheses are required if specified. ! The legend is useful when the help topic is not ! appropriate to display in the keypad diagram ! or the list of defined keys. ! ! 4. Define help topics that are not for EVE commands, that is, they ! are for informational help topics. For each such topic, define ! constants of the form: ! ! eve$kt_topic__some_topic := "some_topic"; ! ! where: ! facility = the facility name, for example, NOTES ! ! The last part of the variable must match the quoted string. ! For example: ! ! eve$kt_topic_eve_section_files := "section_files"; ! ! You can put any topic in your library. However, if you don't ! define one of these variables, then you will not take advantage ! of the parser that lets you enter abbreviated topics with no ! underscores between multiple words, for example, "l o t" for ! "list of topics". ! ! 5. Build the interface using EVE$BUILD. ! ! ! B. Once the user interface has been built, build the user help library ! containing all user command and informational help topics. ! The user library must also contain the following topics: ! ! = The facility name, for example, NOTES. This topic ! should describe the facility. It could also optionally ! describe how to switch between facilities. ! ! commands = A topic that lists the commands and informational topics ! included in the library. (EVE help looks up this topic ! when the user asks for help on "?", "commands", or ! "list of topics".) See A.1. above for more discussion on ! the contents of the "commands" topic. ! ! An example of a library .hlp file for a NOTES facility is: ! !1 notes ! NOTES lets you hold bulletin-board-style discussions on line. ! .... ! 1 commands ! Below are the commands and informational topics available to you. ! ! ~I~ ! o To exit from help and resume editing, press RETURN. ! o If you want help on an EVE command, at the help prompt enter "eve" ! followed by the command. ! ! Back_reply Back_topic Next_reply Next_topic ! .... ! 1 back_reply ! .... ! 1 back_topic ! .... ! 1 next_reply ! .... ! 1 next_topic ! .... ! NOTE: The topics are parsed by the EVE parser which ! has a token limit of 5. This means informational ! or command topics must be limited to no more than 5 ! tokens. For example, KEY_MAPS_AND_KEYMAP_LISTS, which ! can be entered "k m a k l" is valid having only 5 tokens, ! but KEY_MAPS_AND_KEY_MAY_LISTS is not valid having 6. ! ! C. Once the private interface is invoked, get help from the user help ! library as follows: ! ! 1. For help on the facility, type: ! ! help facility ! ! This switches from EVE's help library to the facility's library, ! and looks up the facility topic, for example, NOTES. You must type ! in the complete facility name, not abbreviated. To switch to ! another facility's library, simply enter the facility name ! at the help prompt. EVE initially provides two help facilities: ! EVE - describing EVE commands and informational topics ! TPU - describing TPU builtins ! ! 2. For help on one of the facility commands, type: ! ! help facility some_command ! ! This switches to the facility's library and looks up some_command. ! If already in the facility's library, then only some_command need be ! entered at the help prompt. ! ! 3. Get help on a facility informational topic by typing: ! ! help facility info_topic ! ! This switches to the facility's library and looks up info_topic. ! If already in the facility library, then only info_topic need be ! entered at the help prompt. Informational topics can be ! abbreviated, and entered with or without underscores between ! multiple words in the topic. ! ! 4. Get help on a user key by pressing and then the user key. ! This automatically switches to the facility library, and obtains ! the associated help topic from the key definition comment. ! ! EVE$BUILD.TPU Page 4 procedure eve$insert_option_list ! Dump the options local option_prefix, space_index, the_names, the_name, the_length, the_value; on_error [TPU$_NONAMES, TPU$_MULTIPLENAMES]: [OTHERWISE]: endon_error; split_line; move_vertical (-1); option_prefix := "eve$x_option_"; the_names := expand_name (option_prefix, ALL) + " "; the_length := length (option_prefix) + 1; if the_names <> " " then loop exitif (the_names = ""); space_index := index (the_names, " "); the_name := substr (the_names, 1, space_index - 1); the_value := execute (fao ("on_error return 0 endon_error " + "if get_info (!AS, 'type') = INTEGER " + "then return !AS " + "else return 0 " + "endif", the_name, the_name)); if the_value then copy_text (substr (the_name, the_length, 99) + " "); endif; the_names := substr (the_names, space_index + 1, length (the_names)); endloop; endif; move_horizontal (-current_offset); if length (current_line) = 0 then copy_text (message_text (EVE$_NONE, 1)); move_horizontal (-current_offset); endif; copy_text (message_text (EVE$_OPTIONS, 1)); move_horizontal (-current_offset); move_vertical (1); endprocedure; ! eve$insert_option_list ! EVE$BUILD.TPU Page 5 procedure eve$insert_module_summary ! Dump the module history local version_prefix, option_prefix, space_index, the_names, the_name, the_length, the_value, saved_mark; on_error [TPU$_NONAMES, TPU$_MULTIPLENAMES]: [OTHERWISE]: position (saved_mark); endon_error; saved_mark := mark (NONE); copy_text (" " + eve$version); split_line; split_line; eve$insert_option_list; split_line; copy_text (message_text (EVE$_SHOWSUM_HEAD, 1)); split_line; copy_text (message_text (EVE$_SHOWSUM_HEAD2, 1)); split_line; split_line; version_prefix := "*_module_ident"; the_names := expand_name (version_prefix, PROCEDURES) + " "; the_length := length (version_prefix) - 1; if the_names <> " " then loop exitif (the_names = ""); space_index := index (the_names, " "); the_name := substr (the_names, 1, space_index - 1); copy_text (fao (" !15AS ", substr (the_name, 1, length (the_name) - the_length))); if the_name = "" then copy_text (" "); else the_value := execute (fao ("on_error return 0 endon_error " + "if get_info(!AS, 'type') = STRING " + "then return !AS " + "else return 0 " + "endif", the_name, the_name)); if the_value <> 0 then copy_text (fao ("!15AS ", the_value)); endif; split_line; endif; the_names := substr (the_names, space_index + 1, length (the_names)); endloop; endif; position (saved_mark); endprocedure; ! eve$insert_module_summary ! EVE$BUILD.TPU Page 6 procedure eve$$require ! Require another module (module_name) local the_procedure, the_expansion; on_error [TPU$_MULTIPLENAMES]: ! No message for MULTIPLENAMES [OTHERWISE]: endon_error; the_procedure := module_name + "_module_ident"; change_case (the_procedure, UPPER); the_expansion := " " + expand_name (the_procedure, PROCEDURES) + " "; if index (the_expansion, " " + the_procedure + " ") = 0 then message (fao ("Required module (!AS) not present.", module_name)); quit (OFF, 2); endif; endprocedure; ! eve$$require ! EVE$BUILD.TPU Page 7 procedure eve$$conditional_compile ! TPU "conditional compilation" (the_buffer) ! This procedure implements a hack version of conditional compilation for ! TPU. When and if TPU's compiler supports real conditional compilation, ! this procedure will go away and the compiler directives will have to ! be translated to the TPU syntax. The syntax used here is based on the ! one used by BLISS, and shouldn't be too hard to convert, assuming the ! TPU conditional compilation strategy resembles BLISS. ! ! The "keywords" that control conditional compilation all start with the ! string "!%", and must be located at the beginning of the line. Since ! the first character is an exclamation point all of the "compiler ! directives" are TPU comments. BLISS flags all such directives with a ! percent sign. Four keywords are used, !%IF, !%THEN, !%ELSE, and !%ENDIF. ! (BLISS uses %FI, but since TPU closes IFs with ENDIFs, it seemed that ! a more TPU-like thing to do was to use %ENDIF. ! ! Additionally, in order for code containing conditional compilations to ! be compilable via EVE's EXTEND commands or TPU's COMPILE and EXECUTE ! built-ins, the delimiter !% without a keyword following it is used ! to comment out the untaken code-path. ! ! The effect of calling eve$$conditional_compile is manipulate the comment ! delimiters in the specified buffer so that the "!% " is removed from the ! beginning of any lines enclosed in a conditional compilation directive ! that evluates as true, and to make sure that all lines whose condition ! evaluates as false are commented out. ! ! Very little in the way of error checking is done. If extraneous or unmatch ! conditional compilation directives are present or the directives are out of ! order, the code will fail or will act unpredictably. (This is after all, ! a hack, and is intended to be replaced by a real TPU feature, when and if ! such a feature becomes available.) ! ! An example of a conditional compilation is as follows: ! ! !%IF eve$x_option_foo ! !%THEN ! ! Output a message ! message ("Message text"); ! !%ELSE ! !% ! Blow up ! !% abort; ! !%ENDIF ! ! This code will be left alone if eve$x_option_foo is true. If it is false. ! it will be changed to look like this: ! ! !%IF eve$x_option_foo ! !%THEN ! !% ! Output a message ! !% message ("Message text"); ! !%ELSE ! ! Blow up ! abort; ! !%ENDIF ! ! Note: Constants of the form EVE$X_OPTION_foo are handled specially by ! the module summary code. Each such constant, if it is true will cause ! an element to appear in the option field of the module summary. Constants ! of this form should be used for controlling the conditional compiles ! associated with products and major packages. local saved_buffer, saved_mark, temp; on_error [TPU$_STRNOTFOUND]: [OTHERWISE]: position (saved_buffer); position (saved_mark); endon_error; if get_info (eve$$x_list_conditional_compiles, "type") = UNSPECIFIED then eve$$x_list_conditional_compiles := 0; endif; saved_mark := mark (FREE_CURSOR); saved_buffer := current_buffer; position (beginning_of (the_buffer)); loop temp := search (LINE_BEGIN + "!%IF", FORWARD); exitif temp = 0; position (end_of (temp)); if not eve$$sub_conditional_compile (1) then return (0); endif; endloop; position (saved_buffer); position (saved_mark); return (1); endprocedure; ! eve$$conditional_compile ! EVE$BUILD.TPU Page 8 procedure eve$$sub_conditional_compile ! Recursive routine for nesting (old_boolean) local temp, saved_flag, start_mark, the_condition, the_type, the_boolean; on_error [TPU$_STRNOTFOUND]: [TPU$_NONAMES]: [TPU$_MULTIPLENAMES]: [OTHERWISE]: endon_error; move_horizontal (4 - current_offset); start_mark := mark (FREE_CURSOR); temp := search (LINE_BEGIN + "!%THEN", FORWARD); if temp = 0 then message (""); message (" Missing !%THEN"); message (""); return (0); endif; position (temp); move_horizontal (-1); the_condition := create_range (start_mark, mark (NONE), NONE); the_condition := substr (the_condition, 1, length (the_condition)); temp := index (the_condition, "!"); if temp <> 0 then the_condition := substr (the_condition, 1, temp - 1); endif; edit (the_condition, TRIM, COMPRESS, UPPER); temp := expand_name (the_condition, VARIABLES); if temp <> the_condition then message (""); message (fao (" Unknown symbol in conditional compile: !AS", the_condition)); message (""); return 0; endif; the_type := execute (fao ("on_error" + " return 0 " + "endon_error " + "return get_info (!AS, 'type');", the_condition)); if the_type <> INTEGER then message (""); message (fao (" !AS is !AS. Conditional compile requires INTEGER.", the_condition, get_info (the_type, "name"))); message (""); return 0; endif; if eve$$x_list_conditional_compiles then message (fao ("%%% !!%IF !AS", the_condition)); message ("%%% !%THEN"); endif; saved_flag := get_info (SYSTEM, "line_number"); set (LINE_NUMBER, OFF); the_boolean := execute (fao ("on_error" + " return 0 " + "endon_error " + "return !AS;", the_condition)); if saved_flag then set (LINE_NUMBER, ON); endif; move_horizontal (1); move_vertical (1); loop if mark (FREE_CURSOR) = end_of (current_buffer) then message (""); message (" Unexpected end of file during contional compile."); message (""); return (0); endif; temp := current_line; change_case (temp, UPPER); if substr (temp, 1, 4) = "!%IF" then if not eve$$sub_conditional_compile (the_boolean) then return (0); endif; else if substr (temp, 1, 6) = "!%ELSE" then the_boolean := not the_boolean; if eve$$x_list_conditional_compiles then message (fao ("%%% !AS", current_line)); endif; else if substr (temp, 1, 7) = "!%ENDIF" then if eve$$x_list_conditional_compiles then message (fao ("%%% !AS", current_line)); endif; exitif 1; else if old_boolean and the_boolean then if substr (temp, 1, 2) = "!%" then erase_character (2); if current_character = " " then erase_character (1); endif; endif; else if substr (temp, 1, 1) <> "!" then copy_text ("!% "); move_horizontal (-3); endif; endif; if eve$$x_list_conditional_compiles then message (fao ("%%% !AS", current_line)); endif; endif; endif; endif; move_vertical (1); endloop; return (1); endprocedure; ! eve$$sub_conditional_compile ! EVE$BUILD.TPU Page 9 procedure eve$defined_procedure ! See if a procedure is defined (the_procedure) return (get_info (PROCEDURES, "defined", the_procedure)); endprocedure; ! eve$defined_procedure ! EVE$BUILD.TPU Page 10 procedure eve$build_synonym ! Build a new EVE command synonym (eve_command; ! root string to be made into an element in ! eve$$x_build_array, and/or to which the_synonym ! will be added. This may or may not be an EVE command. a_synonym, ! new synonym string, e.g., "scroll_down" (optional) create_flag) ! 0 = create synonym (but not procedure + arg ! variables) - optional ! 1 = create synonym + procedure and arg variables ! 2 = create synonym (but not procedure and arg ! variables, and don't test if eve_command is ! a command) ! Create integer-indexed eve$$x_build_array during build. ! 1. Create a synonym by either creating the synonym root or by ! adding to the synonym root in eve$$x_build_array. ! 2. Optionally, creating a new procedure for the synonym that will ! simply call the original EVE procedure. This is required if the ! synonym can be entered from the command line. ! Implicit Inputs ! eve$$x_build_array - an integer-indexed array where each element ! contains strings for all keys that are synonyms for an EVE command. ! NOTE: EVE's array is string-indexed, so we write code that will ! load synonyms into it accordingly ! eve$$x_build_array {0} - count of used elements in the array ! Implicit Outputs ! eve$$x_build_array - updated with new element or new string in an ! existing element. EVE$BUILD will convert this array into code that ! will build the eve$$x_synonym_array at editor startup. ! eve$x_synonym_buffer - contains synonym procedures followed by the ! corresponding eve$argN_the_synonym argument variables (if create_flag=1) ! Return Value ! true - successfully created ! false - eve_command is not an expected EVE command, a_synonym already ! exists as a procedure or as a synonym for eve_command local the_command, the_synonym, the_index, the_buffer, last_procedure, saved_window, saved_mark, arg_count, a_comma, temp, test_procedure, found_it, temp_arg, any_args, min_args, max_args; on_error [TPU$_STRNOTFOUND, TPU$_NONAMES, TPU$_MULTIPLENAMES]: [OTHERWISE]: message (""); message (error_text); if get_info (saved_window, "type") = WINDOW then position (saved_window); endif; position (saved_mark); return (2); endon_error; if get_info (current_buffer, "map_count") <> 0 then saved_window := current_window; endif; saved_mark := mark (FREE_CURSOR); ! Test if the first argument is an eve command unless create_flag = 2. if create_flag <> tpu$k_unspecified then if create_flag <> 2 then test_procedure := TRUE; endif; else test_procedure := TRUE; endif; if test_procedure then if not get_info (PROCEDURES, "defined", "eve_" + eve_command) then message (" '" + eve_command + "' is not an EVE command."); if get_info (saved_window, "type") = WINDOW then position (saved_window); endif; position (saved_mark); return (2); endif; endif; ! Create the synonym array if it doesn't already exist if get_info (eve$$x_build_array, "type") <> ARRAY then eve$$x_build_array := create_array (); eve$$x_build_array {0} := 0; ! number of used elements in array endif; the_command := eve_command; edit (the_command, TRIM, COMPRESS, LOWER, OFF); ! was a_synonym passed? if a_synonym = tpu$k_unspecified then the_synonym := ""; else the_synonym := a_synonym; edit (the_synonym, TRIM, COMPRESS, LOWER, OFF); endif; ! If create_flag = 1, then create the_synonym procedure and the argument ! variables: if (create_flag <> tpu$k_unspecified) and (the_synonym <> "") then if create_flag = 1 then if (get_info (PROCEDURES, "defined", "eve_" + the_synonym)) then message (" '" + a_synonym + "' is already a synonym procedure."); if get_info (saved_window, "type") = WINDOW then position (saved_window); endif; position (saved_mark); return (2); endif; min_args := get_info (PROCEDURES, "minimum_parameters", "eve_" + the_command); max_args := get_info (PROCEDURES, "maximum_parameters", "eve_" + the_command); ! Create the synonyms buffer to construct the procedure if get_info (eve$x_synonym_buffer, "type") <> BUFFER then eve$x_synonym_buffer := create_buffer ("SYNONYMS"); endif; position (end_of (eve$x_synonym_buffer)); last_procedure := search (LINE_BEGIN + "endprocedure", REVERSE); if last_procedure <> 0 then position (last_procedure); ! put new procedure just before move_vertical (1); ! argument variable declarations split_line; endif; copy_text ("procedure eve_" + the_synonym); if max_args > 0 then copy_text (" ("); ! add args to synonym procedure declaration loop exitif arg_count = max_args; if (max_args > min_args) and ! add ";" before optional args (arg_count = min_args) then copy_text (";" + "arg" + str (arg_count + 1)); else a_comma := ""; if arg_count <> 0 then a_comma := ","; endif; copy_text (a_comma + "arg" + str (arg_count + 1)); endif; arg_count := arg_count + 1; endloop; copy_text (")"); endif; split_line; !** need we worry about handling ^C here? copy_text ("on_error"); split_line; copy_text (" return (FALSE);"); split_line; copy_text ("endon_error;"); split_line; copy_text (" return ("); copy_text ("eve_" + the_command); ! add args to the_command if max_args > 0 then copy_text (" ("); arg_count := 0; ! add args to synonym procedure declaration loop exitif arg_count = max_args; a_comma := ""; if arg_count <> 0 then a_comma := ","; endif; copy_text (a_comma + "arg" + str (arg_count + 1)); arg_count := arg_count + 1; endloop; copy_text (")"); endif; copy_text (");"); split_line; copy_text ("endprocedure;"); split_line; ! put the argument declarations at the end of buffer position (end_of (eve$x_synonym_buffer)); loop exitif arg_count = 0; temp_arg := "eve$arg" + str (arg_count) + "_" + the_command; change_case (temp_arg, UPPER); any_args := expand_name (temp_arg, VARIABLES); if any_args <> "" then if (any_args = temp_arg) or ! Is the ONLY variable valid? (index (any_args + " ", ! Is ONE of the variables valid? temp_arg + " ") <> 0) then copy_text ("eve$arg" + str (arg_count) + "_" + the_synonym + " := " + "eve$arg" + str (arg_count) + "_" + the_command + ";"); split_line; endif; endif; arg_count := arg_count - 1; endloop; endif; endif; ! See if the synonym root already exists (eve_command is the first string ! in any eve$$x_build_array element); if it does, then remember the ! index, and test if a_synonym is already in that element temp := eve$$x_build_array {0}; ! count of used elements loop exitif temp = 0; if index (" " + eve$$x_build_array {temp} + " ", " " + the_command + " ") = 1 then found_it := 1; the_index := temp; if the_synonym <> "" then if index (" " + eve$$x_build_array {temp} + " ", " " + the_synonym + " ") > 0 then message (" '" + the_synonym + "' is already a synonym for command '" + the_command + "'."); if get_info (saved_window, "type") = WINDOW then position (saved_window); endif; position (saved_mark); return (2); endif; else message (" Command '" + eve_command + "' is already " + "a synonym root, being ignored..."); if get_info (saved_window, "type") = WINDOW then position (saved_window); endif; position (saved_mark); return (2); endif; exitif; endif; temp := temp - 1; endloop; if not found_it then ! Create the synonym element eve$$x_build_array {0} := eve$$x_build_array {0} + 1; the_index := eve$$x_build_array {0}; eve$$x_build_array {the_index} := the_command; endif; ! Add the_synonym to the root element if the_synonym <> "" then eve$$x_build_array {the_index} := eve$$x_build_array {the_index} + " " + the_synonym; endif; if get_info (saved_window, "type") = WINDOW then position (saved_window); endif; position (saved_mark); return (TRUE); endprocedure ! eve$build_synonym ! EVE$BUILD.TPU Page 11 procedure eve$$build ! Main-line build routine local build_buffer, ! Buffer compilations happen in file_name, ! File name and type of current file file_spec, ! File spec from the master file dump_buffer, ! Buffer to extract TPU$INIT_PROCEDURE through init_pattern, ! Pattern to match the whole TPU$INIT_PROCEDURE init_code, ! Range containing the TPU$INIT_PROCEDURE init_file, ! File the automatically generated code goes in last_procedure, ! Pointer to the last endprocedure statement last_arg, ! Pointer to the last argument declaration listing_buffer, ! Buffer to build the listing in listing_file, ! Name of file to write listing to listing_locale, ! Directory to write the listings to master_buffer, ! Buffer containing master file master_file, ! Master file from DCL command line master_line, ! Current line from the master file message_file, ! Name of file to write message buffer to build_message_window, ! Window to message buffer (/DISPLAY only) source_file_default, ! Source file default name product_name, ! Name of the product being built product_version, ! Version string for the product product_ident, ! Ident string for the product version_file, ! Name of file containing the product version build_time, ! String containing the time the build started found_synonym, ! Boolean if synonym already exists the_command, ! Copy of command for synonym section_file, ! File-spec to write the section file to space_pos, ! Position of space in expand_name variable temp, ! Guess... temp_buffer, ! Scratch buffer. the_code, ! Trailing executable statements, if any the_end, ! Gets end_of(build_buffer) the_length, ! The length of the_names the_name, ! Individual names within the_names the_names, ! Return value from expand_names array_count, ! Elements created in synonym_array + 1 module_idents, ! List (from expand name) of known idents parser_flags, ! List of all parser routine flags module_pre_inits, ! List of all pre-inits module_inits, ! List of all inits declare_synonyms, ! List of all declare_synonyms synonym_inits, ! List of all synonym_inits exit_handlers, ! List of all exit_handlers quit_handlers, ! List of all quit_handlers status_fields, ! List of status-line fields the_program, ! Compiled version of the_code white_space, ! Space, and tab used to build patterns facility, ! Help facility string space_index, ! Index temp variable save_command, ! Save command to execute ultrix_active; ! Ultrix flag constant eve$kt_format_module_ident := "*_module_ident"; constant eve$kt_format_enable_parser := "eve$x_enable_parser_"; constant eve$kt_format_pre_init := "*_module_pre_init"; constant eve$kt_format_module_init := "*_module_init"; constant eve$kt_format_status_field := "*_status_field"; constant eve$kt_format_declare_synonym := "*_declare_synonym"; constant eve$kt_format_synonym_init := "*_synonym_init"; constant eve$kt_format_exit_handler := "*_exit_handler"; constant eve$kt_format_quit_handler := "*_quit_handler"; ! Error handler -- All errors are fatal except "String not found", ! "No names expanded", and "Multiple names expanded" on_error [TPU$_STRNOTFOUND]: [TPU$_NONAMES]: [TPU$_MULTIPLENAMES]: [OTHERWISE]: message (""); message (error_text); message (""); return (2); endon_error; set (SUCCESS, OFF); set (MESSAGE_FLAGS, 1); dump_buffer := 0; ! insure eve$$x_synonym_array exists (none exists if /SECTION= not specified) if get_info (eve$$x_synonym_array, "type") <> ARRAY then eve$$x_synonym_array := create_array; endif; if eve$defined_procedure ("eve$$build_module_idents") then module_idents := execute ("on_error" + " return (''); " + "endon_error " + " return eve$$build_module_idents"); else module_idents := expand_name (eve$kt_format_module_ident, PROCEDURES); if module_idents <> "" then module_idents := module_idents + " "; endif; endif; if eve$defined_procedure ("eve$$build_parser_flags") then parser_flags := execute ("on_error" + " return (''); " + "endon_error " + " return eve$$build_parser_flags"); else parser_flags := expand_name (eve$kt_format_enable_parser, VARIABLES); if parser_flags <> "" then parser_flags := parser_flags + " "; endif; endif; if eve$defined_procedure ("eve$$build_module_pre_inits") then module_pre_inits := execute ("on_error" + " return (''); " + "endon_error " + " return eve$$build_module_pre_inits"); else module_pre_inits := expand_name (eve$kt_format_pre_init, PROCEDURES); if module_pre_inits <> "" then module_pre_inits := module_pre_inits + " "; endif; endif; if eve$defined_procedure ("eve$$build_module_inits") then module_inits := execute ("on_error" + " return (''); " + "endon_error " + " return eve$$build_module_inits"); else module_inits := expand_name (eve$kt_format_module_init, PROCEDURES); if module_inits <> "" then module_inits := module_inits + " "; endif; endif; if eve$defined_procedure ("eve$$build_status_fields") then status_fields := execute ("on_error" + " return (''); " + "endon_error " + " return eve$$build_status_fields"); else status_fields := expand_name (eve$kt_format_status_field, PROCEDURES); if status_fields <> "" then status_fields := status_fields + " "; endif; endif; if eve$defined_procedure ("eve$$build_declare_synonyms") then declare_synonyms := execute ("on_error" + " return (''); " + "endon_error " + " return eve$$build_declare_synonyms"); else declare_synonyms := expand_name (eve$kt_format_declare_synonym, PROCEDURES); if declare_synonyms <> "" then declare_synonyms := declare_synonyms + " "; endif; endif; if eve$defined_procedure ("eve$$build_synonym_inits") then synonym_inits := execute ("on_error" + " return (''); " + "endon_error " + " return eve$$build_synonym_inits"); else synonym_inits := expand_name (eve$kt_format_synonym_init, PROCEDURES); if synonym_inits <> "" then synonym_inits := synonym_inits + " "; endif; endif; if eve$defined_procedure ("eve$$build_exit_handlers") then exit_handlers := execute ("on_error" + " return (''); " + "endon_error " + " return eve$$build_exit_handlers"); else exit_handlers := expand_name (eve$kt_format_exit_handler, PROCEDURES); if exit_handlers <> "" then exit_handlers := exit_handlers + " "; endif; endif; if eve$defined_procedure ("eve$$build_quit_handlers") then quit_handlers := execute ("on_error" + " return (''); " + "endon_error " + " return eve$$build_quit_handlers"); else quit_handlers := expand_name (eve$kt_format_quit_handler, PROCEDURES); if quit_handlers <> "" then quit_handlers := quit_handlers + " "; endif; endif; ! Set all buffers that exist when we start up to be NO-WRITE. This ! should only happen if we were started /SECTION, which may cause ! other problems. temp_buffer := get_info (BUFFER, "first"); loop exitif temp_buffer = 0; set (NO_WRITE, temp_buffer); temp_buffer := get_info (BUFFER, "next"); endloop; temp_buffer := create_buffer ("Temp buffer"); set (NO_WRITE, temp_buffer); white_space := " " + ascii (9); init_pattern := "procedure" + spanl (white_space) + "tpu$init_procedure"; ! Parse the command line. ! ! In /DISPLAY make sure there is a message buffer & window. ! In /NODISPLAY make sure there isn't. if get_info (COMMAND_LINE, "display") then if get_info (tpu$x_message_buffer, "type") <> BUFFER then tpu$x_message_buffer := create_buffer ("Message Buffer"); set (SYSTEM, tpu$x_message_buffer); set (EOB_TEXT, tpu$x_message_buffer, ""); build_message_window := create_window (1, 24, ON); map (build_message_window, tpu$x_message_buffer); set (PROMPT_AREA, 24, 1, NONE); endif; else tpu$x_message_buffer := 0; endif; ! The DCL command line parameter is the name of the product. ! From it we get the name of master and version [and section] files. ! If there is none, ask and quit if there is no answer. product_name := get_info (COMMAND_LINE, "file_name"); if (product_name = "") then product_name := read_line ("Product name: "); endif; if (product_name = "") then return (1); endif; ! Preserve the case of the product name. if get_info (SYSTEM, "version") >= 3 then ultrix_active := (get_info (system, "operating_system") = ULTRIX); endif; master_file := product_name + "_master.file"; version_file := product_name + "_version.dat"; if (file_search (master_file) = "") or (file_search (version_file) = "") then master_file := product_name + "$master.file"; version_file := product_name + "$version.dat"; if (file_search (master_file) = "") or (file_search (version_file) = "") then message ("Can't find MASTER and VERSION files."); return (2); endif; endif; source_file_default := product_name; product_name := file_parse (product_name, "", "", NAME); ! The /OUTPUT qualifier gives us the name of the section file. ! If none is specified, ask with a default of the product name. if get_info (COMMAND_LINE, "output") then section_file := get_info (COMMAND_LINE, "output_file"); if (section_file = "") then section_file := read_line ("Section file name [default = " + "product name " + product_name + "]: "); if (section_file = "") then message ("Using default section file name = " + product_name + "..."); if not ultrix_active then section_file := "sys$disk:[]" + product_name; else section_file := product_name; endif; endif; endif; endif; if not ultrix_active then edit (section_file, TRIM, UPPER); section_file := file_parse (section_file, "sys$disk:[].TPU$SECTION", product_name); else edit (section_file, TRIM); section_file := file_parse (section_file, "./.tpu_section", product_name); endif; if (substr (section_file, 1, 5) = "EXE$:") then listing_locale := "MAP$:"; else listing_locale := ""; endif; ! The listing file name is the same as the section file, with a ".LIST" ! file type. listing_file := file_parse (".list", listing_locale, section_file); init_file := file_parse (".init", listing_locale, section_file); listing_buffer := create_buffer ("Listing buffer"); set (OUTPUT_FILE, listing_buffer, listing_file); ! Creaate a log file from the message buffer if tpu$x_message_buffer <> 0 then message_file := file_parse (listing_locale + ".log", section_file); set (OUTPUT_FILE, tpu$x_message_buffer, message_file); endif; ! Create the major buffers. master_buffer := create_buffer ("Master file", master_file); set (NO_WRITE, master_buffer); build_buffer := create_buffer ("Build Buffer"); set (NO_WRITE, build_buffer); tpu$x_show_buffer := create_buffer ("Show Buffer"); set (NO_WRITE, tpu$x_show_buffer); ! Get the version number. position (temp_buffer); read_file (version_file); position (beginning_of (temp_buffer)); temp := current_line; product_ident := substr (temp, 1, length (temp)); erase (temp_buffer); build_time := fao ("!%D", 0); if substr (build_time, 1, 1) = " " then build_time := "0" + substr (build_time, 2, length (build_time)); endif; product_version := product_ident + " " + substr (build_time, 8, 4) + "-" + fao ("!2ZL", !** internationalize the following: index (" JANFEBMARAPRMAYJUNJULAUGSEPOCTNOVDEC", substr (build_time, 4, 3)) / 3) + "-" + substr (build_time, 1, 2) + " " + substr (build_time, 13, 5); ! Print out the heading for the listing file. position (listing_buffer); copy_text (fao ("!15AS !23AS !AS !8AS", product_name, build_time, file_parse ( get_info (command_line, "command_file"), "", "", NAME), eve$build_module_ident)); split_line; split_line; copy_text ("Master file = " + get_info (master_buffer, "file_name")); split_line; copy_text ("Section file = " + section_file); split_line; copy_text ("Listing file = " + listing_file); split_line; copy_text ("Init file = " + init_file); split_line; message (create_range (beginning_of (listing_buffer), end_of (listing_buffer), NONE)); split_line; copy_text ("Product Name Version"); split_line; copy_text ("------------ -------"); split_line; split_line; copy_text (fao ("!31AS !AS", product_name, product_version)); split_line; split_line; copy_text ("-------- Source Module Synopsis --------"); split_line; split_line; if get_info (COMMAND_LINE, "section") then temp := get_info (COMMAND_LINE, "section_file"); if temp <> "" then temp := file_parse (temp, "sys$share:tpu$section.tpu$section"); copy_text (fao ("Built under existing section file: !AS", temp)); split_line; split_line; copy_text (" Module summary"); split_line; copy_text (" --------------"); split_line; split_line; eve$insert_module_summary; split_line; split_line; endif; endif; copy_text ("Module Name Ident Lines File"); split_line; copy_text ("----------- ----- ----- ----"); split_line; split_line; ! Get the file names from the master file one at a time. ! Get each file and compile it position (beginning_of (master_buffer)); array_count := 1; loop position (master_buffer); exitif (mark (NONE) = end_of (master_buffer)); master_line := current_line; move_vertical (1); temp := index (master_line, "!"); if temp <> 0 then master_line := substr (master_line, 1, temp - 1); endif; if not ultrix_active then edit (master_line, UPPER, COMPRESS, TRIM, ON); endif; if master_line <> "" then if substr (master_line, 1, 1) = "%" then if master_line = "%LIST" then eve$$x_list_conditional_compiles := 1; else if master_line = "%NOLIST" then eve$$x_list_conditional_compiles := 0; else message ("Unrecognized build directive: !AS", temp); endif; endif; else message ("Loading " + master_line); position (build_buffer); erase (build_buffer); file_spec := file_search (master_line, ".tpu", source_file_default); if file_spec = "" then message ("Can't find file: " + master_line); return (2); endif; file_spec := read_file (file_spec); message (" From file: " + file_spec); file_name := file_parse (file_spec, "", "", NAME) + file_parse (file_spec, "", "", TYPE); position (listing_buffer); copy_text (fao ("!6UL !AS", get_info (build_buffer, "record_count"), file_spec)); split_line; move_vertical (-1); ! ! Handle conditional compilation (until TPU supports it better) ! if not eve$$conditional_compile (build_buffer) then return (2); endif; ! ! Look for the trailing executable code ! the_code := 0; the_end := end_of (build_buffer); position (the_end); last_procedure := search (LINE_BEGIN + ("endprocedure" | "endmodule"), REVERSE); if (last_procedure <> 0) then position (last_procedure); move_vertical (1); move_horizontal (-current_offset); else position (beginning_of (build_buffer)); endif; if (mark (NONE) <> the_end) then message (" Found trailing executable statements."); the_code := create_range (mark (NONE), the_end, NONE); ! ! Clean up the executable code--remove SAVEs, QUITs, and DEBUGONs ! position (temp_buffer); erase (temp_buffer); copy_text (the_code); loop position (beginning_of (temp_buffer)); temp := search (LINE_BEGIN + "quit" + REMAIN, FORWARD); exitif (temp = 0); message (" Commenting out QUIT statement."); position (temp); copy_text ("!"); endloop; loop position (beginning_of (temp_buffer)); temp := search (LINE_BEGIN + "save" + match (";") + REMAIN, FORWARD); exitif (temp = 0); message (" Commenting out SAVE statement."); position (temp); copy_text ("!"); endloop; loop position (beginning_of (temp_buffer)); temp := search (LINE_BEGIN + "debugon;" + REMAIN, FORWARD); exitif (temp = 0); message (" Commenting out DEBUGON call."); position (temp); copy_text ("!"); endloop; the_code := create_range (beginning_of (temp_buffer), end_of (temp_buffer), NONE); endif; ! ! TPU$INIT_PROCEDURE is only valid in one file: EVE$CORE.TPU. ! Complain about all other copies. ! if (file_name <> "EVE$CORE.TPU") OR (file_name <> "eve_core.tpu") then loop position (beginning_of (build_buffer)); init_code := search (init_pattern, FORWARD); exitif init_code = 0; position (init_code); if current_offset = 0 then message (" Warning: Found tpu$init_procedure."); exitif; endif; move_horizontal (-current_offset); move_vertical (1); endloop; endif; ! ! Now that it has been sanitized, compile the code. ! set (INFORMATIONAL, ON); the_program := compile (build_buffer); if (the_code <> 0) then the_program := 0; the_program := compile (the_code); if (the_program <> 0) then message (" Executing the trailing code..."); execute (the_program); else message (" Trailing code is not executable."); endif; endif; set (INFORMATIONAL, OFF); erase (build_buffer); ! ! Add any module-specific components just compiled to their variables. ! the_names := expand_name (eve$kt_format_enable_parser, VARIABLES) + " "; if the_names <> " " then loop exitif the_names = ""; space_index := index (the_names, " "); the_name := substr (the_names, 1, space_index - 1); the_names := substr (the_names, space_index + 1, length (the_names)); if index (parser_flags, the_name) = 0 then parser_flags := parser_flags + the_name + " "; endif; endloop; endif; the_names := expand_name (eve$kt_format_pre_init, PROCEDURES) + " "; if the_names <> " " then loop exitif the_names = ""; space_index := index (the_names, " "); the_name := substr (the_names, 1, space_index - 1); the_names := substr (the_names, space_index + 1, length (the_names)); if index (module_pre_inits, the_name) = 0 then module_pre_inits := module_pre_inits + the_name + " "; endif; endloop; endif; the_names := expand_name (eve$kt_format_module_init, PROCEDURES) + " "; if the_names <> " " then loop exitif the_names = ""; space_index := index (the_names, " "); the_name := substr (the_names, 1, space_index - 1); the_names := substr (the_names, space_index + 1, length (the_names)); if index (module_inits, the_name) = 0 then module_inits := module_inits + the_name + " "; endif; endloop; endif; the_names := expand_name (eve$kt_format_status_field, PROCEDURES) + " "; if the_names <> " " then loop exitif the_names = ""; space_index := index (the_names, " "); the_name := substr (the_names, 1, space_index - 1); the_names := substr (the_names, space_index + 1, length (the_names)); if index (status_fields, the_name) = 0 then status_fields := status_fields + the_name + " "; endif; endloop; endif; the_names := expand_name (eve$kt_format_exit_handler, PROCEDURES) + " "; if the_names <> " " then loop exitif the_names = ""; space_index := index (the_names, " "); the_name := substr (the_names, 1, space_index - 1); the_names := substr (the_names, space_index + 1, length (the_names)); if index (exit_handlers, the_name) = 0 then exit_handlers := exit_handlers + the_name + " "; endif; endloop; endif; the_names := expand_name (eve$kt_format_quit_handler, PROCEDURES) + " "; if the_names <> " " then loop exitif the_names = ""; space_index := index (the_names, " "); the_name := substr (the_names, 1, space_index - 1); the_names := substr (the_names, space_index + 1, length (the_names)); if index (quit_handlers, the_name) = 0 then quit_handlers := quit_handlers + the_name + " "; endif; endloop; endif; the_names := expand_name (eve$kt_format_declare_synonym, PROCEDURES) + " "; if the_names <> " " then the_length := length (eve$kt_format_declare_synonym) - 1; loop exitif the_names = ""; space_index := index (the_names, " "); the_name := substr (the_names, 1, space_index - 1); the_names := substr (the_names, space_index + 1, length (the_names)); if index (declare_synonyms, the_name) = 0 then ! got a new facility declare_synonyms := declare_synonyms + the_name + " "; change_case (the_name, LOWER); facility := substr (the_name, 1, length (the_name) - the_length); synonym_inits := synonym_inits + facility + "_synonym_init" + " "; ! execute the declare_synonyms procedure the_program := 0; the_program := compile (the_name); if (the_program <> 0) then message (" Executing " + the_name + "..."); execute (the_program); else message (" " + the_name + " is not executable."); return (2); endif; ! If any new synonym argument variables were just ! created, put them into a _synonym_init ! procedure that also inits the array elements, ! and keep track of all the new procedures in ! synonym_inits. if get_info (eve$x_synonym_buffer, "type") <> BUFFER then eve$x_synonym_buffer := create_buffer ("SYNONYMS"); endif; position (end_of (eve$x_synonym_buffer)); last_arg := search (LINE_BEGIN + "eve$arg", REVERSE); if last_arg <> 0 then last_procedure := search (LINE_BEGIN + "endprocedure", REVERSE); endif; if (last_arg <> 0) and (last_procedure <> 0) then if (beginning_of (last_arg)) > (beginning_of (last_procedure)) then position (last_procedure); move_vertical (1); endif; endif; split_line; copy_text ("procedure " + facility + "_synonym_init"); split_line; split_line; ! add code to _synonym_init to init the ! synonym array elements if get_info (eve$$x_build_array, "type") = ARRAY then loop exitif array_count > eve$$x_build_array {0}; ! get the root eve command in the array space_index := index ( eve$$x_build_array {array_count}, " "); if space_index = 0 then the_command := eve$$x_build_array {array_count}; else the_command := substr ( eve$$x_build_array {array_count}, 1, space_index - 1); endif; ! see if the_command has already been copied ! from eve$$x_build_array to ! eve$$x_synonym_array during this build; ! array_count = (# of elements + 1) the build ! has added to eve$$x_synonym_array up to now temp := array_count - 1; loop exitif temp = 0; if index (" " + eve$$x_build_array {temp} + " ", " " + the_command + " ") = 1 then found_synonym := 1; exitif; endif; temp := temp - 1; endloop; copy_text ("eve$$x_synonym_array {'" + the_command + "'} := "); ! see if the synonym already existed in ! eve$$x_synonym_array due to /SECTION= if (eve$$x_synonym_array {the_command} <> tpu$k_unspecified) or (found_synonym) then ! the_command is already in the array, ! prevent duplicate root commands in array if space_index = 0 then message (" '" + the_command + "' has already been " + " declared a synonym root."); return (2); else eve$$x_build_array {array_count} := substr ( eve$$x_build_array { array_count }, space_index + 1, 999 ); copy_text ("eve$$x_synonym_array {'" + the_command + "'} + ' "); endif; else copy_text ("'"); endif; copy_text (eve$$x_build_array {array_count} + "';"); split_line; array_count := array_count + 1; endloop; endif; position (end_of (eve$x_synonym_buffer)); copy_text ("endprocedure"); split_line; split_line; endif; endloop; endif; the_names := expand_name (eve$kt_format_module_ident, PROCEDURES) + " "; the_length := length (eve$kt_format_module_ident) - 1; the_name := ""; if the_names <> " " then loop exitif (the_names = ""); space_index := index (the_names, " "); temp := substr (the_names, 1, space_index - 1); if index (module_idents, temp + " ") = 0 then module_idents := module_idents + temp + " "; the_name := temp; endif; the_names := substr (the_names, space_index + 1, length (the_names)); endloop; endif; position (listing_buffer); copy_text (fao ("!15AS ", substr (the_name, 1, length (the_name) - the_length))); if the_name = "" then copy_text (" "); else execute ("if get_info(" + the_name + ",'type')=STRING then " + "copy_text(fao('!15AS '," + the_name + "));" + "endif;"); endif; move_vertical (1); message (" "); endif; endif; endloop; ! EVE$BUILD.TPU Page 12 ! Build the dynamicly overloaded/created procedures ! ! eve$parser_dispatch, eve$$pre_init_modules, eve$$init_modules, ! eve$get_status_fields, eve$version, ! eve$dynamic_module_ident, eve$exit_dispatch, eve$$quit_dispatch message (" Building Parser Dispatch Procedure..."); position (build_buffer); copy_text ("procedure eve$parser_dispatch(the_command)"); split_line; copy_text ("local status;"); split_line; the_names := parser_flags; if (the_names <> " ") then the_length := length (eve$kt_format_enable_parser) + 1; the_names := the_names + " "; loop exitif (the_names = " "); space_index := index (the_names, " "); if (space_index = 0) then message ("Can't find space in parser dispatch."); return (2); endif; the_name := substr (the_names, 1, space_index - 1); edit (the_name, LOWER); ! insure each enabled parser has a corresponding procedure temp := substr (the_name, the_length, 9999); facility := expand_name (temp + "%process_command", PROCEDURES); if (facility = 0) then message ("Can't find parser dispatch procedure for facility = " + temp); return (2); endif; if index (facility, " ") then message ("Too many parser dispatches for facility = " + temp); return (2); endif; split_line; copy_text (" if " + the_name); split_line; copy_text (" then"); split_line; copy_text (" status := " + facility + "(the_command);"); split_line; copy_text (" if status"); split_line; copy_text (" then"); split_line; copy_text (" if status = eve$k_informational"); split_line; copy_text (" then"); split_line; copy_text (" return (FALSE);"); split_line; copy_text (" else"); split_line; copy_text (" return (TRUE);"); split_line; copy_text (" endif;"); split_line; copy_text (" endif;"); split_line; copy_text (" endif;"); split_line; message (" Found parser dispatch for facility = " + temp); the_names := substr (the_names, space_index + 1, length (the_names)); endloop; endif; position (end_of (build_buffer)); if get_info (PROCEDURES, "defined", "eve$process_command") then copy_text (" return (eve$process_command(the_command));"); else copy_text (" return (0);"); endif; split_line; copy_text ("endprocedure"); split_line; split_line; message (" "); ! EVE$BUILD.TPU Page 13 message (" Building Package Pre-Initialization Dispatch Procedure..."); copy_text ("procedure eve$$pre_init_modules"); split_line; split_line; the_names := module_pre_inits; if (the_names <> " ") then the_length := length (eve$kt_format_pre_init) - 1; the_names := the_names + " "; loop exitif (the_names = " "); space_index := index (the_names, " "); if (space_index = 0) then message ("Can't find space in module pre-init."); return (2); endif; the_name := substr (the_names, 1, space_index - 1); edit (the_name, LOWER); facility := substr (the_name, 1, length (the_name) - the_length); copy_text (" "); copy_text (the_name); copy_text (";"); split_line; message (" Found package pre-init for facility = " + facility); the_names := substr (the_names, space_index + 1, length (the_names)); endloop; endif; position (end_of (build_buffer)); copy_text ("endprocedure"); split_line; split_line; message (" "); ! EVE$BUILD.TPU Page 14 message (" Building Package Initialization Dispatch Procedure..."); copy_text ("procedure eve$$init_modules"); split_line; split_line; the_names := module_inits; if (the_names <> " ") then the_length := length (eve$kt_format_module_init) - 1; the_names := the_names + " "; loop exitif (the_names = " "); space_index := index (the_names, " "); if (space_index = 0) then message ("Can't find space in module init."); return (2); endif; the_name := substr (the_names, 1, space_index - 1); edit (the_name, LOWER); facility := substr (the_name, 1, length (the_name) - the_length); copy_text (" "); copy_text (the_name); copy_text (";"); split_line; message (" Found package init for facility = " + facility); the_names := substr (the_names, space_index + 1, length (the_names)); endloop; endif; position (end_of (build_buffer)); copy_text ("endprocedure"); split_line; split_line; message (" "); ! EVE$BUILD.TPU Page 15 message (" Building Status Line Dispatch Procedure..."); copy_text ("procedure eve$get_status_fields (the_length, the_format)"); split_line; split_line; copy_text ("local remaining,"); split_line; copy_text (" the_fields,"); split_line; copy_text (" the_field;"); split_line; split_line; copy_text ('the_fields := "";'); split_line; copy_text ("remaining := the_length;"); split_line; split_line; the_names := status_fields; if (the_names <> " ") then the_length := length (eve$kt_format_status_field) - 1; the_names := the_names + " "; loop exitif (the_names = " "); space_index := index (the_names, " "); if (space_index = 0) then message ("Can't find space in status field."); return (2); endif; the_name := substr (the_names, 1, space_index - 1); edit (the_name, LOWER); facility := substr (the_name, 1, length (the_name) - the_length); copy_text ("the_field := "); copy_text (the_name); copy_text (" (remaining, the_format);"); split_line; copy_text ("if length (the_field) <= remaining"); split_line; copy_text ("then"); split_line; copy_text (" the_fields := the_field + the_fields;"); split_line; copy_text (" remaining := remaining - length (the_field);"); split_line; copy_text ("endif;"); split_line; split_line; message (" Found status line for facility = " + facility); the_names := substr (the_names, space_index + 1, length (the_names)); endloop; endif; position (end_of (build_buffer)); copy_text ("return the_fields"); split_line; split_line; copy_text ("endprocedure"); split_line; split_line; message (" "); ! EVE$BUILD.TPU Page 16 the_names := declare_synonyms; if (the_names <> " ") then message (" Building Synonym Initialization Dispatch Procedure..."); ! copy dynamically created synonym procedures and argument variables if get_info (eve$x_synonym_buffer, "type") = BUFFER then copy_text (eve$x_synonym_buffer); endif; ! create procedure to (1) invoke all dynamically created synonym procedures ! of the form _synonym_init that declare argument variables, ! (2) build the string-indexed eve$$x_synonym_array from integer-indexed ! eve$$x_build_array. copy_text ("procedure eve$$init_all_synonyms"); split_line; split_line; the_names := synonym_inits; the_length := length (eve$kt_format_synonym_init) - 1; the_names := the_names + " "; loop exitif (the_names = " "); space_index := index (the_names, " "); if (space_index = 0) then message ("Can't find space in synonym_inits."); return (2); endif; the_name := substr (the_names, 1, space_index - 1); edit (the_name, LOWER); facility := substr (the_name, 1, length (the_name) - the_length); copy_text (the_name + ";"); split_line; message (" Found synonym_init for facility = " + facility); the_names := substr (the_names, space_index + 1, length (the_names)); endloop; endif; position (end_of (build_buffer)); copy_text ("endprocedure"); split_line; split_line; message (" "); ! EVE$BUILD.TPU Page 17 message (" Building Exit Dispatch Procedure Procedure..."); position (build_buffer); copy_text ("procedure eve$exit_dispatch"); split_line; the_names := exit_handlers; if (the_names <> " ") then the_names := the_names + " "; loop exitif (the_names = " "); space_index := index (the_names, " "); if (space_index = 0) then message ("Can't find space in exit dispatch."); return (2); endif; the_name := substr (the_names, 1, space_index - 1); edit (the_name, LOWER); split_line; copy_text (" if "); copy_text (the_name); split_line; copy_text (" then"); split_line; copy_text (" return;"); split_line; copy_text (" endif;"); split_line; message (" Found exit dispatch for facility = " + the_name); the_names := substr (the_names, space_index + 1, length (the_names)); endloop; endif; position (end_of (build_buffer)); if get_info (PROCEDURES, "defined", "eve$exit") then copy_text (" eve$exit;"); split_line; endif; split_line; copy_text ("endprocedure"); split_line; split_line; message (" "); ! EVE$BUILD.TPU Page 18 message (" Building Quit Dispatch Procedure Procedure..."); position (build_buffer); copy_text ("procedure eve$quit_dispatch"); split_line; the_names := quit_handlers; if (the_names <> " ") then the_names := the_names + " "; loop exitif (the_names = " "); space_index := index (the_names, " "); if (space_index = 0) then message ("Can't find space in quit dispatch."); return (2); endif; the_name := substr (the_names, 1, space_index - 1); edit (the_name, LOWER); split_line; copy_text (" if "); copy_text (the_name); split_line; copy_text (" then"); split_line; copy_text (" return;"); split_line; copy_text (" endif;"); split_line; message (" Found quit dispatch for facility = " + the_name); the_names := substr (the_names, space_index + 1, length (the_names)); endloop; endif; position (end_of (build_buffer)); if get_info (PROCEDURES, "defined", "eve$quit") then copy_text (" eve$quit;"); split_line; endif; split_line; copy_text ("endprocedure"); split_line; split_line; message (" "); ! EVE$BUILD.TPU Page 19 message (" Building eve$version procedure..."); position (end_of (build_buffer)); copy_text ("procedure eve$version"); split_line; copy_text (fao (" return '!AS !AS';", product_name, product_version)); split_line; copy_text ("endprocedure"); split_line; temp := substr (build_time, 10, 2) + !** internationalize the following: fao ("!2ZL", index (" JANFEBMARAPRMAYJUNJULAUGSEPOCTNOVDEC", substr (build_time, 4, 3)) / 3) + substr (build_time, 1, 2) + "." + substr (build_time, 13, 2) + substr (build_time, 16, 2) + substr (build_time, 19, 2); position (beginning_of (build_buffer)); copy_text ("procedure eve$dynamic_module_ident"); split_line; copy_text (fao ("return '!AS';", temp)); split_line; copy_text ("endprocedure"); split_line; split_line; ! EVE$BUILD.TPU Page 20 message (" Preserving procedure/variable lists..."); position (end_of (build_buffer)); copy_text ("procedure eve$$build_module_idents"); split_line; split_line; copy_text ("return ("); loop exitif module_idents = ""; space_index := index (module_idents, " "); the_name := substr (module_idents, 1, space_index - 1); module_idents := substr (module_idents, space_index + 1, length (module_idents)); copy_text ("'" + the_name + " ' +"); split_line; copy_text (" "); endloop; copy_text ("'EVE$DYNAMIC_MODULE_IDENT ' + "); split_line; copy_text (" '');"); split_line; split_line; copy_text ("endprocedure;"); split_line; split_line; copy_text ("procedure eve$$build_parser_flags"); split_line; split_line; copy_text ("return ("); loop exitif parser_flags = ""; space_index := index (parser_flags, " "); the_name := substr (parser_flags, 1, space_index - 1); parser_flags := substr (parser_flags, space_index + 1, length (parser_flags)); copy_text ("'" + the_name + " ' +"); split_line; copy_text (" "); endloop; copy_text ("'');"); split_line; split_line; copy_text ("endprocedure;"); split_line; split_line; copy_text ("procedure eve$$build_module_pre_inits"); split_line; split_line; copy_text ("return ("); loop exitif module_pre_inits = ""; space_index := index (module_pre_inits, " "); the_name := substr (module_pre_inits, 1, space_index - 1); module_pre_inits := substr (module_pre_inits, space_index + 1, length (module_pre_inits)); copy_text ("'" + the_name + " ' +"); split_line; copy_text (" "); endloop; copy_text ("'');"); split_line; split_line; copy_text ("endprocedure;"); split_line; split_line; copy_text ("procedure eve$$build_module_inits"); split_line; split_line; copy_text ("return ("); loop exitif module_inits = ""; space_index := index (module_inits, " "); the_name := substr (module_inits, 1, space_index - 1); module_inits := substr (module_inits, space_index + 1, length (module_inits)); copy_text ("'" + the_name + " ' +"); split_line; copy_text (" "); endloop; copy_text ("'');"); split_line; split_line; copy_text ("endprocedure;"); split_line; split_line; copy_text ("procedure eve$$build_declare_synonyms"); split_line; split_line; copy_text ("return ("); loop exitif declare_synonyms = ""; space_index := index (declare_synonyms, " "); the_name := substr (declare_synonyms, 1, space_index - 1); declare_synonyms := substr (declare_synonyms, space_index + 1, length (declare_synonyms)); copy_text ("'" + the_name + " ' +"); split_line; copy_text (" "); endloop; copy_text ("'');"); split_line; split_line; copy_text ("endprocedure;"); split_line; split_line; copy_text ("procedure eve$$build_synonym_inits"); split_line; split_line; copy_text ("return ("); loop exitif synonym_inits = ""; change_case (synonym_inits, UPPER); space_index := index (synonym_inits, " "); the_name := substr (synonym_inits, 1, space_index - 1); synonym_inits := substr (synonym_inits, space_index + 1, length (synonym_inits)); copy_text ("'" + the_name + " ' +"); split_line; copy_text (" "); endloop; copy_text ("'');"); split_line; split_line; copy_text ("endprocedure;"); split_line; split_line; copy_text ("procedure eve$$build_status_fields"); split_line; split_line; copy_text ("return ("); loop exitif status_fields = ""; space_index := index (status_fields, " "); the_name := substr (status_fields, 1, space_index - 1); status_fields := substr (status_fields, space_index + 1, length (status_fields)); copy_text ("'" + the_name + " ' +"); split_line; copy_text (" "); endloop; copy_text ("'');"); split_line; split_line; copy_text ("endprocedure;"); split_line; split_line; copy_text ("procedure eve$$build_exit_handlers"); split_line; split_line; copy_text ("return ("); loop exitif exit_handlers = ""; space_index := index (exit_handlers, " "); the_name := substr (exit_handlers, 1, space_index - 1); exit_handlers := substr (exit_handlers, space_index + 1, length (exit_handlers)); copy_text ("'" + the_name + " ' +"); split_line; copy_text (" "); endloop; copy_text ("'');"); split_line; split_line; copy_text ("endprocedure;"); split_line; split_line; copy_text ("procedure eve$$build_quit_handlers"); split_line; split_line; copy_text ("return ("); loop exitif quit_handlers = ""; space_index := index (quit_handlers, " "); the_name := substr (quit_handlers, 1, space_index - 1); quit_handlers := substr (quit_handlers, space_index + 1, length (quit_handlers)); copy_text ("'" + the_name + " ' +"); split_line; copy_text (" "); endloop; copy_text ("'');"); split_line; split_line; copy_text ("endprocedure;"); split_line; split_line; position (listing_buffer); copy_text (fao ("!15AS !15AS !6UL !AS", " linkage code", temp, get_info (build_buffer, "record_count"), init_file)); ! EVE$BUILD.TPU Page 21 ! Handle conditional compilation (until TPU supports it better) if not eve$$conditional_compile (build_buffer) then return (2); endif; ! ! Time to actually compile the code ! set (INFORMATIONAL, OFF); compile (build_buffer); compile ("procedure eve$$require(temp) endprocedure;"); ! ! List options ! split_line; split_line; eve$insert_option_list; ! ! Do a second module summary if we're building under a section ! file. ! if get_info (COMMAND_LINE, "section") then temp := get_info (COMMAND_LINE, "section_file"); if temp <> "" then split_line; split_line; copy_text (" Module summary"); split_line; copy_text (" --------------"); split_line; split_line; eve$insert_module_summary; endif; endif; ! ! Now that everything is compiled, list the variables and procedures ! in the listing file. ! show (SUMMARY); position (end_of (listing_buffer)); copy_text (ascii (12)); split_line; copy_text ("---------------- Summary ---------------"); split_line; copy_text (create_range (beginning_of (tpu$x_show_buffer), end_of (tpu$x_show_buffer), NONE)); show (VARIABLES); position (end_of (listing_buffer)); copy_text (ascii (12)); split_line; copy_text ("------------ Variables used ------------"); split_line; copy_text (create_range (beginning_of (tpu$x_show_buffer), end_of (tpu$x_show_buffer), NONE)); show (PROCEDURES); position (end_of (listing_buffer)); copy_text (ascii (12)); split_line; copy_text ("--------------- Procedures -------------"); split_line; copy_text (create_range (beginning_of (tpu$x_show_buffer), end_of (tpu$x_show_buffer), NONE)); split_line; ! For V2.0 compatibility: if get_info (PROCEDURES, "defined", "eve$$save_settings") then execute ("eve$$save_settings"); position (end_of (build_buffer)); copy_text (eve$context_buffer); endif; set (SUCCESS, ON); write_file (build_buffer, init_file); write_file (listing_buffer); message (" "); if (dump_buffer <> 0) then write_file (dump_buffer); endif; set (SUCCESS, OFF); compile ("procedure eve$$build endprocedure"); save_command := "on_error [OTHERWISE]: endon_error;" + "save ('" + section_file + "', 'IDENT', '" + product_ident + "'"; if eve$$x_save_names = tpu$k_unspecified then eve$$x_save_names := 0; endif; case eve$$x_save_names [0]: ; [-1]: save_command := save_command + ", 'NO_DEBUG_NAMES'"; [1]: save_command := save_command + ", 'NO_PROCEDURE_NAMES'"; [INRANGE, OUTRANGE]: message ("Eve$$x_save_names was not -1, 0, or 1."); return (2); endcase; if eve$$x_save_changes = tpu$k_unspecified then eve$$x_save_changes := 0; endif; if eve$$x_save_changes then save_command := save_command + ", 'CHANGES_ONLY'"; endif; save_command := save_command + "); return 1;"; set (SUCCESS, ON); set (INFORMATIONAL, ON); if not execute (save_command) then return (2); endif; message ("*** Build complete ***"); return (1); endprocedure; ! eve$$build endmodule; ! EVE$BUILD.TPU Page 22 ! ! Global constant and variable declarations ! variable eve$context_buffer; ! EVE$BUILD.TPU Page 23 ! ! EVE$BUILD time executable code ! ! Call the main build routine, and execute the string it returns. ! If there are no errors this will delete eve$$build and eve$$require, ! and also save the section file. ! quit (OFF, eve$$build);