/*
 *
 *  WinRes - OS/2 to Windows resource conversion utility
 *
 *  RESCONV is a utility program used to convert OS/2 resources to
 *  Windows resources.
 *
 */

#include "resconv.h"
#include "extdef.h"

int is_debug_on = FALSE; // JMH

/*
 *  The following string is printed when the user fails to supply
 *  sufficient information when running the program.
 */

static char usage_msg [] = "\
\n\
RESCONV - Resource Conversion Utility program\n\
\n\
Usage:\n\
  RESCONV <OS/2 src_file> <Windows dst_file>\n\
";


static uchar search  [] = {'~', 0};
static uchar replace [] = {'&', 0};

ushort cLineCurrent = 1;  /* the current line number */


/*******************************************************************
 *                                                                 *
 *  LOWER_CASE_CHAR                                                *
 *                                                                 *
 *  This procedure is called to convert a character from upper to  *
 *  lower case.                                                    *
 *                                                                 *
 *******************************************************************/

uchar lower_case_char (uchar ch)
{

/*  Is it an upper case ASCII character? */

if (ch >= 'A' && ch <= 'Z')
    return ch ^ (uchar) ' ';

/*  It doesn't have a case. */

return ch;
}


/*******************************************************************
 *                                                                 *
 *  UPPER_CASE_CHAR                                                *
 *                                                                 *
 *  This procedure is called to convert a character from lower to  *
 *  upper case.                                                    *
 *                                                                 *
 *******************************************************************/

uchar upper_case_char (uchar ch)
{

/*  Is it a lower case ASCII character? */

if (ch >= 'a' && ch <= 'z')
    return ch ^ (uchar) ' ';

/*  It doesn't have a case. */

return ch;
}



/*******************************************************************
 *                                                                 *
 *  GET_CHAR_CASE                                                  *
 *                                                                 *
 *  This procedure is called to get the case of the character.     *
 *  The procedure returns 0 if the character has no case, 1 if     *
 *  the character is lower case, and 2 if the character is upper   *
 *  case.                                                          *
 *                                                                 *
 *******************************************************************/

ushort get_char_case (uchar ch)
{

/*  Is it a lower case ASCII character? */

if (ch >= 'a' && ch <= 'z')
    return char_case_lower;

/*  Is it an upper case ASCII character? */

if (ch >= 'A' && ch <= 'Z')
    return char_case_upper;

/*  It doesn't have a case. */

return char_case_none;
}


/*******************************************************************
 *                                                                 *
 *  EQUAL_IGNORING_CASE                                            *
 *                                                                 *
 *  Determines whether two strings of characters are identical,    *
 *  ignoring the case of the characters.                           *
 *                                                                 *
 *******************************************************************/

flag equal_ignoring_case (uchar ptr string1, uchar ptr string2)
{
register uchar a;
register uchar b;

if (string1 == NULL || string2 == NULL)
    return FALSE;

/*
 *  Loop as long as both strings have some data. We quit if we find
 *  a mismatch in the strings.
 */

forever {
    if ((a = *string1++) != (b = *string2++)) {
        if (get_char_case (a) == char_case_lower)
            a = upper_case_char (a);
        if (get_char_case (b) == char_case_lower)
            b = upper_case_char (b);
        }
    if (a != b)
        return (FALSE);
    if (a == 0)
        return (TRUE);
    }
}


/*******************************************************************
 *                                                                 *
 *  STRING_LENGTH                                                  *
 *                                                                 *
 *  Determines the length of a string of characters, not including *
 *  the final null.						   *
 *                                                                 *
 *******************************************************************/

ushort string_length (uchar ptr string)
{
return (_fstrlen (string));
}


/*******************************************************************
 *                                                                 *
 *  STRING_COPY 						   *
 *                                                                 *
 *  Copies the contents of one string of characters into another,  *
 *  returning a pointer to the null terminator of the destination. *
 *                                                                 *
 *******************************************************************/

void ptr string_copy (uchar ptr dest, uchar ptr source)
{

while (*source)
    *dest++ = *source++;

*dest = 0;
return (dest);
}

/*******************************************************************
 *                                                                 *
 *  STRING_APPEND						   *
 *                                                                 *
 *  Copies the contents of one string of characters into another,  *
 *  returning a pointer to the null terminator of the destination. *
 *                                                                 *
 *******************************************************************/

void ptr string_append (uchar ptr dest, uchar ptr source)
{

while (*dest)
    dest++;

while (*source)
    *dest++ = *source++;

*dest = 0;
return (dest);
}



/*******************************************************************
 *                                                                 *
 *  STRING_REPLACE                                                 *
 *                                                                 *
 *  Searches the given string for characters in the search string. *
 *  Any characters found are replaced with the corresponding	   *
 *  character in the replace string.				   *
 *                                                                 *
 *******************************************************************/

void string_replace (uchar ptr string, uchar ptr search, uchar ptr replace)
{
ushort len;
ushort length;
uchar ptr sp;
uchar ptr ep;

length = string_length (string);
while (*search) {
    len = length;
    sp  = string;
    while (ep = _fstrchr (sp, *search)) {
        *ep = *replace;
        len -= ep - sp + 1;
        sp = &ep [1];
        }
    search++;
    replace++;
    }
}

/*******************************************************************
 *                                                                 *
 *  DOUBLE_AMPERSANDS						   *
 *                                                                 *
 *  Searches the given string for ampersands and doubles them,	   *
 *  so they will not be interpreted incorrectly as mnemonics	   *
 *                                                                 *
 *******************************************************************/

void double_ampersands (uchar ptr string)
{
ushort length;
uchar ptr sp;
uchar ptr ep;
uchar ptr dp;

length = string_length (string);
ep = string;
for (ep = string; *ep; ep++) {
    if (*ep == '&')
	if (length+1 >= max_string_size)
	    report_error (err_string_too_long, 0, "doubling ampersands");
	else {
	    dp = string+length+1;
	    sp = string+length;
	    while (sp >= ep)
		*dp-- = *sp--;
	    *ep = '&';
	    length++;
	    ep++;
	    }
    }
}



/**************************************************************************
 *                                                                        *
 *  REPORT_ERROR                                                          *
 *                                                                        *
 *  This procedure reports the indicated error and exits the program.     *
 *                                                                        *
 **************************************************************************/

