ansi2knr.c File Reference

#include <stdio.h>
#include <ctype.h>
#include <string.h>

Include dependency graph for ansi2knr.c:

Go to the source code of this file.

Defines

#define NULL   (0)
#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

Functions

char * malloc ()
int free ()
char * ppdirforward ()
char * ppdirbackward ()
char * skipspace ()
char * scanstring ()
int writeblanks ()
int test1 ()
int convert1 ()
int main (int argc, argv)
char * ppdirforward (char *p)
char * ppdirbackward (char *p, char *limit)
char * skipspace (char *p, int dir)
char * scanstring (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

Referenced by main().

#define is_alnum (  )     (is_ascii(c) && isalnum(c))

Definition at line 213 of file ansi2knr.c.

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

Definition at line 212 of file ansi2knr.c.

#define is_ascii (  )     1

Definition at line 206 of file ansi2knr.c.

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

Definition at line 211 of file ansi2knr.c.

Referenced by skipspace().

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

Definition at line 216 of file ansi2knr.c.

Referenced by convert1(), and test1().

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

Definition at line 217 of file ansi2knr.c.

Referenced by convert1(), and test1().

#define NULL   (0)


Function Documentation

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

Definition at line 556 of file ansi2knr.c.

References free(), isidchar, isidfirstchar, malloc(), NULL, scanstring(), skipspace(), and writeblanks().

00561 {       char *endfn;
00562         char *p;
00563         /*
00564          * The breaks table contains pointers to the beginning and end
00565          * of each argument.
00566          */
00567         char **breaks;
00568         unsigned num_breaks = 2;        /* for testing */
00569         char **btop;
00570         char **bp;
00571         char **ap;
00572         char *vararg = 0;
00573 
00574         /* Pre-ANSI implementations don't agree on whether strchr */
00575         /* is called strchr or index, so we open-code it here. */
00576         for ( endfn = buf; *(endfn++) != '('; )
00577           ;
00578 top:    p = endfn;
00579         breaks = (char **)malloc(sizeof(char *) * num_breaks * 2);
00580         if ( breaks == NULL )
00581            {    /* Couldn't allocate break table, give up */
00582                 fprintf(stderr, "Unable to allocate break table!\n");
00583                 fputs(buf, out);
00584                 return -1;
00585            }
00586         btop = breaks + num_breaks * 2 - 2;
00587         bp = breaks;
00588         /* Parse the argument list */
00589         do
00590            {    int level = 0;
00591                 char *lp = NULL;
00592                 char *rp = NULL;
00593                 char *end = NULL;
00594 
00595                 if ( bp >= btop )
00596                    {    /* Filled up break table. */
00597                         /* Allocate a bigger one and start over. */
00598                         free((char *)breaks);
00599                         num_breaks <<= 1;
00600                         goto top;
00601                    }
00602                 *bp++ = p;
00603                 /* Find the end of the argument */
00604                 for ( ; end == NULL; p++ )
00605                    {    switch(*p)
00606                            {
00607                            case ',':
00608                                 if ( !level ) end = p;
00609                                 break;
00610                            case '(':
00611                                 if ( !level ) lp = p;
00612                                 level++;
00613                                 break;
00614                            case ')':
00615                                 if ( --level < 0 ) end = p;
00616                                 else rp = p;
00617                                 break;
00618                            case '/':
00619                                 if (p[1] == '*')
00620                                     p = skipspace(p, 1) - 1;
00621                                 break;
00622                            case '"':
00623                                p = scanstring(p, 1) - 1;
00624                                break;
00625                            default:
00626                                 ;
00627                            }
00628                    }
00629                 /* Erase any embedded prototype parameters. */
00630                 if ( lp && rp )
00631                   writeblanks(lp + 1, rp);
00632                 p--;                    /* back up over terminator */
00633                 /* Find the name being declared. */
00634                 /* This is complicated because of procedure and */
00635                 /* array modifiers. */
00636                 for ( ; ; )
00637                    {    p = skipspace(p - 1, -1);
00638                         switch ( *p )
00639                            {
00640                            case ']':    /* skip array dimension(s) */
00641                            case ')':    /* skip procedure args OR name */
00642                            {    int level = 1;
00643                                 while ( level )
00644                                  switch ( *--p )
00645                                    {
00646                                    case ']': case ')':
00647                                        level++;
00648                                        break;
00649                                    case '[': case '(':
00650                                        level--;
00651                                        break;
00652                                    case '/':
00653                                        if (p > buf && p[-1] == '*')
00654                                            p = skipspace(p, -1) + 1;
00655                                        break;
00656                                    case '"':
00657                                        p = scanstring(p, -1) + 1;
00658                                        break;
00659                                    default: ;
00660                                    }
00661                            }
00662                                 if ( *p == '(' && *skipspace(p + 1, 1) == '*' )
00663                                    {    /* We found the name being declared */
00664                                         while ( !isidfirstchar(*p) )
00665                                           p = skipspace(p, 1) + 1;
00666                                         goto found;
00667                                    }
00668                                 break;
00669                            default:
00670                                 goto found;
00671                            }
00672                    }
00673 found:          if ( *p == '.' && p[-1] == '.' && p[-2] == '.' )
00674                   {     if ( convert_varargs )
00675                           {     *bp++ = "va_alist";
00676                                 vararg = p-2;
00677                           }
00678                         else
00679                           {     p++;
00680                                 if ( bp == breaks + 1 ) /* sole argument */
00681                                   writeblanks(breaks[0], p);
00682                                 else
00683                                   writeblanks(bp[-1] - 1, p);
00684                                 bp--;
00685                           }
00686                    }
00687                 else
00688                    {    while ( isidchar(*p) ) p--;
00689                         *bp++ = p+1;
00690                    }
00691                 p = end;
00692            }
00693         while ( *p++ == ',' );
00694         *bp = p;
00695         /* Make a special check for 'void' arglist */
00696         if ( bp == breaks+2 )
00697            {    p = skipspace(breaks[0], 1);
00698                 if ( !strncmp(p, "void", 4) )
00699                    {    p = skipspace(p+4, 1);
00700                         if ( p == breaks[2] - 1 )
00701                            {    bp = breaks;    /* yup, pretend arglist is empty */
00702                                 writeblanks(breaks[0], p + 1);
00703                            }
00704                    }
00705            }
00706         /* Put out the function name and left parenthesis. */
00707         p = buf;
00708         while ( p != endfn ) putc(*p, out), p++;
00709         /* Put out the declaration. */
00710         if ( header )
00711           {     fputs(");", out);
00712                 for ( p = breaks[0]; *p; p++ )
00713                   if ( *p == '\r' || *p == '\n' )
00714                     putc(*p, out);
00715           }
00716         else
00717           {     for ( ap = breaks+1; ap < bp; ap += 2 )
00718                   {     p = *ap;
00719                         while ( isidchar(*p) )
00720                           putc(*p, out), p++;
00721                         if ( ap < bp - 1 )
00722                           fputs(", ", out);
00723                   }
00724                 fputs(")  ", out);
00725                 /* Put out the argument declarations */
00726                 for ( ap = breaks+2; ap <= bp; ap += 2 )
00727                   (*ap)[-1] = ';';
00728                 if ( vararg != 0 )
00729                   {     *vararg = 0;
00730                         fputs(breaks[0], out);          /* any prior args */
00731                         fputs("va_dcl", out);           /* the final arg */
00732                         fputs(bp[0], out);
00733                   }
00734                 else
00735                   fputs(breaks[0], out);
00736           }
00737         free((char *)breaks);
00738         return 0;
00739 }

Here is the call graph for this function:

int convert1 (  ) 

Referenced by main().

int free (  ) 

Referenced by convert1(), and main().

int main ( int  argc,
argv   
)

Definition at line 230 of file ansi2knr.c.

References bufsize, convert1(), free(), malloc(), NULL, ppdirforward(), skipspace(), and test1().

00233 {       FILE *in = stdin;
00234         FILE *out = stdout;
00235         char *filename = 0;
00236         char *program_name = argv[0];
00237         char *output_name = 0;
00238 #define bufsize 5000                    /* arbitrary size */
00239         char *buf;
00240         char *line;
00241         char *more;
00242         char *usage =
00243           "Usage: ansi2knr [--filename FILENAME] [INPUT_FILE [OUTPUT_FILE]]\n";
00244         /*
00245          * In previous versions, ansi2knr recognized a --varargs switch.
00246          * If this switch was supplied, ansi2knr would attempt to convert
00247          * a ... argument to va_alist and va_dcl; if this switch was not
00248          * supplied, ansi2knr would simply drop any such arguments.
00249          * Now, ansi2knr always does this conversion, and we only
00250          * check for this switch for backward compatibility.
00251          */
00252         int convert_varargs = 1;
00253         int output_error;
00254 
00255         while ( argc > 1 && argv[1][0] == '-' ) {
00256           if ( !strcmp(argv[1], "--varargs") ) {
00257             convert_varargs = 1;
00258             argc--;
00259             argv++;
00260             continue;
00261           }
00262           if ( !strcmp(argv[1], "--filename") && argc > 2 ) {
00263             filename = argv[2];
00264             argc -= 2;
00265             argv += 2;
00266             continue;
00267           }
00268           fprintf(stderr, "%s: Unrecognized switch: %s\n", program_name,
00269                   argv[1]);
00270           fprintf(stderr, usage);
00271           exit(1);
00272         }
00273         switch ( argc )
00274            {
00275         default:
00276                 fprintf(stderr, usage);
00277                 exit(0);
00278         case 3:
00279                 output_name = argv[2];
00280                 out = fopen(output_name, "w");
00281                 if ( out == NULL ) {
00282                   fprintf(stderr, "%s: Cannot open output file %s\n",
00283                           program_name, output_name);
00284                   exit(1);
00285                 }
00286                 /* falls through */
00287         case 2:
00288                 in = fopen(argv[1], "r");
00289                 if ( in == NULL ) {
00290                   fprintf(stderr, "%s: Cannot open input file %s\n",
00291                           program_name, argv[1]);
00292                   exit(1);
00293                 }
00294                 if ( filename == 0 )
00295                   filename = argv[1];
00296                 /* falls through */
00297         case 1:
00298                 break;
00299            }
00300         if ( filename )
00301           fprintf(out, "#line 1 \"%s\"\n", filename);
00302         buf = malloc(bufsize);
00303         if ( buf == NULL )
00304            {
00305                 fprintf(stderr, "Unable to allocate read buffer!\n");
00306                 exit(1);
00307            }
00308         line = buf;
00309         while ( fgets(line, (unsigned)(buf + bufsize - line), in) != NULL )
00310            {
00311 test:           line += strlen(line);
00312                 switch ( test1(buf) )
00313                    {
00314                 case 2:                 /* a function header */
00315                         convert1(buf, out, 1, convert_varargs);
00316                         break;
00317                 case 1:                 /* a function */
00318                         /* Check for a { at the start of the next line. */
00319                         more = ++line;
00320 f:                      if ( line >= buf + (bufsize - 1) ) /* overflow check */
00321                           goto wl;
00322                         if ( fgets(line, (unsigned)(buf + bufsize - line), in) == NULL )
00323                           goto wl;
00324                         switch ( *skipspace(ppdirforward(more), 1) )
00325                           {
00326                           case '{':
00327                             /* Definitely a function header. */
00328                             convert1(buf, out, 0, convert_varargs);
00329                             fputs(more, out);
00330                             break;
00331                           case 0:
00332                             /* The next line was blank or a comment: */
00333                             /* keep scanning for a non-comment. */
00334                             line += strlen(line);
00335                             goto f;
00336                           default:
00337                             /* buf isn't a function header, but */
00338                             /* more might be. */
00339                             fputs(buf, out);
00340                             strcpy(buf, more);
00341                             line = buf;
00342                             goto test;
00343                           }
00344                         break;
00345                 case -1:                /* maybe the start of a function */
00346                         if ( line != buf + (bufsize - 1) ) /* overflow check */
00347                           continue;
00348                         /* falls through */
00349                 default:                /* not a function */
00350 wl:                     fputs(buf, out);
00351                         break;
00352                    }
00353                 line = buf;
00354            }
00355         if ( line != buf )
00356           fputs(buf, out);
00357         free(buf);
00358         if ( output_name ) {
00359           output_error = ferror(out);
00360           output_error |= fclose(out);
00361         } else {                /* out == stdout */
00362           fflush(out);
00363           output_error = ferror(out);
00364         }
00365         if ( output_error ) {
00366           fprintf(stderr, "%s: error writing to %s\n", program_name,
00367                   (output_name ? output_name : "stdout"));
00368           exit(1);
00369         }
00370         if ( in != stdin )
00371           fclose(in);
00372         return 0;
00373 }

Here is the call graph for this function:

char* malloc (  ) 

Referenced by convert1(), and main().

char* ppdirbackward ( char *  p,
char *  limit 
)

Definition at line 392 of file ansi2knr.c.

00395 {
00396     char *np = p;
00397 
00398     for (;; p = --np) {
00399         if (*np == '\n' && np[-1] == '\r')
00400             --np;
00401         for (; np > limit && np[-1] != '\r' && np[-1] != '\n'; --np)
00402             if (np[-1] == 0)
00403                 return np;
00404         if (*np != '#')
00405             return p;
00406     }
00407 }

char* ppdirbackward (  ) 

Referenced by test1().

char* ppdirforward ( char *  p  ) 

Definition at line 379 of file ansi2knr.c.

00381 {
00382     for (; *p == '#'; ++p) {
00383         for (; *p != '\r' && *p != '\n'; ++p)
00384             if (*p == 0)
00385                 return p;
00386         if (*p == '\r' && p[1] == '\n')
00387             ++p;
00388     }
00389     return p;
00390 }

char* ppdirforward (  ) 

Referenced by main().

char* scanstring ( char *  p,
int  dir 
)

Definition at line 436 of file ansi2knr.c.

00439 {
00440     for (p += dir; ; p += dir)
00441         if (*p == '"' && p[-dir] != '\\')
00442             return p + dir;
00443 }

char* scanstring (  ) 

Referenced by convert1().

char* skipspace ( char *  p,
int  dir 
)

Definition at line 414 of file ansi2knr.c.

References is_space.

00417 {
00418     for ( ; ; ) {
00419         while ( is_space(*p) )
00420             p += dir;
00421         if ( !(*p == '/' && p[dir] == '*') )
00422             break;
00423         p += dir;  p += dir;
00424         while ( !(*p == '*' && p[dir] == '/') ) {
00425             if ( *p == 0 )
00426                 return p;       /* multi-line comment?? */
00427             p += dir;
00428         }
00429         p += dir;  p += dir;
00430     }
00431     return p;
00432 }

char* skipspace (  ) 

Referenced by convert1(), main(), and test1().

int test1 ( char *  buf  ) 

Definition at line 474 of file ansi2knr.c.

References isidchar, isidfirstchar, ppdirbackward(), and skipspace().

00476 {       char *p = buf;
00477         char *bend;
00478         char *endfn;
00479         int contin;
00480 
00481         if ( !isidfirstchar(*p) )
00482           return 0;             /* no name at left margin */
00483         bend = skipspace(ppdirbackward(buf + strlen(buf) - 1, buf), -1);
00484         switch ( *bend )
00485            {
00486            case ';': contin = 0 /*2*/; break;
00487            case ')': contin = 1; break;
00488            case '{': return 0;          /* not a function */
00489            case '}': return 0;          /* not a function */
00490            default: contin = -1;
00491            }
00492         while ( isidchar(*p) )
00493           p++;
00494         endfn = p;
00495         p = skipspace(p, 1);
00496         if ( *p++ != '(' )
00497           return 0;             /* not a function */
00498         p = skipspace(p, 1);
00499         if ( *p == ')' )
00500           return 0;             /* no parameters */
00501         /* Check that the apparent function name isn't a keyword. */
00502         /* We only need to check for keywords that could be followed */
00503         /* by a left parenthesis (which, unfortunately, is most of them). */
00504            {    static char *words[] =
00505                    {    "asm", "auto", "case", "char", "const", "double",
00506                         "extern", "float", "for", "if", "int", "long",
00507                         "register", "return", "short", "signed", "sizeof",
00508                         "static", "switch", "typedef", "unsigned",
00509                         "void", "volatile", "while", 0
00510                    };
00511                 char **key = words;
00512                 char *kp;
00513                 unsigned len = endfn - buf;
00514 
00515                 while ( (kp = *key) != 0 )
00516                    {    if ( strlen(kp) == len && !strncmp(kp, buf, len) )
00517                           return 0;     /* name is a keyword */
00518                         key++;
00519                    }
00520            }
00521            {
00522                char *id = p;
00523                int len;
00524                /*
00525                 * Check for identifier1(identifier2) and not
00526                 * identifier1(void), or identifier1(identifier2, xxxx).
00527                 */
00528 
00529                while ( isidchar(*p) )
00530                    p++;
00531                len = p - id;
00532                p = skipspace(p, 1);
00533                if (*p == ',' ||
00534                    (*p == ')' && (len != 4 || strncmp(id, "void", 4)))
00535                    )
00536                    return 0;    /* not a function */
00537            }
00538         /*
00539          * If the last significant character was a ), we need to count
00540          * parentheses, because it might be part of a formal parameter
00541          * that is a procedure.
00542          */
00543         if (contin > 0) {
00544             int level = 0;
00545 
00546             for (p = skipspace(buf, 1); *p; p = skipspace(p + 1, 1))
00547                 level += (*p == '(' ? 1 : *p == ')' ? -1 : 0);
00548             if (level > 0)
00549                 contin = -1;
00550         }
00551         return contin;
00552 }

Here is the call graph for this function:

int test1 (  ) 

Referenced by main().

int writeblanks ( char *  start,
char *  end 
)

Definition at line 450 of file ansi2knr.c.

00453 {       char *p;
00454         for ( p = start; p < end; p++ )
00455           if ( *p != '\r' && *p != '\n' )
00456             *p = ' ';
00457         return 0;
00458 }

int writeblanks (  ) 

Referenced by convert1().


Generated on Wed Nov 19 00:00:21 2008 for FreeFEM3D (aka ff3d) by  doxygen 1.5.6