//%2003////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2000, 2001, 2002  BMC Software, Hewlett-Packard Development
// Company, L. P., IBM Corp., The Open Group, Tivoli Systems.
// Copyright (c) 2003 BMC Software; Hewlett-Packard Development Company, L. P.;
// IBM Corp.; EMC Corporation, The Open Group.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
// 
// THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN
// ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED
// "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
// LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
//==============================================================================
//
// Author: Bob Blair (bblair@bmc.com)
//
// Modified By:
//
//%/////////////////////////////////////////////////////////////////////////////


// A main for the cimmof_parser.  It can be embedded elsewhere, too. 

#include <Pegasus/Common/Config.h>
#include <iostream>
#include <Pegasus/Compiler/mofCompilerOptions.h>
#include "cmdlineExceptions.h"
#include <Pegasus/Compiler/cimmofParser.h>
#include <Pegasus/Compiler/parserExceptions.h>

#include <Pegasus/Common/PegasusVersion.h>

#ifdef PEGASUS_OS_OS400
#include <qycmutiltyUtility.H>
#include <qycmutilu2.H>
#include "vfyptrs.cinc"
#include <stdio.h>
#include "OS400ConvertChar.h"
#endif

PEGASUS_USING_STD;

#ifdef PEGASUS_HAVE_NAMESPACES
using namespace ParserExceptions;
#endif

// This is used by the parsing routines to control flow
// through include files
static mofCompilerOptions cmdline;


extern "C++" int processCmdLine(int, char **, mofCompilerOptions &, ostream &);

extern "C++" ostream& help(ostream& os);

extern "C++" ostream& warning(ostream& os);

#define NAMESPACE_ROOT "root/cimv2"

int
main(int argc, char ** argv) {
  int ret = 0;
  String msg_;
  MessageLoaderParms parms;

  MessageLoader::_useProcessLocale = true; //l10n set message loading to use process locale

#ifdef PEGASUS_OS_OS400

  VFYPTRS_INCDCL;               // VFYPTRS local variables

  // verify pointers
  #pragma exception_handler (qsyvp_excp_hndlr,qsyvp_excp_comm_area,\
    0,_C2_MH_ESCAPE)
    for( int arg_index = 1; arg_index < argc; arg_index++ ){
	VFYPTRS(VERIFY_SPP_NULL(argv[arg_index]));
    }
  #pragma disable_handler

    // Convert the args to ASCII
    for(Uint32 i = 0;i< argc;++i)
    {
	EtoA(argv[i]);
    }

  // check what environment we are running in, native or qsh
    Boolean qsh = false;
    if( getenv(
#pragma convert(37)
	       "SHLVL"
#pragma convert(0)
	       ) == NULL ){  // native mode
	// Check to ensure the user is authorized to use the command,
	// suppress diagnostic message, send escape message
	if(FALSE == ycmCheckCmdAuthorities(1)){
	  ycmSend_Message_Escape(CPFDF80_RC,
				 NULL,
				 NULL,
#pragma convert(37)
				 "*CTLBDY   ",
#pragma convert(0)
				 1);
	  return CPFDF80_RC;
	}
    }
    else{ // qsh mode
	// Check to ensure the user is authorized to use the command
	// ycmCheckCmdAuthorities() will send a diagnostic message to qsh
        qsh = true;
	if(FALSE == ycmCheckCmdAuthorities()){
	  return CPFDF80_RC;
	}
    }

#endif

  try {
    ret = processCmdLine(argc, argv, cmdline, cerr);
  } catch (ArgumentErrorsException &e) {
    cerr << e.getMessage() << endl;
    help(cerr);
    ret =  -2;
  } catch (CmdlineNoRepository &e) {
    cerr << e.getMessage() << endl;
    ret = -3;
  } catch (CIMException &e) {
  	//l10n
    //cerr << "Unexpected condition: " << e.getMessage() << endl;
    parms.msg_id = "Compiler.cmdline.cimmof.main.UNEXPECTED_CONDITION";
    parms.default_msg = "Unexpected condition: ";
    cerr << MessageLoader::getMessage(parms) << e.getMessage() << endl;
    ret = -4;
  }
  if (cmdline.is_local()) 
	warning(cerr);
  if (ret) {
    if (ret != 0) {
    	//l10n
      //cerr << "Unexpected result from processing command line: " << ret <<endl;
      //cerr << "Compilation terminating." << endl;
      parms.msg_id = "Compiler.cmdline.cimmof.main.UNEXPECTED_RESULT";
      parms.default_msg = "Unexpected result from processing command line: $0";
      parms.arg0 = ret;
      cerr << MessageLoader::getMessage(parms) << endl;
      parms.msg_id = "Compiler.cmdline.cimmof.main.COMPILE_TERMINATING";
      parms.default_msg = "Compilation terminating.";
      cerr << MessageLoader::getMessage(parms) << endl;
    }
    return ret;
  }
  const Array<String>& filespecs = cmdline.get_filespec_list();

#ifdef PEGASUS_OS_OS400
  // If quiet mode is chosen then shut down stdout and stderr.
  // This is used during product installation and PTF application.
  // We must be absolutely quiet to avoid a terminal being
  // activated in native mode.
  if (cmdline.quiet())
  {
      // Redirect to /dev/null.
      // Works for both qshell and native modes.
      freopen("/dev/null","w",stdout);
      freopen("/dev/null","w",stderr);
  } 	