void report_error (ushort error, ushort token, uchar ptr string)
{
uchar   ptr msg;

/*  Case on the error and print the message. */

switch (error) {
    case err_full_put_char_buffer:
        msg = "The put_char buffer is full.";
        break;
    case err_full_put_token_buffer:
        msg = "The put_token buffer is full.";
        break;
    case err_no_source_file:
        msg = "No source file is open.";
        break;
    case err_unexpected_comment_char:
        msg = "Unexpected comment character.";
        break;
    case err_unexpected_eof:
        msg = "Unexpected EOF.";
        break;
    case err_string_too_long:
        msg = "The string is too long.";
        break;
    case err_identifier_too_long:
        msg = "The identifier is too long.";
        break;
    case err_value_too_big:
        msg = "The value is too large.";
        break;
    case err_invalid_syntax:
        msg = "Invalid syntax.";
        break;
    case err_invalid_character:
        msg = "Invalid character.";
        break;
    case err_bad_menu_option:
        msg = "Invalid menu option. Line Omitted";
        break;
    case err_bad_load_option:
        msg = "Invalid load option.";
        break;
    case err_bad_dialog_option:
        msg = "Invalid dialog option.";
        break;
    case err_bad_control_class:
        msg = "Invalid dialog control class.";
        break;
    case err_bad_accel_option:
        msg = "Invalid accelerator table option.";
        break;
    case err_convert_resources:
        msg = "Bad token found in convert_resources.";
        break;
    default:
        msg = "Unknown error occurred.";
        break;
    }

if (string)

    printf ("%s Token = %d Keyword = %s Line = %d \n",
	    msg, token, string, cLineCurrent);
else
    printf ("%s Token = %d Line = %d\n", msg, token, cLineCurrent);

close_destination_file ();
terminate_input ();
exit(1);
}


/**************************************************************************
 *                                                                        *
 *  REPORT_WARNING							  *
 *                                                                        *
 *  This procedure reports the indicated warning.			  *
 *                                                                        *
 **************************************************************************/

void report_warning (uchar ptr szerror, ushort token, uchar ptr string, long value)
{

/*  Case on the error and print the message. */

if (string)
    printf ("%s Token = %d Keyword = %s Line = %d \n",
	    szerror, token, string, cLineCurrent);

else if (value)
    printf ("%s Token = %d Keyword = %d Line = %d \n",
	    szerror, token, value, cLineCurrent);

else
    printf ("%s Token = %d Line = %d\n", szerror, token, cLineCurrent);

}


/***********************************************************************
 *                                                                     *
 *  CONVERT_TO_UPPER                                                   *
 *                                                                     *
 *  This procedure converts the character string to upper case.        *
 *                                                                     *
 ***********************************************************************/

void ptr convert_to_upper (uchar ptr string)
{
uchar   ptr sp;                             /* string pointer */

sp = string;
while (*sp) {
    *sp = upper_case_char (*sp);
    sp++;
    }

return sp;
}


/**************************************************************************
 *                                                                        *
 *  CONVERT_RESOURCE                                                      *
 *                                                                        *
 *  This procedure is called to convert a resource statement.             *
 *                                                                        *
 **************************************************************************/

void convert_resource (void)
{
ushort      token;
uchar   ptr string;
long        value;

/*  Get the resource type identifier. */

if ((token = get_token ()) == tok_numeric)
    value = current_token_value ();
else {
    string = _fmalloc (string_length (current_token_string ()) + 1);
    string_copy (string, current_token_string ());
    }

/*  Output the resource name identifier. */

if (get_token () == tok_numeric)
    output_value (current_token_value ());
else
    output_token (current_token_string ());

/*  Output the resource type identifier. */

if (token == tok_numeric)
    output_value (value);
else {
    output_token (string);
    _ffree (string);
    }

/*  Output the file name. */

if ((token = get_token ()) == tok_string)
    output_string (current_token_string ());
else
    output_token (current_token_string ());
}


/**************************************************************************
 *                                                                        *
 *  PROCESS_RCINCLUDE                                                     *
 *                                                                        *
 *  This procedure is called to process an rcinclude statement.           *
 *                                                                        *
 **************************************************************************/

void process_rcinclude (void)
{
ushort  token;

/*  Get the filename token and open the source file. */

token = get_token ();
open_source_file (current_token_string ());
}


/**************************************************************************
 *                                                                        *
 *  PROCESS_DLGINCLUDE							  *
 *                                                                        *
 *  This procedure is called to process an dlginclude statement.	  *
 *                                                                        *
 **************************************************************************/

void process_dlginclude (void)
{
ushort  token;

/*  Get the id token */
token = get_token ();

token = get_token ();

/* someday should add byron's new support */
}


/**************************************************************************
 *                                                                        *
 *  CONVERT_STRINGTABLE                                                   *
 *                                                                        *
 *  This procedure is called to convert a stringtable statement.          *
 *                                                                        *
 *  Syntax:                                                               *
 *      STRINGTABLE                                                       *
 *      BEGIN                                                             *
 *          stringid, string                                              *
 *      END                                                               *
 *                                                                        *
 **************************************************************************/

void convert_stringtable (void)
{
ushort      token;
uchar   ptr string;

/*  Output the STRINGTABLE keyword. */

output_token ("STRINGTABLE");

/*  Output the BEGIN keyword. */

output_newline ();
token = get_token ();
output_token ("BEGIN");

/*
 *  Until we've seen the END keyword or the EOF, output the information
 *  for each of the strings.
 */

while ((token = get_token ()) != tok_end && token != tok_eof) {
    /*
     *  Output the string identifier.
     */
    output_newline ();
    output_tab (1);
    if (token == tok_numeric)
        output_value (current_token_value ());
    else
        output_token (current_token_string ());
    /*
     *  Output the comma.
     */
    output_token (",");
    /*
     *  Output the string.
     */
    token = get_token ();
    if (token == tok_comma)
	token = get_token();
    string = current_token_string ();
    double_ampersands(string);
    string_replace (string, search, replace);
    output_string (string);
    }

/*  Output the END keyword. */

output_newline ();
output_token ("END");
}


/**************************************************************************
 *                                                                        *
 *  CONVERT_POINTER                                                       *
 *                                                                        *
 *  This procedure is called to convert a pointer statement.              *
 *                                                                        *
 *  Syntax:                                                               *
 *      idvalue CURSOR filename                                           *
 *                                                                        *
 **************************************************************************/

