def _xsplit(st):
"""Tao list cac terminal/guard, bo qua &,|,!,(,)
Chi tra ve cac list chua co trong danh sach __guards ma thoi
"""
## last modify: Ky Anh, 2003/12/27
## : use global __guards
global __guards
for ops in ['&', '(', ')', '!', '|', ',', ' ']:
st = string.replace(st, ops, ':')
tmp = []
for ops in string.split(st, ':'):
if (ops != '') and (not ops in __guards):
tmp.append(ops)
__guards.extend(tmp)
__use(tmp,0)
def _do_global():
## add, Ky Anh, 2003/12/27
## _force_
## _gonly_
## _kins_nopre
## _kins_nopost
## _kins_debug
## _kins_destdir
## jobnames ## list of job (<kins> files)
## __guards ## list of guard in DTX files
## add, Ky Anh, 2003/12/27
## NO ## list of NO-equivalent (0, No, NO, etc.)
## __block_ops ## list of operators in a DTX guard (block)
## __kins_vars ## list of global kins variables
## __global_kins_vars ## kins variables that are also the global
## variables in this program
## __no_skip_vars ## variables appear in the third part of |$gen|
## command; these variables arenot the <test>
## __alpha_options ## this DTX options will always be set to 1
## __beta_options ## - 0
## _tex_ ## output as the INS file
global\
_force_,\
_gonly_,\
_kins_nopre,\
_kins_nopost,\
_kins_debug,\
_kins_destdir,\
jobnames,\
__guards,\
NO,\
__block_ops,\
__kins_vars,\
__global_kins_vars,\
__no_skip_vars,\
_tex_,\
_kins_pre_def,\
_kins_pos_def
## __alpha_options,\
## __beta_options
## initialize the global variables
## these variable can be exported, i.e.,
## we can use `--exec cmd' at command line.
_kins_nopre = '0'
_kins_nopost = '0'
_kins_debug = '0'
_kins_destdir = '.'
__kins_vars = ["nopre", "nopost", "destdir", "debug"]
_kins_pre_def = "%% This file was generate\n\
%% \tfrom the file `$source'\n\
%% \twith option `$option'\n\
%% GenDate: $date\n\
%% Generator: $generator\n"
_kins_pos_def = "%% End of file `$dest'"
## init the <special> guards
## we neednot do this, because if a guard appears in a DTX file
## it is recognize by _xsplit and then set the value by __use
## see the defintionof _xplist for more details
## __use(__alpha_options + __beta_options)
def _xstrip(options, debug=0):
"""Tach ma tu file DTX voi options"""
global __ilines, __output
_use(options, 1)
__output = []
__level = 0
__prints = [1]
if debug: print "%s" % ("=" * 72),
for weapon in __ilines:
print_code = 0
if re_begin.match(weapon):
__level = __level + 1
if __prints[__level - 1]: # previous block
current_bblock = re_begin.match(weapon).group(1)
exec("print_code=%s" % _translate(current_bblock))
__prints.append(int(print_code))
if debug: print "\nlevel%2d %s *%s -> "\
% (__level,__prints,re_begin.match(weapon).group(1)),
elif re_end.match(weapon):
__level = __level - 1
if __level < 0: break
__prints.pop()
if debug: print "\nlevel%2d %s /%s -> "\
% (__level,__prints,re_end.match(weapon).group(1)),
elif re_sblock.match(weapon): #
if __prints[__level]:
current_bblock = re_sblock.match(weapon).group(1)
exec("print_code=%s" % _translate(current_bblock))
if debug: print "\nlevel%2d %s %s -> "\
% (__level,__prints,re_sblock.match(weapon).group(1)),
if print_code:
if debug: sys.stdout.write('s')
else: __output.append(re_sblock.match(weapon).group(2))
if debug:
print "\nlevel%2d %s -> " % (__level,__prints),
elif re_code.match(weapon):
if __prints[__level]:
if debug: sys.stdout.write('n')
else: __output.append(weapon)
if __level:
print \
"\nThe blocks of your DTX file donot balance.\n\
To debug, use <docstrip> with `--debug' option."
if debug: print "\n%s" % ("=" * 72)
_use(options, 0) # reset options' value to 0
def _readkins(filename):
## add, Ky Anh, 2003/12/25
"""Read a KINS file, remove the comment line, and strip the lines.
This function returns a LIST of KINS lines."""
mykinslines = []
f = open(filename, 'r')
iline = f.readline()
while iline:
iline = re_com.split(iline)[0]
iline = string.strip(iline)
if re_eof.match(iline):
if re_eof.match(iline).group(1) == '1':
break ## reach END OF FILE
elif iline:
mykinslines.append(iline)
iline = f.readline()
f.close()
return mykinslines
def _dokins(filename):
"""Excute the KINS code. The original name is |_readkins|; this version
wasnot support |$import|. To do |$import|, a new function |_readkins| was
added, and this function is now named |_dokins|."""
global _kins_pre, _kins_post, kins_lines, _kins_pre_def, _kins_pos_def
kins_lines = []
__imported = [] # list of imported files
while kins_lines:
iline = kins_lines.pop(0)
## :: = $if
if re_if.match(iline):
if_value = 0
__iflevel = __iflevel + 1
if in_if[__iflevel - 1]:
var_name = re_if.match(iline).group(1)
if re_kasg.match(var_name):
var_value = re_kasg.match(var_name).group(2)
var_name = re_kasg.match(var_name).group(1)
try:
if var_name in __kins_vars:
exec("tmp_value=_kins_%s" % var_name)
else:
exec("tmp_value=_gen_%s" % var_name)
if var_value == tmp_value:
if_value = 1
except NameError: pass
in_if.append(if_value)
## :: = $elif
elif re_elif.match(iline):
__iflevel = __iflevel - 1
iline = "$if%s" % iline[5:]
kins_lines.insert(0, iline)
## :: = $else
elif iline == "$else":
in_if[__iflevel] = 1 - in_if[__iflevel]
## :: = $enif
elif iline == "$enif":
__iflevel = __iflevel - 1
if __iflevel < 0:
sys.stderr.write(\
"\nerror: to much $enif. The program is going to stop.\n")
sys.exit(1)
else:
in_if.pop()
if __iflevel == 0:
kins_lines[0:0], __ifcont = __ifcont, []
elif __iflevel:
if in_if[__iflevel]:
__ifcont.append(iline)
## :: = pre, post
elif iline == "$pre": _kins_pre, in_pre = "", 1
elif iline == "$post": _kins_post, in_post = "", 1
elif iline == "$enpre": in_pre = 0
elif iline == "$enpost": in_post = 0
## ## :: = $(.+)
## elif re_expand.match(iline):
## var_name = re_expand.match(iline).group(1)
## :: = $<<<<
elif re_exec.match(iline):
try:
exec(re_exec.match(iline).group(1))
except:
sys.stderr.write("E")
## :: = if in_pre, in_post
## hai do`ng sau pha?i dde^? sau bo^'n do`ng tre^n
elif in_pre: _kins_pre = _kins_pre + iline + '\n'
elif in_post: _kins_post = _kins_post + iline + '\n'
## :: = $from
elif re_from.match(iline): # from macro
_kins_source = re_from.search(iline).group(1)
_readsource(_kins_source)
sys.stderr.write('_')
## :: = $import
elif re_import.match(iline):
_i_file = re_import.match(iline).group(1)
if not _i_file in __imported:
__imported.append(_i_file)
if not string.lower(_i_file[-5:]) == ".kins":
_i_file = _i_file + ".kins"
kins_lines[0:0] = _readkins(_i_file)
sys.stderr.write('=')
else:
sys.stderr.write('*')
## :: = assign
elif re_asg.match(iline):
var_name = re_asg.match(iline).group(1)
var_value= re_asg.match(iline).group(2)
## :: = = $docstrip
if var_name == 'docstrip': #
if SELF_VER < int(var_value):
sys.stderr.write(\
"need docstrip %d or higher. Current docstrip's version: %d.\n"\
% (int(var_value), SELF_VER))
return
## :: = = global kins variables
elif var_name in __global_kins_vars:
exec('global _kins_%s\n_kins_%s="""%s"""'\
% (var_name, var_name, var_value))
## :: = = other kins variables
else:
if not var_name in __kins_vars:
__kins_vars.append(var_name)
exec('_kins_%s="""%s"""' % (var_name,var_value))
if var_name == 'source': _readsource(_kins_source)
## :: = $local
elif re_local.match(iline):
zzz = re_local.match(iline).group(1)
if re_kasg.match(zzz):
var_name = re_kasg.match(zzz).group(1)
var_value = re_kasg.match(zzz).group(2)
exec('_gen_%s="""%s"""' % (var_name,var_value))
## :: = $gen
elif re_gen.match(iline): # gen macro
gen_des = re_gen.match(iline).group(1)
if (not _gonly_) or (only_files.search(gen_des)):
gen_opt = re_gen.match(iline).group(2)
## neu $gen co them tham so thu ba
## tham so nay phai de trong ngoac: (.+)
kins_skip = 0
_gen_append = '0' # <initial value must be '0'>
_gen_nopre = _kins_nopre # get the global value
_gen_nopost = _kins_nopost # as the initialization
_gen_destdir = _kins_destdir# add 2003/12/10
_gen_debug = _kins_debug #
if re_gen.search(iline).group(3) != "":
gen_optlist = string.split(\
re_gen.search(iline).group(3)[1:-1],',')
for item in gen_optlist:
item = string.strip(item)
if item == "append": _gen_append = '1'
elif item == "nopost": _gen_nopost = '1'
elif item == "nopre" : _gen_nopre = '1'
else:
zzz = re_kasg.match(item)
if zzz:
var_name = zzz.group(1)
var_value= str(zzz.group(2))
if var_name in __no_skip_vars:
exec('_gen_%s="""%s"""' % (var_name,var_value))
else:
try:
if var_name in __kins_vars:
exec("tmp_value=_kins_%s" % var_name)
else:
exec("tmp_value=_gen_%s" % var_name)
if not var_value == tmp_value:
kins_skip = 1
break # break the FOR loop
## donot mention other check
except NameError:
exec('_gen_%s="""%s"""' % (var_name,var_value))
if kins_skip:
sys.stderr.write('o')
else:
gen_des = "%s/%s" % (_gen_destdir, gen_des)
_gen(gen_des,gen_opt,\
_gen_append,\
_gen_nopre,_gen_nopost,\
_kins_source, _gen_debug)
else:
sys.stderr.write('o')
## :: = anything else
else: pass
if __iflevel != 0:
sys.stderr.write("\nerror: missing $if or $enif\n")
def _readsource(source):
## last modify: Ky Anh, 2003/12/27
## : according to changes of _xsplit
global __ilines,\
src_time
__ilines = []
src_time = os.stat(source)[stat.ST_MTIME]
f = open(source, 'r')
iline = f.readline() #
while iline:
if re_code.match(iline): # code
__ilines.append(iline)
elif re_begin.match(iline): # begin block
__ilines.append(iline)
_xsplit(re_begin.match(iline).group(1))
elif re_sblock.match(iline):# single block
__ilines.append(iline)
_xsplit(re_sblock.match(iline).group(1))
elif re_end.match(iline): # end block
__ilines.append(iline)
iline = f.readline()
f.close()
if not _gen_debug in NO: #yes, debug is ON
sys.stderr.write('-')
print "f(%s)s(%s)o(%s)a(%s)npre(%s)npos(%s)bug(%s)"\
% (filename, source_name, opt,\
_gen_append, _gen_nopre, _gen_nopost, _gen_debug)
_xstrip(opt, 1)
else:
des = string.split(filename, '/')[-1:][0]
try:
dest_time = os.stat(filename)[stat.ST_MTIME]
except os.error:
dest_time = 0
if _force_ or (src_time > dest_time):
try:
if _gen_append in NO:
g = open(filename, 'w')
sys.stderr.write('.')
else:
g = open(filename, 'a')
g.write('\n')
sys.stderr.write('+')
except IOError:
sys.stderr.write('X')
return
if _gen_nopost in NO:
global _kins_post
tmp__pre = _kins_post
## expand |posamble|. Only macro "$dest" is allowed.
tmp__pre = string.replace(_kins_post,"$dest", des)
tmp__pre = string.replace(tmp__pre, "$c", "#")
g.write(tmp__pre)# the tail
def usage():
sys.stdout.write(\
"""Usage: docstrip [options] file1 file2...
-e --exec code excute <code> before any job
(only the assignments are accepted)
-g --gen expr generate only files whose names
match the regular expression <expr>
-j --job job specify the kins file named <job>
(the extension `.kins' can be omitted)
-t --tex print the (TeX) INS code
-d --debug print debug information (donot generate any file)
-f --force force generatation (skip time check)
-h --help show this message
-v --version print version information and exit
Report:
. generate sucessfully
+ generate in `append' mode
o skip file (specified by <kins> file)
? some things wrong occur
_ opening new source file
= importing a kins file
* file is already imported. Inogre it!
X cannot open file for writting
E failed on excuting embeded python code
| skip file (the source time <= the destination time)
Within the `--debug' option:
- debugging
n normal code
s single block code
""")
for o, a in opts:
if o in ("-h", "--help"):
usage()
sys.exit(0)
elif o in ("-v", "--version"):
sys.stdout.write("%s\n" % SELF_INFOR)
sys.exit(0)
elif o in ("-f", "--force"):
_force_ = 1
elif o in ("-t", "--tex"):
_tex_ = 1
elif o in ("-d", "--debug"):
_kins_debug = '1'
elif o in ("-g", "--gen"):
_gonly_ = 1
only_files = re.compile(a)
sys.stderr.write(" genonly = %s\n" % a)
elif o in ("-j", "--job"):
if not string.lower(a[-5:]) == ".kins":
a = a + ".kins"
jobnames.append(a)
elif o in ("-e", "--exec"):
a = string.split(a, ';')
for code in a:
zzz = re_kasg.match(string.strip(code))
if zzz:
var_name = zzz.group(1)
var_value= zzz.group(2)
exec('_kins_%s="""%s"""' % (var_name,var_value))
if not var_name in __kins_vars:
__kins_vars.append(var_name)
sys.stderr.write(" %s = %s\n" % (var_name,var_value))
else:
sys.stderr.write(" ?code: %s\n" % code)
for item in args:
if not string.lower(item[-5:]) == ".kins":
item = item + ".kins"
jobnames.append(item)
if jobnames == []:
sys.stderr.write("Please try |docstrip.py --help|\n")
sys.exit(1)
if _tex_:
print\
"%%%% This file was generated by `%s'\n\
%%%% from the source(s) %s\n\
\\input docstrip.tex" % (SELF_INFOR, jobnames)
for jobname in jobnames:
if os.path.isfile(jobname):
sys.stderr.write("\n<<%s>>\n" % jobname)
_dokins(jobname)
else:
sys.stderr.write("\n<<%s>>: cannot open this file\n" % jobname)
if _tex_:
print "\\endbatchfile\n\\endinput\n%% End of file."
sys.stderr.write("(ok)\n")
####################
## END OF PROGRAM ##
####################