OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-old/] [gcc-4.2.2/] [fixincludes/] [fixincl.c] - Blame information for rev 853

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 38 julius
/* Install modified versions of certain ANSI-incompatible system header
2
   files which are fixed to work correctly with ANSI C and placed in a
3
   directory that GCC will search.
4
 
5
   Copyright (C) 1997, 1998, 1999, 2000, 2004 Free Software Foundation, Inc.
6
 
7
This file is part of GCC.
8
 
9
GCC is free software; you can redistribute it and/or modify
10
it under the terms of the GNU General Public License as published by
11
the Free Software Foundation; either version 2, or (at your option)
12
any later version.
13
 
14
GCC is distributed in the hope that it will be useful,
15
but WITHOUT ANY WARRANTY; without even the implied warranty of
16
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
GNU General Public License for more details.
18
 
19
You should have received a copy of the GNU General Public License
20
along with GCC; see the file COPYING.  If not, write to
21
the Free Software Foundation, 51 Franklin Street, Fifth Floor,
22
Boston, MA 02110-1301, USA.  */
23
 
24
#include "fixlib.h"
25
 
26
#include <sys/stat.h>
27
#ifndef SEPARATE_FIX_PROC
28
#include <sys/wait.h>
29
#endif
30
 
31
#if defined( HAVE_MMAP_FILE )
32
#include <sys/mman.h>
33
#define  BAD_ADDR ((void*)-1)
34
#endif
35
 
36
#ifndef SEPARATE_FIX_PROC
37
#include "server.h"
38
#endif
39
 
40
/*  The contents of this string are not very important.  It is mostly
41
    just used as part of the "I am alive and working" test.  */
42
 
43
static const char program_id[] = "fixincl version 1.1";
44
 
45
/*  This format will be used at the start of every generated file */
46
 
47
static const char z_std_preamble[] =
48
"/*  DO NOT EDIT THIS FILE.\n\n\
49
    It has been auto-edited by fixincludes from:\n\n\
50
\t\"%s/%s\"\n\n\
51
    This had to be done to correct non-standard usages in the\n\
52
    original, manufacturer supplied header file.  */\n\n";
53
 
54
int find_base_len = 0;
55
 
56
typedef enum {
57
  VERB_SILENT = 0,
58
  VERB_FIXES,
59
  VERB_APPLIES,
60
  VERB_PROGRESS,
61
  VERB_TESTS,
62
  VERB_EVERYTHING
63
} te_verbose;
64
 
65
te_verbose  verbose_level = VERB_PROGRESS;
66
int have_tty = 0;
67
 
68
#define VLEVEL(l)  ((unsigned int) verbose_level >= (unsigned int) l)
69
#define NOT_SILENT VLEVEL(VERB_FIXES)
70
 
71
pid_t process_chain_head = (pid_t) -1;
72
 
73
char*  pz_curr_file;  /*  name of the current file under test/fix  */
74
char*  pz_curr_data;  /*  original contents of that file  */
75
char*  pz_temp_file;  /*  for DOS, a place to stash the temporary
76
                          fixed data between system(3) calls  */
77
t_bool curr_data_mapped;
78
int    data_map_fd;
79
size_t data_map_size;
80
size_t ttl_data_size = 0;
81
 
82
#ifdef DO_STATS
83
int process_ct = 0;
84
int apply_ct = 0;
85
int fixed_ct = 0;
86
int altered_ct = 0;
87
#endif /* DO_STATS */
88
 
89
const char incl_quote_pat[] = "^[ \t]*#[ \t]*include[ \t]*\"[^/]";
90
tSCC z_fork_err[] = "Error %d (%s) starting filter process for %s\n";
91
regex_t incl_quote_re;
92
 
93
static void do_version (void) ATTRIBUTE_NORETURN;
94
char *load_file (const char *);
95
void run_compiles (void);
96
void initialize (int argc, char** argv);
97
void process (void);
98
 
99
/*  External Source Code */
100
 
101
#include "fixincl.x"
102
 
103
/* * * * * * * * * * * * * * * * * * *
104
 *
105
 *  MAIN ROUTINE
106
 */
107
extern int main (int, char **);
108
int
109
main (int argc, char** argv)
110
{
111
  char *file_name_buf;
112
 
113
  initialize ( argc, argv );
114
 
115
  have_tty = isatty (fileno (stderr));
116
 
117
  /* Before anything else, ensure we can allocate our file name buffer. */
118
  file_name_buf = load_file_data (stdin);
119
 
120
  /*  Because of the way server shells work, you have to keep stdin, out
121
      and err open so that the proper input file does not get closed
122
      by accident  */
123
 
124
  freopen ("/dev/null", "r", stdin);
125
 
126
  if (file_name_buf == (char *) NULL)
127
    {
128
      fputs ("No file names listed for fixing\n", stderr);
129
      exit (EXIT_FAILURE);
130
    }
131
 
132
  for (;;)
133
    {
134
      char* pz_end;
135
 
136
      /*  skip to start of name, past any "./" prefixes */
137
 
138
      while (ISSPACE (*file_name_buf))  file_name_buf++;
139
      while ((file_name_buf[0] == '.') && (file_name_buf[1] == '/'))
140
        file_name_buf += 2;
141
 
142
      /*  Check for end of list  */
143
 
144
      if (*file_name_buf == NUL)
145
        break;
146
 
147
      /*  Set global file name pointer and find end of name */
148
 
149
      pz_curr_file = file_name_buf;
150
      pz_end = strchr( pz_curr_file, '\n' );
151
      if (pz_end == (char*)NULL)
152
        pz_end = file_name_buf = pz_curr_file + strlen (pz_curr_file);
153
      else
154
        file_name_buf = pz_end + 1;
155
 
156
      while ((pz_end > pz_curr_file) && ISSPACE( pz_end[-1]))  pz_end--;
157
 
158
      /*  IF no name is found (blank line) or comment marker, skip line  */
159
 
160
      if ((pz_curr_file == pz_end) || (*pz_curr_file == '#'))
161
        continue;
162
      *pz_end = NUL;
163
 
164
      process ();
165
    } /*  for (;;) */
166
 
167
#ifdef DO_STATS
168
  if (VLEVEL( VERB_PROGRESS )) {
169
    tSCC zFmt[] =
170
      "\
171
Processed %5d files containing %d bytes    \n\
172
Applying  %5d fixes to %d files\n\
173
Altering  %5d of them\n";
174
 
175
    fprintf (stderr, zFmt, process_ct, ttl_data_size, apply_ct,
176
             fixed_ct, altered_ct);
177
  }
178
#endif /* DO_STATS */
179
 
180
# ifdef SEPARATE_FIX_PROC
181
  unlink( pz_temp_file );
182
# endif
183
  exit (EXIT_SUCCESS);
184
}
185
 
