//
// Copyright (C) 2013 LunarG, Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
//    Redistributions of source code must retain the above copyright
//    notice, this list of conditions and the following disclaimer.
//
//    Redistributions in binary form must reproduce the above
//    copyright notice, this list of conditions and the following
//    disclaimer in the documentation and/or other materials provided
//    with the distribution.
//
//    Neither the name of 3Dlabs Inc. Ltd. nor the names of its
//    contributors may be used to endorse or promote products derived
//    from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
/****************************************************************************\
Copyright (c) 2002, NVIDIA Corporation.

NVIDIA Corporation("NVIDIA") supplies this software to you in
consideration of your agreement to the following terms, and your use,
installation, modification or redistribution of this NVIDIA software
constitutes acceptance of these terms.  If you do not agree with these
terms, please do not use, install, modify or redistribute this NVIDIA
software.

In consideration of your agreement to abide by the following terms, and
subject to these terms, NVIDIA grants you a personal, non-exclusive
license, under NVIDIA's copyrights in this original NVIDIA software (the
"NVIDIA Software"), to use, reproduce, modify and redistribute the
NVIDIA Software, with or without modifications, in source and/or binary
forms; provided that if you redistribute the NVIDIA Software, you must
retain the copyright notice of NVIDIA, this notice and the following
text and disclaimers in all such redistributions of the NVIDIA Software.
Neither the name, trademarks, service marks nor logos of NVIDIA
Corporation may be used to endorse or promote products derived from the
NVIDIA Software without specific prior written permission from NVIDIA.
Except as expressly stated in this notice, no other rights or licenses
express or implied, are granted by NVIDIA herein, including but not
limited to any patent rights that may be infringed by your derivative
works or by other works in which the NVIDIA Software may be
incorporated. No hardware is licensed hereunder.

THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT
WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED,
INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE,
NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER
PRODUCTS.

IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT,
INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY
OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE
NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT,
TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
\****************************************************************************/

#ifndef PPCONTEXT_H
#define PPCONTEXT_H

#include <stack>
#include <unordered_map>
#include <sstream>

#include "../ParseHelper.h"

/* windows only pragma */
#ifdef _MSC_VER
    #pragma warning(disable : 4127)
#endif

namespace glslang {

class TPpToken {
public:
    TPpToken() { clear(); }
    void clear()
    {
        space = false;
        i64val = 0;
        loc.init();
        name[0] = 0;
    }

    // Used for comparing macro definitions, so checks what is relevant for that.
    bool operator==(const TPpToken& right)
    {
        return space == right.space &&
               ival == right.ival && dval == right.dval && i64val == right.i64val &&
               strncmp(name, right.name, MaxTokenLength) == 0;
    }
    bool operator!=(const TPpToken& right) { return ! operator==(right); }

    TSourceLoc loc;
    // True if a space (for white space or a removed comment) should also be
    // recognized, in front of the token returned:
    bool space;
    // Numeric value of the token:
    union {
        int ival;
        double dval;
        long long i64val;
    };
    // Text string of the token:
    char name[MaxTokenLength + 1];
};

class TStringAtomMap {
//
// Implementation is in PpAtom.cpp
//
// Maintain a bi-directional mapping between relevant preprocessor strings and
// "atoms" which a unique integers (small, contiguous, not hash-like) per string.
//
public:
    TStringAtomMap();

    // Map string -> atom.
    // Return 0 if no existing string.
    int getAtom(const char* s) const
    {
        auto it = atomMap.find(s);
        return it == atomMap.end() ? 0 : it->second;
    }

    // Map a new or existing string -> atom, inventing a new atom if necessary.
    int getAddAtom(const char* s)
    {
        int atom = getAtom(s);
        if (atom == 0) {
            atom = nextAtom++;
            addAtomFixed(s, atom);
        }
        return atom;
    }

