.fo off

/*********************************************************************/
/*  SUBROUTINE NAME: MAIN                                            */
/*                                                                   */
/*  DESCRIPTION NAME: Bind Messages to application program.          */
/*                                                                   */
/*  FUNCTION: Bind root and sub message files to the end of the      */
/*            user EXE file.                                         */
/*                                                                   */
/*  NOTE: None.                                                      */
/*                                                                   */
/*  ENTRY POINT: main()                                              */
/*                                                                   */
/*  INPUT: argc : number of commad line arguments                    */
/*         argv : character pointer to the arguments                 */
/*                                                                   */
/*  EXIT-NORMAL: Root and sub messages appended to end of EXE file   */
/*                                                                   */
/*  EXIT-ERROR: Unable to open pro file                              */
/*                                                                   */
/*  SIDE EFFECTS: None.                                              */
/*                                                                   */
/*  INTERNAL REFERENCES: OpenExeFile, OpenMsgFile, ReadCPData,       */
/*                       ReadFileDef, AddAll, AddMessage,            */
/*                       CloseMsgFile, CloseExeFile.                 */
/*                                                                   */
/*  EXTERNAL REFERENCES: InitInputFile, InputLine                    */
/*                                                                   */
/*********************************************************************/
/* Pseudo-Code Begin */
        If only one argument
           Then stop execution
*DCR361* Initialize work message files table
        Initialize input file
        If input file handle does not exists
           Then stop execution
        While input lines available from input file
           If executable filename prompt exists '>'
              Then open exucutable file
           Else If comment line prompt exists ';'
              Then Skip comment line
           Else If executable file handle exists
              Then If message filename prompt exists '<'
                 Open message file
*DCR361*         If current table exists and version > 1
*DCR361*            If number message files > 1
*DCR361*               Allocate new message file entry for the table
*DCR361*            EndIf
*DCR361*            Read Code Page Data
*DCR361*            Read Subfile Definitions
*DCR361*         EndIf
              Else If message number prompt exists '*' and
              message file handle exists
                 Then If all files processed
                    Then add all messages to the executable file
                    and break out of while loop
                 Else display error message
              Else If message file handle exists
                 Then add messages to the executable file
                 and break out of while loop
              Else If not file processing error
                 Then display error message
           While end
           Close executable file
           Return Success
/* Pseudo-Code End */
.fo on
.pa
:h4.Multi-CodePage Message Intra-Component Interfaces
:h4.***** MSGBIND *****
.fo off

/*********************************************************************/
/*  SUBROUTINE NAME: InitInputFile                                   */
/*                                                                   */
/*  DESCRIPTION NAME: Initialize Input File                          */
/*                                                                   */
/*  FUNCTION: Initialize data structure and enviroment for the pro   */
/*            file use by msgbind. Allocates memory, opens file,     */
/*            and assign a pointer to the buffer area.               */
/*                                                                   */
/*  NOTE: None.                                                      */
/*                                                                   */
/*  ENTRY POINT: InitInputFile                                       */
/*                                                                   */
/*  INPUT: s: character string pointer to name of pro file           */
/*         n: length of buffer to be allocated                       */
/*                                                                   */
/*  EXIT-NORMAL: Return p data structure with buffer and file handle */
/*                                                                   */
/*  EXIT-ERROR: None.                                                */
/*                                                                   */
/*  SIDE EFFECTS: None.                                              */
/*                                                                   */
/*  INTERNAL REFERENCES: None.                                       */
/*                                                                   */
/*  EXTERNAL REFERENCES: MyAlloc                                     */
/*                                                                   */
/*********************************************************************/
/* Pseudo-Code Begin*/
   If buffer length zero
      Then set it to MAXPATHLEN or 512, whichever is largest
   Allocate memory space for buffer
   Open input file and assign file handle
   Assign input file buffer pointer to allocated buffer
   Assign input file buffer size to buffer length
   Assign input file buffer length to zero
   Assign input file current buffer pointer to null
   Return input file pointer
/* Pseudo-Code End*/

.fo on
.pa
:h4.Multi-CodePage Message Intra-Component Interfaces
:h4.***** MSGBIND *****
.fo off

