/*
 *  ======== package/cfg/main_pe430.cfg ========
 *  This generated configuration script runs the user's configuration script
 *  the context of a specific target and platform in order to generate
 *  all the files necessary to create an executable; e.g., linker command
 *  files, static C/C++ data structures, etc.
 */

/*
 *  ======== _applyChanges ========
 *  Changes that bring the build target to the state at the end of the build
 *  model
 */
function _applyChanges(obj, chgObj) {
    var wasSealed = false;
    if (obj.$sealed) {
        wasSealed = true;
        obj.$unseal();
    }
    for (var prop in chgObj) {
        if (typeof obj[prop] == 'object' && obj[prop] != undefined) {
            if ("$category" in obj[prop] && obj[prop].$category == "Vector") {
               obj[prop].length = chgObj[prop].length;
               for (var i = 0; i < chgObj[prop].length; i++) {
                   if (obj[prop].length < i + 1) {
                       obj[prop].length++;
                   }
                   obj[prop][i] = chgObj[prop][i];
               }
            }
            else {
        	_applyChanges(obj[prop], chgObj[prop]);
            }
	}
	else {
            obj[prop] = chgObj[prop];
	}
    }
    if (wasSealed) {
        obj.$seal();
    }
}

/*
 *  ======== _runescape ========
 *  Recursive unescape to decode serialized strings
 */
function _runescape(obj) {
    for (var i in obj) {
	if (obj[i] != null) {
	    if (typeof obj[i] == 'string') {
		obj[i] = unescape(obj[i]);
	    }
	    else if (typeof obj[i] == 'object') {
		_runescape(obj[i]);
	    }
	}
    }
}

/*
 *  ======== _getPlatCfg ========
 */
function _getPlatCfg() {
    var tmp = {};
    _runescape(tmp);
    return (tmp);
}
/*
 *  ======== _cfginit ========
 */
function _cfginit() {
    xdc.loadPackage('xdc.services.intern.cmd');
    var prog = xdc.om['xdc.cfg.Program'];

    /* initialize prog attrs from build model */
    var build = {
        profile: "release",
        cfgScript: "C%3A/Work/CCS/ADS1118_Grace/main.cfg",
        cfgHome: "xconfig_main",
        cfgArgs: "null",
        cfgArgsEncoded: true,
        releases: {
            0: {
                name: "xconfig_main",
                attrs: {
                    prefix: "",
                    label: "default"
                },
                otherFiles: {},
                excludeDirs: {}
            }
        },
        prelink: false
    };
    _runescape(build);
    build.cfgArgs = null;
    build.target = xdc.module("ti.targets.msp430.elf.MSP430");
    var targChange = {
        platform: "ti.platforms.exp430F5438",
        platforms: [
            "ti.platforms.exp430F5438"
        ],
        version: "ti.targets.msp430.elf.MSP430%7B1%2C0%2C4.1%2C1",
        extensions: {
            ".se430": {
                suf: ".se430",
                typ: "asm"
            },
            ".s430": {
                suf: ".s430",
                typ: "asm"
            }
        },
        rootDir: "C%3A/ti/ccsv5/tools/compiler/msp430_4.1.1",
        ccOpts: {
            prefix: "--symdebug%3Adwarf%20--optimize_with_debug%20-qq%20-pdsw225"
        }
    };
    _runescape(targChange);
    _applyChanges(build.target, targChange);

    prog.build = build;
    
    prog.name = "main.xe430";
    prog.cfgBase = "package/cfg/main_pe430";

    prog.endian = prog.build.target.model.endian;
    prog.codeModel = prog.build.target.model.codeModel;
    prog.dataModel = prog.build.target.model.dataModel;

    /* use the platform package's Platform module */
    var Platform = xdc.useModule("ti.platforms.msp430.Platform");
    var platParams = _getPlatCfg();
    var invalidParams = [];
    for (var prop in platParams) {
        if (!(prop in Platform.PARAMS)) {
            delete platParams[prop];
            invalidParams.push(prop);
        }
    }
    prog.platformName = "ti.platforms.msp430:MSP430G2553";
    prog.platform = Platform.create("MSP430G2553", _getPlatCfg(), platParams);
    for (var i = 0; i < invalidParams.length; i++) {
        Platform.$logWarning("The parameter '" + invalidParams[i] + "' is " +
            "passed to this platform instance through Build.platformTable, " +
            "but the instance does not have a configuration parameter with " +
            "that name.", prog.platform, "MSP430G2553");
    }

    /* record the executable's package name */
    prog.buildPackage = "xconfig_main";

    /* record build-model information required during config generation */
    prog.$$bind("$$isasm", 0);
    prog.$$bind("$$isrom", 0);
    prog.$$bind("$$gentab", [
    ]);
    
    /* bind prog to an appropriate execution context */
    prog.cpu = prog.platform.getExeContext(prog);

    /* import the target's run-time support pkg */
    xdc.loadPackage("ti.targets.msp430.rts430");
}
    
