/****************************************************************************
 *
 * MODULE:       g.parser
 * AUTHOR(S):    Glynn Clements <glynn gclements.plus.com> (original
 *                 contributor)
 *               Bernhard Reiter <bernhard intevation.de>,
 *               Cedric Shock <cedricgrass shockfamily.net>,
 *               Hamish Bowman <hamish_b yahoo.com>,
 *               Paul Kelly <paul-grass stjohnspoint.co.uk>,
 *               Radim Blazek <radim.blazek gmail.com>
 * PURPOSE:
 * COPYRIGHT:    (C) 2001-2007, 2010-2011 by the GRASS Development Team
 *
 *               This program is free software under the GNU General Public
 *               License (>=v2). Read the file COPYING that comes with GRASS
 *               for details.
 *
 *****************************************************************************/

#include <stdlib.h>
#include <unistd.h>
#include <string.h>

#include <grass/glocale.h>

#include "proto.h"

int translate_output;

int main(int argc, char *argv[])
{
    char *progname;
    struct context ctx;
    const char *filename;
    int standard_output;
    int separator_nul;

    progname = argv[0];

    ctx.module = NULL;
    ctx.option = NULL;
    ctx.flag = NULL;
    ctx.first_option = NULL;
    ctx.first_flag = NULL;
    ctx.state = S_TOPLEVEL;

    standard_output = translate_output = separator_nul = FALSE;

    /* Detect request to get strings to translate from a file */
    /* It comes BEFORE the filename to completely avoid confusion with parser.c
     * behaviours */
    if (argc >= 2 && (strcmp(argv[1], "-t") == 0)) {
        /* Turn on translation output */
        translate_output = TRUE;
        argv++, argc--;
    }

    if (argc >= 2 && (strcmp(argv[1], "-s") == 0)) {
        /* write to stdout rather than re-invoking */
        standard_output = TRUE;
        argv++, argc--;
    }

    if (argc >= 2 && (strcmp(argv[1], "-n") == 0)) {
        /* write to stdout with NUL as separator */
        standard_output = TRUE;
        separator_nul = TRUE;
        argv++, argc--;
    }

    if ((argc < 2) ||
        ((strcmp(argv[1], "help") == 0) || (strcmp(argv[1], "-help") == 0) ||
         (strcmp(argv[1], "--help") == 0))) {
        fprintf(stderr, "%s: %s [-t] [-s] [-n] <filename> [<argument> ...]\n",
                _("Usage"), progname);
        exit(EXIT_FAILURE);
    }

    filename = argv[1];
    argv++, argc--;
    G_debug(2, "filename = %s", filename);

    ctx.fp = fopen(filename, "r");
    if (!ctx.fp) {
        perror(_("Unable to open script file"));
        exit(EXIT_FAILURE);
    }

    G_gisinit((char *)filename);

    for (ctx.line = 1;; ctx.line++) {
        char buff[4096];
        char *cmd, *arg;
        size_t line_size;

        if (!fgets(buff, sizeof(buff), ctx.fp))
            break;

        arg = strchr(buff, '\n');
        if (!arg) {
            fprintf(stderr, _("Line too long or missing newline at line %d\n"),
                    ctx.line);
            exit(EXIT_FAILURE);
        }
        *arg = '\0';

        line_size = strlen(buff);
        if (line_size > 2 && buff[0] == '#') {
            if (buff[1] == '%')
                cmd = buff + 2;
            else if (line_size > 3 && buff[1] == ' ' && buff[2] == '%')
                cmd = buff + 3;
            else
                continue;
        }
        else {
            continue;
        }

        G_chop(cmd);

        arg = strchr(cmd, ':');

        if (arg) {
            *(arg++) = '\0';
            G_strip(cmd);
            G_strip(arg);
        }

        switch (ctx.state) {
        case S_TOPLEVEL:
            parse_toplevel(&ctx, cmd);
            break;
        case S_MODULE:
            parse_module(&ctx, cmd, arg);
            break;
        case S_FLAG:
            parse_flag(&ctx, cmd, arg);
            break;
        case S_OPTION:
            parse_option(&ctx, cmd, arg);
            break;
        case S_RULES:
            parse_rule(&ctx, cmd, arg);
            break;
        }
    }

    if (fclose(ctx.fp) != 0) {
        perror(_("Error closing script file"));
        exit(EXIT_FAILURE);
    }

    /* Stop here successfully if all that was desired was output of text to
     * translate */
    /* Continuing from here would get argc and argv all wrong in G_parser. */
    if (translate_output)
        exit(EXIT_SUCCESS);

    if (G_parser(argc, argv))
        exit(EXIT_FAILURE);

    return standard_output ? print_options(&ctx, separator_nul ? '\0' : '\n')
                           : reinvoke_script(&ctx, filename);
}