void convert_pointer (void)
{
    ushort      token;
    ushort      done;

/*  Output the CURSOR keyword.
    ==========================  */

    output_token ("CURSOR");

/*  Output the identifier value.
    ============================  */

    token = get_token ();
    if (token == tok_numeric)
        output_value (current_token_value ());
    else if (current_token_string() != NULL)
        output_token (current_token_string ());

/*  Output option keywords and then the file name.
    ==============================================  */

    done = 0;
    while (!done) {
        token = get_token ();

        switch (token) {
        case tok_preload:
            output_token("PRELOAD");
            break;
        case tok_loadoncall:
            output_token("LOADONCALL");
            break;
        case tok_fixed:
            output_token("FIXED");
            break;
        case tok_moveable:
            output_token("MOVEABLE");
            break;
        case tok_discardable:
            output_token("DISCARDABLE");
            break;
        default:
            if (current_token_string() != NULL)
                output_token (current_token_string ());
            done = 1;
            break;
        }
    }
}


#define OPTIONSUBMENU 1
#define OPTIONSEPARATOR 2

/**************************************************************************
 *                                                                        *
 *  CONVERT_MENU_OPTIONS                                                  *
 *                                                                        *
 *  This procedure is called to convert menu item options.                *
 *  returns OPTIONSUBMENU if it's submenu                                 *
 *  returns OPTIONSEPARATOR if it's a separator                           *
 *  otherwise, returns 0.                                                                      *
 *                                                                        *
 **************************************************************************/

ushort convert_menu_options (uchar ptr buffer)
{
    ushort      token;
    ushort	    ret = 0;
    ushort      error = 0;

/*  While we have options, read and process them.
    =============================================  */

    while ((token = get_token ()) == tok_comma || token == tok_bitor) {

/*      Get the token to process.
        =========================  */

        token = get_token ();

/*      If we've encountered an error, don't bother to process.
        ======================================================= */

        if (error)
            continue;

/*      Otherwise, process this option.
        =============================== */

        switch (token) {

        case tok_mia_disabled:
	        if (buffer)
	            string_append(buffer, ", CHECKED");
	        else
		        output_token (", CHECKED");
            break;

	    case tok_mia_checked:
	        if (buffer)
		        string_append(buffer, ", INACTIVE");
	        else
		        output_token (", INACTIVE");
            break;

        case tok_mis_bitmap:
            report_warning("Warning -- MIS_BITMAP not supported. ", token, NULL, 0L);
            error = 1;
            break;          

	    case tok_mis_breakseparator:
	        if (buffer)
		        string_append(buffer, ", MENUBARBREAK");
	        else
		        output_token (", MENUBARBREAK");
	        break;

        case tok_mis_break:
	        if (buffer)
                string_append(buffer, ", MENUBREAK");
	        else
		        output_token (", MENUBREAK");
            break;

        case tok_mis_ownerdraw:
	        if (buffer)
		        string_append(buffer, ", CHECKED");
	        else
		        output_token ("CHECKED");
            break;

	    case tok_mis_separator:
	        ret = OPTIONSEPARATOR;
	        break;

        case tok_mis_text:
            break;

	    case tok_mis_submenu:
	        ret = OPTIONSUBMENU;
	        break;

        case tok_mis_buttonseparator:
	        report_warning("Warning - MIS_BUTTONSEPARATOR not supported.", token, current_token_string(),0);
	        break;

        case tok_mis_syscommand:
	        report_warning("Warning - MIS_SYSCOMMAND not supported.", token, current_token_string(),0);
            error = 1;
	        break;

        default:
            // report_error (err_bad_menu_option, token, current_token_string ());
            report_warning("Invalid menu option.  Option omitted.", token, NULL, 0L);
            error = 1;
            break;
        }
    }

/*  Put the last token back. */

put_token ();
return(ret);
}


/**************************************************************************
 *                                                                        *
 *  CONVERT_MENU_ITEMS                                                    *
 *                                                                        *
 *  This procedure is called to convert a menuitem statement.             *
 *                                                                        *
 *  Syntax:                                                               *
 *      POPUP text, [option-list]                                         *
 *      BEGIN                                                             *
 *          item-definitions                                              *
 *      END                                                               *
 *  or                                                                    *
 *      MENUITEM text, result, [option-list]                              *
 *  or                                                                    *
 *      MENUITEM SEPARATOR                                                *
 *                                                                        *
 **************************************************************************/

void convert_menu_items (ushort level)
{
    ushort      token;
    uchar   ptr string;
    uchar	ptr buffer;
    uchar ptr bufferTmp;
    uchar	buf[40];
    uchar	ptr buffer2;
    ushort	    option;

/*  Allocate buffer in case of MIS_SUBMENU.
    =======================================  */

    buffer = _fmalloc (max_string_size);
    buffer2 = _fmalloc (max_string_size);

/*  Output the BEGIN keyword.
    =========================  */

    output_newline ();
    output_tab (level + 1);
    token = get_token ();
    output_token ("BEGIN");

/*  Until we've seen the END keyword or the EOF, output the information
    for each of the menu items.
    ===================================================================  */

    while ((token = get_token ()) != tok_end && token != tok_eof) {

        output_newline ();
        output_tab (level + 1);

/*      If this menu item has submenus, output the POPUP keyword.
        =========================================================  */

        if (token == tok_submenu) {
            output_token ("POPUP");

            //  Output the menu item name.

            token = get_token ();
            if ((string = current_token_string ()) == NULL)
                string = ""; // was: string = current_token_string ();
	        double_ampersands(string);
            string_replace (string, search, replace);
            output_string (string);

            //  Get the comma and submenu identifier (which isn't used for
            //  windows).

            token = get_token ();         // Get the comma
            if (token == tok_comma)
                token = get_token ();     // If it was the comma, get the id
            else
                put_token();              // If not a comma, put it back

	        // Get any terminating commas.

	        token = get_token();
	        if (token != tok_comma)
	            put_token();

            //  Convert the menu options.

            convert_menu_options (NULL);   

            //  Get the BEGIN keyword and convert the menu items.

            convert_menu_items (level + 1);
        }

/*      If a regular item or separator, output the MENUITEM keyword.
        ============================================================  */

        else if (token == tok_menuitem) {

	        string_copy (buffer, "MENUITEM ");

            //  See if this is a separator or menu text.

            if ((token = get_token ()) == tok_separator) {
                string_append (buffer, "SEPARATOR ");
            }
            else {
	            if ((string = current_token_string ()) == NULL)
		            string = "";
	            double_ampersands(string);
                string_replace (string, search, replace);

	            // Save menu text in case of popup.

	            string_copy(buffer2, string);
	            string_append(buffer, "\"");
	            string_append (buffer, string);
	            string_append(buffer, "\"");

                //  Output the comma and menu identifier.

                token = get_token ();
	            string_append (buffer, ", ");
                token = get_token ();
	            if (token == tok_numeric) {
		            ltoa (current_token_value(), buf, 10);
		            string_append(buffer, buf);
		        } else {
		            if (bufferTmp = current_token_string ()) {
                        string_append(buffer, bufferTmp);
                    }
                }

                //  Convert the options list.

	            option = convert_menu_options (buffer);

                //  If the options say it's a SUBMENU, make it a POPUP.

	            if (option == OPTIONSUBMENU) {
		            string_copy (buffer, "POPUP ");
		            string_append(buffer, "\"");
		            string_append(buffer, buffer2);
		            string_append(buffer, "\"");
		            output_token(buffer);
		            convert_menu_items(level+1);
		        }

                //  If the options say separator, make it so.

	            else if (option == OPTIONSEPARATOR)
		            output_token("MENUITEM SEPARATOR");

                // Otherwise, just output the options.

	            else
		            output_token(buffer);
            }

/*      Unrecognized token in the menu description.
        =========================================== */

        } else {
            report_error (err_bad_menu_option, token, current_token_string ());
        }

/*  Continue looping until we reach the END keyword or end-of-file.
    ===============================================================  */
    }

/*  Output the END keyword. */

    output_newline ();
    output_tab (level + 1);
    output_token ("END");
    _ffree (buffer);
    _ffree (buffer2);
}


