/*
\funcref{directive}{void directive ()}
    {}
    {}
    {error(), pushfile(), insert()}
    {lexer()}
    {directiv.c}
    {
        {\em directive()} is called from {\em lexer()} when a `\#' character is
        read in the input file. {\em directive()} does not expect to read the
        `\#' character. Three directives are recognized:

        \begin{itemize}

            \item {\bf \#} {\em [spaces]} {\bf include} {\em [spaces]} {\bf
            "}{\em filename}{\bf "}. When this directive is read, {\em
            pushfile()} is called to start processing the included file.

            Analogous to {\bf C}, an {\bf \#include} $<$...$>$ form is
            supported.

            \item {\bf \#} {\em [spaces]} {\bf define} {\em [spaces]} {\em name}
            {\em [spaces]} {\em [redefinition]}. When this directive is read,
            {\em insert()} is called to insert the definition in the symbol
            table. The defined {\em name} is passed to {\em insert()} as
            argument; the redefinition is stored in the lexical buffer {\em
            lexbuf}.

            \item {\bf \#\!} \ldots

            The line containing this directive is skipped. The directive is
            intended to be used on {\sc unix} platforms, where it can be used
            to execute an icmake script.

        \end{itemize}

        Other directives following the `\#' character lead to an error.
    }
*/

#include "icm-pp.h"

void directive ()
{
    register int
        imdir_used,
        index,
        ch;
    static char
        dirsep [2] = { DIRSEP, '\0' },
        idname [200];
    char
        filename [_MAX_PATH];

                                            /* directive is #! */
    if ((ch = fgetc (filestack [filesp].f)) == '!')
    {                                       /* skip while not \n and not EOF */
        while ((ch = fgetc (filestack [filesp].f)) != '\n' && ch != EOF)
            ;

        if (ch == '\n')                     /* last char was newline */
        {
            filestack [filesp].l++;         /* then increment line counter */
            fputc ('\n', outfile);          /* and empty line to output */
        }

        return;
    }
                                            /* not #!, but maybe '#  ' */
    while (ch == ' ' || ch == '\t')         /* skip all blanks */
        ch = fgetc (filestack [filesp].f);

    ungetc (ch, filestack [filesp].f);      /* push back next char, not ' ' */

    if (! fgets (lexbuf, 8, filestack [filesp].f))
        error ("%s: %d: bad preprocessor directive",
               filestack [filesp].n, filestack [filesp].l);

    if (! strncmp (lexbuf, "include", 7))
    {
        imdir_used = 0;                 /* assume include "..." form */
        while ( (ch = fgetc (filestack [filesp].f)) == ' ' ||
                ch == '\t'
              )
            ;
        if (ch != '\"' && ch != '<')
            error ("%s: %d: \" or < expected after #include directive",
                   filestack [filesp].n, filestack [filesp].l);
        if (ch == '<')                  /* include <...> form? */
            imdir_used++;
        index = 0;
        while ( (ch = fgetc (filestack [filesp].f)) != '\"' && ch != '>')
            if (ch == '\n' || ch == EOF)
                error ("%s: %d: unterminated name after #include directive",
                       filestack [filesp].n, filestack [filesp].l);
            else
                lexbuf [index++] = (char) ch;
        lexbuf [index] = '\0';
        while ( (ch = fgetc (filestack [filesp].f)) != '\n' &&
                ch != EOF)
            ;
        ungetc (ch, filestack [filesp].f);

        if (imdir_used)
        {
            strcpy (filename, imdir);
            strcat (filename, dirsep);
            strcat (filename, lexbuf);
            pushfile (filename);
        }
        else
            pushfile (lexbuf);
    }
    else if (! strncmp (lexbuf, "define", 6))
    {
        while ( (ch = fgetc (filestack [filesp].f)) == ' ' ||
                ch == '\t'
              )
            ;
        ungetc (ch, filestack [filesp].f);
        getident (idname);
        while ( (ch = fgetc (filestack [filesp].f)) == ' ' ||
                ch == '\t'
              )
            ;
        ungetc (ch, filestack [filesp].f);
        index = 0;
        while ( (ch = fgetc (filestack [filesp].f)) != '\n' &&
                ch != EOF
              )
            lexbuf [index++] = (char) ch;
        lexbuf [index] = '\0';
        ungetc (ch, filestack [filesp].f);
        insert (idname);
    }
    else
        error ("%s: %d: bad preprocessor directive",
               filestack [filesp].n, filestack [filesp].l);
}
