From dedc2614b863e8e540e79fa9dd1c224ce1cacd15 Mon Sep 17 00:00:00 2001 From: Jefferson Carpenter Date: Wed, 16 Mar 2242 12:56:21 +10480234 Subject: [PATCH] Rewrite wineserver main.c in Haskell. --- Makefile.in | 9 +++ configure | 34 ++++++++-- configure.ac | 10 +++ server/Main.hs | 102 +++++++++++++++++++++++++++++ server/Makefile.in | 4 +- server/main.c | 151 ------------------------------------------- server/object.c | 4 ++ tools/make_makefiles | 6 ++ tools/makedep.c | 81 +++++++++++++++++++++-- 9 files changed, 239 insertions(+), 162 deletions(-) create mode 100644 server/Main.hs delete mode 100644 server/main.c diff --git a/Makefile.in b/Makefile.in index b52495f741f..5c219a26b81 100644 --- a/Makefile.in +++ b/Makefile.in @@ -46,6 +46,7 @@ MSVCRTFLAGS = @MSVCRTFLAGS@ TARGETFLAGS = @TARGETFLAGS@ LDDLLFLAGS = @LDDLLFLAGS@ LDEXECFLAGS = @LDEXECFLAGS@ +GHC = ghc LIBS = @LIBS@ BISON = @BISON@ FLEX = @FLEX@ @@ -101,6 +102,14 @@ include/config.h: include/stamp-h include/stamp-h: $(srcdir)/include/config.h.in config.status @./config.status include/config.h include/stamp-h +include/Config.hs: include/config.h + @awk 'BEGIN { print "module Config where\n" }; $$0~/^#define/ && NF > 2 { printf "%s = ", tolower($$2); $$1=$$2=""; sub(/^[ \t]+/, ""); print $$0 }' include/config.h >include/Config.hs + +include/Config.hi: include/Config.hs + @$(GHC) include/Config.hs + +server/Main.o: include/Config.hi + # Rules for cleaning distclean:: clean diff --git a/configure b/configure index a19bb0b9581..3560ccfbe61 100755 --- a/configure +++ b/configure @@ -5850,6 +5850,30 @@ $as_echo "$wine_cv_builtin_ms_va_list" >&6; } ;; esac +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ghc is installed" >&5 +$as_echo_n "checking whether ghc is installed... " >&6; } +if ${wine_cv_have_ghc+:} false; then : + $as_echo_n "(cached) " >&6 +else + wine_cv_have_ghc=no + ghc --help && wine_cv_have_ghc=yes +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $wine_cv_have_ghc" >&5 +$as_echo "$wine_cv_have_ghc" >&6; } +test $wine_cv_have_ghc != no || as_fn_error $? "Install ghc." "$LINENO" 5 + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether stack is installed" >&5 +$as_echo_n "checking whether stack is installed... " >&6; } +if ${wine_cv_have_stack+:} false; then : + $as_echo_n "(cached) " >&6 +else + wine_cv_have_stack=no + stack && wine_cv_have_stack=yes +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $wine_cv_have_stack" >&5 +$as_echo "$wine_cv_have_stack" >&6; } +test $wine_cv_have_stack != no || as_fn_error $? "Install stack." "$LINENO" 5 + enable_win16=${enable_win16:-no} enable_win64=${enable_win64:-no} enable_wow64cpu=${enable_wow64cpu:-no} @@ -6980,7 +7004,7 @@ else We can't simply define LARGE_OFF_T to be 9223372036854775807, since some C++ compilers masquerading as C compilers incorrectly reject 9223372036854775807. */ -#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31)) +#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62)) int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 && LARGE_OFF_T % 2147483647 == 1) ? 1 : -1]; @@ -7026,7 +7050,7 @@ else We can't simply define LARGE_OFF_T to be 9223372036854775807, since some C++ compilers masquerading as C compilers incorrectly reject 9223372036854775807. */ -#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31)) +#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62)) int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 && LARGE_OFF_T % 2147483647 == 1) ? 1 : -1]; @@ -7050,7 +7074,7 @@ rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext We can't simply define LARGE_OFF_T to be 9223372036854775807, since some C++ compilers masquerading as C compilers incorrectly reject 9223372036854775807. */ -#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31)) +#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62)) int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 && LARGE_OFF_T % 2147483647 == 1) ? 1 : -1]; @@ -7095,7 +7119,7 @@ else We can't simply define LARGE_OFF_T to be 9223372036854775807, since some C++ compilers masquerading as C compilers incorrectly reject 9223372036854775807. */ -#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31)) +#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62)) int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 && LARGE_OFF_T % 2147483647 == 1) ? 1 : -1]; @@ -7119,7 +7143,7 @@ rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext We can't simply define LARGE_OFF_T to be 9223372036854775807, since some C++ compilers masquerading as C compilers incorrectly reject 9223372036854775807. */ -#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31)) +#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62)) int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 && LARGE_OFF_T % 2147483647 == 1) ? 1 : -1]; diff --git a/configure.ac b/configure.ac index eb08e8b0f17..68f125d4d3a 100644 --- a/configure.ac +++ b/configure.ac @@ -222,6 +222,16 @@ case $host in ;; esac +AC_CACHE_CHECK([whether ghc is installed], [wine_cv_have_ghc], + [wine_cv_have_ghc=no + ghc --help && wine_cv_have_ghc=yes]) +test $wine_cv_have_ghc != no || AC_MSG_ERROR([Install ghc.]) + +AC_CACHE_CHECK([whether stack is installed], [wine_cv_have_stack], + [wine_cv_have_stack=no + stack && wine_cv_have_stack=yes]) +test $wine_cv_have_stack != no || AC_MSG_ERROR([Install stack.]) + dnl enable_win16 defaults to yes on x86, to no on other CPUs enable_win16=${enable_win16:-no} enable_win64=${enable_win64:-no} diff --git a/server/Main.hs b/server/Main.hs new file mode 100644 index 00000000000..b9f16171380 --- /dev/null +++ b/server/Main.hs @@ -0,0 +1,102 @@ +import Config + +import Data.Foldable (forM_, mapM_) +import Data.Int +import Data.Maybe (fromMaybe) +import Foreign.C.Types +import Foreign.Ptr (Ptr) +import Foreign.Storable (peek, poke) +import System.Console.GetOpt +import System.Environment (getArgs, getProgName) +import System.Exit +import System.IO (BufferMode(..), hSetBuffering, stderr) +import System.Posix.Signals +import Text.Read (readMaybe) + +foreign import ccall "&debug_level" debug_level :: Ptr CInt +foreign import ccall "&foreground" foreground :: Ptr CInt +foreign import ccall "&master_socket_timeout" master_socket_timeout :: Ptr Int64 + +foreign import ccall "kill_lock_owner" kill_lock_owner :: CInt -> IO () + +foreign import ccall "sock_init" sock_init :: IO () +foreign import ccall "open_master_socket" open_master_socket :: IO () + +foreign import ccall "set_current_time" set_current_time :: IO () +foreign import ccall "init_signals" init_signals :: IO () +foreign import ccall "load_intl_file" load_intl_file :: IO (Ptr ()) +foreign import ccall "init_directories" init_directories :: Ptr () -> IO () +foreign import ccall "main_loop" main_loop :: IO () + +data Option + = Debug (Maybe Int) + | Foreground + | Help + | Kill (Maybe Int) + | Persistent (Maybe Int) + | Version + | Wait + +parse_int_option :: (Maybe Int -> Option) -> Maybe String -> Option +parse_int_option = (. (readMaybe =<<)) + +options :: [OptDescr Option] +options = + [ Option ['d'] ["debug"] (OptArg (parse_int_option Debug) "n") "set debug level to n or +1 if n not specified" + , Option ['f'] ["foreground"] (NoArg Foreground) "remain in the foreground for debugging" + , Option ['h'] ["help"] (NoArg Help) "display this help message" + , Option ['k'] ["kill"] (OptArg (parse_int_option Kill) "n") "kill the current wineserver, optionally with signal n" + , Option ['p'] ["persistent"] (OptArg (parse_int_option Persistent) "n") "make server persistent, optionally for n seconds" + , Option ['v'] ["version"] (NoArg Version) "display version information and exit" + , Option ['w'] ["wait"] (NoArg Wait) "wait until the current wineserver terminates" + ] + +usage :: IO String +usage = do + prog_name <- getProgName + return $ usageInfo ("Usage: " ++ prog_name ++ " [options]\n\nOptions:") options + +handle_option :: Option -> IO () +handle_option opt = do + case opt of + Debug Nothing -> do + d <- peek debug_level + poke debug_level (d + 1) + Debug (Just n) -> poke debug_level (fromIntegral n) + Foreground -> poke foreground 1 + Help -> do + usage_string <- usage + putStrLn usage_string + exitSuccess + Kill n -> kill_lock_owner . fromIntegral . fromMaybe (-1) $ n + Persistent n -> let + timeout = case n of + Nothing -> maxBound + Just n -> fromIntegral n + in + poke master_socket_timeout timeout + +main :: IO () +main = do + hSetBuffering stderr LineBuffering + + (options, _, _) <- fmap (getOpt Permute options) getArgs + mapM_ handle_option options + + installHandler sigPIPE Ignore Nothing + mapM_ (\sig -> installHandler sig (Catch exitFailure) Nothing) + [ sigHUP + , sigINT + , sigQUIT + , sigTERM + , sigABRT + ] + + sock_init + open_master_socket + + set_current_time + init_signals + file <- load_intl_file + init_directories file + main_loop diff --git a/server/Makefile.in b/server/Makefile.in index 4264e3db108..f4181f3eb29 100644 --- a/server/Makefile.in +++ b/server/Makefile.in @@ -18,7 +18,6 @@ C_SRCS = \ hook.c \ mach.c \ mailslot.c \ - main.c \ mapping.c \ mutex.c \ named_pipe.c \ @@ -52,3 +51,6 @@ MANPAGES = \ EXTRALIBS = $(LDEXECFLAGS) $(POLL_LIBS) $(RT_LIBS) $(INOTIFY_LIBS) unicode_EXTRADEFS = -DNLSDIR="\"${nlsdir}\"" -DBIN_TO_NLSDIR=\"`$(MAKEDEP) -R ${bindir} ${nlsdir}`\" + +HS_SRCS = \ + Main.hs diff --git a/server/main.c b/server/main.c deleted file mode 100644 index d7aed0da199..00000000000 --- a/server/main.c +++ /dev/null @@ -1,151 +0,0 @@ -/* - * Server main function - * - * Copyright (C) 1998 Alexandre Julliard - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA - */ - -#include "config.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#ifdef HAVE_GETOPT_H -# include -#endif - -#include "object.h" -#include "file.h" -#include "thread.h" -#include "request.h" -#include "unicode.h" - -/* command-line options */ -int debug_level = 0; -int foreground = 0; -timeout_t master_socket_timeout = 3 * -TICKS_PER_SEC; /* master socket timeout, default is 3 seconds */ -const char *server_argv0; - -/* parse-line args */ - -static void usage( FILE *fh ) -{ - fprintf(fh, "Usage: %s [options]\n\n", server_argv0); - fprintf(fh, "Options:\n"); - fprintf(fh, " -d[n], --debug[=n] set debug level to n or +1 if n not specified\n"); - fprintf(fh, " -f, --foreground remain in the foreground for debugging\n"); - fprintf(fh, " -h, --help display this help message\n"); - fprintf(fh, " -k[n], --kill[=n] kill the current wineserver, optionally with signal n\n"); - fprintf(fh, " -p[n], --persistent[=n] make server persistent, optionally for n seconds\n"); - fprintf(fh, " -v, --version display version information and exit\n"); - fprintf(fh, " -w, --wait wait until the current wineserver terminates\n"); - fprintf(fh, "\n"); -} - -static void parse_args( int argc, char *argv[] ) -{ - int ret, optc; - - static struct option long_options[] = - { - {"debug", 2, NULL, 'd'}, - {"foreground", 0, NULL, 'f'}, - {"help", 0, NULL, 'h'}, - {"kill", 2, NULL, 'k'}, - {"persistent", 2, NULL, 'p'}, - {"version", 0, NULL, 'v'}, - {"wait", 0, NULL, 'w'}, - { NULL, 0, NULL, 0} - }; - - server_argv0 = argv[0]; - - while ((optc = getopt_long( argc, argv, "d::fhk::p::vw", long_options, NULL )) != -1) - { - switch(optc) - { - case 'd': - if (optarg && isdigit(*optarg)) - debug_level = atoi( optarg ); - else - debug_level++; - break; - case 'f': - foreground = 1; - break; - case 'h': - usage(stdout); - exit(0); - break; - case 'k': - if (optarg && isdigit(*optarg)) - ret = kill_lock_owner( atoi( optarg ) ); - else - ret = kill_lock_owner(-1); - exit( !ret ); - case 'p': - if (optarg && isdigit(*optarg)) - master_socket_timeout = (timeout_t)atoi( optarg ) * -TICKS_PER_SEC; - else - master_socket_timeout = TIMEOUT_INFINITE; - break; - case 'v': - fprintf( stderr, "%s\n", PACKAGE_STRING ); - exit(0); - case 'w': - wait_for_lock(); - exit(0); - default: - usage(stderr); - exit(1); - } - } -} - -static void sigterm_handler( int signum ) -{ - exit(1); /* make sure atexit functions get called */ -} - -int main( int argc, char *argv[] ) -{ - setvbuf( stderr, NULL, _IOLBF, 0 ); - parse_args( argc, argv ); - - /* setup temporary handlers before the real signal initialization is done */ - signal( SIGPIPE, SIG_IGN ); - signal( SIGHUP, sigterm_handler ); - signal( SIGINT, sigterm_handler ); - signal( SIGQUIT, sigterm_handler ); - signal( SIGTERM, sigterm_handler ); - signal( SIGABRT, sigterm_handler ); - - sock_init(); - open_master_socket(); - - if (debug_level) fprintf( stderr, "wineserver: starting (pid=%ld)\n", (long) getpid() ); - set_current_time(); - init_signals(); - init_directories( load_intl_file() ); - init_registry(); - main_loop(); - return 0; -} diff --git a/server/object.c b/server/object.c index b2779fd61fe..d020b44463c 100644 --- a/server/object.c +++ b/server/object.c @@ -42,6 +42,10 @@ #include "unicode.h" #include "security.h" +int debug_level = 0; +int foreground = 0; +timeout_t master_socket_timeout = 3 * -TICKS_PER_SEC; /* master socket timeout, default is 3 seconds */ +const char *server_argv0; struct namespace { diff --git a/tools/make_makefiles b/tools/make_makefiles index 3abba2da840..34b4e58ce56 100755 --- a/tools/make_makefiles +++ b/tools/make_makefiles @@ -59,6 +59,7 @@ my @source_vars = ( "C_SRCS", "FONT_SRCS", "HEADER_SRCS", + "HS_SRCS", "IDL_SRCS", "IN_SRCS", "LEX_SRCS", @@ -360,6 +361,10 @@ sub assign_sources_to_makefiles(@) { next if $dir ne "include"; } + elsif ($name =~ /\.hs$/) + { + push @{${$make}{"=HS_SRCS"}}, $name; + } elsif ($name =~ /\.rc$/) { push @{${$make}{"=RC_SRCS"}}, $name; @@ -407,6 +412,7 @@ sub assign_sources_to_makefiles(@) my $parent = get_parent_makefile( $file ); next unless $parent; preserve_shared_source_files( $makefiles{$file}, $makefiles{$parent}, "C_SRCS" ); + preserve_shared_source_files( $makefiles{$file}, $makefiles{$parent}, "HS_SRCS" ); preserve_shared_source_files( $makefiles{$file}, $makefiles{$parent}, "RC_SRCS" ); preserve_shared_source_files( $makefiles{$file}, $makefiles{$parent}, "IDL_SRCS" ); preserve_shared_source_files( $makefiles{$file}, $makefiles{$parent}, "LEX_SRCS" ); diff --git a/tools/makedep.c b/tools/makedep.c index 8245a324279..94d68d3e181 100644 --- a/tools/makedep.c +++ b/tools/makedep.c @@ -109,6 +109,7 @@ struct incl_file #define FLAG_C_IMPLIB 0x020000 /* file is part of an import library */ #define FLAG_C_UNIX 0x040000 /* file is part of a Unix library */ #define FLAG_SFD_FONTS 0x080000 /* sfd file generated bitmap fonts */ +#define FLAG_HS 0x100000 /* is haskell source file */ static const struct { @@ -206,6 +207,7 @@ struct makefile int is_cross; int is_win16; int is_exe; + int is_hs; /* values generated at output time */ struct strarray in_files; @@ -1016,6 +1018,18 @@ static void parse_include_directive( struct file *source, char *str ) } +/******************************************************************* + * parse_import_directive + */ +static void parse_import_directive( struct file *source, char *str ) +{ + while (*str && isspace(*str)) str++; + if (!strncmp("Config", str, 6)) { + add_dependency( source, "include/Config.hi", INCL_NORMAL ); + } +} + + /******************************************************************* * parse_pragma_directive */ @@ -1095,6 +1109,18 @@ static void parse_cpp_directive( struct file *source, char *str ) } +/******************************************************************* + * parse_hs_directive + */ +static void parse_hs_directive( struct file *source, char *str ) +{ + while (*str && isspace(*str)) str++; + + if (!strncmp( str, "import", 6 )) + parse_import_directive( source, str + 6 ); +} + + /******************************************************************* * parse_idl_file */ @@ -1190,6 +1216,23 @@ static void parse_c_file( struct file *source, FILE *file ) } +/******************************************************************* + * parse_hs_file + */ +static void parse_hs_file( struct file *source, FILE *file ) +{ + char *buffer; + + input_line = 0; + while ((buffer = get_line( file ))) + { + parse_hs_directive( source, buffer ); + } + + source->flags |= FLAG_HS; +} + + /******************************************************************* * parse_rc_file */ @@ -1311,6 +1354,7 @@ static const struct { ".rh", parse_c_file }, { ".x", parse_c_file }, { ".y", parse_c_file }, + { ".hs", parse_hs_file }, { ".idl", parse_idl_file }, { ".rc", parse_rc_file }, { ".in", parse_in_file }, @@ -1484,6 +1528,13 @@ static struct file *open_include_file( const struct makefile *make, struct incl_ return file; } + /* ignore Config.hi */ + + if (!strcmp( pFile->name, "include/Config.hi" )) + { + return NULL; + } + /* check for extra targets */ if (strarray_exists( &make->extra_targets, pFile->name )) { @@ -1644,6 +1695,10 @@ static void parse_file( struct makefile *make, struct incl_file *source, int src if (file->flags & FLAG_C_UNIX) source->use_msvcrt = 0; else if (file->flags & FLAG_C_IMPLIB) source->use_msvcrt = 1; + if (file->flags & FLAG_HS) { + make->is_hs = 1; + } + if (source->sourcename) { if (strendswith( source->sourcename, ".idl" )) @@ -3146,16 +3201,26 @@ static void output_source_default( struct makefile *make, struct incl_file *sour else strarray_add( &make->clean_files, strmake( "%s.o", obj )); output( "%s.o: %s\n", obj_dir_path( make, obj ), source->filename ); - output( "\t%s$(CC) -c -o $@ %s", cmd_prefix( "CC" ), source->filename ); + if (source->file->flags & FLAG_HS) { + output( "\t%s$(GHC) -c -o $@ %s", cmd_prefix( "GHC" ), source->filename ); + } + else { + output( "\t%s$(CC) -c -o $@ %s", cmd_prefix( "CC" ), source->filename ); + } output_filenames( defines ); if (make->module || make->staticlib || make->sharedlib || make->testdll) { output_filenames( dll_flags ); if (source->use_msvcrt) output_filenames( msvcrt_flags ); } - output_filenames( extra_cflags ); - output_filenames( cpp_flags ); - output_filename( "$(CFLAGS)" ); + if (source->file->flags & FLAG_HS) { + output_filename( "-fPIC -i./include $(GHCFLAGS)" ); + } + else { + output_filenames( extra_cflags ); + output_filenames( cpp_flags ); + output_filename( "$(CFLAGS)" ); + } output( "\n" ); } if (need_cross) @@ -3659,7 +3724,12 @@ static void output_programs( struct makefile *make ) output_filenames_obj_dir( make, objs ); output_filenames( deps ); output( "\n" ); - output( "\t%s$(CC) -o $@", cmd_prefix( "CC" )); + if (make->is_hs) { + output( "\t%s$(GHC) -package unix -o $@", cmd_prefix( "GHC" )); + } + else { + output( "\t%s$(CC) -o $@", cmd_prefix( "CC" )); + } output_filenames_obj_dir( make, objs ); output_filenames( all_libs ); output_filename( "$(LDFLAGS)" ); @@ -4196,6 +4266,7 @@ static void load_sources( struct makefile *make ) { "SOURCES", "C_SRCS", + "HS_SRCS", "OBJC_SRCS", "RC_SRCS", "MC_SRCS", -- 2.26.2