/**************************************************************************
 *                                                                        *
 *  CONVERT_MENU                                                          *
 *                                                                        *
 *  This procedure is called to convert a menu statement.                 *
 *                                                                        *
 *  Syntax:                                                               *
 *      menuid MENU [load-option] [mem-option]                            *
 *      BEGIN                                                             *
 *          item-definitions                                              *
 *      END                                                               *
 *                                                                        *
 **************************************************************************/

void convert_menu (void)
{
    ushort      token;

/*  Output the menu identifier.
    =========================== */

    token = get_token ();
    if (token == tok_numeric)
        output_value (current_token_value ());
    else if (current_token_string() != NULL)
        output_token (current_token_string ());

/*  Output the MENU keyword.
    ======================== */

    output_token ("MENU");

/*  Output any load and memory options.
    =================================== */

    while ((token = get_token ()) != tok_begin && token != tok_eof) {
        switch (token) {
        case tok_discardable:
            output_token ("DISCARDABLE");
            break;
        case tok_fixed:
            output_token ("FIXED");
            break;
        case tok_moveable:
            output_token ("MOVEABLE");
            break;
        case tok_loadoncall:
            output_token ("LOADONCALL");
            break;
        case tok_preload:
            output_token ("PRELOAD");
            break;
        default:
            report_error (err_bad_load_option, token, current_token_string ());
            break;
        }
    }

/*  Replace the BEGIN or eof token that caused us to exit the loop.
    =============================================================== */

    put_token ();

/*  Convert the menu items.
    ======================= */

    if (token != tok_eof)
        convert_menu_items (0);
}

/**************************************************************************
 *                                                                        *
 *  CONVERT_HELPTABLE							  *
 *                                                                        *
 *  This procedure is called to convert a help table.			  *
 *                                                                        *
 **************************************************************************/

void convert_helptable (void)
{
    ushort token;

    report_warning("Helptables not supported.", 0, NULL, 0);

    for (token = get_token();
	 token != tok_end && token != tok_eof;
	 token = get_token())
	;
}

/**************************************************************************
 *                                                                        *
 *  CONVERT_HELPSUBTABLE						  *
 *                                                                        *
 *  This procedure is called to convert a help table.			  *
 *                                                                        *
 **************************************************************************/

void convert_helpsubtable (void)
{
    ushort token;

    report_warning("Helpsubtables not supported.", 0, NULL, 0);

    for (token = get_token();
	 token != tok_end && token != tok_eof;
	 token = get_token())
	;
}

/**************************************************************************
 *                                                                        *
 *  CONVERT_INCLUDE                                                       *
 *                                                                        *
 *  This procedure is called to convert an include statement.             *
 *                                                                        *
 **************************************************************************/

void convert_include (void)
{
ushort      token;
uchar   ptr string;

/*  Get the filename. */

token = get_token ();
string = current_token_string ();

/*
 *  If this is the <os2.h> include file, we need to change it to <windows.h>.
 *  We also need to undefine a define because we need some defines that are
 *  not included.
 *
 *  If this is not <os2.h>, output the #include and the filename.
 */

output_newline();
if (equal_ignoring_case (string, "<os2.h>")) {
    output_token ("#undef RC_INVOKED");
    output_newline ();
    output_token ("#include");
    output_token ("<windows.h>");
    }
else {
    output_token ("#include");
    if (token == tok_string)
        output_string (string);
    else
        output_token (string);
    }
}


/**************************************************************************
 *                                                                        *
 *  CONVERT_ICON                                                          *
 *                                                                        *
 *  This procedure is called to convert an icon statement.                *
 *                                                                        *
 *  Syntax:                                                               *
 *      idvalue ICON filename                                             *
 *                                                                        *
 **************************************************************************/

void convert_icon (void)
{
    ushort      token;
    ushort      done;

/*  Output the ICON keyword. */

    output_token ("ICON");

/*  Output the identifier value. */

    token = get_token ();
    if (token == tok_numeric)
        output_value (current_token_value ());
    else if (token == tok_constant)
        output_token (current_token_string ());
    else if (current_token_string() != NULL)
        output_string (current_token_string());

/*  Output option keywords and then the file name.
    ==============================================  */

    done = 0;
    while (!done) {
        token = get_token ();

        switch (token) {
        case tok_preload:
            output_token("PRELOAD");
            break;
        case tok_loadoncall:
            output_token("LOADONCALL");
            break;
        case tok_fixed:
            output_token("FIXED");
            break;
        case tok_moveable:
            output_token("MOVEABLE");
            break;
        case tok_discardable:
            output_token("DISCARDABLE");
            break;
        default:
            if (current_token_string() != NULL)
                output_token (current_token_string ());
            done = 1;
            break;
        }
    }
}


/**************************************************************************
 *                                                                        *
 *  CONVERT_DIALOG_OPTIONS                                                *
 *                                                                        *
 *  This procedure is called to convert a dialog elements options.        *
 *                                                                        *
 **************************************************************************/

