Back to index

plt-scheme  4.2.1
Defines | Functions
ansi2knr.c File Reference
#include <stdio.h>
#include <ctype.h>
#include <string.h>

Go to the source code of this file.

Defines

#define is_ascii(c)   1
#define is_space(c)   (is_ascii(c) && isspace(c))
#define is_alpha(c)   (is_ascii(c) && isalpha(c))
#define is_alnum(c)   (is_ascii(c) && isalnum(c))
#define isidchar(ch)   (is_alnum(ch) || (ch) == '_')
#define isidfirstchar(ch)   (is_alpha(ch) || (ch) == '_')
#define bufsize   5000 /* arbitrary size */

Functions

char * malloc ()
int free ()
char * skipspace ()
int writeblanks ()
int test1 ()
int convert1 ()
int main (int argc, argv)
char * skipspace (char *p, int dir)
int writeblanks (char *start, char *end)
int test1 (char *buf)
int convert1 (char *buf, FILE *out, int header, int convert_varargs)

Define Documentation

#define bufsize   5000 /* arbitrary size */
#define is_alnum (   c)    (is_ascii(c) && isalnum(c))

Definition at line 306 of file ansi2knr.c.

#define is_alpha (   c)    (is_ascii(c) && isalpha(c))

Definition at line 305 of file ansi2knr.c.

#define is_ascii (   c)    1

Definition at line 299 of file ansi2knr.c.

#define is_space (   c)    (is_ascii(c) && isspace(c))

Definition at line 304 of file ansi2knr.c.

#define isidchar (   ch)    (is_alnum(ch) || (ch) == '_')

Definition at line 309 of file ansi2knr.c.

#define isidfirstchar (   ch)    (is_alpha(ch) || (ch) == '_')

Definition at line 310 of file ansi2knr.c.


Function Documentation

Here is the caller graph for this function:

int convert1 ( char *  buf,
FILE *  out,
int  header,
int  convert_varargs 
)

Definition at line 528 of file ansi2knr.c.

