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