void convert_dialog_options (flag output)
{
ushort      token;

/*
 *  Until we find the 'stopper' keywords or the EOF, output the option
 *  information.
 */

for (token = get_token();
     token != tok_begin && token != tok_end && token != tok_eof &&
     token != tok_ltext && token != tok_rtext && token != tok_ctext &&
     token != tok_radiobutton && token != tok_autoradiobutton &&
     token != tok_checkbox && token != tok_autocheckbox &&
     token != tok_pushbutton && token != tok_defpushbutton &&
     token != tok_listbox && token != tok_groupbox && token != tok_entryfield
     && token != tok_icon;
     token = get_token()){

    /*
     *	If we have output something, output a '|' before the next keyword.
     */
    /*
     *  Output the option.
     */
    switch (token) {
        case tok_bs_autocheckbox:
	    if (output)
		output_token ("|");
            output_token ("BS_AUTOCHECKBOX");
	    output = TRUE;
            break;

        case tok_bs_autoradiobutton:
	    if (output)
		output_token ("|");
            output_token ("BS_AUTORADIOBUTTON");
	    output = TRUE;
            break;

        case tok_bs_checkbox:
	    if (output)
		output_token ("|");
            output_token ("BS_CHECKBOX");
	    output = TRUE;
            break;

        case tok_bs_default:
	    if (output)
		output_token ("|");
            output_token ("BS_DEFPUSHBUTTON");
	    output = TRUE;
            break;

        case tok_bs_help:
            break;

        case tok_bs_nopointerfocus:
            break;

        case tok_bs_pushbutton:
	    if (output)
		output_token ("|");
            output_token ("BS_PUSHBUTTON");
	    output = TRUE;
            break;

        case tok_bs_radiobutton:
	    if (output)
		output_token ("|");
            output_token ("BS_RADIOBUTTON");
	    output = TRUE;
            break;

        case tok_cbs_dropdown:
	    if (output)
		output_token ("|");
            output_token ("CBS_DROPDOWN");
	    output = TRUE;
            break;

        case tok_cbs_dropdownlist:
	    if (output)
		output_token ("|");
            output_token ("CBS_DROPDOWNLIST");
	    output = TRUE;
            break;

        case tok_cbs_simple:
	    if (output)
		output_token ("|");
            output_token ("CBS_SIMPLE");
	    output = TRUE;
            break;

        case tok_dt_bottom:
	    if (output)
		output_token ("|");
            output_token ("DT_TOP");
	    output = TRUE;
            break;

        case tok_dt_center:
	    if (output)
		output_token ("|");
            output_token ("DT_CENTER");
	    output = TRUE;
            break;

        case tok_dt_left:
	    if (output)
		output_token ("|");
            output_token ("DT_LEFT");
	    output = TRUE;
            break;

        case tok_dt_mnemonic:
            break;

        case tok_dt_right:
	    if (output)
		output_token ("|");
            output_token ("DT_RIGHT");
	    output = TRUE;
            break;

        case tok_dt_top:
	    if (output)
		output_token ("|");
            output_token ("DT_TOP");
	    output = TRUE;
            break;

        case tok_dt_vcenter:
	    if (output)
		output_token ("|");
            output_token ("DT_CENTER");
	    output = TRUE;
            break;

        case tok_dt_wordbreak:
	    if (output)
		output_token ("|");
            output_token ("DT_WORDBREAK");
	    output = TRUE;
            break;

	case tok_dt_halftone:
	    if (output)
		output_token ("|");
	    output_token ("DT_HALFTONE");
	    output = TRUE;
	    break;

        case tok_es_autoscroll:
	    if (output)
		output_token ("|");
            output_token ("ES_AUTOHSCROLL");
	    output = TRUE;
            break;

        case tok_es_center:
	    if (output)
		output_token ("|");
            output_token ("ES_CENTER");
	    output = TRUE;
            break;

        case tok_es_left:
	    if (output)
		output_token ("|");
            output_token ("ES_LEFT");
	    output = TRUE;
            break;

        case tok_es_margin:
            break;

        case tok_es_right:
	    if (output)
		output_token ("|");
            output_token ("ES_RIGHT");
	    output = TRUE;
            break;

	case tok_mls_vscroll:
	    if (output)
		output_token ("|");
	    output_token ("ES_AUTOVSCROLL");
	    output = TRUE;
            break;

	case tok_mls_wordwrap:
	    break;

	case tok_mls_border:
	    if (output)
		output_token ("|");
	    output_token ("WS_BORDER");
	    output = TRUE;
	    break;

        case tok_fcf_sysmenu:
	    if (output)
		output_token ("|");
            output_token ("WS_SYSMENU");
	    output = TRUE;
            break;

        case tok_fcf_titlebar:
	    if (output)
		output_token ("|");
            output_token ("WS_CAPTION");
	    output = TRUE;
            break;

        case tok_fs_border:
	    if (output)
		output_token ("|");
            output_token ("DS_MODALFRAME");
	    output = TRUE;
            break;

        case tok_fs_dlgborder:
	case tok_fcf_dlgborder:
	    if (output)
		output_token ("|");
            output_token ("DS_MODALFRAME");
	    output = TRUE;
            break;

        case tok_fs_mousealign:
            break;

	case tok_fcf_icon:
	case tok_fs_icon:
	    report_warning("Icon style on dialogs not supported.", token, current_token_string(), 0);
	    break;

	case tok_fcf_minbutton:
	    report_warning("Minimize style on dialogs not supported.", token, current_token_string(), 0);
	    break;

        case tok_fs_nobytealign:
	case tok_fcf_nobytealign:
            break;

        case tok_ls_horzscroll:
	    if (output)
		output_token ("|");
            output_token ("WS_HSCROLL");
	    output = TRUE;
            break;

        case tok_ls_multiplesel:
	    if (output)
		output_token ("|");
            output_token ("LBS_MULTIPLESEL");
	    output = TRUE;
            break;

	case tok_ls_ownerdraw:
	    if (output)
		output_token ("|");
	    output_token ("LBS_OWNERDRAWFIXED");
	    output = TRUE;
	    break;

        case tok_sbs_horz:
	    if (output)
		output_token ("|");
            output_token ("SBS_HORZ");
	    output = TRUE;
            break;

        case tok_sbs_vert:
	    if (output)
		output_token ("|");
            output_token ("SBS_VERT");
	    output = TRUE;
            break;

	case tok_ss_icon:
        case tok_ss_fgndframe:
        case tok_ss_groupbox:
        case tok_ss_halftoneframe:
            /*
             *  This information was already output with the static
             *  style.
             */
            break;

        case tok_ss_text:
            break;

        case tok_ws_clipsiblings:
	    if (output)
		output_token ("|");
            output_token ("WS_CLIPSIBLINGS");
	    output = TRUE;
            break;

        case tok_ws_group:
	    if (output)
		output_token ("|");
            output_token ("WS_GROUP");
	    output = TRUE;
            break;

        case tok_ws_savebits:
	    if (output)
		output_token ("|");
            output_token ("CS_SAVEBITS");
	    output = TRUE;
            break;

        case tok_ws_tabstop:
	    if (output)
		output_token ("|");
            output_token ("WS_TABSTOP");
	    output = TRUE;
            break;

        case tok_ws_visible:
	    if (output)
		output_token ("|");
            output_token ("WS_VISIBLE");
	    output = TRUE;
            break;

	case tok_numeric:
	    report_warning ("Warning - Unknown window style.", token, NULL, current_token_value ());
	    output_value(current_token_value());
	    break;

	case tok_string:
	    report_warning ("Warning - Unknown window style.", token, current_token_string (), 0);
	    output_string(current_token_string());
	    break;

    case tok_comma:
        put_token();
        break;  //JMH

        default:
            report_error (err_bad_dialog_option, token, current_token_string ());
            break;
        }
    /*
     *  Skip over the '|' or ',' characters. If it isn't one of these
     *  two characters, exit.
     */
    if ((token = get_token ()) != tok_bitor && token != tok_comma) {
        put_token ();
        return;
        }
    }

/*  Put back the last token. */

put_token ();
}