/* function to import the cfg script's package */
function _userscript($$legacy, script) {
    var home;
    var spath;
    home = xdc.loadPackage("xconfig_main");
    
    xdc.om.$$bind('$homepkg', home);

    var platParams = _getPlatCfg();

    /* load & run program cfg script and monitor all loaded files */
    _runCfg("C:/Work/CCS/ADS1118_Grace/main.cfg", spath, "package/cfg/main_pe430",  
             undefined, 
             undefined,
             platParams, script);

    /*
     *  ======== _loadOrEval ========
     *  Either load the user configuration script from disk, or else
     *  execute the supplied source text directly. In either case,
     *  provide the same execution environment.
     */
    function _loadOrEval(cfgScript, noTrack, path, script) {
        if (!script) {
            utils.loadCapsule(cfgScript, noTrack, path);
        }
        else {
            /* set up the same environment that loadCapsule would */
            var $saveCsd = utils.csd;
            var $cfgFile = utils.findFile(cfgScript, path);
            var cname = cfgScript;
            if ($cfgFile) {
                $cfgFile = java.io.File($cfgFile);
                utils.csd = $cfgFile.getParentFile().getCanonicalPath();
                cname = "" + $cfgFile.getCanonicalPath();
            }

            /* create the capsule object */
            var cap = {
                prototype:  utils.global,
                $path:      cname,
                $private:   {path: cname},
                $capsule:   undefined,      /* set to cap below */
            };

            /* 'this.$capsule' is always cap object */
            cap.$capsule = cap;

            /* save the capsule object */
            utils.$$capmap[cname] = cap;

            try {
                var cx =
                    Packages.org.mozilla.javascript.Context.getCurrentContext();
                var rdr = new
                    java.io.BufferedReader(new java.io.StringReader(script));
                Packages.config.Shell.evaluateLoad(cx, cap, rdr, cname, 1);
            }
            finally {
                rdr.close();
                utils.csd = $saveCsd;
            }
        }
    }

    /*
     *  ======== _runCfg ========
     *  Run a user supplied configuration script and prevent user's script from
     *  overwriting the global variable prog.
     */
    function _runCfg(cfgScript, path, programName, legacyTcf, legacyCfg,
        platParams, script)
    {
        if (legacyTcf) {
            /* save current global variables */
            var $save = {prog: utils.global.prog, Program: Program};
    
            /* initialize global variables for legacy config scripts */
            environment["config.programName"] = programName;
            environment["config.platform"] = Program.platformName;
            utils.seedPath = environment["config.importPath"];
            utils.loadPlatform.params = platParams;
            Program = $$legacy.Program;     /* defined in cfg.tci */
            
            /* run legacy config script with prog == to RTSC Program; this
             * allows legacy script to read build atributes from RTSC model
             * before re-creating the prog object
             */
            utils.loadCapsule(cfgScript, false, path);  
    
            /* restore global variables; now prog == TCOM prog because
             * utils.loadPlatform() creates the TCOM prog object.
             */
            $$legacy.prog = utils.global.prog;  /* in case XDC wants it */
            utils.global.prog = $save.prog;
            Program = $save.Program;
    
            /* run XDC configuration script, if it exists */
            if (legacyCfg) {
                utils.importFile(cfgScript.replace(/\.tcf/, ".cfg"), path);
            }
        }
        else {
            _loadOrEval(cfgScript, false, path, script);
        }
    }
}
    
function _postinit() {

    var cout = null;

    var Program = xdc.om['xdc.cfg.Program'];
    /* get the exec command for this executable */
    if (Program.execCmd == null) {
        Program.execCmd = Program.platform.getExecCmd(Program,
            xdc.om["ti.platforms.msp430"].packageBase);
    }
    cout = "define EXEC." + Program.name + '\n\n';
    cout += Program.execCmd;
    cout += "\nendef\n\n";

    /* if SourceDir generates a makefile, we need to run it */
    _genSourceDirMak("package/cfg/main_pe430", "main.pe430");

    utils.genDep("package/cfg/main_pe430", "xconfig_main", utils.loadedFiles, cout, null);
}

function _genSourceDirMak(cfgBase, cfgName)
{
    var SourceDir = xdc.om['xdc.cfg.SourceDir'];

    if (SourceDir && SourceDir.$instances.length > 0) {
        /* construct rule to run SourceDir generated makefile */
        var make = "\t$(MAKE) -f "
            + SourceDir.outputDir + "/" + SourceDir.makefileName;
    
        /* this file is included by package.mak (if it exists) */
        var file = new java.io.File(cfgBase + ".cfg.mak");
        file["delete"]();
        var out = new java.io.BufferedWriter(new java.io.FileWriter(file));

        /* add rules to run SourceDir generated makefile */
        out.write("# invoke SourceDir generated makefile for " + cfgName
            + "\n" + cfgName + ": .libraries," + cfgName
            + "\n.libraries," + cfgName + ": " + cfgBase + ".xdl\n"
            + make + "\n\n"
            + "clean::\n" + make + " clean\n\n"
        );
        out.close();
        out = null;
    }
}