186
 
187
static void
188
do_version (void)
189
{
190
  static const char zFmt[] = "echo '%s'";
191
  char zBuf[ 1024 ];
192
 
193
  /* The 'version' option is really used to test that:
194
     1.  The program loads correctly (no missing libraries)
195
     2.  that we can compile all the regular expressions.
196
     3.  we can correctly run our server shell process
197
  */
198
  run_compiles ();
199
  sprintf (zBuf, zFmt, program_id);
200
#ifndef SEPARATE_FIX_PROC
201
  puts (zBuf + 5);
202
  exit (strcmp (run_shell (zBuf), program_id));
203
#else
204
  exit (system (zBuf));
205
#endif
206
}
207
 
208
/* * * * * * * * * * * * */
209
 
210
void
211
initialize ( int argc, char** argv )
212
{
213
  xmalloc_set_program_name (argv[0]);
214
 
215
  switch (argc)
216
    {
217
    case 1:
218
      break;
219
 
220
    case 2:
221
      if (strcmp (argv[1], "-v") == 0)
222
        do_version ();
223
      if (freopen (argv[1], "r", stdin) == (FILE*)NULL)
224
        {
225
          fprintf (stderr, "Error %d (%s) reopening %s as stdin\n",
226
                   errno, xstrerror (errno), argv[1] );
227
          exit (EXIT_FAILURE);
228
        }
229
      break;
230
 
231
    default:
232
      fputs ("fixincl ERROR:  too many command line arguments\n", stderr);
233
      exit (EXIT_FAILURE);
234
    }
235
 
236
#ifdef SIGCHLD
237
  /* We *MUST* set SIGCHLD to SIG_DFL so that the wait4() call will
238
     receive the signal.  A different setting is inheritable */
239
  signal (SIGCHLD, SIG_DFL);
240
#endif
241
 
242
  initialize_opts ();
243
 
244
  if (ISDIGIT ( *pz_verbose ))
245
    verbose_level = (te_verbose)atoi( pz_verbose );
246
  else
247
    switch (*pz_verbose) {
248
    case 's':
249
    case 'S':
250
      verbose_level = VERB_SILENT;     break;
251
 
252
    case 'f':
253
    case 'F':
254
      verbose_level = VERB_FIXES;      break;
255
 
256
    case 'a':
257
    case 'A':
258
      verbose_level = VERB_APPLIES;    break;
259
 
260
    default:
261
    case 'p':
262
    case 'P':
263
      verbose_level = VERB_PROGRESS;   break;
264
 
265
    case 't':
266
    case 'T':
267
      verbose_level = VERB_TESTS;      break;
268
 
269
    case 'e':
270
    case 'E':
271
      verbose_level = VERB_EVERYTHING; break;
272
    }
273
  if (verbose_level >= VERB_EVERYTHING) {
274
    verbose_level = VERB_EVERYTHING;
275
    fputs ("fixinc verbosity:  EVERYTHING\n", stderr);
276
  }
277
  while ((pz_find_base[0] == '.') && (pz_find_base[1] == '/'))
278
    pz_find_base += 2;
279
  if ((pz_find_base[0] != '.') || (pz_find_base[1] != NUL))
280
    find_base_len = strlen( pz_find_base );
281
 
282
  /*  Compile all the regular expressions now.
283
      That way, it is done only once for the whole run.
284
      */
285
  run_compiles ();
286
 
287
# ifdef SEPARATE_FIX_PROC
288
  /* NULL as the first argument to `tempnam' causes it to DTRT
289
     wrt the temporary directory where the file will be created.  */
290
  pz_temp_file = tempnam( NULL, "fxinc" );
291
# endif
292
 
293
  signal (SIGQUIT, SIG_IGN);
294
  signal (SIGIOT,  SIG_IGN);
295
  signal (SIGPIPE, SIG_IGN);
296
  signal (SIGALRM, SIG_IGN);
297
  signal (SIGTERM, SIG_IGN);
298
}
299
 
300
/* * * * * * * * * * * * *
301
 
302
   load_file loads all the contents of a file into malloc-ed memory.
303
   Its argument is the name of the file to read in; the returned
304
   result is the NUL terminated contents of the file.  The file
305
   is presumed to be an ASCII text file containing no NULs.  */
306
char *
307
load_file ( const char* fname )
308
{
309
  struct stat stbf;
310
  char* res;
311
 
312
  if (stat (fname, &stbf) != 0)
313
    {
314
      if (NOT_SILENT)
315
        fprintf (stderr, "error %d (%s) stat-ing %s\n",
316
                 errno, xstrerror (errno), fname );
317
      return (char *) NULL;
318
    }
319
  if (stbf.st_size == 0)
320
    return (char*)NULL;
321
 
322
  /*  Make the data map size one larger than the file size for documentation
323
      purposes.  Truth is that there will be a following NUL character if
324
      the file size is not a multiple of the page size.  If it is a multiple,
325
      then this adjustment sometimes fails anyway.  */
326
  data_map_size = stbf.st_size+1;
327
  data_map_fd   = open (fname, O_RDONLY);
328
  ttl_data_size += data_map_size-1;
329
 
330
  if (data_map_fd < 0)
331
    {
332
      if (NOT_SILENT)
333
        fprintf (stderr, "error %d (%s) opening %s for read\n",
334
                 errno, xstrerror (errno), fname);
335
      return (char*)NULL;
336
    }
337
 
338
#ifdef HAVE_MMAP_FILE
339
  curr_data_mapped = BOOL_TRUE;
340
 
341
  /*  IF the file size is a multiple of the page size,
342
      THEN sometimes you will seg fault trying to access a trailing byte */
343
  if ((stbf.st_size & (getpagesize()-1)) == 0)
344
    res = (char*)BAD_ADDR;
345
  else
346
    res = (char*)mmap ((void*)NULL, data_map_size, PROT_READ,
347
                       MAP_PRIVATE, data_map_fd, 0);
348
  if (res == (char*)BAD_ADDR)
349
#endif
350
    {
351
      FILE* fp = fdopen (data_map_fd, "r");
352
      curr_data_mapped = BOOL_FALSE;
353
      res = load_file_data (fp);
354
      fclose (fp);
355
    }
356
 
357
  return res;
358
}
359
 
