[comp.lang.c++] inline management

nicb@ctr@italy.eu.net (Nicola Bernardini) (01/23/91)

Is there anybody that has an evident solution to managing
inline functions in a decent way?

My problem is the following:

1) I do not want to keep inlines in the definition files (.h)
   because I want to be able to move my functions in and out
   of inlining whenever I need to do so, without changing
   header files to my clients.

2) If I do not inline inside the header file, I have to provide
   inline declarations wherever I actually use these inlines
   thus generating a lot of duplicate code.

Up to now I haven't found a solution to this, but I made a very
simple hackwork which extracts inlines out of source files.
This way I can produce  inline header files (<.inl> ?)
that I can include wherever they are needed. The whole process
can be taken care by make and I do not need to worry about it.
But, again, it is far from elegant I must admit.

Anybody knows better?

(source to the inline extractor is right after the signature)
------------------------------------------
Nicola Bernardini -  nicb%ctr@italy.eu.net - nicb@ctr.UUCP
Centro Tempo Reale
Villa Strozzi
Via Pisana, 77
50143 Firenze
I T A L I A
Tel. ++3955/702444
Fax. ++3955/717712
----------------------CUT HERE
#! /bin/sh
# this is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh to create the files:
#	README
#	ie.l
#	ie.LC
# This archive created: Tue Jan 22 22:08:01 MET 1991 by nicb
#
#
export PATH; PATH=/bin:$PATH
#

if test -f README
then
echo shar: will not over-write existing file README
else
echo shar: extracting 'README',     699 characters
sed 's/^X//' > README <<'SHAR_EOF'
X
X
X	ie - by Nicola Bernardini
X
X	This is an inline function extractor. It allows
X	extraction of c++ inline functions out of regular
X	c++ syntax files.
X	ie accepts input from the standard in and produces
X	its output on the standard out.
X
X	It's written in the lex language, so you will have
X	to lex it and then compile it (no -ll options, though).
X
X	You may use this code freely provided you do not
X	try to sell it. Please retain the name of the author
X	wherever you find it so that other people you pass
X	this code to will be able to report bugs.
X
X	report any bugs to:
X
X	nicb%ctr@italy.eu.net (Nicola Bernardini)
X	nicb@ctr.i2unix.UUCP
X
XFILES
X
X	ie.l - the code
X	ie.LC - the man page
X	README - this file
SHAR_EOF
len=`wc -c < README`
if test $len !=     699 ; then
echo error: README was $len bytes long, should have been     699
fi
fi # end of overwriting check

