diff anagram/agcore/operations.cpp @ 0:13d2b8934445

Import AnaGram (near-)release tree into Mercurial.
author David A. Holland
date Sat, 22 Dec 2007 17:52:45 -0500
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/anagram/agcore/operations.cpp	Sat Dec 22 17:52:45 2007 -0500
@@ -0,0 +1,375 @@
+/*
+ * AnaGram, A System for Syntax Directed Programming
+ * Copyright 1993-2002 Parsifal Software. All Rights Reserved.
+ * Copyright 2006 David A. Holland. All Rights Reserved.
+ * See the file COPYING for license and usage terms.
+ *
+ * operations.cpp - central operations
+ */
+
+#ifdef AG_ON_UNIX
+#include <sys/types.h>
+#include <sys/param.h>	// for MAXPATHLEN (see below)
+#endif
+
+#ifdef AG_ON_WINDOWS
+#include <windows.h>	// for HMODULE and GetModuleFileName
+#endif
+
+#include "port.h"
+
+#ifdef VACLGUI
+//#include <imsgbox.hpp>
+#include "action.h"
+#endif
+
+#include "agdict.h"
+#include "aglib.h"
+#include "agstring.h"
+#include "assert.h"
+#include "bpe3.h"
+#include "bpu.h"
+#include "cf-defs.h"
+#include "checksum.h"
+#include "config.h"
+#include "configparam.h"
+#include "data.h"
+#include "engdef.h"
+#include "error.h"
+#include "file.h"
+#include "ftpar.h"
+#include "keyword.h"
+#include "operations.h"
+#include "p.h"
+#include "q1a.h"
+#include "rproc.h"
+#include "rule.h"
+#include "stacks.h"
+#include "sums-defs.h"
+#include "symbol.h"
+#include "token.h"
+#include "tree.h"
+#include "textfile.h"
+
+//#define INCLUDE_LOGGING
+#include "log.h"
+
+
+/*
+extern int bytesAllocated;
+extern int constructorCalls;
+extern int copyConstructorCalls;
+extern int destructorCalls;
+
+extern int nodesCreated;
+extern int nodesDeleted;
+extern int nodesAllocated;
+extern int nodesFreed;
+
+extern int myallocs;
+extern int myfrees;
+extern int myallocBytes;
+extern int myfreeBytes;
+extern int arrayBytesAllocated;
+extern int arrayBytesFreed;
+extern int arraysAllocated;
+extern int arraysFreed;
+
+extern int newCalls;
+extern int newArrayCalls;
+extern int deleteCalls;
+extern int deleteArrayCalls;
+
+extern int dcsCreated;
+extern int dcsDestroyed;
+extern int sconConstructorCalls;
+extern int sconDestructorCalls;
+*/
+
+
+static unsigned         n_config_errors;
+
+// XXX does this really accomplish anything?
+#ifdef VACLGUI
+static AgAction       startAction;
+#endif
+
+unsigned char *input_base;
+static AgString my_own_dir;
+
+
+/* first thing that happens; comes from main() */
+void init(char *argv_0) {
+  LOGINIT();
+  LOGSECTION("init");
+  LOGV(argv_0);
+
+#ifdef AG_ON_WINDOWS
+  /* Is this necessary or even useful? */
+  char buf[MAX_PATH];
+  //_fullpath(buf, argv_0, MAX_PATH);
+  HMODULE module = GetModuleHandle(0);
+  GetModuleFileName(module, buf, MAX_PATH);
+  LOGV(buf);
+  argv_0 = buf;
+#endif
+
+#ifdef AG_ON_UNIX
+  // realpath is documented with MAXPATHLEN from sys/param.h, not 
+  // PATH_MAX from limits.h.
+  //
+  // I don't think there are systems where these are different, but
+  // never underestimate the power of stupidity when people decide
+  // to release their very own System-V-derived Buggix.
+  //
+  //char buf[PATH_MAX];
+  char buf[MAXPATHLEN];
+  if (realpath(argv_0, buf) != NULL) {
+    LOGV(buf);
+    argv_0 = buf;
+  }
+#endif
+
+  sum_remember_argv0(argv_0);
+
+  AgString myself = argv_0;
+  my_own_dir = myself.lastCut(PATH_DELIMITER).leftX();
+}
+
+void init_parser(void) {
+  LOGSECTION("init_parser");
+  no_assertions = 0;
+
+  init_stk();
+  init_data();
+  Cast::reset();
+  Symbol::reset();
+  Token::reset();
+  set_work_dir();
+  read_config(my_own_dir);
+  ConfigParam::initAll();
+
+  n_config_errors = errorList.size();  //nerrors;
+  reset_parser();
+}
+
+#if 0  /* NOT USED */
+int netAllocations() {
+  return newArrayCalls - deleteArrayCalls
+       + newCalls - deleteCalls
+       - (arraysAllocated - arraysFreed);
+}
+#endif
+
+#if 0 /* NOT USED */
+void logAlloc() {
+  LOGV(bytesAllocated) LCV(constructorCalls) LCV(copyConstructorCalls)
+    LCV(destructorCalls);
+  LOGV(nodesCreated - nodesDeleted);
+  LOGV(newArrayCalls) LCV(deleteArrayCalls) LCV(newCalls) LCV(deleteCalls);
+  LOGV(myallocs - myfrees) LCV(myallocBytes- myfreeBytes);
+  LOGV(newArrayCalls - deleteArrayCalls) LCV(newCalls - deleteCalls);
+  LOGV(arraysAllocated - arraysFreed)
+    LCV(arrayBytesAllocated - arrayBytesFreed);
+  // note: this line wasn't in agsa.cpp, only main.cpp
+  LOGV(dcsCreated) LCV(dcsDestroyed) 
+    LCV(sconConstructorCalls) LCV(sconDestructorCalls);
+}
+#endif
+
+void reset_parser(void) {
+  LOGSECTION("reset_parser");
+  if (syntax_state == syntax_reset) {
+    return;
+  }
+  syntax_state = syntax_reset;
+#if 0
+  logAlloc();
+#endif
+  reset_result_data();
+  LOGS("result data reset");
+  reset_summary_data();
+  LOGS("summary data reset");
+  cSegmentStack.reset();
+  LOGS("cSegmentStack reset");
+  extensionStack.reset();
+  LOGS("extenstionStack.reset");
+  cVariableList.reset();
+  LOGS("cVariablelist reset");
+  //errorList.reset();
+  traceCounts.reset();
+  LOGS("traceCounts reset");
+  valueToken.reset();
+  LOGS("valueToken reset");
+
+  Cast::reset();
+  LOGS("Cast reset");
+  Keyword::reset();
+  LOGS("Keyword reset");
+  ParseTree::reset();
+  LOGS("ParseTree reset");
+  Procedure::reset();
+  Rule::reset();
+  //State::reset();
+  Symbol::reset();
+  Token::reset();
+  // note: the following line was not in agsa.cpp, only main.cpp.
+  // but I suspect that was a bug...
+  VpRule::reset();
+
+  LOGS("Tables reset");
+  ConfigParam::resetAll();
+  nPrologueSegments = 0;
+}
+
+void analyzeGrammar(AgString data, int hasGui) {
+  LOGSECTION("analyzeGrammar");
+  reset_parser();
+  input_base = (unsigned char *) data.pointer();
+  syntax_state = syntax_loaded;
+  syntax_error_flag = parse_abort_flag = 0;
+  badRecursionFlag = 0;
+  scan_input();
+  LOGS("input scan complete");
+  if (badRecursionFlag && hasGui) {
+    ssprintf("File Trace disabled: %s", badRecursionFlag);
+    log_error();
+  }
+  if (syntax_error_flag ||
+      parse_abort_flag ||
+      nprods == 0 ||
+      grammar_token == 0 ||
+      //badRecursionFlag ||
+      syntax_state != syntax_parsed) {
+    return;
+  }
+  new_syntax_analyzer();
+  assert(int_stack_top == 0);
+  assert(nc == 0);
+  assert(nw == 0);
+}
+
+void buildParser() {
+  LOGSECTION("Build parser");
+  LOGV(syntax_state);
+  if (syntax_state == syntax_analyzed) {
+    LOGS("build engine");
+    *buildErrorMsg = 0;
+    build_parse_engine();
+    if (*buildErrorMsg) {
+      errorList.push(Error(buildErrorMsg));
+    }
+    LOGS("build complete");
+    syntax_state = engine_built;
+  }
+  assert(int_stack_top == 0);
+  assert(nc == 0);
+  assert(nw == 0);
+}
+
+static void dump_errors() {
+  LOGSECTION("dump_errors");
+  unsigned i;
+
+  LOGV(errorList.size());
+  for (i = 0; i < errorList.size(); i++) {
+    Error &e = errorList[i];
+    LOGV(i) LCV(e.line) LCV(e.column);
+    LOGV(e.file.pointer());
+    LOGV((int) e.key) LCV(Error::keyString[e.key]);
+    // XXX if AG_ON_UNIX should default to gcc's format, and go to stderr
+    printf("%s(%d-%d): %s: %s\n",
+	   e.file.pointer(), e.line, e.column, 
+	   Error::keyString[e.key], e.message.pointer());
+  }
+  fflush(stdout);
+}
+
+static text_file buildFile;
+
+static void doBuild(void) {
+  if (buildFile.text.exists()) {
+    analyzeGrammar(buildFile.text, 0 /* no GUI */);
+    buildParser();
+  }
+  else {
+    ssprintf("Cannot read %s",infile_name.pointer());
+    log_error();
+    errorList.top().setFatal();
+  }
+  if (errorList.size()) {
+    dump_errors();
+  }
+}
+
+int commandLineBuild(char *n) {
+  LOGSECTION("commandLineBuild");
+
+  //AgString path(fp);
+  engdef_init();
+  init_parser();
+  const char *failure = checksums_ok();
+  if (failure) {
+    fprintf(stderr, "Initialization failure: %s\n", failure);
+    AgString whine = code_segment("broken").pointer();
+    fprintf(stderr, "%s\n", whine.pointer());
+    return 1;
+  }
+
+  AgString name(n);
+  LOGV(name);
+
+  // XXX. Does this really need to be conditional?
+#ifdef VACLGUI
+  startAction = actionObject(doBuild);
+#endif
+
+#ifdef AG_ON_WINDOWS
+  AgString fullpath(_MAX_PATH);
+  _fullpath(fullpath.pointer(), name.pointer(), _MAX_PATH);
+  AgString fileName = fullpath.lastCut("\\/:").rightX();
+#endif
+
+#ifdef AG_ON_UNIX
+#if 0 /* Don't use realpath; it's not the canonical Unix way */
+  // realpath is documented to use MAXPATHLEN, not PATH_MAX. sigh.
+  // (see longer comment above)
+  //AgString fullpath(PATH_MAX);
+  AgString fullpath(MAXPATHLEN);
+
+  realpath(name.pointer(), fullpath.pointer());
+  AgString fileName = fullpath.lastCut('/').rightX();
+#else
+  AgString fullpath = name;
+  AgString fileName = fullpath.lastCut('/').rightX();
+  if (fileName.size() == 0) {
+    fileName = fullpath;
+  }
+#endif /* 0 */
+#endif /* AG_ON_UNIX */
+
+  infile_name = fullpath;   // Store selected file name
+  errorReportFile = infile_name;   // Store selected file name
+
+  simple_file_name = fileName.lastCut('.').leftX();
+
+  LOGV(fileName.pointer());
+  LOGV(simple_file_name.pointer());
+  text_file inputFile(infile_name);
+
+  if (!inputFile.text.exists() && fileName == simple_file_name) {
+    infile_name = infile_name.concat(".syn");
+    inputFile = text_file(infile_name);
+    LOGV(infile_name.pointer());
+  }
+  buildFile = inputFile;
+
+  // XXX as above
+#ifdef VACLGUI
+  startAction();
+#else
+  doBuild();
+#endif
+
+  return syntax_state != engine_built;
+}