360
static int
361
machine_matches( tFixDesc* p_fixd )
362
        {
363
# ifndef SEPARATE_FIX_PROC
364
          tSCC case_fmt[] = "case %s in\n";     /*  9 bytes, plus string */
365
          tSCC esac_fmt[] =
366
               " )\n    echo %s ;;\n* ) echo %s ;;\nesac";/*  4 bytes */
367
          tSCC skip[] = "skip";                 /*  4 bytes */
368
          tSCC run[] = "run";                   /*  3 bytes */
369
          /* total bytes to add to machine sum:    49 - see fixincl.tpl */
370
 
371
          const char **papz_machs = p_fixd->papz_machs;
372
          char *pz;
373
          const char *pz_sep = "";
374
          tCC *pz_if_true;
375
          tCC *pz_if_false;
376
          char cmd_buf[ MACH_LIST_SIZE_LIMIT ]; /* size lim from fixincl.tpl */
377
 
378
          /* Start the case statement */
379
 
380
          sprintf (cmd_buf, case_fmt, pz_machine);
381
          pz = cmd_buf + strlen (cmd_buf);
382
 
383
          /*  Determine if a match means to apply the fix or not apply it */
384
 
385
          if (p_fixd->fd_flags & FD_MACH_IFNOT)
386
            {
387
              pz_if_true  = skip;
388
              pz_if_false = run;
389
            }
390
          else
391
            {
392
              pz_if_true  = run;
393
              pz_if_false = skip;
394
            }
395
 
396
          /*  Emit all the machine names.  If there are more than one,
397
              then we will insert " | \\\n" between the names  */
398
 
399
          for (;;)
400
            {
401
              const char* pz_mach = *(papz_machs++);
402
 
403
              if (pz_mach == (const char*) NULL)
404
                break;
405
              sprintf (pz, "%s%s", pz_sep, pz_mach);
406
              pz += strlen (pz);
407
              pz_sep = " | \\\n";
408
            }
409
 
410
          /* Now emit the match and not-match actions and the esac */
411
 
412
          sprintf (pz, esac_fmt, pz_if_true, pz_if_false);
413
 
414
          /*  Run the script.
415
              The result will start either with 's' or 'r'.  */
416
 
417
          {
418
            int skip;
419
            pz = run_shell (cmd_buf);
420
            skip = (*pz == 's');
421
            free ( (void*)pz );
422
            if (skip)
423
              {
424
                p_fixd->fd_flags |= FD_SKIP_TEST;
425
                return BOOL_FALSE;
426
              }
427
          }
428
 
429
  return BOOL_TRUE;
430
# else /* is SEPARATE_FIX_PROC */
431
  const char **papz_machs = p_fixd->papz_machs;
432
  int invert = (p_fixd->fd_flags & FD_MACH_IFNOT) != 0;
433
  for (;;)
434
    {
435
      const char* pz_mach = *(papz_machs++);
436
 
437
      if (pz_mach == (const char*) NULL)
438
        break;
439
      if (strstr (pz_mach, "dos") != NULL && !invert)
440
        return BOOL_TRUE;
441
    }
442
 
443
  p_fixd->fd_flags |= FD_SKIP_TEST;
444
  return BOOL_FALSE;
445
# endif
446
}
447
 
448
/* * * * * * * * * * * * *
449
 
450
   run_compiles   run all the regexp compiles for all the fixes once.
451
   */
452
void
453
run_compiles (void)
454
{
455
  tFixDesc *p_fixd = fixDescList;
456
  int fix_ct = FIX_COUNT;
457
  regex_t *p_re = XCNEWVEC (regex_t, REGEX_COUNT);
458
 
459
  /*  Make sure compile_re does not stumble across invalid data */
460
 
461
  memset (&incl_quote_re, '\0', sizeof (regex_t));
462
 
463
  compile_re (incl_quote_pat, &incl_quote_re, 1,
464
              "quoted include", "run_compiles");
465
 
466
  /*  Allow machine name tests to be ignored (testing, mainly) */
467
 
468
  if (pz_machine && ((*pz_machine == '\0') || (*pz_machine == '*')))
469
    pz_machine = (char*)NULL;
470
 
471
  /* FOR every fixup, ...  */
472
  do
473
    {
474
      tTestDesc *p_test = p_fixd->p_test_desc;
475
      int test_ct = p_fixd->test_ct;
476
 
477
      /*  IF the machine type pointer is not NULL (we are not in test mode)
478
             AND this test is for or not done on particular machines
479
          THEN ...   */
480
 
481
      if (  (pz_machine != NULL)
482
         && (p_fixd->papz_machs != (const char**) NULL)
483
         && ! machine_matches (p_fixd) )
484
        continue;
485
 
486
      /* FOR every test for the fixup, ...  */
487
 
488
      while (--test_ct >= 0)
489
        {
490
          switch (p_test->type)
491
            {
492
            case TT_EGREP:
493
            case TT_NEGREP:
494
              p_test->p_test_regex = p_re++;
495
              compile_re (p_test->pz_test_text, p_test->p_test_regex, 0,
496
                          "select test", p_fixd->fix_name);
497
            default: break;
498
            }
499
          p_test++;
500
        }
501
    }
502
  while (p_fixd++, --fix_ct > 0);
503
}
504
 
505
 
506
/* * * * * * * * * * * * *
507
 
508
   create_file  Create the output modified file.
509
   Input:    the name of the file to create
510
   Returns:  a file pointer to the new, open file  */
511
 
512
#if defined(S_IRUSR) && defined(S_IWUSR) && \
513
    defined(S_IRGRP) && defined(S_IROTH)
514
 
515
#   define S_IRALL (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)
516
#else
517
#   define S_IRALL 0644
518
#endif
519
 
520
#if defined(S_IRWXU) && defined(S_IRGRP) && defined(S_IXGRP) && \
521
    defined(S_IROTH) && defined(S_IXOTH)
522
 
523
#   define S_DIRALL (S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)
524
#else
525
#   define S_DIRALL 0755
526
#endif
527
 
528
 