#endif

  // For most options, a real repository is required.  If we can't
  // create one and we need to, bail. 
  cimmofParser *p = cimmofParser::Instance(); 
  p->setCompilerOptions(&cmdline);
  if ( p->setRepository() ) {	
    p->setDefaultNamespacePath(NAMESPACE_ROOT);
  } else {
  	//l10n
    //cerr << "Failed to set DefaultNamespacePath." << endl;
    parms.msg_id = "Compiler.cmdline.cimmof.main.FAILED_TO_SET";
    parms.default_msg = "Failed to set DefaultNamespacePath.";
    cerr << MessageLoader::getMessage(parms) << endl;
    // ATTN: P3 BB 2001 Did not set namespace.  We may need to log an error here. 
    ret = -9;
    return ret;
  }
  if (filespecs.size())    // user specified command line args
    for (unsigned int i = 0; i < filespecs.size(); i++) {
      if (p->setInputBufferFromName((const String &)filespecs[i]) == 0) {
	try {
	  ret = p->parse();
	} catch(ParserLexException &e) {
		//l10n
		parms.msg_id = "Compiler.cmdline.cimmof.main.LEXER_ERROR";
		parms.default_msg = "Lexer error: ";
	    //msg_ = String("Lexer error: ").append(e.getMessage());
	    msg_ = MessageLoader::getMessage(parms).append(e.getMessage());
	    ret = -5;
	} catch(Exception &e) {
		//l10n
		parms.msg_id = "Compiler.cmdline.cimmof.main.PARSING_ERROR";
		parms.default_msg = "Parsing error: ";
	    //msg_ = String("Parsing error: ").append(e.getMessage());
	    msg_ = MessageLoader::getMessage(parms).append(e.getMessage());
	    ret = -6;
	}
      } else {
	  //l10n
// l10n TODO - this path was not localized by the msg freeze for R2.3.  So, use an
// internal exception msg for now.  But, need to replace this with
// a new cimmof msg in release 2.4.
	  parms.msg_id = "Common.InternalException.CANNOT_OPEN_FILE";
	  parms.default_msg = "Can't open file $0";
          parms.arg0 = filespecs[i];
	  //msg_ = String("Can't open file ").append(filespecs[i]);
	  msg_ = MessageLoader::getMessage(parms);
          ret = -7;
      }
    }
  else {
    try {
    int ret =  p->parse();
    } catch(ParserLexException &e) {
    	//l10n
    	parms.msg_id = "Compiler.cmdline.cimmof.main.LEXER_ERROR";
	parms.default_msg = "Lexer error: ";
	    //msg_ = String("Lexer error: ").append(e.getMessage());
	    msg_ = MessageLoader::getMessage(parms).append(e.getMessage());
        ret = -5;
    } catch(Exception &e) {
    	//l10n
    	parms.msg_id = "Compiler.cmdline.cimmof.main.GENERAL_EXCEPTION";
    	parms.default_msg = "Compiler general exception: ";
	    //msg_ = String("Compiler general exception: ").append(e.getMessage());
	    msg_ = MessageLoader::getMessage(parms).append(e.getMessage());
        ret = -8;
    }
  }
  cerr << msg_ << endl;

#ifdef PEGASUS_OS_OS400
  // Send good completion message to stdout if the compile worked.
  // Callers of QYCMMOFL *PGM from the native command line will want to see this.
  // Note: in PTF mode the quiet option should be used.
  if (ret == 0)
  {
      //l10n
      //cout << "Compile completed successfully." << endl;
      parms.msg_id = "Compiler.cmdline.cimmof.main.COMPILE_SUCCESSFUL";
      parms.default_msg = "Compile completed successfully.";
      cout << MessageLoader::getMessage(parms) << endl;
  }

  // Send a CPDDF83 and CPFDF81 OS/400 program message if an error occurred,
  // and we are running in native mode.
  // This will allow PTFs to monitor for this message.
  if (ret != 0 && !qsh)
  {
      message_t    message_;	// Message information
      cmd_msg_t    cmdMSG;
      memset((char *)&cmdMSG, ' ', sizeof(cmd_msg_t) ); // init to blanks
      memcpy(cmdMSG.commandName, "QYCMMOFL", 7);  // must be in utf-8
      CString utf8 = msg_.getCStringUTF8();
      if (strlen((const char *)utf8) <= 200)            // max repl data is 200 chars  
	  memcpy(cmdMSG.message, utf8, strlen((const char *)utf8));
      else
	  memcpy(cmdMSG.message, utf8, 200);
#pragma convert(37)
      memcpy(message_.MsgId, "CPDDF83", 7);
      memcpy(message_.MsgData, (char *)&cmdMSG, sizeof(cmd_msg_t));
      message_.MsgLen = sizeof(cmd_msg_t);
      memcpy(message_.MsgType, "*DIAG     ", 10); 
      ycmSend_Message(&message_,
		      "*PGMBDY   ",
		      1,
		      true);                     // repl data is utf-8 

      ycmSend_Message_Escape(CPFDF81_RC,
			     "03",               // must be in ccsid 37
			     "QYCMMOFL",         // must be in ccsid 37
			     "*CTLBDY   ",
			     1);
#pragma convert(0)
  }
#endif

  return ret;
}
