pgenmain.c 3.72 KB
Newer Older
1

Guido van Rossum's avatar
Guido van Rossum committed
2 3
/* Parser generator main program */

Guido van Rossum's avatar
Guido van Rossum committed
4 5 6 7 8 9 10
/* This expects a filename containing the grammar as argv[1] (UNIX)
   or asks the console for such a file name (THINK C).
   It writes its output on two files in the current directory:
   - "graminit.c" gets the grammar as a bunch of initialized data
   - "graminit.h" gets the grammar's non-terminals as #defines.
   Error messages and status info during the generation process are
   written to stdout, or sometimes to stderr. */
Guido van Rossum's avatar
Guido van Rossum committed
11

12 13 14 15
/* XXX TO DO:
   - check for duplicate definitions of names (instead of fatal err)
*/

16
#include "Python.h"
Guido van Rossum's avatar
Guido van Rossum committed
17
#include "pgenheaders.h"
Guido van Rossum's avatar
Guido van Rossum committed
18 19 20 21 22
#include "grammar.h"
#include "node.h"
#include "parsetok.h"
#include "pgen.h"

23
int Py_DebugFlag;
24
int Py_VerboseFlag;
25
int Py_IgnoreEnvironmentFlag;
Guido van Rossum's avatar
Guido van Rossum committed
26

Guido van Rossum's avatar
Guido van Rossum committed
27
/* Forward */
28
grammar *getgrammar(char *filename);
Guido van Rossum's avatar
Guido van Rossum committed
29

30
void
Thomas Wouters's avatar
Thomas Wouters committed
31
Py_Exit(int sts)
32
{
33
    exit(sts);
34 35
}

Guido van Rossum's avatar
Guido van Rossum committed
36
int
Thomas Wouters's avatar
Thomas Wouters committed
37
main(int argc, char **argv)
Guido van Rossum's avatar
Guido van Rossum committed
38
{
39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
    grammar *g;
    FILE *fp;
    char *filename, *graminit_h, *graminit_c;

    if (argc != 4) {
        fprintf(stderr,
            "usage: %s grammar graminit.h graminit.c\n", argv[0]);
        Py_Exit(2);
    }
    filename = argv[1];
    graminit_h = argv[2];
    graminit_c = argv[3];
    g = getgrammar(filename);
    fp = fopen(graminit_c, "w");
    if (fp == NULL) {
        perror(graminit_c);
        Py_Exit(1);
    }
    if (Py_DebugFlag)
        printf("Writing %s ...\n", graminit_c);
    printgrammar(g, fp);
    fclose(fp);
    fp = fopen(graminit_h, "w");
    if (fp == NULL) {
        perror(graminit_h);
        Py_Exit(1);
    }
    if (Py_DebugFlag)
        printf("Writing %s ...\n", graminit_h);
    printnonterminals(g, fp);
    fclose(fp);
    Py_Exit(0);
    return 0; /* Make gcc -Wall happy */
Guido van Rossum's avatar
Guido van Rossum committed
72 73 74
}

grammar *
Thomas Wouters's avatar
Thomas Wouters committed
75
getgrammar(char *filename)
Guido van Rossum's avatar
Guido van Rossum committed
76
{
77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116
    FILE *fp;
    node *n;
    grammar *g0, *g;
    perrdetail err;

    fp = fopen(filename, "r");
    if (fp == NULL) {
        perror(filename);
        Py_Exit(1);
    }
    g0 = meta_grammar();
    n = PyParser_ParseFile(fp, filename, g0, g0->g_start,
                  (char *)NULL, (char *)NULL, &err);
    fclose(fp);
    if (n == NULL) {
        fprintf(stderr, "Parsing error %d, line %d.\n",
            err.error, err.lineno);
        if (err.text != NULL) {
            size_t i;
            fprintf(stderr, "%s", err.text);
            i = strlen(err.text);
            if (i == 0 || err.text[i-1] != '\n')
                fprintf(stderr, "\n");
            for (i = 0; i < err.offset; i++) {
                if (err.text[i] == '\t')
                    putc('\t', stderr);
                else
                    putc(' ', stderr);
            }
            fprintf(stderr, "^\n");
            PyObject_FREE(err.text);
        }
        Py_Exit(1);
    }
    g = pgen(n);
    if (g == NULL) {
        printf("Bad grammar.\n");
        Py_Exit(1);
    }
    return g;
Guido van Rossum's avatar
Guido van Rossum committed
117 118
}

119 120 121 122
/* Can't happen in pgen */
PyObject*
PyErr_Occurred()
{
123
    return 0;
124 125
}

Guido van Rossum's avatar
Guido van Rossum committed
126
void
127
Py_FatalError(const char *msg)
Guido van Rossum's avatar
Guido van Rossum committed
128
{
129 130
    fprintf(stderr, "pgen: FATAL ERROR: %s\n", msg);
    Py_Exit(1);
Guido van Rossum's avatar
Guido van Rossum committed
131 132
}

133 134 135
/* No-nonsense my_readline() for tokenizer.c */

char *
136
PyOS_Readline(FILE *sys_stdin, FILE *sys_stdout, char *prompt)
137
{
138 139 140 141 142 143 144 145 146 147 148 149 150 151 152
    size_t n = 1000;
    char *p = (char *)PyMem_MALLOC(n);
    char *q;
    if (p == NULL)
        return NULL;
    fprintf(stderr, "%s", prompt);
    q = fgets(p, n, sys_stdin);
    if (q == NULL) {
        *p = '\0';
        return p;
    }
    n = strlen(p);
    if (n > 0 && p[n-1] != '\n')
        p[n-1] = '\n';
    return (char *)PyMem_REALLOC(p, n+1);
153
}
154

155 156 157 158
/* No-nonsense fgets */
char *
Py_UniversalNewlineFgets(char *buf, int n, FILE *stream, PyObject *fobj)
{
159
    return fgets(buf, n, stream);
160 161 162
}


163 164 165 166 167
#include <stdarg.h>

void
PySys_WriteStderr(const char *format, ...)
{
168
    va_list va;
169

170 171 172
    va_start(va, format);
    vfprintf(stderr, format, va);
    va_end(va);
173
}