529
static FILE *
530
create_file (void)
531
{
532
  int fd;
533
  FILE *pf;
534
  char fname[MAXPATHLEN];
535
 
536
  sprintf (fname, "%s/%s", pz_dest_dir, pz_curr_file + find_base_len);
537
 
538
  fd = open (fname, O_WRONLY | O_CREAT | O_TRUNC, S_IRALL);
539
 
540
  /*  We may need to create the directories needed... */
541
  if ((fd < 0) && (errno == ENOENT))
542
    {
543
      char *pz_dir = strchr (fname + 1, '/');
544
      struct stat stbf;
545
 
546
      while (pz_dir != (char *) NULL)
547
        {
548
          *pz_dir = NUL;
549
          if (stat (fname, &stbf) < 0)
550
            {
551
#ifdef _WIN32
552
              mkdir (fname);
553
#else
554
              mkdir (fname, S_IFDIR | S_DIRALL);
555
#endif
556
            }
557
 
558
          *pz_dir = '/';
559
          pz_dir = strchr (pz_dir + 1, '/');
560
        }
561
 
562
      /*  Now, lets try the open again... */
563
      fd = open (fname, O_WRONLY | O_CREAT | O_TRUNC, S_IRALL);
564
    }
565
  if (fd < 0)
566
    {
567
      fprintf (stderr, "Error %d (%s) creating %s\n",
568
               errno, xstrerror (errno), fname);
569
      exit (EXIT_FAILURE);
570
    }
571
  if (NOT_SILENT)
572
    fprintf (stderr, "Fixed:  %s\n", pz_curr_file);
573
  pf = fdopen (fd, "w");
574
 
575
  /*
576
   *  IF pz_machine is NULL, then we are in some sort of test mode.
577
   *  Do not insert the current directory name.  Use a constant string.
578
   */
579
  fprintf (pf, z_std_preamble,
580
           (pz_machine == NULL)
581
           ? "fixinc/tests/inc"
582
           : pz_input_dir,
583
           pz_curr_file);
584
 
585
  return pf;
586
}
587
 
588
 
589
/* * * * * * * * * * * * *
590
 
591
  test_test   make sure a shell-style test expression passes.
592
  Input:  a pointer to the descriptor of the test to run and
593
          the name of the file that we might want to fix
594
  Result: APPLY_FIX or SKIP_FIX, depending on the result of the
595
          shell script we run.  */
596
#ifndef SEPARATE_FIX_PROC
597
static int
598
test_test (tTestDesc* p_test, char* pz_test_file)
599
{
600
  tSCC cmd_fmt[] =
601
"file=%s\n\
602
if ( test %s ) > /dev/null 2>&1\n\
603
then echo TRUE\n\
604
else echo FALSE\n\
605
fi";
606
 
607
  char *pz_res;
608
  int res;
609
 
610
  static char cmd_buf[4096];
611
 
612
  sprintf (cmd_buf, cmd_fmt, pz_test_file, p_test->pz_test_text);
613
  pz_res = run_shell (cmd_buf);
614
 
615
  switch (*pz_res) {
616
  case 'T':
617
    res = APPLY_FIX;
618
    break;
619
 
620
  case 'F':
621
    res = SKIP_FIX;
622
    break;
623
 
624
  default:
625
    fprintf (stderr, "Script yielded bogus result of `%s':\n%s\n\n",
626
             pz_res, cmd_buf );
627
    res = SKIP_FIX;
628
  }
629
 
630
  free ((void *) pz_res);
631
  return res;
632
}
633
#else
634
/*
635
 *  IF we are in MS-DOS land, then whatever shell-type test is required
636
 *  will, by definition, fail
637
 */
638
#define test_test(t,tf)  SKIP_FIX
639
#endif
640
 
641
/* * * * * * * * * * * * *
642
 
643
  egrep_test   make sure an egrep expression is found in the file text.
644
  Input:  a pointer to the descriptor of the test to run and
645
          the pointer to the contents of the file under suspicion
646
  Result: APPLY_FIX if the pattern is found, SKIP_FIX otherwise
647
 
648
  The caller may choose to reverse meaning if the sense of the test
649
  is inverted.  */
650
 
651
static int
652
egrep_test (char* pz_data, tTestDesc* p_test)
653
{
654
#ifdef DEBUG
655
  if (p_test->p_test_regex == 0)
656
    fprintf (stderr, "fixincl ERROR RE not compiled:  `%s'\n",
657
             p_test->pz_test_text);
658
#endif
659
  if (xregexec (p_test->p_test_regex, pz_data, 0, 0, 0) == 0)
660
    return APPLY_FIX;
661
  return SKIP_FIX;
662
}
663
 
664
 
665
/* * * * * * * * * * * * *
666
 
667
  quoted_file_exists  Make sure that a file exists before we emit
668
  the file name.  If we emit the name, our invoking shell will try
669
  to copy a non-existing file into the destination directory.  */
670
 
671
static int
672
quoted_file_exists (const char* pz_src_path,
673
                    const char* pz_file_path,
674
                    const char* pz_file)
675
{
676
  char z[ MAXPATHLEN ];
677
  char* pz;
678
  sprintf (z, "%s/%s/", pz_src_path, pz_file_path);
679
  pz = z + strlen ( z );
680
 
681
  for (;;) {
682
    char ch = *pz_file++;
683
    if (! ISGRAPH( ch ))
684
      return 0;
685
    if (ch == '"')
686
      break;
687
    *pz++ = ch;
688
  }
689
  *pz = '\0';
690
  {
691
    struct stat s;
692
    if (stat (z, &s) != 0)
693
      return 0;
694
    return S_ISREG( s.st_mode );
695
  }
696
}
697
 
698
 
699
/* * * * * * * * * * * * *
700
 *
701
   extract_quoted_files
702
 
703
   The syntax, `#include "file.h"' specifies that the compiler is to
704
   search the local directory of the current file before the include
705
   list.  Consequently, if we have modified a header and stored it in
706
   another directory, any files that are included by that modified
707
   file in that fashion must also be copied into this new directory.
708
   This routine finds those flavors of #include and for each one found
709
   emits a triple of:
710
 
711
    1.  source directory of the original file
712
    2.  the relative path file name of the #includ-ed file
713
    3.  the full destination path for this file
714
 
715
   Input:  the text of the file, the file name and a pointer to the
716
           match list where the match information was stored.
717
   Result: internally nothing.  The results are written to stdout
718
           for interpretation by the invoking shell  */
719
 
720
 
721
static void
722
extract_quoted_files (char* pz_data,
723
                      const char* pz_fixed_file,
724
                      regmatch_t* p_re_match)
