Ethereal-dev: [ethereal-dev] Automatically generating "proto_register_XXX()" calls

Note: This archive is from the project's previous web site, ethereal.com. This list is no longer active.

From: Guy Harris <guy@xxxxxxxxxx>
Date: Mon, 18 Oct 1999 20:26:13 -0700 (PDT)
I stole from GDB a way of automatically generating calls to
initialization routines; it scans all the "packet*.c" files looking for
functions with a name like "proto_register_XXX()", and generates an
"init.c" file with a function "initialize_all_protocols()" that calls
all those functions; that function is then called from "proto.c".

(GDB's Makefile actually looks for the relevant ".o" files and generates
the list of ".c" files to scan based on that; I'm not sure why they did
that.)

It requires that you be able to say, in a Makefile:

	init.c: packet*.c

but GNU "make" handles that, and I think most if not all other modern
"make"s handle that (and we may require GNU "make" in any case).

I've attached a patch and a new file "init.h".
Index: proto.c
===================================================================
RCS file: /usr/local/cvsroot/ethereal/proto.c,v
retrieving revision 1.45
diff -r1.45 proto.c
63a64,67
> #ifndef __INIT_H__
> #include "init.h"
> #endif
> 
103,168d106
< /* centralization of registration functions */
< void proto_register_aarp(void);
< void proto_register_arp(void);
< void proto_register_ascend(void);
< void proto_register_atalk(void);
< void proto_register_atm(void);
< void proto_register_bgp(void);
< void proto_register_bootp(void);
< void proto_register_bpdu(void);
< void proto_register_cdp(void);
< void proto_register_clnp(void);
< void proto_register_cotp(void);
< void proto_register_data(void);
< void proto_register_dns(void);
< void proto_register_eth(void);
< void proto_register_fddi(void);
< void proto_register_frame(void);
< void proto_register_ftp(void);
< void proto_register_giop(void);
< void proto_register_gre(void);
< void proto_register_http(void);
< void proto_register_icmp(void);
< void proto_register_icmpv6(void);
< void proto_register_icp(void);
< void proto_register_igmp(void);
< void proto_register_ip(void);
< void proto_register_ipp(void);
< void proto_register_ipsec(void);
< void proto_register_ipv6(void);
< void proto_register_ipx(void);
< void proto_register_isakmp(void);
< void proto_register_lapb(void);
< void proto_register_llc(void);
< void proto_register_lpd(void);
< void proto_register_mp(void);
< void proto_register_nbipx(void);
< void proto_register_nbt(void);
< void proto_register_ncp(void);
< void proto_register_netbios(void);
< void proto_register_nntp(void);
< void proto_register_ntp(void);
< void proto_register_null(void);
< void proto_register_ospf(void);
< void proto_register_pim(void);
< void proto_register_pop(void);
< void proto_register_ppp(void);
< void proto_register_radius(void);
< void proto_register_rip(void);
< void proto_register_ripng(void);
< void proto_register_rsvp(void);
< void proto_register_rtsp(void);
< void proto_register_sdp(void);
< void proto_register_smb(void);
< void proto_register_sna(void);
< #if defined(WITH_SNMP_CMU) || defined(WITH_SNMP_UCD)
< void proto_register_snmp(void);
< #endif
< void proto_register_telnet(void);
< void proto_register_tftp(void);
< void proto_register_tcp(void);
< void proto_register_tr(void);
< void proto_register_trmac(void);
< void proto_register_udp(void);
< void proto_register_x25(void);
< void proto_register_yhoo(void);
< 
222,288c160,161
< 	/* Have each dissector register its protocols and fields. The
< 	 * order doesn't matter. Put the calls in alphabetical order
< 	 * just to make it easy. */
< 	proto_register_aarp();
< 	proto_register_arp();
< 	proto_register_ascend();
< 	proto_register_atalk();
< 	proto_register_atm();
< 	proto_register_bgp();
< 	proto_register_bootp();
< 	proto_register_bpdu();
< 	proto_register_cdp();
< 	proto_register_clnp();
< 	proto_register_cotp();
< 	proto_register_data();
< 	proto_register_dns();
< 	proto_register_eth();
< 	proto_register_fddi();
< 	proto_register_frame();
< 	proto_register_ftp();
< 	proto_register_giop();
< 	proto_register_gre();
< 	proto_register_http();
< 	proto_register_icmp();
< 	proto_register_icmpv6();
< 	proto_register_icp();
< 	proto_register_igmp();
< 	proto_register_ip();
< 	proto_register_ipp();
< 	proto_register_ipsec();
< 	proto_register_ipv6();
< 	proto_register_ipx();
< 	proto_register_isakmp();
< 	proto_register_lapb();
< 	proto_register_llc();
< 	proto_register_lpd();
< 	proto_register_mp();
< 	proto_register_nbipx();
< 	proto_register_nbt();
< 	proto_register_ncp();
< 	proto_register_netbios();
< 	proto_register_nntp();
< 	proto_register_ntp();
< 	proto_register_null();
< 	proto_register_ospf();
< 	proto_register_pim();
< 	proto_register_pop();
< 	proto_register_ppp();
< 	proto_register_radius();
< 	proto_register_rip();
< 	proto_register_ripng();
< 	proto_register_rsvp();
< 	proto_register_rtsp();
< 	proto_register_sdp();
< 	proto_register_smb();
< 	proto_register_sna();
< #if defined(WITH_SNMP_CMU) || defined(WITH_SNMP_UCD)
< 	proto_register_snmp();
< #endif
< 	proto_register_telnet();
< 	proto_register_tftp();
< 	proto_register_tcp();
< 	proto_register_tr();
< 	proto_register_trmac();
< 	proto_register_udp();
< 	proto_register_x25();
< 	proto_register_yhoo();
---
> 	/* Have each dissector register its protocols and fields. */
> 	initialize_all_protocols();
Index: Makefile.am
===================================================================
RCS file: /usr/local/cvsroot/ethereal/Makefile.am,v
retrieving revision 1.89
diff -r1.89 Makefile.am
53a54
> 	init.c         \
172a174,198
> 
> # We do this by grepping through sources.  If that turns out to be too slow,
> # maybe we could just require every .o file to have an initialization routine
> # of a given name (remote-udi.o -> _initialize_remote_udi, etc.).
> #
> # Formatting conventions:  The name of the _initialize_* routines must start
> # in column zero, and must not be inside #if.
> #
> # Note that the set of files with init functions might change, or the names
> # of the functions might change, so this files needs to depend on all the
> # object files that will be linked into gdb.
> 
> init.c: packet*.c
> 	@echo Making init.c
> 	@rm -f init.c-tmp
> 	@echo '/* Do not modify this file.  */' >init.c-tmp
> 	@echo '/* It is created automatically by the Makefile.  */'>>init.c-tmp
> 	@echo '#include "init.h"' >>init.c-tmp
> 	@echo 'void initialize_all_protocols(void) {' >>init.c-tmp
> 	@for f in packet*.c; do grep '^proto_register_[a-z_0-9A-Z]* *(' $$f 2>/dev/null; done | \
> 	sed -e 's/^.*://' -e 's/^\([a-z_0-9A-Z]*\).*/  {extern void \1 (void); \1 ();}/' >>init.c-tmp
> 	@echo '}' >>init.c-tmp
> 	@mv init.c-tmp init.c
> 
> .PRECIOUS: init.c
/* init.h
 * Definitions for protocol initialization
 *
 * $Id$
 *
 * Ethereal - Network traffic analyzer
 * By Gerald Combs <gerald@xxxxxxxx>
 * Copyright 1998 Gerald Combs
 *
 * 
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */

#ifndef __INIT_H__
#define __INIT_H__

extern void initialize_all_protocols(void);

#endif /* __INIT_H__ */