#!/usr/bin/python3
import re
import sys
debugPrint1=0
debugPrint3=0
debugPrint5=0
def quoteOrComment(matchobj):
    if(matchobj.group(1)):
        return " "
    elif(matchobj.group(2) or matchobj.group(3) or matchobj.group(4) or matchobj.group(5)):
        return matchobj.group()
    elif(matchobj.group(6)):
        sys.stderr.write("Unterminated Comment\n")
        return ""

def removeComments(s):
    removeBlocks = re.compile(r'(/\*.*?\*/)|(\".*?\")|(\'.*?\')|(\'.*)|(\".*)|(/\*.*)',flags=re.DOTALL)
    s=re.sub(removeBlocks, quoteOrComment ,s)
    return s 

#important is "DEFINE" case sensitive
#important get rid of trailing white space in group2
def define(macros,s):
    matchobj = re.match(r"^#\s*define\s+([a-zA-Z_][a-zA-Z_0-9]*)\s*(.*)\s*",s)
    if(matchobj):
        macros[matchobj.group(1)]=matchobj.group(2).rstrip()
    else:
       sys.stderr.write("Bad define macro\n")
    return macros

        
def badQuote(matchobj):
    if(matchobj.group(1)):
        return ""
    elif(matchobj.group(2)):
        return ""
    elif(matchobj.group(3) or matchobj.group(4)):
        sys.stderr.write("Bad quote\n")
    return ""

def normalLine(macros, s, p):
    reBlock = re.compile(r'(\".*?\")|(\'.*?\')|(\".*)|(\'.*)|([a-zA-Z_][a-zA-Z_0-9]*)|([ \t\r\f\v]*##[ \t\r\f\v]*)')
    matchobjs = re.finditer(reBlock,s)
    matchobj=None
    for match in matchobjs:
        matchobj = match
        break
    if(matchobj):
        original = s
        if(debugPrint5):
            print(s)
        string = matchobj.group()
        if(matchobj.group(5)):
            if(string in macros.keys()):
                string= macros[string]
            else:
                string =  matchobj.group(5)
        elif(matchobj.group(6)):
            string = ""
        else:
            string = matchobj.group()
        s = s[:matchobj.start()] + string + s[matchobj.end():]
        if(s!=original):
            s = s[:matchobj.start()] + normalLine(macros, s[matchobj.start():], 0)
        else:
            if(debugPrint5 and p):
                print("Index:" + str(matchobj.end()))
                print("first part of String:" + s[:matchobj.end()+1] + " second part Of String " + s[matchobj.end():])
            s = s[:matchobj.end()] + normalLine(macros, s[matchobj.end():], 0)
    if(p):
        print(s,end="")
    return s