    // Map atom -> string.
    const char* getString(int atom) const { return stringMap[atom]->c_str(); }

protected:
    TStringAtomMap(TStringAtomMap&);
    TStringAtomMap& operator=(TStringAtomMap&);

    TUnorderedMap<TString, int> atomMap;
    TVector<const TString*> stringMap;    // these point into the TString in atomMap
    int nextAtom;

    // Bad source characters can lead to bad atoms, so gracefully handle those by
    // pre-filling the table with them (to avoid if tests later).
    TString badToken;

    // Add bi-directional mappings:
    //  - string -> atom
    //  - atom -> string
    void addAtomFixed(const char* s, int atom)
    {
        auto it = atomMap.insert(std::pair<TString, int>(s, atom)).first;
        if (stringMap.size() < (size_t)atom + 1)
            stringMap.resize(atom + 100, &badToken);
        stringMap[atom] = &it->first;
    }
};

class TInputScanner;

enum MacroExpandResult {
    MacroExpandNotStarted, // macro not expanded, which might not be an error
    MacroExpandError,      // a clear error occurred while expanding, no expansion
    MacroExpandStarted,    // macro expansion process has started
    MacroExpandUndef       // macro is undefined and will be expanded
};

// This class is the result of turning a huge pile of C code communicating through globals
// into a class.  This was done to allowing instancing to attain thread safety.
// Don't expect too much in terms of OO design.
class TPpContext {
public:
    TPpContext(TParseContextBase&, const std::string& rootFileName, TShader::Includer&);
    virtual ~TPpContext();

    void setPreamble(const char* preamble, size_t length);

    int tokenize(TPpToken& ppToken);
    int tokenPaste(int token, TPpToken&);

    class tInput {
    public:
        tInput(TPpContext* p) : done(false), pp(p) { }
        virtual ~tInput() { }

        virtual int scan(TPpToken*) = 0;
        virtual int getch() = 0;
        virtual void ungetch() = 0;
        virtual bool peekPasting() { return false; }          // true when about to see ##
        virtual bool endOfReplacementList() { return false; } // true when at the end of a macro replacement list (RHS of #define)
        virtual bool isMacroInput() { return false; }

        // Will be called when we start reading tokens from this instance
        virtual void notifyActivated() {}
        // Will be called when we do not read tokens from this instance anymore
        virtual void notifyDeleted() {}
    protected:
        bool done;
        TPpContext* pp;
    };

    void setInput(TInputScanner& input, bool versionWillBeError);

    void pushInput(tInput* in)
    {
        inputStack.push_back(in);
        in->notifyActivated();
    }
    void popInput()
    {
        inputStack.back()->notifyDeleted();
        delete inputStack.back();
        inputStack.pop_back();
    }

    //
    // From PpTokens.cpp
    //

    class TokenStream {
    public:
        TokenStream() : current(0) { }

        void putToken(int token, TPpToken* ppToken);
        int getToken(TParseContextBase&, TPpToken*);
        bool atEnd() { return current >= data.size(); }
        bool peekTokenizedPasting(bool lastTokenPastes);
        bool peekUntokenizedPasting();
        void reset() { current = 0; }

    protected:
        void putSubtoken(char);
        int getSubtoken();
        void ungetSubtoken();

        TVector<unsigned char> data;
        size_t current;
    };

    //
    // From Pp.cpp
    //

    struct MacroSymbol {
        MacroSymbol() : functionLike(0), busy(0), undef(0) { }
        TVector<int> args;
        TokenStream body;
        unsigned functionLike : 1;  // 0 means object-like, 1 means function-like
        unsigned busy         : 1;
        unsigned undef        : 1;
    };

    typedef TMap<int, MacroSymbol> TSymbolMap;
    TSymbolMap macroDefs;  // map atoms to macro definitions
    MacroSymbol* lookupMacroDef(int atom)
    {
        auto existingMacroIt = macroDefs.find(atom);
        return (existingMacroIt == macroDefs.end()) ? nullptr : &(existingMacroIt->second);
    }
    void addMacroDef(int atom, MacroSymbol& macroDef) { macroDefs[atom] = macroDef; }

protected:
    TPpContext(TPpContext&);
    TPpContext& operator=(TPpContext&);