/*********************************************************************/
/*  SUBROUTINE NAME: InputLine                                       */
/*                                                                   */
/*  DESCRIPTION NAME: Read Input Line                                */
/*                                                                   */
/*  FUNCTION: Read in line from opened pro file and placing contents */
/*            into the allocated buffer area. While reading, all     */
/*            '\n' are replaced with a NULL.                         */
/*                                                                   */
/*  NOTE: None.                                                      */
/*                                                                   */
/*  ENTRY POINT: InputLine                                           */
/*                                                                   */
/*  INPUT: p: INPUTFILE data structure which defines pro file        */
/*                                                                   */
/*  EXIT-NORMAL: Return number of characters read in.                */
/*                                                                   */
/*  EXIT-ERROR: Return -1 if no characters were read in              */
/*                                                                   */
/*  SIDE EFFECTS: None.                                              */
/*                                                                   */
/*  INTERNAL REFERENCES: None.                                       */
/*                                                                   */
/*  EXTERNAL REFERENCES: None.                                       */
/*                                                                   */
/*********************************************************************/
/* Pseudo-Code Begin*/
   Assign input file buffer pointer to string pointer
   While forever
      if input file  current buffer pointer empty
         Then read input line
         and assign input file  current buffer pointer to it
         If input file buffer length is less than zero
            Then break of while loop
         While input file buffer length greater than zero
            Assign input file current buffer's character to c
            If character c is a return character
               Then replace input file buffer character with a null (NULLC)
               return character count
            Else
               Replace input file buffer character with c character
               Increment character count
            End If
            Decrement 1 from input file buffer length
         While End
      Truncating input file current buffer to length zero
   While End
   Return character count or failure if less than or equal to zero
/* Pseudo-Code End*/
.fo on
.pa
:h4.Multi-CodePage Message Intra-Component Interfaces
:h4.***** MSGBIND *****
.fo off

/*********************************************************************/
/*  SUBROUTINE NAME: OpenExeFile                                     */
/*                                                                   */
/*  DESCRIPTION NAME: Open Executable File                           */
/*                                                                   */
/*  FUNCTION: Open the executable file for which the messages        */
/*            will be appended to.                                   */
/*                                                                   */
/*  NOTE: None.                                                      */
/*                                                                   */
/*  ENTRY POINT: OpenExeFile                                         */
/*                                                                   */
/*  INPUT: s: string pointer to name of executable file              */
/*                                                                   */
/*  EXIT-NORMAL: Provide file handle for the executable file, exefh, */
/*               after successfully opening it, and capitalize       */
/*               executable's filename.                              */
/*                                                                   */
/*  EXIT-ERROR: Error trapped and returns                            */
/*              . File not found                                     */
/*              . File not linked with MSGSEG.OBJ                    */
/*                                                                   */
/*  SIDE EFFECTS: None.                                              */
/*                                                                   */
/*  INTERNAL REFERENCES: CloseExeFile,                               */
/*                                                                   */
/*                                                                   */
/*  EXTERNAL REFERENCES: ReadExeFile, MyStrupr                       */
/*                                                                   */
/*********************************************************************/
/* Pseudo-Code Begin*/
   Close executable file
   Flush stdout
   If failure to open executable
      Create error message
   Else if failure to determine bound message segment
      Create error message
   Endif
   If error message
      Print warning
      Close executable file
   Else
      Capitalize executable filename
   Endif
/* Pseudo-Code End*/

.fo on
.pa
:h4.Multi-CodePage Message Intra-Component Interfaces
:h4.***** MSGBIND *****
.fo off

/*********************************************************************/
/*  SUBROUTINE NAME: OpenMsgFile                                     */
/*                                                                   */
/*  DESCRIPTION NAME: Open Message File                              */
/*                                                                   */
/*  FUNCTION: Opens message file and places contents into allocated  */
/*            memory buffer and sets up values to the current table  */
/*                                                                   */
/*  NOTE: None.                                                      */
/*                                                                   */
/*  ENTRY POINT: OpenMsgFile                                         */
/*                                                                   */
/*  INPUT: s: character string pointer to name of message file       */
/*                                                                   */
/*  EXIT-NORMAL: Fill in data structures for pMsgFile, pMsgTable,    */
/*               pCurTable, and increment nMsgFiles                  */
/*                                                                   */
/*  EXIT-ERROR: Error trapped and returns                            */
/*              . File not found                                     */
/*              . File not created with MKMSGF utility               */
/*              . Not enough memory for pCurTable                    */
/*                                                                   */
/*  SIDE EFFECTS: None.                                              */
/*                                                                   */
/*  INTERNAL REFERENCES: CloseMsgFile                                */
/*                                                                   */
/*  EXTERNAL REFERENCES: MyRead, MyAlloc, MyStrupr, MySeek           */
/*                                                                   */
/*********************************************************************/
/* Pseudo-Code Begin*/
*DCR361*   if number of message files > MAXMSGFILES
*DCR361*      generate error
*DCR361*   Endif
   Close message file
   Flush stdout
   If failure open message file
      Create error message
   Else
      Read message format header
      If message format signature is not "MKMSGF"
         Create error message
      Else If cannot allocate message table
         Create error message
      Endif
   Endif
   If error message exists
      Print warning
      Close message file
   Else
      Assign capitalized message filename to message file table
      Assign pointer current message table to message table
      copy old message format header to new messge format header
      Assign number messages plus base message number minus 1
         to current message table maximum message number
      Assign message format base message number
         to current message table base message number
      Assign message format 16bit offset
         to current message table 16bit offset
