00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134 #if HAVE_CONFIG_H
00135 # include <config.h>
00136 #endif
00137
00138 #include <stdio.h>
00139 #include <ctype.h>
00140
00141 #if HAVE_CONFIG_H
00142
00143
00144
00145
00146
00147
00148 # if STDC_HEADERS || HAVE_STRING_H
00149 # include <string.h>
00150 # else
00151 # include <strings.h>
00152 # endif
00153
00154 #else
00155
00156
00157
00158 # ifdef BSD
00159 # include <strings.h>
00160 # else
00161 # ifdef VMS
00162 extern int strlen(), strncmp();
00163 # else
00164 # include <string.h>
00165 # endif
00166 # endif
00167
00168 #endif
00169
00170 #if STDC_HEADERS
00171 # include <stdlib.h>
00172 #else
00173
00174
00175
00176
00177 # ifdef MSDOS
00178 # include <malloc.h>
00179 # else
00180 # ifdef VMS
00181 extern char *malloc();
00182 extern void free();
00183 # else
00184 extern char *malloc();
00185 extern int free();
00186 # endif
00187 # endif
00188
00189 #endif
00190
00191
00192 #ifndef NULL
00193 # define NULL (0)
00194 #endif
00195
00196
00197
00198
00199
00200 #ifdef isascii
00201 # undef HAVE_ISASCII
00202 # define HAVE_ISASCII 1
00203 #else
00204 #endif
00205 #if STDC_HEADERS || !HAVE_ISASCII
00206 # define is_ascii(c) 1
00207 #else
00208 # define is_ascii(c) isascii(c)
00209 #endif
00210
00211 #define is_space(c) (is_ascii(c) && isspace(c))
00212 #define is_alpha(c) (is_ascii(c) && isalpha(c))
00213 #define is_alnum(c) (is_ascii(c) && isalnum(c))
00214
00215
00216 #define isidchar(ch) (is_alnum(ch) || (ch) == '_')
00217 #define isidfirstchar(ch) (is_alpha(ch) || (ch) == '_')
00218
00219
00220 char *ppdirforward();
00221 char *ppdirbackward();
00222 char *skipspace();
00223 char *scanstring();
00224 int writeblanks();
00225 int test1();
00226 int convert1();
00227
00228
00229 int
00230 main(argc, argv)
00231 int argc;
00232 char *argv[];
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
00239 char *buf;
00240 char *line;
00241 char *more;
00242 char *usage =
00243 "Usage: ansi2knr [--filename FILENAME] [INPUT_FILE [OUTPUT_FILE]]\n";
00244
00245
00246
00247
00248
00249
00250
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
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
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:
00315 convert1(buf, out, 1, convert_varargs);
00316 break;
00317 case 1:
00318
00319 more = ++line;
00320 f: if ( line >= buf + (bufsize - 1) )
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
00328 convert1(buf, out, 0, convert_varargs);
00329 fputs(more, out);
00330 break;
00331 case 0:
00332
00333
00334 line += strlen(line);
00335 goto f;
00336 default:
00337
00338
00339 fputs(buf, out);
00340 strcpy(buf, more);
00341 line = buf;
00342 goto test;
00343 }
00344 break;
00345 case -1:
00346 if ( line != buf + (bufsize - 1) )
00347 continue;
00348
00349 default:
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 {
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 }
00374
00375
00376
00377
00378 char *
00379 ppdirforward(p)
00380 char *p;
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 }
00391 char *
00392 ppdirbackward(p, limit)
00393 char *p;
00394 char *limit;
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 }
00408
00409
00410
00411
00412
00413 char *
00414 skipspace(p, dir)
00415 char *p;
00416 int dir;
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;
00427 p += dir;
00428 }
00429 p += dir; p += dir;
00430 }
00431 return p;
00432 }
00433
00434
00435 char *
00436 scanstring(p, dir)
00437 char *p;
00438 int dir;
00439 {
00440 for (p += dir; ; p += dir)
00441 if (*p == '"' && p[-dir] != '\\')
00442 return p + dir;
00443 }
00444
00445
00446
00447
00448
00449 int
00450 writeblanks(start, end)
00451 char *start;
00452 char *end;
00453 { char *p;
00454 for ( p = start; p < end; p++ )
00455 if ( *p != '\r' && *p != '\n' )
00456 *p = ' ';
00457 return 0;
00458 }
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473 int
00474 test1(buf)
00475 char *buf;
00476 { char *p = buf;
00477 char *bend;
00478 char *endfn;
00479 int contin;
00480
00481 if ( !isidfirstchar(*p) )
00482 return 0;
00483 bend = skipspace(ppdirbackward(buf + strlen(buf) - 1, buf), -1);
00484 switch ( *bend )
00485 {
00486 case ';': contin = 0 ; break;
00487 case ')': contin = 1; break;
00488 case '{': return 0;
00489 case '}': return 0;
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;
00498 p = skipspace(p, 1);
00499 if ( *p == ')' )
00500 return 0;
00501
00502
00503
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;
00518 key++;
00519 }
00520 }
00521 {
00522 char *id = p;
00523 int len;
00524
00525
00526
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;
00537 }
00538
00539
00540
00541
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 }
00553
00554
00555 int
00556 convert1(buf, out, header, convert_varargs)
00557 char *buf;
00558 FILE *out;
00559 int header;
00560 int convert_varargs;
00561 { char *endfn;
00562 char *p;
00563
00564
00565
00566
00567 char **breaks;
00568 unsigned num_breaks = 2;
00569 char **btop;
00570 char **bp;
00571 char **ap;
00572 char *vararg = 0;
00573
00574
00575
00576 for ( endfn = buf; *(endfn++) != '('; )
00577 ;
00578 top: p = endfn;
00579 breaks = (char **)malloc(sizeof(char *) * num_breaks * 2);
00580 if ( breaks == NULL )
00581 {
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
00589 do
00590 { int level = 0;
00591 char *lp = NULL;
00592 char *rp = NULL;
00593 char *end = NULL;
00594
00595 if ( bp >= btop )
00596 {
00597
00598 free((char *)breaks);
00599 num_breaks <<= 1;
00600 goto top;
00601 }
00602 *bp++ = p;
00603
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
00630 if ( lp && rp )
00631 writeblanks(lp + 1, rp);
00632 p--;
00633
00634
00635
00636 for ( ; ; )
00637 { p = skipspace(p - 1, -1);
00638 switch ( *p )
00639 {
00640 case ']':
00641 case ')':
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 {
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 )
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
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;
00702 writeblanks(breaks[0], p + 1);
00703 }
00704 }
00705 }
00706
00707 p = buf;
00708 while ( p != endfn ) putc(*p, out), p++;
00709
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
00726 for ( ap = breaks+2; ap <= bp; ap += 2 )
00727 (*ap)[-1] = ';';
00728 if ( vararg != 0 )
00729 { *vararg = 0;
00730 fputs(breaks[0], out);
00731 fputs("va_dcl", out);
00732 fputs(bp[0], out);
00733 }
00734 else
00735 fputs(breaks[0], out);
00736 }
00737 free((char *)breaks);
00738 return 0;
00739 }