Mercurial > ~dholland > hg > ag > index.cgi
diff examples/mpp/mpp.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/examples/mpp/mpp.cpp Sat Dec 22 17:52:45 2007 -0500 @@ -0,0 +1,258 @@ +/* + * AnaGram, a System for Syntax Directed Programming + * C Macro preprocessor + * Global Data and Main Program + * + * Copyright 1993-2000 Parsifal Software. All Rights Reserved. + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * 3. This notice may not be removed or altered from any source distribution. + */ + +// for out of date compilers +#if defined(__IBMCPP__) +#define OLDCPLUSPLUS +#endif + +#include "mpp.h" +#include <stdlib.h> +#include <ctype.h> + +#ifdef OLDCPLUSPLUS +#include <new.h> +#else +#include <new> +#endif + +#include "array.h" // \ANAGRAM\CLASSLIB\INCLUDE\ARRAY.H +#include "util.h" // \ANAGRAM\CLASSLIB\INCLUDE\UTIL.H + + +// Global data definitions + +expression_evaluator condition; +unsigned defined_value; +int if_clause = 0; +char default_path[] = ""; //default include file path, if desired +macro_descriptor macro[N_MACROS]; +unsigned macro_id[N_SYMBOLS] = {0}; +int n_macros = 0; +unsigned n_reserved_words = 0; +int nest_comments = 0; +unsigned one_value; +stack<char *> paths(20,1); +string_accumulator sa(1000,20); +token_sink *scanner_sink; +token_accumulator ta(1000,20); +string_dictionary td(N_SYMBOLS); +unsigned token_handles[256]; +unsigned zero_value; + + +// Initialization data + +op_descriptor ops[] = { + {"&&" , ANDAND}, + {"&=" , ANDassign}, + {"->" , ARROW}, + {"##" , CONCAT}, + {"--" , DECR}, + {"/=" , DIVassign}, + {"..." , ELLIPSIS}, + {"==" , EQ}, + {"^=" , ERassign}, + {">=" , GE}, + {"++" , ICR}, + {"<=" , LE}, + {"<<" , LS}, + {"<<=" , LSassign}, + {"%=" , MODassign}, + {"-=" , MINUSassign}, + {"*=" , MULTassign}, + {"!=" , NE}, + {"|=" , ORassign}, + {"||" , OROR}, + {"+=" , PLUSassign}, + {">>" , RS}, + {">>=" , RSassign}, + {" " , SPACE}, +}; + +op_descriptor reserved_words[] = { + {NULL, END_OF_FILE }, + {"auto", AUTO }, + {"break", BREAK }, + {"case", CASE }, + {"char", CHAR }, + {"const", CONSTANT }, + {"continue", CONTINUE }, + {"default", DEFAULT }, + {"do", DO }, + {"double", DOUBLE }, + {"else", ELSE }, + {"enum", ENUM }, + {"extern", EXTERN }, + {"float", FLOAT }, + {"for", FOR }, + {"goto", GOTO }, + {"if", IF }, + {"int", INT }, + {"long", LONG }, + {"register", REGISTER }, + {"return", RETURN }, + {"short", SHORT }, + {"signed", SIGNED }, + {"sizeof", SIZEOF }, + {"static", STATIC }, + {"struct", STRUCT }, + {"switch", SWITCH }, + {"typedef", TYPEDEF }, + {"union", UNION }, + {"unsigned", UNSIGNED }, + {"void", VOIDkey }, + {"volatile", VOLATILE }, + {"while", WHILE }, +}; + + +// Data initializer + +static void init_data(void) { + unsigned k; + + memset(token_handles, 0, 256*sizeof(unsigned)); + + n_reserved_words = sizeof(reserved_words) / sizeof(op_descriptor); + + assert(size(td) == 0); + + for (k = 1; k < n_reserved_words; k++) { + unsigned index = td << reserved_words[k].op; + token_handles[reserved_words[k].id] = index; + assert(index == k); + } + + k = sizeof(ops) / sizeof(op_descriptor); + while (k--) token_handles[ops[k].id] = td << ops[k].op; + + for (k = 1; k < 127; k++) { + if (token_handles[k] || isalnum(k)) continue; + token_handles[k] = td << (char *) &k; + } + + defined_value = td << "defined"; + one_value = td << "1"; + zero_value = td << "0"; +} + + +// Field memory allocation failures + +#if defined(OLDCPLUSPLUS) && defined(_MSC_VER) +// Cope with peculiarity of MSVC++ +// (probably not needed any more - someone with a recent MSVC please advise) +static int out_of_space(size_t) { + printf("\nOut of space\n"); + exit(1); + // Cookie for the cookie monster + return 0; +} +#else +static void out_of_space(void) { + printf("\nOut of space\n"); + exit(1); +} +#endif + +// Extract and directory names from path statement + +static void extract_paths(const char *path_string) { + if (path_string == NULL) return; // exit if no default paths + ++sa << path_string; // temporary copy of path string + char *p = sa.top(); // init scan pointer + char *q = strrchr(p,';'); // look for rightmost semi-colon + while (q != NULL) { + *q++ = 0; // replace it with null + while (*q == ' ') q++; // skip over blanks + paths << memdup(q, 1+strlen(q)); // stack copy + q = strrchr(p, ';'); + } + while (*p == ' ') p++; // get rid of blanks + paths << memdup(p, 1+strlen(p)); // stack last path + --sa; +} + + +// Main Program + +int main(int argc, char *argv[]) { + int i; // for indexing args + c_parser cp; // initialize c parser + char *inpath = NULL; // input file name + char *outpath = NULL; // output file name + +#if defined(OLDCPLUSPLUS) +#ifdef _MSC_VER //Cope with peculiarity of MSVC++ + _set_new_handler(out_of_space); // field allocation errors +#else + set_new_handler(out_of_space); // field allocation errors +#endif +#else /* current standard C++ dialect */ + std::set_new_handler(out_of_space); // field allocation errors +#endif + init_data(); // initialize data + + extract_paths(default_path); // get default include directories + + for (i = 1; i < argc; i++) { + switch (*argv[i]) { + case '-': + case '/': + switch (argv[i][1]) { + case 'c': + scanner_sink = &cp; // output to c parser + break; + case 'n': + nest_comments = 1; // accept nested comments + break; + case 'i': + extract_paths(argv[i] + 2); // include path + break; + default: + printf("Unrecognized switch: %c\n", argv[i][1]); + } + continue; + } + break; + } + + extract_paths("./"); // add local directory to include paths + + assert(i < argc); // there always has to be an input + inpath = argv[i++]; + + if (i < argc) outpath = argv[i++]; // output file specified? + else outpath = NULL; + + output_file file(outpath); // open output file + token_translator tt(&file); // set up translator + + if (scanner_sink == NULL) // if compiler not selected + scanner_sink = &tt; // output to token translator + + scan_input(inpath); // do it! (see TS.SYN) + return 0; +}