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;
+}