Date: Sun, 8 Sep 1996 10:51:32 +0200 (IST) From: Eli Zaretskii To: djgpp-workers AT delorie DOT com Subject: Make 3.74 diffs Message-Id: Mime-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII The diffs below are against stock make-3.74.tar.gz distribution. They will allow to build a DJGPP port of Make with the following features: * Supports LFN on Windows 95. * Calls `system' for commands which use redirection, pipes, or other features which require to call a shell (so you can have long command lines *and* redirection/pipes). * Calls `popen' to implement $(shell) built-in (so you can have long commands and pipes). * Supports signals to the child programs (prints the signal name). * Returns to the original directory when interrupted. * Knows about [4N]DOS and Unix-like shells as well as COMMAND.COM. * Ignores "SHELL = /bin/sh" lines on Makefiles (only if the value is "/bin/sh" verbatim). * Notes the $SHELL variable and instructs `system' to call the shell to do everything if the value of $SHELL is a Unix-style shell. * An additional variable $MAKESHELL is supported, so you can run a shell port as your interactive program and use COMMMAND.COM in Makefiles. * You can build a no-FP version of Make which should not require a co-processor (somebody with an SX please test this). I will upload the source distribution in a couple of days, but I'd like for people to review the diffs and the features and comment on them even now. Some of the code was lifted from and old port by Morten, so I'd appreciate if Morten could find a few minutes to look at the diffs. Thanks. Btw, I've looked at Make 3.75 hoping that applying the diffs from 3.74 and building will be all that's needed, but there are a lot of Win32 changes in there, so it will take a bit more time to make it happen, and I'd like the next alpha to have an improved Make. This way, people who use 4DOS and sh will have an opportunity to test the whole concept of `system' and its use in Make. *** configur.b~1 Sat Aug 24 17:12:16 1996 --- configur.bat Sat Aug 31 11:34:14 1996 *************** *** 1,10 **** @echo off ! echo Configuring MAKE for go32 rem This batch file assumes a unix-type "sed" program update configh.dos config.h ! echo # Makefile generated by "configure.bat"> Makefile if exist config.sed del config.sed --- 1,10 ---- @echo off ! echo Configuring MAKE for DJGPP rem This batch file assumes a unix-type "sed" program update configh.dos config.h ! echo # Makefile generated for DJGPP by "configure.bat"> Makefile if exist config.sed del config.sed *************** *** 18,24 **** --- 18,32 ---- echo "s/@srcdir@/./ ">> config.sed echo "s/@CC@/gcc/ ">> config.sed echo "s/@CFLAGS@/-O2 -g/ ">> config.sed + if "%1"=="no-float" goto nofloat + if "%1"=="NO-FLOAT" goto nofloat + if "%1"=="NO_FLOAT" goto nofloat + if "%1"=="no_float" goto nofloat echo "s/@CPPFLAGS@/-DHAVE_CONFIG_H/ ">> config.sed + goto floatdone + :nofloat + echo "s/@CPPFLAGS@/-DHAVE_CONFIG_H -DNO_FLOAT/ ">> config.sed + :floatdone echo "s/@LDFLAGS@// ">> config.sed echo "s/@RANLIB@/ranlib/ ">> config.sed echo "s/@DEFS@// ">> config.sed *** configh.d~1 Thu Mar 9 01:11:28 1995 --- configh.dos Fri Sep 6 19:44:28 1996 *************** *** 21,33 **** #endif /* Define if `sys_siglist' is declared by . */ ! #define SYS_SIGLIST_DECLARED ! ! /* Define if you have getdtablesize. */ ! #define HAVE_GETDTABLESIZE ! ! /* Define if you have dup2. */ ! #define HAVE_DUP2 /* Define if you have sys_siglist. */ #undef HAVE_SYS_SIGLIST --- 21,27 ---- #endif /* Define if `sys_siglist' is declared by . */ ! #undef SYS_SIGLIST_DECLARED /* Define if you have sys_siglist. */ #undef HAVE_SYS_SIGLIST *************** *** 38,43 **** --- 32,49 ---- /* Define if you have psignal. */ #define HAVE_PSIGNAL + /* Define if you have strsignal. */ + #undef HAVE_STRSIGNAL + + /* Define NSIG. */ + #define NSIG SIGMAX + + /* Define if you have getdtablesize. */ + #define HAVE_GETDTABLESIZE + + /* Define if you have dup2. */ + #define HAVE_DUP2 + /* Define if you have getcwd. */ #define HAVE_GETCWD *************** *** 64,68 **** --- 70,77 ---- /* Define if you have the `strerror' function. */ #define HAVE_STRERROR + + /* Define if you have the header file. */ + #define HAVE_SYS_WAIT_H #define SCCS_GET "get" *** dir.c~1 Tue Nov 8 00:14:50 1994 --- dir.c Fri Aug 30 14:47:46 1996 *************** *** 49,54 **** --- 49,55 ---- #ifdef __MSDOS__ #include + #include static char * dosify (filename) *************** *** 58,66 **** char *df; int i; ! if (filename == 0) ! return 0; if (strpbrk (filename, "\"*+,;<=>?[\\]|") != 0) return filename; --- 59,68 ---- char *df; int i; ! if (filename == 0 || _USE_LFN) ! return filename; + /* FIXME: what about filenames that violate 8+3 constraints? */ if (strpbrk (filename, "\"*+,;<=>?[\\]|") != 0) return filename; *** function.c~1 Wed Apr 19 18:08:48 1995 --- function.c Sat Sep 7 19:06:54 1996 *************** *** 22,32 **** #include "commands.h" #include "job.h" - #ifdef __MSDOS__ - #include - #include - #endif - static char *string_glob (); /* Store into VARIABLE_BUFFER at O the result of scanning TEXT and replacing --- 22,27 ---- *************** *** 344,349 **** --- 339,349 ---- char *error_prefix; int pipedes[2]; int pid; + #ifdef __MSDOS__ + int e; + FILE *fpipe; + int save_sys_flags = 0; + #endif /* Expand the command line. */ text = expand_argument (text, end); *************** *** 376,389 **** else error_prefix = ""; ! #ifndef __MSDOS__ if (pipe (pipedes) < 0) { perror_with_name (error_prefix, "pipe"); break; } pid = vfork (); if (pid < 0) perror_with_name (error_prefix, "fork"); else if (pid == 0) --- 376,461 ---- else error_prefix = ""; ! #ifdef __MSDOS__ ! { ! struct variable *sh = lookup_variable ("SHELL", 5); ! char *shbase; ! ! if (sh) ! { ! char buf[PATH_MAX + 7]; ! #ifndef _POSIX_SOURCE ! for (shbase = sh->value + strlen (sh->value) - 1; ! shbase > sh->value; ! shbase--) ! { ! if (*shbase == '/' || *shbase == '\\' || *shbase == ':') ! { ! shbase++; ! break; ! } ! } ! ! /* If $SHELL doesn't match any of the known MSDOS shells, ! we assume it is a real (Unix-like) shell, and thus ! doesn't need any assistance from our `system'. */ ! if (stricmp (shbase, "command.com") ! && stricmp (shbase, "4dos.com") ! && stricmp (shbase, "ndos.com")) ! { ! save_sys_flags = __system_flags; ! __system_flags |= __system_call_cmdproc; ! } ! #endif ! /* This makes sure $SHELL value is used by $(shell), even ! though the target environment is not passed to it. */ ! sprintf (buf, "SHELL=%s", sh->value); ! putenv (buf); ! } ! } ! e = errno; ! errno = 0; ! { ! extern int dos_command_running, dos_status; ! ! dos_command_running = 1; ! dos_status = 0; ! fpipe = popen (text, "rt"); ! dos_command_running = 0; ! #ifndef _POSIX_SOURCE ! if (save_sys_flags) ! __system_flags = save_sys_flags; ! #endif ! if (!fpipe || dos_status) ! { ! pipedes[0] = -1; ! pid = -1; ! if (dos_status) ! errno = EINTR; ! else if (errno == 0) ! errno = ENOMEM; ! shell_function_completed = -1; ! } ! else ! { ! pipedes[0] = fileno (fpipe); ! pid = 42; ! errno = e; ! shell_function_completed = 1; ! } ! } ! if (pipedes[0] < 0) ! #else if (pipe (pipedes) < 0) + #endif { perror_with_name (error_prefix, "pipe"); break; } + #ifndef __MSDOS__ pid = vfork (); + #endif if (pid < 0) perror_with_name (error_prefix, "fork"); else if (pid == 0) *************** *** 407,423 **** /* Record the PID for reap_children. */ shell_function_pid = pid; shell_function_completed = 0; /* Set up and read from the pipe. */ maxlen = 200; buffer = (char *) xmalloc (maxlen + 1); - /* Close the write side of the pipe. */ - (void) close (pipedes[1]); - /* Read from the pipe until it gets EOF. */ i = 0; do --- 479,496 ---- /* Record the PID for reap_children. */ shell_function_pid = pid; + #ifndef __MSDOS__ shell_function_completed = 0; + /* Close the write side of the pipe. */ + (void) close (pipedes[1]); + #endif /* Set up and read from the pipe. */ maxlen = 200; buffer = (char *) xmalloc (maxlen + 1); /* Read from the pipe until it gets EOF. */ i = 0; do *************** *** 440,446 **** --- 513,524 ---- #endif /* Close the read side of the pipe. */ + #ifdef __MSDOS__ + if (fpipe) + (void) pclose (fpipe); + #else (void) close (pipedes[0]); + #endif /* Loop until child_handler sets shell_function_completed to the status of our child shell. */ *************** *** 481,549 **** free (buffer); } - #else /* MSDOS. */ - { - /* MS-DOS can't do fork, but it can do spawn. However, this - means that we don't have an opportunity to reopen stdout to - trap it. Thus, we save our own stdout onto a new descriptor - and dup a temp file's descriptor onto our stdout temporarily. - After we spawn the shell program, we dup our own stdout back - to the stdout descriptor. The buffer reading is the same as - above, except that we're now reading from a file. */ - - int save_stdout; - int child_stdout; - char tmp_output[FILENAME_MAX]; - FILE *child_stream; - unsigned int maxlen = 200; - int cc; - char *buffer; - - strcpy (tmp_output, "shXXXXXX"); - mktemp (tmp_output); - child_stdout = open (tmp_output, - O_WRONLY|O_CREAT|O_TRUNC|O_TEXT, 0644); - save_stdout = dup (1); - dup2 (child_stdout, 1); - spawnvp (P_WAIT, argv[0], argv); - dup2 (save_stdout, 1); - close (child_stdout); - close (save_stdout); - - child_stdout = open (tmp_output, O_RDONLY|O_TEXT, 0644); - - buffer = xmalloc (maxlen); - i = 0; - do - { - if (i == maxlen) - { - maxlen += 512; - buffer = (char *) xrealloc (buffer, maxlen + 1); - } - - cc = read (child_stdout, &buffer[i], maxlen - i); - if (cc > 0) - i += cc; - } while (cc > 0); - - close (child_stdout); - unlink (tmp_output); - - if (i > 0) - { - if (buffer[i - 1] == '\n') - buffer[--i] = '\0'; - else - buffer[i] = '\0'; - p = buffer; - while ((p = index (p, '\n')) != 0) - *p++ = ' '; - o = variable_buffer_output (o, buffer, i); - } - free (buffer); - } - #endif /* Not MSDOS. */ free (text); break; --- 559,564 ---- *** main.c~1 Tue Mar 28 18:59:06 1995 --- main.c Sat Sep 7 18:38:02 1996 *************** *** 61,67 **** --- 61,69 ---- flag_off, /* Turn int flag off. */ string, /* One string per switch. */ positive_int, /* A positive integer. */ + #if !defined(__MSDOS__) || !defined(NO_FLOAT) floating, /* A floating-point number (double). */ + #endif ignore /* Ignored. */ } type; *************** *** 171,178 **** --- 173,182 ---- zero load (which could be useful to start infinite jobs remotely but one at a time locally). */ + #if !defined(__MSDOS__) || !defined(NO_FLOAT) double max_load_average = -1.0; double default_load_average = -1.0; + #endif /* List of directories given with -C switches. */ *************** *** 235,244 **** --- 239,250 ---- 0, (char *) &default_keep_going_flag, "keep-going", 0, "Keep going when some targets can't be made" }, + #if !defined(__MSDOS__) || !defined(NO_FLOAT) { 'l', floating, (char *) &max_load_average, 1, 1, 0, (char *) &default_load_average, (char *) &default_load_average, "load-average", "N", "Don't start multiple jobs unless load is below N" }, + #endif { 'm', ignore, 0, 0, 0, 0, 0, 0, 0, 0, "-b" }, *************** *** 352,357 **** --- 358,376 ---- This turns on pedantic compliance with POSIX.2. */ int posix_pedantic; + + #ifdef __MSDOS__ + /* The initial directory, where it all started. */ + + static char *initial_directory; + + static void + msdos_return_to_initial_directory () + { + if (initial_directory) + chdir (initial_directory); + } + #endif /* Mask of signals that are being caught with fatal_error_signal. */ *************** *** 424,429 **** --- 443,460 ---- default_goal_file = 0; reading_filename = 0; reading_lineno_ptr = 0; + + #if defined (__MSDOS__) && !defined (_POSIX_SOURCE) + /* Request the most powerful version of `system', to + make up for the dumb default shell. */ + __system_flags = (__system_redirect + | __system_use_shell + | __system_allow_multiple_cmds + | __system_allow_long_cmds + | __system_handle_null_commands + | __system_emulate_chdir); + + #endif #if !defined (HAVE_STRSIGNAL) && !defined (HAVE_SYS_SIGLIST) signame_init (); *************** *** 519,524 **** --- 550,562 ---- else directory_before_chdir = savestring (current_directory, strlen (current_directory)); + #ifdef __MSDOS__ + /* MS-DOS doesn't have per-process cwd. */ + if (directory_before_chdir) + initial_directory = savestring (current_directory, + strlen (current_directory)); + atexit (msdos_return_to_initial_directory); + #endif /* Read in variables from the environment. It is important that this be done before $(MAKE) is are figured out so its definitions will not be *************** *** 1180,1186 **** --- 1218,1226 ---- case string: case positive_int: + #if !defined(__MSDOS__) || !defined(NO_FLOAT) case floating: + #endif if (isalnum (switches[i].c)) *p++ = ':'; if (switches[i].noarg_value != 0) *************** *** 1366,1371 **** --- 1406,1412 ---- = *(unsigned int *) cs->noarg_value; break; + #if !defined(__MSDOS__) || !defined(NO_FLOAT) case floating: if (optarg == 0 && optind < argc && (isdigit (argv[optind][0]) || argv[optind][0] == '.')) *************** *** 1377,1382 **** --- 1418,1424 ---- : *(double *) cs->noarg_value); break; + #endif } /* We've found the switch. Stop looking. */ *************** *** 1692,1697 **** --- 1734,1740 ---- } break; + #if !defined(__MSDOS__) || !defined(NO_FLOAT) case floating: if (all) { *************** *** 1711,1716 **** --- 1754,1760 ---- } } break; + #endif case string: if (all) *** make.h~1 Tue Feb 7 18:36:00 1995 --- make.h Sat Aug 24 17:09:36 1996 *************** *** 333,339 **** --- 333,341 ---- extern int posix_pedantic; extern unsigned int job_slots; + #if !defined(__MSDOS__) || !defined(NO_FLOAT) extern double max_load_average; + #endif extern char *program; extern char *starting_directory; *** read.c~1 Mon Mar 13 05:38:52 1995 --- read.c Fri Aug 30 20:27:56 1996 *************** *** 712,717 **** --- 712,735 ---- /* Is this a static pattern rule: `target: %targ: %dep; ...'? */ p = index (p2, ':'); + #ifdef __MSDOS__ + /* On MS-DOS, search for a colon which is neither + escaped by a backslash, nor a drive letter followed + by a slash (like in "C:\..." or "c:/..."). */ + while (p != 0 + && (p[-1] == '\\' || p[1] == '/' || p[1] == '\\')) + { + int dos_full_path = (p[1] == '/' || p[1] == '\\'); + register char *q = &p[-1]; + register int backslash = 0; + while (*q-- == '\\') + backslash = !backslash; + if (backslash || dos_full_path) + p = index (p + 1, ':'); + else + break; + } + #else /* not __MSDOS__ */ while (p != 0 && p[-1] == '\\') { register char *q = &p[-1]; *************** *** 723,733 **** else break; } ! #ifdef __MSDOS__ ! /* For MS-DOS, skip a "C:\...". */ ! if (p != 0 && p[1] == '\\' && isalpha (p[-1])) ! p = 0; ! #endif if (p != 0) { struct nameseq *target; --- 741,748 ---- else break; } ! #endif /* not __MSDOS__ */ ! if (p != 0) { struct nameseq *target; *************** *** 1543,1551 **** q = p; p = find_char_unquote (q, stopchars, 1); #ifdef __MSDOS__ ! /* For MS-DOS, skip a "C:\...". */ ! if (stopchar == ':' && p != 0 && p[1] == '\\' && isalpha (p[-1])) ! p = 0; #endif if (p == 0) p = q + strlen (q); --- 1558,1569 ---- q = p; p = find_char_unquote (q, stopchars, 1); #ifdef __MSDOS__ ! /* For MS-DOS,a colon in "C:\..." or "c:/..." doesn't count. ! We should search for the first colon which isn't followed by ! a slash or a backslash. */ ! if (stopchar == ':') ! while (p != 0 && (p[1] == '\\' || p[1] == '/')) ! p = find_char_unquote (p + 1, stopchars, 1); #endif if (p == 0) p = q + strlen (q); *************** *** 1804,1809 **** --- 1822,1830 ---- register char **dirs = (char **) xmalloc ((5 + defsize) * sizeof (char *)); register unsigned int idx = 0; + #ifdef __MSDOS__ + defsize++; + #endif /* First consider any dirs specified with -I switches. Ignore dirs that don't exist. */ *************** *** 1834,1839 **** --- 1855,1874 ---- } /* Now add at the end the standard default dirs. */ + + #ifdef __MSDOS__ + { + struct variable *djdir = lookup_variable ("DJDIR", 5); + + if (djdir) + { + char *defdir = (char *) xmalloc (strlen (djdir->value) + 8 + 1); + + strcat (strcpy (defdir, djdir->value), "/include"); + dirs[idx++] = defdir; + } + } + #endif for (i = 0; default_include_directories[i] != 0; ++i) if (safe_stat (default_include_directories[i], &stbuf) == 0 *** remake.c~1 Thu Apr 27 16:36:38 1995 --- remake.c Fri Aug 30 21:26:30 1996 *************** *** 29,34 **** --- 29,38 ---- #include #endif + #ifdef __MSDOS__ + #include "variable.h" + #endif + extern int try_implicit_rule (); *************** *** 1061,1066 **** --- 1065,1093 ---- } /* Now try the standard set of directories. */ + + #ifdef __MSDOS__ + { + struct variable *djdir = lookup_variable ("DJDIR", 5); + + if (djdir) + { + size_t djdir_len = strlen (djdir->value); + + if (djdir_len > sizeof(LIBDIR) + 8 + strlen(libname) + 4 + 2) + buf = (char *) xrealloc (djdir_len + 1); + sprintf (buf, "%s/lib/lib%s.a", djdir->value, libname); + mtime = name_mtime (buf); + if (mtime != (time_t) -1) + { + *lib = buf; + if (mtime_ptr != 0) + *mtime_ptr = mtime; + return 1; + } + } + } + #endif for (dp = dirs; *dp != 0; ++dp) { *** signame.c~1 Wed May 10 21:46:48 1995 --- signame.c Sat Sep 7 19:17:58 1996 *************** *** 227,232 **** --- 227,235 ---- #if defined (SIGINFO) init_sig (SIGINFO, "INFO", "Information request"); #endif + #if defined (SIGNOFP) + init_sig (SIGNOFP, "NOFP", "Floating point co-processor not available"); + #endif } /* Return the abbreviation for signal NUMBER. */ *** variable.c~1 Mon Oct 10 08:08:58 1994 --- variable.c Sat Sep 7 19:20:22 1996 *************** *** 360,371 **** --- 360,399 ---- ? "" : remote_description); (void) define_variable ("MAKE_VERSION", 12, buf, o_default, 0); + #ifdef __MSDOS__ + /* Allow to specify a special shell just for Make, + and use $COMSPEC as the default $SHELL when appropriate. */ + { + static char shell_str[] = "SHELL"; + const int shlen = sizeof (shell_str) - 1; + struct variable *mshp = lookup_variable ("MAKESHELL", 9); + struct variable *comp = lookup_variable ("COMSPEC", 7); + + /* Make $MAKESHELL override $SHELL even if -e is in effect. */ + if (mshp) + (void) define_variable (shell_str, shlen, + mshp->value, o_env_override, 0); + else if (comp) + { + /* $COMSPEC shouldn't override $SHELL, unless $SHELL is /bin/sh, + which is just the default setting on many Makefiles. */ + struct variable *shp = lookup_variable (shell_str, shlen); + + if (!shp || (!strcmp (shp->value, "/bin/sh") && shp->origin == o_file)) + (void) define_variable (shell_str, shlen, comp->value, o_env, 0); + } + } + #endif /* This won't override any definition, but it will provide one if there isn't one there. */ v = define_variable ("SHELL", 5, default_shell, o_default, 0); v->export = v_export; /* Always export SHELL. */ + /* On MSDOS we do use SHELL from environment, since + it isn't a standard environment variable on MSDOS, + so whoever sets it, does that on purpose. */ + #ifndef __MSDOS__ /* Don't let SHELL come from the environment. */ if (*v->value == '\0' || v->origin == o_env || v->origin == o_env_override) { *************** *** 373,378 **** --- 401,407 ---- v->origin = o_file; v->value = savestring (default_shell, strlen (default_shell)); } + #endif /* Make sure MAKEFILES gets exported if it is set. */ v = define_variable ("MAKEFILES", 9, "", o_default, 0); *************** *** 678,683 **** --- 707,725 ---- bcopy (p, &value[oldlen + 1], newlen + 1); } } + + #ifdef __MSDOS__ + /* Don't let "SHELL=/bin/sh" from the Makefile override $SHELL + from the environment. Most Unix Makefiles include such a line, + but $SHELL in the environment points to the real pathname. + Note that we don't use EXPANDED_NAME: if they use such trickery, + they might know what they are doing, so let them have what they want. */ + if (origin == o_file + && strncmp (name, "SHELL", 6) == 0 + && strncmp (value, "/bin/sh", 8) == 0) + v = lookup_variable (name, 5); + else + #endif v = define_variable (expanded_name, strlen (expanded_name), value, origin, flavor == recursive); *** makefile.d~1 Sat Aug 31 11:34:36 1996 --- makefile.djg Sat Sep 7 18:50:36 1996 *************** *** 118,124 **** TEXI2DVI = texi2dvi # Programs to make tags files. ! ETAGS = etags -w CTAGS = ctags -w objs = commands.o job.o dir.o file.o misc.o main.o read.o remake.o rule.o implicit.o default.o variable.o expand.o function.o vpath.o version.o ar.o arscan.o signame.o remote-$(REMOTE).o $(GLOB) $(GETOPT) $(ALLOCA) $(extras) --- 118,124 ---- TEXI2DVI = texi2dvi # Programs to make tags files. ! ETAGS = etags CTAGS = ctags -w objs = commands.o job.o dir.o file.o misc.o main.o read.o remake.o rule.o implicit.o default.o variable.o expand.o function.o vpath.o version.o ar.o arscan.o signame.o remote-$(REMOTE).o $(GLOB) $(GETOPT) $(ALLOCA) $(extras) *************** *** 158,164 **** $(MAKE) -C glob libglob.a FORCE: ! tagsrcs = $(srcs) $(srcdir)/remote-*.c TAGS: $(tagsrcs) $(ETAGS) $(tagsrcs) tags: $(tagsrcs) --- 158,164 ---- $(MAKE) -C glob libglob.a FORCE: ! tagsrcs = $(srcs:.h.in=.h) $(srcdir)/remote-*.c TAGS: $(tagsrcs) $(ETAGS) $(tagsrcs) tags: $(tagsrcs) *** glob/configur.b~1 Sat Aug 24 17:18:00 1996 --- glob/configur.bat Sat Aug 24 17:18:14 1996 *************** *** 1,5 **** @echo off ! echo Configuring glob for GO32 rem This batch file assumes a unix-type "sed" program echo # Makefile generated by "configure.bat"> Makefile --- 1,5 ---- @echo off ! echo Configuring glob for DJGPP rem This batch file assumes a unix-type "sed" program echo # Makefile generated by "configure.bat"> Makefile