def ifstatement(macros, curLine, lines, p):
    matchobj=re.match(r"^\s*#\s*ifdef\s+(.*)\s*", curLine)
    name = matchobj.group(1)
    inElse=0
    if(debugPrint3):
        print("IN if statement")
    if(debugPrint1):
        print("Name in if directive: " + name)
    if(name not in macros.keys()):
        inElse=1
        if(lines):
            curLine=lines.pop(0)
        else: 
            sys.stderr.write("missing #endif\n")
            return [macros, lines]
        while((re.match(r"^\s*#\s*else\s*$",curLine)==None) and (re.match(r"^\s*#\s*endif\s*$",curLine)==None)): 
            
            re.sub(r'(\".*?\")|(\'.*?\')|(\".*)|(\'.*)', badQuote, curLine)
            if(re.match(r"^\s*#\s*ifdef\s+[a-zA-Z_][a-zA-Z0-9_]*\s*$", curLine)):
                output = ifstatement(macros, curLine, lines, 0)
                macros= output[0]
                lines = output[1]
            if(lines):
                curLine=lines.pop(0)
            else:
                sys.stderr.write("missing #endif\n")
                return [macros, lines]
        if(re.match(r"^\s*#\s*endif\s*$",curLine)):
                return [macros, lines]
    if(lines):
        curLine=lines.pop(0)
    else: 
        sys.stderr.write("missing #endif\n")
        return [macros, lines]
    while((re.match(r"^\s*#\s*else\s*$",curLine)==None) and (re.match(r"^\s*#\s*endif\s*$",curLine)==None)):
        
        re.sub(r'(\".*?\")|(\'.*?\')|(\".*)|(\'.*)', badQuote, curLine)
        if(debugPrint1):
            print("IN WHILE LOOP:" + curLine)
        if(re.match(r"^\s*#\s*define\s+.*", curLine) and p):
            macros = define(macros, curLine)
        elif(re.match(r"^\s*#\s*ifdef\s+[a-zA-Z_][a-zA-Z0-9_]*\s*$", curLine)):
            output = ifstatement(macros, curLine, lines,p)
            macros= output[0]
            lines = output[1]
        elif(re.match(r"^\s*#.*",curLine) and p):
            sys.stderr.write("Unexpected direcative\n")
        else:
            normalLine(macros, curLine, p)
        if(lines):
            curLine= lines.pop(0)
        else:
            sys.stderr.write("line 94missing #endif\n")
            return [macros, lines]
    if(debugPrint3):
        print("RIGHT BEFORE ELSE STATEMENT")
    #if we reached the else statment
    if(re.match(r"^\s*#\s*else\s*$",curLine)):
        if(debugPrint3):
            print("AT ELSE STATEMENT")
        if(inElse):
            sys.stderr.write("extra else statement\n")
            return [macros, lines]
        else:
            if(debugPrint3):
                print("In useless else statement")
            if(lines):
                curLine=lines.pop(0)
            else: 
                sys.stderr.write("missing #endif\n")
                return [macros, lines]
            while(re.match(r"^\s*#\s*endif\s*",curLine)==None): 
                re.sub(r'(\".*?\")|(\'.*?\')|(\".*)|(\'.*)', badQuote, curLine)
                if(re.match(r"^\s*#\s*ifdef\s+[a-zA-Z_][a-zA-Z0-9_]*\s*$", curLine)):
                    output = ifstatement(macros, curLine, lines, 0)
                    macros= output[0]
                    lines = output[1]
                elif(re.match(r"^\s*#\s*else\s*$",curLine)):                        
                    sys.stderr.write("extra else statement\n")
                    return [macros, lines]
                if(lines):
                    curLine= lines.pop(0)
                else:
                    sys.stderr.write("missing #endif\n")
                    return [macros, lines]
    if(debugPrint1):
        print("At end of endif function:" + str(lines))
    return [macros, lines]




def overall(macros, s):
    s=removeComments(s)
    endInLine=0
    if(s):
        if(s[len(s)-1]=='\n'):
            endInLine=1
        lines=s.splitlines()
        if(debugPrint1):
            print("List of Lines:" + str(lines))
        for line in range(0, len(lines)):
            lines[line]+='\n'
        if(endInLine==0):
            lines[len(lines)-1]=lines[len(lines)-1][0:len(lines[len(lines)-1])-1]
    if(s):
        macros={}
        curLine= lines.pop(0)
    else:
        curLine=None
    while(curLine):
        re.sub(r'(\".*?\")|(\'.*?\')|(\".*)|(\'.*)', badQuote, curLine)
        if(debugPrint1):
            print("Current Line " + curLine)
        if(re.match(r"^\s*#\s*define\s+.*", curLine)):
            if(debugPrint1):
                print("We are about to define value")
            macros = define(macros, curLine)
        elif(re.match(r"^\s*#\s*ifdef\s+[a-zA-Z_][a-zA-Z0-9_]*\s*$", curLine)):
            output = ifstatement(macros, curLine, lines, 1)
            if(debugPrint1):
                print("Done with entering if statement")
            macros= output[0]
            lines = output[1]
        elif(re.match(r"^\s*#.*",curLine)):
            sys.stderr.write("Unexpected direcative\n")
        else:
            normalLine(macros, curLine,1)
        if(lines):
            curLine= lines.pop(0)
        else:
            curLine=None


def main():
    macros = {}
    inputString = sys.stdin.read()
    overall(macros, inputString)

if __name__=="__main__":
    main()