    TStringAtomMap atomStrings;
    char*   preamble;               // string to parse, all before line 1 of string 0, it is 0 if no preamble
    int     preambleLength;
    char**  strings;                // official strings of shader, starting a string 0 line 1
    size_t* lengths;
    int     numStrings;             // how many official strings there are
    int     currentString;          // which string we're currently parsing  (-1 for preamble)

    // Scanner data:
    int previous_token;
    TParseContextBase& parseContext;

    // Get the next token from *stack* of input sources, popping input sources
    // that are out of tokens, down until an input source is found that has a token.
    // Return EndOfInput when there are no more tokens to be found by doing this.
    int scanToken(TPpToken* ppToken)
    {
        int token = EndOfInput;

        while (! inputStack.empty()) {
            token = inputStack.back()->scan(ppToken);
            if (token != EndOfInput || inputStack.empty())
                break;
            popInput();
        }

        return token;
    }
    int  getChar() { return inputStack.back()->getch(); }
    void ungetChar() { inputStack.back()->ungetch(); }
    bool peekPasting() { return !inputStack.empty() && inputStack.back()->peekPasting(); }
    bool endOfReplacementList() { return inputStack.empty() || inputStack.back()->endOfReplacementList(); }
    bool isMacroInput() { return inputStack.size() > 0 && inputStack.back()->isMacroInput(); }

    static const int maxIfNesting = 65;

    int ifdepth;                  // current #if-#else-#endif nesting in the cpp.c file (pre-processor)
    bool elseSeen[maxIfNesting];  // Keep a track of whether an else has been seen at a particular depth
    int elsetracker;              // #if-#else and #endif constructs...Counter.

    class tMacroInput : public tInput {
    public:
        tMacroInput(TPpContext* pp) : tInput(pp), prepaste(false), postpaste(false) { }
        virtual ~tMacroInput()
        {
            for (size_t i = 0; i < args.size(); ++i)
                delete args[i];
            for (size_t i = 0; i < expandedArgs.size(); ++i)
                delete expandedArgs[i];
        }

        virtual int scan(TPpToken*) override;
        virtual int getch() override { assert(0); return EndOfInput; }
        virtual void ungetch() override { assert(0); }
        bool peekPasting() override { return prepaste; }
        bool endOfReplacementList() override { return mac->body.atEnd(); }
        bool isMacroInput() override { return true; }

        MacroSymbol *mac;
        TVector<TokenStream*> args;
        TVector<TokenStream*> expandedArgs;

    protected:
        bool prepaste;         // true if we are just before ##
        bool postpaste;        // true if we are right after ##
    };

    class tMarkerInput : public tInput {
    public:
        tMarkerInput(TPpContext* pp) : tInput(pp) { }
        virtual int scan(TPpToken*) override
        {
            if (done)
                return EndOfInput;
            done = true;

            return marker;
        }
        virtual int getch() override { assert(0); return EndOfInput; }
        virtual void ungetch() override { assert(0); }
        static const int marker = -3;
    };

    class tZeroInput : public tInput {
    public:
        tZeroInput(TPpContext* pp) : tInput(pp) { }
        virtual int scan(TPpToken*) override;
        virtual int getch() override { assert(0); return EndOfInput; }
        virtual void ungetch() override { assert(0); }
    };

    std::vector<tInput*> inputStack;
    bool errorOnVersion;
    bool versionSeen;

    //
    // from Pp.cpp
    //

    // Used to obtain #include content.
    TShader::Includer& includer;