*DCR361*      If version > 1
*DCR361*         Assign Code Page offset
*DCR361*         Assign Extended Header offset
*DCR361*      EndIf
      Increment message file count
   Endif
/* Pseudo-Code End*/

.fo on
.pa
:h4.Multi-CodePage Message Intra-Component Interfaces
:h4.***** MSGBIND *****
.fo off

/*********************************************************************/
/*  SUBROUTINE NAME: ReadCPData                                      */
/*                                                                   */
/*  DESCRIPTION NAME: Read Code Page Data                            */
/*                                                                   */
/*  FUNCTION: Seeks and retrieves from the message file the Language */
/*            Code Page and Filename information for the root and its*/
/*            subfiles. It is then store in memory in a linked list  */
/*            of subfiles.                                           */
/*                                                                   */
/*  NOTE: None.                                                      */
/*                                                                   */
/*  ENTRY POINT: ReadCPData                                          */
/*                                                                   */
/*  INPUT: wRootFile: Pointer to the root of the code page linked    */
/*         list.                                                     */
/*                                                                   */
/*  EXIT-NORMAL: Fill in the structures for MsgFileType which        */
/*               includes Language, Code Page, and Filename          */
/*               structures                                          */
/*                                                                   */
/*  EXIT-ERROR: None                                                 */
/*                                                                   */
/*  SIDE EFFECTS: None.                                              */
/*                                                                   */
/*  INTERNAL REFERENCES: MySeek                                      */
/*                                                                   */
/*  EXTERNAL REFERENCES:                                             */
/*                                                                   */
/*********************************************************************/
/* Pseudo-Code Begin*/
   Determine pointer to the last entry in the linked list
   Seek in message file to the location of the Code Page Data
   Read in Language, Code Page, and Filename data
/* Pseudo-Code End*/

.fo on
.pa
:h4.Multi-CodePage Message Intra-Component Interfaces
:h4.***** MSGBIND *****
.fo off

/*********************************************************************/
/*  SUBROUTINE NAME: ReadFileDef                                     */
/*                                                                   */
/*  DESCRIPTION NAME: Read SubFile Definitions                       */
/*                                                                   */
/*  FUNCTION: Seeks and retrieves from the message file the Language */
/*            Code Page and Filename information for the message     */
/*            subfile definitions. It is then stored in memory in a  */
/*            linked list subfile definitions.                       */
/*                                                                   */
/*  NOTE: None.                                                      */
/*                                                                   */
/*  ENTRY POINT: ReadFileDef                                         */
/*                                                                   */
/*  INPUT: wRootFile: Pointer to the root of the subfile definition  */
/*         list.                                                     */
/*                                                                   */
/*  EXIT-NORMAL: Fill in the structures for MsgFileType which        */
/*               includes Language, Code Page, and Filename          */
/*               structures                                          */
/*                                                                   */
/*  EXIT-ERROR: None                                                 */
/*                                                                   */
/*  SIDE EFFECTS: None.                                              */
/*                                                                   */
/*  INTERNAL REFERENCES: MySeek                                      */
/*                                                                   */
/*  EXTERNAL REFERENCES: MyRead, MyAlloc, MyStrupr, MySeek           */
/*                                                                   */
/*********************************************************************/
/* Pseudo-Code Begin*/
   if extended header exists
      Determine pointer to the last entry in the linked list of code pages
      Seek in message file to the location of the Code Page Data for subfile
      definitions
      Read in Length of subfile definitions
      Add to the length size of the variable for the length.
      Read in number of files in the extended file header
      For 0 to number of files
         Determine pointer to the last entry in the linked list of subfile definitions
         Read in Language, Code Page, and Filename data
         Link in new entry to list
      EndFor
   EndIf