/**************************************************************************
 *                                                                        *
 *  CONVERT_DLGTEMPLATE                                                   *
 *                                                                        *
 *  This procedure is called to convert a dlgtemplate statement.          *
 *                                                                        *
 *  Syntax:                                                               *
 *      nameid DIALOG [load-option] [mem-option] x, y, width, height      *
 *      [option-statements]                                               *
 *      BEGIN                                                             *
 *          control-statements                                            *
 *      END                                                               *
 *                                                                        *
 **************************************************************************/

void convert_dlgtemplate (void)
{
ushort	    token;
uchar	ptr string;
uchar	ptr title;
long	    dlg_width, dlg_height;
long	    x, y, width, height;
ushort	    type;
ushort	    ctltype;
ushort	    fOutputOr;

/*  Output the name identifier. */

token = get_token ();
output_token (current_token_string ());

/*  Output the DIALOG keyword. */

output_token ("DIALOG");

/*
 *  Until we see the BEGIN keyword of the EOF, output the load and
 *  memory options.
 */

while ((token = get_token ()) != tok_begin && token != tok_eof) {
    switch (token) {
        case tok_discardable:
            output_token ("DISCARDABLE");
            break;
        case tok_fixed:
            output_token ("FIXED");
            break;
        case tok_moveable:
            output_token ("MOVEABLE");
            break;
        case tok_loadoncall:
            output_token ("LOADONCALL");
            break;
        case tok_preload:
            output_token ("PRELOAD");
            break;
        default:
            report_error (err_bad_load_option, token, current_token_string ());
            break;
        }
    }

/*  Skip over the DIALOG/FRAME keyword and make a copy of the title. */

type = get_token ();
token = get_token ();
title = _fmalloc (string_length (current_token_string ()) + 1);
string_copy (title, current_token_string ());

/*  Skip over the comma, second dialog identifier, and another comma. */

token = get_token ();
token = get_token ();
token = get_token ();

/*  Output the x, y, width, and height values. */

output_newline ();
output_tab (2);

token = get_token ();
x = current_token_value ();
output_value (x);
token = get_token ();
output_token (",");

token = get_token ();
y = current_token_value ();
output_value (y);
token = get_token ();
output_token (",");

token = get_token ();
dlg_width = current_token_value ();
output_value ((long) ((double) dlg_width * .8));
token = get_token ();
output_token (",");

token = get_token ();
dlg_height = current_token_value ();
output_value (dlg_height);
token = get_token ();

/*  Output the dialog title. */

output_newline ();
output_tab (2);
output_token ("CAPTION");
output_string (title);
_ffree (title);

/*  Output the dialog style information. */

output_newline ();
output_tab (2);
output_token ("STYLE");
convert_dialog_options (FALSE);
if (type == tok_frame)
    output_token (" | WS_CHILD");

/*  Output the BEGIN keyword. */

output_newline ();
output_tab (1);
token = get_token ();
output_token ("BEGIN");

/*
 *  While there are still control statements in the dialog, convert them.
 *  Syntax:
 *      CONTROL text, id, class, style, x, y, width, height
 */

for (token = get_token();
     token != tok_end && token != tok_eof;
     token = get_token()){
    /*
     *  Output the CONTROL keyword.
     */
    output_newline ();
    output_tab (2);
    output_token ("CONTROL");

    ctltype = token;

    /*
     *  Output the text and a comma.
     */
    /* listboxes don't have text */
    if (ctltype == tok_listbox)
	output_string("");
    else {
	token = get_token ();
	string = current_token_string ();
	/* check for ICON case, where text can be a constant */
	if (token == tok_constant)
	    output_token(string);
	else {
	    double_ampersands(string);
	    string_replace (string, search, replace);
	    output_string (string);
	    }
	/* get the following comma */
	token = get_token ();
	if (token != tok_comma)
	    put_token();
	}

    output_token (",");
    /*
     *  Output the control identifier and a comma.
     */
    token = get_token ();
    if (token == tok_numeric)
        output_value (current_token_value ());
    else if (token == tok_did_ok)
	output_token("IDOK");
    else if (token == tok_did_cancel)
	output_token("IDCANCEL");
    else
        output_token (current_token_string ());
    token = get_token ();
    output_token (",");
    /*
     *  The next four fields are x, y, width, and height. We need to save
     *  these off because they are output after the class and style options.
     */
    token = get_token ();
    x = current_token_value ();
    token = get_token ();

    token = get_token ();
    y = current_token_value ();
    token = get_token ();

    token = get_token ();
    width = current_token_value ();
    token = get_token ();

    token = get_token ();
    height = current_token_value ();

    /* if next thing is a comma, get it */
    token = get_token ();
    if (token != tok_comma)
	put_token();

    /*
     *	If using CONTROL syntax, the next option will be the control class.
     *	If using alternate syntax, fake code into believing there is a style.
     */
    if (ctltype == tok_control){
	type = token = get_token ();
	}
    else
	type = token = ctltype;
    fOutputOr = FALSE;
    if (token == wc_static) {
	/*
	 *  Get the comma and the type of static item.
	 */
	token = get_token ();
	token = get_token ();
	switch (token) {
	    case tok_ss_fgndframe:
		output_token ("STATIC, SS_GRAYFRAME ");
		fOutputOr = TRUE;
		break;

	    case tok_ss_groupbox:
		output_token ("BUTTON, BS_GROUPBOX");
		fOutputOr = TRUE;
		break;

	    case tok_ss_halftoneframe:
		output_token ("STATIC, SS_GRAYFRAME");
		fOutputOr = TRUE;
		break;

	    case tok_ss_text:
		output_token ("STATIC,");
		break;

	    case tok_ss_icon:
		output_token ("STATIC, SS_ICON");
		fOutputOr = TRUE;
		break;

	    default:
		report_error (err_bad_control_class, token, current_token_string ());
		break;
	    }
	/*
	 *  Put the static type back to make parsing consistent in
	 *  convert_dialog_options. However, since we've already output
	 *  the information here, convert_dialog_options will just ignore
	 *  the ss_xxx tokens.
	 */
	put_token ();
	output_newline ();
	output_tab (3);
	}
    else {
	switch(token) {
	    case tok_icon:
		output_token ("STATIC, SS_ICON");
		fOutputOr = TRUE;
		break;
	    case tok_ltext:
		output_token ("STATIC, DT_LEFT");
		fOutputOr = TRUE;
		break;
	    case tok_rtext:
		output_token ("STATIC, DT_RIGHT");
		fOutputOr = TRUE;
		break;
	    case tok_ctext:
		output_token ("STATIC, DT_CENTER");
		fOutputOr = TRUE;
		break;
	    case tok_radiobutton:
		output_token ("BUTTON, BS_RADIOBUTTON");
		fOutputOr = TRUE;
		break;
	    case tok_autoradiobutton:
		output_token ("BUTTON, BS_AUTORADIOBUTTON");
		fOutputOr = TRUE;
		break;
	    case tok_checkbox:
		output_token ("BUTTON, BS_CHECKBOX");
		fOutputOr = TRUE;
		break;
	    case tok_autocheckbox:
		output_token ("BUTTON, BS_AUTOCHECKBOX");
		fOutputOr = TRUE;
		break;
	    case tok_pushbutton:
		output_token ("BUTTON, BS_PUSHBUTTON");
		fOutputOr = TRUE;
		break;
	    case tok_defpushbutton:
		output_token ("BUTTON, BS_DEFPUSHBUTTON");
		fOutputOr = TRUE;
		break;
	    case tok_groupbox:
		output_token ("BUTTON, BS_GROUPBOX");
		fOutputOr = TRUE;
		break;
	    case wc_button:
		output_token ("BUTTON,");
		break;

	    case wc_combobox:
		output_token ("COMBOBOX,");
		break;

	    case wc_mle:
		output_token ("EDIT, ES_MULTILINE");
		fOutputOr = TRUE;
		height += 2;
		break;

	    case tok_entryfield:
		type = wc_entryfield;
	    case wc_entryfield:
		output_token ("EDIT, WS_BORDER");
		fOutputOr = TRUE;
		height += 2;
		break;

	    case tok_listbox:
		type = wc_listbox;
	    case wc_listbox:
		output_token ("LISTBOX, LBS_NOTIFY | WS_BORDER | WS_VSCROLL");
		fOutputOr = TRUE;
		break;

	    case wc_scrollbar:
		output_token ("SCROLLBAR,");
		break;

	    case tok_string:
		report_warning ("Warning - Unknown control class.", token, current_token_string (), 0);
		output_string (current_token_string());
		output_token (",");
		type = wc_static;
		break;

	    default:
		report_error (err_bad_control_class, token, current_token_string ());
		break;
	    }
	/*
	 *  Get the comma and output a newline.
	 */
	token = get_token ();
	if (token != tok_comma)
	    put_token();
	output_newline ();
	output_tab (3);
	}

    /*
     *  Output the style options.
     */
    convert_dialog_options (fOutputOr);
    output_token (",");
    output_newline ();
    output_tab (3);
    /*
     *  Now we can output the x, y, width, and height information.
     */
    output_value ((long) ((double) x * .8));
    output_token (",");
    if (type == wc_listbox)
        output_value (dlg_height - y - height + 2);
    else
        output_value (dlg_height - y - height);
    output_token (",");
    output_value ((long) ((double) width * .8));
    output_token (",");
    if (type == wc_entryfield)
        output_value (height + 2);
    else
        output_value (height);
    }

/*  Output the END keyword. */

output_newline ();
output_tab (1);
token = get_token ();
output_token ("END");
}