{      char *endfn;
       register char *p;
       char **breaks;
       unsigned num_breaks = 2;    /* for testing */
       char **btop;
       char **bp;
       char **ap;
       char *vararg = 0;

       /* Pre-ANSI implementations don't agree on whether strchr */
       /* is called strchr or index, so we open-code it here. */
       for ( endfn = buf; *(endfn++) != '('; )
         ;
top:   p = endfn;
       breaks = (char **)malloc(sizeof(char *) * num_breaks * 2);
       if ( breaks == 0 )
          {   /* Couldn't allocate break table, give up */
              fprintf(stderr, "Unable to allocate break table!\n");
              fputs(buf, out);
              return -1;
          }
       btop = breaks + num_breaks * 2 - 2;
       bp = breaks;
       /* Parse the argument list */
       do
          {   int level = 0;
              char *lp = NULL;
              char *rp;
              char *end = NULL;

              if ( bp >= btop )
                 {   /* Filled up break table. */
                     /* Allocate a bigger one and start over. */
                     free((char *)breaks);
                     num_breaks <<= 1;
                     goto top;
                 }
              *bp++ = p;
              /* Find the end of the argument */
              for ( ; end == NULL; p++ )
                 {   switch(*p)
                        {
                        case ',':
                            if ( !level ) end = p;
                            break;
                        case '(':
                            if ( !level ) lp = p;
                            level++;
                            break;
                        case ')':
                            if ( --level < 0 ) end = p;
                            else rp = p;
                            break;
                        case '/':
                            p = skipspace(p, 1) - 1;
                            break;
                        default:
                            ;
                        }
                 }
              /* Erase any embedded prototype parameters. */
              if ( lp )
                writeblanks(lp + 1, rp);
              p--;                 /* back up over terminator */
              /* Find the name being declared. */
              /* This is complicated because of procedure and */
              /* array modifiers. */
              for ( ; ; )
                 {   p = skipspace(p - 1, -1);
                     switch ( *p )
                        {
                        case ']':  /* skip array dimension(s) */
                        case ')':  /* skip procedure args OR name */
                        {   int level = 1;
                            while ( level )
                             switch ( *--p )
                               {
                               case ']': case ')': level++; break;
                               case '[': case '(': level--; break;
                               case '/': p = skipspace(p, -1) + 1; break;
                               default: ;
                               }
                        }
                            if ( *p == '(' && *skipspace(p + 1, 1) == '*' )
                               {   /* We found the name being declared */
                                   while ( !isidfirstchar(*p) )
                                     p = skipspace(p, 1) + 1;
                                   goto found;
                               }
                            break;
                        default:
                            goto found;
                        }
                 }
found:        if ( *p == '.' && p[-1] == '.' && p[-2] == '.' )
                {    if ( convert_varargs )
                       {    *bp++ = "va_alist";
                            vararg = p-2;
                       }
                     else
                       {    p++;
                            if ( bp == breaks + 1 )     /* sole argument */
                              writeblanks(breaks[0], p);
                            else
                              writeblanks(bp[-1] - 1, p);
                            bp--;
                       }
                 }
              else
                 {   while ( isidchar(*p) ) p--;
                     *bp++ = p+1;
                 }
              p = end;
          }
       while ( *p++ == ',' );
       *bp = p;
       /* Make a special check for 'void' arglist */
       if ( bp == breaks+2 )
          {   p = skipspace(breaks[0], 1);
              if ( !strncmp(p, "void", 4) )
                 {   p = skipspace(p+4, 1);
                     if ( p == breaks[2] - 1 )
                        {   bp = breaks;  /* yup, pretend arglist is empty */
                            writeblanks(breaks[0], p + 1);
                        }
                 }
          }
       /* Put out the function name and left parenthesis. */
       p = buf;
       while ( p != endfn ) putc(*p, out), p++;
       /* Put out the declaration. */
       if ( header )
         {    fputs(");", out);
              for ( p = breaks[0]; *p; p++ )
                if ( *p == '\r' || *p == '\n' )
                  putc(*p, out);
         }
       else
         {    for ( ap = breaks+1; ap < bp; ap += 2 )
                {    p = *ap;
                     while ( isidchar(*p) )
                       putc(*p, out), p++;
                     if ( ap < bp - 1 )
                       fputs(", ", out);
                }
              fputs(")  ", out);
              /* Put out the argument declarations */
              for ( ap = breaks+2; ap <= bp; ap += 2 )
                (*ap)[-1] = ';';
              if ( vararg != 0 )
                {    *vararg = 0;
                     fputs(breaks[0], out);             /* any prior args */
                     fputs("va_dcl", out);              /* the final arg */
                     fputs(bp[0], out);
                }
              else
                fputs(breaks[0], out);
         }
       free((char *)breaks);
       return 0;
}

Here is the call graph for this function:

int free ( )
int main ( int  argc,
argv   
)

Definition at line 320 of file ansi2knr.c.