725
{
726
  char *pz_dir_end = strrchr (pz_fixed_file, '/');
727
  char *pz_incl_quot = pz_data;
728
 
729
  if (VLEVEL( VERB_APPLIES ))
730
    fprintf (stderr, "Quoted includes in %s\n", pz_fixed_file);
731
 
732
  /*  Set "pz_fixed_file" to point to the containing subdirectory of the source
733
      If there is none, then it is in our current directory, ".".   */
734
 
735
  if (pz_dir_end == (char *) NULL)
736
    pz_fixed_file = ".";
737
  else
738
    *pz_dir_end = '\0';
739
 
740
  for (;;)
741
    {
742
      pz_incl_quot += p_re_match->rm_so;
743
 
744
      /*  Skip forward to the included file name */
745
      while (*pz_incl_quot != '"')
746
        pz_incl_quot++;
747
 
748
      if (quoted_file_exists (pz_src_dir, pz_fixed_file, pz_incl_quot))
749
        {
750
          /* Print the source directory and the subdirectory
751
             of the file in question.  */
752
          printf ("%s  %s/", pz_src_dir, pz_fixed_file);
753
          pz_dir_end = pz_incl_quot;
754
 
755
          /* Append to the directory the relative path of the desired file */
756
          while (*pz_incl_quot != '"')
757
            putc (*pz_incl_quot++, stdout);
758
 
759
          /* Now print the destination directory appended with the
760
             relative path of the desired file */
761
          printf ("  %s/%s/", pz_dest_dir, pz_fixed_file);
762
          while (*pz_dir_end != '"')
763
            putc (*pz_dir_end++, stdout);
764
 
765
          /* End of entry */
766
          putc ('\n', stdout);
767
        }
768
 
769
      /* Find the next entry */
770
      if (xregexec (&incl_quote_re, pz_incl_quot, 1, p_re_match, 0) != 0)
771
        break;
772
    }
773
}
774
 
775
 
776
/* * * * * * * * * * * * *
777
 
778
    Somebody wrote a *_fix subroutine that we must call.
779
    */
780
#ifndef SEPARATE_FIX_PROC
781
static int
782
internal_fix (int read_fd, tFixDesc* p_fixd)
783
{
784
  int fd[2];
785
 
786
  if (pipe( fd ) != 0)
787
    {
788
      fprintf (stderr, "Error %d on pipe(2) call\n", errno );
789
      exit (EXIT_FAILURE);
790
    }
791
 
792
  for (;;)
793
    {
794
      pid_t childid = fork();
795
 
796
      switch (childid)
797
        {
798
        case -1:
799
          break;
800
 
801
        case 0:
802
          close (fd[0]);
803
          goto do_child_task;
804
 
805
        default:
806
          /*
807
           *  Parent process
808
           */
809
          close (read_fd);
810
          close (fd[1]);
811
          return fd[0];
812
        }
813
 
814
      /*
815
       *  Parent in error
816
       */
817
      fprintf (stderr, z_fork_err, errno, xstrerror (errno),
818
               p_fixd->fix_name);
819
      {
820
        static int failCt = 0;
821
        if ((errno != EAGAIN) || (++failCt > 10))
822
          exit (EXIT_FAILURE);
823
        sleep (1);
824
      }
825
    } do_child_task:;
826
 
827
  /*
828
   *  Close our current stdin and stdout
829
   */
830
  close (STDIN_FILENO);
831
  close (STDOUT_FILENO);
832
  UNLOAD_DATA();
833
 
834
  /*
835
   *  Make the fd passed in the stdin, and the write end of
836
   *  the new pipe become the stdout.
837
   */
838
  dup2 (fd[1], STDOUT_FILENO);
839
  dup2 (read_fd, STDIN_FILENO);
840
 
841
  apply_fix (p_fixd, pz_curr_file);
842
  exit (0);
843
}
844
#endif /* !SEPARATE_FIX_PROC */
845
 
846
 
847
#ifdef SEPARATE_FIX_PROC
848
static void
849
fix_with_system (tFixDesc* p_fixd,
850
                 tCC* pz_fix_file,
851
                 tCC* pz_file_source,
852
                 tCC* pz_temp_file)