    int CPPdefine(TPpToken * ppToken);
    int CPPundef(TPpToken * ppToken);
    int CPPelse(int matchelse, TPpToken * ppToken);
    int extraTokenCheck(int atom, TPpToken* ppToken, int token);
    int eval(int token, int precedence, bool shortCircuit, int& res, bool& err, TPpToken * ppToken);
    int evalToToken(int token, bool shortCircuit, int& res, bool& err, TPpToken * ppToken);
    int CPPif (TPpToken * ppToken);
    int CPPifdef(int defined, TPpToken * ppToken);
    int CPPinclude(TPpToken * ppToken);
    int CPPline(TPpToken * ppToken);
    int CPPerror(TPpToken * ppToken);
    int CPPpragma(TPpToken * ppToken);
    int CPPversion(TPpToken * ppToken);
    int CPPextension(TPpToken * ppToken);
    int readCPPline(TPpToken * ppToken);
    int scanHeaderName(TPpToken* ppToken, char delimit);
    TokenStream* PrescanMacroArg(TokenStream&, TPpToken*, bool newLineOkay);
    MacroExpandResult MacroExpand(TPpToken* ppToken, bool expandUndef, bool newLineOkay);

    //
    // From PpTokens.cpp
    //
    void pushTokenStreamInput(TokenStream&, bool pasting = false);
    void UngetToken(int token, TPpToken*);

    class tTokenInput : public tInput {
    public:
        tTokenInput(TPpContext* pp, TokenStream* t, bool prepasting) : tInput(pp), tokens(t), lastTokenPastes(prepasting) { }
        virtual int scan(TPpToken *ppToken) override { return tokens->getToken(pp->parseContext, ppToken); }
        virtual int getch() override { assert(0); return EndOfInput; }
        virtual void ungetch() override { assert(0); }
        virtual bool peekPasting() override { return tokens->peekTokenizedPasting(lastTokenPastes); }
    protected:
        TokenStream* tokens;
        bool lastTokenPastes;     // true if the last token in the input is to be pasted, rather than consumed as a token
    };

    class tUngotTokenInput : public tInput {
    public:
        tUngotTokenInput(TPpContext* pp, int t, TPpToken* p) : tInput(pp), token(t), lval(*p) { }
        virtual int scan(TPpToken *) override;
        virtual int getch() override { assert(0); return EndOfInput; }
        virtual void ungetch() override { assert(0); }
    protected:
        int token;
        TPpToken lval;
    };

    //
    // From PpScanner.cpp
    //
    class tStringInput : public tInput {
    public:
        tStringInput(TPpContext* pp, TInputScanner& i) : tInput(pp), input(&i) { }
        virtual int scan(TPpToken*) override;

        // Scanner used to get source stream characters.
        //  - Escaped newlines are handled here, invisibly to the caller.
        //  - All forms of newline are handled, and turned into just a '\n'.
        int getch() override
        {
            int ch = input->get();

            if (ch == '\\') {
                // Move past escaped newlines, as many as sequentially exist
                do {
                    if (input->peek() == '\r' || input->peek() == '\n') {
                        bool allowed = pp->parseContext.lineContinuationCheck(input->getSourceLoc(), pp->inComment);
                        if (! allowed && pp->inComment)
                            return '\\';

                        // escape one newline now
                        ch = input->get();
                        int nextch = input->get();
                        if (ch == '\r' && nextch == '\n')
                            ch = input->get();
                        else
                            ch = nextch;
                    } else
                        return '\\';
                } while (ch == '\\');
            }

            // handle any non-escaped newline
            if (ch == '\r' || ch == '\n') {
                if (ch == '\r' && input->peek() == '\n')
                    input->get();
                return '\n';
            }

            return ch;
        }

        // Scanner used to backup the source stream characters.  Newlines are
        // handled here, invisibly to the caller, meaning have to undo exactly
        // what getch() above does (e.g., don't leave things in the middle of a
        // sequence of escaped newlines).
        void ungetch() override
        {
            input->unget();

            do {
                int ch = input->peek();
                if (ch == '\r' || ch == '\n') {
                    if (ch == '\n') {
                        // correct for two-character newline
                        input->unget();
                        if (input->peek() != '\r')
                            input->get();
                    }
                    // now in front of a complete newline, move past an escape character
                    input->unget();
                    if (input->peek() == '\\')
                        input->unget();
                    else {
                        input->get();
                        break;
                    }
                } else
                    break;
            } while (true);
        }

