diff options
author | 2011-07-14 23:22:34 +0200 | |
---|---|---|
committer | 2011-07-14 23:22:34 +0200 | |
commit | 11cc610aee0455ba23c5a7182d599fcad523e9ca (patch) | |
tree | 4f565d570496658b805ebb36648071698622cd23 | |
parent | The autoconf parser now parser whole files (diff) | |
download | ebuildgen-11cc610aee0455ba23c5a7182d599fcad523e9ca.tar.gz ebuildgen-11cc610aee0455ba23c5a7182d599fcad523e9ca.tar.bz2 ebuildgen-11cc610aee0455ba23c5a7182d599fcad523e9ca.zip |
More work on autotools
-rw-r--r-- | TODO | 1 | ||||
-rw-r--r-- | filetypes/acif.py | 144 | ||||
-rw-r--r-- | filetypes/autoconf.py | 55 | ||||
-rw-r--r-- | filetypes/automake.py | 77 |
4 files changed, 264 insertions, 13 deletions
@@ -12,3 +12,4 @@ Handle zip,tar for unpacking Handle $(foo)_test = ... variable assingment Add more filetypes to search for in the implicid makefile ".c" search Have ply write the parser.out to different files for different filetypes so that is doesn't overwrite other parsers +Properly handle names of AC_ARG_WITH (convert stuff to underscores) diff --git a/filetypes/acif.py b/filetypes/acif.py new file mode 100644 index 0000000..3da4ecb --- /dev/null +++ b/filetypes/acif.py @@ -0,0 +1,144 @@ +from ply import lex +from ply import yacc + +def parseif(ifoptions): + optstr = "" + for option in ifoptions: + optstr += option + " " + + tokens = ( + "NOT", + "AND", + "OR", + "EQ", + "NEQ", + "NONZERO", + "SEMICOL", + "LBRAC", + "RPRAC", + "OPT", + "TEST", + ) + + def t_TEST(t): + r"test" + return t + + def t_AND(t): + r"(\-a|\&\&)" + return t + + def t_OR(t): + r"(\-o|\|\|)" + return t + + def t_EQ(t): + r"=" + return t + + def t_NEQ(t): + r"\!=" + return t + + def t_NOT(t): + r"\!" + return t + + def t_NONZERO(t): + r"\-n" + return t + + def t_SEMICOL(t): + r";" + pass + + def t_LBRAC(t): + r"\{" + return t + + def t_RPRAC(t): + r"\}" + return t + + def t_space(t): + r"[ \t\n]" + pass + + def t_quote(t): + r"[\"\']" + pass + + def t_OPT(t): + r"[^ \t\n;\"\']+" + return t + + def t_ANY_error(t): + print("Illegal character '%s'" % t.value[0],t.lexer.lineno) + t.lexer.skip(1) + + lexer = lex.lex() + + #lexer.input(optstr) + #for tok in lexer: + # print(tok) + + #YACC + #Add more cases! + + def p_exp(p): + """ + exp : NOT TEST expopt + | TEST expopt + """ + if len(p) == 4: + newlst = [] + while len(newlst) < len(p[3]): + if p[3][len(newlst)+1][0] == "!": + newresult = p[3][len(newlst)+1][1:] + else: + newresult = "!" + p[3][len(newlst)+1] + + newlst += [p[3][len(newlst)],newresult] + + p[0] = newlst + + else: + p[0] = p[2] + + def p_expopt(p): + """ + expopt : expopt AND expopt + | expopt OR expopt + """ + if p[2] == "-a": + p[0] = p[1] + p[3] + else: #come up with something better + p[0] = p[1] + p[3] + + def p_expopt2(p): + """ + expopt : OPT EQ OPT + | OPT NEQ OPT + | NONZERO OPT + | OPT + """ + if p[2] == "=": + varstr = p[1].split("$") + p[0] = [varstr[1],p[3][len(varstr[0]):]] + #[VARIABLEname,value to pass test] + + elif p[2] == "!=": + varstr = p[1].split("$") + p[0] = [varstr[1],"!" + p[3][len(varstr[0]):]] + + else: + varstr = p[len(p)-1].split("$")[1] + p[0] = [varstr, "!"] #req that the variable is nonzero to be True + + def p_error(p): + print("syntax error at '%s'" % p.type,p.value) + pass + + yacc.yacc() + return yacc.parse(optstr) + diff --git a/filetypes/autoconf.py b/filetypes/autoconf.py index 09bf87d..98555ce 100644 --- a/filetypes/autoconf.py +++ b/filetypes/autoconf.py @@ -188,6 +188,7 @@ def scanacfile(acfile): return t def t_TEXT(t): #most likely commands like "AM_INIT_AUTOMAKE" etc. + #Fix this so I can handle variables like the one above as that is NOT a text string r"([^ ;,\t\n\(\)]+|\([^() \t\n]*\))" return t @@ -352,10 +353,56 @@ def scanacfile(acfile): yacc.yacc() items = yacc.parse(acfile) - #for item in items: - # print(item) + return items + +from acif import parseif + +def output(inputlst): + variables = dict() + ifs = [] + for item in inputlst: + if item[0] == "AC_ARG_ENABLE": + name = convnames(item[1][0]) + if len(item[1]) == 2: + variables["enable_" + name] = [[],[]] + elif len(item[1]) == 3: + variables["enable_" + name] = [item[1][2],[]] + else: + variables["enable_" + name] = [item[1][2],item[1][3]] + + #remember to convert chars in the name of "item[1]" that is not + #alfanumeric char to underscores _ -file="configure.ac" + if item[0] == "AC_ARG_WITH": + name = convnames(item[1][0]) + if len(item[1]) == 2: + variables["with_" + name] = [[],[]] + elif len(item[1]) == 3: + variables["with_" + name] = [item[1][2],[]] + else: + variables["with_" + name] = [item[1][2],item[1][3]] + elif isinstance(item[0],list): #if statements + for variable in variables: + for pattern in item[0][1]: + if variable in pattern: + ifs += [parseif(item[0][1])] + elif "=" in item: + #print(item) + b = 0 + + #for variable in variables: + #print(variable) + #print(variables[variable]) + print(ifs) + +import re +def convnames(string): #strip none alfanumeric chars and replace them with "_" + string = string.strip("[]") #remove quotes + pattern = re.compile("\W") + newstr = re.sub(pattern, "_", string) + return newstr + +file="configure.in" with open(file, encoding="utf-8", errors="replace") as inputfile: - scanacfile(inputfile.read()) + output(scanacfile(inputfile.read())) diff --git a/filetypes/automake.py b/filetypes/automake.py index e9e31a2..1eaa765 100644 --- a/filetypes/automake.py +++ b/filetypes/automake.py @@ -18,11 +18,15 @@ def scanamfile(amfile): "TEXT", "ENDTAB", "SPACE", + "IF", + "ELSE", + "ENDIF", ) states = ( ("com", "exclusive"), #comment ("var", "inclusive"), + ("if", "exclusive"), ) def t_begin_com(t): @@ -42,6 +46,29 @@ def scanamfile(amfile): 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 t.value = t.value.strip("@") @@ -60,11 +87,13 @@ def scanamfile(amfile): 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): @@ -101,15 +130,19 @@ def scanamfile(amfile): return t def t_END(t): - r"[ \t]*\n+" + r"[ \t]*\n" t.lexer.lineno += t.value.count('\n') t.lexer.begin('INITIAL') return t - def t_SPACE(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" @@ -128,26 +161,46 @@ def scanamfile(amfile): #YACC stuff begins here def p_done(p): - "done : vars END" + "done : vars end" p[0] = p[1] def p_vars(p): """ - vars : vars END var - | END var + vars : vars end var + | end var """ if len(p) == 4: - p[1].update(p[3]) - p[0] = p[1] + 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 """ - p[0] = {p[1]:p[3]} + 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): """ @@ -183,6 +236,12 @@ def scanamfile(amfile): 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 @@ -192,7 +251,7 @@ def scanamfile(amfile): variables = yacc.parse(amfile) print(variables) -file="/usr/portage/distfiles/svn-src/moc/trunk/Makefile.am" +file="/usr/portage/distfiles/svn-src/moc/trunk/decoder_plugins/Makefile.am" with open(file, encoding="utf-8", errors="replace") as inputfile: scanamfile(inputfile.read()) |