/* class comment
*/!!

inherit(Window, #CliServer, #(newServerDictionary
  /* serverName, dll library */
newCommandDictionary
  /* command name, entry point */
newHelpDictionary
  /* command name, help text */
initDone  /* true if initialization done */
abortingServer /* true if aborting cli server */
pendingAbort /* true if cmd abort pending */
cliPresenters /* active presenters list */
currentCliPresenter /* for current command */
cliExecutionEngine /* executes commands */
cliBusy /* if busy, can't be closed */
serverCallFlag /* true if inside server call */
eventsOutstandingFlag
   /* true if events still propagating from call */
eventDescSet /* registered events */
checkMessageSemaphore
   /* true if calling checkMessage() */), 2, nil)!!

setClassVars(CliServer, #(cliServer  /* cli server's object */
cliDlls  /* dictionary of handle to cli library instances */
))!!

now(class(CliServer))!!

Def cliDlls(self)
{ ^cliDlls;
}!!

/* returns the CLI Server's handle */
Def getCliServerHandle(self)
{
  ^getHWnd(cliServer);
}!!

/* returns the CLI Server's object */
Def getCliServerObject(self)
{
  ^cliServer;
}!!

/* create new object only if one hasn't been started yet */
Def new(self, a1, a2, a3, a4)
{
  if (getCliServerObject(CliServer))
    displayFormattedError(ErrorTextLibClass$Inst,
       ER_CLI_ALREADY_RUNNING, FORCE_POPUP, nil, nil, nil);
    ^nil;
  endif;
  ^new(self:ancestor, a1, a2, a3, a4);
}!!

/* THIS IS TO SUPPORT CLIExecEngine TESTING ONLY; SEE TCLIExecEngine. */
Def setCliServerObject(self, new)
{
  cliServer := new;
}!!

now(CliServer)!!

