/**
 * Bin2Rexx: "DosOpen() / DosRead() / DosWrite() / DosClose()" example.
 */

#include <OS2.h>
#include <CType.h>
#include <StdLib.h>
#include <String.h>

#define Main main

#ifndef STDIN
#define STDIN  0
#define STDOUT 1
#define STDERR 2
#endif

Say (PBYTE String) { ULONG Written = 0; DosWrite (STDOUT, String, strlen (String), &Written); return 0; }
Err (PBYTE String) { ULONG Written = 0; DosWrite (STDERR, String, strlen (String), &Written); return 0; }

Say (PBYTE A, PBYTE B) { Say (A); Say (B); return 0; }
Err (PBYTE A, PBYTE B) { Err (A); Err (B); return 0; }

Say (PBYTE A, PBYTE B, PBYTE C) { Say (A); Say (B); Say (C); return 0; }
Err (PBYTE A, PBYTE B, PBYTE C) { Err (A); Err (B); Err (C); return 0; }

Say (PBYTE A, PBYTE B, PBYTE C, PBYTE D) { Say (A); Say (B); Say (C); Say (D); return 0; }
Err (PBYTE A, PBYTE B, PBYTE C, PBYTE D) { Err (A); Err (B); Err (C); Say (D); return 0; }

Say (PBYTE A, PBYTE B, PBYTE C, PBYTE D, PBYTE E) { Say (A); Say (B); Say (C); Say (D); Say (E); return 0; }
Err (PBYTE A, PBYTE B, PBYTE C, PBYTE D, PBYTE E) { Err (A); Err (B); Err (C); Say (D); Say (E); return 0; }

/* * */

#define STR_REXX_LINE_LENGTH 256

PrintRexxScript (PBYTE, ULONG, PCHAR);

/* * */

Main (INT Arg_c, PCHAR Arg_v[])  
{
  if (Arg_c != 2 || !strstr (Arg_v[1], ".")) 
  {
    Say ("Usage: Bin2Rexx Binary-file.ext > Rexx-script.cmd");
  }
  else
  {
    PBYTE Memory = NULL; ULONG Length = 0;

    HFILE File   = NULLHANDLE; ULONG Report = 0;
    ULONG Action = OPEN_ACTION_OPEN_IF_EXISTS;
    ULONG Mode   = OPEN_SHARE_DENYWRITE |
                   OPEN_ACCESS_READONLY;

    DosOpen (Arg_v[1], &File, &Report, 0, 0, Action, Mode, NULL);

    if (File) 
    {
      DosSetFilePtr (File, 0, FILE_END, &Length);
      DosSetFilePtr (File, 0, FILE_BEGIN, &Report);
      DosAllocMem ((PPVOID) &Memory, Length, PAG_READ | PAG_WRITE | PAG_COMMIT);

      DosRead (File, Memory, Length, &Report);
      DosClose (File), File = NULLHANDLE;

      PrintRexxScript (Memory, Length, Arg_v[1]);
      DosFreeMem (Memory), Memory = NULL, Length = 0;
    }
    else
    {
      DosExit (EXIT_PROCESS, -1);
    }
  }

  return 0;
}

/* * */

PrintRexxScript (PBYTE Memory, ULONG Length, PCHAR File_name)
{
  Say ("/* * */", "\r\n");
  Say ("\r\n");
  Say ("V = ''", "\r\n");

  for (INT Cntr = 0; Cntr < Length; Cntr ++) 
  {
    CHAR Script[STR_REXX_LINE_LENGTH] = ""; strcpy (Script, "V = V || ");

    for (INT Offset = 0; Offset < 16; Offset ++) 
    {
      INT Position = Cntr + Offset;

      if (Position < Length) 
      {
        BYTE Bin_value = 0; CHAR Hex_value[4] = {0};

        Bin_value = (BYTE) Memory[Position];
        ultoa (Bin_value, Hex_value, 16);

        if (strlen (Hex_value) == 1) 
        {
          Hex_value[2] = 0; Hex_value[1] = Hex_value[0]; Hex_value[0] = '0';
        }

        if (islower (Hex_value[0])) Hex_value[0] = toupper (Hex_value[0]);
        if (islower (Hex_value[1])) Hex_value[1] = toupper (Hex_value[1]);

        strcat (Script, "'");
        strcat (Script, Hex_value);
        strcat (Script, "'x");
      }
    }

    Say (Script, "\r\n");

    Cntr += Offset;
    Cntr --;
  }

  Say ("\r\n");
  Say ("File = '", File_name, "'", "\r\n");
  Say ("Call SysFileDelete File", "\r\n");
  Say ("Call CharOut File, V", "\r\n");
  Say ("\r\n");
  Say ("Exit");

  return 0;
}