if test -f ie.l
then
echo shar: will not over-write existing file ie.l
else
echo shar: extracting 'ie.l',    4432 characters
sed 's/^X//' > ie.l <<'SHAR_EOF'
X%{
X/*
X	ie.l
X
X	This is an inline function extractor. It allows
X	extraction of c++ inline functions out of regular
X	c++ syntax files.
X	ie accepts input from the standard in and produces
X	its output on the standard out.
X	
X*/
X#include	<stdio.h>
X#include	<string.h>
X#include	<sys/types.h>
X#include	<sys/errno.h>
X#include	<unistd.h>
X
X#define	LINE_SIZE	256
X#define outs(x)		{ fprintf (yyout, "%s", (char *) x); }
X
Xtypedef enum
X{
X	true,
X	false
X} boolean;
X
Xtypedef struct
X{
X	int ac;
X	char **av;
X} Args;
X
Xint numgraphs = 0;
Xboolean flag = false;
Xboolean pflag = false;
Xlong lineno = 1;
X
Xchar *file_name;
X#define set_name(s)	{ file_name = (char *) s; }
X#define get_name()	file_name
X#define USAGE_STRING	"Usage [-p] [file ...]\n"
X#define set_pflag()	{ pflag = true; }
X#define reset_pflag()	{ pflag = false; }
X
X%}
X
XEMPTY	^$
X
X%%
X"inline"	{ 
X			char buffer [LINE_SIZE];
X			flag = true; 
X			sprintf (buffer, "#line %ld \"%s\"\n",
X				lineno, get_name());
X			outs (buffer);
X			outs (yytext);
X		}
X"{"		{
X			if (flag == true) 
X			{
X				++numgraphs;
X				output (yytext[0]);
X			} 
X			else numgraphs = 0;
X		}
X"}"		{
X			if (flag == true) 
X			{
X				--numgraphs;
X				output (yytext[0]);
X			} 
X			else numgraphs = 0;
X			if (!numgraphs)
X			{
X				flag = false;
X				output ('\n');
X			}
X			else
X				flag = true;
X		}
X{EMPTY}		{ ; }
X.		{ if (flag == true) output (yytext[0]); }
X\n		{ ++lineno; if (flag == true) output (yytext[0]); }
X%%
X#ifdef _SCO_SYSV_
X#	ident	"@(#)ie.l	1.2 9/27/90"
X#endif /* _SCO_SYSV_ */
X
Xyywrap()
X{
X		/* this call must exist */
X}
X
Xtypedef enum
X{
X	FATAL,
X	NON_FATAL
X} Errcode;
X
Xchar *version()
X{
X	char *string = "ie version 1.2 9/27/90";
X
X	return string;
X}
X
Xvoid stop (c)
Xint c;
X{
X	exit(c);
X}
X
Xvoid error (s, ec)
Xchar *s;
XErrcode ec;
X{
X	fputs (s, stderr);
X	switch (ec)
X	{
X		default:
X		case FATAL:
X			stop (1);
X			break;
X		case NON_FATAL:
X			break;
X	}
X}
X
X
XFILE *getfile (s)
Xchar *s;
X{
X	int faccess = access (s, R_OK | F_OK);
X	FILE *retvalue;
X
X	if (faccess)
X	{
X		char buf [LINE_SIZE];
X		sprintf (buf, "file %s not found\n", s);
X		error (buf, NON_FATAL);
X		retvalue = (FILE *) NULL;
X	}
X	else
X		retvalue = fopen (s, "r");
X
X	return retvalue;
X}
X
XFILE *setfile (s)
Xchar *s;
X{
X	int faccess = access (s, W_OK);
X	FILE *retvalue;
X	extern int errno;
X
X	if (faccess && errno != ENOENT)
X	{
X		char buf [LINE_SIZE];
X		sprintf (buf, "Cannot create file %s. I die.\n", s);
X		error (buf, FATAL);
X		retvalue = (FILE *) NULL;
X	}
X	else
X		retvalue = fopen (s, "w");
X
X	return retvalue;
X}
X
Xchar *outname(s)
Xchar *s;
X{
X	char *suffix = ".inl", *place;
X	static char buffer [LINE_SIZE]; /* only one name at a time allowed */
X
X	strncpy (buffer, s, (size_t) LINE_SIZE);
X	
X	if ((place = strrchr (buffer, '.')) ==  (char *) NULL)
X	{
X		strcat (buffer, suffix);
X	}
X	else
X		strcpy (place, suffix);
X
X	return buffer;
X}
X
Xvoid lexit (fp)
XFILE *fp;
X{
X	yyin = fp;
X
X	while (!feof(yyin))
X		yylex();
X}
X
Xchar *strsub (s, old, new)
Xchar *s, old, new;
X{
X	char *p;
X
X	for (p = s; *p != '\0'; ++p)
X		if (*p == old)
X			*p = new;
X
X	return s;
X}
X
Xchar *head_define (s)
Xchar *s;
X{
X	static char name_define [LINE_SIZE]; /* only one name at a time */
X
X	sprintf (name_define, "_%s_", s);
X	strsub (name_define, '.', '_');
X
X	return name_define;
X}
X
Xvoid header (s)
Xchar *s;
X{
X	char buffer [LINE_SIZE];
X	char *name = head_define(s);
X	
X	sprintf (buffer, "/*\n\tFile %s: created by %s\n*/\n#ifndef %s\n#define %s\n", outname(s), version(), name, name);
X	outs (buffer);
X}
X
Xvoid trailer (s)
Xchar *s;
X{
X	char buffer [LINE_SIZE];
X	char *name = head_define(s);
X	
X	sprintf (buffer, "#endif /* %s */\n", name);
X	outs (buffer);
X}
X
XArgs *getargs (ac, av)
Xint ac;
Xchar **av;
X{
X	int c, errflg = 0;
X	static Args files;
X	extern char *optarg;
X	extern int optind;
X
X	while ((c = getopt(ac,av, "p")) != -1)
X		switch (c) 
X		{
X			case 'p':
X					set_pflag();
X					break;
X			case '?':
X					errflg++;
X					break;
X			default:
X					++errflg;
X					break;
X		}
X
X	if (errflg)
X		error (USAGE_STRING, FATAL);
X
X	files.ac = ac - optind + 1;
X	files.av = &av[optind-1];
X
X	return &files;
X}
X
Xmain(ac, av)
Xint ac;
Xchar **av;
X{
X	FILE *in;
X	Args *files = getargs (ac, av);
X
X	if (files->ac < 1)
X		lexit (stdin);
X	else
X		while (--files->ac)
X		{
X			lineno = 1;
X			set_name (*++files->av);
X			in = getfile(get_name());
X
X			if (in != (FILE *) NULL)
X			{
X				yyout = (pflag == true) ? stdout : 
X					setfile (outname(get_name()));
X				header (get_name());
X				lexit (in);
X				trailer (get_name());
X			}
X
X			if (pflag == false)
X				fclose (yyout);
X		}
X}
SHAR_EOF
len=`wc -c < ie.l`
if test $len !=    4432 ; then
echo error: ie.l was $len bytes long, should have been    4432
fi
fi # end of overwriting check