/**************************************************************************
 *                                                                        *
 *  CONVERT_BITMAP                                                        *
 *                                                                        *
 *  This procedure is called to convert a bitmap statement.               *
 *                                                                        *
 *  Syntax:                                                               *
 *      idvalue BITMAP filename                                           *
 *                                                                        *
 **************************************************************************/

void convert_bitmap (void)
{
    ushort      token;
    ushort      done;

/*  Output the identifier value.
    ============================  */

    token = get_token ();
    if (token == tok_numeric)
        output_value (current_token_value ());
    else if (current_token_string() != NULL)
        output_token (current_token_string ());

/*  Output the PM12BITMAP keyword.
    ==============================  */

    output_token ("BITMAP");

/*  Output option keywords and then the file name.
    ==============================================  */

    done = 0;
    while (!done) {
        token = get_token ();

        switch (token) {
        case tok_preload:
            output_token("PRELOAD");
            break;
        case tok_loadoncall:
            output_token("LOADONCALL");
            break;
        case tok_fixed:
            output_token("FIXED");
            break;
        case tok_moveable:
            output_token("MOVEABLE");
            break;
        case tok_discardable:
            output_token("DISCARDABLE");
            break;
        default:
            if (current_token_string() != NULL)
                output_token (current_token_string ());
            done = 1;
            break;
        }
    }
}


/**************************************************************************
 *                                                                        *
 *  CONVERT_ACCELTABLE                                                    *
 *                                                                        *
 *  This procedure is called to convert an acceltable statement.          *
 *                                                                        *
 *  Syntax:                                                               *
 *      acctablename ACCELERATORS                                         *
 *      BEGIN                                                             *
 *          event, idvalue, [type] [NOINVERT] [ALT] [SHIFT] [CONTROL]     *
 *                                                                        *
 *                                                                        *
 **************************************************************************/

