# Part of the A-A-P GUI IDE: Aap project Activity class # Copyright (C) 2002-2003 Stichting NLnet Labs # Permission to copy and use this file is specified in the file COPYING. # If this file is missing you can find it here: http://www.a-a-p.org/COPYING from Activity import Activity from os import stat from sre import split import Navigator import os.path # TODO: Do this properly with gettext(). def _(x): return x class Makefile(Activity): """Makefile Activity.""" def open(self): item = Navigator.ActyItem(self.name, os.getcwd(), self, None) nav = Navigator.Navigator("Project", item) self.addNav(nav) makefile_items, makefile_topdir = makefile2items(self.name) if makefile_items: item.addTree(makefile_items, makefile_topdir, 0) self.modified = 0 def save(self): # Nothing to be done since Makefile support is read only. pass def getMenuText(): return _("Makefile"), _("View a Makefile") def create(topmodel): """Create a new activity: create a Makefile.""" name = topmodel.view.fileDialog(_("Enter name for new Makefile project")) if not name: return None # XXX: This is really ugly. if name[name.rfind('/')+1:] not in ["Makefile", "makefile", \ "GNUmakefile", "GNUMakefile"] \ and name[-3:] != ".mk": name = name + ".mk" if os.path.exists(name): print "Project's makefile '%s' already exist!" % name return None try: f = open(name, "w") except StandardError, e: print "Cannot create '%s': %s", (name, str(e)) return None try: f.write("# Makefile autogenerated. Please edit it before use.\n" + "CC = gcc\n" + "CFLAGS = -g -O2\n" + "CPPFLAGS = -I.\n" + "OBJS = myprog.o\n\n" + "myprog: $(OBJS)\n" + "\t$(CC) $(CFLAGS) -o myprog myprog.o\n" ) except StandardError, e: print "Cannot write to '%s': %s" % (name, str(e)) return None f.close() act = Makefile(name, topmodel) act.open() return act def canOpen(name, type): """Returns true if it's a Makefile.""" return os.path.isfile(name) and (type == "make" or name[-3:] == ".mk") files = {} def line2list(line, input, variables, expand_var = 1): """Splits all elements of a line including those which follow an escape sequence ('\\'). Adds all existing files to global 'files'.""" global files depsdict = {} while 1: # First line passed must not be null. if line == "": try: line = input.readline() if not line: # End of file. return depsdict except IOError, e: # TODO: Print file name. print "Cannot read file: %s" % str(e) return {} if line.find("#") > 0: # Skip comments line = line[0:line.find("#")] deps = split("([ \t]*)([^ \t\\\\]+)", line) deps = [dep.lstrip().rstrip() for dep in deps] for dep in deps: is_escaped = 0 if dep != "" and dep != "\\": # dep is "something\" (without space.) if dep[len(dep)-1] == "\\": deps[deps.find(dep)] = dep[-1:] is_escaped = 1 if dep[0] == "$" and expand_var == 1: dep = dep.replace("$(", "").replace(")", "") # Expand variables. try: depsdict[dep] = variables[dep] except KeyError: pass # Forget unknown variables. else: try: if stat(dep)[3] == 1: # Is an exisiting file. files[dep] = {} except OSError: pass depsdict[dep] = {} # "\" could be followed by some empty fields. if "\\" in deps or is_escaped: line = "" continue # There is an escaped line. else: break return depsdict def makefile2items(name): """Generates tow threes, VARS and TARGETS from Makefile. Really trivial parsing, doesn't work with really complex makefiles.""" global files try: input = file(name, "r") except IOError, e: print "Cannot open '%s': %s" % (name, str(e)) return {} items = {} variables = {} targets = {} while 1: try: line = input.readline() if not line: break except IOError, e: print "Cannot read '%s': %s" % (name, str(e)) return {} if line.find("#") >= 0: # Skip comments line = line[0:line.find("#")] # If line is empty, continue. if line.lstrip() == "": continue colon = line.find(":") equal = line.find("=") if not line[0].isspace() and (colon > 1 and (equal < 0 or equal > colon)): # Is a target try: [useless, target, depslist] = split("^([^:]+):[ \t]*", line) except ValueError: # Should never happen really, but avoids failures. print "Sorry, cannot parse this line:\n%s" % line continue if depslist: depsdict = line2list(depslist, input, variables) else: depsdict = {} # Also add objects without dependencies. if target[0] == "$": target = target.replace('$(', '').replace(')', '') targets[target] = depsdict continue if not line[0].isspace() and (equal > 1 and (colon < 0 or colon > equal)): # Is a variable try: [useless, varname, useless, varvalue, useless] = \ split("^([A-Za-z_][0-9A-Za-z_]+)([ \t]*\\+?=[ \t]*)(.*)$",\ line) except ValueError: # Should never happen really, but avoids failures. print "Sorry, cannot parse this line:\n%s" % line continue if variables.has_key(varname): newcontent = variables[varname] varvalues = line2list(varvalue, input, variables, 0) for varvalue in varvalues.keys(): newcontent[varvalue] = {} variables[varname] = newcontent else: if varvalue: variables[varname] = line2list(varvalue, input, variables) else: variables[varname] = {} if variables != {}: items["VARS"] = variables if targets != {}: items["TARGETS"] = targets # Insert FILES even if it's empty. items["FILES"] = files return items, os.getcwd() # vim: set sw=4 et sts=4 tw=79 fo+=l: