From owner-freebsd-hackers@FreeBSD.ORG Wed Dec 14 00:04:39 2005 Return-Path: X-Original-To: freebsd-hackers@freebsd.org Delivered-To: freebsd-hackers@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id C68E716A420; Wed, 14 Dec 2005 00:04:39 +0000 (GMT) (envelope-from hselasky@c2i.net) Received: from swip.net (mailfe05.swip.net [212.247.154.129]) by mx1.FreeBSD.org (Postfix) with ESMTP id 7839243D60; Wed, 14 Dec 2005 00:04:29 +0000 (GMT) (envelope-from hselasky@c2i.net) X-T2-Posting-ID: Y1QAsIk9O44SO+J/q9KNyQ== X-Cloudmark-Score: 0.000000 [] Received: from mp-217-38-178.daxnet.no ([193.217.38.178] verified) by mailfe05.swip.net (CommuniGate Pro SMTP 5.0.2) with ESMTP id 48854800; Wed, 14 Dec 2005 01:04:26 +0100 From: Hans Petter Selasky To: John Baldwin Date: Wed, 14 Dec 2005 01:05:45 +0100 User-Agent: KMail/1.7 References: <200512131936.11640.hselasky@c2i.net> <200512131448.22599.jhb@freebsd.org> In-Reply-To: <200512131448.22599.jhb@freebsd.org> MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Content-Disposition: inline Message-Id: <200512140105.46945.hselasky@c2i.net> Cc: freebsd-hackers@freebsd.org Subject: Re: Standard C-macro scripting X-BeenThere: freebsd-hackers@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list Reply-To: hselasky@c2i.net List-Id: Technical Discussions relating to FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 14 Dec 2005 00:04:39 -0000 On Tuesday 13 December 2005 20:48, John Baldwin wrote: > On Tuesday 13 December 2005 01:36 pm, Hans Petter Selasky wrote: > > Hi, > > > > ... > > > > What do you think about using C-macros like a scripting language? > > Honestly, I think I've now been scarred for life. :-/ I think that this > stuff would be so obscure that no one else would be able to help with > maintenace. Macros are easy. It is just concat, stringify and expand. Maybe you have to think more about it before you get it. I am probably too used to it. What is the alternative? An Awk script would require a lot more code and it cannot be called from a C-program when it is compiling. Consider the following: One has some "enums" and wants to declare these and make a debugging table at the same time. The problem is that at some time one adds another "enum" and then the debugging table is out of sync. Using an Awk/Perl/XXX script to keep things in sync would be overkill. If one makes some standard macros that do standard transforms, then people will not get confused. I have started out to standardise this, for example one macro to make enums, MAKE_ENUM, and another to make tables of different kinds, MAKE_TABLE. There might be room for improvement. #define _MAKE_ENUM(enum,value,arg...) \ enum value, \ /**/ #define MAKE_ENUM(macro,end...) \ enum { macro(_MAKE_ENUM) end } \ /**/ #define __MAKE_TABLE(a...) a /* double pass to expand all macros */ #define _MAKE_TABLE(a...) (a), /* add comma */ #define MAKE_TABLE(m,field,p,a...) m##_##field p = \ { __MAKE_TABLE(m(m##_##field _MAKE_TABLE)) a } What the macros above do, is not difficult to understand at all. It is bare simple. Here is the definition of some enum series: #define MY_ENUMS_DEFAULT_DRIVER_DESC(enum,val,desc) desc #define MY_ENUMS(m)\ m(MY_ENUM_UNKNOWN ,,"unknown")\ m(MY_ENUM_YYY ,,"yyy ...")\ m(MY_ENUM_DAIC ,,"zzz ...")\ /**/ Here is the declaration: MAKE_ENUM(MY_ENUMS, N_MY_ENUMS); Here is the debugging table: static const char * const MAKE_TABLE(MY_ENUMS,DEFAULT_DRIVER_DESC,[]); Because the "MAKE_ENUM" macro only use the two first arguments passed to "m" in "MY_ENUMS", the other arguments can be used for other purpose, and one can list more information: Here is a real example of a state machine: #define L3_STATES(m)/* \ m(----------------,,--------,-------------,-------------------------,------)*\ m( ,,timeout , timeout , , q931 )*\ m( state ,,delay , state , desc , conv.)*\ m(----------------,,--------,-------------,-------------------------,------)*/ \ m( ST_L3_U0 ,, 0/*hz*/, ST_L3_U0 , "Null" , 0x00 )\ \ m( ST_L3_OUTGOING ,, 8/*hz*/, ST_L3_U0 , "Outgoing initialized" , 0x00 )\ m( ST_L3_U1 ,, 8/*hz*/, ST_L3_U0 , "Outgoing setup (U1)" , 0x01 )\ m( ST_L3_U2 ,,16/*hz*/, ST_L3_U0 , "Outgoing setup (U2)" , 0x02 )\ m( ST_L3_U2_ACK ,,16/*hz*/, ST_L3_U0 , "Outgoing setup (U2)" , 0x02 )\ m( ST_L3_U3 ,, 8/*hz*/, ST_L3_U3_TO , "Outgoing proceeding" , 0x03 )\ m( ST_L3_U3_TO ,, 4/*hz*/, ST_L3_U0 , "Outgoing proceeding" , 0x03 )\ \ m( ST_L3_U4 ,, 8/*hz*/, ST_L3_U4_TO , "Outgoing delivered" , 0x04 )\ m( ST_L3_U4_TO ,, 4/*hz*/, ST_L3_U0 , "Outgoing delivered" , 0x04 )\ \ m( ST_L3_INCOMING ,, 8/*hz*/, ST_L3_U0 , "Incoming initialized" , 0x00 )\ m( ST_L3_IN_ACK ,,16/*hz*/, ST_L3_U0 , "Incoming initialized" , 0x19 )\ m( ST_L3_U6 ,, 8/*hz*/, ST_L3_U0 , "Incoming present" , 0x06 )\ m( ST_L3_U7 ,, 8/*hz*/, ST_L3_U7_TO , "Incoming alerted" , 0x07 )\ m( ST_L3_U7_TO ,, 4/*hz*/, ST_L3_U0 , "Incoming alerted" , 0x07 )\ m( ST_L3_U8 ,, 4/*hz*/, ST_L3_U0 , "Incoming connecting" , 0x08 )\ \ m( ST_L3_UA ,, 8/*hz*/, ST_L3_UA_TO , "Active" , 0x0A )\ m( ST_L3_UA_TO ,, 4/*hz*/, ST_L3_U0 , "Active" , 0x0A )\ \ m( ST_L3_UC ,, 8/*hz*/, ST_L3_UC_TO , "Disconnected" , 0x0C )\ m( ST_L3_UC_TO ,, 4/*hz*/, ST_L3_U0 , "Disconnected" , 0x0C )\ /**/ Isn't the state-machine above easy to edit and understand ? What is wrong about that? And how would you solve it? --HPS