[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: General outline of what I'm trying to do
From: |
Eric Blake |
Subject: |
Re: General outline of what I'm trying to do |
Date: |
Fri, 13 Jan 2012 20:53:39 -0700 |
User-agent: |
Mozilla/5.0 (X11; Linux x86_64; rv:9.0) Gecko/20111222 Thunderbird/9.0 |
On 01/13/2012 06:49 PM, jfw wrote:
>
> Am I correct in assuming that the following is doable using M4.
M4 is a Turing complete language, so without reading your question, I
can state that yes, it should be possible. That said, the devil's in
the details :)
> If so are there M4 implementations of macros available on the web to do this
> sort of thing
> that I can model my m4_lib.m4 code on?
That, I don't know. autoconf has a pretty good library of m4 macros,
but they are tuned more to shell script generation.
> Here's what I'm trying to do:
> use a library of M4 macros: m4_lib.m4
> use text files {g,h,s}.txt containing general definition of items
> use specific M4 files: {e,g,h,s}_{enum,name,hash}.m4 to generate files from
> the txt files.
> generate .h files: {e,g,h,s}_enum.h, {g,h)_name.h, and s_hash.h.
>
> macros:
>
> __in(name,value,flags,comment) definition selected from m4_lib.m4 by flag
> settings
Considering just __in(), I would lay things out so that m4_lib.m4 has
common setup, then specific .m4 files have the appropriate definitions
for the end result file it will be generating. Going by your example,
that means for converting .txt to enum, you would have enum.m4 contain:
define(`__in', `\tg_$1\t=\t$2,\t$4')dnl
while for converting .txt to name, you would have name.m4 contain:
define(`__in', `\t"$1",')dnl
Then to run the conversions, you would do:
m4 m4_lib.m4 enum.m4 g.txt > g_enum.h
m4 m4_lib.m4 enum.m4 h.txt > h_enum.h
m4 m4_lib.m4 name.m4 g.txt > g_name.h
m4 m4_lib.m4 name.m4 h.txt > h_name.h
Or are you trying to say that __in() should probe the third argument to
decide whether to make an output or skip a line, according to the flags
present in that argument? In that case, I'd suggest you put this in
m4_lib.m4:
define(`__ENUM', `1')dnl
define(`__NAME', `2')dnl
then in enum.m4:
define(`__in', `ifelse(expr((($3) & __ENUM) == __ENUM), `1',
`\tg_$1\t=\t$2,\t$4')')dnl
and in name.m4:
define(`__in', `ifelse(expr((($3) & __NAME) == __NAME), `1',
`\t"$1",')')dnl
You didn't quite show what you wanted s_hash to contain, so it's hard to
say how to write those macros.
> __begbit(initial bit value for __nextbit)
This could live in m4_lib.m4, something like:
define(`__begbit', `define(`__bit', `$1')')dnl
> __nextbit(return 32bit hex representation of value; increase value*2)
define(`__nextbit', `__bit`'define(`__bit',
format(`0x%x', expr(__bit * 2)))')dnl
> __genbit(named base, begin value (default to last __nextbit),end value)
Here, you're asking for a tough one. The way you described __begbit,
you plan on passing in the power of 2, which means you have to compute
the log base 2 of __bit; which is doable using bit-wise manipulations in
expr() but not trivial. I'd suggest that you instead rewrite your .txt
files to pass in the exponent instead of the power of 2, at which point
you then rewrite __nextbit to compute the power of 2. That is, the sequence
__begbit(3)
__nextbit
__nextbit
would generate 0x00000008 then 0x00000010, with this definition of
__nextbit:
define(`__nextbit', `format(`0x%08x',
expr(1<<__bit))`'define(`__bit', incr(__bit))')dnl
At which point, your desired implementation of __genbit is based on
using a for loop, as documented in the m4 manual, in your m4_lib.m4:
https://www.gnu.org/software/m4/manual/m4.html#Forloop
define(`forloop', `pushdef(`$1', `$2')_forloop($@)popdef(`$1')')dnl
define(`_forloop',
`$4`'ifelse($1, `$3', `', `define(`$1', incr($1))$0($@)')')dnl
define(`__genbit',
`forloop(`__i', ifelse(`$2', `', __bit, `$2'), `$3',
`\t"$1`'__i",
')dnl')dnl
--
Eric Blake address@hidden +1-919-301-3266
Libvirt virtualization library http://libvirt.org
signature.asc
Description: OpenPGP digital signature