    protected:
        TInputScanner* input;
    };

    // Holds a reference to included file data, as well as a
    // prologue and an epilogue string. This can be scanned using the tInput
    // interface and acts as a single source string.
    class TokenizableIncludeFile : public tInput {
    public:
        // Copies prologue and epilogue. The includedFile must remain valid
        // until this TokenizableIncludeFile is no longer used.
        TokenizableIncludeFile(const TSourceLoc& startLoc,
                          const std::string& prologue,
                          TShader::Includer::IncludeResult* includedFile,
                          const std::string& epilogue,
                          TPpContext* pp)
            : tInput(pp),
              prologue_(prologue),
              epilogue_(epilogue),
              includedFile_(includedFile),
              scanner(3, strings, lengths, names, 0, 0, true),
              prevScanner(nullptr),
              stringInput(pp, scanner)
        {
              strings[0] = prologue_.data();
              strings[1] = includedFile_->headerData;
              strings[2] = epilogue_.data();

              lengths[0] = prologue_.size();
              lengths[1] = includedFile_->headerLength;
              lengths[2] = epilogue_.size();

              scanner.setLine(startLoc.line);
              scanner.setString(startLoc.string);

              scanner.setFile(startLoc.name, 0);
              scanner.setFile(startLoc.name, 1);
              scanner.setFile(startLoc.name, 2);
        }

        // tInput methods:
        int scan(TPpToken* t) override { return stringInput.scan(t); }
        int getch() override { return stringInput.getch(); }
        void ungetch() override { stringInput.ungetch(); }

        void notifyActivated() override
        {
            prevScanner = pp->parseContext.getScanner();
            pp->parseContext.setScanner(&scanner);
            pp->push_include(includedFile_);
        }

        void notifyDeleted() override
        {
            pp->parseContext.setScanner(prevScanner);
            pp->pop_include();
        }

    private:
        TokenizableIncludeFile& operator=(const TokenizableIncludeFile&);

        // Stores the prologue for this string.
        const std::string prologue_;

        // Stores the epilogue for this string.
        const std::string epilogue_;

        // Points to the IncludeResult that this TokenizableIncludeFile represents.
        TShader::Includer::IncludeResult* includedFile_;

        // Will point to prologue_, includedFile_->headerData and epilogue_
        // This is passed to scanner constructor.
        // These do not own the storage and it must remain valid until this
        // object has been destroyed.
        const char* strings[3];
        // Length of str_, passed to scanner constructor.
        size_t lengths[3];
        // String names
        const char* names[3];
        // Scans over str_.
        TInputScanner scanner;
        // The previous effective scanner before the scanner in this instance
        // has been activated.
        TInputScanner* prevScanner;
        // Delegate object implementing the tInput interface.
        tStringInput stringInput;
    };

    int ScanFromString(char* s);
    void missingEndifCheck();
    int lFloatConst(int len, int ch, TPpToken* ppToken);
    int characterLiteral(TPpToken* ppToken);

    void push_include(TShader::Includer::IncludeResult* result)
    {
        currentSourceFile = result->headerName;
        includeStack.push(result);
    }

    void pop_include()
    {
        TShader::Includer::IncludeResult* include = includeStack.top();
        includeStack.pop();
        includer.releaseInclude(include);
        if (includeStack.empty()) {
            currentSourceFile = rootFileName;
        } else {
            currentSourceFile = includeStack.top()->headerName;
        }
    }

    bool inComment;
    std::string rootFileName;
    std::stack<TShader::Includer::IncludeResult*> includeStack;
    std::string currentSourceFile;

    std::istringstream strtodStream;
};

} // end namespace glslang

#endif  // PPCONTEXT_H
