Message-Id: <200007281731.UAA10498@mailgw1.netvision.net.il> Date: Fri, 28 Jul 2000 20:30:22 +0200 To: Bruce Korb X-Mailer: Emacs 20.6 (via feedmail 8.2.emacs20_6 I) and Blat ver 1.8.5b From: "Eli Zaretskii" CC: djgpp-workers AT delorie DOT com In-reply-to: <397DCC3F.32D9BB7C@sco.com> (message from Bruce Korb on Tue, 25 Jul 2000 10:19:59 -0700) Subject: Re: DJGPP patch for fixincludes References: <397DCC3F DOT 32D9BB7C AT sco DOT com> Reply-To: djgpp-workers AT delorie DOT com Errors-To: nobody AT delorie DOT com X-Mailing-List: djgpp-workers AT delorie DOT com X-Unsubscribes-To: listserv AT delorie DOT com Precedence: bulk > Date: Tue, 25 Jul 2000 10:19:59 -0700 > From: Bruce Korb > > Good luck and feel free to write :-). Okay, I have a first working version of fixincl and applyfix programs. The patches are attached below; they should be applied *after* the patches posted by Bruce here a few days ago. (If someone wants diffs agains the current CVS, I can do that, too.) These patches don't include any changes to fixinc/Makefile.in. Since the programs built for Unix and DOS are now different, I didn't make any changes in Makefile.in; instead, I simply threw together a Makefile by editing Makefile.in manually. Bruce, please let me know if you would like me to do something about Makefile.in. I tested the programs by running the fixinc.sh script on the DJGPP include directory. The utility of this testing is limited, since inclhack.def doesn't have any DJGPP-specific fixes. But some of the tests catch all platforms, and they did get run and allowed to test both internal and external fix methods. The result was that none of the DJGPP headers were changed in any way (one more sign that the programs DTRT ;-) (I did see some of the headers being ``fixed''--due to bugs--while working on this. So it seems that when the program decides it needs to edit a header, it does that correctly.) Nevertheless, I think it might be a good idea to come up with DJGPP-specific fixes and actually run them. Does someone have ideas for such fixes? DJ? Well, enough talking; let the code talk now ;-) 2000-07-28 Eli Zaretskii * fixinc/fixfixes.c (main) [__MSDOS__]: Avoid overwriting the output file with the temporary one by appending ".X" to generate the temporary fuile's name. If the output file already has an extension, replace it with ".X". * fixinc/fixincl.c (fix_with_system) [__MSDOS__]: Use $ORIGDIR, not $DESTDIR, to find applyfix. Use sprintf instead of snprintf; reallocate the command buffer while copying the command-line argument. Redirect the output directly to the temporary file, instead of going through another temporary file. (process): Close the temporary file before unlinking it. (machine_matches) [__MSDOS__]: If the machine doesn't match, set the FD_SKIP_TEST flag. Pay attention to the FD_MACH_IFNOT flag. (run_compiles): Pass p_fixd argument to machine_matches, as it expects. * fixinc/fixincl.sh: Export ORIGDIR. If $DJDIR is set in the environment, assume there are no symlinks in the include directory. When cleaning up the DONE files, look for them case-insensitively. Don't try to remove symlinks if they aren't there. * fixinc/fixlib.c (make_raw_shell_str): Accept new argument smax; all callers changed. Declare pz "const char *", to avoid compiler warnings. * fixinc/fixlib.h (ENV_TABLE): Get ORIGDIR from the environment. Change prototype of make_raw_shell_str. 2000-07-27 Eli Zaretskii * fixinc/fixincl.c [__MSDOS__]: Don't include "server.h". (initialize) [__MSDOS__]: Use tempnam. (initialize): Don't use SIGPIPE if it is not defined. * fixinc/fixfixes.c (main) [__MSDOS__]: freopen for stdout should return stdout. --- fixinc/fixlib.c~0 Thu Jul 27 20:53:42 2000 +++ fixinc/fixlib.c Fri Jul 28 13:37:16 2000 @@ -247,20 +247,24 @@ #endif -#ifdef __DOS__ +#ifdef __MSDOS__ char* -make_raw_shell_str( pz_d, pz_s ) +make_raw_shell_str( pz_d, pz_s, smax ) char* pz_d; tCC* pz_s; + size_t smax; { tSCC zQ[] = "'\\''"; size_t dtaSize; + char* pz_d_start = pz_d; + + smax--; /* adjust for trailing NUL */ dtaSize = strlen( pz_s ) + 3; { - char* pz = pz_s - 1; + const char* pz = pz_s - 1; for (;;) { pz = strchr( pz+1, '\'' ); @@ -269,15 +273,21 @@ dtaSize += sizeof( zQ )-1; } } + if (dtaSize > smax) + return (char*)NULL; *(pz_d++) = '\''; for (;;) { + if (pz_d - pz_d_start >= smax) + return (char*)NULL; switch (*(pz_d++) = *(pz_s++)) { case NUL: goto loopDone; case '\'': + if (pz_d - pz_d_start >= smax - sizeof( zQ )-1) + return (char*)NULL; strcpy( pz_d-1, zQ ); pz_d += sizeof( zQ )-2; } --- fixinc/fixlib.h~0 Thu Jul 27 21:54:12 2000 +++ fixinc/fixlib.h Fri Jul 28 13:45:20 2000 @@ -100,6 +100,9 @@ _ENV_( pz_machine, BOOL_TRUE, "TARGET_MACHINE", \ "output from config.guess" ) \ \ + _ENV_( pz_orig_dir, BOOL_TRUE, "ORIGDIR", \ + "directory of fixincl and applyfix" ) \ + \ _ENV_( pz_src_dir, BOOL_TRUE, "SRCDIR", \ "directory of original files" ) \ \ @@ -204,8 +207,8 @@ void apply_fix _P_(( tFixDesc* p_fixd, tCC* filname )); apply_fix_p_t run_test _P_((tCC* t_name, tCC* f_name, tCC* text )); -#ifdef __DOS__ -char* make_raw_shell_str _P_(( char* pz_d, tCC* pz_s )); +#ifdef __MSDOS__ +char* make_raw_shell_str _P_(( char* pz_d, tCC* pz_s, size_t smax )); #endif #ifdef MN_NAME_PAT --- fixinc/fixfixes.c~1 Thu Jul 27 20:53:42 2000 +++ fixinc/fixfixes.c Fri Jul 28 19:05:18 2000 @@ -60,7 +60,7 @@ #include "fixlib.h" #define GTYPE_SE_CT 1 -#ifdef __DOS__ +#ifdef __MSDOS__ #include "fixincl.x" #endif @@ -730,7 +730,7 @@ (*pfe->fix_proc)( filname, buf, p_fixd ); } -#ifdef __DOS__ +#ifdef __MSDOS__ tSCC z_usage[] = "USAGE: applyfix \n"; tSCC z_reopen[] = @@ -743,6 +743,8 @@ { tFixDesc* pFix; char* pz_tmptmp; + char* pz_tmp_base; + char* pz_tmp_dot; if (argc != 5) { @@ -771,8 +773,19 @@ } pz_tmptmp = (char*)xmalloc( strlen( argv[4] ) + 5 ); - sprintf( pz_tmptmp, "%sX", argv[4] ); - if (freopen( pz_tmptmp, "w", stdout ) != stdin) + strcpy( pz_tmptmp, argv[4] ); + + /* Don't lose because "12345678" and "12345678X" map to the same + file under DOS restricted 8+3 file namespace. Note that DOS + doesn't allow more than one dot in the trunk of a file name. */ + pz_tmp_base = basename( pz_tmptmp ); + pz_tmp_dot = strchr( pz_tmp_base, '.' ); + if (pathconf( pz_tmptmp, _PC_NAME_MAX ) <= 12 /* is this DOS or Windows9X? */ + && pz_tmp_dot != (char*)NULL) + strcpy( pz_tmp_dot+1, "X" ); /* nuke the original extension */ + else + strcat( pz_tmptmp, ".X" ); + if (freopen( pz_tmptmp, "w", stdout ) != stdout) { fprintf( stderr, z_reopen, errno, strerror( errno ), pz_tmptmp, "out" ); return EXIT_FAILURE; --- fixinc/fixincl.c~1 Thu Jul 27 20:59:30 2000 +++ fixinc/fixincl.c Fri Jul 28 19:26:08 2000 @@ -30,7 +30,7 @@ #endif #include -#ifndef __DOS__ +#ifndef __MSDOS__ #include "server.h" #endif @@ -182,7 +182,7 @@ } #endif /* DO_STATS */ -# ifdef __DOS__ +# ifdef __MSDOS__ unlink( pz_temp_file ); # endif return EXIT_SUCCESS; @@ -202,7 +202,7 @@ */ run_compiles (); sprintf (zBuf, zFmt, program_id); -#ifndef __DOS__ +#ifndef __MSDOS__ puts (zBuf + 5); exit (strcmp (run_shell (zBuf), program_id)); #else @@ -298,22 +298,19 @@ */ run_compiles (); -# ifdef __DOS__ - { - tSCC z_tmp_fname_fmt[] = "%s/fxinc%03X.tp"; - char* pz = getenv( "TMP" ); - if (pz == NULL) - pz = "/tmp"; - pz_temp_file = (char*)xmalloc (sizeof(z_tmp_fname_fmt) + strlen (pz)); - sprintf (pz_temp_file, z_tmp_fname_fmt, pz, getpid() & 0x0FFF); - } +# ifdef __MSDOS__ + /* NULL as the first argument to `tempnam' causes it to DTRT + wrt the temporary directory where the file will be created. */ + pz_temp_file = tempnam( NULL, "fxinc" ); # endif signal (SIGQUIT, SIG_IGN); #ifdef SIGIOT signal (SIGIOT, SIG_IGN); #endif +#ifdef SIGPIPE signal (SIGPIPE, SIG_IGN); +#endif signal (SIGALRM, SIG_IGN); signal (SIGTERM, SIG_IGN); } @@ -374,7 +371,7 @@ machine_matches( p_fixd ) tFixDesc *p_fixd; { -# ifndef __DOS__ +# ifndef __MSDOS__ tSCC case_fmt[] = "case %s in\n"; /* 9 bytes, plus string */ tSCC esac_fmt[] = " )\n echo %s ;;\n* ) echo %s ;;\nesac";/* 4 bytes */ @@ -436,26 +433,25 @@ if (skip) { p_fixd->fd_flags |= FD_SKIP_TEST; - return BOOL_FALSE; - } - } + return BOOL_FALSE; + } + } return BOOL_TRUE; -# else /* is __DOS__ */ +# else /* is __MSDOS__ */ const char **papz_machs = p_fixd->papz_machs; + int invert = (p_fixd->fd_flags & FD_MACH_IFNOT) != 0; for (;;) { const char* pz_mach = *(papz_machs++); if (pz_mach == (const char*) NULL) break; - if (strstr (pz_mach, "dos") != NULL) - { - p_fixd->fd_flags |= FD_SKIP_TEST; - return BOOL_TRUE; - } - } + if (strstr (pz_mach, "dos") != NULL && !invert) + return BOOL_TRUE; + } + p_fixd->fd_flags |= FD_SKIP_TEST; return BOOL_FALSE; # endif } @@ -476,7 +472,7 @@ fprintf (stderr, "fixincl ERROR: cannot allocate %d bytes for regex\n", REGEX_COUNT * sizeof (regex_t)); exit (EXIT_FAILURE); - } + } /* Make sure compile_re does not stumble across invalid data */ @@ -503,7 +499,7 @@ if ( (pz_machine != NULL) && (p_fixd->papz_machs != (const char**) NULL) - && ! machine_matches () ) + && ! machine_matches (p_fixd) ) continue; /* FOR every test for the fixup, ... */ @@ -611,7 +607,7 @@ the name of the file that we might want to fix Result: APPLY_FIX or SKIP_FIX, depending on the result of the shell script we run. */ -#ifndef __DOS__ +#ifndef __MSDOS__ int test_test (p_test, pz_test_file) tTestDesc *p_test; @@ -767,7 +763,7 @@ /* Skip forward to the included file name */ while (ISSPACE (*pz_incl_quot)) pz_incl_quot++; - /* ISSPACE() may evaluate is argument more than once! */ + /* ISSPACE() may evaluate its argument more than once! */ while (++pz_incl_quot, ISSPACE (*pz_incl_quot)) ; pz_incl_quot += sizeof ("include") - 1; @@ -806,7 +802,7 @@ Somebody wrote a *_fix subroutine that we must call. */ -#ifndef __DOS__ +#ifndef __MSDOS__ int internal_fix (read_fd, p_fixd) int read_fd; @@ -872,10 +868,10 @@ apply_fix (p_fixd, pz_curr_file); exit (0); } -#endif +#endif /* !__MSDOS__ */ -#ifdef __DOS__ +#ifdef __MSDOS__ static void fix_with_system (p_fixd, pz_fix_file, pz_file_source, pz_temp_file) tFixDesc* p_fixd; @@ -889,10 +885,10 @@ if (p_fixd->fd_flags & FD_SUBROUTINE) { - tSCC z_applyfix_prog = "fixinc/applyfix"; + tSCC z_applyfix_prog[] = "/fixinc/applyfix"; argsize = 32 - + strlen( pz_dest_dir ) + + strlen( pz_orig_dir ) + sizeof( z_applyfix_prog ) + strlen( pz_fix_file ) + strlen( pz_file_source ) @@ -900,26 +896,34 @@ pz_cmd = (char*)xmalloc( argsize ); - strcpy( pz_cmd, pz_dest_dir ); - pz_scan = strrchr( pz_cmd, '/' ); - strcpy( pz_scan+1, z_applyfix_prog ); - pz_scan += sizeof( z_applyfix_prog ); + strcpy( pz_cmd, pz_orig_dir ); + pz_scan = pz_cmd + strlen( pz_orig_dir ); + strcpy( pz_scan, z_applyfix_prog ); + pz_scan += sizeof( z_applyfix_prog ) - 1; *(pz_scan++) = ' '; /* * Now add the fix number and file names that may be needed */ - snprintf (pz_scan, argsize - (pz_scan - pz_cmd), - "%d %s %s %s", fixDescList - p_fixd, - pz_fix_file, pz_file_source, pz_temp_file); + sprintf (pz_scan, "%ld %s %s %s", p_fixd - fixDescList, + pz_fix_file, pz_file_source, pz_temp_file); } else /* NOT an "internal" fix: */ { - tSCC z_cmd_fmt[] = " %s > %sX\nrm -f %s\nmv -f %sX %s"; + size_t parg_size; + /* Don't use the "src > dstX; rm -f dst; mv -f dstX dst" trick: + dst is a temporary file anyway, so we know there's no other + file by that name; and DOS's system(3) doesn't mind to + clobber existing file in redirection. Besides, with DOS 8+3 + limited file namespace, we can easily lose if dst already has + an extension that is 3 or more characters long. */ + tSCC z_cmd_fmt[] = " %s > %s"; tCC** ppArgs = p_fixd->patch_args; - argsize = sizeof( z_cmd_fmt ) + 4 * strlen( pz_temp_file ) + argsize = sizeof( z_cmd_fmt ) + strlen( pz_temp_file ) + strlen( pz_file_source ); + parg_size = argsize; + /* * Compute the size of the command line. Add lotsa extra space @@ -936,7 +940,12 @@ argsize += 24 + strlen( p_arg ); } + /* Estimated buffer size we will need. */ pz_scan = pz_cmd = (char*)xmalloc( argsize ); + /* How much of it do we allot to the program name and its + arguments. */ + parg_size = argsize - parg_size; + ppArgs = p_fixd->patch_args; /* @@ -959,19 +968,31 @@ for (;;) { tCC* pArg = *(ppArgs++); + char* pz_scan_save; if (pArg == NULL) break; *(pz_scan++) = ' '; - pz_scan = make_raw_shell_str( pz_scan, pArg ); + pz_scan = make_raw_shell_str( pz_scan_save = pz_scan, pArg, + parg_size - (pz_scan - pz_cmd) ); + /* + * Make sure we don't overflow the buffer due to sloppy + * size estimation. + */ + while (pz_scan == (char*)NULL) + { + size_t already_filled = pz_scan_save - pz_cmd; + pz_cmd = (char*)xrealloc( pz_cmd, argsize += 100 ); + pz_scan_save = pz_scan = pz_cmd + already_filled; + parg_size += 100; + pz_scan = make_raw_shell_str( pz_scan, pArg, + parg_size - (pz_scan - pz_cmd) ); + } } /* - * add the file machinations. Make sure we don't overflow - * the buffer due to sloppy size estimation. + * add the file machinations. */ - snprintf( pz_scan, argsize - (pz_scan - pz_cmd), z_cmd_fmt, - pz_file_source, - pz_temp_file, pz_temp_file, pz_temp_file ); + sprintf( pz_scan, z_cmd_fmt, pz_file_source, pz_temp_file ); } system( pz_cmd ); free( (void*)pz_cmd ); @@ -984,7 +1005,7 @@ its stdin and returns the new fd this process will use for stdout. */ -#else /* is *NOT* __DOS__ */ +#else /* is *NOT* __MSDOS__ */ int start_fixer (read_fd, p_fixd, pz_fix_file) int read_fd; @@ -1073,7 +1094,7 @@ int test_ct; tTestDesc *p_test; -# ifdef __DOS__ +# ifdef __MSDOS__ /* * There is only one fix that uses a shell script as of this writing. * I hope to nuke it anyway, it does not apply to DOS and it would @@ -1280,9 +1301,9 @@ tFixDesc *p_fixd = fixDescList; int todo_ct = FIX_COUNT; int read_fd = -1; -# ifndef __DOS__ +# ifndef __MSDOS__ int num_children = 0; -# else /* is __DOS__ */ +# else /* is __MSDOS__ */ char* pz_file_source = pz_curr_file; # endif @@ -1305,7 +1326,7 @@ if (VLEVEL( VERB_PROGRESS ) && have_tty) fprintf (stderr, "%6d %-50s \r", data_map_size, pz_curr_file ); -# ifndef __DOS__ +# ifndef __MSDOS__ process_chain_head = NOPROCESS; /* For every fix in our fix list, ... */ @@ -1366,7 +1387,7 @@ } while (--num_children > 0); } -# else /* is __DOS__ */ +# else /* is __MSDOS__ */ for (; todo_ct > 0; p_fixd++, todo_ct--) { @@ -1389,6 +1410,9 @@ read_fd = open( pz_temp_file, O_RDONLY ); test_for_changes( read_fd ); + /* Unlinking a file while it is still open is a Bad Idea on + DOS/Windows. */ + close( read_fd ); unlink( pz_temp_file ); # endif --- fixinc/README.~0 Wed May 24 19:12:56 2000 +++ fixinc/README Thu Jul 27 20:44:54 2000 @@ -67,7 +67,7 @@ It is nice if: 3. The expression is as simple as possible to both - process and uderstand by people. :-) + process and understand by people. :-) Please take advantage of the fact AutoGen will glue together string fragments. It helps. Also take note --- fixinc/fixincl.s~0 Fri Jul 28 00:09:02 2000 +++ fixinc/fixincl.sh Fri Jul 28 19:52:04 2000 @@ -112,7 +112,9 @@ then echo Fixing headers into ${LIB} for ${target_canonical} target ; fi # Determine whether this system has symbolic links. -if ln -s X $LIB/ShouldNotExist 2>/dev/null; then +if test -n "$DJDIR"; then + LINKS=false +elif ln -s X $LIB/ShouldNotExist 2>/dev/null; then rm -f $LIB/ShouldNotExist LINKS=true elif ln -s X /tmp/ShouldNotExist 2>/dev/null; then @@ -423,7 +425,9 @@ if test $VERBOSE -gt 2 then echo 'Cleaning up DONE files.' ; fi cd $LIB -find . -name DONE -exec rm -f '{}' ';' +# Look for files case-insensitively, for the benefit of +# DOS/Windows filesystems. +find . -name '[Dd][Oo][Nn][Ee]' -exec rm -f '{}' ';' if test $VERBOSE -gt 1 then echo 'Cleaning up unneeded directories:' ; fi @@ -436,20 +440,25 @@ fi done 2> /dev/null -test $VERBOSE -gt 2 && echo "Removing unused symlinks" +# On systems which don't support symlinks, `find' may barf +# if called with "-type l" predicate. So only use that if +# we know we should look for symlinks. +if $LINKS; then + test $VERBOSE -gt 2 && echo "Removing unused symlinks" -all_dirs=`find . -type l -print` -for file in $all_dirs -do - if ls -lLd $file > /dev/null - then : - else rm -f $file - test $VERBOSE -gt 3 && echo " removed $file" - rmdir `dirname $file` > /dev/null && \ - test $VERBOSE -gt 3 && \ - echo " removed `dirname $file`" - fi -done 2> /dev/null + all_dirs=`find . -type l -print` + for file in $all_dirs + do + if ls -lLd $file > /dev/null + then : + else rm -f $file + test $VERBOSE -gt 3 && echo " removed $file" + rmdir `dirname $file` > /dev/null && \ + test $VERBOSE -gt 3 && \ + echo " removed `dirname $file`" + fi + done 2> /dev/null +fi if test $VERBOSE -gt 0 then echo fixincludes is done ; fi