if test -f ie.LC
then
echo shar: will not over-write existing file ie.LC
else
echo shar: extracting 'ie.LC',    2054 characters
sed 's/^X//' > ie.LC <<'SHAR_EOF'
X.\"#ident "@(#)ie manpage (nicb@trxp7.UUCP) 1.2.1.1 91/01/22"
X.TH IE LOCAL "local addition" "Tempo Reale"
X.SH NAME
X.P
Xie \- \f2C++\fP inline extractor
X.SH SYNOPSIS
X.P
X\f3ie\fP [ -p ] [ \f2file\fP ... ]
X.SH DESCRIPTION
X.P
X.B ie
Xis a utility that allows
Xextraction of \f2C++\fP syntax inline functions
Xout of source code files.
X.P
XSeparated inline functions that appear in
X\f2C++\fP source code must be externally declarated
Xfor linkage purposes.
XThis process is a boring and
Xparticularly error prone one.
XCalled upon in a make process,
X.B ie
Xextracts and builds automatically
Xthe files that contain the external inline declarations,
Xthus relieving the user
Xfrom doing it manually.
X.P
X.B ie
Xtakes its input from one or more
X.I file s
Xor from stdin if no files are explicitly written
Xin the command line.
X.B ie
Xproduces its output
Xon files created appending the suffix \f2.inl\fP
Xto \f2file\fP or substituting the last suffix of the file.
XIf the
X.B -p
Xoption is specified,
Xthe output of
X.B ie
Xappears on stdout and no files are created.
X.P
XThe created files are surrounded by
X.I #ifdef 's
Xand
X.I #endif s
Xto permit exclusion of the content of the file
Xby control of the definition.
X.P
XAs an example, consider the code:
X.sp
X.ft CW
X.nf
X	#define _foo_inl_
X	#include "foo.inl"
X.fi
X.sp
XThe definition \f(CW_foo_inl_\fP is needed if
Xexclusion of the contents of foo.inl is wanted.
XThe \f(CWdefine\fP name is created by substituting
Xall dots by underscores (_) and by inserting
Xand appending underscores at the beginning
Xand at the end of the string.
X.ft
X.SH "SEE \ALSO"
X\f3CC\fP(1)
X.SH AUTHOR
X.nf
XNicola Bernardini
XCentro di Ricerca, Produzione e Didattica Musicale \f3Tempo Reale\fP
XVilla Strozzi
XVia Pisana, 77
X50143 Firenze
XITALIA
Xe-mail: nicb@trxp7.UUCP
X.fi
X.SH IDENTIFICATION
X.nf
XAuthor: Nicola Bernardini
XAffiliation: Centro Tempo Reale
XRelease: 1.2.1.1
XThis is free software and it is not copyrighted.
X.SH BUGS
XI think
X.B ie
Xis too simple to have significant bugs,
Xbut you never know.
XLet the author know if you find bugs,
Xand he'll be glad to work on it.
SHAR_EOF
len=`wc -c < ie.LC`
if test $len !=    2054 ; then
echo error: ie.LC was $len bytes long, should have been    2054
fi
fi # end of overwriting check
exit 0
-- 
------------------------------------------
Nicola Bernardini -  nicb%ctr@italy.eu.net
Centro Tempo Reale
Villa Strozzi

davidm@uunet.UU.NET (David S. Masterson) (01/25/91)

>>>>> On 22 Jan 91 21:31:15 GMT, nicb@ctr@italy.eu.net (Nicola Bernardini) said:

Nicola> My problem is the following:

Nicola> 1) I do not want to keep inlines in the definition files (.h) because
Nicola> I want to be able to move my functions in and out of inlining whenever
Nicola> I need to do so, without changing header files to my clients.

Presumably, the header files in declaring a class would declare its member
functions.  These declarations should include a specification as to whether
they are inlined or not (even if the definition is not in the header file).
Otherwise, the C++ compiler might set up an 'outlined' reference that it
expects it will need to fill in later (saw this in C++ 1.2 -- don't know if it
changed).  Basically, if your clients don't see that certain functions are
inlined, how could they 'do the right thing' with your objects?

Nicola> 2) If I do not inline inside the header file, I have to provide inline
Nicola> declarations wherever I actually use these inlines thus generating a
Nicola> lot of duplicate code.

Your suggestion of building a .INL file could work especially if the .INL
includes the .H file.  Then, as you use objects, you just include the .INL to
define the object and not the .H.  Then again, though, doing this means that
your .INL file is a .H file under a different name.  What would you have
gained?
--
====================================================================
David Masterson					Consilium, Inc.
(415) 691-6311					640 Clyde Ct.
uunet!cimshop!davidm				Mtn. View, CA  94043
====================================================================
"If someone thinks they know what I said, then I didn't say it!"

rfg@NCD.COM (Ron Guilmette) (02/05/91)

In article <1991Jan22.213115.8716@ctr@italy.eu.net> nicb@ctr.UUCP (Nicola Bernardini) writes:
>Is there anybody that has an evident solution to managing
>inline functions in a decent way?
>
>My problem is the following:
>
>1) I do not want to keep inlines in the definition files (.h)
>   because I want to be able to move my functions in and out
>   of inlining whenever I need to do so, without changing
>   header files to my clients.

