code: /**
   * Copyright (c) 2004-2005, Regents of the University of California
   * All rights reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * Redistributions of source code must retain the above copyright notice,
   * this list of conditions and the following disclaimer.
   *
   * Redistributions in binary form must reproduce the above copyright
   * notice, this list of conditions and the following disclaimer in the
   * documentation and/or other materials provided with the distribution.
   *
   * Neither the name of the University of California, Los Angeles nor the
   * names of its contributors may be used to endorse or promote products
   * derived from this software without specific prior written permission.
   *
   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
   * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
   * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
   * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
   * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   */
  
  package avrora;
  
  import avrora.actions.*;
  import avrora.arch.ArchitectureRegistry;
  import avrora.core.Program;
  import avrora.core.ProgramReader;
  import avrora.monitors.*;
  import avrora.sim.Simulation;
  import avrora.sim.Simulator;
  import avrora.sim.clock.ClockDomain;
  import avrora.sim.mcu.*;
  import avrora.sim.platform.*;
  import avrora.sim.radio.*;
  import avrora.sim.types.*;
  import avrora.syntax.atmel.AtmelProgramReader;
  import avrora.syntax.elf.ELFParser;
  import avrora.syntax.objdump.*;
  import avrora.syntax.raw.RAWReader;
  import avrora.test.*;
  import avrora.test.sim.SimTestHarness;
  import cck.help.*;
  import cck.test.TestEngine;
  import cck.text.StringUtil;
  import cck.util.ClassMap;
  import cck.util.Util;
  import java.util.*;
  
  /**
   * The <code>Defaults</code> class contains the default mappings for microcontrollers, actions,
   * input formats, constants, etc.
   *
   * @author Ben L. Titzer
   */
  public class Defaults {
      private static final HashMap<String, HelpCategory> mainCategories = new HashMap<>();
  
      private static ClassMap microcontrollers;
      private static ClassMap platforms;
      private static ClassMap actions;
      private static ClassMap inputs;
      private static ClassMap harnessMap;
      private static ClassMap monitorMap;
      private static ClassMap simMap;
      private static ClassMap topologies;
  
      private static synchronized void addAll() {
          addMicrocontrollers();
          addPlatforms();
          addActions();
          addInputFormats();
          addTestHarnesses();
          addMonitors();
          addSimulations();
          addTopologies();
          ArchitectureRegistry.addArchitectures();
      }
  
      private static synchronized void addMonitors() {
          if (monitorMap == null) {
              monitorMap = new ClassMap("Monitor", MonitorFactory.class);
              //-- DEFAULT MONITORS AVAILABLE
              monitorMap.addClass("calls", CallMonitor.class);
              monitorMap.addClass("break", BreakMonitor.class);
              monitorMap.addClass("c-print", PrintMonitor.class);
              monitorMap.addClass("c-timer", TimerMonitor.class);
              monitorMap.addClass("profile", ProfileMonitor.class);
              monitorMap.addClass("memory", MemoryMonitor.class);
              monitorMap.addClass("sleep", SleepMonitor.class);
              monitorMap.addClass("leds", LEDMonitor.class);
              monitorMap.addClass("stack", StackMonitor.class);
              monitorMap.addClass("energy", EnergyMonitor.class);
              monitorMap.addClass("interrupts", InterruptMonitor.class);
              monitorMap.addClass("interactive", InteractiveMonitor.class);
              monitorMap.addClass("trace", TraceMonitor.class);
              monitorMap.addClass("energy-profile", EnergyProfiler.class);
              monitorMap.addClass("packet", PacketMonitor.class);
              monitorMap.addClass("gdb", GDBServer.class);
              monitorMap.addClass("simperf", SimPerfMonitor.class);
              monitorMap.addClass("serial", SerialMonitor.class);
              monitorMap.addClass("spi", SPIMonitor.class);
              monitorMap.addClass("call-time", CallTimeMonitor.class);
              monitorMap.addClass("call-profile", CallTreeProfiler.class);
              monitorMap.addClass("trip-time", TripTimeMonitor.class);
              monitorMap.addClass("ioregs", IORegMonitor.class);
              monitorMap.addClass("virgil", VirgilMonitor.class);
              monitorMap.addClass("real-time", RealTimeMonitor.class);
              monitorMap.addClass("sniffer", SnifferMonitor.class);
              monitorMap.addClass("retaddr", RetAddrWatch.class);
  
              HelpCategory hc = new HelpCategory("monitors", "Help for the supported simulation monitors.");
              hc.addOptionValueSection("SIMULATION MONITORS", "Avrora's simulator offers the ability to install execution " +
                      "monitors that instrument the program in order to study and analyze its behavior. The " +
                      "\"simulate\" action supports this option that allows a monitor class " +
                      "to be loaded which will instrument the program before it is run and then generate a report " +
                      "after the program has completed execution.", "-monitors", monitorMap);
              addMainCategory(hc);
              addSubCategories(monitorMap);
          }
      }
  
      private static synchronized void addTestHarnesses() {
          if (harnessMap == null) {
              harnessMap = new ClassMap("Test Harness", TestEngine.Harness.class);
              //-- DEFAULT TEST HARNESSES
              harnessMap.addClass("simulator", SimTestHarness.class);
              harnessMap.addClass("simplifier", SimplifierTestHarness.class);
              harnessMap.addClass("probes", ProbeTestHarness.class);
              harnessMap.addClass("disassembler", DisassemblerTestHarness.class);
              harnessMap.addClass("interrupt", InterruptTestHarness.class);
          }
      }
  
      private static synchronized void addInputFormats() {
          if (inputs == null) {
              inputs = new ClassMap("Input Format", ProgramReader.class);
              //-- DEFAULT INPUT FORMATS
              inputs.addClass("auto", AutoProgramReader.class);
              inputs.addClass("raw", RAWReader.class);
              inputs.addClass("atmel", AtmelProgramReader.class);
              inputs.addClass("objdump", ObjDumpProgramReader.class);
              inputs.addClass("odpp", ObjDump2ProgramReader.class);
              inputs.addClass("elf", ELFParser.class);
  
              HelpCategory hc = new HelpCategory("inputs", "Help for the supported program input formats.");
              hc.addOptionValueSection("INPUT FORMATS", "The input format of the program is specified with the \"-input\" " +
                  "option supplied at the command line. This input format is used by " +
                  "actions that operate on programs to determine how to interpret the " +
                  "input and build a program from the files specified. For example, the input format might " +
                  "be Atmel syntax, GAS syntax, or the output of a disassembler such as avr-objdump. Currently " +
                  "no binary formats are supported.", "-input", inputs);
              addMainCategory(hc);
              addSubCategories(inputs);
          }
      }
  
      private static synchronized void addActions() {
          if (actions == null) {
              actions = new ClassMap("Action", Action.class);
              //-- DEFAULT ACTIONS
              actions.addClass("disassemble", DisassembleAction.class);
              actions.addClass("simulate", SimAction.class);
              actions.addClass("analyze-stack", AnalyzeStackAction.class);
              actions.addClass("test", TestAction.class);
              actions.addClass("cfg", CFGAction.class);
              actions.addClass("isea", ISEAAction.class);
              actions.addClass("odpp", ODPPAction.class);
              actions.addClass("elf-dump", ELFDumpAction.class);
  
              // plug in a new help category for actions accesible with "-help actions"
              HelpCategory hc = new HelpCategory("actions", "Help for Avrora actions.");
              hc.addOptionValueSection("ACTIONS", "Avrora accepts the \"-action\" command line option " +
                      "that you can use to select from the available functionality that Avrora " +
                      "provides. This action might be to assemble the file, " +
                      "print a listing, perform a simulation, or run an analysis tool. This " +
                      "flexibility allows this single frontend to select from multiple useful " +
                      "tools. The currently supported actions are given below.", "-action", actions);
              addMainCategory(hc);
              addSubCategories(actions);
          }
      }
  
      private static synchronized void addSimulations() {
          if (simMap == null) {
              simMap = new ClassMap("Simulation", Simulation.class);
              //-- DEFAULT ACTIONS
              simMap.addClass("single", SingleSimulation.class);
              simMap.addClass("sensor-network", SensorSimulation.class);
              simMap.addClass("wired", WiredSimulation.class);
  
              // plug in a new help category for simulations accesible with "-help simulations"
              HelpCategory hc = new HelpCategory("simulations", "Help for supported simulation types.");
              hc.addOptionValueSection("SIMULATION TYPES",
                      "When running a simulation, Avrora accepts the \"-simulation\" command line option " +
                      "that selects the simulation type from multiple different types provided, or a " +
                      "user-supplied Java class of your own. For example, a simulation might be for a " +
                      "sensor network application, a single node simulation, or a robotics simulation. ",
                      "-simulation", simMap);
              addMainCategory(hc);
              addSubCategories(simMap);
          }
      }
  
      private static synchronized void addPlatforms() {
          if (platforms == null) {
              platforms = new ClassMap("Platform", PlatformFactory.class);
              //-- DEFAULT PLATFORMS
              platforms.addClass("mica2", Mica2.Factory.class);
              platforms.addClass("micaz", MicaZ.Factory.class);
              platforms.addClass("seres", Seres.Factory.class);
              platforms.addClass("superbot", Superbot.Factory.class);
              platforms.addClass("telos", Telos.Factory.class);
          }
      }
  
      private static synchronized void addMicrocontrollers() {
          if (microcontrollers == null) {
              microcontrollers = new ClassMap("Microcontroller", MicrocontrollerFactory.class);
              //-- DEFAULT MICROCONTROLLERS
              microcontrollers.addInstance("atmega128", new ATMega128.Factory());
              microcontrollers.addInstance("atmega32", new ATMega32.Factory());
              microcontrollers.addInstance("atmega16", new ATMega16.Factory());
          }
      }
  
      private static synchronized void addTopologies() {
          if (topologies == null) {
              topologies = new ClassMap("Topology", Topology.class);
              //-- DEFAULT TOPOLOGIES
              topologies.addClass("static", TopologyStatic.class);
              topologies.addClass("rwp", TopologyRWP.class);
              // plug in a new help category for simulations accesible with "-help topologies"
              HelpCategory hc = new HelpCategory("topologies", "Help for supported topology types.");
              hc.addOptionValueSection("TOPOLOGY TYPES",
                      "Avrora supports different types of topolgies using the \"-topology\" command " +
                      "line option. This option works only for sensor-network simulation. Note that a " +
                      "topology must be set to use a specific radio model.",
                      "-topology", topologies);
              addMainCategory(hc);
              addSubCategories(topologies);
          }
      }
  
      /**
       * The <code>getMicrocontroller()</code> method gets the microcontroller factory corresponding
       * to the given name represented as a string. This string can represent a short name for the
       * class (an alias), or a fully qualified Java class name.
       *
       * @param s the name of the microcontroller as string; a class name or an alias such as "atmega128"
       * @return an instance of the <code>MicrocontrollerFactory</code> interface that is capable
       *         of creating repeated instances of the microcontroller.
       */
      public static MicrocontrollerFactory getMicrocontroller(String s) {
          addMicrocontrollers();
          return (MicrocontrollerFactory) microcontrollers.getObjectOfClass(s);
      }
  
      /**
       * The <code>getPlatform()</code> method gets the platform factory corresponding to the
       * given name represented as a string. This string can represent a short name for the
       * class (an alias), or a fully qualified Java class name.
       *
       * @param s the name of the platform as string; a class name or an alias such as "mica2"
       * @return an instance of the <code>PlatformFactory</code> interface that is capable of
       *         creating repeated instances of the microcontroller.
       */
      public static PlatformFactory getPlatform(String s) {
          addPlatforms();
          return (PlatformFactory) platforms.getObjectOfClass(s);
      }
  
      /**
       * The <code>getProgramReader()</code> method gets the program reader corresponding to
       * the given name represented as a string. This string can represent a short name for the
       * class (an alias), or a fully qualified Java class name.
       *
       * @param s the name of the program reader format as a string
       * @return an instance of the <code>ProgramReader</code> class that is capable of reading
       *         a program into the internal program representation format.
       */
      public static ProgramReader getProgramReader(String s) {
          addInputFormats();
          return (ProgramReader) inputs.getObjectOfClass(s);
      }
  
      /**
       * The <code>getAction()</code> method gets the action corresponding to the given name
       * represented as a string. This string can represent a short name for the
       * class (an alias), or a fully qualified Java class name.
       *
       * @param s the name of the action as a string
       * @return an instance of the <code>Action</code> class which can run given the command
       *         line arguments and options provided.
       */
      public static Action getAction(String s) {
          addActions();
          return (Action) actions.getObjectOfClass(s);
      }
  
      /**
       * The <code>getMonitor()</code> method gets the monitor corresponding to the given name
       * represented as a string. This string can represent a short name for the class (an alias),
       * or a fully qualified Java class name.
       *
       * @param s the name of the monitor as a string
       * @return an instance of the <code>MonitorFactory</code> class that is capable of attaching
       *         monitors to nodes as they are created
       */
      public static MonitorFactory getMonitor(String s) {
          addMonitors();
          return (MonitorFactory) monitorMap.getObjectOfClass(s);
      }
  
      public static Simulation getSimulation(String s) {
          addSimulations();
          // TODO: add a simulation factory
          return (Simulation)simMap.getObjectOfClass(s);
      }
  
       public static Topology getTopology(String s) {
          addTopologies();
          return (Topology)topologies.getObjectOfClass(s);
      }
  
      /**
       * The <code>getTestHarnessMap()</code> method gets the test harness class map.
       *
       * @return an instance of the <code>ClassMap</code> class that is capable of creating a
       *         test case for a file and running it
       */
      public static ClassMap getTestHarnessMap() {
          addTestHarnesses();
          return harnessMap;
      }
  
      /**
       * The <code>getActionList()</code> method returns a list of aliases for actions sorted
       * alphabetically.
       *
       * @return a sorted list of known actions
       */
      public static List<String> getActionList() {
          addActions();
          return actions.getSortedList();
      }
  
      /**
       * The <code>getProgramReaderList()</code> method returns a list of aliases for program
       * readers sorted alphabetically.
       *
       * @return a sorted list of known program readers
       */
      public static List<String> getProgramReaderList() {
          addInputFormats();
          return inputs.getSortedList();
      }
  
      public static void addSubCategories(ClassMap vals) {
          List<String> l = vals.getSortedList();
          for (String val : l) { 
              Class<?> cz = vals.getClass(val);
              if (HelpCategory.class.isAssignableFrom(cz))
                  HelpSystem.addCategory(val, cz);
          }
      }
  
      public static void addMainCategory(HelpCategory cat) {
          HelpSystem.addCategory(cat.name, cat);
          mainCategories.put(cat.name, cat);
      }
  
      public static HelpCategory getHelpCategory(String name) {
          addAll();
          return HelpSystem.getCategory(name);
      }
  
      public static List<HelpCategory> getMainCategories() {
          addAll();
          List<HelpCategory> list = Collections.list(Collections.enumeration(mainCategories.values()));
          Collections.sort(list, HelpCategory.COMPARATOR);
          return list;
      }
  
      public static List<HelpCategory> getAllCategories() {
          addAll();
          List<String> l = HelpSystem.getSortedList();
          LinkedList<HelpCategory> nl = new LinkedList<>();
          for (String s : l) {
              nl.addLast(HelpSystem.getCategory(s));
          }
          return nl;
      }
  
      public static Simulator newSimulator(int id, Program p) {
          return newSimulator(id, "atmega128", 8000000, 8000000, p);
      }
  
      public static Simulator newSimulator(int id, String mcu, long hz, long exthz, Program p) {
          MicrocontrollerFactory f = getMicrocontroller(mcu);
          ClockDomain cd = new ClockDomain(hz);
          cd.newClock("external", exthz);
  
          return f.newMicrocontroller(id, new SingleSimulation(), cd, p).getSimulator();
      }
  
      public static class AutoProgramReader extends ProgramReader {
          public AutoProgramReader() {
              super("The \"auto\" input format reads a program from a single file at a time. " +
                      "It uses the extension of the filename as a clue to decide what input " +
                      "reader to use for that file. For example, an extension of \".asm\" is " +
                      "considered to be a program in Atmel assembly syntax.");
          }
  
          @Override
          public Program read(String[] args) throws Exception {
              if (args.length == 0)
                  Util.userError("no input files");
              if (args.length != 1)
                  Util.userError("input type \"auto\" accepts only one file at a time.");
  
              String n = args[0];
              int offset = n.lastIndexOf('.');
              if (offset < 0)
                  Util.userError("file " + StringUtil.quote(n) + " does not have an extension");
  
              String extension = n.substring(offset).toLowerCase();
  
              ProgramReader reader;// = null;
              switch (extension) {
                  case ".asm":
                      reader = new AtmelProgramReader();
                      break;
                  case ".od":
                      reader = new ObjDumpProgramReader();
                      break;
                  case ".odpp":
                      reader = new ObjDump2ProgramReader();
                      break;
                  case ".elf":
                      reader = new ELFParser();
                      break;
                  default:
                      reader = new ELFParser(); //for contiki .$(TARGET) elf files
                      break;
              }
  
              /*if ( reader == null ) {
                  Util.userError("file extension " + StringUtil.quote(extension) + " unknown");
                  return null;
              }*/
  
              // TODO: this is a hack; all inherited options should be available
              reader.INDIRECT_EDGES.set(INDIRECT_EDGES.stringValue());
              reader.ARCH.set(ARCH.stringValue());
              reader.options.process(options);
              return reader.read(args);
          }
  
      }
  }
  