1 PSM_Routines The print symbiont modification (PSM) routines allow you to modify the behavior of the print symbiont supplied with the operating system. 2 PSM$PRINT The PSM$PRINT routine invokes the OpenVMS-supplied print symbiont. PSM$PRINT must be called exactly once after all user service routines have been specified using PSM$REPLACE. Format PSM$PRINT [streams] [,bufsiz] [,worksiz] [,maxqios] [,options] 3 Returns OpenVMS usage:cond_value type: longword (unsigned) access: write only mechanism: by value Longword condition value. Most utility routines return a condition value in R0. Condition values that this routine can return are listed under Condition Values Returned. 3 Arguments streams OpenVMS usage:longword_unsigned type: longword (unsigned) access: read only mechanism: by reference Maximum number of streams that the symbiont is to support. The streams argument is the address of a longword containing this number, which must be in the range of 1 to 16. If you do not specify streams, a default value of 1 is used. Thus, by default, a user-modified symbiont supports one stream, which is to say that it is a single-threaded symbiont. A stream (or thread) is a logical link between a print execution queue and a printing device. When a symbiont process can accept simultaneous links to more than one queue, that is, when it can service multiple queues simultaneously, the symbiont is said to be multithreaded. bufsiz OpenVMS usage:longword_unsigned type: longword (unsigned) access: read only mechanism: by reference Maximum buffer size in bytes that the print symbiont is to use for output operations. The bufsiz argument is the address of a longword containing the specified number of bytes. The print symbiont actually uses a buffer size that is the smaller of: (1) the value specified by bufsiz or (2) the system parameter MAXBUF. If you do not specify bufsiz, the print symbiont uses the value of MAXBUF. The print symbiont uses this size limit only for output operations. Output operations involve the placing of processed or formatted pages into a buffer that will be passed to the output routine. The print symbiont uses the value specified by bufsiz only as an upper limit; most buffers that it writes will be smaller than this value. worksiz OpenVMS usage:longword_unsigned type: longword (unsigned) access: read only mechanism: by reference Size in bytes of a work area to be allocated for the use of user routines. The worksiz argument is the address of a longword containing this size in bytes. If you do not specify worksiz, no work area is allocated. A separate area of the specified size is allocated for each active symbiont stream. maxqios OpenVMS usage:longword_unsigned type: longword (unsigned) access: read only mechanism: by reference Specifies the maximum number of outstanding $QIOs that a print symbiont stream using the LAT protocol may generate. Set symbiont process quotas large enough to handle the maximum number of QIOs multiplied by the number of streams, using a number between 2 and 32. For normal printing capabilities, the suggested quota is 10; for high-speed printing, use a larger number. options OpenVMS usage:longword_unsigned type: longword (unsigned) access: read only mechanism: by reference Longword bit vector that specifies the LAT protocal option using the PSM$M_LAT_PROTOCOL symbolic value. Note that using the LAT_ PROTOCOL option carries the following restrictions: o Replacement of the output and job completion routines will be overridden o Output device must be a LAT device 3 Description The PSM$PRINT routine must be called exactly once after all user routines have been specified to the print symbiont. Each user routine is specified to the symbiont in a call to the PSM$REPLACE routine. The PSM$PRINT routine allows you to specify whether the print symbiont is to be single-threaded or multithreaded, and if multithreaded, how many streams or threads it can have. In addition, this routine allows you to control the maximum size of the output buffer. 3 Condition_Values_Returned SS$_NORMAL Normal successful completion. This routine also returns any condition values returned by the $SETPRV, $GETSYI, $PURGWS, and $DCLAST system services, as well as any condition values returned by the SMB$INITIALIZE routine. 2 PSM$READ_ITEM_DX The PSM$READ_ITEM_DX routine obtains the value of message items that are sent by the job controller and stored by the symbiont. Format PSM$READ_ITEM_DX request_id ,item ,buffer 3 Returns OpenVMS usage:cond_value type: longword (unsigned) access: write only mechanism: by value Longword condition value. Most utility routines return a condition value in R0. Condition values that this routine can return are listed under Condition Values Returned. 3 Arguments request_id OpenVMS usage:address type: longword (unsigned) access: read only mechanism: by reference Request identifier supplied by the symbiont to the user routine currently calling PSM$READ_ITEM_DX. The symbiont always supplies a request identifier when it calls a user routine with a service request. The request_id argument is the address of a longword containing this request identifier value. Your user routine must copy the request identifier value that the symbiont supplies (in the request_id argument) when it calls your user routine. Then, when your user routine calls PSM$READ_ITEM_ DX, it must supply (in the request_id argument) the address of the request identifier value that it copied. item OpenVMS usage:longword_unsigned type: longword (unsigned) access: read only mechanism: by reference Item code that identifies the message item that PSM$READ_ITEM_DX is to return. The item argument is the address of a longword that specifies the item's code. buffer OpenVMS usage:char_string type: character string access: write only mechanism: by descriptor Buffer into which PSM$READ_ITEM_DX returns the specified informational item. The buffer argument is the address of a descriptor pointing to this buffer. The PSM$READ_ITEM_DX routine returns the specified informational item by copying that item to the buffer using one of the STR$COPY_xx routines documented in the OpenVMS RTL String Manipulation (STR$) Manual. 3 Description The PSM$READ_ITEM_DX routine obtains the value of message items that are sent by the job controller and stored by the symbiont. Use PSM$READ_ITEM_DX to obtain information about the task currently being processed, for example, the name of the file being printed (SMBMSG$K_FILE_SPECIFICATION) or the name of the user who submitted the job (SMBMSG$K_USER_NAME). 3 Condition_Values_Returned SS$_NORMAL Normal successful completion. PSM$_INVITMCOD Invalid item code specified in the item argument. This routine also returns any condition values returned by any of the STR$COPY_xx routines documented in the OpenVMS RTL String Manipulation (STR$) Manual. 2 PSM$REPLACE The PSM$REPLACE routine substitutes a user service routine for a symbiont routine or adds a user service routine to the set of symbiont routines. You must call PSM$REPLACE once for each routine that you replace or add. Format PSM$REPLACE code ,routine 3 Returns OpenVMS usage:cond_value type: longword (unsigned) access: write only mechanism: by value Longword condition value. Most utility routines return a condition value in R0. The condition value that this routine can return is listed under Condition Value Returned. 3 Arguments code OpenVMS usage:longword_unsigned type: longword (unsigned) access: read only mechanism: by reference Routine code that identifies the symbiont routine to be replaced by a user service routine. The code argument is the address of a longword containing the routine code. Some routine codes identify routines that are supplied with the symbiont; when you specify such a routine code, you replace the symbiont-supplied routine with your service routine. Two routine codes identify routines that are not supplied with the symbiont; when you specify such a routine code, your service routine is added to the set of symbiont routines. Each programming language provides an appropriate mechanism for defining these routine codes. The following pages list each routine code in alphabetical order; the description of each code includes the following information about its corresponding routine: o Whether the routine is supplied by the symbiont o Whether the routine is an input, formatting, or output routine o Under what conditions the routine is called o What task the routine performs 3 Routine_Codes PSM$K_FILE_BURST This code identifies a symbiont-supplied input routine; it is called whenever a file burst page is requested. This routine obtains information about the job, formats the file burst page, and returns the contents of the page to the input buffer. A file burst page follows a file flag page and precedes the contents of the file. PSM$K_FILE_ERRORS This code identifies a symbiont-supplied input routine; it is called when errors have occurred during the job. This routine places the error message text in the input buffer. PSM$K_FILE_FLAG This code identifies a symbiont-supplied input routine; it is called whenever a file flag page is requested. This routine obtains information about the job, formats the file flag page, and returns the contents of the page to the input buffer. A flag page follows the job burst page (if any) and precedes the file burst page (if any). It contains such information as the file specification of the file and the name of the user issuing the print request. PSM$K_FILE_INFORMATION This code identifies a symbiont-supplied input routine; it is called when the file information item has been specified by the job controller. This routine expands the file information item to text and returns it to the input buffer. PSM$K_FILE_SETUP This code identifies a symbiont-supplied input routine; it is always called. This routine queues any specified file-setup modules for insertion in the input stream when the PSM$K_FILE_ SETUP routine closes. PSM$K_FILE_SETUP_2 This code identifies a symbiont-supplied input routine; it is always called. This routine returns a form feed to ensure that printing of the file begins at the top of the page. This routine is called just before the main input routine. PSM$K_FILE_TRAILER This code identifies a symbiont-supplied input routine; it is called whenever a file trailer page is requested. This routine obtains information about the job, formats the file trailer page, and returns the contents of the page to the input buffer. A trailer page follows the last page of the file contents. PSM$K_MAIN_FORMAT This code identifies the symbiont-supplied formatting routine; it is always called. This routine performs numerous formatting functions. You cannot replace this routine. PSM$K_FORM_SETUP This code identifies a symbiont-supplied input routine; it is always called. This routine queues any specified form-setup modules for insertion in the input stream when the PSM$K_FORM_ SETUP routine closes. PSM$K_INPUT_FILTER This code identifies a format routine that is not supplied by the symbiont. If the routine is supplied by the user, it is always called immediately prior to the symbiont-supplied formatting routine (routine code PSM$K_MAIN_FORMAT). An input-filter service routine is useful for modifying input data records and their carriage control before they are formatted by the symbiont. PSM$K_JOB_BURST This code identifies a symbiont-supplied input routine; it is called whenever a job burst page is requested. This routine obtains information about the job, formats the job burst page, and returns the contents of the page to the input buffer. A job burst page follows the job flag page and precedes the file flag page (if any) of the first file in the job. It is similar to a file burst page except that it appears only once per job and only at the beginning of the job. PSM$K_JOB_COMPLETION This code identifies a symbiont-supplied input routine that returns a form feed, which causes any output stored by the device to be printed. The routine is always called. It cannot be replaced when using the LAT protocol option. PSM$K_JOB_FLAG This code identifies a symbiont-supplied input routine; it is called whenever a job flag page is requested. This routine obtains information about the job, formats the job flag page, and returns the contents of the page to the input buffer. A job flag page is similar to a file flag page except that it appears only once per job, preceding the job burst page (if any). PSM$K_JOB_RESET This code identifies a symbiont-supplied input routine; it is always called. This routine queues any specified job-reset modules for insertion in the input stream when the PSM$K_JOB_ RESET routine closes. PSM$K_JOB_SETUP This code identifies a symbiont-supplied input routine; it is always called. This routine checks to see if this is the first job to be printed on the device, and if so, it issues a form feed and then performs a job reset. See the description of the PSM$K_ JOB_RESET routine for information about job reset. PSM$K_JOB_TRAILER This code identifies a symbiont-supplied input routine; it is called whenever a job trailer page is requested. This routine obtains information about the job, formats the job trailer page, and returns the contents of the page to the input buffer. A job trailer page is similar to a file trailer page except that it appears only once per job, as the last page in the job. PSM$K_MAIN_INPUT This code identifies a symbiont-supplied input routine; it is always called. This routine opens the file to be printed, returns input records to the input buffer, and closes the file. PSM$K_LIBRARY_INPUT This code identifies a symbiont-supplied input routine; it is called when an input routine closes and when modules have been requested for insertion in the input stream. This routine returns the contents of the specified modules, one record per call. You cannot replace this routine. PSM$K_OUTPUT_FILTER This code identifies a formatting routine that is not supplied by the symbiont. If the routine is supplied by the user, it is always called. This routine executes prior to the symbiont output routine (routine code PSM$K_OUTPUT). An output-filter service routine is useful for modifying output data buffers before they are passed to the output routine. At the point where the output-filter routine executes within the symbiont execution stream, the input data is no longer in record format; instead, the data exists as a stream of characters. The carriage control, for example, is embedded in the data stream. Thus, the output buffer might contain what was once a complete record, part of a record, or several records. PSM$K_PAGE_HEADER This code identifies a symbiont-supplied input routine; it is called once at the beginning of each page if page headers are requested. This routine returns to the input buffer one or more lines containing information about the file being printed and the current page number. This routine is called only while the main input routine is open. PSM$K_PAGE_SETUP This code identifies a symbiont-supplied routine; it is called at the beginning of each page if page-setup modules were specified. This routine queues any specified page-setup modules for insertion in the input stream when the PSM$K_PAGE_SETUP routine closes. This routine is called only while the main input routine is open. PSM$K_OUTPUT This code identifies the symbiont-supplied output routine that writes the contents of the output buffer to the printing device, together with many other functions. This routine is always called. It cannot be replaced when using the LAT protocol option. routine OpenVMS usage:procedure type: procedure value access: read only mechanism: by reference User service routine that is to replace a symbiont routine or to be included. The routine argument is the address of the user routine entry point. 3 Description The PSM$REPLACE routine must be called each time a user service routine replaces a symbiont routine or is added to a set of symbiont routines. The code argument specifies the symbiont routine to be replaced. The routine codes that can be specified in the code argument are of two types: those that identify existing print symbiont routines and those that do not. All the routine codes are similar, however, in the sense that each supplies a location within the print symbiont execution stream where your routine can execute. By selecting a routine code that identifies an existing symbiont routine, you effectively disable that symbiont routine. The service routine that you specify might or might not perform the function that the disabled symbiont routine performs. If it does not, the net effect of the replacement is to eliminate that function from the list of functions performed by the print symbiont. Exactly what your service routine does is up to you. By selecting a routine code that does not identify an existing symbiont routine (those that identify the input-filter and output-filter routines), your service routine has a chance to execute at the location signified by the routine code. Because the service routine you specify to execute at this location does not replace another symbiont routine, your service routine is an addition to the set of symbiont routines. As mentioned, each routine code identifies a location in the symbiont execution stream, whether or not it identifies a symbiont routine. 3 Condition_Value_Returned SS$_NORMAL Normal successful completion. 2 PSM$REPORT The PSM$REPORT routine reports to the print symbiont the completion status of an asynchronous operation initiated by a user routine. Such a user routine must return the completion status PSM$_ PENDING. PSM$REPORT must be called exactly once for each time a user routine returns the status PSM$_PENDING. Format PSM$REPORT request_id [,status] 3 Returns OpenVMS usage:cond_value type: longword (unsigned) access: write only mechanism: by value Longword condition value. Most utility routines return a condition value in R0. The condition value that this routine can return is listed under Condition Value Returned. 3 Arguments request_id OpenVMS usage:address type: longword (unsigned) access: read only mechanism: by reference Request identifier supplied by the symbiont to the user routine at the time the symbiont called the user routine with the service request. The user routine must return the completion status PSM$_ PENDING on the call for this service request. The request_id argument is the address of a longword containing the request identifier value. The symbiont calls the user routine with a request code that specifies the function that the symbiont expects the user routine to perform. In the call, the symbiont also supplies a request identifier, which serves to identify the request. If the user routine initiates an asynchronous operation, a mechanism is required for notifying the symbiont that the asynchronous operation has completed and for providing the completion status of the operation. The PSM$REPORT routine conveys the above two pieces of information. In addition, PSM$REPORT returns to the symbiont (in the request_id argument) the same request identifier value as that supplied by the symbiont to the user routine that initiated the operation. In this way, the symbiont synchronizes the completion status of an asynchronous operation with that invocation of the user routine that initiated the operation. Any user routine that initiates an asynchronous operation must, therefore, copy the request identifier value that the symbiont supplies (in the request_id argument) when it calls the user routine. The user routine will later need to supply this value to PSM$REPORT. In addition, when the user routine returns, which it does before the asynchronous operation has completed, the user routine must return the status PSM$_PENDING. status OpenVMS usage:cond_value type: longword (unsigned) access: read only mechanism: by reference Completion status of the asynchronous operation that has completed. The status argument is the address of a longword containing this completion status. The status argument is optional; if it is not specified, the symbiont assumes the completion status SS$_NORMAL. The user routine that initiates the asynchronous operation must test for the completion of the operation and must supply the operation's completion status as the status argument to the PSM$REPORT routine. The Description section describes this procedure in greater detail. If the completion status specified by status has the low bit clear, the symbiont aborts the task. 3 Description An asynchronous operation is an operation that, once initiated, executes "off to the side" and need not be completed before other operations can begin to execute. Asynchronous operations are common in symbiont applications because a symbiont, if it is multithreaded, must handle concurrent I/O operations. One example of a user routine that performs an asynchronous operation is an output routine that calls the $QIO system service to write a record to the printing device. When the user output routine completes execution, the I/O request queued by $QIO might not have completed. In order to synchronize this I/O request, that is, to associate the I/O request with the service request that initiated it, you should use the following mechanism: 1. In making the call to $QIO, specify the astadr and iosb arguments. The astadr argument specifies an AST routine to execute when the queued output request has completed, and the iosb argument specifies an I/O status block to receive the completion status of the I/O operation. Step 3 describes some functions that your AST routine will need to do. 2. Have the user output routine return the status PSM$_PENDING. 3. Write the AST routine to perform the following functions: a. Copy the completion status word from the I/O status block to a longword location that you will specify as the status argument in the call to PSM$REPORT. b. Call PSM$REPORT. Specify as the request_id argument the request identifier that was supplied by the print symbiont in the original call to the user output routine. 3 Condition_Value_Returned SS$_NORMAL Normal successful completion. 2 USER-FORMAT-ROUTINE The user-written USER-FORMAT-ROUTINE performs format operations. The symbiont's control logic routine calls your format routine at one of two possible points within the symbiont's execution stream. You select this point by specifying one of two routine codes when you call the PSM$REPLACE routine. A user format routine can be an input filter routine (routine code PSM$K_INPUT_FILTER) or an output filter routine (routine code PSM$K_OUTPUT_FILTER). The main format routine (routine code PSM$K_MAIN_FORMAT) cannot be replaced. A user format routine must use the call interface described here. Format USER-FORMAT-ROUTINE request_id ,work_area ,func ,func_desc_1 ,func_arg_1 ,func_desc_2 ,func_arg_2 3 Returns OpenVMS usage:cond_value type: longword (unsigned) access: write only mechanism: by value Longword condition value. Most utility routines return a condition value in R0. Condition values that this routine can return are listed under Condition Values Returned. 3 Arguments request_id OpenVMS usage:address type: longword (unsigned) access: read only mechanism: by reference Request identifier supplied by the symbiont when it calls your format routine. The request_id argument is the address of a longword containing this request identifier value. work_area OpenVMS usage:address type: longword (unsigned) access: write only mechanism: by reference Work area supplied by the symbiont for the use of your format routine. The symbiont supplies the address of this area when it calls your routine. The work_area argument is a longword containing the address of the work area. The work area is a section of memory that your format routine can use for buffering and other internal operations. The size of the work area allocated is specified by the work_size argument in the PSM$PRINT routine. If you do not specify work_ size in the call to PSM$PRINT, no work area is allocated. In a multithreaded symbiont, a separate work area is allocated for each thread. This work area is shared by all user routines. The work area is initialized to zero when the symbiont is first started. func OpenVMS usage:function_code type: longword (unsigned) access: read only mechanism: by reference Function code specifying the service that the symbiont expects your format routine to perform. The func argument is the address of a longword into which the symbiont writes this function code. The function code specifies the reason the symbiont is calling your format routine or, in other words, the service that the symbiont expects your routine to perform at this time. The PSM$K_FORMAT function code is the only one to which your format routine must respond. When the symbiont calls your format routine with this function code, your routine must move a record from the input buffer to the output buffer. The symbiont can call your format routine with other function codes. Your routine should return the status PSM$_FUNNOTSUP (function not supported) when it is called with any of the following function codes or with any undocumented function code. When the status PSM$_FUNNOTSUP is returned, the symbiont performs its normal action as if no format routine were supplied. To suppress the symbiont's normal action, you should return SS$_ NORMAL. PSM$K_START_STREAM PSM$K_STOP_STREAM PSM$K_START_TASK PSM$K_PAUSE_TASK PSM$K_RESUME_TASK PSM$K_STOP_TASK PSM$K_RESET_STREAM These function codes correspond to message items sent by the job controller to the symbiont. Other function codes correspond to internal symbiont mechanisms that are not part of the public interface to the print symbiont. Your format routine should return the status PSM$_FUNNOTSUP or SS$_NORMAL when it is called with a message function code or with a private function code. func_desc_1 OpenVMS usage:char_string type: character string access: read only mechanism: by descriptor Descriptor supplying an input record to be processed by the format routine. The func_desc_1 argument is the address of a string descriptor. By using this argument, the symbiont supplies the input record that your format routine is to process. Because this descriptor can be of any valid string type, your format routine should use the Run-Time Library string routines to analyze this descriptor and to manipulate the input record. func_arg_1 OpenVMS usage:vector_byte_unsigned type: byte (unsigned) access: read only mechanism: by reference Carriage control for the input record supplied by func_desc_ 1. The func_arg_1 argument is the address of a 4-byte vector that specifies the carriage control for the input record. The following diagram depicts the format of this 4-byte vector: Bytes 0 and 1 describe the leading carriage control to apply to the input data record; bytes 2 and 3 describe the trailing carriage control. Byte 0 is a number specifying the number of times the carriage control specifier in byte 1 is to be repeated preceding the input data record. Byte 2 is a number specifying the number of times the carriage control specifier in byte 3 is to be repeated following the input data record. For values of the carriage control specifier from 1 to 255, the specifier is the ASCII character to be used as carriage control. Value 0 represents the ASCII "newline" sequence. Newline consists of a carriage return followed by a linefeed. The func_arg_1 argument is not used if your format routine is an output filter routine (routine code PSM$K_OUTPUT_FILTER). See the Description section for more information. func_desc_2 OpenVMS usage:char_string type: character string access: write only mechanism: by reference Descriptor of a buffer to which your format routine writes the formatted output record. The func_desc_2 argument is the address of a string descriptor. Your format routine must return the formatted data record by using the func_desc_2 argument. Your format routine should use the Run-Time Library string routines to write into the buffer specified by this descriptor. func_arg_2 OpenVMS usage:vector_byte_unsigned type: byte (unsigned) access: write only mechanism: by reference Carriage control for the output record returned in func_desc_2. The func_arg_2 argument is the address of a 4-byte vector that specifies the carriage control for the output record. See the description of func_arg_1 for the contents and format of this 4-byte vector. If you do not process the carriage-control information supplied in func_arg_1, then you should copy that value into func_arg_2. Otherwise, the carriage-control information will be lost. The func_arg_2 argument is not used if your format routine is an output filter routine (routine code PSM$K_OUTPUT_FILTER). See the Description section for more information. 3 Description When used, the func_arg_1 argument describes carriage-control information for the input data record, and the func_arg_2 argument describes carriage-control information for the output data record. The input data record is passed to the format routine (input filter or output filter) for processing, and the output data record is returned by the format routine (input filter or output filter). One of the tasks performed by the main format routine (routine code PSM$K_MAIN_FORMAT) is that of embedding the carriage-control information (specified by func_arg_1) into the data record (specified by func_desc_1). Thus, the output data (specified by func_desc_2) contains embedded carriage control and is thus no longer in record format; it is, therefore, properly referred to as an output data stream rather than an output data record. Similarly, the output filter routine (routine code PSM$K_OUTPUT_ FILTER), which executes after the main format routine, uses neither the func_arg_1 nor func_arg_2 argument; the data it receives (via func_desc_1) and the data it returns (via func_ desc_2) are data streams, not data records. However, the input filter routine (routine code PSM$K_INPUT_ FILTER), which executes before the main format routine, uses both func_arg_1 and func_arg_2. This is so because the main format routine has not yet executed, and so the carriage control information has not yet been embedded in the data record. 3 Condition_Values_Returned SS$_NORMAL Successful completion. The user format routine has completed the function that the symbiont requested. PSM$_FUNNOTSUP Function not supported. The user format routine does not support or does not recognize the function code supplied by the symbiont. To ensure future compatibility, your format routine should return this status for any unrecognized status codes. This routine also returns any error condition values that you have coded your format routine to return. 2 USER-INPUT-ROUTINE The user-written USER-INPUT-ROUTINE performs input operations. The symbiont calls your routine at a specified point in its execution stream; you specify this point using the PSM$REPLACE routine. Format USER-INPUT-ROUTINE request_id ,work_area ,func ,funcdesc ,funcarg 3 Returns OpenVMS usage:cond_value type: longword (unsigned) access: write only mechanism: by value Longword condition value. Most utility routines return a condition value in R0. Condition values that this routine can return are listed under Condition Values Returned. 3 Arguments request_id OpenVMS usage:address type: longword (unsigned) access: read only mechanism: by reference Request identifier value supplied by the symbiont when it calls your input routine. The request_id argument is the address of a longword containing this request identifier value. If your input routine initiates an asynchronous operation (for example, a call to the $QIO system service), your input routine must copy the request identifier value specified by request_ id because this value must later be passed to the PSM$REPORT routine. See the description of the PSM$REPORT routine for more information. work_area OpenVMS usage:address type: longword (unsigned) access: write only mechanism: by reference Work area supplied by the symbiont for the use of your input routine. The symbiont supplies the address of this area when it calls your routine. The work_area argument is a longword into which the symbiont writes the address of the work area. The work area is a section of memory that your input routine can use for buffering and for other internal operations. The size of the work area allocated is specified by the work_size argument in the PSM$PRINT routine. If you do not specify work_ size in the call to PSM$PRINT, no work area is allocated. In a multithreaded symbiont, a separate work area is allocated for each thread. This work area is shared by all user routines. The work area is initialized to zero when the symbiont is first started. func OpenVMS usage:function_code type: longword (unsigned) access: read only mechanism: by reference Function code supplied by the symbiont when it calls your input routine. The func argument is the address of a longword containing this code. The function code specifies the reason the symbiont is calling your input routine or, in other words, the function that the symbiont expects your routine to perform at this time. Most function codes require or allow additional information to be passed in the call by means of the funcdesc and funcarg arguments. The description of each input function code, therefore, includes a description of how these two arguments are used with that function code. Following is a list of all the function codes that the symbiont can specify when it calls your input routine (function codes applicable only to format and output routines are explained in the descriptions of the USER-FORMAT-ROUTINE and USER-OUTPUT- ROUTINE, respectively); all function codes are defined by the $PSMDEF macro. 3 Function_Codes_for_Input_Routines PSM$K_CLOSE When the symbiont calls your routine with this function code, your routine must terminate processing by releasing any resources it might have allocated. The symbiont calls your routine with PSM$K_CLOSE when (1) your routine returns from a PSM$K_READ function call with the status PSM$_EOF (end of input) or with any error condition, or (2) the symbiont receives a task-abortion request from the job controller. In any event, the symbiont always calls your input routine with PSM$K_CLOSE if your routine returns successfully from a PSM$K_OPEN function call. This guaranteed behavior ensures that any resources your routine might have allocated on the OPEN will be released on the CLOSE. PSM$K_GET_KEY Typically, the use of both the PSM$K_GET_KEY and PSMK$K_POSITION_ TO_KEY function codes is appropriate only for a main input routine (routine code PSM$K_MAIN_INPUT). When the symbiont calls your routine with this function code, your routine can do one of two things: (1) return PSM$_FUNNOTSUP (function not supported) or (2) return an input marker string to the symbiont. If your routine returns PSM$_FUNNOTSUP to this function code, then your routine must also return PSM$_FUNNOTSUP if the symbiont subsequently calls your routine with the PSM$K_POSITION_TO_KEY function code. By returning PSM$_FUNNOTSUP, your routine is choosing not to respond to the symbiont request. If your routine chooses to respond to the PSM$K_GET_KEY function code, your routine must return an input marker string to the symbiont; this input marker string identifies the input record that your input routine most recently returned to the symbiont. Subsequently, when the symbiont calls your input routine with the PSM$K_POSITION_TO_KEY function code, the symbiont passes your input routine one of the input marker strings that your input routine has returned on a previous PSM$K_GET_KEY function call. Using this marker string, your input routine must position itself so that, on the next PSM$K_READ call from the symbiont, your input routine will return (or reread) the input record identified by the marker string. Coding your input routine to respond to PSM$K_GET_KEY and PSM$K_POSITION_TO_KEY allows the modified symbiont to perform the file-positioning functions specified by the DCL commands START/QUEUE/FORWARD, START/QUEUE/ALIGN, START/QUEUE/TOP_OF_ FILE, START/QUEUE/SEARCH, and START/QUEUE/BACKWARD. These file positioning functions also depend on the job controller's checkpointing capability for print jobs. Note that your input routine might be called with a marker string that was originally returned in a different process context from the current one. This can occur because marker strings are sometimes stored in the queue-data file across system shutdowns or different invocations of your symbiont. The funcdesc argument specifies the address of a string descriptor. Your routine must return the marker string by way of this argument. Compaq recommends that you use one of the Run- Time Library string routines to copy the marker string to the descriptor. The symbiont periodically calls your input routine with the PSM$K_GET_KEY function code when the symbiont wants to save a marker to a particular input record. PSM$K_OPEN When the symbiont calls your routine with this function code, your routine should prepare for input operations by performing such tasks as allocating necessary resources, initializing storage areas, opening an input file, and so on. Typically, the next time the symbiont calls your input routine, the symbiont will specify the PSM$K_READ function code. Note, however, that under some circumstances the symbiont might follow an OPEN call immediately with a CLOSE call. The funcdesc argument points to the name of the file to be opened. Your routine can use this file specification or the file identification to open the file. The funcarg argument specifies the address of a longword. Your input routine must return, in this longword, the carriage control type that is to be applied to the input records that your input routine will provide. The symbiont formatting routine requires this information to determine where to apply leading and trailing carriage control characters to the input records that your input routine will provide. The $PSMDEF macro defines the following four carriage control types: Carriage Control Type Description PSM$K_CC_ Implied carriage control. For this type, the IMPLIED symbiont inserts a leading line feed (LF) and trailing carriage return (CR) in each input record. This is the default carriage control type; it is used if your routine does not supply a carriage control type in the funcarg argument in response to the PSM$K_OPEN function call. PSM$K_CC_ Fortran carriage control. For this type, the FORTRAN symbiont extracts the first byte of each input record and interprets the byte as a Fortran carriage control character, which it then applies to the input record. PSM$K_CC_PRINT PRN carriage control. For this type, the symbiont generates carriage control from a 2-byte record header that your input routine supplies, with each READ call, in the funcarg argument. The funcarg argument specifies the address of a longword to receive this 2-byte header record, which appears only in PRN print files. PSM$K_CC_ Embedded carriage control. For this type, the INTERNAL symbiont supplies no carriage control to input records. Carriage control is assumed to be embedded in the input records. PSM$K_POSITION_TO_KEY When the symbiont calls your routine with this function code, your routine must locate the point in the input stream designated by the marker string that your routine returned to the symbiont on the PSM$K_GET_KEY function call. The next time the symbiont calls your routine, the symbiont specifies the PSM$K_READ function call, expecting to receive the next sequential input record. After rereading this record, subsequent READ calls proceed from this new position of the file. This is not a one-time rereading of a single record but a repositioning of the file. The symbiont calls your routine with this function code when the job controller receives a request to resume printing at a particular page. Refer to the description of the PSM$K_GET_KEY for more information. PSM$K_READ When the symbiont calls your routine with this function code, your routine must return an input record. The symbiont repeatedly calls your input routine with the PSM$K_READ function code until: (1) your routine indicates end of input by returning the status PSM$_EOF, (2) your routine or another routine returns an error status, or (3) the symbiont receives an asynchronous task-abortion request from the job controller. The funcdesc argument specifies the address of a string descriptor. Your routine must return the input record by using this argument. Compaq recommends that you use one of the Run- Time Library string routines to copy the input record to the descriptor. The funcarg argument specifies the address of a longword. This argument is used only if the carriage control type returned by your input routine on the PSM$K_OPEN function call was PSM$K_ CC_PRINT. In this case, your input routine must supply, in the funcarg argument, the 2-byte record header found at the beginning of each input record. PSM$K_REWIND When the symbiont calls your routine with this function code, your routine must do one of two things: (1) return PSM$_ FUNNOTSUP (function not supported) or (2) locate the point in the input stream designated as the beginning of the file. If your routine returns PSM$_FUNNOTSUP to this function code, then the symbiont subsequently calls your input routine with a PSM$K_CLOSE function call followed by a PSM$K_OPEN function call. By returning PSM$_FUNNOTSUP, your routine is choosing not to support the repositioning of the input service to the beginning of the file. The symbiont, therefore, performs the desired function by closing and then reopening the input routine. You cannot use the funcdesc and the funcarg arguments with this function code. This function call allows the modified symbiont to perform the file-positioning functions specified by the DCL commands START/QUEUE/TOP_OF_FILE, START/QUEUE/FORWARD, START/QUEUE/BACKWARD, START/QUEUE/SEARCH, and START/QUEUE/ALIGN. This is a required repositioning of the file. Other Input Function Codes The symbiont can call your input routine with other function codes. Your routine must return the status PSM$_FUNNOTSUP (function not supported) when it is called with any of the following function codes or with any undocumented function code. When the status PSM$_FUNNOTSUP is returned, the symbiont performs its normal action as if no input routine were supplied. To suppress the symbiont's normal action, you should return SS$_ NORMAL. PSM$K_START_STREAM PSM$K_STOP_STREAM PSM$K_START_TASK PSM$K_PAUSE_TASK PSM$K_RESUME_TASK PSM$K_STOP_TASK PSM$K_RESET_STREAM These function codes correspond to message items sent by the job controller to the symbiont. Other function codes correspond to internal symbiont mechanisms that are not part of the public interface to the print symbiont. Your input routine should return the status PSM$_FUNNOTSUP or SS$_NORMAL when it is called with a message function code or with a private function code. funcdesc OpenVMS usage:char_string type: character string access: read only mechanism: by descriptor Function descriptor supplying information related to the function specified by the func argument. The funcdesc argument is the address of this descriptor. The contents of the function descriptor can vary for each function. Refer to the description of each function code to determine the contents of the function descriptor. In some cases, the function descriptor is not used at all. funcarg OpenVMS usage:longword_unsigned type: longword (unsigned) access: read only mechanism: by reference Function argument supplying information related to the function specified by the func argument. The funcarg argument is the address of a longword containing this function argument. This argument can be an input or an output argument, depending on the function request, but is usually used as an output argument. 3 Condition_Values_Returned SS$_NORMAL Successful completion. The user input routine has completed the function that the symbiont requested. PSM$_FLUSH Flush output stream. The user input routine can return this status only when called with the PSM$K_READ function code. When this status is returned to the symbiont, the symbiont stops calling the input routine with the PSM$K_READ function code until all outstanding format and output operations have completed. PSM$_FUNNOTSUP Function not supported. The user input routine does not support or does not recognize the function code supplied by the symbiont. To ensure future compatibility, your input routine should return this status for any unrecognized status codes. PSM$_PENDING Requested function accepted but not completed. Your input routine can return this status only with the PSM$K_READ function call. Further, if your routine returns PSM$_PENDING, your routine must eventually signal completion via the PSM$REPORT routine. Refer to the description of the PSM$REPORT routine for more information about asynchronous operations and the PSM$_PENDING condition value. This routine also returns any error condition values that you have coded your format routine to return. 2 USER-OUTPUT-ROUTINE The user-written USER-OUTPUT-ROUTINE performs output operations. You supply a user output routine by calling the PSM$REPLACE routine with the routine code PSM$K_OUTPUT. Format USER-OUTPUT-ROUTINE request_id ,work_area ,func ,funcdesc ,funcarg 3 Returns OpenVMS usage:cond_value type: longword (unsigned) access: write only mechanism: by value Longword condition value. Most utility routines return a condition value in R0. Condition values that this routine can return are listed under Condition Values Returned. 3 Arguments request_id OpenVMS usage:address type: longword (unsigned) access: read only mechanism: by reference Request identifier value supplied by the symbiont when it calls your output routine. The request_id argument is the address of a longword containing this value. If your output routine initiates an asynchronous operation (for example, a call to the $QIO system service), you must save the request_id argument because you will need to store the request identifier value for later use with the PSM$REPORT routine. See the description of the PSM$REPORT routine for more information. work_area OpenVMS usage:address type: longword (unsigned) access: write only mechanism: by reference Work area supplied by the symbiont for the use of your format routine. The symbiont supplies the address of this area when it calls your routine. The work_area argument is a longword containing the address of the work area. The work area is a section of memory that your format routine can use for buffering and other internal operations. The size of the work area allocated is specified by the work_size argument in the PSM$PRINT routine. If you do not specify work_ size in the call to PSM$PRINT, no work area is allocated. In a multithreaded symbiont, a separate work area is allocated for each thread. This work area is shared by all user routines. The work area is initialized to zero when the symbiont is first started. func OpenVMS usage:function_code type: longword (unsigned) access: read only mechanism: by reference Function code supplied by the symbiont when it calls your output routine. The func argument is the address of a longword containing this code. The function code specifies the reason the symbiont is calling your output routine or, in other words, the function that the symbiont expects your routine to perform at this time. Most function codes require or allow additional information to be passed in the call via the funcdesc and funcarg arguments. The description of each output function code, therefore, includes a description of how these two arguments are used for that function code. The following list describes all the function codes that the symbiont might supply when it calls your output routine (function codes applicable only to input and formatting routines are explained in the descriptions of the user input routine and user formatting routine, respectively). Each programming language provides an appropriate mechanism for defining these function codes. 3 Function_Codes_for_Output_Routines PSM$K_OPEN When the symbiont calls your output routine with this function code, your routine should prepare to move data to the device by performing such tasks as allocating the device, assigning a channel to the device, and so on. The next time the symbiont calls your output routine, the symbiont specifies one of the WRITE function codes (PSM$K_WRITE or PSM$K_WRITE_NOFORMAT). The symbiont calls your output routine with the PSM$K_OPEN function code when the symbiont receives the SMBMSG$K_START_ STREAM message from the job controller. If your output routine returns an error condition value (low bit clear) to the PSM$K_OPEN function call, the job controller stops processing on the stream and reports the error to whomever entered the DCL command START/QUEUE. The funcdesc argument is the address of a descriptor that identifies the name of the device to which the output routine is to write. This device name is established by the DCL command INITIALIZE/QUEUE/ON=device. The funcarg argument is the address of a longword into which the user output routine returns the device status longword. Your output routine sets bits in the device status longword to indicate to the job controller whether the device falls into one of the following categories: o Can print lowercase letters o Is a terminal o Is connected to the CPU by means of a modem (remote) If your output routine does not set any of these bits in the device status longword, the job controller assumes, by default, that the device is a line printer that prints only uppercase letters. PSM$K_WRITE When the symbiont calls your routine with this function code, your routine must write data to the device. The symbiont supplies the data to be written in the funcdesc argument. Compaq recommends that you use one of the Run-Time Library string routines to access the data in the buffer described by the funcdesc argument. PSM$K_WRITE_NOFORMAT When the symbiont calls your routine with this function code, your routine must write data to the device and must indicate to the device driver that the data is not to be formatted. The symbiont calls your routine with this function code when: (1) the print request specifies the PASSALL option or (2) data is introduced by the ANSI DCS (device control string) escape sequence. The symbiont supplies the data to be written in the funcdesc argument. Compaq recommends that you use one of the Run-Time Library string routines to move the data from the descriptor to the device. The output routine of the symbiont informs the device driver not to format the data in the following way: o When the device is a line printer, the symbiont's output routine specifies the IO$_WRITEPBLK function code when it calls the $QIO system service. o When the device is a terminal, the symbiont's output routine specifies the IO$M_NOFORMAT function modifier when it calls the $QIO system serivce. PSM$K_CANCEL When the symbiont calls your routine with this function code, your routine must abort any outstanding asynchronous I/O requests. The output routine supplied by the symbiont aborts outstanding I/O requests by calling the $CANCEL system service with the IO$_ CANCEL function code. If your output routine returned the condition value PSM$_ PENDING to one or more previous write requests that are still outstanding (that is, PSM$REPORT has not yet been called to report completion), then your output routine must call PSM$REPORT one time for each outstanding write request that is canceled with this call. That is, canceling an asynchronous write request does not relieve the user output routine of the requirement to call PSM$REPORT once for each asynchronous write request. You cannot use the funcdesc and funcarg arguments with this function code. PSM$K_CLOSE When the symbiont calls your routine with this function code, your output routine must terminate processing and release any resources it allocated (for example, channels assigned to the device). You cannot use the funcdesc and funcarg arguments with this function code. Other Output Function Codes The symbiont can call your output routine with other function codes. Your routine should return the status PSM$_FUNNOTSUP (function not supported) when it is called with any of the following function codes or with any undocumented function code. When the status PSM$_FUNNOTSUP is returned, the symbiont performs its normal action as if no output routine were supplied. To suppress the symbiont's normal action, you should return SS$_ NORMAL. PSM$K_START_STREAM PSM$K_STOP_STREAM PSM$K_START_TASK PSM$K_PAUSE_TASK PSM$K_RESUME_TASK PSM$K_STOP_TASK PSM$K_RESET_STREAM These function codes correspond to message items sent by the job controller to the symbiont. Other function codes correspond to internal symbiont mechanisms that are not part of the public interface to the print symbiont. Your output routine should return the status PSM$_FUNNOTSUP or SS$_NORMAL when it is called with a message function code or with a private function code. funcdesc OpenVMS usage:char_string type: character string access: read only mechanism: by descriptor Function descriptor supplying information related to the function specified by the func argument. The funcdesc argument is the address of this descriptor. The contents of the function descriptor can vary for each function. Refer to the description of each function code to determine the contents of the function descriptor. In some cases, the function descriptor is not used at all. funcarg OpenVMS usage:user_arg type: longword (unsigned) access: read only mechanism: by reference Function argument supplying information related to the function specified by the func argument. The funcarg argument is the address of a longword containing this function argument. The contents of the function argument can vary for each function. Refer to the description of each function code to determine the contents of the function argument. In some cases, the function argument is not used. 3 Condition_Values_Returned SS$_NORMAL Normal successful completion. The user output routine has completed the function that the symbiont requested. PSM$_FUNNOTSUP Function not supported. The user output routine does not support or does not recognize the function code supplied by the symbiont. To ensure future compatibility, your output routine should return this status for any unrecognized status codes. PSM$_PENDING Requested function accepted but not completed. Your output routine can return this status only with PSM$K_WRITE and PSM$K_WRITE_NOFORMAT function calls. Further, if your routine returns PSM$_PENDING, your routine must eventually signal completion by way of the PSM$REPORT routine. Refer to the description of the PSM$REPORT routine for more information about asynchronous write operations and the PSM$_PENDING condition value. This routine also returns any error condition values that you have coded your output routine to return.