/* 2/19/1998 15:19 */
Def checkSymbolHalt(self, symbol)
{ 

  if (symbol = #BXCLISETBKPT) cand (raStatus = BOOL_TRUE) cand (bkptrunning = 1) then
    emStatus := prim_getEmulationStatus(requireWithPath(HLBrkRootLib,"bkroot.dll"));
    if (emStatus = HLB_EMU_HALTED) then
      bkptrunning := 0;
      showWaitCurs();
      go(HLBreakLibClass$Inst);  
      showOldCurs();             
    endif;
  endif;

}
!!

/* 2/19/1998 15:17 */
Def checkSymbolGo(self, symbol)
{ 
  if (symbol = #BXCLISETBKPT) then
    bkptrunning := 0;
    raStatus := getRunAccess(HLBrkRootLibClass$Inst);
    if (raStatus = BOOL_TRUE) then
      emStatus := prim_getEmulationStatus(requireWithPath(HLBrkRootLib,"bkroot.dll"));
      if (emStatus = HLB_EMU_RUNNING) then
        bkptrunning := 1; 
        showWaitCurs();
        halt(HLBreakLibClass$Inst);
        showOldCurs();             
      endif;
    endif;
  endif; 
}
!!

/* return true if inside check message, nil otherwise. */
Def checkMessageLock?(self)
{
  ^checkMessageSemaphore;
}
!!

/* abort processing on this command */
Def abortCommand(self)
{
  reInit(self);  /* have to do this here; abort doesn't return */
  abort();
}
!!

/* Add a command; system error if duplicate. */
Def addCommand(self, command, entryPoint | key)
{
  key := asLowerCase(command);
  if at(newCommandDictionary, key)
    displayFormattedError(ErrorTextLibClass$Inst,
       ER_CLI_DUPLICATE_KEY, FORCE_POPUP, asciiz(key), nil, nil);
    ^nil;
  endif;

  add(newCommandDictionary, key, entryPoint);
  ^0;
}
!!

/* Add a collection to help; system error if duplicate. */
Def addHelpCol(self, key, helpCol)
{
  key := asLowerCase(key);
  if at(newHelpDictionary, key)
    displayFormattedError(ErrorTextLibClass$Inst,
       ER_CLI_DUPLICATE_KEY, FORCE_POPUP, asciiz(key), nil, nil);
    ^nil;
  endif;

  ^add(newHelpDictionary, key, helpCol);
}
!!

/* shortcut for creating collection from string on the fly;
   let addHelpCol catch the errors. */
Def addHelpText(self, key, helpText | col)
{
  col := new(TextCollection, 1);
  add(col, helpText);
  ^addHelpCol(self, key, col);
}
!!

/* Add a server; system error if duplicate. */
Def addServer(self, server, library | key)
{
  key := asLowerCase(server);
  if at(newServerDictionary, key)
    displayFormattedError(ErrorTextLibClass$Inst,
       ER_CLI_DUPLICATE_SERVER, FORCE_POPUP, asciiz(key), nil, nil);
    ^nil;
  endif;

  add(newServerDictionary, key, library);
  ^0;
}
!!

/* call function in server dll */
Def callCServer(self, serverName, commandName, argString, argc, argv |
  dllLib index status symbol serverEntry commandEntry cArgv errorMessage)
{
  /* retrieve server entry from registration info, then get dll library */
  dllLib := at(newServerDictionary, asLowerCase(serverName));
  if (not(dllLib))
    errorMessage := getFormattedError(ErrorTextLibClass$Inst,
       ER_CLI_UNREGISTERED_SERVER, serverName, nil, nil);
    syntaxError(self, nil, errorMessage);
    /* syntaxError unravels call stack, and does not return */
  endif;

  /* retrieve command entry from registration info,
     then convert into entry point symbol */
  commandEntry := at(newCommandDictionary, asLowerCase(commandName));
  if (not(commandEntry))
    errorMessage := getFormattedError(ErrorTextLibClass$Inst,
       ER_CLI_UNREGISTERED_COMMAND, commandName, nil, nil);
    syntaxError(self, nil, errorMessage);
    /* syntaxError unravels call stack, and does not return */
  endif;
  symbol := asSymbol(asUpperCase(commandEntry));

  /* convert argv; string and argc can be passed directly */
  cArgv := new(Struct, 4*size(argv));
  index := 0;
  loop
  while index < size(argv)
  begin
    putLong(cArgv, argv[index], index*4);
    index := index + 1;
  endLoop;

  checkSymbolGo(self,symbol);

  /* call dll */
  if pcallLock(MallocLibClass$Inst)
    serverCallFlagSet(self);
    status := pcall(procs(dllLib)[symbol], argString, argc, lP(cArgv));
    serverCallFlagReset(self);
    pcallUNLock(MallocLibClass$Inst);
  else
    status := ERR_PCALL_RECURSION;
  endif;

  checkSymbolHalt(self,symbol);

  freeHandle(cArgv);
  if status <> 0
    /* abort completely if lower level command aborted */
    if (status = ER_ABORT_FROM_ESC) cor
       (status = ER_ABORT_SESSION) cor
       (status = ER_CLI_USER_ABORT) cor
       (status = ER_CMD_ABORT) cor
       (status = ER_COPY_ABORT) cor
       (status = ER_DQ_ABORTED) cor
       (status = ER_FILL_ABORT) cor
       (status = ER_HEX_ABORT) cor
       (status = ER_LDR_ABORT) cor
       (status = ER_LOAD_ABORT) cor
       (status = ER_SEARCH_ABORT) cor
       (status = ER_SWAT_ABORT) cor
       (status = ER_TRIGGER_ABORTED) cor
       (status = ER_USER_ABORT)

      syntaxError(self, nil, getErrorText(ErrorTextLibClass$Inst, status));
      /* this call doesn't return */
    else
      /* load memory verify info if applicable */
      if (status = ER_MEMORY_VERIFY)
        processVerifyError(MemServLibClass$Inst);
      endif;
      outputCRLFLine(self, getErrorText(ErrorTextLibClass$Inst, status));
    endif;
  endif;

  /* wait for events to complete */
  waitForEvents(self);

  /* if server didn't acknowledge abort, abort anyway without message */
  if pendingAbort?(self)
    abortCommand(self);
      /* this call doesn't return */
  endif;

  ^status;
}!!

/* Get checkMessage semaphore; return true if got it, nil otherwise. */
Def checkMessageLock(self)
{
  if checkMessageSemaphore
    ^nil;
  endif;
  checkMessageSemaphore := 0;
  ^0;
}
!!

/* Clear checkMessage semaphore. */
Def checkMessageUnlock(self)
{
  checkMessageSemaphore := nil;
  ^0;
}
!!

/* set CLI busy flag */
Def cliBusy(self)
{
  cliBusy := 0;
  ^0;
}
!!

/* test CLI busy flag */
Def cliBusy?(self)
{
  ^cliBusy;
}
!!

/* clear CLI busy flag */
Def cliNotBusy(self)
{
  cliBusy := nil;
  ^0;
}
!!

/* close server */
Def close(self | index)
{
  cliServer := nil;
  cliDlls := nil;
  /* close all of the cliPresenters */
  abortingServer := 0;
  if cliPresenters
    /* cycle through entries 0..n to find match */
    index := 0;
    loop
    while (index < size(cliPresenters))
    begin
      if cliPresenters[index]
        close(cliPresenters[index]);
      endif;
      index := index + 1;
    endLoop;
  endif;
  close(cliExecutionEngine);
  cliServer := nil;
  close(self:ancestor);
}!!

Def deleteAlias(self, key)
{
  ^deleteAlias(cliExecutionEngine, key);
}
!!

/* Events are not outstanding. */
Def eventsOutstandingClear(self)
{
  eventsOutstandingFlag := nil;
  ^0;
}
!!

/* get flag. */
Def eventsOutstandingGet(self)
{
  ^eventsOutstandingFlag;
}
!!

/* Events are outstanding. */
Def eventsOutstandingSet(self)
{
  eventsOutstandingFlag := 0;
  ^0;
}
!!

/* Find the presenter handle in an ordered collection;
   return index if found, or nil. */
Def findPresenterHandle(self, entry | index)
{
  if not(cliPresenters)
    ^nil;
  endif;

  /* cycle through entries 0..n to find match */
  index := 0;
  loop
  while (index < size(cliPresenters))
  begin
    if entry = cliPresenters[index]
      /* entry found */
      ^index;
    endif;
    index := index + 1;
  endLoop;
  ^nil;
}!!

Def getAlias(self, key, system)
{
  ^getAlias(cliExecutionEngine, key, system);
}
!!

/* output each line of the help collection;
   return nil if interrupted. */
Def helpCommandDisplay(self, helpCollection | index status)
{
  index := 0;
  loop
  while (index < size(helpCollection))
  begin
    if (TaskLibClass$Inst cand queryAbort(TaskLibClass$Inst) )
      outputExplicit(currentCliPresenter,
        getFormattedError(ErrorTextLibClass$Inst,
           ER_CLI_USER_ABORT, nil, nil, nil));
      ^nil;
    endif;

    outputExplicit(currentCliPresenter, helpCollection[index]);

    index := index + 1;
  endLoop;

  ^0;
}!!

/* display the help line for all commands. */
Def helpOnAll(self, internal | cmd status)
{
  /* for each server, display the help text */
  assocsDo(newHelpDictionary,
    {using(assoc)
      cmd := key(assoc);
      if (internal cor (cmd cand (cmd[0] <> '_')))
        status := helpCommandDisplay(self, value(assoc));
        if not(status)
          ^nil;
        endif;
      endif;
    });
  ^0;
}!!

/* output help for a single command */
Def helpOnOne(self, commandName, internal | helpEntry lc done temp)
{
  lc := asLowerCase(commandName);

  /* stay in loop until help entry found, or can't expand aliases */
  done := nil;
  loop
  while not(done)
  begin
    if (helpEntry := at(newHelpDictionary, lc))
      done := 0;
    else
      temp := getSystemAlias(CLIExecEngine, lc);
      if not(temp)
        outputExplicit(currentCliPresenter, "No entry for "+commandName);
        ^0;
      else
        lc := asLowerCase(temp);
      endif;
    endif;
  endLoop;

  /* reject if not found, or empty key, or hidden command */
  if not(helpEntry) cor not(lc) cor (not(internal) cand (commandName[0] = '_'))
    outputExplicit(currentCliPresenter, "No entry for "+commandName);
    ^0;
  endif;

  ^helpCommandDisplay(self, helpEntry);
  ^0;
}!!

/* initialization */
Def init(self)
{ /* init(self:ancestor); */
  initDone cor initOnce(self);
}!!

/* initialize CLI help text */
Def initCLIHelp(self | dq col)
{
  dq := doubleQuoteString(CLIUtilities);
  addHelpText(self, "alias",
     "alias [" + dq + "<name>" + dq + " [" + dq + "<value>" + dq + "]]");
  addHelpText(self, "append", "append");
  addHelpText(self, "clear", "clear");

  col := new(TextCollection, 2);
  add(col, "delete <variable>");
  add(col, "delete alias " + dq + "<name>" + dq);
  addHelpCol(self, "delete", col);

  addHelpText(self, "echo", "echo [on|off]");
  addHelpText(self, "exit", "exit");
  addHelpText(self, "help", "help [" + dq + "<topic>" + dq + "]");
  addHelpText(self, "history", "history [<size>]");
  addHelpText(self, "if",
    "if (<condition>) { <statement list> } [else { <statement list> }]");
  addHelpText(self, "include", "include " + dq + "<filename>" + dq);
  addHelpText(self, "integer", "integer (<variable>)");
  addHelpText(self, "laptimer", "laptimer");
  addHelpText(self, "list", "list [<variable>]");
  addHelpText(self, "log", "log [" + dq + "<filename>" + dq + "]");
  addHelpText(self, "logging", "logging [on|off]");
  addHelpText(self, "overwrite", "overwrite");
  addHelpText(self, "print", "print (<variable>|" + dq + "<string>" + dq + ")");
  addHelpText(self, "results", "results [on|off]");
  addHelpText(self, "starttimer", "starttimer");
  addHelpText(self, "stoptimer", "stoptimer");
  addHelpText(self, "string", "string (<variable>)");
  addHelpText(self, "time", "time");
  addHelpText(self, "while", "while (<condition>) { <statement list> }");
}
!!

/* Initialize one or more servers in a DLL.  This method is used
   to load dlls which have no corresponding Actor class (contrast
   initDLLLib).  */
Def initDLL(self, pathname | lib, index, temp, t1, t2, t3)
{ /* pull it out of the DLL, and execute it */
  showWaitCurs();
  lib := new(Classes[#CliLibrary]);
  setName(lib, pathname);
  /* add the hardcoded initialization entry point */
  add(lib, #INITCSERVER, 1, #(0 0));
  load(lib);
  add(cliDlls, handle(lib), lib);
  t1 := procs(lib)[#INITCSERVER];
  t2 := getHWnd(self);
  t3 := handle(lib);
  if pcallLock(MallocLibClass$Inst)
    temp := pcall(t1, t2, t3);
    pcallUNLock(MallocLibClass$Inst);
  else
    temp := ERR_PCALL_RECURSION;
  endif;
  displayError(ErrorTextLibClass$Inst,temp,FORCE_CLI);
  showOldCurs();
  ^temp;
}!!

/*
** Initialize one or more servers in a DLL.  This method is invoked
** to load dlls which have actor interfaces (i.e. have a library class).
*/
Def initDLLLib(self, libClass, serverPrefix, pathName |
    lib, index, temp, t1, t2, t3)
{
  /* @@ ignore old registrations */
  /*
  if (asLowerCase(serverPrefix) <> "cliulib") cand
     (asLowerCase(serverPrefix) <> "cpu") cand
     (asLowerCase(serverPrefix) <> "enlib") cand
     (asLowerCase(serverPrefix) <> "dasm") cand
     (asLowerCase(serverPrefix) <> "map") cand
     (asLowerCase(serverPrefix) <> "stk") cand
     (asLowerCase(serverPrefix) <> "addr") cand
     (asLowerCase(serverPrefix) <> "mem") cand
     (asLowerCase(serverPrefix) <> "symbol")
    ^0;
  endif;
  */

  /* pull it out of the DLL, and execute it */
  showWaitCurs();
  lib := requireWithPath(libClass, pathName);

  add(cliDlls, handle(lib), lib);
  t1 := procs(lib)[#INITCSERVER];
  t2 := getHWnd(self);
  t3 := handle(lib);
  if pcallLock(MallocLibClass$Inst)
    pcall(t1, t2, t3);
    pcallUNLock(MallocLibClass$Inst);
  else
    temp := ERR_PCALL_RECURSION;
  endif;
  /*
  displayError(ErrorTextLibClass$Inst, temp, FORCE_CLI);
  */
  showOldCurs();

  ^temp;
}!!

/* PRIVATE */
Def initEvents(self | eventDesc, events)
{
  /* REGISTER with Event Notification for Whatever... */

  eventDescSet := new(Set, 1);

  /* dynamic to pick up current values */
  events := tuple(EVENT_CLI_COMMAND_COMPLETE);
  do(events,
   { using(event)
     eventDesc := register(EvNoteLibClass$Inst, event, hWnd(self));
       if (eventDesc <> 0)
         add(eventDescSet, eventDesc);
       endif;
  });

}
!!

/* one-time only initialization */
Def initOnce(self)
{
  cliServer := self;
  cliPresenters := new(OrderedCollection, 5);

  newServerDictionary := new(OrderedDictionary, SERVER_TABLE_SIZE);
  setOrderClass(newServerDictionary, SortedCollection);

  newCommandDictionary := new(OrderedDictionary, SERVER_TABLE_SIZE);
  setOrderClass(newCommandDictionary, SortedCollection);

  newHelpDictionary := new(OrderedDictionary, SERVER_TABLE_SIZE);
  setOrderClass(newHelpDictionary, SortedCollection);

  /* declare structure types for registration, results, sys variable */
  def(UserType, #CServerRegistration, #(
    short target 1
    short messageType 1
    short stringResourceHandle 1
    short serverNameIndex 1
    short dllNameIndex 1
    short commandCount 1
    short commandInfoStartIndex 1));
  def(UserType, #CServerResults, #(
    short target 1
    short messageType 1
    short messageLength 1
    short messageText 1));
  def(UserType, #CSystemVariable, #(
    short integerValueFlag 1
    long  integerValue 1
    long  variableName 1
    long  stringValue 1));
  def(UserType, #CNewServerRegistration, #(
    short stringResourceHandle 1
    short serverNameIndex 1
    short dllNameIndex 1
    short numberOfCommandsIndex 1
    short commandStartIndex 1));

  if not(UserMessages)
    UserMessages := new(Dictionary, 10);
  endif;
  add(UserMessages, CLI_SERVER_REGISTRATION, #WM_REGISTER_SERVER);
  add(UserMessages, CLI_SERVER_RESULTS, #WM_WRITE_TRANSCRIPT);
  add(UserMessages, CLI_SYSTEM_VARIABLE, #WM_SYSTEM_VARIABLE);
  add(UserMessages, CLI_NEW_SVR_REGISTRATION, #WM_NEW_REGISTER_SERVER);
  add(UserMessages, EVENT_MSG, #WM_EVENT);

  cliDlls := nil;
  cliDlls := new(Dictionary, 20);

  /* open execution engine, and register with it */
  cliExecutionEngine := open(CLIExecEngine);
  registerServerHandle(cliExecutionEngine, self);
  registerServerHandle(CLParser, self);

  /* initialize CLI help */
  initCLIHelp(self);

  /* initialize event trapping */
  initEvents(self);

  initDone := 0;
}!!

/* Process the results received from the server after executing the command.
   resultsText is a null-terminated string, embedded CR_LF's to terminate
   lines. */
Def outputCRLFLine(self, resultsText | resultsCollection)
{
  if not(currentCliPresenter)
    ^nil;
  endif;

  add(resultsCollection := new(TextCollection, 5), "");
  insertText(resultsCollection, removeNulls(resultsText), 0, 0);
  do(size(resultsCollection),
    {using(index)
      outputResults(currentCliPresenter, resultsCollection[index]);
    });
}!!

/* Process a single results line.  Input is a string. */
Def outputLine(self, text)
{
  if not(currentCliPresenter)
    ^nil;
  endif;

  ^outputLine(currentCliPresenter, text);
}!!

/* for debugging: used to show generated Actor source. */
Def outputTextCollection(self, lines | index maxsize)
{
  if not(currentCliPresenter)
    ^nil;
  endif;

  outputLine(currentCliPresenter, "Actor source code begin:");
  index := 0;
  maxsize := size(lines);
  loop
  while index < maxsize
  begin
    outputLine(currentCliPresenter, "    "+lines[index]);
    index := index + 1;
  endLoop;
  outputLine(currentCliPresenter, "Actor source code end");
  ^0;
}!!

/* 10/20/1992 15:32 */
Def pendingAbort?(self)
{
  ^pendingAbort;
}
!!

/* 10/20/1992 15:32 */
Def pendingAbortClear(self)
{
  pendingAbort := nil;
  ^0;
}
!!

/* 10/20/1992 15:32 */
Def pendingAbortSet(self)
{
  pendingAbort := 0;
  ^0;
}
!!

/* return the cli presenter */
Def presenter(self)
{
  ^currentCliPresenter;
}
!!

/* Process a CLI command passed in from the presenter. */
Def processCliCommand(self, presenter, commandText)
{
  /* don't allow close while executing */
  cliBusy(self);

  /* make sure there is at least 10k available memory; otherwise, collect */
  if (staticRoom() < 10240)
    outputLine(self, "// temporary memory low...");
    outputLine(self, "// performing garbage collection");
    showWaitCurs();
    cleanup();
    showOldCurs();
  endif;

  if(TaskLibClass$Inst)
      queryAbort(TaskLibClass$Inst);
  endif;
  currentCliPresenter := presenter;
  showWaitCurs();

  /* send the command as a text collection to the lexer. */
  initStream(lex(CLParser), 1, commandText);
  /* since a load command can cause additional input, continue to parse
     and execute until the lexer is empty at the end of a pass */
  loop
  while tokensAvailable(lex(CLParser))
  begin
    expressionEchoReset(cliExecutionEngine);
    resetNestLevel(CLParser);
    parse(CLParser);
    /* each statement is individually compiled and executed as part of the
       parsing; refer to CLIStatement */
    if(TaskLibClass$Inst)
        queryAbort(TaskLibClass$Inst);
    endif;
  endLoop;

  showOldCurs();

  cliNotBusy(self);
}!!

/* Register a CLI Presenter.  Save the Presenter's handle in a collection. */
Def registerCliPresenter(self, presenter | newWindow, index)
{
  /* find available entry in middle, or add one to end */
  index := findPresenterHandle(self, nil);
  if not(index)
    add(cliPresenters, nil);
    index := size(cliPresenters) - 1;
  endif;

  /* insert entry */
  cliPresenters[index] := presenter;
  currentCliPresenter := presenter;

  ^0;
}!!

/* Pick out each command's information, and register it. */
Def registerEachCommand(self, serverName, dllHandle, dllLib, cmdCount,
    startIndex | index rIndex cmdName entryPoint helpText done temp)
{
  rIndex := startIndex;
  index := 0;
  loop
  while (index < cmdCount)
  begin
    /* get command name */
    cmdName := getStringResource(CLIUtilities, dllHandle, rIndex);
    if not(cmdName) cor (size(cmdName) = 0)
      displayFormattedError(ErrorTextLibClass$Inst,
         ER_CLI_COMMAND_NAME, FORCE_POPUP, nil, nil, nil);
    endif;

    rIndex := rIndex + 1;
    /* get entry point name */
    entryPoint := getStringResource(CLIUtilities, dllHandle, rIndex);
    if not(entryPoint) cor (size(entryPoint) = 0)
      displayFormattedError(ErrorTextLibClass$Inst,
         ER_CLI_ENTRY_POINT, FORCE_POPUP, nil, nil, nil);
    endif;

    rIndex := rIndex + 1;
    /* get help text */
    helpText := new(TextCollection, 2);
    done := nil;
    loop
    while not(done)
    begin
      temp := getStringResource(CLIUtilities, dllHandle, rIndex);
      if not(temp) cor (size(temp) < 2) cor (temp[0] <> 'h') cor (temp[1] <> ':')
        done := 0;
      else
        add(helpText, subString(temp, 2, size(temp)));
        rIndex := rIndex + 1;
      endif
    endLoop;
    if size(helpText) = 0
      displayFormattedError(ErrorTextLibClass$Inst,
         ER_CLI_NO_HELP, FORCE_POPUP, nil, nil, nil);
    endif;

    /* get aliases */
    done := nil;
    loop
    while not(done)
    begin
      temp := getStringResource(CLIUtilities, dllHandle, rIndex);
      if not(temp) cor (size(temp) < 2) cor (temp[0] <> 'a') cor (temp[1] <> ':')
        done := 0;
      else
        addSystemAlias(CLIExecEngine, subString(temp, 2, size(temp)), cmdName);
        rIndex := rIndex + 1;
      endif
    endLoop;

    /* insert command entry, command alias */
    if at(newCommandDictionary, asLowerCase(cmdName))
      temp := getFormattedError(ErrorTextLibClass$Inst,
         ER_CLI_SERVER_REG, nil, nil, nil);
      syntaxError(self, nil, temp + " (R0)");
      ^nil;
    endif;

    addCommand(self, cmdName, entryPoint);
    add(dllLib, asSymbol(asUpperCase(entryPoint)), 1, #(1 1 1));
      /* follow this with "reload" in caller when all commands added */
    addHelpCol(self, cmdName, helpText);
    addSystemAlias(CLIExecEngine, cmdName,
      "call " + serverName + "_" + cmdName);

    index := index + 1;

  endLoop;

  ^0;
}
!!

/* perform reinitialization after command processing resulted in an error. */
Def reInit(self)
{
  reInit(CLParser);
  reInit(CLParser.lex);
  reInit(cliExecutionEngine);
  reInit(currentCliPresenter);
  checkMessageUnlock(self);
}
!!

/* clear server call flag
   nil: server hasn't been called
   0:   server has been called
   1:   returned from server call. */
Def serverCallFlagClear(self)
{
  serverCallFlag := nil;
}!!

/* check server call flag
   nil: server hasn't been called
   0:   server has been called
   1:   returned from server call. */
Def serverCallFlagClear?(self)
{
  ^not(serverCallFlag);
}!!

/* set server call flag to the 3rd state
   nil: server hasn't been called
   0:   server has been called
   1:   returned from server call. */
Def serverCallFlagReset(self)
{
  serverCallFlag := 1;
}!!

/* check server call flag to the 3rd state
   nil: server hasn't been called
   0:   server has been called
   1:   returned from server call. */
Def serverCallFlagReset?(self)
{
  ^(serverCallFlag = 1);
}!!

/* set server call flag
   nil: server hasn't been called
   0:   server has been called
   1:   returned from server call. */
Def serverCallFlagSet(self)
{
  serverCallFlag := 0;
}!!

/* set server call flag
   nil: server hasn't been called
   0:   server has been called
   1:   returned from server call. */
Def serverCallFlagSet?(self)
{
  ^(serverCallFlag = 0);
}!!

Def setAlias(self, key, value)
{
  ^setAlias(cliExecutionEngine, key, value);
}!!

/* DEBUG: used for TCliTokenizer testing only. */
Def setCurrentCliPresenter(self, presenter)
{
  currentCliPresenter := presenter;
}!!

/* 8/27/1992 9:40 */
Def shouldClose(self)
{
  /* check with ancestor */
  if not(shouldClose(self:ancestor))
    ^nil;
  endif;
  
  /* don't close if executing a shell command */
  if not(cliBusy?(self))
    ^0;
  else
    displayFormattedError(ErrorTextLibClass$Inst,
         ER_CLI_DOING_COMMAND, FORCE_POPUP, nil, nil, nil);
    ^nil;
  endif;
}!!

/* process syntax error */
Def syntaxError(self, bp, str)
{
  outputExplicit(currentCliPresenter, str);
  abortCommand(self); /* does not return */
}
!!

/* Look up handle in cliPresenters, set to nil. */
Def unregisterCliPresenter(self, handle | entryIndex)
{
  /* mark CLI inactive */
  clearCliActive(CLIULibraryClass$Inst);

  entryIndex := findPresenterHandle(self, handle);
  if entryIndex
    cliPresenters[entryIndex] := nil;
  endif;

  /* currently only one supported; set to nil */
  currentCliPresenter := nil;

  ^0;
}!!

/* Stay here until all presenter updates have occurred. */
Def waitForEvents(self)
{
  /* if can't get lock, return */
  if not(checkMessageLock(self))
    ^nil;
  endif;

  eventsOutstandingSet(self);  /* set flag */
  notify(EvNoteLibClass$Inst, EVENT_CLI_COMMAND_COMPLETE);
    /* send outself a message; when we receive this message, we know that
       all event messages have been processed. */

  loop
  while (eventsOutstandingGet(self))
  begin
    checkMessage();
    if pendingAbort?(self)
      ^0;
    endif;
  endLoop;

  /* release lock */
  checkMessageUnlock(self);

  ^0;
}
!!

/* Handle events. */
Def WM_EVENT(self, target, event)
{
  select
    case (event = EVENT_CLI_COMMAND_COMPLETE) is
      eventsOutstandingClear(self);
      ^0;
    endCase
  endSelect;
  ^0;
}!!

/* Respond to the register server message.
     wP: double check message type
     lP: pointer to registration structure (allocated by tmalloc). */
Def WM_NEW_REGISTER_SERVER(self, wP, lP | struct rStruct serverName
    size dllHandle lib cmdCount temp)
{
  if (wP <> CLI_NEW_SVR_REGISTRATION)  /* ignore message if bad call */
    ^0;
  endif;
  struct :=
    copyFromLong(new(Struct, size(#CNewServerRegistration)), lP);

  rStruct := cStructFromStruct(TbirdStruct, #CNewServerRegistration, struct);

  /* get resource handle */
  if (not (dllHandle := new(Handle))) /* abort if can't allocate handle */
    ^0;
  endif;

  /* abort if can't set handle */
  dllHandle := rStruct[#stringResourceHandle];
  lib := at(cliDlls, dllHandle);

  /* grab server name prefix */
  serverName :=
    getStringResource(CLIUtilities, dllHandle, rStruct[#serverNameIndex]);
  if not(serverName) cor (size(serverName) = 0)
    displayFormattedError(ErrorTextLibClass$Inst,
         ER_CLI_NO_SERVER_NAME, FORCE_POPUP, nil, nil, nil);
  endif;

  /* grab number of commands */
  temp :=
    getStringResource(CLIUtilities, dllHandle, rStruct[#numberOfCommandsIndex]);
  if not(temp) cor (size(temp) = 0) cor not(cmdCount := asInt(temp, 10))
    cmdCount := 0;
  endif;

  /* register individual commands; abort if nil */
  if not(registerEachCommand(self, serverName, dllHandle, lib, cmdCount,
      rStruct[#commandStartIndex]))
    ^nil;
  endif;

  /* reload dll */
  reLoad(lib);

  /* register server information */
  addServer(self, serverName, lib);

  ^0;
}!!

/* Respond to a system variable message. */
Def WM_SYSTEM_VARIABLE(self, wP, lP |
      rStruct struct varName intValFlag intVal stringVal)
{
  struct :=
    copyFromLong(new(Struct, size(#CSystemVariable)), lP);

  rStruct := cStructFromStruct(TbirdStruct, #CSystemVariable, struct);

  /* get struct fields */
  intValFlag :=  rStruct[#integerValueFlag];
  varName := getTextFromAddress(rStruct[#variableName]);

  /* see if it is an integer value */
  if intValFlag <> 0
    intVal := rStruct[#integerValue];
    setSystemVariableValue(cliExecutionEngine, varName, intVal);
  else
    /* get string value */
    stringVal := getTextFromAddress(rStruct[#stringValue]);
    setSystemVariableValue(cliExecutionEngine, varName, stringVal);
  endif;

  /* deallocate structure if asked to */
  if wP = 1
    cFree(MallocLibClass$Inst, rStruct[#variableName]);
    if intValFlag = 0
      cFree(MallocLibClass$Inst, rStruct[#stringValue]);
    endif;
    cFree(MallocLibClass$Inst, lP);
  endif;

  ^0
}!!

/* Respond to the write transcript message. */
Def WM_WRITE_TRANSCRIPT(self, wP, lP | ptr, handle, rStruct, start, end, aString)
{
  if (lP <> CLI_SERVER_RESULTS)  /* ignore message if bad call */
    ^0;
  endif;
  if (not (handle := new(Handle)))  /* abort if can't allocate handle */
    ^0;
  endif;
  if (not (setHandle(handle, wP)))  /* abort if can't set handle */
    free(handle);
    ^0;
  endif;
  if (not (lock(handle)))  /* abort if can't lock handle */
    free(handle);
    ^0;
  endif;
  rStruct := cStructFromStruct(TbirdStruct, #CServerResults, asStruct(handle));
 /* ignore message if not for us, or type incorrect */
  if (rStruct[#target] <> 0) cor (rStruct[#messageType] <> CLI_SERVER_RESULTS)
    unlock(handle);
    free(handle);
    ^0;
  endif;

  /* don't send if nobody there */
  if not(currentCliPresenter)
    ^nil;
  endif;

  if showResults(currentCliPresenter)
    start := offset( fieldAt(rStruct, #messageText));
    end   := ( start + rStruct[#messageLength]);
    aString := removeNulls(physicalString(copyFrom(data(rStruct),
      start, end)));
    outputCRLFLine(self, aString);
  endif;
  unlock(handle);
  free(handle);
  ^1;
}!!
/* CLIServer Class Initialization Code */

/* initialize the parsing tables */
/* note: yacc grammar stored in /tbird/arccore/cli */
CLParser := open(CLIParser);
CLParser.lex := open(CliTokenizer);
registerServerHandle(CLParser, self);
registerParserHandle(CLParser.lex, CLParser);
CLParser.yyexca := #( -1, 1, 0, -1, -2, 0); !!
CLParser.yyActions := new(Array, 196); !!
CLParser.yylast := 404; !!
CLParser.yyact := #(
 154, 155, 151, 156, 157, 55, 158, 159, 160, 161,
 162, 163, 150, 164, 165, 166, 167, 168, 169, 170,
 171, 172, 173, 174, 53, 175, 176, 177, 178, 181,
 182, 179, 180, 183, 184, 185, 186, 187, 188, 189,
 126, 190, 191, 192, 193, 194, 195, 196, 197, 198,
 242, 199, 200, 51, 51, 201, 202, 203, 204, 205,
 206, 207, 7, 140, 12, 54, 10, 123, 13, 6,
 21, 133, 134, 139, 138, 46, 29, 235, 234, 27,
 28, 25, 132, 32, 229, 8, 50, 135, 49, 130,
 5, 233, 231, 24, 23, 230, 149, 44, 148, 48,
 71, 50, 14, 49, 131, 11, 47, 22, 69, 56,
 68, 67, 70, 137, 48, 15, 16, 9, 45, 17,
 136, 47, 4, 31, 26, 99, 128, 100, 65, 66,
 123, 101, 102, 103, 63, 64, 124, 142, 62, 104,
 61, 237, 105, 106, 107, 98, 108, 109, 110, 111,
 60, 129, 58, 112, 57, 59, 113, 114, 52, 241,
 125, 127, 236, 2, 153, 115, 42, 39, 116, 97,
 117, 41, 34, 38, 240, 40, 37, 30, 118, 119,
 120, 74, 121, 75, 20, 36, 122, 76, 77, 78,
 35, 33, 3, 19, 43, 79, 18, 152, 80, 1,
 81, 73, 82, 83, 84, 85, 46, 0, 0, 86,
 0, 0, 87, 88, 0, 0, 0, 50, 0, 49,
 0, 89, 0, 0, 90, 72, 91, 145, 44, 0,
 48, 0, 0, 0, 92, 93, 94, 47, 95, 141,
 143, 144, 96, 0, 146, 147, 0, 0, 0, 45,
 0, 0, 0, 142, 209, 210, 0, 208, 0, 0,
 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 0, 0, 0, 0, 0, 0, 0, 212, 218, 219,
 220, 221, 216, 217, 215, 226, 227, 228, 224, 225,
 222, 223, 214, 0, 0, 211, 213, 232, 0, 0,
 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 0, 0, 0, 0, 0, 0, 0, 0, 238, 0,
 0, 239, 0, 243 ); !!
CLParser.yypact := #(
-239,-1000,-298,-1000,-153,-337,-296,-236,-173,-175,
-166,-177,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-187,
-189,-205,-211,-229,-237,-226,-245,-120,-176,-1000,
-201,-1000,-1000,-194,-144,-320,-141,-186,-246,-262,
-223,-279,-1000,-1000,-224,-224,-224,-1000,-1000,-108,
-1000,-239,-239,-1000,-1000,-247,-249,-349,-359,-301,
-108,-239,-239,-1000,-1000,-1000,-1000,-1000,-1000,-1000,
-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,
-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,
-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,
-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,
-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,
-1000,-1000,-1000,-108,-108,-108,-108,-108,-108,-108,
-108,-108,-108,-108,-108,-108,-108,-108,-108,-108,
-108,-1000,-1000,-1000,-1000,-264,-1000,-1000,-1000,-1000,
-253,-256,-301,-1000,-1000,-1000,-1000,-1000,-1000,-1000,
-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,
-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,
-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,
-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,
-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-257,-270,
-271,-194,-144,-320,-141,-186,-246,-246,-262,-262,
-262,-262,-223,-223,-279,-279,-1000,-1000,-1000,-1000,
-1000,-1000,-1000,-1000,-185,-185,-1000,-239,-151,-297,
-185,-1000,-1000,-1000 ); !!
CLParser.yypgo := #(
 0, 199, 163, 192, 197, 196, 193, 162, 184, 174,
 164, 194, 177, 166, 171, 175, 167, 173, 176, 185,
 190, 172, 191 ); !!
CLParser.yyr1 := #(
 0, 1, 2, 2, 2, 2, 3, 3, 3, 3,
 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
 3, 3, 3, 3, 3, 3, 3, 8, 9, 6,
 7, 10, 10, 10, 10, 10, 10, 10, 10, 10,
 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
 10, 10, 10, 10, 10, 4, 4, 4, 11, 11,
 11, 11, 11, 13, 13, 13, 13, 14, 14, 14,
 14, 15, 15, 15, 16, 16, 16, 17, 17, 17,
 17, 17, 18, 18, 18, 19, 19, 20, 20, 21,
 21, 22, 22, 12, 12, 5 ); !!
CLParser.yyr2 := #(
 0, 1, 0, 1, 2, 3, 3, 1, 2, 2,
 1, 2, 3, 3, 4, 4, 3, 4, 1, 1,
 1, 1, 1, 1, 1, 5, 5, 7, 1, 2,
 2, 1, 2, 2, 1, 2, 2, 1, 2, 1,
 2, 1, 2, 1, 2, 2, 2, 2, 2, 2,
 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
 2, 2, 2, 2, 2, 2, 2, 2, 2, 1,
 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
 2, 2, 2, 2, 2, 2, 1, 1, 1, 1,
 3, 1, 1, 1, 1, 1, 1, 1, 1, 1,
 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
 1, 1, 1, 1, 1, 0, 1, 2, 1, 1,
 1, 3, 1, 1, 2, 2, 2, 1, 3, 3,
 3, 1, 3, 3, 1, 3, 3, 1, 3, 3,
 3, 3, 1, 3, 3, 1, 3, 1, 3, 1,
 3, 1, 3, 1, 3, 1 ); !!
CLParser.yychk := #(
-1000, -1, -2, -3, 361, 329, 308, 301, 324, 356,
 305, 344, 303, 307, 341, 354, 355, 358, -5, -6,
 -8, 309, 346, 333, 332, 320, 363, 318, 319, 315,
 -12, 362, 322, -22, -21, -20, -19, -18, -17, -16,
 -15, -14, -13, -11, 336, 357, 314, 345, 338, 327,
 325, 351, 311, 361, 361, 301, 345, 327, 327, 321,
 327, 327, 327, 339, 340, 339, 340, 340, 339, 345,
 338, 345, 345, 321, 301, 303, 307, 308, 309, 315,
 318, 320, 322, 323, 324, 325, 329, 332, 333, 341,
 344, 346, 354, 355, 356, 358, 362, 345, 321, 301,
 303, 307, 308, 309, 315, 318, 319, 320, 322, 323,
 324, 325, 329, 332, 333, 341, 344, 346, 354, 355,
 356, 358, 362, 331, 330, 304, 360, 302, 312, 337,
 335, 350, 328, 317, 334, 349, 343, 336, 353, 352,
 342, -11, 361, -11, -11, -12, -3, -3, 345, 345,
 361, 361, -4, -10, 301, 302, 304, 305, 307, 308,
 309, 310, 311, 312, 314, 315, 316, 317, 318, 319,
 320, 321, 322, 323, 324, 326, 327, 328, 329, 332,
 333, 330, 331, 334, 335, 336, 337, 338, 339, 340,
 342, 343, 344, 345, 346, 347, 348, 349, 350, 352,
 353, 356, 357, 358, 359, 360, 361, 362, -5, -3,
 -3, -22, -21, -20, -19, -18, -17, -17, -16, -16,
 -16, -16, -15, -15, -14, -14, -13, -13, -13, 348,
 348, 348, -10, 348, 348, 348, -7, 326, -7, -2,
 -9, 310, 347, -7 ); !!
CLParser.yydef := #(
 2, -2, 1, 3, 159, 7, 0, 10, 0, 0,
 0, 0, 18, 19, 20, 21, 22, 23, 24, 0,
 0, 28, 31, 34, 37, 39, 41, 43, 69, 96,
 195, 99, 97, 193, 191, 189, 187, 185, 182, 177,
 174, 171, 167, 163, 0, 0, 0, 158, 160, 0,
 162, 4, 0, 8, 9, 0, 11, 0, 0, 155,
 0, 0, 0, 29, 30, 32, 33, 35, 36, 38,
 40, 42, 44, 45, 46, 47, 48, 49, 50, 51,
 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,
 62, 63, 64, 65, 66, 67, 68, 70, 71, 72,
 73, 74, 75, 76, 77, 78, 79, 80, 81, 82,
 83, 84, 85, 86, 87, 88, 89, 90, 91, 92,
 93, 94, 95, 0, 0, 0, 0, 0, 0, 0,
 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 0, 164, 159, 165, 166, 0, 5, 6, 13, 12,
 0, 0, 16, 156, 101, 102, 103, 104, 105, 106,
 107, 108, 109, 110, 111, 112, 113, 114, 115, 116,
 117, 118, 119, 120, 121, 122, 123, 124, 125, 126,
 127, 128, 129, 130, 131, 132, 133, 134, 135, 136,
 137, 138, 139, 140, 141, 142, 143, 144, 145, 146,
 147, 148, 149, 150, 151, 152, 153, 154, 0, 0,
 0, 194, 192, 190, 188, 186, 183, 184, 178, 179,
 180, 181, 175, 176, 172, 173, 168, 169, 170, 161,
 14, 15, 157, 17, 0, 0, 25, 2, 26, 0,
 0, 98, 100, 27 ); !!
CLParser.yyActions[1] := #doStatements; !!
CLParser.yyActions[2] := #doStmtEmpty; !!
CLParser.yyActions[3] := #doStmt; !!
CLParser.yyActions[4] := #pass; !!
CLParser.yyActions[5] := #doStmtList; !!
CLParser.yyActions[6] := #doAssignment; !!
CLParser.yyActions[7] := #doList; !!
CLParser.yyActions[8] := #doListVar; !!
CLParser.yyActions[9] := #doDeleteVar; !!
CLParser.yyActions[10] := #doAlias; !!
CLParser.yyActions[11] := #doAliasName; !!
CLParser.yyActions[12] := #doAliasAssign; !!
CLParser.yyActions[13] := #doAliasDelete; !!
CLParser.yyActions[14] := #doInteger; !!
CLParser.yyActions[15] := #doString; !!
CLParser.yyActions[16] := #doCall; !!
CLParser.yyActions[17] := #doPrintExpr; !!
CLParser.yyActions[18] := #doAppend; !!
CLParser.yyActions[19] := #doClear; !!
CLParser.yyActions[20] := #doOverwrite; !!
CLParser.yyActions[21] := #doStartTimer; !!
CLParser.yyActions[22] := #doStopTimer; !!
CLParser.yyActions[23] := #doTimestamp; !!
CLParser.yyActions[24] := #doExpr; !!
CLParser.yyActions[25] := #doWhile; !!
CLParser.yyActions[26] := #doIf; !!
CLParser.yyActions[27] := #doIfElse; !!
CLParser.yyActions[28] := #doShowCmd; !!
CLParser.yyActions[29] := #doShowCmdOff; !!
CLParser.yyActions[30] := #doShowCmdOn; !!
CLParser.yyActions[31] := #doShowRes; !!
CLParser.yyActions[32] := #doShowResOff; !!
CLParser.yyActions[33] := #doShowResOn; !!
CLParser.yyActions[34] := #doLogging; !!
CLParser.yyActions[35] := #doLoggingOn; !!
CLParser.yyActions[36] := #doLoggingOff; !!
CLParser.yyActions[37] := #doLog; !!
CLParser.yyActions[38] := #doLogFileName; !!
CLParser.yyActions[39] := #doHistory; !!
CLParser.yyActions[40] := #doHistorySize; !!
CLParser.yyActions[41] := #doWorkDirShow; !!
CLParser.yyActions[42] := #doWorkDirSet; !!
CLParser.yyActions[43] := #doHelp; !!
CLParser.yyActions[44] := #doHelpTopic; !!
CLParser.yyActions[45] := #doHelpIdent; !!
CLParser.yyActions[46] := #doHelpPrimitive; !!
CLParser.yyActions[47] := #doHelpPrimitive; !!
CLParser.yyActions[48] := #doHelpPrimitive; !!
CLParser.yyActions[49] := #doHelpPrimitive; !!
CLParser.yyActions[50] := #doHelpPrimitive; !!
CLParser.yyActions[51] := #doHelpPrimitive; !!
CLParser.yyActions[52] := #doHelpPrimitive; !!
CLParser.yyActions[53] := #doHelpPrimitive; !!
CLParser.yyActions[54] := #doHelpPrimitive; !!
CLParser.yyActions[55] := #doHelpPrimitive; !!
CLParser.yyActions[56] := #doHelpPrimitive; !!
CLParser.yyActions[57] := #doHelpPrimitive; !!
CLParser.yyActions[58] := #doHelpPrimitive; !!
CLParser.yyActions[59] := #doHelpPrimitive; !!
CLParser.yyActions[60] := #doHelpPrimitive; !!
CLParser.yyActions[61] := #doHelpPrimitive; !!
CLParser.yyActions[62] := #doHelpPrimitive; !!
CLParser.yyActions[63] := #doHelpPrimitive; !!
CLParser.yyActions[64] := #doHelpPrimitive; !!
CLParser.yyActions[65] := #doHelpPrimitive; !!
CLParser.yyActions[66] := #doHelpPrimitive; !!
CLParser.yyActions[67] := #doHelpPrimitive; !!
CLParser.yyActions[68] := #doHelpPrimitive; !!
CLParser.yyActions[69] := #doHelp_; !!
CLParser.yyActions[70] := #doHelp_Topic; !!
CLParser.yyActions[71] := #doHelp_Ident; !!
CLParser.yyActions[72] := #doHelp_Primitive; !!
CLParser.yyActions[73] := #doHelp_Primitive; !!
CLParser.yyActions[74] := #doHelp_Primitive; !!
CLParser.yyActions[75] := #doHelp_Primitive; !!
CLParser.yyActions[76] := #doHelp_Primitive; !!
CLParser.yyActions[77] := #doHelp_Primitive; !!
CLParser.yyActions[78] := #doHelp_Primitive; !!
CLParser.yyActions[79] := #doHelp_Primitive; !!
CLParser.yyActions[80] := #doHelp_Primitive; !!
CLParser.yyActions[81] := #doHelp_Primitive; !!
CLParser.yyActions[82] := #doHelp_Primitive; !!
CLParser.yyActions[83] := #doHelp_Primitive; !!
CLParser.yyActions[84] := #doHelp_Primitive; !!
CLParser.yyActions[85] := #doHelp_Primitive; !!
CLParser.yyActions[86] := #doHelp_Primitive; !!
CLParser.yyActions[87] := #doHelp_Primitive; !!
CLParser.yyActions[88] := #doHelp_Primitive; !!
CLParser.yyActions[89] := #doHelp_Primitive; !!
CLParser.yyActions[90] := #doHelp_Primitive; !!
CLParser.yyActions[91] := #doHelp_Primitive; !!
CLParser.yyActions[92] := #doHelp_Primitive; !!
CLParser.yyActions[93] := #doHelp_Primitive; !!
CLParser.yyActions[94] := #doHelp_Primitive; !!
CLParser.yyActions[95] := #doHelp_Primitive; !!
CLParser.yyActions[96] := #doExit; !!
CLParser.yyActions[97] := #incrementNestLevel; !!
CLParser.yyActions[98] := #incrementNestLevel; !!
CLParser.yyActions[99] := #incrementNestLevel; !!
CLParser.yyActions[100] := #doBlock; !!
CLParser.yyActions[101] := #doCallListKeyword; !!
CLParser.yyActions[102] := #doCallListOperator; !!
CLParser.yyActions[103] := #doCallListOperator; !!
CLParser.yyActions[104] := #doCallListKeyword; !!
CLParser.yyActions[105] := #doCallListKeyword; !!
CLParser.yyActions[106] := #doCallListKeyword; !!
CLParser.yyActions[107] := #doCallListKeyword; !!
CLParser.yyActions[108] := #doCallListKeyword; !!
CLParser.yyActions[109] := #doCallListOperator; !!
CLParser.yyActions[110] := #doCallListOperator; !!
CLParser.yyActions[111] := #doCallListOperator; !!
CLParser.yyActions[112] := #doCallListKeyword; !!
CLParser.yyActions[113] := #doCallListKeyword; !!
CLParser.yyActions[114] := #doCallListOperator; !!
CLParser.yyActions[115] := #doCallListKeyword; !!
CLParser.yyActions[116] := #doCallListKeyword; !!
CLParser.yyActions[117] := #doCallListKeyword; !!
CLParser.yyActions[118] := #doCallListString; !!
CLParser.yyActions[119] := #doCallListKeyword; !!
CLParser.yyActions[120] := #doCallListKeyword; !!
CLParser.yyActions[121] := #doCallListKeyword; !!
CLParser.yyActions[122] := #doCallListOperator; !!
CLParser.yyActions[123] := #doCallListOperator; !!
CLParser.yyActions[124] := #doCallListOperator; !!
CLParser.yyActions[125] := #doCallListKeyword; !!
CLParser.yyActions[126] := #doCallListKeyword; !!
CLParser.yyActions[127] := #doCallListKeyword; !!
CLParser.yyActions[128] := #doCallListOperator; !!
CLParser.yyActions[129] := #doCallListOperator; !!
CLParser.yyActions[130] := #doCallListOperator; !!
CLParser.yyActions[131] := #doCallListOperator; !!
CLParser.yyActions[132] := #doCallListOperator; !!
CLParser.yyActions[133] := #doCallListOperator; !!
CLParser.yyActions[134] := #doCallListString; !!
CLParser.yyActions[135] := #doCallListKeyword; !!
CLParser.yyActions[136] := #doCallListKeyword; !!
CLParser.yyActions[137] := #doCallListOperator; !!
CLParser.yyActions[138] := #doCallListOperator; !!
CLParser.yyActions[139] := #doCallListKeyword; !!
CLParser.yyActions[140] := #doCallListQString; !!
CLParser.yyActions[141] := #doCallListKeyword; !!
CLParser.yyActions[142] := #doCallListOperator; !!
CLParser.yyActions[143] := #doCallListOperator; !!
CLParser.yyActions[144] := #doCallListOperator; !!
CLParser.yyActions[145] := #doCallListOperator; !!
CLParser.yyActions[146] := #doCallListOperator; !!
CLParser.yyActions[147] := #doCallListOperator; !!
CLParser.yyActions[148] := #doCallListKeyword; !!
CLParser.yyActions[149] := #doCallListOperator; !!
CLParser.yyActions[150] := #doCallListKeyword; !!
CLParser.yyActions[151] := #doCallListString; !!
CLParser.yyActions[152] := #doCallListOperator; !!
CLParser.yyActions[153] := #doCallListVariable; !!
CLParser.yyActions[154] := #doCallListKeyword; !!
CLParser.yyActions[155] := #doNoCallParams; !!
CLParser.yyActions[156] := #doCallParam; !!
CLParser.yyActions[157] := #doCallParamList; !!
CLParser.yyActions[158] := #doQuotedString; !!
CLParser.yyActions[159] := #doVariable; !!
CLParser.yyActions[160] := #pass; !!
CLParser.yyActions[161] := #doParen; !!
CLParser.yyActions[162] := #doLapTime; !!
CLParser.yyActions[163] := #pass; !!
CLParser.yyActions[164] := #doUnaryOp; !!
CLParser.yyActions[165] := #doUnaryOp; !!
CLParser.yyActions[166] := #doUnaryOp; !!
CLParser.yyActions[167] := #pass; !!
CLParser.yyActions[168] := #doBinaryOp; !!
CLParser.yyActions[169] := #doBinaryOp; !!
CLParser.yyActions[170] := #doBinaryOp; !!
CLParser.yyActions[171] := #pass; !!
CLParser.yyActions[172] := #doBinaryOp; !!
CLParser.yyActions[173] := #doBinaryOp; !!
CLParser.yyActions[174] := #pass; !!
CLParser.yyActions[175] := #doBinaryOp; !!
CLParser.yyActions[176] := #doBinaryOp; !!
CLParser.yyActions[177] := #pass; !!
CLParser.yyActions[178] := #doBinaryOp; !!
CLParser.yyActions[179] := #doBinaryOp; !!
CLParser.yyActions[180] := #doBinaryOp; !!
CLParser.yyActions[181] := #doBinaryOp; !!
CLParser.yyActions[182] := #pass; !!
CLParser.yyActions[183] := #doBinaryOp; !!
CLParser.yyActions[184] := #doBinaryOp; !!
CLParser.yyActions[185] := #pass; !!
CLParser.yyActions[186] := #doBinaryOp; !!
CLParser.yyActions[187] := #pass; !!
CLParser.yyActions[188] := #doBinaryOp; !!
CLParser.yyActions[189] := #pass; !!
CLParser.yyActions[190] := #doBinaryOp; !!
CLParser.yyActions[191] := #pass; !!
CLParser.yyActions[192] := #doBinaryOp; !!
CLParser.yyActions[193] := #pass; !!
CLParser.yyActions[194] := #doBinaryOp; !!
CLParser.yyActions[195] := #pass; !!