853
{
854
  char*  pz_cmd;
855
  char*  pz_scan;
856
  size_t argsize;
857
 
858
  if (p_fixd->fd_flags & FD_SUBROUTINE)
859
    {
860
      static const char z_applyfix_prog[] =
861
        "/../fixincludes/applyfix" EXE_EXT;
862
 
863
      struct stat buf;
864
      argsize = 32
865
              + strlen (pz_orig_dir)
866
              + sizeof (z_applyfix_prog)
867
              + strlen (pz_fix_file)
868
              + strlen (pz_file_source)
869
              + strlen (pz_temp_file);
870
 
871
      /* Allocate something sure to be big enough for our purposes */
872
      pz_cmd = XNEWVEC (char, argsize);
873
      strcpy (pz_cmd, pz_orig_dir);
874
      pz_scan = pz_cmd + strlen (pz_orig_dir);
875
 
876
      strcpy (pz_scan, z_applyfix_prog);
877
 
878
      /* IF we can't find the "applyfix" executable file at the first guess,
879
         try one level higher up  */
880
      if (stat (pz_cmd, &buf) == -1)
881
        {
882
          strcpy (pz_scan, "/..");
883
          strcpy (pz_scan+3, z_applyfix_prog);
884
        }
885
 
886
      pz_scan += strlen (pz_scan);
887
 
888
      /*
889
       *  Now add the fix number and file names that may be needed
890
       */
891
      sprintf (pz_scan, " %ld '%s' '%s' '%s'", p_fixd - fixDescList,
892
               pz_fix_file, pz_file_source, pz_temp_file);
893
    }
894
  else /* NOT an "internal" fix: */
895
    {
896
      size_t parg_size;
897
#ifdef __MSDOS__
898
      /* Don't use the "src > dstX; rm -f dst; mv -f dstX dst" trick:
899
         dst is a temporary file anyway, so we know there's no other
900
         file by that name; and DOS's system(3) doesn't mind to
901
         clobber existing file in redirection.  Besides, with DOS 8+3
902
         limited file namespace, we can easily lose if dst already has
903
         an extension that is 3 or more characters long.
904
 
905
         I do not think the 8+3 issue is relevant because all the files
906
         we operate on are named "*.h", making 8+2 adequate.  Anyway,
907
         the following bizarre use of 'cat' only works on DOS boxes.
908
         It causes the file to be dropped into a temporary file for
909
         'cat' to read (pipes do not work on DOS).  */
910
      tSCC   z_cmd_fmt[] = " '%s' | cat > '%s'";
911
#else
912
      /* Don't use positional formatting arguments because some lame-o
913
         implementations cannot cope  :-(.  */
914
      tSCC   z_cmd_fmt[] = " %s > %sX ; rm -f %s; mv -f %sX %s";
915
#endif
916
      tCC**  ppArgs = p_fixd->patch_args;
917
 
918
      argsize = sizeof( z_cmd_fmt ) + strlen( pz_temp_file )
919
              + strlen( pz_file_source );
920
      parg_size = argsize;
921
 
922
 
923
      /*
924
       *  Compute the size of the command line.  Add lotsa extra space
925
       *  because some of the args to sed use lotsa single quotes.
926
       *  (This requires three extra bytes per quote.  Here we allow
927
       *  for up to 8 single quotes for each argument, including the
928
       *  command name "sed" itself.  Nobody will *ever* need more. :)
929
       */
930
      for (;;)
931
        {
932
          tCC* p_arg = *(ppArgs++);
933
          if (p_arg == NULL)
934
            break;
935
          argsize += 24 + strlen( p_arg );
936
        }
937
 
938
      /* Estimated buffer size we will need.  */
939
      pz_scan = pz_cmd = XNEWVEC (char, argsize);
940
      /* How much of it do we allot to the program name and its
941
         arguments.  */
942
      parg_size = argsize - parg_size;
943
 
944
      ppArgs = p_fixd->patch_args;
945
 
946
      /*
947
       *  Copy the program name, unquoted
948
       */
949
      {
950
        tCC*   pArg = *(ppArgs++);
951
        for (;;)
952
          {
953
            char ch = *(pArg++);
954
            if (ch == NUL)
955
              break;
956
            *(pz_scan++) = ch;
957
          }
958
      }
959
 
960
      /*
961
       *  Copy the program arguments, quoted
962
       */
963
      for (;;)
964
        {
965
          tCC*   pArg = *(ppArgs++);
966
          char*  pz_scan_save;
967
          if (pArg == NULL)
968
            break;
969
          *(pz_scan++) = ' ';
970
          pz_scan = make_raw_shell_str( pz_scan_save = pz_scan, pArg,
971
                                        parg_size - (pz_scan - pz_cmd) );
972
          /*
973
           *  Make sure we don't overflow the buffer due to sloppy
974
           *  size estimation.
975
           */
976
          while (pz_scan == (char*)NULL)
977
            {
978
              size_t already_filled = pz_scan_save - pz_cmd;
979
              pz_cmd = xrealloc (pz_cmd, argsize += 100);
980
              pz_scan_save = pz_scan = pz_cmd + already_filled;
981
              parg_size += 100;
982
              pz_scan = make_raw_shell_str( pz_scan, pArg,
983
                                            parg_size - (pz_scan - pz_cmd) );
984
            }
985
        }
986
 
987
      /*
988
       *  add the file machinations.
989
       */
990
#ifdef __MSDOS__
991
      sprintf (pz_scan, z_cmd_fmt, pz_file_source, pz_temp_file );
992
#else
993
      sprintf (pz_scan, z_cmd_fmt, pz_file_source, pz_temp_file,
994
               pz_temp_file, pz_temp_file, pz_temp_file);
995
#endif
996
    }
997
  system( pz_cmd );
998
  free( (void*)pz_cmd );
999
}
1000
 
1001
/* * * * * * * * * * * * *
1002
 
1003
    This loop should only cycle for 1/2 of one loop.
1004
    "chain_open" starts a process that uses "read_fd" as
1005
    its stdin and returns the new fd this process will use
1006
    for stdout.  */
1007
 
1008
#else /* is *NOT* SEPARATE_FIX_PROC */
1009
static int
1010
start_fixer (int read_fd, tFixDesc* p_fixd, char* pz_fix_file)
1011
{
1012
  tCC* pz_cmd_save;
1013
  char* pz_cmd;
1014
 
1015
  if ((p_fixd->fd_flags & FD_SUBROUTINE) != 0)
1016
    return internal_fix (read_fd, p_fixd);
1017
 
1018
  if ((p_fixd->fd_flags & FD_SHELL_SCRIPT) == 0)
1019
    {
1020
      pz_cmd = NULL;
1021
      pz_cmd_save = NULL;
1022
    }
1023
  else
1024
    {
1025
      tSCC z_cmd_fmt[] = "file='%s'\n%s";
1026
      pz_cmd = XNEWVEC (char, strlen (p_fixd->patch_args[2])
1027
                        + sizeof (z_cmd_fmt) + strlen (pz_fix_file));
1028
      sprintf (pz_cmd, z_cmd_fmt, pz_fix_file, p_fixd->patch_args[2]);
1029
      pz_cmd_save = p_fixd->patch_args[2];
1030
      p_fixd->patch_args[2] = pz_cmd;
1031
    }
1032
 
1033
  /*  Start a fix process, handing off the  previous read fd for its
1034
      stdin and getting a new fd that reads from the fix process' stdout.
1035
      We normally will not loop, but we will up to 10 times if we keep
1036
      getting "EAGAIN" errors.
1037
 
1038
      */
1039
  for (;;)
1040
    {
1041
      static int failCt = 0;
1042
      int fd;
1043
 
1044
      fd = chain_open (read_fd,
1045
                       (tCC **) p_fixd->patch_args,
1046
                       (process_chain_head == -1)
1047
                       ? &process_chain_head : (pid_t *) NULL);
1048
 
1049
      if (fd != -1)
1050
        {
1051
          read_fd = fd;
1052
          break;
1053
        }
1054
 
1055
      fprintf (stderr, z_fork_err, errno, xstrerror (errno),
1056
               p_fixd->fix_name);
1057
 
1058
      if ((errno != EAGAIN) || (++failCt > 10))
1059
        exit (EXIT_FAILURE);
1060
      sleep (1);
1061
    }
1062
 
1063
  /*  IF we allocated a shell script command,
1064
      THEN free it and restore the command format to the fix description */
1065
  if (pz_cmd != (char*)NULL)
1066
    {
1067
      free ((void*)pz_cmd);
1068
      p_fixd->patch_args[2] = pz_cmd_save;
1069
    }
1070
 
1071
  return read_fd;
1072
}
1073
#endif
1074
 
1075
 
1076
/* * * * * * * * * * * * *
1077
 
1078
   Process the potential fixes for a particular include file.
1079
   Input:  the original text of the file and the file's name
1080
   Result: none.  A new file may or may not be created.  */
1081
 
