Mini Awk

Michal Moskal malekith w pld.org.pl
Śro, 4 Kwi 2001, 10:47:36 CEST


Helo,

Może sprecyzuje ten pomysł z mini-awkiem. Wiget mówił, żeby config
robić w XML. Trzeba to jakoś parsować. Pewnie nikomu nie będzie się
chciało pisać konfiguratorów do, powiedzmy MTA, w C, a robienie
tego z shella, czy nawet awka może być kłopotliwe.

Jeśli konfig ma być w XML, to może program też? N.p.:

<proc>
 <name>part_conf</name>
 <body>
  <if>
   <cond>
    <exp>$a == 1</exp>
   </cond>
   <then>
    <call>shut_me</call>
   </then>
   <else>
    <call>bum</call>
   </else>
  </if>
 </body>
</proc>

Hmmm... to jest beznadziejne, 3 razy bardziej przegadane, niż Ada :^)
Wole prostą składnie, TCL-like:

proc part_conf {
	if ($a == 1) {
		shut_me
	} else {
		bum
	}
}

Ile to razy krócej?

Dobra, to daje opis proponowanej składni mini-awka (jakaś nazwa by się
przydała). Mogę to do jutra napisać. Jakby to uskutecznić, możnaby
pozbyć się z bootdisku ash'a (wszystkie skrypty przepisać na to, zostawić
sobie tylko lasha).

Jeśli config będzie w XMLu (jak sądzicie, co będzie lepsze: XML czy
sekcja { costam } ?), to parser raczej nie będzie patrzał na DTD
tudzież encje (encje by się mogły przydać, ale chyba można bez nich
przeżyć). DTD można napisać i sobie zewnętrznie walidować.

----------- CUT -------------
{},'',q - quote, no expansion
"",qq - quote with expanstion ($ and [] are executed)
[],x - execute commands, subsitute output
(X) - same as [ex X]
`X` - same as [sh X]

q,qq,x works as in perl (i.e. q{} or qq||).

General concept:

return value is string, most of builtins doesn't return (output)
anything. read, open, conf, sh, ex, out and printf does.

Your own proc return, what was output during their execution,
and not caputured with [].

proc pm {
	if ($argv[0] > 0) {out "Plus"} else {out "Minus"}
	out $argv[0]
}

Then:

([pm -10] == "Minus-10")
([pm 10] == "Plus10")

Highest level program outputs to stdout.


builtins:

*** general

out STR... - output STR
printf FMT ARG... - output formatted string, 
		  - only limited version is supported.
eval STR... - execute STR
proc NAME BODY - define procedure with NAME and BODY
ex EXPRESSION... - evaluate expression, output result.
set VARNAME VALUE - set varname to value
local BODY - execute BODY in subprocess, changing variables, opening
	   - files etc inside it doesn't have any effect for main
	   - program, output can be caputured with [].
fork BODY  - same as local, but doesn't wait for subprocess to finish.
	   - output is lost.

*** output/exits/shell

sh CMD... - pass CMD to sh -c, substitute output
echo STR... - print STR to stdout
err STR... - print STR to stderr
die STR... - print STR to stderr, and die
exit CODE - finish script with CODE

*** flow control

if COND BODY 
 (elif COND BODY)* 
 (else BODY)? - conditional stmt, COND should be 0 (false) 
	      - or other number (true), if it's not number 
	      - it's assumed 0 (false).
while COND BODY
break
continue

*** file

open NAME MODE - open NAME, MODE as in fopen(3), output FD
write FD STRING... - write to file
read FD - read one line from file
readch FD - read one char
close FD

*** RegExps
rx STRING REGEXP FLAGS		- output 1|0 if STRING matches or not REGEXP
sub STRING REGEXP SUBST FLAGS	- substitue REGEXP with SUBST in STRING

FLAGS can be 0 or more from
 g - global
 m - multiline
 s - singleline [???]

*** config file/templates

conf VARNAME

VARNAME is in form ( /absolute/path/conffile: | ./conffile: )? (sectname:)* varname
So /etc/sysconfig/mta:global:aliases:root is ok, as well as foo and foo:bar.

conffile FILENAME BODY		- specify default file for BODY
conffd FD BODY			- "
sect SECTNAME BODY		- specify default section for BODY
allsect SECTNAME BODY		- execute BODY for all sections with given
				- name, specifing it as default.

ex:
conffile /etc/sysconfig/mta {
	sect global:yrgh:end {
		set foo [conf foo]
		set bar [conf bar]
		set baz [conf baz]
	}
}

template STRING... - subsitute strings in {} with conf variables, output result

ex:
set fd [open foo/bar w]
conffile /etc/sysconfig/mta {
	sect global:yrgh:end {
		if ([conf baz] == "") {set baz 'none'}
		write $fd [template \
			"# autogenerated file
			foo = {foo}
			bar = {bar}
			baz = $baz
			"]
	}
	allsect global:aliases:alias {
		write $fd [template "{name}: {user}\n"]
	}
}
close $fd

actual /etc/sysconfig/mta could look like:

<global>
 <yrgh>
  <end>
   <foo>Abc</foo>
   <bar>Xyz</bar>
  </end>
 </yrgh>
 <aliases>
  <alias>
   <name>postmaster</name>
   <user>me</user>
  </alias>
  <alias>
   <name>hostmaster</name>
   <user>me</user>
  </alias>
 </aliases>
</global>

or:

global {
 yrgh {
  end {
   foo = Abc
   bar = Xyz
  }
 }
 aliases {
  alias {
   name = postmaster
   user = me
  }
  alias {
   name = hostmaster
   user = me
  }
 }
}
   
word split is done first, so "$a$b" is same as $a$b, "[out 'Hello world']"
is same as [echo Hello world] which is the same as 'Hello world', "Hello world"
and even Hello\ world.

eval builtin can be used to override this.

*** special variables

$argc, $argv[] - in main program, as in C, in proc - arguments.
$rxc, $rxv[] - \(\) from last rx, $rxv[0] is entire regexp.
----------- CUT --------------



-- 
: Michal ``,/\/\,       '' Moskal    | |            : GCS {C,UL}++++$
:          |    |alekith      @    |)|(| . org . pl : {E--, W, w-,M}-
:                                  |                : {b,e>+}++ !tv h
: Current project:  http://aleph-0.dhs.org/ywindow/ : PLD Team member



Więcej informacji o liście dyskusyjnej pld-installer