aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'ebuildgen/filetypes/automake.py')
-rw-r--r--ebuildgen/filetypes/automake.py342
1 files changed, 342 insertions, 0 deletions
diff --git a/ebuildgen/filetypes/automake.py b/ebuildgen/filetypes/automake.py
new file mode 100644
index 0000000..c4ca432
--- /dev/null
+++ b/ebuildgen/filetypes/automake.py
@@ -0,0 +1,342 @@
+from ply import lex
+from ply import yacc
+import glob
+import os
+
+def scanamfile(amfile):
+ """Scan automake (.am) file
+
+ Returns ...
+ """
+ amfile = "\n" + amfile #Add \n so you can guess vars
+ tokens = (
+ "END",
+ "COL",
+ "EQ",
+ "PEQ",
+ "CVAR",
+ "MVAR",
+ "TEXT",
+ "ENDTAB",
+ "SPACE",
+ "IF",
+ "ELSE",
+ "ENDIF",
+ )
+
+ states = (
+ ("com", "exclusive"), #comment
+ ("var", "inclusive"),
+ ("if", "exclusive"),
+ )
+
+ def t_begin_com(t):
+ r"[ \t]*\#"
+ t.lexer.begin("com")
+
+ def t_com_other(t):
+ r"[^\\\n]+"
+ pass
+
+ def t_com_lit(t):
+ r"\\."
+ pass
+
+ def t_com_newline(t):
+ r".*\\\n"
+ t.lexer.lineno += 1
+ pass
+
+ def t_ifbegin(t):
+ #ugly hack to ensure that this is at the begining of the line and keep the newline token.
+ #PLY doesn't support the "^" beginning of line regexp :,(
+ r"\nif"
+ t.type = "END"
+ t.lexer.push_state("if")
+ return t
+
+ def t_if_IF(t):
+ #http://www.gnu.org/s/hello/manual/automake/Usage-of-Conditionals.html#Usage-of-Conditionals
+ r"[ \t]+[^ \n\t]*"
+ t.value = t.value.strip() #take the variable to test
+ t.lexer.pop_state()
+ return t
+
+ def t_ELSE(t):
+ r"\nelse"
+ return t
+
+ def t_ENDIF(t):
+ r"\nendif"
+ return t
+
+ def t_CVAR(t): #configure variable
+ r"@.*?@" #not greedy
+ return t
+
+ def t_MVAR(t): #makefile variable
+ r"\$\(.*?\)"
+ return t
+
+ def t_com_END(t):
+ r"\n"
+ t.lexer.begin("INITIAL")
+ t.lexer.lineno += 1
+ return t
+
+ def t_EQ(t):
+ r"[ \t]*=[ \t]*"
+ t.lexer.begin("var")
+ t.value = t.value.strip()
+ return t
+
+ def t_PEQ(t):
+ r"[ \t]*\+=[ \t]*"
+ t.lexer.begin("var")
+ t.value = t.value.strip()
+ return t
+
+ def t_contline(t):
+ r"\\\n"
+ t.lexer.lineno += 1
+ pass
+
+ def t_litteral(t):
+ r"\\."
+ t.value = t.value[1] #take the literal char
+ t.type = "TEXT"
+ return t
+
+ def t_COL(t):
+ r"[ \t]*:[ \t]*"
+ t.lexer.begin("var")
+ return t
+
+ def t_var_ENDTAB(t):
+ r"[ \t]*;[ \t]*"
+ return t
+
+ def t_ENDTAB(t):
+ r"[ \t]*\n\t[ \t]*"
+ t.lexer.lineno += 1
+ return t
+
+ def t_var_TEXT(t):
+ r"[^ #\n\t,\$@\\]+"
+ return t
+
+ def t_TEXT(t):
+ r"[^ \n\t:=\$@\\]+"
+ return t
+
+ def t_END(t):
+ r"[ \t]*\n"
+ t.lexer.lineno += t.value.count('\n')
+ t.lexer.begin('INITIAL')
+ return t
+
+ def t_var_SPACE(t):
+ r"[ \t]+"
+ return t
+
+ def t_space(t):
+ r"[ \t]"
+ pass
+
+ def t_var_special(t):
+ r"\$[^({]"
+ t.type = "TEXT"
+ return t
+
+ def t_ANY_error(t):
+ print("Illegal character '%s'" % t.value[0])
+ t.lexer.skip(1)
+
+ lexer = lex.lex()
+
+ #lexer.input(amfile)
+ #for tok in lexer:
+ # print(tok)
+
+ #YACC stuff begins here
+
+ def p_done(p):
+ "done : vars end"
+ p[0] = p[1]
+
+ def p_vars(p):
+ """
+ vars : vars end var
+ | end var
+ """
+ if len(p) == 4:
+ p[1][0].update(p[3][0])
+ p[1][2].update(p[3][2])
+ p[0] = [p[1][0], p[1][1] + p[3][1], p[1][2]]
+
+ else:
+ p[0] = p[2]
+
+ def p_if(p):
+ """
+ var : IF vars ENDIF
+ | IF vars ELSE vars ENDIF
+ """
+ if len(p) == 4:
+ p[0] = [{},[],{p[1]:p[2]}]
+
+ else:
+ p[0] = [{},[],{p[1]:p[2],"!"+p[1]:p[4]}]
+
+ def p_var(p):
+ """
+ var : textstr EQ textlst
+ | textstr EQ
+ | textstr PEQ textlst
+ """
+ if p[2] == "=":
+ if len(p) == 4:
+ p[0] = [{p[1]: p[3]},[],{}]
+ else:
+ p[0] = [{p[1]: []},[],{}]
+ else:
+ p[0] = [{},[[p[1], p[3]]],{}]
+
+ def p_textlst(p):
+ """
+ textlst : textlst spacestr textstr
+ | textstr
+ """
+ if len(p) == 4:
+ p[0] = p[1] + [p[3]]
+ else:
+ p[0] = [p[1]]
+
+ def p_teststr(p):
+ """
+ textstr : textstr TEXT
+ | textstr CVAR
+ | textstr MVAR
+ | TEXT
+ | CVAR
+ | MVAR
+ """
+ if len(p) == 3:
+ p[0] = p[1] + p[2]
+ else:
+ p[0] = p[1]
+
+ def p_space(p):
+ """
+ spacestr : spacestr SPACE
+ | SPACE
+ """
+ if len(p) == 3:
+ p[0] = p[1] + p[2]
+ else:
+ p[0] = p[1]
+
+ def p_end(p):
+ """
+ end : end END
+ | END
+ """
+
+ def p_error(p):
+ print("syntax error at '%s'" % p.type,p.value)
+ pass
+
+ yacc.yacc()
+
+ variables = yacc.parse(amfile)
+ return variables
+
+def initscan(amfile,iflst):
+ useflag_sources = {} #{source: [useflag, value]}
+ incflag_sources = {} #{source: [include flags]}
+ top_dir = os.path.split(amfile)[0] + "/"
+
+ def scan(amfile):
+ curdir = os.path.split(amfile)[0] + "/"
+ amlist = scanamfile(openfile(amfile))
+ #print(amfile)
+
+ def sources_to_scan(amlist,curdir):
+ incflags = []
+ sources = []
+ extra_sources = []
+ #perhaps use set() here to eliminate the possibilty of duplicates?
+ for variable in amlist[0]:
+ if variable.split("_")[-1] == "SOURCES":
+ if variable.split("_")[0] == "EXTRA":
+ extra_sources += amlist[0][variable]
+ else:
+ sources += amlist[0][variable]
+
+ if variable.split("_")[-1] == "LDADD":
+ for item in amlist[0][variable]:
+ if item[0] == "@" and item[-1] == "@":
+ for ifstate in iflst:
+ if item.strip("@") in ifstate[1]:
+ for file in ifstate[1][item.strip("@")]:
+ for src in extra_sources:
+ if file.split(".")[0] == src.split(".")[0]:
+ useflag_sources[curdir + src] = ifstate[0]
+ incflag_sources[curdir + src] = incflags
+
+ for src in extra_sources:
+ if item.split(".")[0] == src.split(".")[0]:
+ sources += [src]
+
+ if variable.split("_")[-1] == "CFLAGS" or variable == "DEFAULT_INCLUDES":
+ for item in amlist[0][variable]:
+ if item[:2] == "-I":
+ if item[2:] == "$(top_srcdir)" or item[2:] == "$(srcdir)":
+ incflags += [top_dir]
+ elif item[2] == "/":
+ incflags += [item[2:]]
+ else:
+ incflags += [curdir + item[2:]]
+
+ if not "DEFAULT_INCLUDES" in amlist[0]:
+ incflags += [curdir,top_dir]
+
+ if "SUBDIRS" in amlist[0]:
+ for dir in amlist[0]["SUBDIRS"]:
+ sources += scan(curdir + dir + "/Makefile.am")
+
+ for lst in amlist[1]:
+ if lst[0] == "SUBDIRS":
+ for dir in lst[1]:
+ sources += scan(curdir + dir + "/Makefile.am")
+
+ for ifstatement in amlist[2]:
+ #print(ifstatement)
+ for item in iflst:
+ if ifstatement.lstrip("!") in item[1]:
+ if ifstatement[0] == "!":
+ if item[1][ifstatement.lstrip("!")] == "false":
+ for src in sources_to_scan(amlist[2][ifstatement],curdir):
+ useflag_sources[src] = item[0]
+
+ elif item[1][ifstatement] == "true":
+ for src in sources_to_scan(amlist[2][ifstatement],curdir):
+ useflag_sources[src] = item[0]
+
+ #add filepath
+ dirsources = []
+ for source in sources:
+ if os.path.split(source)[0] == "":
+ dirsources += [curdir + source]
+ incflag_sources[curdir + source] = incflags
+ else:
+ dirsources += [source]
+
+ return dirsources
+
+ return sources_to_scan(amlist,curdir)
+ return scan(amfile),useflag_sources,incflag_sources
+
+def openfile(ofile):
+ with open(ofile, encoding="utf-8", errors="replace") as inputfile:
+ return inputfile.read()