1082
static t_bool
1083
fix_applies (tFixDesc* p_fixd)
1084
{
1085
  const char *pz_fname = pz_curr_file;
1086
  const char *pz_scan = p_fixd->file_list;
1087
  int test_ct;
1088
  tTestDesc *p_test;
1089
 
1090
# ifdef SEPARATE_FIX_PROC
1091
  /*
1092
   *  There is only one fix that uses a shell script as of this writing.
1093
   *  I hope to nuke it anyway, it does not apply to DOS and it would
1094
   *  be painful to implement.  Therefore, no "shell" fixes for DOS.
1095
   */
1096
  if (p_fixd->fd_flags & (FD_SHELL_SCRIPT | FD_SKIP_TEST))
1097
    return BOOL_FALSE;
1098
# else
1099
  if (p_fixd->fd_flags & FD_SKIP_TEST)
1100
    return BOOL_FALSE;
1101
# endif
1102
 
1103
  /*  IF there is a file name restriction,
1104
      THEN ensure the current file name matches one in the pattern  */
1105
 
1106
  if (pz_scan != (char *) NULL)
1107
    {
1108
      size_t name_len;
1109
 
1110
      while ((pz_fname[0] == '.') && (pz_fname[1] == '/'))
1111
        pz_fname += 2;
1112
      name_len = strlen (pz_fname);
1113
 
1114
      for (;;)
1115
        {
1116
          pz_scan = strstr (pz_scan + 1, pz_fname);
1117
          /*  IF we can't match the string at all,
1118
              THEN bail  */
1119
          if (pz_scan == (char *) NULL)
1120
            return BOOL_FALSE;
1121
 
1122
          /*  IF the match is surrounded by the '|' markers,
1123
              THEN we found a full match -- time to run the tests  */
1124
 
1125
          if ((pz_scan[-1] == '|') && (pz_scan[name_len] == '|'))
1126
            break;
1127
        }
1128
    }
1129
 
1130
  /*  FOR each test, see if it fails.
1131
      IF it does fail, then we go on to the next test */
1132
 
1133
  for (p_test = p_fixd->p_test_desc, test_ct = p_fixd->test_ct;
1134
       test_ct-- > 0;
1135
       p_test++)
1136
    {
1137
      switch (p_test->type)
1138
        {
1139
        case TT_TEST:
1140
          if (test_test (p_test, pz_curr_file) != APPLY_FIX) {
1141
#ifdef DEBUG
1142
            if (VLEVEL( VERB_EVERYTHING ))
1143
              fprintf (stderr, z_failed, "TEST", p_fixd->fix_name,
1144
                       pz_fname, p_fixd->test_ct - test_ct);
1145
#endif
1146
            return BOOL_FALSE;
1147
          }
1148
          break;
1149
 
1150
        case TT_EGREP:
1151
          if (egrep_test (pz_curr_data, p_test) != APPLY_FIX) {
1152
#ifdef DEBUG
1153
            if (VLEVEL( VERB_EVERYTHING ))
1154
              fprintf (stderr, z_failed, "EGREP", p_fixd->fix_name,
1155
                       pz_fname, p_fixd->test_ct - test_ct);
1156
#endif
1157
            return BOOL_FALSE;
1158
          }
1159
          break;
1160
 
1161
        case TT_NEGREP:
1162
          if (egrep_test (pz_curr_data, p_test) == APPLY_FIX) {
1163
#ifdef DEBUG
1164
            if (VLEVEL( VERB_EVERYTHING ))
1165
              fprintf (stderr, z_failed, "NEGREP", p_fixd->fix_name,
1166
                       pz_fname, p_fixd->test_ct - test_ct);
1167
#endif
1168
            /*  Negated sense  */
1169
            return BOOL_FALSE;
1170
          }
1171
          break;
1172
 
1173
        case TT_FUNCTION:
1174
          if (run_test (p_test->pz_test_text, pz_curr_file, pz_curr_data)
1175
              != APPLY_FIX) {
1176
#ifdef DEBUG
1177
            if (VLEVEL( VERB_EVERYTHING ))
1178
              fprintf (stderr, z_failed, "FTEST", p_fixd->fix_name,
1179
                       pz_fname, p_fixd->test_ct - test_ct);
1180
#endif
1181
            return BOOL_FALSE;
1182
          }
1183
          break;
1184
        }
1185
    }
1186
 
1187
  return BOOL_TRUE;
1188
}
1189
 
1190
 
1191
/* * * * * * * * * * * * *
1192
 
1193
   Write out a replacement file  */
1194
 
1195
static void
1196
write_replacement (tFixDesc* p_fixd)
1197
{
1198
   const char* pz_text = p_fixd->patch_args[0];
1199
 
1200
   if ((pz_text == (char*)NULL) || (*pz_text == NUL))
1201
     return;
1202
 
1203
   {
1204
     FILE* out_fp = create_file ();
1205
     size_t sz = strlen (pz_text);
1206
     fwrite (pz_text, sz, 1, out_fp);
1207
     if (pz_text[ sz-1 ] != '\n')
1208
       fputc ('\n', out_fp);
1209
     fclose (out_fp);
1210
   }
1211
}
1212
 
1213
 
1214
/* * * * * * * * * * * * *
1215
 
1216
    We have work to do.  Read back in the output
1217
    of the filtering chain.  Compare each byte as we read it with
1218
    the contents of the original file.  As soon as we find any
1219
    difference, we will create the output file, write out all
1220
    the matched text and then copy any remaining data from the
1221
    output of the filter chain.
1222
    */
