def gen_func_cfgopen_low(obj): ''' write a function that initialize an object from configuration file Note: it loads configuration parameters only, it does not load previous data ''' objtp = obj.name objptr = obj.ptrname fread = "%scfgopen_low" % obj.fprefix fdesc = '''initialize members of %s from configuration file `cfg', or if unavailable, from default values ''' % objtp cfgdecl = "cfgdata_t *cfg" usrvars = obj.get_usrvars("cfg") fdecl = "int %s(%s *%s, %s%s)" % (fread, objtp, objptr, cfgdecl, usrvars[0]) cow = CCodeWriter() cow.begin_function(fread, fdecl, fdesc) cow.die_if("%s == NULL" % objptr, "null pointer to %s" % objtp, onerr = "goto ERR;") # read configuration file items = obj.sort_items(obj.items, "cfg") for it in items: it.cfgget_var(cow, obj.ptrname) cow.end_function("return 0;\nERR:\nreturn -1;", silence = ["cfg"]) return cow.prototype, cow.function
def gen_func_manifest(self): ''' write a function to present current data ''' cow = CCodeWriter() funcnm = "%smanifest" % (self.fprefix) fdecl = "void %s(%s *%s, FILE *fp, int arrmax)" % (funcnm, self.name, self.ptrname) cow.begin_function(funcnm, fdecl, "clear %s data" % self.name) for it in self.items: it.manifest_var(cow, self.ptrname) cow.end_function("", silence = "arrmax") return cow.prototype, cow.function
def gen_func_close(self): cow = CCodeWriter() usrs = self.get_usrvars("close") macroname = "%sclose" % self.fprefix funcnm = macroname + "_low" macro = "#define %s(%s%s) { %s(%s%s); free(%s); %s = NULL; }" % ( macroname, self.ptrname, usrs[1], funcnm, self.ptrname, usrs[1], self.ptrname, self.ptrname) fdecl = "void %s(%s *%s%s)" % (funcnm, self.name, self.ptrname, usrs[0]) cow.begin_function(funcnm, fdecl, "close a pointer to %s" % self.name, None if self.cmds["private"] else macro) # compute the longest variable calc_len = lambda it: len(it.decl.name)+2+len(self.ptrname) if ( it.decl and it.gtype in ("char *", "dynamic array") ) else 0 maxwid = max(calc_len(it) for it in self.items) if len(self.items) else 0 for it in self.items: it.close_var(cow, self.ptrname, maxwid) cow.addln("memset(%s, 0, sizeof(*%s));", self.ptrname, self.ptrname) cow.end_function("") return cow.prototype, cow.function
def gen_flags_def(self): tab = 4 offset = 2 cow = CCodeWriter() block = [] for it in self.items: if "flag" in it.cmds: flag = it.cmds["flag"] if not it.cmds["flagval"]: print "missing value for flag [%s]" % it.cmds["flag"] raise Exception bval = it.cmds["flagval"] cmt = it.cmds["desc"] cmt = "/* %s */" % cmt if cmt else "" # print flag, bval, cmt; raw_input() block += [("#define", flag, bval, cmt)] else: cow.dump_block(block, tab, offset) block = [] cow.dump_block(block, tab, offset) return cow.gets()
def gen_func_clear(self, f): ''' write a function for clearing data ''' cow = CCodeWriter() funcnm = "%sclear" % (self.folds[f].fprefix) fdecl = "void %s(%s *%s)" % (funcnm, self.name, self.ptrname) cow.begin_function(funcnm, fdecl, "clear %s data" % self.name + ("/" + f if len(f) else "")) # add fold prereq and validation self.folds[f].add_fold_tests(cow, funcnm, "") ## for f = "", we clear everything including contents in folds #items = self.folds[f].items if len(f) else self.items items = self.folds[f].items items = [it for it in items if it.cmds["clr"]] #print "fold: %s\nitems: %s" % (f, items) for it in items: it.clear_var(cow, self.ptrname) cow.end_function("") return cow.prototype, cow.function
def gen_func_binrw(self, f, rw): ''' write a wrapper function for reading/writing data in binary form ''' readwrite = "read" if rw == "r" else "write" cow = CCodeWriter() funcnm = "%s%sbin" % (self.folds[f].fprefix, readwrite) funcnm_ = funcnm + "_low" u1 = self.get_usrvars("bin", f) u2 = self.get_usrvars(rw+"b", f) usrs = [u1[0]+u2[0], u1[1]+u2[1]] #print "%s rw=%s usrs: %s" % (self, rw, usrs); raw_input() fdecl = "int %s(%s *%s, const char *fname, int %s%s)" % ( funcnm, self.name, self.ptrname, "ver" if rw == "w" else "*pver", usrs[0]) cow.begin_function(funcnm, fdecl, "%s %s data as binary" % (readwrite, self.name + ("/"+f if len(f) else "") ) ) self.folds[f].add_fold_tests(cow, funcnm, "0") cow.declare_var("FILE *fp") condf = '(fp = fopen(fname, "%sb")) == NULL' % rw cow.die_if(condf, r"cannot %s binary file [%%s]." % readwrite, "fname", onerr = "return -1;") # can only return -1 since fp == NULL cow.addln() # add checking bytes if rw == "r": cow.rb_checkbytes(); cow.declare_var("int ver") cow.rb_var("ver", "int") cow.addln("if (pver != NULL) *pver = ver;") else: cow.wb_checkbytes(); cow.wb_var("ver", "int") cow.addln() # call the actual low-level function cow.add_comment("call low level %s function for members" % readwrite) cow.declare_var("int i") cow.addln("i = %s(%s, fp, ver%s%s);", funcnm_, self.ptrname, ", endn" if rw == "r" else "", usrs[1]); cow.end_function("fclose(fp);\nreturn i;\nERR:\nfclose(fp);\nreturn -1;"); return cow.prototype, cow.function
def gen_func_binrw_low(self, f, rw): ''' write a function for reading/writing data in binary form low level functions have no overhead from file-opening, checking-bytes and thus can be recursively applied to member objects ''' readwrite = "read" if rw == "r" else "write" fprefix = self.folds[f].fprefix ptr = self.ptrname cow = CCodeWriter() funcnm = "%s%sbin_low" % (fprefix, readwrite) usrs = self.get_usrvars("bin", f)[0]+self.get_usrvars(rw+"b", f)[0] #print "low %s rw=%s usrs: %s" % (self, rw, usrs); raw_input() fdecl = "int %s(%s *%s, FILE *fp, int ver%s%s)" % ( funcnm, self.name, ptr, ", int endn" if rw == "r" else "", usrs) title = self.name + (("/%s" % f) if len(f) else "") cow.begin_function(funcnm, fdecl, "%s %s data as binary" % (readwrite, title)) callclear = "%sclear(%s);" % (fprefix, self.ptrname) cow.die_if("%s == NULL" % ptr, "passing null pointer to %s" % funcnm, onerr = "return -1;") if rw == "r": cow.add_comment("clear data before reading") cow.addln(callclear) cow.addln() # sort item according to $binprev items = self.sort_items(self.folds[f].items, "bin") for it in items: if it.pre: continue if it.cmds["fold"] != f: continue #print "%s" % it.cmds; raw_input() # additional variables to read/write xvars = it.cmds["fold_bin_add"] if xvars: # additional vars to the fold variables xvl = [s.strip() for s in xvars.split(",")] for xv in xvl: xit = self.var2item(xv) if not xit: raise Exception xit.rwb_var(cow, rw, xv) continue if not it.decl or it.isdummy: call = it.cmds[rw + "bcall"] if call: cow.addln(call) continue usr = it.cmds["usr"] varname = ("" if (usr != None and usr.endswith("tmp")) else self.ptrname+"->") + it.decl.name it.rwb_var(cow, rw, varname) cow.end_function("return 0;\nERR:\n%sreturn -1;" % ( callclear+"\n" if rw == "r" else ""), # clear data silence = ["ver"]) return cow.prototype, cow.function
def gen_func_cfgopen(obj): ''' write a function that returns an new object initialized from configuration file Note: it loads configuration parameters only, it does not load previous data ''' cfgopen = (obj.cmds["cfgopen"] != None) objtp = obj.name objptr = obj.ptrname fopen = "%scfgopen" % obj.fprefix fread = fopen + "_low" fdesc = '''return a pointer of an initialized %s if possible, initial values are taken from configuration file `cfg', otherwise default values are assumed ''' % objtp cfgdecl = "cfgdata_t *cfg" usrvars = obj.get_usrvars("cfg") fdecl = "%s *%s(%s%s)" % (obj.name, fopen, "const char *cfgname" if cfgopen else cfgdecl, usrvars[0]) cow = CCodeWriter() cow.begin_function(fopen, fdecl, fdesc) cow.declare_var("%s *%s" % (objtp, objptr), objptr) # open a configuration file if cfgopen: cow.add_comment("open configuration file") cow.declare_var("cfgdata_t *cfg", "cfg") scfg = "(cfg = cfg_open(cfgname)) == NULL" cow.die_if(scfg, "%s: cannot open config. file %%s." % objtp, "cfgname", onerr = "return NULL;") cow.addln() # allocate memory cow.add_comment("allocate memory for %s" % obj.name) sobj = "(%s = calloc(1, sizeof(*%s))) == NULL" % (objptr, objptr) cow.die_if(sobj, "no memory for %s (size %%u)" % obj.name, "(unsigned) sizeof(*%s)" % objptr); cow.addln() cow.add_comment("call low level function") s = "0 != %s(%s, cfg%s)" % (fread, objptr, usrvars[1]) ermsg = objtp + ": error while reading configuration file" onerr = "free(%s);\nreturn NULL;" % objptr if cfgopen: cow.die_if(s, ermsg + " %s", "cfgname", onerr = onerr) else: cow.die_if(s, ermsg, onerr = onerr) cow.addln() if cfgopen: cow.add_comment("close handle to configuration file") cow.addln("cfg_close(cfg);") cow.end_function("return %s;" % objptr) return cow.prototype, cow.function
def gen_decl(self): ''' write code for the object declaration ''' tab = 4 offset = 2 cow = CCodeWriter() cow.addln("typedef struct {") block = [] # block list for it in self.items: block = it.declare_var(cow, block, tab, offset) cow.dump_block(block, tab, offset) block = [] if not disabled(self.cmds["mpi"]): cow.addln("int mpi_rank, mpi_size;") cow.addln("#ifdef %s\nMPI_Comm mpi_comm;\n#endif\n", USE_MPI) cow.addln("} " + self.name + ";") return cow.gets()
def gen_func_mpitask(self, tag): ''' write a function to for mpi taks every node calls this function ''' cow = CCodeWriter() funcnm = self.fprefix+tag obj = self.name ptr = self.ptrname fdecl = "int %s(%s *%s)" % (funcnm, obj, ptr) cow.begin_function(funcnm, fdecl, "MPI %s for %s" % (tag, obj), pp = "#ifdef %s" % USE_MPI) cow.die_if(ptr+" == NULL", "null pointer %s to %s" % (ptr, obj), onerr = "goto ERR;") cow.die_if("%s->mpi_comm == %s && %s->mpi_size > 1" % (ptr, type2zero("MPI_Comm"), ptr), "null communicator: %s->mpi_comm" % (ptr), onerr = "goto ERR;") cow.addln() items = self.sort_items(self.items, tag) for it in items: it.mpitask_var(cow, tag, self.ptrname) cow.end_function("return 0;\nERR:\nreturn -1;") return cow.prototype, cow.function
def gen_func_initmpi(self): ''' write a function to initialize MPI every node calls this function ''' cow = CCodeWriter() funcnm = "%sinitmpi" % (self.fprefix) obj = self.name ptr = self.ptrname fdecl = "int %s(%s *%s, MPI_Comm comm)" % (funcnm, obj, ptr) cow.begin_function(funcnm, fdecl, "initialize MPI for %s" % obj, pp = "#ifdef %s" % USE_MPI) cow.die_if(ptr + " == NULL", "null pointer %s to %s" % (ptr, obj), onerr = "return -1;") cow.declare_var("int mpisize = 1;") cow.declare_var("int mpirank = 0;") # get size first cond = "comm != MPI_COMM_NULL" cow.begin_if(cond) cow.die_if("MPI_SUCCESS != MPI_Comm_size(comm, &mpisize)", "cannot even get MPI size") cow.end_if(cond) cond = "mpisize > 1" cow.begin_if(cond) cow.die_if("MPI_SUCCESS != MPI_Comm_rank(comm, &mpirank)", "cannot get MPI rank"); cow.end_if(cond) # bcast the structure cow.mpibcast("mpirank", "mpisize", ptr, 1, "*"+ptr, MASTERID, "comm") # assign MPI-rank and communicator # must be done after Bcast to avoid being overwritten cow.addln("%s->mpi_comm = comm;", ptr) cow.addln("%s->mpi_size = mpisize;", ptr) cow.addln("%s->mpi_rank = mpirank;", ptr) cow.addln() for it in self.items: it.initmpi_var(cow, self.ptrname) cow.addln("return 0;") cow.end_function("") return cow.prototype, cow.function