[comp.lang.c] Protoize/Unprotoize

rfg@ics.uci.edu (Ronald Guilmette) (06/04/90)

In article <1990May31.214655.18960@csrd.uiuc.edu> pommerel@sp14.csrd.uiuc.edu (Claude Pommerell) writes:
>
>I am looking for a portable converter from ANSI C syntax to
>traditional Kernighan&Ritchie syntax.
>
>It should run as a preprocessor...

What do you care *how* it runs, as long as it does the job?

>to get my ANSI C code portable to
>machines where there is no ANSI compiler or where the ANSI compiler's
>lacks vectorization or parallelization support.
>
>I am mainly interested to convert parameter lists...

I have a tool (called unprotoize) which can do this one part of the job only.
This is typically the majority of the work.  An announcement message for
unprotoize is provided below.

>...and to get constants
>and enum's converted into #define, or maybe expanded as constants in the
>generated C code.

Even many old (so-called) K&R compilers accept enum types.  You may not
have to convert these at all!

>
>A C++ to C translator would probably do the job...

Correction.  That would only do the job if your existing code is *also* C++
conformant.  (It probably isn't... there are lots of added rules for C++ that
don't exist in C.)

>...but I don't want to start porting something too big.

You may not like unprotoize then.

>A portable YACC or C source would be perfect.

Protoize, unprotoize, and GCC are all fairly portable.

My standard blurb about protoize & unprotoize follow my signature below.

// Ron Guilmette (rfg@ics.uci.edu)
// C++ Entomologist
// Motto:  If it sticks, force it.  If it breaks, it needed replacing anyway.

-------------------------------------------------------------------------------
Protoize/Unprotoize
-------------------

This is a brief announcement concerning to two free software tools called
protoize and unprotoize.

Protoize is a tool to assist in the conversion of old-style (K&R) C code to
new-style ANSI C code or C++ code (with function prototypes).

Unprotoize is a tool to assist in the conversion of new-style ANSI C code
to old-style (K&R) C code without function prototypes.

Neither of these tools claims to do a complete conversion (there are too
many sniggling little incompatabilities) however the bulk of the work
(usually more than 90%) in such conversions usually involves function
prototypes.  This is the part of the job that protoize & unprotoize
can perform automatically (leaving you to contend only with the remaining
sniggling details).

The Protoize and Unprotoize tools have been built specifically for doing
these types of conversions on LARGE systems of C source code.  They are
fairly intelligent and are able to perform conversions of both function
definitions and function declarations, and they can do so over entire
groups of source files at a time.  Protoize can use information gleaned
from one source file to update other source files.  This capability is
most useful when one wants one's include files to contain ANSI C
(and/or C++) function prototypes.  Protoize is able to automagically
insert such prototypes into .h files based upon information it gets from
your .c files.  Likewise, extern function declarations appearing in one
.c file will be converted to prototype form based upon information gathered
from the actual function definitions in the same .c source file, or in
other .c files.

Protoize can also be used with your system's native "source flavor" lint
libraries to generate a complete set of fully prototyped "system" include
files.  Such a set can be useful for catching more function calling errors
at compile time.

Protoize and unprotoize work in conjunction with the GNU C compiler (GCC)
which is used as a front-end information gathering tool.  In order to
build or use protoize or unprotoize you must also build and use GCC.

Protoize, Unprotoize, and GCC are owned and operated by the Free Software
Foundation.  They are available to all under the terms and conditions of the
GNU Public Licence, a copy of which is provided with the source code for GCC.

Availability
------------

Protoize/Unprotoize version 1.07 and is now available for anonymous FTP from
ics.uci.edu.

Size of the protoize-1.07.Z file is 89135 bytes.

Protoize/Unprotoize 1.07 can also be obtained via anonymous UUCP from osu-cis.
(Contact for UUCP transfer is Karl Kleinpaste <karl@cis.ohio-state.edu>).
(European availablity of protoize/unprotoize is described below).

On ics.uci.edu, protoize/unprotoize 1.07 can be found as:

	~ftp/pub/protoize-1.07.Z
	~ftp/pub/protoize-1.07.93.Z

Version 1.07 is dramatically better than previous versions.
Substantial improvements have been made in robustness and ease-of-use.
If you tried protoize/unprotoize before and didn't like them, please try
them again.  You may be plesantly surprized.

This version has been pre-tested by several people on a number of different
machines and is belived to be quite portable and reasonably bug free.
(My special thanks to all the pre-testers!)

As with prior versions, the distribution file is a compressed *patch*
file (not a tar file) which should be applied to a pristine set of GCC
Version 1.36 source files.  (The file protoize-1.07.93.Z is also available
for those users now pre-testing GCC 1.36.93.  Size is 89029 bytes.
That version should also be used for GCC 1.37 until I have a chance to
create another patch file just for that version of GCC.)

The application of the protoize/unprotoize patches will result in the
creation of several new files.  Among these "additions" are the file
README_PROTOIZE and a common pre-man-page file called proto-unproto.1.
The latter file will be preprocessed into two man-page files (called
protoize.1 and unprotoize.1) by the (modified) Makefile during a normal
build of the (modified) GCC.

Because so many things have changed in this version, it is strongly advised
that you read the README_PROTOIZE file and the man pages again, even if
you have already been using prior versions of protoize/unprotoize.

As before, I welcome comments, suggestions, bug reports and (especially)
compliments.  User suggestions have been the major source of ideas for
new features up till now, and I'll try to be receptive if you have a new
idea for an additional feature.

Please let me know if you use these tools to do a conversion on any large
(i.e. >= 100k lines of code) system.

Note that when using protoize 1.07 you may occasionally get messages like:

	please add `extern foobar()' to SYSCALLS.c

These messages are an indication that your native "system" include files are
not yet in fully prototyped form.  For now, you should just ignore these
messages.  I am now developing a plan whereby protoize will be able to auto-
magically create protoized versions of system include files for a variety
of systems.  This scheme will probably make its debut in v1.08.  After that,
we can all (finally) get totally protoized.  (This will also be a major
benefit for C++ users.)

-----------------------------------------------------------------------------
European Availability:

Two sites are distributing protoize-1.07.Z in Europe:

	Protoize-1.07.Z can be retrieved by anonymous ftp from
	mizar.docs.uu.se (130.238.4.1).  Contact is Ove Ewerlid
	<ewerlid@mizar.docs.uu.se>.  The files are located in:

		~ftp/pub/gnu/protoize-1.07.Z
		~ftp/pub/gnu/protoize-1.07.93.Z

	(Thanks Ove!)

	---------------------------------------------------------------------

	Rijks Universiteit Utrecht (Utrecht University, Department of Computer
	Science).  Contact is Edwin Kremer <edwin@cs.ruu.nl>.

	It may be obtained either via anonymous FTP or by mail, as follows:

	* Anon FTP:
	    System:	sol.cs.ruu.nl [131.211.80.5]
	    Files:	~ftp/pub/GNU/protoize-1.07.Z
	    		~ftp/pub/GNU/protoize-1.07.93.Z

	* Mail Server:
	  European sites not having FTP access may retrieve it from the Rijks
	  Universiteit Utrecht by sending an email message to
	  <mail-server@cs.ruu.nl> with contents

	    path <your_valid_return_address>
	    btoa
	    send GNU/protoize-1.07.Z
	    end

	  Leave out the line with "btoa" if you prefer uuencoding.
	  Please use a domain-based return address, or you may loose out.

minow@mountn.dec.com (Martin Minow) (06/05/90)

In article <1990May31.214655.18960@csrd.uiuc.edu> pommerel@sp14.csrd.uiuc.edu
(Claude Pommerell) writes:
>
>I am looking for a portable converter from ANSI C syntax to
>traditional Kernighan&Ritchie syntax.

I've had good results by writing prototypes using the following process:

	/*
	 * prototype.h
	 */
	#ifdef _STDC_
	#if _STDC_ != 0
	#define _(x)	x
	#endif
	#endif
	#ifndef _STDC_
	#define _(x)	()
	#endif

	/*
	 * All functions are specified here:
	 */
	int		sample _((int, char *, struct foo));

The actual definition of a function uses the old -- but still valid -- syntax:

	int
	sample(i, cp, foostruct)
	int		i;
	char		*cp;
	struct foo	foostruct;
	...

The advantage is that your code remains maximally portable, yet you have
the advantage of type-safety where available.  The disadvantage is that
you *must* not presuppose other Ansi features, such as automatic conversion
of variables.  Also, the above doesn't handle variable-length argument lists.
(Also, strictly speaking, the macro '_' is reserved to the implementation).

The above should be portable to all C implementations since around 1978.

Martin Minow
minow@thundr.enet.dec.com

neil@yc.estec.nl (Neil Dixon) (06/05/90)

In article <1645@mountn.dec.com>, minow@mountn.dec.com (Martin Minow) writes:
|>In article <1990May31.214655.18960@csrd.uiuc.edu> pommerel@sp14.csrd.uiuc.edu
|>(Claude Pommerell) writes:
|>>
|>>I am looking for a portable converter from ANSI C syntax to
|>>traditional Kernighan&Ritchie syntax.
|>
|>I've had good results by writing prototypes using the following process:
|>
|>	/*
|>	 * prototype.h
|>	 */
|>	#ifdef _STDC_
|>	#if _STDC_ != 0
|>	#define _(x)	x
|>	#endif
|>	#endif
|>	#ifndef _STDC_
|>	#define _(x)	()
|>	#endif
|>
|>The above should be portable to all C implementations since around 1978.
|>
|>Martin Minow
|>minow@thundr.enet.dec.com

I used this scheme before we got an ANSI C compiler. When it arrived I
found that
there is one failing in using this method, which is the promotion of char and
float arguments to int and double respectively.  In this respect the old
and new
forms of function declaration are incompatible.

Neil Dixon <neil@yc.estec.nl>
UUCP:...!mcvax!esatst!neil, BITNET: NDIXON@ESTEC Thermal Control & Life Support
Division (YC) European Space Research and Technology Centre (ESTEC), Noordwijk,
The Netherlands.  

steve@taumet.com (Stephen Clamage) (06/05/90)

In article <1645@mountn.dec.com> minow@thundr.enet.dec.com (Martin Minow) writes:
>I've had good results by writing prototypes using the following process:
> [ details deleted ]
>	/*
>	 * All functions are specified here:
>	 */
>	int		sample _((int, char *, struct foo));
>The actual definition of a function uses the old -- but still valid -- syntax:
>	int sample(i, cp, foostruct)
>	int		i;
>	char		*cp;
>	struct foo	foostruct;

This will not work properly if any of the parameters are of type char,
short, or float.  If you are lucky, the ANSI compiler will complain about
mismatched prototype and defintion if the prototypes are in scope when the
definition occurs.

Consider the prototype
	int foo(float f);
and the definition
	int foo(f)
	float f;
	{ ... }
and the call to foo
	int x = foo(1.0);

With an ANSI compiler, the compiler will see the prototype and know that
foo expects to see a float parameter.  It will pass a float version of
1.0 to foo().

At the definition point, assume the compiler doesn't see the prototype.
It will see an old-style definition, and know that any caller will have
actually passed a double, not a float, by the rules of default promotion.
So it will expect to be passed a double, which is different in size and
in format from floats on most machines.

So the caller passes a different type than the called function expects.
Sad to say, your solution is not portable.

You can make it portable by conditionalizing the function definition:
#if __STDC__
	int sample(int i, char *cp, struct foo foostruct)
#else
	int sample(i, cp, foostruct)
	int		i;
	char		*cp;
	struct foo	foostruct;
#endif
{ ...
}

Unfortunately, this is very ugly and error-prone.
-- 

Steve Clamage, TauMetric Corp, steve@taumet.com

lerman@stpstn.UUCP (Ken Lerman) (06/06/90)

In article <1645@mountn.dec.com> minow@thundr.enet.dec.com (Martin Minow) writes:
>In article <1990May31.214655.18960@csrd.uiuc.edu> pommerel@sp14.csrd.uiuc.edu
...
>>I am looking for a portable converter from ANSI C syntax to
>>traditional Kernighan&Ritchie syntax.
>
>I've had good results by writing prototypes using the following process:
... <details of _ macro deleted>
>	/*
>	 * All functions are specified here:
>	 */
>	int		sample _((int, char *, struct foo));
>
>The actual definition of a function uses the old -- but still valid -- syntax:
>
>	int
>	sample(i, cp, foostruct)
>	int		i;
>	char		*cp;
>	struct foo	foostruct;
>	...
...<more stuff deleted>

>The above should be portable to all C implementations since around 1978.
>
>Martin Minow
>minow@thundr.enet.dec.com


Sorry, Martin, but IMHO that is not correct.  I don't have my copy of
the Standard handy, but the last time I tried that (or something like
that) I found that the DG Avvion (Greenhills) C compiler either
complained or generated bad code (I forget which) if a function was
declared with ANSI prototypes and defined without them.

At that time I investigated and found that ANSI leaves that case
"undefined".



Ken

karl@haddock.ima.isc.com (Karl Heuer) (06/06/90)

In article <5160@stpstn.UUCP> lerman@stpstn.UUCP (Ken Lerman) writes:
>In article <1645@mountn.dec.com> minow@thundr.enet.dec.com (Martin Minow) writes:
>>[Use a macro to get prototyped declarations conditional on __STDC__, but
>>continue to use the obsolescent syntax for function definitions]
>
>Sorry, Martin, but IMHO that is not correct.  I don't have my copy of
>the Standard handy, but the last time I tried that (or something like
>that) I found that the DG Avvion (Greenhills) C compiler either
>complained or generated bad code (I forget which) if a function was
>declared with ANSI prototypes and defined without them.

This is true in the case of formal parameters (e.g. char, float) that are
subject to promotion (see the FAQ list for the reason), but for functions with
no promotable arguments (this includes the entire standard library) there
should not be any such restriction.  As I recall, the Committee intentionally
allowed it, to make it easier to upgrade old code with new headers.

Karl W. Z. Heuer (karl@ima.ima.isc.com or harvard!ima!karl), The Walking Lint