1223
static void
1224
test_for_changes (int read_fd)
1225
{
1226
  FILE *in_fp = fdopen (read_fd, "r");
1227
  FILE *out_fp = (FILE *) NULL;
1228
  unsigned char *pz_cmp = (unsigned char*)pz_curr_data;
1229
 
1230
#ifdef DO_STATS
1231
  fixed_ct++;
1232
#endif
1233
  for (;;)
1234
    {
1235
      int ch;
1236
 
1237
      ch = getc (in_fp);
1238
      if (ch == EOF)
1239
        break;
1240
      ch &= 0xFF; /* all bytes are 8 bits */
1241
 
1242
      /*  IF we are emitting the output
1243
          THEN emit this character, too.
1244
      */
1245
      if (out_fp != (FILE *) NULL)
1246
        putc (ch, out_fp);
1247
 
1248
      /*  ELSE if this character does not match the original,
1249
          THEN now is the time to start the output.
1250
      */
1251
      else if (ch != *pz_cmp)
1252
        {
1253
          out_fp = create_file ();
1254
 
1255
#ifdef DO_STATS
1256
          altered_ct++;
1257
#endif
1258
          /*  IF there are matched data, write the matched part now. */
1259
          if ((char*)pz_cmp != pz_curr_data)
1260
            fwrite (pz_curr_data, (size_t)((char*)pz_cmp - pz_curr_data),
1261
                                        1, out_fp);
1262
 
1263
          /*  Emit the current unmatching character */
1264
          putc (ch, out_fp);
1265
        }
1266
      else
1267
        /*  ELSE the character matches.  Advance the compare ptr */
1268
        pz_cmp++;
1269
    }
1270
 
1271
  /*  IF we created the output file, ... */
1272
  if (out_fp != (FILE *) NULL)
1273
    {
1274
      regmatch_t match;
1275
 
1276
      /* Close the file and see if we have to worry about
1277
         `#include "file.h"' constructs.  */
1278
      fclose (out_fp);
1279
      if (xregexec (&incl_quote_re, pz_curr_data, 1, &match, 0) == 0)
1280
        extract_quoted_files (pz_curr_data, pz_curr_file, &match);
1281
    }
1282
 
1283
  fclose (in_fp);
1284
  close (read_fd);  /* probably redundant, but I'm paranoid */
1285
}
1286
 
1287
 
1288
/* * * * * * * * * * * * *
1289
 
1290
   Process the potential fixes for a particular include file.
1291
   Input:  the original text of the file and the file's name
1292
   Result: none.  A new file may or may not be created.  */
1293
 
1294
void
1295
process (void)
1296
{
1297
  tFixDesc *p_fixd = fixDescList;
1298
  int todo_ct = FIX_COUNT;
1299
  int read_fd = -1;
1300
# ifndef SEPARATE_FIX_PROC
1301
  int num_children = 0;
1302
# else /* is SEPARATE_FIX_PROC */
1303
  char* pz_file_source = pz_curr_file;
1304
# endif
1305
 
1306
  if (access (pz_curr_file, R_OK) != 0)
1307
    {
1308
      int erno = errno;
1309
      fprintf (stderr, "Cannot access %s from %s\n\terror %d (%s)\n",
1310
               pz_curr_file, getcwd ((char *) NULL, MAXPATHLEN),
1311
               erno, xstrerror (erno));
1312
      return;
1313
    }
1314
 
1315
  pz_curr_data = load_file (pz_curr_file);
1316
  if (pz_curr_data == (char *) NULL)
1317
    return;
1318
 
1319
#ifdef DO_STATS
1320
  process_ct++;
1321
#endif
1322
  if (VLEVEL( VERB_PROGRESS ) && have_tty)
1323
    fprintf (stderr, "%6lu %-50s   \r",
1324
             (unsigned long) data_map_size, pz_curr_file);
1325
 
1326
# ifndef SEPARATE_FIX_PROC
1327
  process_chain_head = NOPROCESS;
1328
 
1329
  /* For every fix in our fix list, ...  */
1330
  for (; todo_ct > 0; p_fixd++, todo_ct--)
1331
    {
1332
      if (! fix_applies (p_fixd))
1333
        continue;
1334
 
1335
      if (VLEVEL( VERB_APPLIES ))
1336
        fprintf (stderr, "Applying %-24s to %s\n",
1337
                 p_fixd->fix_name, pz_curr_file);
1338
 
1339
      if (p_fixd->fd_flags & FD_REPLACEMENT)
1340
        {
1341
          write_replacement (p_fixd);
1342
          UNLOAD_DATA();
1343
          return;
1344
        }
1345
 
1346
      /*  IF we do not have a read pointer,
1347
          THEN this is the first fix for the current file.
1348
          Open the source file.  That will be used as stdin for
1349
          the first fix.  Any subsequent fixes will use the
1350
          stdout descriptor of the previous fix for its stdin.  */
1351
 
1352
      if (read_fd == -1)
1353
        {
1354
          read_fd = open (pz_curr_file, O_RDONLY);
1355
          if (read_fd < 0)
1356
            {
1357
              fprintf (stderr, "Error %d (%s) opening %s\n", errno,
1358
                       xstrerror (errno), pz_curr_file);
1359
              exit (EXIT_FAILURE);
1360
            }
1361
 
1362
          /*  Ensure we do not get duplicate output */
1363
 
1364
          fflush (stdout);
1365
        }
1366
 
1367
      read_fd = start_fixer (read_fd, p_fixd, pz_curr_file);
1368
      num_children++;
1369
    }
1370
 
1371
  /*  IF we have a read-back file descriptor,
1372
      THEN check for changes and write output if changed.   */
1373
 
1374
  if (read_fd >= 0)
1375
    {
1376
      test_for_changes (read_fd);
1377
#ifdef DO_STATS
1378
      apply_ct += num_children;
1379
#endif
1380
      /* Wait for child processes created by chain_open()
1381
         to avoid leaving zombies.  */
1382
      do  {
1383
        wait ((int *) NULL);
1384
      } while (--num_children > 0);
1385
    }
1386
 
1387
# else /* is SEPARATE_FIX_PROC */
1388
 
1389
  for (; todo_ct > 0; p_fixd++, todo_ct--)
1390
    {
1391
      if (! fix_applies (p_fixd))
1392
        continue;
1393
 
1394
      if (VLEVEL( VERB_APPLIES ))
1395
        fprintf (stderr, "Applying %-24s to %s\n",
1396
                 p_fixd->fix_name, pz_curr_file);
1397
 
1398
      if (p_fixd->fd_flags & FD_REPLACEMENT)
1399
        {
1400
          write_replacement (p_fixd);
1401
          UNLOAD_DATA();
1402
          return;
1403
        }
1404
      fix_with_system (p_fixd, pz_curr_file, pz_file_source, pz_temp_file);
1405
      pz_file_source = pz_temp_file;
1406
    }
1407
 
1408
  read_fd = open (pz_temp_file, O_RDONLY);
1409
  if (read_fd < 0)
1410
    {
1411
      if (errno != ENOENT)
1412
        fprintf (stderr, "error %d (%s) opening output (%s) for read\n",
1413
                 errno, xstrerror (errno), pz_temp_file);
1414
    }
1415
  else
1416
    {
1417
      test_for_changes (read_fd);
1418
      /* Unlinking a file while it is still open is a Bad Idea on
1419
         DOS/Windows.  */
1420
      close (read_fd);
1421
      unlink (pz_temp_file);
1422
    }
1423
 
1424
# endif
1425
  UNLOAD_DATA();
1426
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.