Mercurial > ~dholland > hg > ag > index.cgi
view anagram/agcore/operations.cpp @ 21:1c9dac05d040
Add lint-style FALLTHROUGH annotations to fallthrough cases.
(in the parse engine and thus the output code)
Document this, because the old output causes warnings with gcc10.
author | David A. Holland |
---|---|
date | Mon, 13 Jun 2022 00:04:38 -0400 |
parents | 13d2b8934445 |
children |
line wrap: on
line source
/* * 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; }