/* Pseudo-Code End*/

.fo on
.pa
:h4.Multi-CodePage Message Intra-Component Interfaces
:h4.***** MSGBIND *****
.fo off

/*********************************************************************/
/*  SUBROUTINE NAME: AddAll                                          */
/*                                                                   */
/*  DESCRIPTION NAME: Read in all messages from message file         */
/*                                                                   */
/*  FUNCTION: Read all messages from a message file and set up the   */
/*            necessary data structures.                             */
/*                                                                   */
/*  NOTE: None.                                                      */
/*                                                                   */
/*  ENTRY POINT: Addall                                              */
/*                                                                   */
/*  INPUT: None.                                                     */
/*                                                                   */
/*  EXIT-NORMAL: Return SUCCESS                                      */
/*                                                                   */
/*  EXIT-ERROR:  None                                                */
/*                                                                   */
/*                                                                   */
/*  SIDE EFFECTS: None.                                              */
/*                                                                   */
/*  INTERNAL REFERENCES:                                             */
/*                                                                   */
/*  EXTERNAL REFERENCES: MySeek, MyRead, MyAlloc                     */
/*                                                                   */
/*********************************************************************/
/* Pseudo-Code Begin*/
   If current table 16bit offset true
      Set byte count to 2
   Else
      Set byte count to 4
   End If
   Assign current table base message number to message number
   For loop
      Start: Set message number to current table base message number
      Test : message less than equal to current table maximum message number
      End  : Increment message number
      Flush stdout

      Move to corresponding entry in message offset table
         Set message index to diffence between message number
             and current table base message number
         Set message offset to message index
         Multiply message offset by byte count
         Shift message offset by size of MKMSGF structure
         Seek in message file to message offset

      Retrieve message offset for this entry
         Reset message offset to zero
         Read message offset

      Skip to end of message linked list
         Set pointer to current table
         While pointer is not null
            Set pointer to next message

      While End
      Increment message count
      Allocate space for new message
      End linked list
      Set message number
      Set message offset
      Set message length
         If maximum number messages
         Then set message length to message file size less message offset
         Else
            Read message length
            Set pointer message length to message length less pointer
             message offset
         End If
      Add to message segment size the byte size of pointer message number,
         size of pointer message length, and pointer message length
      If message segment size is greater then maximum offset then
         Remove node from list
            Subtract one from Current table number messages
            Free node
            Set pointer of next message to null
         Return Failure
      End if
   End loop
   Return Success
/* Pseudo-Code End*/

.fo on
.pa
:h4.Multi-CodePage Message Intra-Component Interfaces
:h4.***** MSGBIND *****
.fo off

/*********************************************************************/
/*  SUBROUTINE NAME: AddMessage                                      */
/*                                                                   */
/*  DESCRIPTION NAME: Add specified message to the messages list     */
/*                                                                   */
/*  FUNCTION: Add specified message to the messages list which will  */
/*            be bounded to the executable file.                     */
/*                                                                   */
/*  NOTE: None.                                                      */
/*                                                                   */
/*  ENTRY POINT: AddMessage                                          */
/*                                                                   */
/*  INPUT: string pointer to message which will be added to list     */
/*                                                                   */
/*  EXIT-NORMAL: Return SUCCESS if message is inserted into list     */
/*               or warning if invalid message number                */
/*                                                                   */
/*  EXIT-ERROR:  None                                                */
/*                                                                   */
/*  SIDE EFFECTS: None.                                              */
/*                                                                   */
/*  INTERNAL REFERENCES:                                             */
/*                                                                   */
/*  EXTERNAL REFERENCES: MySeek, MyRead, MyAlloc                     */
/*                                                                   */
/*********************************************************************/
/* Pseudo-Code Begin*/
   If string length is 7
      Skip first three characters (signature)
      Set message number to zero
      Test string for message number
         While current character not null
            if character not within range '0'..'9'
               skip message
            Else
               convert character to integer
         While End
      If message number less than current table base message number or
         message number greater than current table maximum message number
         Skip message
      End If
      Flush stdout
      Set message index to message number less current table base message number
      Set message offset to message index
      If current table 16bit offset true
         Set byte count to 2
      Else
         Set byte count to 4
      End If
      Move to corresponding entry in message offset table
         Set message index to diffence between message number
             and current table base message number
         Set message offset to message index
         Multiply message offset by byte count
         Shift message offset by size of MKMSGF structure
         Seek in message file to message offset

      Retrieve message offset for this entry
         Reset message offset to zero
         Read message offset

      Skip to end of message linked list
         Set pointer to current table
         While pointer is not null
            Set pointer to next message

      While End
      Increment message count
      Allocate space for new message
      End linked list
      Set message number
      Set message offset
      Set message length
         If maximum number messages
         Then set message length to message file size less message offset
         Else
            Read message length
            Set pointer message length to message length less pointer
             message offset
         End If
      Add to message segment size the byte size of pointer message number,
         size of pointer message length, and pointer message length
      If message segment size is greater then maximum offset then
         Remove node from list
            Subtract one from Current table number messages
            Free node
            Set pointer of next message to null
         Return Failure
      End if
   End If
   Return Success
