From owner-cvs-all Thu Feb 8 23:35:16 2001 Delivered-To: cvs-all@freebsd.org Received: from info.iet.unipi.it (info.iet.unipi.it [131.114.9.184]) by hub.freebsd.org (Postfix) with ESMTP id 7CF6237B4EC; Thu, 8 Feb 2001 23:34:51 -0800 (PST) Received: (from luigi@localhost) by info.iet.unipi.it (8.9.3/8.9.3) id IAA31362; Fri, 9 Feb 2001 08:35:36 +0100 (CET) (envelope-from luigi) From: Luigi Rizzo Message-Id: <200102090735.IAA31362@info.iet.unipi.it> Subject: QUEUE macros considered harmful (was Re: cvs commit: src/usr.bin/lam lam.c) In-Reply-To: from Bruce Evans at "Feb 9, 2001 05:55:42 pm" To: Bruce Evans Date: Fri, 9 Feb 2001 08:35:35 +0100 (CET) Cc: Peter Wemm , Mark Murray , Mike Heffner , cvs-committers@FreeBSD.ORG, cvs-all@FreeBSD.ORG X-Mailer: ELM [version 2.4ME+ PL61 (25)] MIME-Version: 1.0 Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: 7bit Sender: owner-cvs-all@FreeBSD.ORG Precedence: bulk X-Loop: FreeBSD.ORG > __P(()) is much less visually offensive than things like LIST_FOREACH() > which have been growing like weeds lately. well i would say that they fall in the same category. Personally i find these macro-extensions-to-the-language very annoying and of questionable usefulness in many cases. According to the manpage, we have: 12 macros for singly linked lists (SLIST) 13 macros for singly linked tail queues (STAILQ) 11 macros for [doubly-linked] lists (LIST) 15 macros for [doubly-linked] tail queues (TAILQ) 15 macros for [doubly-linked ?] circular queues (CIRCLEQ) and apart from the number of them, the interface is not always obvious, the manpage is not consistent, and the way they are used is worth a prize at the Obfuscated Programming contest. Simple example taken from the firewall code: the manpage says that LIST_ENTRY(TYPE) "declares a structure", but 'TYPE' is not really a type, (the real type 'struct TYPE'), and the macro declares a type, not the actual object. The LIST macros are then used as follows: struct ip_fw_chain { LIST_ENTRY(ip_fw_chain) chain; struct ip_fw *rule; }; ... LIST_HEAD (ip_fw_head, ip_fw_chain) ip_fw_chain; ... chain = LIST_FIRST(&ip_fw_chain); for (; chain; chain = LIST_NEXT(chain, chain)) { with a wonderful mix of structures and objects and fields with the same or similar names. In my simple world i would have done the following: struct ip_fw_chain { struct ip_fw_chain *next ; struct ip_fw *rule; } ; ... struct ip_fw_chain *ip_fw_chain_head ; chain = ip_fw_chain_head ; for (; chain ; chain = chain->next) { which is infinitely more readable. Even the macros for inserting into the list are totally useless and extremely obfuscating, because there are two different ones depending on the insert position (HEAD or in the middle) and the programmer (obviously) must know how to scan a single-linked list. I can admit that there are some cases where a (limited) use of such macros can simplify life and reduce the chance of errors, but my feeling is that we are really abusing these macros. Thanks for bringing up the topic! cheers luigi ----------------------------------+----------------------------------------- Luigi RIZZO, luigi@iet.unipi.it . ACIRI/ICSI (on leave from Univ. di Pisa) http://www.iet.unipi.it/~luigi/ . 1947 Center St, Berkeley CA 94704 Phone (510) 666 2927 . ----------------------------------+----------------------------------------- To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe cvs-all" in the body of the message