VocalEasel/mma/MMA/macro.py

767 lines
20 KiB
Python
Raw Normal View History

2006-11-10 08:07:56 +00:00
# macros.py
"""
This module is an integeral part of the program
MMA - Musical Midi Accompaniment.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
2007-04-29 06:47:40 +00:00
Bob van der Poel <bob@mellowood.ca>
2006-11-10 08:07:56 +00:00
The macros are stored, set and parsed in this single-instance
class. At the top of MMAparse an instance in created with
2007-04-29 06:47:40 +00:00
something like: macros=MMMmacros.Macros().
2006-11-10 08:07:56 +00:00
"""
2009-05-17 22:34:44 +00:00
import random
2006-11-10 08:07:56 +00:00
import MMA.midiC
import MMA.translate
import MMA.patSolo
2007-04-29 06:47:40 +00:00
import MMA.patAria
2006-11-10 08:07:56 +00:00
import MMA.volume
2009-05-17 22:34:44 +00:00
import MMA.grooves
import MMA.parse
import MMA.seqrnd
2006-11-10 08:07:56 +00:00
2009-05-17 22:34:44 +00:00
import gbl
from MMA.lyric import lyric
from MMA.common import *
from MMA.safe_eval import safe_eval
2006-11-10 08:07:56 +00:00
class Macros:
2007-04-29 06:47:40 +00:00
vars={} # storage
expandMode = 1 # flag for variable expansion
pushstack = []
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
def __init__(self):
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
self.vars={}
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
def clear(self, ln):
if ln:
error("VarClear does not take an argument.")
self.vars={}
if gbl.debug:
print "All variable definitions cleared."
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
def stackValue(self, s):
self.pushstack.append(' '.join(s))
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
def sysvar(self, s):
""" Create an internal macro. """
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
# Simple/global system values
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
if s == 'KEYSIG':
a=MMA.patSolo.keySig.kSig
if a >= 0:
f='#'
else:
f='b'
return "%s%s" % (abs(a), f)
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
elif s == 'TIME':
return str(gbl.QperBar)
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
elif s == 'TEMPO':
return str(gbl.tempo)
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
elif s == 'VOLUME':
return str(int(MMA.volume.volume * 100)) # INT() is important
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
elif s == 'VOLUMERATIO':
return str((MMA.volume.vTRatio * 100))
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
elif s == 'LASTVOLUME':
return str(int(MMA.volume.lastVolume * 100))
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
elif s == 'GROOVE':
2009-05-17 22:34:44 +00:00
return MMA.grooves.currentGroove
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
elif s == 'LASTGROOVE':
2009-05-17 22:34:44 +00:00
return MMA.grooves.lastGroove
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
elif s == 'SEQRND':
2009-05-17 22:34:44 +00:00
if MMA.seqrnd.seqRnd[0] == 0: return "Off"
if MMA.seqrnd.seqRnd[0] == 1: return "On"
return ' '.join(MMA.seqrnd.seqRnd[1:])
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
elif s == 'SEQSIZE':
return str(gbl.seqSize)
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
elif s == 'SWINGMODE':
if gbl.swingMode:
a = "On"
else:
a = "Off"
return "%s Skew=%s" % (a, gbl.swingSkew)
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
elif s == 'TRANSPOSE':
return str(gbl.transpose)
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
elif s == 'STACKVALUE':
if not self.pushstack:
error( "Empty push/pull variable stack")
return self.pushstack.pop()
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
elif s == 'DEBUG':
return "Debug=%s Filenames=%s Patterns=%s " \
"Sequence=%s Runtime=%s Warnings=%s Expand=%s" % \
(gbl.debug, gbl.showFilenames, gbl.pshow, gbl.seqshow, \
gbl.showrun, int(not gbl.noWarn), gbl.showExpand)
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
elif s == 'LASTDEBUG':
return "Debug=%s Filenames=%s Patterns=%s " \
"Sequence=%s Runtime=%s Warnings=%s Expand=%s" % \
(gbl.Ldebug, gbl.LshowFilenames, gbl.Lpshow, gbl.Lseqshow, \
gbl.Lshowrun, int(not gbl.LnoWarn), gbl.LshowExpand)
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
elif s == 'VEXPAND':
if self.expandMode:
return "On"
else:
return "Off"
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
elif s == "MIDISPLIT":
return ' '.join([str(x) for x in MMA.midi.splitChannels])
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
elif s == 'SEQRNDWEIGHT':
2009-05-17 22:34:44 +00:00
return ' '.join([str(x) for x in MMA.seqrnd.seqRndWeight])
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
elif s == 'AUTOLIBPATH':
return gbl.autoLib
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
elif s == 'LIBPATH':
return gbl.libPath
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
elif s == 'INCPATH':
return gbl.incPath
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
elif s == 'VOICETR':
return MMA.translate.vtable.retlist()
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
elif s == 'TONETR':
return MMA.translate.dtable.retlist()
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
elif s == 'OUTPATH':
return gbl.outPath
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
elif s == 'BARNUM':
return str(gbl.barNum + 1)
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
elif s == 'LINENUM':
return str(gbl.lineno)
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
elif s == 'LYRIC':
2009-05-17 22:34:44 +00:00
return lyric.setting()
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
# Track vars ... these are in format TRACKNAME_VAR
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
a=s.rfind('_')
if a==-1:
error("Unknown system variable $_%s" % s)
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
tname = s[:a]
func = s[a+1:]
2006-11-10 08:07:56 +00:00
2009-05-17 22:34:44 +00:00
try:
2007-04-29 06:47:40 +00:00
t=gbl.tnames[tname]
2009-05-17 22:34:44 +00:00
except:
error("System variable $_%s refers to nonexistent track." % s )
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
if func == 'ACCENT':
r=[]
for s in t.accent:
r.append("{")
for b,v in s:
r.append(str((b/gbl.BperQ)+1))
r.append(str(int(v * 100)))
r.append("}")
return ' '.join(r)
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
elif func == 'ARTICULATE':
return ' '.join([str(x) for x in t.artic])
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
elif func == 'CHANNEL':
return str(t.channel)
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
elif func == 'COMPRESS':
return ' '.join([str(x) for x in t.compress])
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
elif func == 'DIRECTION':
if t.vtype == 'ARIA':
return ' '.join([str(x) for x in t.selectDir])
else:
return ' '.join([str(x) for x in t.direction])
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
elif func == 'DUPROOT':
if t.vtype != "CHORD":
error("Only CHORD tracks have DUPROOT")
return ' '.join([str(x) for x in t.dupRoot])
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
elif func == 'HARMONY':
return ' '.join([str(x) for x in t.harmony])
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
elif func == 'HARMONYVOLUME':
return ' '.join([str(int(a * 100)) for a in t.harmonyVolume])
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
elif func == 'INVERT':
return ' '.join([str(x) for x in t.invert])
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
elif func == 'LIMIT':
return str( t.chordLimit )
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
elif func == 'MALLET':
if t.vtype not in ("SOLO", "MELODY"):
error("Mallet only valid in SOLO and MELODY tracks")
return "Mallet Rate=%i Decay=%i" % (t.mallet, t.malletDecay*100)
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
elif func == 'OCTAVE':
return ' '.join([str(a/12) for a in t.octave])
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
elif func == 'RANGE':
return ' '.join([str(x) for x in t.chordRange])
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
elif func == 'RSKIP':
return ' '.join([str(int(a * 100)) for a in t.rSkip])
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
elif func == 'RTIME':
return ' '.join([str(x) for x in t.rTime])
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
elif func == 'RVOLUME':
return ' '.join([str(int(a * 100)) for a in t.rVolume])
2009-05-17 22:34:44 +00:00
elif func == 'SEQUENCE':
tmp = []
for a in range(gbl.seqSize):
tmp.append('{' + t.formatPattern(t.sequence[a]) + '}')
return ' '.join(tmp)
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
elif func == 'SEQRND':
if t.seqRnd: return 'On'
else: return 'Off'
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
elif func == 'SEQRNDWEIGHT':
return ' '.join([str(x) for x in t.seqRndWeight])
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
elif func == 'SPAN':
return "%s %s" % (t.spanStart, t.spanEnd)
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
elif func == 'STRUM':
if t.vtype != "CHORD":
error("Only CHORD tracks have STRUM")
return ' '.join([str(x) for x in t.strum])
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
elif func == 'TONE':
if t.vtype != "DRUM":
error("Only DRUM tracks have TONE")
return ' '.join([MMA.midiC.valueToDrum(a) for a in t.toneList])
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
elif func == 'UNIFY':
return ' '.join([str(x) for x in t.unify])
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
elif func == 'VOICE':
2009-05-17 22:34:44 +00:00
return ' '.join([MMA.midiC.valueToInst(a) for a in t.voice])
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
elif func == 'VOICING':
if t.vtype != 'CHORD':
error("Only CHORD tracks have VOICING")
t=t.voicing
return "Mode=%s Range=%s Center=%s RMove=%s Move=%s Dir=%s" % \
(t.mode, t.range, t.center, t.random, t.bcount, t.dir)
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
elif func == 'VOLUME':
return ' '.join([str(int(a * 100)) for a in t.volume])
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
else:
error("Unknown system track variable %s" % s)
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
def expand(self, l):
""" Loop though input line and make variable subsitutions.
MMA variables are pretty simple ... any word starting
with a "$xxx" is a variable.
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
l - list
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
RETURNS: new list with all subs done.
"""
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
if not self.expandMode:
return l
2006-11-10 08:07:56 +00:00
2009-05-17 22:34:44 +00:00
gotmath=0
2007-04-29 06:47:40 +00:00
while 1: # Loop until no more subsitutions have been done
sub=0
2009-05-17 22:34:44 +00:00
2007-04-29 06:47:40 +00:00
for i,s in enumerate(l):
if s[0]=='$':
2006-11-10 08:07:56 +00:00
2009-05-17 22:34:44 +00:00
s = s[1:].upper()
frst = s[0]
if frst == '$': # $$ - don't expand (done in IF clause)
continue
elif frst == '(': # flag math macro
gotmath = 1
continue
# we have a var, see if system or user. Set 'ex'
elif frst == '_': # system var
2007-04-29 06:47:40 +00:00
ex=self.sysvar(s[1:])
2009-05-17 22:34:44 +00:00
elif s in self.vars: # user var?
ex = self.vars[s]
2006-11-10 08:07:56 +00:00
2009-05-17 22:34:44 +00:00
else: # unknown var...error
2007-04-29 06:47:40 +00:00
error("User variable '%s' has not been defined" % s )
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
if type(ex) == type([]): # MSET variable
if len(ex):
gbl.inpath.push( ex[1:], [gbl.lineno] * len(ex[1:]))
if len(ex):
ex=ex[0]
else:
ex=[]
else: # regular SET variable
ex=ex.split()
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
l=l[:i] + ex + l[i+1:] # ex might be a list, so this is needed
sub=1
break
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
if not sub:
break
2006-11-10 08:07:56 +00:00
2009-05-17 22:34:44 +00:00
# all the mma internal and system macros are expanded. Now check for math.
if gotmath:
l = ' '.join(l) # join back into one line
while 1:
try:
s1 = l.index('$(') # any '$(' left?
except:
break # nope, done
# find trailing )
nest=0
s2 = s1+2
max = len(l)
while 1:
if l[s2] == '(': nest+=1
if l[s2] == ')':
if not nest:
break
else:
nest-=1
s2 += 1
if s2 >= max:
error("Unmatched delimiter in '%s'." % l)
l = l[:s1] + str(safe_eval( l[s1+2:s2].strip())) + l[s2+1:]
l=l.split()
2007-04-29 06:47:40 +00:00
return l
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
def showvars(self, ln):
""" Display all currently defined variables. """
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
if len(ln):
for a in ln:
a=a.upper()
if a in self.vars:
print "$%s: %s" % (a, self.vars[a])
else:
print "$%s - not defined" % a
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
else:
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
print "User variables defined:"
kys = self.vars.keys()
kys.sort()
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
mx = 0
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
for a in kys: # get longest name
if len(a) > mx:
mx = len(a)
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
mx = mx + 2
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
for a in kys:
print " %-*s %s" % (mx, '$'+a, self.vars[a])
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
def getvname(self, v):
""" Helper routine to validate variable name. """
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
if v[0] in ('$', '_'):
error("Variable names cannot start with a '$' or '_'")
return v.upper()
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
def rndvar(self, ln):
""" Set a variable randomly from a list. """
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
if len(ln) < 2:
error("Use: RndSet Variable_Name <list of possible values>")
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
v = self.getvname(ln[0])
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
self.vars[v] = random.choice(ln[1:])
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
if gbl.debug:
print "Variable $%s randomly set to '%s'" % (v, self.vars[v])
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
def newsetvar(self, ln):
""" Set a new variable. Ignore if already set. """
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
if not len(ln):
error("Use: NSET VARIABLE_NAME [Value] [[+] [Value]]")
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
if self.getvname(ln[0]) in self.vars:
return
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
self.setvar(ln)
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
def setvar(self, ln):
""" Set a variable. Not the difference between the next 2 lines:
Set Bar BAR
Set Foo AAA BBB $bar
$Foo == "AAA BBB BAR"
Set Foo AAA + BBB + $bar
$Foo == "AAABBBBAR"
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
The "+"s just strip out interveing spaces.
"""
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
if len(ln) < 1:
error("Use: SET VARIABLE_NAME [Value] [[+] [Value]]")
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
v=self.getvname(ln.pop(0))
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
t=''
addSpace = 0
for i,a in enumerate(ln):
if a == '+':
addSpace = 0
continue
else:
if addSpace:
t += ' '
t += a
addSpace = 1
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
self.vars[v]=t
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
if gbl.debug:
print "Variable $%s == '%s'" % (v, self.vars[v])
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
def msetvar(self, ln):
""" Set a variable to a number of lines. """
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
if len(ln) !=1:
error("Use: MSET VARIABLE_NAME <lines> MsetEnd")
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
v=self.getvname(ln[0])
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
lm=[]
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
while 1:
l=gbl.inpath.read()
if not l:
error("Reached EOF while looking for MSetEnd")
cmd=l[0].upper()
if cmd in ("MSETEND", 'ENDMSET'):
if len(l) > 1:
error("No arguments permitted for MSetEnd/EndMSet")
else:
break
lm.append(l)
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
self.vars[v]=lm
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
def unsetvar(self, ln):
""" Delete a variable reference. """
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
if len(ln) != 1:
error("Use: UNSET Variable")
v=ln[0].upper()
if v[0] == '_':
error("Internal variables cannot be deleted or modified")
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
if v in self.vars:
del(macros.vars[v])
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
if gbl.debug:
print "Variable '%s' UNSET" % v
else:
warning("Attempt to UNSET nonexistent variable '%s'" % v)
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
def vexpand(self, ln):
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
if len(ln) == 1:
cmd = ln[0].upper()
else:
cmd=''
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
if cmd == 'ON':
self.expandMode=1
if gbl.debug:
print "Variable expansion ON"
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
elif cmd == 'OFF':
self.expandMode=0
if gbl.debug:
print "Variable expansion OFF"
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
else:
error("Use: Vexpand ON/Off")
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
def varinc(self, ln):
""" Increment a variable. """
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
if len(ln) == 1:
inc=1
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
elif len(ln) == 2:
inc = stof(ln[1], "Expecting a value (not %s) for Inc" % ln[1])
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
else:
error("Usage: INC Variable [value]")
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
v=ln[0].upper()
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
if v[0] == '_':
error("Internal variables cannot be modified")
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
if not v in self.vars:
error("Variable '%s' not defined" % v)
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
vl=stoi(self.vars[v], "Variable must be a value to increment") + inc
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
if vl == int(vl):
vl = int(vl)
self.vars[v]=str(vl)
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
if gbl.debug:
print "Variable '%s' INC to %s" % (v, self.vars[v])
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
def vardec(self, ln):
""" Decrement a varaiable. """
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
if len(ln) == 1:
dec = 1
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
elif len(ln) == 2:
dec = stof(ln[1], "Expecting a value (not %s) for Inc" % ln[1])
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
else:
error("Usage: DEC Variable [value]")
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
v=ln[0].upper()
if v[0] == '_':
error("Internal variables cannot be modified")
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
if not v in self.vars:
error("Variable '%s' not defined" % v)
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
vl=stoi(self.vars[v], "Variable must be a value to decrement") - dec
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
if vl == int(vl):
vl = int(vl)
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
self.vars[v]=str(vl)
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
if gbl.debug:
print "Variable '%s' DEC to %s" % (v, self.vars[v])
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
def varIF(self, ln):
""" Conditional variable if/then. """
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
def expandV(l):
""" Private func. """
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
l=l.upper()
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
if l[:2] == '$$':
2009-05-17 22:34:44 +00:00
l=l.upper()
2007-04-29 06:47:40 +00:00
l=l[2:]
if not l in self.vars:
error("String Variable '%s' does not exist" % l)
l=self.vars[l]
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
try:
v=float(l)
except:
2009-05-17 22:34:44 +00:00
try:
v=int(l,0) # this lets us convert HEX/OCTAL
except:
v=None
2006-11-10 08:07:56 +00:00
2009-05-17 22:34:44 +00:00
return ( l.upper(), v )
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
def readblk():
""" Private, reads a block until ENDIF, IFEND or ELSE.
Return (Terminator, lines[], linenumbers[] )
"""
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
q=[]
qnum=[]
nesting=0
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
while 1:
l=gbl.inpath.read()
if not l:
error("EOF reached while looking for EndIf")
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
cmd=l[0].upper()
if cmd == 'IF':
nesting+=1
if cmd in ("IFEND", 'ENDIF', 'ELSE'):
if len(l) > 1:
error("No arguments permitted for IfEnd/EndIf/Else")
if not nesting:
break
if cmd != 'ELSE':
nesting -= 1
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
q.append(l)
qnum.append(gbl.lineno)
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
return (cmd, q, qnum)
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
if len(ln)<2:
error("Usage: IF <Operator> ")
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
action = ln[0].upper()
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
# 1. do the unary options: DEF, NDEF
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
if action in ('DEF', 'NDEF'):
if len(ln) != 2:
error("Usage: IF %s VariableName" % action)
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
v=ln[1].upper()
retpoint = 2
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
if action == 'DEF':
2009-05-17 22:34:44 +00:00
compare = v in self.vars
2007-04-29 06:47:40 +00:00
elif action == 'NDEF':
2009-05-17 22:34:44 +00:00
compare = ( v not in self.vars )
2007-04-29 06:47:40 +00:00
else:
error("Unreachable unary conditional")
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
# 2. Binary ops: EQ, NE, etc.
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
elif action in ('LT', 'LE', 'EQ', 'GE', 'GT', 'NE'):
if len(ln) != 3:
error("Usage: VARS %s Value1 Value2" % action)
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
s1,v1 = expandV(ln[1])
s2,v2 = expandV(ln[2])
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
if type(v1) == type(1.0) and type(v2) == type(1.0):
s1=v1
s2=v2
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
retpoint = 3
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
if action == 'LT':
compare = (v1 < v2)
elif action == 'LE':
compare = (v1 <= v2)
elif action == 'EQ':
compare = (v1 == v2)
elif action == 'GE':
compare = (v1 >= v2)
elif action == 'GT':
compare = (v1 > v2)
elif action == 'NE':
compare = (v1 != v2)
else:
error("Unreachable binary conditional")
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
else:
error("Usage: IF <CONDITON> ...")
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
""" Go read until end of if block.
We shove the block back if the compare was true.
Unless, the block is terminated by an ELSE ... then we need
to read another block and push back one of the two.
"""
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
cmd, q, qnum = readblk()
if cmd == 'ELSE':
cmd, q1, qnum1 = readblk()
if cmd == 'ELSE':
error("Only one ELSE is permitted in IF construct")
if not compare:
compare = 1
q = q1
qnum = qnum1
if compare:
gbl.inpath.push( q, qnum )
2006-11-10 08:07:56 +00:00
2009-05-17 22:34:44 +00:00
def domath(s):
""" A simple math factoring func. Just does add, sub, mult, divide. """
print '>>>',s
s = ' '.join(s)
try:
s = eval(s)
except:
error("Error in '%s' expression." % s)
print s
return str(s)
2006-11-10 08:07:56 +00:00
macros = Macros()