3
// K&R syntax
int foo(a, p) 
int a; 
char *p; 
{ 
    return 0; 
}

// ANSI syntax
int foo(int a, char *p) 
{ 
    return 0; 
}

As you see, in K&R style, the types of variables are declared in new lines instead of in the braces. How to convert a K&R function declaration to an ANSI function declaration automatically? Does anybody know such an easy-to-use tool in Linux?

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
user1038013
  • 83
  • 1
  • 5
  • Check out the `indent` utility, but I think that only adjusts whitespace and isn't entirely what you want. – a paid nerd Nov 09 '11 at 16:58
  • Way late here, but **never** create prototypes for K&R functions. K&R functions assume their arguments have undergone [default argument promotions](https://stackoverflow.com/questions/1255775/default-argument-promotions-in-c-function-calls). Functions called with prototypes do not promote arguments other than varargs. That mismatch **will break your program**. – Andrew Henle Jul 25 '22 at 17:02

4 Answers4

3

You can use cproto or protoize (part of GCC) to generate function prototypes or convert old style (K&R) functions to ANSI format.

schot
  • 10,958
  • 2
  • 46
  • 71
  • I think `cproto` is now the best available choice. It isn't perfect; it gets confused by attributes in system headers on Linux, sometimes. However, if you generate headers, rather than converting in situ, it seems to work OK. The `protoize` code has not been a part of GCC for a number of years now. – Jonathan Leffler Jul 29 '12 at 08:33
  • 1
    protoize hasn't been part of GCC for quite some time now. –  Jul 13 '12 at 17:49
  • @JonathanLeffler *However, if you generate headers, rather than converting in situ* Waaay late here, but if you generate headers without updating the functions themselves, you **will break things**. K&R functions assume their arguments have undergone default argument promotions. Functions called via prototype do not perform those promotions... – Andrew Henle Jul 25 '22 at 17:04
  • @AndrewHenle — yes, you have to convert both source and headers. The problem is/was that cproto doesn't handle (some of) the Linux headers very well, and converting them in situ caused problems, whereas generating the headers anew worked reasonably well (and you could integrate the generated header information back into the original headers, removing any K&R declarations, etc. So, I was not advocating "only convert the headers"; I was advocating "convert headers by generating the declarations from the source code" because, in my experience, that worked better. – Jonathan Leffler Jul 25 '22 at 17:18
  • @JonathanLeffler I know you understand that. ;-) My comment was directed at anyone reading who might think it's a good idea to create headers with prototypes for legacy K&R functions without updating the functions themselves. Sorry that wasn't clear. – Andrew Henle Jul 25 '22 at 19:12
0

Since You wanna convert a multiline string, you chould consider perl

you have

void old_style( c , a ) char c; int a; { /* some multiline code */ }

and must have

void old_style( char c, int a) {}

So

perl -i.bkp -nle 's/\((void|int|char|float|long) [a-zA-Z0-9_-]*\)([a-zA-Z0-9_-] ?,[a-zA-Z0-9_-] ?)\(.*{\)/\1(\2)/g'

or something like it, would do the trick.

It would be easier to tackle down the correct regex to this if you try it out and post in comments the output of

diff file.c file.c.bkp

for each of your source files.

Rafareino
  • 2,515
  • 1
  • 19
  • 26
  • Just seen that this question was answered, I wanna try cproto in some of my old code and share results here! Looks promising. – Rafareino Nov 09 '13 at 20:10
0
  1. if you want to create standard C prototypes for a .h file use mkproto.c

mkproto thisoldfile.c > thisoldfile.h

You then could also paste over the old K&R code in the C file definition if desired.


Another answer by Robert contained the following (useful) information before it was deleted for being a 'link-only' answer:

You can find mkproto.c at:

https://www.pcorner.com/list/C

There are plenty of other utilities there.

The site hosts two versions of "mkproto" — MKPROTO.ZIP dated 1989-09-07 and MKPROTOB.ZIP dated 1992-06-27. You have to register with the host site, The Programmer's Corner, to download the files. The files appear about 2/3 of the way down a long page of possible downloads.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
MarkT
  • 21
  • 2
  • Again, late here, but you should **NEVER** create prototypes for K&R functions unless you change the functions to up-to-date definitions. K&R functions assume their arguments have undergone default argument promotions, but the caller will not do those argument promotions if the call was made with a function prototype. – Andrew Henle Jul 25 '22 at 17:06
  • 1
    Despite the age of the source code, both MKPROTO.ZIP and MKPROTOB.ZIP contain source code that can be compiled by GCC 11.2.0 with no warning options set (that is, `gcc -o mkproto mkproto.c` compiles cleanly for both). The ZIP files contain various Windows binaries (`MKPROTO.EXE`, `MKPROTO.COM`, `PROTOGEN.COM`) too. Everything is upper-case, of course, and the source code has DOS/Windows CRLF line endings (no big surprises there). – Jonathan Leffler Jul 25 '22 at 17:58
0

My gcc installation had neither cproto nor mkproto. But I did have Vim and I figured out a global substitute to do this one parameter at a time...

:%s/^\(\%(\w\+\%(\s*\*\+\s*\|\s\+\)\)\+\)\(\w\+\)\s*(\@=\(.\{-}\)\([(,)]\)\s*\(\w\+\)\s*\([,)].*\)\n\s*\(.\{-}\)\5\([^;]*\);/\1\2\3\4\7\5\8\6/

where the recorded subexpressions are:

  1. the function return type
  2. the function name
  3. the already-prototyped parameters (if any)
  4. the delimiter before the next K&R parameter to fix - '(' or ','
  5. the next K&R parameter to fix
  6. the following delimiter - ',' or ')' followed by any remaining (unprocessed) K&R parameter identifiers and closing ')'
  7. the parameter's type
  8. the parameter's post-identifier characters (e.g., brackets)

Repeat until no more matches in the file. Note, the pattern presumes the K&R function declaration is on one line, followed by individual parameter declarations on successive lines.

Two applications of this substitute successfully processes:

int main(argc,argv)
  int argc;
  char *argv[];
{
  printf("Hello world!\n");
  return 0;
}

into:

int main(int argc,char *argv[])
{
  printf("Hello world!\n");
  return 0;
}
Firstrock
  • 931
  • 8
  • 5