Mercurial > ~dholland > hg > ag > index.cgi
view examples/mpp/mpp.cpp @ 16:f9e4689b837d
Some minor updates for 15 years later.
author | David A. Holland |
---|---|
date | Tue, 31 May 2022 01:45:26 -0400 |
parents | 13d2b8934445 |
children |
line wrap: on
line source
/* * 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; }