1 2 /* Parser generator main program */ 3 4 /* This expects a filename containing the grammar as argv[1] (UNIX) 5 or asks the console for such a file name (THINK C). 6 It writes its output on two files in the current directory: 7 - "graminit.c" gets the grammar as a bunch of initialized data 8 - "graminit.h" gets the grammar's non-terminals as #defines. 9 Error messages and status info during the generation process are 10 written to stdout, or sometimes to stderr. */ 11 12 /* XXX TO DO: 13 - check for duplicate definitions of names (instead of fatal err) 14 */ 15 16 #define PGEN 17 18 #include "Python.h" 19 #include "internal/mem.h" 20 #include "internal/pystate.h" 21 #include "pgenheaders.h" 22 #include "grammar.h" 23 #include "node.h" 24 #include "parsetok.h" 25 #include "pgen.h" 26 27 int Py_DebugFlag; 28 int Py_VerboseFlag; 29 int Py_IgnoreEnvironmentFlag; 30 _PyRuntimeState _PyRuntime = _PyRuntimeState_INIT; 31 32 /* Forward */ 33 grammar *getgrammar(const char *filename); 34 35 void 36 Py_Exit(int sts) 37 { 38 exit(sts); 39 } 40 41 /* Needed by obmalloc.c */ 42 int PyGILState_Check(void) 43 { return 1; } 44 45 void _PyMem_DumpTraceback(int fd, const void *ptr) 46 {} 47 48 int 49 main(int argc, char **argv) 50 { 51 grammar *g; 52 FILE *fp; 53 char *filename, *graminit_h, *graminit_c; 54 55 if (argc != 4) { 56 fprintf(stderr, 57 "usage: %s grammar graminit.h graminit.c\n", argv[0]); 58 Py_Exit(2); 59 } 60 filename = argv[1]; 61 graminit_h = argv[2]; 62 graminit_c = argv[3]; 63 g = getgrammar(filename); 64 fp = fopen(graminit_c, "w"); 65 if (fp == NULL) { 66 perror(graminit_c); 67 Py_Exit(1); 68 } 69 if (Py_DebugFlag) 70 printf("Writing %s ...\n", graminit_c); 71 printgrammar(g, fp); 72 fclose(fp); 73 fp = fopen(graminit_h, "w"); 74 if (fp == NULL) { 75 perror(graminit_h); 76 Py_Exit(1); 77 } 78 if (Py_DebugFlag) 79 printf("Writing %s ...\n", graminit_h); 80 printnonterminals(g, fp); 81 fclose(fp); 82 freegrammar(g); 83 Py_Exit(0); 84 return 0; /* Make gcc -Wall happy */ 85 } 86 87 grammar * 88 getgrammar(const char *filename) 89 { 90 FILE *fp; 91 node *n; 92 grammar *g0, *g; 93 perrdetail err; 94 95 fp = fopen(filename, "r"); 96 if (fp == NULL) { 97 perror(filename); 98 Py_Exit(1); 99 } 100 g0 = meta_grammar(); 101 n = PyParser_ParseFile(fp, filename, g0, g0->g_start, 102 (char *)NULL, (char *)NULL, &err); 103 fclose(fp); 104 if (n == NULL) { 105 fprintf(stderr, "Parsing error %d, line %d.\n", 106 err.error, err.lineno); 107 if (err.text != NULL) { 108 size_t len; 109 int i; 110 fprintf(stderr, "%s", err.text); 111 len = strlen(err.text); 112 if (len == 0 || err.text[len-1] != '\n') 113 fprintf(stderr, "\n"); 114 for (i = 0; i < err.offset; i++) { 115 if (err.text[i] == '\t') 116 putc('\t', stderr); 117 else 118 putc(' ', stderr); 119 } 120 fprintf(stderr, "^\n"); 121 PyObject_FREE(err.text); 122 } 123 Py_Exit(1); 124 } 125 g = pgen(n); 126 PyNode_Free(n); 127 if (g == NULL) { 128 printf("Bad grammar.\n"); 129 Py_Exit(1); 130 } 131 return g; 132 } 133 134 /* Can't happen in pgen */ 135 PyObject* 136 PyErr_Occurred() 137 { 138 return 0; 139 } 140 141 void 142 Py_FatalError(const char *msg) 143 { 144 fprintf(stderr, "pgen: FATAL ERROR: %s\n", msg); 145 Py_Exit(1); 146 } 147 148 /* No-nonsense my_readline() for tokenizer.c */ 149 150 char * 151 PyOS_Readline(FILE *sys_stdin, FILE *sys_stdout, const char *prompt) 152 { 153 size_t n = 1000; 154 char *p = (char *)PyMem_MALLOC(n); 155 char *q; 156 if (p == NULL) 157 return NULL; 158 fprintf(stderr, "%s", prompt); 159 q = fgets(p, n, sys_stdin); 160 if (q == NULL) { 161 *p = '\0'; 162 return p; 163 } 164 n = strlen(p); 165 if (n > 0 && p[n-1] != '\n') 166 p[n-1] = '\n'; 167 return (char *)PyMem_REALLOC(p, n+1); 168 } 169 170 /* No-nonsense fgets */ 171 char * 172 Py_UniversalNewlineFgets(char *buf, int n, FILE *stream, PyObject *fobj) 173 { 174 return fgets(buf, n, stream); 175 } 176 177 178 #include <stdarg.h> 179 180 void 181 PySys_WriteStderr(const char *format, ...) 182 { 183 va_list va; 184 185 va_start(va, format); 186 vfprintf(stderr, format, va); 187 va_end(va); 188 } 189