See the other article I just posted.  It describes an automatic way of
getting .h files generated for you (by your makefile).

Using my scheme, it is easy to change a given inline routine into a
non-inline and vise-versa.  All you have to do is to move it below
the line in your .C file which acts as the delimiter between the
"implementation" and the "interface" part.

Note however that such actions may cause the .h file to change (automatically)
and that this in turn may cause a bunch of recompilations, but that's ok.

-- 

// Ron Guilmette  -  C++ Entomologist
// Internet: rfg@ncd.com      uucp: ...uunet!lupine!rfg
// Motto:  If it sticks, force it.  If it breaks, it needed replacing anyway.

fuchs@it.uka.de (Harald Fuchs) (02/06/91)

rfg@NCD.COM (Ron Guilmette) writes:

>Using my scheme, it is easy to change a given inline routine into a
>non-inline and vise-versa.  All you have to do is to move it below
>the line in your .C file which acts as the delimiter between the
>"implementation" and the "interface" part.

As far as I know, there is a program named "GNU Emacs" which makes
moving text between files as easy as moving text within a file :-).
--

Harald Fuchs <fuchs@telematik.informatik.uni-karlsruhe.de>
<fuchs@telematik.informatik.uni-karlsruhe.dbp.de>   *gulp*

rfg@NCD.COM (Ron Guilmette) (02/08/91)

In article <fuchs.665771316@tmipi4> fuchs@it.uka.de (Harald Fuchs) writes:
>
>As far as I know, there is a program named "GNU Emacs" which makes
>moving text between files as easy as moving text within a file :-).


Yes, but I don't have to f*** around to get "key bindings" (so that
the bloody arrow keys work) when I use `vi'. :-)

Also, unlike Emacs, vi uses up somewhat less than twice the amount of
physical memory that I have on my machine. (1/2 :-)

-- 

// Ron Guilmette  -  C++ Entomologist
// Internet: rfg@ncd.com      uucp: ...uunet!lupine!rfg
// Motto:  If it sticks, force it.  If it breaks, it needed replacing anyway.