{      FILE *in, *out;
#define bufsize 5000               /* arbitrary size */
       char *buf;
       char *line;
       char *more;
       /*
        * In previous versions, ansi2knr recognized a --varargs switch.
        * If this switch was supplied, ansi2knr would attempt to convert
        * a ... argument to va_alist and va_dcl; if this switch was not
        * supplied, ansi2knr would simply drop any such arguments.
        * Now, ansi2knr always does this conversion, and we only
        * check for this switch for backward compatibility.
        */
       int convert_varargs = 1;

       if ( argc > 1 && argv[1][0] == '-' )
         {    if ( !strcmp(argv[1], "--varargs") )
                {    convert_varargs = 1;
                     argc--;
                     argv++;
                }
              else
                {    fprintf(stderr, "Unrecognized switch: %s\n", argv[1]);
                     exit(1);
                }
         }
       switch ( argc )
          {
       default:
              printf("Usage: ansi2knr input_file [output_file]\n");
              exit(0);
       case 2:
              out = stdout;
              break;
       case 3:
              out = fopen(argv[2], "w");
              if ( out == NULL )
                 {   fprintf(stderr, "Cannot open output file %s\n", argv[2]);
                     exit(1);
                 }
          }
       in = fopen(argv[1], "r");
       if ( in == NULL )
          {   fprintf(stderr, "Cannot open input file %s\n", argv[1]);
              exit(1);
          }
       fprintf(out, "#line 1 \"%s\"\n", argv[1]);
       buf = malloc(bufsize);
       line = buf;
       while ( fgets(line, (unsigned)(buf + bufsize - line), in) != NULL )
          {
test:         line += strlen(line);
              switch ( test1(buf) )
                 {
              case 2:                     /* a function header */
                     convert1(buf, out, 1, convert_varargs);
                     break;
              case 1:                     /* a function */
                     /* Check for a { at the start of the next line. */
                     more = ++line;
f:                   if ( line >= buf + (bufsize - 1) ) /* overflow check */
                       goto wl;
                     if ( fgets(line, (unsigned)(buf + bufsize - line), in) == NULL )
                       goto wl;
                     switch ( *skipspace(more, 1) )
                       {
                       case '{':
                         /* Definitely a function header. */
                         convert1(buf, out, 0, convert_varargs);
                         fputs(more, out);
                         break;
                       case 0:
                         /* The next line was blank or a comment: */
                         /* keep scanning for a non-comment. */
                         line += strlen(line);
                         goto f;
                       default:
                         /* buf isn't a function header, but */
                         /* more might be. */
                         fputs(buf, out);
                         strcpy(buf, more);
                         line = buf;
                         goto test;
                       }
                     break;
              case -1:             /* maybe the start of a function */
                     if ( line != buf + (bufsize - 1) ) /* overflow check */
                       continue;
                     /* falls through */
              default:             /* not a function */
wl:                  fputs(buf, out);
                     break;
                 }
              line = buf;
          }
       if ( line != buf )
         fputs(buf, out);
       free(buf);
       fclose(out);
       fclose(in);
       return 0;
}

Here is the call graph for this function:

char* malloc ( )
char* skipspace ( )

Here is the caller graph for this function:

char* skipspace ( char *  p,
int  dir 
)

Definition at line 428 of file ansi2knr.c.

{      for ( ; ; )
          {   while ( is_space(*p) )
                p += dir;
              if ( !(*p == '/' && p[dir] == '*') )
                break;
              p += dir;  p += dir;
              while ( !(*p == '*' && p[dir] == '/') )
                 {   if ( *p == 0 )
                       return p;   /* multi-line comment?? */
                     p += dir;
                 }
              p += dir;  p += dir;
          }
       return p;
}
int test1 ( )

Here is the caller graph for this function:

int test1 ( char *  buf)

Definition at line 476 of file ansi2knr.c.

{      register char *p = buf;
       char *bend;
       char *endfn;
       int contin;

       if ( !isidfirstchar(*p) )
         return 0;          /* no name at left margin */
       bend = skipspace(buf + strlen(buf) - 1, -1);
       switch ( *bend )
          {
          case ';': contin = 0 /*2*/; break;
          case ')': contin = 1; break;
          case '{': return 0;             /* not a function */
          case '}': return 0;             /* not a function */
          default: contin = -1;
          }
       while ( isidchar(*p) )
         p++;
       endfn = p;
       p = skipspace(p, 1);
       if ( *p++ != '(' )
         return 0;          /* not a function */
       p = skipspace(p, 1);
       if ( *p == ')' )
         return 0;          /* no parameters */
       /* Check that the apparent function name isn't a keyword. */
       /* We only need to check for keywords that could be followed */
       /* by a left parenthesis (which, unfortunately, is most of them). */
          {   static char *words[] =
                 {   "asm", "auto", "case", "char", "const", "double",
                     "extern", "float", "for", "if", "int", "long",
                     "register", "return", "short", "signed", "sizeof",
                     "static", "switch", "typedef", "unsigned",
                     "void", "volatile", "while", 0
                 };
              char **key = words;
              char *kp;
              int len = endfn - buf;

              while ( (kp = *key) != 0 )
                 {   if ( strlen(kp) == len && !strncmp(kp, buf, len) )
                       return 0;   /* name is a keyword */
                     key++;
                 }
          }
       return contin;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int writeblanks ( char *  start,
char *  end 
)

Definition at line 452 of file ansi2knr.c.

{      char *p;
       for ( p = start; p < end; p++ )
         if ( *p != '\r' && *p != '\n' )
           *p = ' ';
       return 0;
}