void convert_acceltable (void)
{
ushort      token;                          /* token type */
uchar   ptr string;
ushort	    fControl = FALSE;

/*  Get the table identifier. */

get_token ();
output_token (current_token_string ());

/*  Output the ACCELERATOR and BEGIN keywords. */

output_token ("ACCELERATORS");
output_newline ();
output_token ("BEGIN");

/*
 *  Windows doesn't have any load options, so scan through any that might
 *  be associated with the OS/2 definition.
 */

while ((token = get_token ()) != tok_begin && token != tok_eof);

/*
 *  Until we've seen the END keyword or the EOF, output the information
 *  for each of the accelerators.
 */

while ((token = get_token ()) != tok_end && token != tok_eof) {
    /*
     *  Output the event.
     */
    output_newline ();
    output_tab (1);
    if (token == tok_numeric)
        output_value (current_token_value ());
    else {
        string = current_token_string ();
        if (token == tok_string) {
	    if (*string == '^'){
		string_copy(string, string+1);
		fControl = TRUE;
		}
	    else
		fControl = FALSE;
            convert_to_upper (string);
            output_string (string);
            }
        else if (equal_ignoring_case (string, "VK_BACKSPACE"))
            output_token ("VK_BACK");
        else
            output_token (string);
        }
    /*
     *  Output the comma.
     */
    token = get_token ();
    output_token (",");
    /*
     *  Output the idvalue.
     */
    token = get_token ();
    if (token == tok_numeric)
        output_value (current_token_value ());
    else
        output_token (current_token_string ());

    if ((token = get_token ()) == tok_plus) {
        output_token ("+");
        token = get_token ();
        output_value (current_token_value ());
        token = get_token ();
        }
    /*
     *  We want to make everything a virtual key, so output VERTKEY.
     */
    output_token (",");
    output_token ("VIRTKEY");
    /*
     *  While there are still commas, interpret the modifiers.
     */
    while (token == tok_comma) {
        /*
         *  Output the modifier.
         */
        token = get_token ();
        switch (token) {
            case tok_alt:
                output_token (",");
                output_token ("ALT");
                break;
            case tok_char:
                output_token (",");
                output_token ("ASCII");
                break;
            case tok_control:
                output_token (",");
                output_token ("CONTROL");
                break;
            case tok_shift:
                output_token (",");
                output_token ("SHIFT");
                break;
            case tok_virtualkey:
                /*
                 *  Everything is already a virtual key, so don't ouput
                 *  anything.
                 */
                break;
	    case tok_syscommand:
		report_warning("Warning - SYSCOMMAND accels not supported.", token, current_token_string(), 0);
		break;
            default:
                report_error (err_bad_accel_option, token, current_token_string ());
                break;
            }
        token = get_token ();
        }
    if (fControl) {
	output_token (",");
	output_token ("CONTROL");
	fControl = FALSE;
	}
    put_token ();
    }

/*  Output the END keyword. */

output_newline ();
output_token ("END");
}


/**************************************************************************
 *                                                                        *
 *  CONVERT_RESOURCES                                                     *
 *                                                                        *
 *  This procedure is called to parse the OS/2 resource file and convert  *
 *  it into a Windows resource file.                                      *
 *                                                                        *
 **************************************************************************/

void convert_resources (void)
{
ushort      token;                          /* input token */

/*  While there are still input tokens, process them. */

while ((token = get_token ()) != tok_eof) {
    switch (token) {
        case tok_acceltable:
            output_newline ();
            convert_acceltable ();
            output_newline ();
            break;

        case tok_bitmap:
            convert_bitmap ();
            output_newline ();
            break;

        case tok_dlgtemplate:
            output_newline ();
            convert_dlgtemplate ();
            output_newline ();
            break;

	    case tok_helptable:
	        convert_helptable();
	        break;

	    case tok_helpsubtable:
	        convert_helpsubtable();
	        break;

        case tok_icon:
            convert_icon ();
            output_newline ();
            break;

        case tok_include:
            convert_include ();
            output_newline ();
            break;

        case tok_menu:
            output_newline ();
            convert_menu ();
            output_newline ();
            break;

        case tok_pointer:
            convert_pointer ();
            output_newline ();
            break;

        case tok_rcinclude:
            process_rcinclude ();
            output_newline ();
            break;

        case tok_resource:
            convert_resource ();
            output_newline ();
            break;

        case tok_stringtable:
            output_newline ();
            convert_stringtable ();
            output_newline ();
            break;

	    case tok_dlginclude:
	        process_dlginclude();
	        break;

        default:
            report_error (err_convert_resources, token, current_token_string ());
            break;
        }
    }
}


/**************************************************************************
 *                                                                        *
 *  PROCESS_PARAMS                                                        *
 *                                                                        *
 *  This procedure is called to parse the parameter string and do         *
 *  the right thing.                                                      *
 *                                                                        *
 **************************************************************************/

flag process_params (int argc, char *argv [])
{
uchar   ptr src_fname;                      /* source filename */
uchar   ptr dst_fname;                      /* destination filename */

/*  Skip over our program name. */

argc--;
argv++;

//JMH Is there a debug flag?
if (*(*argv) == '-')
    {
    is_debug_on = TRUE;
    argc--;
    argv++;
    }

/*  We must have a source file name. */

if (argc < 1) {
    printf ("Incorrect usage: A source file name is required.\n");
    printf (usage_msg);
    return FALSE;
    }
src_fname = *argv++;
argc--;

/*  We must have a destination file name. */

if (argc < 1) {
    printf ("Incorrect usage: A destination file name is required.\n");
    printf (usage_msg);
    return FALSE;
    }
dst_fname = *argv++;
argc--;

/*  We should not have any more parameters. */

if (argc != 0) {
    printf ("Incorrect usage: Extra parameters found on command line\n");
    printf (usage_msg);
    return FALSE;
    }

/*  Open the source and destination files. */

if (cant open_source_file (src_fname) ||
    cant open_destination_file (dst_fname))
    return FALSE;

/*  Success. */

return TRUE;
}


/**************************************************************************
 *                                                                        *
 *  MAIN                                                                  *
 *                                                                        *
 *  This procedure is called by the system when the program is executed.  *
 *                                                                        *
 **************************************************************************/

void main (int argc, char *argv [])
{

/*  Do some initialization. */

//_asm int 03h  // put this line for debug break on entry
initialize_input ();

/*  Process the startup parameters and convert the resources. */


if (process_params (argc, argv))
    convert_resources ();

/*  Do some cleanup. */

close_destination_file ();
terminate_input ();
}
