/**
   * Emits C header code for the FSM map.
   *
   * @param map emit Groovy code for this map.
   */
  public void visit(SmcMap map) {
    String packageName = map.getFSM().getPackage();
    String context = map.getFSM().getContext();
    String mapName = map.getName();

    // If a package has been specified,
    if (packageName != null && packageName.length() > 0) {
      context = packageName + "_" + context;
    }

    for (SmcState state : map.getStates()) {
      _source.print("extern const struct ");
      _source.print(context);
      _source.print("State ");
      if (packageName != null && packageName.length() > 0) {
        _source.print(packageName);
        _source.print("_");
      }
      _source.print(mapName);
      _source.print("_");
      _source.print(state.getInstanceName());
      _source.println(";");
    }

    return;
  } // end of visit(SmcMap)
  /**
   * Emits C header code for the finite state machine.
   *
   * @param fsm emit Groovy code for this finite state machine.
   */
  public void visit(SmcFSM fsm) {
    String targetfileCaps;
    String packageName = fsm.getPackage();
    String context = fsm.getContext();
    String fsmClassName = fsm.getFsmClassName();
    String startStateName = fsm.getStartState();
    String cState;
    List<SmcTransition> transList;
    List<SmcParameter> params;
    int index;

    _source.println("/*");
    _source.println(" * ex: set ro:");
    _source.println(" * DO NOT EDIT.");
    _source.println(" * generated by smc (http://smc.sourceforge.net/)");
    _source.print(" * from file : ");
    _source.print(_srcfileBase);
    _source.println(".sm");
    _source.println(" */");
    _source.println();

    // If a package has been specified,
    if (packageName != null && packageName.length() > 0) {
      context = packageName + "_" + context;
      fsmClassName = packageName + "_" + fsmClassName;
      startStateName = packageName + "_" + startStateName;
    }

    // The first two lines in the header file should be:
    //
    //    #ifndef _<source file name>_H
    //    #define _<source file name>_H
    //
    // where the source file name is all in caps.
    // The last line is:
    //
    //    #endif
    //

    // Make the file name upper case and replace
    // slashes with underscores.
    targetfileCaps = _targetfileBase.replace('\\', '_');
    targetfileCaps = targetfileCaps.replace('/', '_');
    targetfileCaps = targetfileCaps.toUpperCase();
    _source.print("#ifndef _");
    _source.print(targetfileCaps);
    _source.println("_H");
    _source.print("#define _");
    _source.print(targetfileCaps);
    _source.println("_H");

    // Include required standard .h files.
    _source.println();
    _source.println("#include <assert.h>");

    if (_debugLevel >= DEBUG_LEVEL_0) {
      _source.println("#define STATEMAP_DEBUG 1");
    }
    _source.println("#include <statemap.h>");

    _source.println();

    // Do user-specified forward declarations now.
    for (String declaration : fsm.getDeclarations()) {
      _source.print(declaration);
      _source.println();
    }

    // Forward declare the application class.
    _source.println();
    _source.print("struct ");
    _source.print(context);
    _source.println(";");
    _source.print("struct ");
    _source.print(fsmClassName);
    _source.println(";");

    // Declare user's base state class.
    _source.println();
    _source.print("struct ");
    _source.print(context);
    _source.println("State {");

    // Add the default Entry() and Exit() definitions.
    if (fsm.hasEntryActions() == true) {
      _source.print("    void(*Entry)(struct ");
      _source.print(fsmClassName);
      _source.println(" *const fsm);");
    }
    if (fsm.hasExitActions() == true) {
      _source.print("    void(*Exit)(struct ");
      _source.print(fsmClassName);
      _source.println(" *const fsm);");
    }

    // Print out the default definitions for all the
    // transitions. First, get the transitions list.
    transList = fsm.getTransitions();

    // Output the global transition declarations.
    for (SmcTransition trans : transList) {
      // Don't output the default state here.
      if (trans.getName().equals("Default") == false) {
        _source.print("    void(*");
        _source.print(trans.getName());
        _source.print(")(struct ");
        _source.print(fsmClassName);
        _source.print(" *const fsm");

        params = trans.getParameters();
        for (SmcParameter param : params) {
          _source.print(", ");
          _source.print(param.getType());
          _source.print(" ");
          _source.print(param.getName());
        }

        _source.println(");");
      }
    }
    _source.print("    void(*Default)(struct ");
    _source.print(fsmClassName);
    _source.println(" *const fsm);");

    _source.println("    STATE_MEMBERS");

    // The base class has been defined.
    _source.println("};");
    _source.println();

    // Generate the map classes. The maps will, in turn,
    // generate the state classes.
    for (SmcMap map : fsm.getMaps()) {
      map.accept(this);
    }

    // Generate the FSM context class.
    _source.println();
    _source.print("struct ");
    _source.print(fsmClassName);
    _source.println(" {");
    _source.print("    struct ");
    _source.print(context);
    _source.println(" *_owner;");
    _source.print("    FSM_MEMBERS(");
    _source.print(context);
    _source.println(")");

    // Put the closing brace on the context class.
    _source.println("};");
    _source.println();

    // The state name "map::state" must be changed to
    // "map_state".
    if ((index = startStateName.indexOf("::")) >= 0) {
      cState = startStateName.substring(0, index) + "_" + startStateName.substring(index + 2);
    } else {
      cState = startStateName;
    }

    _source.print("#ifdef NO_");
    _source.print(targetfileCaps);
    _source.println("_MACRO");

    // Constructor
    _source.print("extern void ");
    _source.print(fsmClassName);
    _source.print("_Init");
    _source.print("(struct ");
    _source.print(fsmClassName);
    _source.print(" *const fsm, struct ");
    _source.print(context);
    _source.println(" *const owner);");

    // EnterStartState method.
    if (fsm.hasEntryActions() == true) {
      _source.print("extern void ");
      _source.print(fsmClassName);
      _source.print("_EnterStartState(struct ");
      _source.print(fsmClassName);
      _source.println(" *const fsm);");
    }

    // Generate a method for every transition in every map
    // *except* the default transition.
    for (SmcTransition trans : transList) {
      if (trans.getName().equals("Default") == false) {
        _source.print("extern void ");
        _source.print(fsmClassName);
        _source.print("_");
        _source.print(trans.getName());
        _source.print("(struct ");
        _source.print(fsmClassName);
        _source.print(" *const fsm");

        params = trans.getParameters();
        for (SmcParameter param : params) {
          _source.print(", ");
          _source.print(param.getType());
          _source.print(" ");
          _source.print(param.getName());
        }
        _source.println(");");
      }
    }

    _source.println("#else");

    // Constructor
    _source.print("#define ");
    _source.print(fsmClassName);
    _source.println("_Init(fsm, owner) \\");
    _source.print("    FSM_INIT((fsm), &");
    _source.print(cState);
    _source.println("); \\");
    _source.println("    (fsm)->_owner = (owner)");

    // EnterStartState method.
    if (fsm.hasEntryActions() == true) {
      _source.println();
      _source.print("#define ");
      _source.print(fsmClassName);
      _source.println("_EnterStartState(fsm) \\");
      _source.println("    ENTRY_STATE(getState(fsm))");
    }

    // Generate a method for every transition in every map
    // *except* the default transition.
    for (SmcTransition trans : transList) {
      if (trans.getName().equals("Default") == false) {
        _source.println();
        _source.print("#define ");
        _source.print(fsmClassName);
        _source.print("_");
        _source.print(trans.getName());
        _source.print("(fsm");

        params = trans.getParameters();
        for (SmcParameter param : params) {
          _source.print(", ");
          _source.print(param.getName());
        }
        _source.println(") \\");

        _source.println("    assert(getState(fsm) != NULL); \\");
        _source.print("    setTransition((fsm), \"");
        _source.print(trans.getName());
        _source.println("\"); \\");
        _source.print("    getState(fsm)->");
        _source.print(trans.getName());
        _source.print("((fsm)");
        for (SmcParameter param : params) {
          _source.print(", (");
          _source.print(param.getName());
          _source.print(")");
        }
        _source.println("); \\");
        _source.println("    setTransition((fsm), NULL)");
      }
    }

    _source.println("#endif");
    _source.println();
    _source.println("#endif");

    _source.println();
    _source.println("/*");
    _source.println(" * Local variables:");
    _source.println(" *  buffer-read-only: t");
    _source.println(" * End:");
    _source.println(" */");

    return;
  } // end of visit(SmcFSM)