/* Pseudo-Code End*/

.fo on
.pa
:h4.Multi-CodePage Message Intra-Component Interfaces
:h4.***** MSGBIND *****
.fo off

/*********************************************************************/
/*  SUBROUTINE NAME: CloseMsgFile                                    */
/*                                                                   */
/*  DESCRIPTION NAME: Closes Message File                            */
/*                                                                   */
/*  FUNCTION: Close the message file pointed to by the global msgfh  */
/*                                                                   */
/*  NOTE: None.                                                      */
/*                                                                   */
/*  ENTRY POINT: CloseMsgFile                                        */
/*                                                                   */
/*  INPUT: None.                                                     */
/*                                                                   */
/*  EXIT-NORMAL: Sets message file handle to failure, msgfh = -1     */
/*                                                                   */
/*  EXIT-ERROR: None.                                                */
/*                                                                   */
/*  SIDE EFFECTS: None.                                              */
/*                                                                   */
/*  INTERNAL REFERENCES: None.                                       */
/*                                                                   */
/*  EXTERNAL REFERENCES:                                             */
/*                                                                   */
/*********************************************************************/
/* Pseudo-Code Begin*/
   If message file handle available
      close message file
      Invalidate message file handle
   End If
/* Pseudo-Code End*/

.fo on
.pa
:h4.Multi-CodePage Message Intra-Component Interfaces
:h4.***** MSGBIND *****
.fo off

/*********************************************************************/
/*  SUBROUTINE NAME: CloseExeFile                                    */
/*                                                                   */
/*  DESCRIPTION NAME: Close Executable File                          */
/*                                                                   */
/*  FUNCTION: Writes new executable file with its new message        */
/*            segment into a temp file and then overwrites the       */
/*            original executable file.                              */
/*                                                                   */
/*  NOTE: None.                                                      */
/*                                                                   */
/*  ENTRY POINT: CloseExeFile                                        */
/*                                                                   */
/*  INPUT: None.                                                     */
/*                                                                   */
/*  EXIT-NORMAL: None.                                               */
/*                                                                   */
/*  EXIT-ERROR: None.                                                */
/*                                                                   */
/*  SIDE EFFECTS: None.                                              */
/*                                                                   */
/*  INTERNAL REFERENCES: CloseMsgFile                                */
/*                                                                   */
/*  EXTERNAL REFERENCES: Write32ExeFile, WriteExeFile                */
/*                                                                   */
/*********************************************************************/
/* Pseudo-Code Begin*/
   Close message file
   If executable file handle exists
      Open temporary output file
      If succesful
         If 32 bit object table created
            Write 32 bit executable file
         Else
            Write 16 bit executable file
         End If
         Close temporary output file
         Close executable file
         Copy over old executable with new one from temporary output file
      End If
*DCR361*      Determine Real or Protect mode of machine
*DCR361*      If mode Real
*DCR361*         create command line buffer using long filenames
*DCR361*      Else
*DCR361*         create command line buffer without long filenames
*DCR361*      EndIf
      call system with command line
      free temporary filename file
      Free dynamic message table entries
      Free dynamic message file entries
      Free dynamic segment table
      Free dynamic resource table
   End If
/* Pseudo-Code End*/

.fo on
