zOs/REXX.O13/F
/* copy f begin *******************************************************/
f: procedure expose m.
parse arg ggFmt, ggA1, ggA2
if symbol('M.f.fmt.ggFmt') == 'VAR' then
interpret M.f.fmt.ggFmt
else
interpret fGen(ggFmt)
endProcedure f
fAll: procedure expose m.
parse arg fmt
do forever
o = inO()
if o == '' then
return
call out f(fmt, o)
end
endProcedure f
/*--- format character2hex (if not sql null) -------------------------*/
fH: procedure expose m.
parse arg v, l
if v \== m.sqlNull then
v = c2x(v)
if l >= 0 then
return right(v, l)
else
return left(v, -l)
endProcedure fH
/*--- format integer or fixPoint Decimal -----------------------------*/
fI: procedure expose m.
parse arg v, l, d
if datatype(v, 'n') then do
if d == '' then
v = format(v, ,0,0)
else
v = format(v, ,d,0)
if abbrev(l, '+') then
if \ abbrev(v, '-') then
v = '+'v
if length(v) > abs(l) then
return right('', abs(l), '*')
end
if l >= 0 then
return right(v, l)
else
return left(v, -l)
endProcedure fI
/*--- format floating point in E notitaion ---------------------------*/
fE: procedure expose m.
parse arg v, l, d, eChar
if eChar == '' then
eChar = 'e'
if \ datatype(v, 'n') then
return left(v, l)
else if l = 7 then
return fEStrip(format(v, 2, 2, 2, 0), 0, 2, 0, 2, eChar)
else if l = 8 then
return fEStrip(format(v, 2, 2, 2, 0), 1, 2, 0, 2, eChar)
else if l < 7 then
call err 'bad width fE('v',' l',' d')'
else if d == '' then
return fEStrip(format(v, 2, l-6, 2, 0), 1, l-6, 0, 2, eChar)
else if l - d - 5 < 1 then
call err 'bad prec fE('v',' l',' d')'
else
return fEStrip(format(v, 2, d, l-d-5, 0), 1, d, 1, l-d-5, eChar)
endProcedure fE
fEStrip: procedure expose m.
parse arg v, mSi, de, eSi, ePr, eChar
parse var v ma 'E' ex
if ex == '' then do
ma = strip(ma, 't')
ex = '+'left('', ePr, 0)
end
if eSi == 0 then do
if abbrev(ex, '+') then
ex = substr(ex, 2)
else if abbrev(ex, '-0') then
ex = '-'substr(ex, 3)
else do
exO = ex
ex = left('-9', ePr, '9')
/* say 'format('ma '* (1E'exO') / (1E'ex'), 2,' de', 0)' */
ma = format(ma * ('1E'exO) / ('1E'ex), 2, de, 0)
end
end
if mSi == 0 then
if abbrev(ma, ' ') then
ma = substr(ma, 2)
else
ma = format(ma, 2, de-1)
r = ma || eChar || ex
if length(r) - length(eChar) <> 2 + mSi + de + eSi + ePr then
call err 'bad fEStrip('v',' mSi',' de',' eSi',' ePr',' eChar ,
|| ') ==>' r 'bad len' length(r)
return r
endProcedure fEStrip
/*--------------------------------------------------------------------
fGen: Format generator should be compatible with fPrint|
<<<< + extension of fPrint, - in fPrint but not implemented
+ \s a single space
+ \n a newLine
+ \% \@ \\ the escaped char
('@' argN? '.'? field)?'%' flags? width? ('.' precision)? specifier
specifier: is the most significant one and defines the type
- c Character a
- C Cut %-nC = left(v,n), %nC = right(v,n) %n.mC = substr(m, n)
- d or i Signed decimal integer
- e Scientific notation (mantissa/exponent) using e character 3.9265e+2
- E Scientific notation (mantissa/exponent) using E character 3.9265E+2
- f Decimal floating point
- g Use the shorter of %e or %f
- G Use the shorter of %E or %f
- h Characters in hex
- o Unsigned octal 610
- S Strip(..., both)
- u Unsigned decimal integer
- x Unsigned hexadecimal integer
- X Unsigned hexadecimal integer (capital letters)
- p Pointer address
- n Nothing printed. The argument must be a pointer to a signed int, wh
+ % A % followed by another % character will write % to stdout. %
+ Q for iterator first nxt end
Flags:
- - Left-justify within the given field width; Right justification is
- + Forces to precede the result with a plus or minus sign (+ or -)
- (space) If no sign is going to be written, a blank space is inserte
- # Used with o, x or X specifiers the value is preceeded with 0, 0x
force decimalpoint ...
- 0 Left-pads the number with zeroes (0) instead of spaces, where pad
+ = reuse previous input argument
length not implemented
----------------------------------------------------------------------*/
fGen: procedure expose m.
parse arg src, key
if key == '' then do
qSuf = right(src, 3)
if length(qSuf) == 3 & abbrev(qSuf, '%Q') then
s2 = left(src, length(src) - 3)
else
s2 = src
call fGen s2, s2
if symbol('m.f.fmt.src') == 'VAR' then
return m.f.fmt.src
call err fGen 'format' src 'still undefined'
end
call scanIni
cx = 1
ky = key
do forever
cy = pos('%q', src, cx)
if cy < 1 then do
m.f.fmt.ky = fGenCode(substr(src, cx), 'F.INFO.'ky)
leave
end
m.f.fmt.ky = fGenCode(substr(src, cx, cy-cx), 'F.INFO.'ky)
if substr(src, cy, 3) == '%q^' then do
if substr(src, cy, 5) == '%q^%q' then
cy = cy+3
else if length(src) = cy + 2 then
leave /* do not overrite existing fmt | */
end
if cy > length(src)-2 then
call err 'bad final %q in' src
if substr(src, cy, 3) == '%q^' then
ky = key
else
ky = key'%Q'substr(src, cy+2, 1)
m.f.tit.ky.0 = 0
cx = cy+3
end
if symbol('m.f.fmt.key') == 'VAR' then
return m.f.fmt.key
call scanErr fGen 'format' src 'still undefined'
endProcedure fGen
fGenCode: procedure expose m.
parse arg aS, jj
jx = 0
call scanSrc fGen, aS
call scanSrc fGen, aS
ax = 0
cd = ''
do forever
txt = fText()
if txt \== '' then
cd = cd '||' quote(txt, "'")
if scanEnd(fGen) then do
m.jj.0 = jx
if cd \== '' then
return "return" substr(cd, 4)
else
return "return ''"
end
an = ''
af = '-'
if \ scanLit(fGen, '@') then do
ax = ax + 1
end
else do
if scanWhile(fGen, '0123456789') then
ax = m.fGen.tok
else if ax < 1 then
ax = 1
if substr(m.fGen.src, m.fGen.pos, 1) \== '%' then do
call scanLit fGen, '.'
af = fText()
end
end
if \ scanLit(fGen, '%') then
call scanErr fGen, 'missing %'
call scanWhile fGen, '-+'
flags = m.fGen.tok
call scanWhile fGen, '0123456789'
len = m.fGen.tok
siL = len
if len \== '' & flags \== '' then
siL = left(flags, 1)len
prec = ''
if scanLit(fGen, '.') then do
if len == '' then
call scanErr fGen, 'empty len'
call scanWhile fGen, '0123456789'
prec = m.fGen.tok
end
call scanChar fGen, 1
sp = m.fGen.tok
if ax < 3 then
aa = 'ggA'ax
else
aa = 'arg(' || (ax+1) || ')'
if af \== '-' then do
if af \== '' then
af = '.'af
if abbrev(aa, 'ggA') & pos('.GG', af) < 1 ,
& translate(af) == af then
aa = 'm.'aa || af
else
aa = 'mGet('aa '||' quote(af, "'")')'
end
if sp = 'c' then do
pd = word('rigPad lefPad', (pos('-', flags) > 0)+1)
if prec \== '' then
cd = cd '||' pd'(substr('aa',' prec'),' len')'
else
cd = cd '||' pd'('aa',' len')'
end
else if sp = 'C' then do
if prec \== '' then
cd = cd '|| substr('aa',' prec',' len')'
else if pos('-', flags) > 0 then
cd = cd '|| left('aa',' len')'
else
cd = cd '|| right('aa',' len')'
end
else if sp == 'H' then
cd = cd "|| fH("aa", '"siL"')"
else if sp == 'h' then
cd = cd "|| translate(fH("aa", '"siL"'), 'abcdef','ABCDEF')"
else if sp == 'i' then do
cd = cd "|| fI("aa", '"siL"'"
if prec == '' then
cd = cd')'
else
cd = cd',' prec')'
end
else if sp == 'E' | sp == 'e' then
cd = cd "|| fE("aa"," len"," prec", '"sp"')"
else if sp == 's' then
cd = cd '||' aa
else if sp = 'S' then
cd = cd '|| strip('aa')'
else
call scanErr fGen, 'bad specifier' sp
jx = jx + 1
m.jj.jx.arg = ax
m.jj.jx.name = af
end
endProcedure fGenCode
fText: procedure expose m. ft.
res = ''
do forever
if scanUntil(fGen, '\@%') then
res = res || m.fGen.tok
if \ scanLit(fGen, '\') then
return res
call scanChar fGen, 1
if pos(m.fGen.tok, 's\@%') < 1 then
res = res'\' || m.fGen.tok
else
res = res || translate(m.fgen.tok, ' ', 's')
end
endProcedure fText
/* copy f end *******************************************************/