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 #include "fixlib.h"
00053 #define GTYPE_SE_CT 1
00054
00055 #ifdef SEPARATE_FIX_PROC
00056 #include "fixincl.x"
00057 #endif
00058
00059 tSCC zNeedsArg[] = "fixincl error: `%s' needs %s argument (c_fix_arg[%d])\n";
00060
00061 typedef void t_fix_proc PARAMS ((const char *, const char *, tFixDesc *));
00062 typedef struct {
00063 const char* fix_name;
00064 t_fix_proc* fix_proc;
00065 } fix_entry_t;
00066
00067 #define FIXUP_TABLE \
00068 _FT_( "char_macro_def", char_macro_def_fix ) \
00069 _FT_( "char_macro_use", char_macro_use_fix ) \
00070 _FT_( "format", format_fix ) \
00071 _FT_( "machine_name", machine_name_fix ) \
00072 _FT_( "wrap", wrap_fix ) \
00073 _FT_( "gnu_type", gnu_type_fix )
00074
00075
00076 #define FIX_PROC_HEAD( fix ) \
00077 static void fix PARAMS ((const char *, const char *, tFixDesc *)); \
00078 static void fix ( filname, text, p_fixd ) \
00079 const char* filname; \
00080 const char* text; \
00081 tFixDesc* p_fixd;
00082
00083 #ifdef NEED_PRINT_QUOTE
00084
00085
00086
00087
00088
00089
00090 static char*
00091 print_quote( q, text )
00092 char q;
00093 char* text;
00094 {
00095 fputc( q, stdout );
00096
00097 for (;;)
00098 {
00099 char ch = *(text++);
00100 fputc( ch, stdout );
00101
00102 switch (ch)
00103 {
00104 case '\\':
00105 if (*text == NUL)
00106 goto quote_done;
00107
00108 fputc( *(text++), stdout );
00109 break;
00110
00111 case '"':
00112 case '\'':
00113 if (ch != q)
00114 break;
00115
00116
00117 case '\n':
00118 case NUL:
00119 goto quote_done;
00120 }
00121 } quote_done:;
00122
00123 return text;
00124 }
00125 #endif
00126
00127
00128
00129
00130
00131
00132
00133 static const char *emit_gnu_type PARAMS ((const char *, regmatch_t *));
00134 static const char*
00135 emit_gnu_type ( text, rm )
00136 const char* text;
00137 regmatch_t* rm;
00138 {
00139 char z_TYPE[ 64 ];
00140 char z_type[ 64 ];
00141
00142 fwrite (text, rm[0].rm_so, 1, stdout);
00143
00144 {
00145 const char* ps = text + rm[1].rm_so;
00146 const char* pe = text + rm[1].rm_eo;
00147 char* pd = z_type;
00148 char* pD = z_TYPE;
00149
00150 while (ps < pe)
00151 *(pD++) = TOUPPER( *(pd++) = *(ps++) );
00152
00153 *pD = *pd = NUL;
00154 }
00155
00156
00157
00158
00159
00160 {
00161 tSCC z_fmt[] = "\
00162 #if !defined(_GCC_%s_T)%s\n\
00163 #define _GCC_%s_T\n\
00164 typedef __%s_TYPE__ %s_t;\n\
00165 #endif\n";
00166
00167 const char *const pz_guard = (strcmp (z_type, "wchar") == 0)
00168 ? " && ! defined(__cplusplus)" : "";
00169
00170 printf (z_fmt, z_TYPE, pz_guard, z_TYPE, z_TYPE, z_type);
00171 }
00172
00173 return text += rm[0].rm_eo;
00174 }
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184 static void format_write PARAMS ((tCC *, tCC *, regmatch_t[]));
00185 static void
00186 format_write (format, text, av)
00187 tCC* format;
00188 tCC* text;
00189 regmatch_t av[];
00190 {
00191 int c;
00192
00193 while ((c = (unsigned)*(format++)) != NUL) {
00194
00195 if (c != '%')
00196 {
00197 putchar(c);
00198 continue;
00199 }
00200
00201 c = (unsigned)*(format++);
00202
00203
00204
00205
00206
00207
00208
00209 if (! ISDIGIT ( c ))
00210 {
00211 putchar( '%' );
00212 switch (c) {
00213 case NUL:
00214 return;
00215 case '%':
00216 break;
00217 default:
00218 putchar(c);
00219 }
00220 }
00221
00222
00223
00224
00225
00226 else {
00227 regmatch_t* pRM = av + (c - (unsigned)'0');
00228 size_t len;
00229
00230 if (pRM->rm_so < 0)
00231 continue;
00232
00233 len = pRM->rm_eo - pRM->rm_so;
00234 if (len > 0)
00235 fwrite(text + pRM->rm_so, len, 1, stdout);
00236 }
00237 }
00238 }
00239
00240
00241
00242
00243
00244
00245
00246 FIX_PROC_HEAD( format_fix )
00247 {
00248 tCC* pz_pat = p_fixd->patch_args[2];
00249 tCC* pz_fmt = p_fixd->patch_args[1];
00250 regex_t re;
00251 regmatch_t rm[10];
00252 IGNORE_ARG(filname);
00253
00254
00255
00256
00257 if (pz_fmt == (tCC*)NULL)
00258 {
00259 fprintf( stderr, zNeedsArg, p_fixd->fix_name, "replacement format", 0 );
00260 exit (EXIT_BROKEN);
00261 }
00262
00263
00264
00265
00266
00267 if (pz_pat == (tCC*)NULL)
00268 {
00269 tTestDesc* pTD = p_fixd->p_test_desc;
00270 int ct = p_fixd->test_ct;
00271 for (;;)
00272 {
00273 if (ct-- <= 0)
00274 {
00275 fprintf( stderr, zNeedsArg, p_fixd->fix_name, "search text", 1 );
00276 exit (EXIT_BROKEN);
00277 }
00278
00279 if (pTD->type == TT_EGREP)
00280 {
00281 pz_pat = pTD->pz_test_text;
00282 break;
00283 }
00284
00285 pTD++;
00286 }
00287 }
00288
00289
00290
00291
00292 compile_re (pz_pat, &re, 1, "format search-text", "format_fix" );
00293 while (regexec (&re, text, 10, rm, 0) == 0)
00294 {
00295 fwrite( text, rm[0].rm_so, 1, stdout );
00296 format_write( pz_fmt, text, rm );
00297 text += rm[0].rm_eo;
00298 }
00299
00300
00301
00302
00303 fputs (text, stdout);
00304 }
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319 FIX_PROC_HEAD( char_macro_use_fix )
00320 {
00321
00322
00323 static const char pat[] =
00324 "^#[ \t]*define[ \t]+[_A-Za-z][_A-Za-z0-9]*[ \t]+";
00325 static regex_t re;
00326
00327 const char* str = p_fixd->patch_args[1];
00328 regmatch_t rm[1];
00329 const char *p, *limit;
00330 size_t len;
00331 IGNORE_ARG(filname);
00332
00333 if (str == NULL)
00334 {
00335 fprintf (stderr, zNeedsArg, p_fixd->fix_name, "ioctl type", 0);
00336 exit (EXIT_BROKEN);
00337 }
00338
00339 len = strlen (str);
00340 compile_re (pat, &re, 1, "macro pattern", "char_macro_use_fix");
00341
00342 for (p = text;
00343 regexec (&re, p, 1, rm, 0) == 0;
00344 p = limit + 1)
00345 {
00346
00347
00348
00349 p += rm[0].rm_eo;
00350 limit = p - 1;
00351 do
00352 {
00353 limit = strchr (limit + 1, '\n');
00354 if (!limit)
00355 goto done;
00356 }
00357 while (limit[-1] == '\\');
00358
00359 do
00360 {
00361 if (*p == str[0] && !strncmp (p+1, str+1, len-1))
00362 goto found;
00363 }
00364 while (++p < limit - len);
00365
00366 continue;
00367
00368 found:
00369
00370
00371
00372 while ((ISSPACE (*p) || ISUPPER (*p)) && p < limit) p++;
00373 if (*p++ != '(')
00374 continue;
00375 if (!ISALPHA (*p))
00376 continue;
00377 if (ISIDNUM (p[1]))
00378 continue;
00379
00380
00381
00382 fwrite (text, 1, p - text, stdout);
00383 putchar ('\'');
00384 putchar (*p);
00385 putchar ('\'');
00386 text = p + 1;
00387 }
00388 done:
00389 fputs (text, stdout);
00390 }
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404 FIX_PROC_HEAD( char_macro_def_fix )
00405 {
00406
00407 static const char pat[] =
00408 "^#[ \t]*define[ \t]+";
00409 static regex_t re;
00410
00411 const char* str = p_fixd->patch_args[1];
00412 regmatch_t rm[1];
00413 const char *p, *limit;
00414 char arg;
00415 size_t len;
00416 IGNORE_ARG(filname);
00417
00418 if (str == NULL)
00419 {
00420 fprintf (stderr, zNeedsArg, p_fixd->fix_name, "ioctl type", 0);
00421 exit (EXIT_BROKEN);
00422 }
00423
00424 len = strlen (str);
00425 compile_re (pat, &re, 1, "macro pattern", "fix_char_macro_defines");
00426
00427 for (p = text;
00428 regexec (&re, p, 1, rm, 0) == 0;
00429 p = limit + 1)
00430 {
00431
00432
00433
00434 p += rm[0].rm_eo;
00435 limit = p - 1;
00436 do
00437 {
00438 limit = strchr (limit + 1, '\n');
00439 if (!limit)
00440 goto done;
00441 }
00442 while (limit[-1] == '\\');
00443
00444 do
00445 {
00446 if (*p == str[0] && !strncmp (p+1, str+1, len-1))
00447 goto found;
00448 p++;
00449 }
00450 while (ISIDNUM (*p));
00451
00452 continue;
00453
00454 found:
00455
00456
00457
00458
00459 while (ISUPPER (*p) && p < limit) p++;
00460 if (*p++ != '(')
00461 continue;
00462 if (!ISALPHA (*p))
00463 continue;
00464 if (ISIDNUM (p[1]))
00465 continue;
00466
00467
00468
00469 arg = *p;
00470 p += 2;
00471
00472 while (p < limit)
00473 {
00474 if (p[-1] == '\'' && p[0] == arg && p[1] == '\'')
00475 {
00476
00477 p--;
00478 fwrite (text, 1, p - text, stdout);
00479 putchar (arg);
00480 p += 3;
00481 text = p;
00482 }
00483 else
00484 p++;
00485 }
00486 }
00487 done:
00488 fputs (text, stdout);
00489 }
00490
00491
00492
00493
00494
00495
00496
00497 #define SCRATCHSZ 64
00498
00499 FIX_PROC_HEAD( machine_name_fix )
00500 {
00501 #ifndef MN_NAME_PAT
00502 fputs( "The target machine has no needed machine name fixes\n", stderr );
00503 #else
00504 regmatch_t match[2];
00505 const char *line, *base, *limit, *p, *q;
00506 regex_t *label_re, *name_re;
00507 char scratch[SCRATCHSZ];
00508 size_t len;
00509 IGNORE_ARG(filname);
00510 IGNORE_ARG(p_fixd);
00511
00512 mn_get_regexps (&label_re, &name_re, "machine_name_fix");
00513
00514 scratch[0] = '_';
00515 scratch[1] = '_';
00516
00517 for (base = text;
00518 regexec (label_re, base, 2, match, 0) == 0;
00519 base = limit)
00520 {
00521 base += match[0].rm_eo;
00522
00523
00524 line = limit = base;
00525 do
00526 {
00527 limit++;
00528 limit = strchr (limit, '\n');
00529 if (!limit)
00530 goto done;
00531 }
00532 while (limit[-1] == '\\');
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543 for (;;)
00544 {
00545 again:
00546 if (base == limit)
00547 break;
00548
00549 if (regexec (name_re, base, 1, match, REG_NOTBOL))
00550 goto done;
00551
00552
00553 if (match[0].rm_eo > limit - base)
00554 break;
00555
00556 p = base + match[0].rm_so;
00557 base += match[0].rm_eo;
00558
00559
00560
00561
00562 if (*p == '_')
00563 {
00564 len = base - p - ((*base == '_') ? 2 : 1);
00565 q = p + 1;
00566 }
00567 else
00568 {
00569 len = base - p - ((*base == '_') ? 1 : 0);
00570 q = p;
00571 }
00572 if (len + 4 > SCRATCHSZ)
00573 abort ();
00574 memcpy (&scratch[2], q, len);
00575 len += 2;
00576 scratch[len++] = '_';
00577 scratch[len++] = '_';
00578
00579 for (q = line; q <= limit - len; q++)
00580 if (*q == '_' && !strncmp (q, scratch, len))
00581 goto again;
00582
00583 fwrite (text, 1, p - text, stdout);
00584 fwrite (scratch, 1, len, stdout);
00585
00586 text = base;
00587 }
00588 }
00589 done:
00590 #endif
00591 fputs (text, stdout);
00592 }
00593
00594
00595 FIX_PROC_HEAD( wrap_fix )
00596 {
00597 tSCC z_no_wrap_pat[] = "^#if.*__need_";
00598 static regex_t no_wrapping_re;
00599
00600 tCC* pz_name = NULL;
00601
00602 if (no_wrapping_re.allocated == 0)
00603 compile_re( z_no_wrap_pat, &no_wrapping_re, 0, "no-wrap pattern",
00604 "wrap-fix" );
00605
00606
00607
00608
00609
00610 if (regexec( &no_wrapping_re, text, 0, NULL, 0 ) != 0)
00611 {
00612
00613
00614
00615
00616
00617 size_t ln = strlen( filname ) + strlen( p_fixd->fix_name ) + 14;
00618 char* pz = xmalloc( ln );
00619 pz_name = pz;
00620 sprintf( pz, "FIXINC_WRAP_%s-%s", filname, p_fixd->fix_name );
00621
00622 for (pz += 12; 1; pz++) {
00623 char ch = *pz;
00624
00625 if (ch == NUL)
00626 break;
00627
00628 if (! ISALNUM( ch )) {
00629 *pz = '_';
00630 }
00631 else {
00632 *pz = TOUPPER( ch );
00633 }
00634 }
00635
00636 printf( "#ifndef %s\n", pz_name );
00637 printf( "#define %s 1\n\n", pz_name );
00638 }
00639
00640 if (p_fixd->patch_args[1] == (tCC*)NULL)
00641 fputs( text, stdout );
00642
00643 else {
00644 fputs( p_fixd->patch_args[1], stdout );
00645 fputs( text, stdout );
00646 if (p_fixd->patch_args[2] != (tCC*)NULL)
00647 fputs( p_fixd->patch_args[2], stdout );
00648 }
00649
00650 if (pz_name != NULL) {
00651 printf( "\n#endif /* %s */\n", pz_name );
00652 free( (void*)pz_name );
00653 }
00654 }
00655
00656
00657
00658
00659
00660
00661
00662 FIX_PROC_HEAD( gnu_type_fix )
00663 {
00664 const char* pz_pat;
00665 regex_t re;
00666 regmatch_t rm[GTYPE_SE_CT+1];
00667 IGNORE_ARG(filname);
00668
00669 {
00670 tTestDesc* pTD = p_fixd->p_test_desc;
00671 int ct = p_fixd->test_ct;
00672 for (;;)
00673 {
00674 if (ct-- <= 0)
00675 {
00676 fprintf (stderr, zNeedsArg, p_fixd->fix_name, "search text", 1);
00677 exit (EXIT_BROKEN);
00678 }
00679
00680 if (pTD->type == TT_EGREP)
00681 {
00682 pz_pat = pTD->pz_test_text;
00683 break;
00684 }
00685
00686 pTD++;
00687 }
00688 }
00689
00690 compile_re (pz_pat, &re, 1, "gnu type typedef", "gnu_type_fix");
00691
00692 while (regexec (&re, text, GTYPE_SE_CT+1, rm, 0) == 0)
00693 {
00694 text = emit_gnu_type (text, rm);
00695 }
00696
00697
00698
00699
00700 fputs (text, stdout);
00701 }
00702
00703
00704
00705
00706
00707
00708
00709
00710
00711 void
00712 apply_fix( p_fixd, filname )
00713 tFixDesc* p_fixd;
00714 tCC* filname;
00715 {
00716 #define _FT_(n,p) { n, p },
00717 static fix_entry_t fix_table[] = { FIXUP_TABLE { NULL, NULL }};
00718 #undef _FT_
00719 #define FIX_TABLE_CT (ARRAY_SIZE (fix_table)-1)
00720
00721 tCC* fixname = p_fixd->patch_args[0];
00722 char* buf;
00723 int ct = FIX_TABLE_CT;
00724 fix_entry_t* pfe = fix_table;
00725
00726 for (;;)
00727 {
00728 if (strcmp (pfe->fix_name, fixname) == 0)
00729 break;
00730 if (--ct <= 0)
00731 {
00732 fprintf (stderr, "fixincl error: the `%s' fix is unknown\n",
00733 fixname );
00734 exit (EXIT_BROKEN);
00735 }
00736 pfe++;
00737 }
00738
00739 buf = load_file_data (stdin);
00740 (*pfe->fix_proc)( filname, buf, p_fixd );
00741 }
00742
00743 #ifdef SEPARATE_FIX_PROC
00744 tSCC z_usage[] =
00745 "USAGE: applyfix <fix-name> <file-to-fix> <file-source> <file-destination>\n";
00746 tSCC z_reopen[] =
00747 "FS error %d (%s) reopening %s as std%s\n";
00748
00749 int
00750 main( argc, argv )
00751 int argc;
00752 char** argv;
00753 {
00754 tFixDesc* pFix;
00755 char* pz_tmptmp;
00756 char* pz_tmp_base;
00757 char* pz_tmp_dot;
00758
00759 if (argc != 5)
00760 {
00761 usage_failure:
00762 fputs (z_usage, stderr);
00763 return EXIT_FAILURE;
00764 }
00765
00766 {
00767 char* pz = argv[1];
00768 long idx;
00769
00770 if (! ISDIGIT ( *pz ))
00771 goto usage_failure;
00772
00773 idx = strtol (pz, &pz, 10);
00774 if ((*pz != NUL) || ((unsigned)idx >= FIX_COUNT))
00775 goto usage_failure;
00776 pFix = fixDescList + idx;
00777 }
00778
00779 if (freopen (argv[3], "r", stdin) != stdin)
00780 {
00781 fprintf (stderr, z_reopen, errno, strerror( errno ), argv[3], "in");
00782 return EXIT_FAILURE;
00783 }
00784
00785 pz_tmptmp = (char*)xmalloc( strlen( argv[4] ) + 5 );
00786 strcpy( pz_tmptmp, argv[4] );
00787
00788
00789
00790
00791 pz_tmp_base = basename( pz_tmptmp );
00792 pz_tmp_dot = strchr( pz_tmp_base, '.' );
00793 if (pathconf( pz_tmptmp, _PC_NAME_MAX ) <= 12
00794 && pz_tmp_dot != (char*)NULL)
00795 strcpy (pz_tmp_dot+1, "X");
00796 else
00797 strcat (pz_tmptmp, ".X");
00798 if (freopen (pz_tmptmp, "w", stdout) != stdout)
00799 {
00800 fprintf (stderr, z_reopen, errno, strerror( errno ), pz_tmptmp, "out");
00801 return EXIT_FAILURE;
00802 }
00803
00804 apply_fix (pFix, argv[1]);
00805 fclose (stdout);
00806 fclose (stdin);
00807 unlink (argv[4]);
00808 if (rename (pz_tmptmp, argv[4]) != 0)
00809 {
00810 fprintf (stderr, "error %d (%s) renaming %s to %s\n", errno,
00811 strerror( errno ), pz_tmptmp, argv[4]);
00812 return EXIT_FAILURE;
00813 }
00814
00815 return EXIT_SUCCESS;
00816 }
00817 #endif