Author: arty
Date: Fri Jan  5 08:56:26 2007
New Revision: 25303
URL: 
http://svn.reactos.org/svn/reactos?rev=25303&view=rev
Log:
Compiler driver wrapper for building pe-powerpcle executables.  Expects access
to a powerpc gcc and ld, as well as alink.  The scripts in here are transformed
by sed ala GNU configure.
fork_win32 and fork_unix provide a uniform way of calling an external program
and reading stderr.
dlltool.cpp is a minimalist what-if about replacing binutils' dlltool.  It's
not used by might be instructive.
Added:
    branches/powerpc/reactos/tools/ppc-build/compdvr/
    branches/powerpc/reactos/tools/ppc-build/compdvr/compdvr-dlltool.in   (with props)
    branches/powerpc/reactos/tools/ppc-build/compdvr/compdvr-gcc.in
    branches/powerpc/reactos/tools/ppc-build/compdvr/compdvr-ld.in
    branches/powerpc/reactos/tools/ppc-build/compdvr/compdvr-windres.in
    branches/powerpc/reactos/tools/ppc-build/compdvr/compdvr.cpp
    branches/powerpc/reactos/tools/ppc-build/compdvr/dlltool.cpp
    branches/powerpc/reactos/tools/ppc-build/compdvr/fork_execvp.h   (with props)
    branches/powerpc/reactos/tools/ppc-build/compdvr/fork_unix.cpp   (with props)
    branches/powerpc/reactos/tools/ppc-build/compdvr/fork_win32.cpp   (with props)
Added: branches/powerpc/reactos/tools/ppc-build/compdvr/compdvr-dlltool.in
URL:
http://svn.reactos.org/svn/reactos/branches/powerpc/reactos/tools/ppc-build…
==============================================================================
--- branches/powerpc/reactos/tools/ppc-build/compdvr/compdvr-dlltool.in (added)
+++ branches/powerpc/reactos/tools/ppc-build/compdvr/compdvr-dlltool.in Fri Jan  5
08:56:26 2007
@@ -1,0 +1,7 @@
+#!/bin/sh
+
+DIR=@PREFIX@
+BPREFIX=@BPREFIX@
+TARGET=@TARGET@
+
+${BPREFIX}dlltool -S $DIR/bin/${TARGET}as -L $DIR/bin/${TARGET}ld $*
Propchange: branches/powerpc/reactos/tools/ppc-build/compdvr/compdvr-dlltool.in
------------------------------------------------------------------------------
    svn:executable = *
Added: branches/powerpc/reactos/tools/ppc-build/compdvr/compdvr-gcc.in
URL:
http://svn.reactos.org/svn/reactos/branches/powerpc/reactos/tools/ppc-build…
==============================================================================
--- branches/powerpc/reactos/tools/ppc-build/compdvr/compdvr-gcc.in (added)
+++ branches/powerpc/reactos/tools/ppc-build/compdvr/compdvr-gcc.in Fri Jan  5 08:56:26
2007
@@ -1,0 +1,60 @@
+#!/bin/sh
+
+DIR=@PREFIX@
+CPREFIX=@CPREFIX@
+TARGET=@TARGET@
+
+if [ "x$*" = "x-v" ] ; then
+       exec ${CPREFIX}gcc -v
+fi
+
+includes="-isystem $DIR/lib/mingw-crt-headers -isystem
$DIR/lib/gcc-core-headers"
+
+argstr=""
+for arg in $* ; do
+       if [ x"$arg" = x-mingw ] ; then
+               argstr="$argstr -isystem $DIR/lib/windows-headers"
+       else
+               argstr="$argstr $arg"
+       fi
+done
+
+TEMP=`mktemp -d`
+export TEMP
+if [ ! -d $TEMP ] ; then
+    echo "Could not make temp dir $TEMP"
+    exit 1
+fi
+TMP=$TEMP
+
+`dirname $0`/${TARGET}driver-gcc \
+       -mlittle \
+       -nostdinc \
+       -D__cdecl__= \
+       -D__stdcall__= \
+       -D__fastcall__= \
+       -D__declspec\(x\)= \
+       -D__cdecl= \
+       -D__stdcall= \
+       -D__fastcall= \
+       -Dcdecl= \
+       -Dstdcall= \
+       -Dfastcall= \
+       -Ddllimport= \
+       -Ddllexport= \
+       -Du_short=unsigned\ short \
+       -Du_long=unsigned\ long \
+       -Du_int=unsigned\ int \
+       -Du_char=unsigned\ char \
+       -ldscript ${DIR}/lib/ldscript \
+       -gcc-name ${CPREFIX}gcc \
+       -link-stage-name ${DIR}/bin/${TARGET}ld \
+       -extra-link-stage $DIR/bin/alink.exe \
+       -mingw-lib-dir $DIR/lib \
+       $includes \
+       $argstr </dev/null
+
+RES=$?
+
+rm -rf $TEMP
+exit $RES
Added: branches/powerpc/reactos/tools/ppc-build/compdvr/compdvr-ld.in
URL:
http://svn.reactos.org/svn/reactos/branches/powerpc/reactos/tools/ppc-build…
==============================================================================
--- branches/powerpc/reactos/tools/ppc-build/compdvr/compdvr-ld.in (added)
+++ branches/powerpc/reactos/tools/ppc-build/compdvr/compdvr-ld.in Fri Jan  5 08:56:26
2007
@@ -1,0 +1,30 @@
+#!/bin/sh
+
+DIR=@PREFIX@
+BPREFIX=@BPREFIX@
+TARGET=@TARGET@
+
+if [ "x$*" = x-v ] ; then
+       exec ${BPREFIX}ld -v
+fi
+
+TEMP=`mktemp -d`
+export TEMP
+if [ ! -d $TEMP ] ; then
+    echo "Could not make temp dir $TEMP"
+    exit 1
+fi
+TMP=$TEMP
+
+`dirname $0`/${TARGET}driver-ld \
+    -EL \
+    -ldscript ${DIR}/lib/ldscript \
+    -mingw-lib-dir ${DIR}/lib \
+    -link-stage-name ${BPREFIX}ld \
+    -extra-link-stage $DIR/bin/alink.exe \
+    $*
+
+RES=$?
+
+rm -rf $TEMP
+exit $RES
Added: branches/powerpc/reactos/tools/ppc-build/compdvr/compdvr-windres.in
URL:
http://svn.reactos.org/svn/reactos/branches/powerpc/reactos/tools/ppc-build…
==============================================================================
--- branches/powerpc/reactos/tools/ppc-build/compdvr/compdvr-windres.in (added)
+++ branches/powerpc/reactos/tools/ppc-build/compdvr/compdvr-windres.in Fri Jan  5
08:56:26 2007
@@ -1,0 +1,7 @@
+#!/bin/sh
+
+DIR=@PREFIX@
+BPREFIX=@BPREFIX@
+TARGET=@TARGET@
+
+exec ${BPREFIX}windres -F elf32-powerpcle $*
Added: branches/powerpc/reactos/tools/ppc-build/compdvr/compdvr.cpp
URL:
http://svn.reactos.org/svn/reactos/branches/powerpc/reactos/tools/ppc-build…
==============================================================================
--- branches/powerpc/reactos/tools/ppc-build/compdvr/compdvr.cpp (added)
+++ branches/powerpc/reactos/tools/ppc-build/compdvr/compdvr.cpp Fri Jan  5 08:56:26 2007
@@ -1,0 +1,363 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <list>
+#include <string>
+#include <vector>
+#include <sstream>
+#include <algorithm>
+#include "fork_execvp.h"
+
+/* tool for transforming gcc -### output and using it to drive the compiler
+ * elements ourselves.  Most importantly, we need to know what file gcc asks
+ * the linker to input and output, and add an intermediate stage with alink.
+ */
+
+typedef enum { empty, found_q, found_bs } break_t;
+
+template <class T>
+T break_arguments( const std::string &line ) {
+    break_t state = empty;
+    T args;
+    std::string arg;
+
+    for( size_t i = 0; i < line.size(); i++ ) {
+       switch( state ) {
+       case empty:
+           if( line[i] == '\"' ) {
+               state = found_q;
+           }
+           break;
+
+       case found_q:
+           if( line[i] == '\\' ) state = found_bs;
+           else if( line[i] == '\"' ) {
+               state = empty;
+               args.push_back(arg);
+               arg = "";
+           } else arg += line[i];
+           break;
+
+       case found_bs:
+           state = found_q;
+           arg += line[i];
+           break;
+       }
+    }
+
+    return args;
+}
+
+template <class T>
+std::vector<char *> get_arg_ptrs
+( const T &arg_strings ) {
+    std::vector<char *> arg_out;
+    for( size_t i = 0; i < arg_strings.size(); i++ )
+       arg_out.push_back( (char *)arg_strings[i].c_str() );
+    arg_out.push_back(0);
+    return arg_out;
+}
+
+int execute_command( bool verbose, const std::vector<std::string> &args ) {
+    std::string error;
+    std::vector<char *> args_ptrs;
+    const char *tag = "executable";
+
+    if( verbose ) {
+       fprintf( stderr, "<command>\n" );
+       for( size_t i = 0; i < args.size(); i++ ) {
+           fprintf( stderr, "<%s>%s</%s>\n", tag, args[i].c_str(),
tag );
+           tag = "argument";
+       }
+    }
+
+    Process p = fork_execvp( args );
+
+    while( p && p->ProcessStarted() && !p->EndOfStream() )
+       fprintf( stderr, "%s", p->ReadStdError().c_str() );
+
+    if( verbose ) {
+       fprintf( stderr, "<status>%d</status>\n", p->GetStatus()
);
+       fprintf( stderr, "</command>\n" );
+    }
+
+    return p ? p->GetStatus() : -1;
+}
+
+std::string make_tmp_name() {
+    int fd;
+    std::string name;
+
+    while( true ) {
+       name = tmpnam(NULL);
+       name += ".obj";
+       if( (fd = creat( name.c_str(), 0644 )) != -1 ) {
+           close(fd);
+           return name;
+       }
+    }
+}
+
+void recognize_arg( std::vector<std::string> &args,
+                   std::string &result,
+                   size_t &i,
+                   const std::string &argname,
+                   const std::string &short_argname = "" ) {
+    if( (short_argname.size() && (args[i] == short_argname)) ||
+       (args[i] == argname) ) {
+       result = args[i+1];
+       args.erase(args.begin()+i);
+       args.erase(args.begin()+i--);
+    } else if( args[i].substr(0,argname.size()+1) == argname + "=" ) {
+       result = args[i].substr(argname.size()+1);
+       args.erase(args.begin()+i--);
+    }
+}
+
+int run_ld( bool verbose, bool nostdlib, bool nostartfiles, bool is_dll,
+           bool make_map,
+           const std::string &lib_dir,
+           const std::string &extra_linker_stage,
+           const std::string &ldscript,
+           const std::vector<std::string> &arg_vect ) {
+    bool use_libgcc = false;
+    std::vector<std::string> args = arg_vect;
+    std::string temp_name = make_tmp_name(), real_output,
+       entry_point, image_base, subsystem = "windows",
+       make_dll, file_align, section_align, base_file;
+    std::vector<std::string>::iterator i =
+       std::find(args.begin(),args.end(),"-lgcc");
+
+    if( i != args.end() ) {
+       args.erase( i );
+       use_libgcc = true;
+    }
+
+    if( !nostartfiles ) {
+       if( make_dll.size() )
+           args.push_back(lib_dir + "/dllcrt2.o");
+       else
+           args.push_back(lib_dir + "/crt2.o");
+    }
+
+    if( !nostdlib ) {
+       args.push_back(std::string("-L") + lib_dir);
+       args.push_back("-lkernel32");
+       args.push_back("-lmsvcrt");
+       args.push_back("-lcrtdll");
+       args.push_back("-lmingw32");
+    }
+    if( use_libgcc )
+       args.push_back(lib_dir + "/libgcc.a");
+
+    if( verbose )
+      args.insert(args.begin()+1,"-v");
+
+    args.insert(args.begin()+1,"-T");
+    args.insert(args.begin()+2,ldscript);
+    args.insert(args.begin()+1,"-r");
+    args.insert(args.begin()+1,"--start-group");
+    args.push_back("--end-group");
+
+    for( size_t i = 0; i < args.size(); i++ ) {
+       if( args[i] == "-o" && i < args.size()-1 ) {
+           real_output = args[++i];
+           args[i] = temp_name;
+       } else if( args[i].substr(0,4) == "-mdll" ) {
+           args.erase(args.begin()+i--);
+           make_dll = "-dll";
+       }
+
+       recognize_arg( args, entry_point, i, "--entry", "-e" );
+       recognize_arg( args, image_base, i, "--image-base" );
+       recognize_arg( args, subsystem, i, "--subsystem" );
+       recognize_arg( args, file_align, i, "--file-alignment" );
+       recognize_arg( args, section_align, i, "--section-alignment" );
+       recognize_arg( args, base_file, i, "--base-file" );
+    }
+
+    if( execute_command( verbose, args ) )
+       return 1;
+
+    if( base_file.size() ) {
+       FILE *f = fopen(base_file.c_str(), "wb");
+       if( !f ) {
+           fprintf(stderr, "<error>\n");
+           perror(base_file.c_str());
+           fprintf(stderr, "</error>\n");
+           return 1;
+       }
+       fclose(f);
+    }
+
+    args.clear();
+    args.push_back( extra_linker_stage );
+    if(make_map)
+       args.push_back("-m+");
+    args.push_back( "-oPE" );
+    args.push_back( "-o" );
+    args.push_back( real_output );
+    args.push_back( "-subsys" );
+    args.push_back( subsystem );
+
+    if( entry_point.size() ) {
+       size_t at = 0;
+       args.push_back("-entry");
+       // Entry points will be specified with leading '_', probably
+       if( entry_point[0] == '_' )
+           entry_point = entry_point.substr(1);
+       at = entry_point.find('@');
+       if( at != std::string::npos )
+           entry_point = entry_point.substr(0,at);
+       args.push_back(entry_point);
+    }
+
+    if( image_base.size() ) {
+       args.push_back("-base");
+       args.push_back(image_base);
+    }
+
+    if( file_align.size() ) {
+       args.push_back("-filealign");
+       args.push_back(file_align);
+    }
+
+    if( section_align.size() ) {
+       args.push_back("-objectalign");
+       args.push_back(section_align);
+    }
+
+    if( make_dll.size() ) {
+       args.push_back(make_dll);
+    }
+
+    if( real_output.size() ) {
+        args.push_back( temp_name );
+        int res = execute_command( verbose, args );
+       unlink( temp_name.c_str() );
+       return res;
+    } else return 0;
+}
+
+int main( int argc, char **argv ) {
+    bool verbose = false, ld_mode = false, nostdlib = false,
+       nostartfiles = false, is_dll = false, make_map = false;
+    int err_fd[2], read_len, child_pid_gcc, child_pid_command, status = 0;
+    std::string gcc_name, gcc_hash_output, gcc_line, linker_name = "ld",
+           mingw_lib_dir, ldscript;
+    std::string extra_linker_stage;
+    std::vector<std::string> gcc_args_str,
+       subcmd_args;
+    std::vector<char *> arguments_for_gcc;
+    char buf[1024];
+
+    for( int i = 1; i < argc; i++ ) {
+       if( std::string("-gcc-name") == argv[i] && i < argc-1 ) {
+           gcc_name = argv[++i];
+       } else if( std::string("-ldscript") == argv[i] && i < argc-1
) {
+           ldscript = argv[++i];
+       } else if( std::string("-link-stage-name") == argv[i] && i <
argc-1 ) {
+           linker_name = argv[++i];
+       } else if( std::string("-extra-link-stage") == argv[i] && i <
argc-1 ) {
+           extra_linker_stage = argv[++i];
+       } else if( std::string("-mingw-lib-dir") == argv[i] && i <
argc-1 ) {
+           mingw_lib_dir = argv[++i];
+       } else if( std::string("-v") == argv[i] ) {
+           verbose = true;
+       } else if( std::string("-pipe") == argv[i] ) {
+           /* ignore */
+       } else if( std::string("-T") == argv[i] ) {
+           /* ignore */
+           i++;
+       } else if( std::string("-nostdlib") == argv[i] ) {
+           nostdlib = true;
+       } else if( std::string("-nostartfiles") == argv[i] ) {
+           nostartfiles = true;
+       } else if( std::string("-shared") == argv[i] ) {
+           is_dll = true;
+       } else if( std::string("-map") == argv[i] ) {
+           make_map = true;
+       } else {
+           gcc_args_str.push_back(argv[i]);
+       }
+    }
+
+    /* We never use the system start files or standard libs */
+    gcc_args_str.insert(gcc_args_str.begin()+1,"-nostdlib");
+    gcc_args_str.insert(gcc_args_str.begin()+1,"-nostartfiles");
+
+    if( std::string(argv[0]).find("ld") != std::string::npos ) {
+       gcc_args_str.insert
+           ( gcc_args_str.begin(), linker_name );
+       return run_ld
+           ( verbose, nostdlib, nostartfiles, is_dll, make_map, mingw_lib_dir,
+             extra_linker_stage, ldscript, gcc_args_str );
+    }
+    if( verbose ) fprintf( stderr, "<compiler-driver>\n" );
+
+    // Stack on driver name and dump commands flag
+    gcc_args_str.insert(gcc_args_str.begin(),std::string("-###"));
+    gcc_args_str.insert(gcc_args_str.begin(),gcc_name);
+
+    /* Redirect stderr to our pipe */
+    if( verbose ) {
+       const char *tag = "executable";
+       fprintf( stderr, "<gcc>\n" );
+       for( size_t i = 0; i < gcc_args_str.size(); i++ ) {
+           fprintf( stderr, " <%s>%s</%s>\n",
+                    tag, gcc_args_str[i].c_str(),
+                    tag );
+           tag = "arg";
+       }
+       fprintf( stderr, "</gcc>\n" );
+    }
+
+    Process p = fork_execvp( gcc_args_str );
+
+    while( p && p->ProcessStarted() && !p->EndOfStream() )
+       gcc_hash_output += p->ReadStdError();
+
+    std::istringstream iss( gcc_hash_output );
+
+    if( p->GetStatus() ) goto final;
+
+    while( std::getline( iss, gcc_line, '\n' ) ) {
+       // command line
+       if( gcc_line.size() > 2 && gcc_line[0] == ' ' ) {
+           subcmd_args =
+               break_arguments<std::vector<std::string> >( gcc_line );
+
+           if( subcmd_args.size() < 1 ) continue;
+
+           if( subcmd_args[0].find("collect2") != std::string::npos ||
+               subcmd_args[0].find("ld") != std::string::npos ) {
+               if( run_ld( verbose, nostdlib, nostartfiles, is_dll, make_map,
+                           mingw_lib_dir, extra_linker_stage, ldscript,
+                           subcmd_args ) )
+                   goto final;
+               else
+                   continue;
+           }
+
+           if( verbose )
+               subcmd_args.insert(subcmd_args.begin()+1,"-v");
+
+           if( execute_command
+               ( verbose, subcmd_args ) )
+               goto final;
+       } else if( verbose )
+           fprintf( stderr, "<error>%s</error>\n", gcc_line.c_str()
);
+    }
+    goto theend;
+
+ final:
+    status = 1;
+
+ theend:
+    if( verbose ) {
+       fprintf( stderr, "<status>%d</status>\n", status );
+       fprintf( stderr, "</compiler-driver>\n" );
+    }
+    return status;
+}
Added: branches/powerpc/reactos/tools/ppc-build/compdvr/dlltool.cpp
URL:
http://svn.reactos.org/svn/reactos/branches/powerpc/reactos/tools/ppc-build…
==============================================================================
--- branches/powerpc/reactos/tools/ppc-build/compdvr/dlltool.cpp (added)
+++ branches/powerpc/reactos/tools/ppc-build/compdvr/dlltool.cpp Fri Jan  5 08:56:26 2007
@@ -1,0 +1,566 @@
+#include <stdio.h>
+#include <ctype.h>
+#include <map>
+#include <vector>
+#include <string>
+#include <sstream>
+#include <fstream>
+
+/*
+ * .idata$2_liba_dll           # liba import directory
+ *  __dll_liba_import_directory:
+ *   .rva __dll_tail
+ *   .long 0
+ *   .long 0
+ *   .rva __liba_dll_name
+ *   .rva __liba_dll_fthunk
+ * .idata$2_libb_dll           # libb import directory
+ *  __dll_libb_import_directory:
+ *   20 bytes ...
+ * .idata$3                    # Zero entry
+ *  __dll_tail:
+ *   20 zeroes ...
+ * .idata$4_liba_dll           # Import Lookup Table
+ *  __dll_liba_ilt:
+ *  .idata$4_liba_fun1_ilt
+ *   __dll_liba_fun1_ilt:
+ *    .rva __dll_liba_fun1_hint
+ *  .idata$4_liba_fun2_ilt
+ *   __dll_libb_fun2_ilt:
+ *    .rva __dll_liba_fun1_hint
+ * .idata$4_libb_dll           # Import Lookup Table
+ *  .idata$5_libb_fun1_ilt
+ *  .idata$5_libb_fun2_ilt
+ * .idata$5_liba_dll           # Import Address Table
+ *  .idata$5_liba_fun1_iat
+ *   __dll_liba_fun1_ia:
+ *    .long 0
+ *  .idata$5_liba_fun2_iat
+ * .idata$5_libb_dll           # Import Address Table
+ *  .idata$5_libb_fun1_iat
+ *  .idata$5_libb_fun2_iat
+ * .idata$6_liba_dll           # Hint Table
+ *  .idata$6_liba_fun1_hint
+ *  .idata$6_liba_fun2_hint
+ * .idata$6_libb_dll           # Hint Table
+ *  .idata$6_liba_fun1_hint
+ *  .idata$6_liba_fun2_hint
+ * .idata$7_liba_dll           # DLL Name
+ *  __liba_dll_name:
+ *   .asciz "liba.dll"
+ * .idata$7_libb_dll           # DLL Name
+ *  __libb_dll_name:
+ *   .asciz "libb.dll"
+ *
+ */
+
+std::string uppercase( const std::string &mcase ) {
+    std::string out;
+    for( std::string::const_iterator i = mcase.begin();
+        i != mcase.end();
+        i++ ) {
+       out += toupper(*i);
+    }
+    return out;
+}
+
+std::string comment_strip( const std::string &line ) {
+    size_t s = line.find(';');
+    if( s != std::string::npos ) return line.substr(0,s);
+    else return line;
+}
+
+class DefFile {
+public:
+    class Export {
+    public:
+       Export( const std::string &name, const std::string &alias = "",
+               int ordinal = -1 ) :
+           name(name), alias_of(alias), ordinal(ordinal) {}
+
+       const std::string &getName() const { return name; }
+       const std::string &getAliasOf() const { return alias_of; }
+       int getOrdinal() const { return ordinal; }
+
+    private:
+       std::string name;
+       std::string alias_of;
+       int ordinal;
+    };
+
+    DefFile() : ordbase(1), mode(0) { }
+
+    static std::string clean_for_symbol( const std::string &s ) {
+       std::string out;
+
+       for( size_t i = 0; i < s.size(); i++ ) {
+           out += isalpha(s[i]) ? s[i] : '_';
+       }
+
+       return out;
+    }
+
+    static std::string section( const std::string &name ) {
+       return std::string("\t.section\t") + name + "\n";
+    }
+
+    static std::string symbol( const std::string &name ) {
+       return name + ":\n";
+    }
+
+    static std::string global( const std::string &name ) {
+       return std::string("\t.global\t") + name + "\n";
+    }
+
+    static std::string global_sym( const std::string &name ) {
+       return global(name) + symbol(name);
+    }
+
+    static std::string impsym( const std::string &name, size_t i ) {
+       std::ostringstream oss;
+       oss << name << "_" << i;
+       return oss.str();
+    }
+
+    std::string archive_deco( const std::string &sym ) {
+       return std::string("__dll_archive_") + libsym + "_" + sym;
+    }
+
+    static std::string rva( const std::string &symbol ) {
+       return std::string("\t.rva\t") + symbol + "\n";
+    }
+
+    std::string common_name( size_t i, const std::string &_name = "" )
const {
+       size_t at;
+       std::string name = _name;
+
+       if( !name.size() ) name = exports[i].getName();
+       if( !name.size() ) {
+           std::ostringstream oss;
+           oss << libsym << "_ordinal_" << i;
+           return oss.str();
+       }
+
+       if( name[0] == '@' ) name = name.substr(1);
+       at = name.find('@');
+       if( at != std::string::npos )
+           name = name.substr(0,at);
+
+       return name;
+    }
+
+    size_t count_names() const {
+       size_t res = 0;
+       for( size_t i = 0; i < exports.size(); i++ )
+           if( exports[i].getName().size() ) ++res;
+       return res;
+    }
+
+    bool parse( int ln, const std::string &line ) {
+       std::string command;
+       std::string stripped_line = comment_strip(line);
+
+       std::istringstream iss(stripped_line);
+
+       bool got_word = iss >> command;
+
+       if( uppercase(command) == "LIBRARY" ) {
+           if( mode ) {
+               fprintf( stderr, "Got library out of turn on line %d\n", ln );
+               return false;
+           }
+           mode++;
+           iss >> libname;
+           libsym = clean_for_symbol(libname);
+           import_directory_entry = archive_deco("import_directory_entry");
+           import_directory_term  = archive_deco("import_directory_term");
+           dll_name_text = archive_deco("dll_name");
+           original_first_thunk = archive_deco("ofirst_thk");
+           original_first_thunk_term = original_first_thunk + "_term";
+           first_thunk = archive_deco("first_thk");
+           first_thunk_term = first_thunk + "_term";
+           import_desc_table = archive_deco("import_desc");
+       } else if( uppercase(command) == "EXPORTS" ) {
+           if( !mode ) {
+               fprintf( stderr, "Got exports out of turn on line %d\n", ln );
+               return false;
+           }
+           mode++;
+       } else if( got_word ) {
+           size_t equal, at;
+           std::string name, alias, name_alias, ordinal_maybe;
+           int ordinal = -1;
+
+           if( mode != 2 ) {
+               fprintf( stderr, "Got extraneous input on line %d\n", ln );
+               return false;
+           }
+
+           name_alias = command;
+           if( iss >> ordinal_maybe )
+               ordinal = atoi(ordinal_maybe.substr(1).c_str());
+
+           equal = name_alias.find('=');
+           if( equal == std::string::npos ) {
+               name = name_alias;
+           } else {
+               name = name_alias.substr(0,equal);
+               equal++;
+               alias = name_alias.substr(equal);
+           }
+
+           if( kill_at ) {
+               at = name.find('@');
+               if( at != std::string::npos )
+                   name = name.substr(0,at);
+               at = alias.find('@');
+               if( at != std::string::npos )
+                   alias = alias.substr(0,at);
+           }
+
+           Export ex(name,alias,ordinal);
+
+           export_byname.insert( std::make_pair(name, exports.size()) );
+           exports.push_back(ex);
+       }
+
+       return true;
+    }
+
+    std::string makeExportData() const {
+       std::ostringstream oss;
+
+       oss << section(".edata")
+           << longdata(0)
+           << longdata(time(NULL))
+           << longdata(0)
+           << rva(libsym)
+           << longdata(ordbase)
+           << longdata(exports.size())
+           << longdata(count_names())
+           << rva("exported_functions")
+           << rva("exported_names")
+           << rva("exported_ordinals")
+           << global_sym(libsym)
+           << asciz(libname)
+           << align(4)
+           << symbol("exported_functions");
+
+       for( size_t i = 0; i < exports.size(); i++ ) {
+           oss << "\t.rva\t" << common_name(i) <<
"\n";
+       }
+
+       oss << "exported_ordinals:\n";
+       int lastord = ordbase;
+       for( size_t i = 0; i < exports.size(); i++ ) {
+           if( exports[i].getOrdinal() != -1 )
+               lastord = exports[i].getOrdinal();
+           else
+               lastord++;
+           oss << "\t.short\t" << lastord << "\n";
+       }
+
+       oss << "exported_names:\n";
+
+       for( size_t i = 0; i < exports.size(); i++ ) {
+           if( exports[i].getName().size() ) {
+               oss << "\t.rva\texport_name_" << (int)i <<
"\n";
+           }
+       }
+
+       for( size_t i = 0; i < exports.size(); i++ ) {
+           if( exports[i].getName().size() ) {
+               oss << "export_name_" << (int)i
+                   << ":\t.asciz\t\""
+                   << exports[i].getName() << "\"\n";
+           }
+       }
+
+       oss << "# End of exports\n";
+
+       return oss.str();
+    }
+
+    static std::string align(int n) {
+       std::ostringstream oss;
+       oss << "\t.align\t" << n << "\n";
+       return oss.str();
+    }
+
+    static std::string longdata(long l) {
+       std::ostringstream oss;
+       oss << "\t.long\t" << l << "\n";
+       return oss.str();
+    }
+
+    static std::string shortdata(int i) {
+       std::ostringstream oss;
+       oss << "\t.short\t" << i << "\n";
+       return oss.str();
+    }
+
+    static std::string space(int s) {
+       std::ostringstream oss;
+       oss << "\t.space\t" << s << "\n";
+       return oss.str();
+    }
+
+    static std::string asciz(const std::string &s) {
+       std::string quote = "\"";
+       if(s.size() && s[0] == '\"')
+           quote = "";
+       return std::string("\t.asciz\t") + quote + s + quote + "\n";
+    }
+
+    std::string makeArchiveHeader() const {
+       std::ostringstream oss;
+
+       oss << section(".idata$2")
+           << global_sym(import_directory_entry)
+           << rva(original_first_thunk)
+           << longdata(0)
+           << longdata(0)
+           << rva(dll_name_text)
+           << section(".idata$4")
+           << global_sym(original_first_thunk)
+           << section(".idata$5")
+           << global_sym(first_thunk)
+           << section(".idata$6")
+           << global_sym(import_desc_table);
+
+       return oss.str();
+    }
+
+    std::string makeArchiveFooter() const {
+       std::ostringstream oss;
+
+       oss << section(".idata$3")
+           << global_sym(import_directory_term)
+           << space(20)
+           << global_sym(original_first_thunk_term)
+           << longdata(0)
+           << global_sym(first_thunk_term)
+           << longdata(0)
+           << section(".idata$7")
+           << global_sym(dll_name_text)
+           << asciz(libname);
+
+       return oss.str();
+    }
+
+    std::string makePerImportData( size_t i ) const {
+       std::ostringstream oss;
+
+       oss << section(".text")
+           << global_sym(common_name(i))
+           << "\taddi\t1,1,16\n"
+           << "\tmflr\t0\n"
+           << "\tstw\t0,0(1)\n"
+           << "\tlis\t0," << impsym(first_thunk,i) <<
"@ha\n"
+           << "\tori\t0,0," << impsym(first_thunk,i) <<
"@l\n"
+           << "\tlwz\t0," << (4 * i) << "(0)\n"
+           << "\tmtlr\t0\n"
+           << "\tblrl\n"
+           << "\tlwz\t0,0(1)\n"
+           << "\taddi\t1,1,-16\n"
+           << "\tblr\n"
+           << rva(impsym(original_first_thunk,i))
+           << rva(impsym(import_desc_table,i))
+           << rva(impsym(first_thunk,i))
+           << rva(import_directory_entry)
+           << rva(import_directory_term)
+           << section(".idata$4")
+           << symbol(impsym(original_first_thunk,i))
+           << rva(impsym(import_desc_table,i))
+           << section(".idata$5")
+           << symbol(impsym(import_desc_table,i))
+           << shortdata(exports[i].getOrdinal())
+           << asciz(exports[i].getName())
+           << section(".idata$6")
+           << symbol(impsym(first_thunk,i))
+           << rva(impsym(import_desc_table,i));
+
+       return oss.str();
+    }
+
+    size_t numFunctions() const { return exports.size(); }
+
+    void setKillAt( bool kill ) { kill_at = kill; }
+
+private:
+    bool kill_at;
+    std::string libname, libsym;
+    std::string import_directory_entry, import_directory_term;
+    std::string original_first_thunk, first_thunk, dll_name_text;
+    std::string original_first_thunk_term, first_thunk_term;
+    std::string import_desc_table;
+    std::vector<Export> exports;
+    std::map<std::string,size_t> export_byname;
+    int ordbase, mode;
+};
+
+std::string maketemp
+( const std::string &prefix,
+  const std::string &suffix,
+  const std::string &payload ) {
+    std::string template_accum =
+       std::string("/tmp/") + prefix + "XXXXXX";
+    std::vector<char> storage, duplicate;
+
+    for( size_t i = 0; i < template_accum.size(); i++ )
+       storage.push_back(template_accum[i]);
+    storage.push_back(0);
+
+    duplicate = storage;
+    std::string result;
+    mktemp(&duplicate[0]);
+    result = &duplicate[0];
+    result += suffix;
+    std::ofstream of;
+    of.open(result.c_str());
+    of << payload;
+    of.close();
+
+    return result;
+}
+
+void _check( const std::string &varname, const std::string &varval ) {
+    if( !varval.size() ) {
+       fprintf( stderr, "You must specify %s\n", varname.c_str() );
+       exit(1);
+    }
+}
+
+#define check(x) _check(#x,x)
+
+bool parseArg(int argc, char **argv,
+             std::string &argval,
+             const char *short_n,
+             const char *long_n = 0,
+             const char *extra_n = 0)
+{
+    std::string argv_i;
+    bool got_val = false;
+
+    if( !long_n ) { long_n = short_n; }
+
+    for( int i = 0; i < argc; i++ ) {
+       argv_i = argv[i];
+       if( argv_i == short_n ) {
+           if( i < argc-1 )
+               argval = argv[i+1];
+           got_val = true;
+       } else if( argv_i == long_n ) {
+           if( i < argc-1 )
+               argval = argv[i+1];
+           got_val = true;
+       } else if( argv_i.substr(0,strlen(long_n)+1) ==
+                  std::string(long_n) + "=" ) {
+           argval = argv_i.substr(strlen(long_n)+1);
+           got_val = true;
+       }
+    }
+
+    if( !got_val && extra_n )
+       return parseArg(argc,argv,argval,short_n,extra_n);
+
+    return got_val;
+}
+
+int main( int argc, char **argv ) {
+    int i, ln = 0;
+    bool dont_delete = false, kill_at = false;
+    DefFile f;
+    std::string line;
+    std::string def_file, exp_file, dll_name, imp_name,
+       as_name = "as", ar_name = "ar cq", foo;
+    std::ifstream in_def;
+
+
parseArg(argc,argv,def_file,"-d","--def","--input-def");
+
parseArg(argc,argv,exp_file,"-e","--exp","--output-exp");
+
parseArg(argc,argv,imp_name,"-l","--lib","--output-lib");
+    parseArg(argc,argv,dll_name,"-D","--dll","--dll-name");
+    parseArg(argc,argv,as_name, "-S","--as");
+    dont_delete = parseArg(argc,argv,foo,"-n");
+    kill_at     = parseArg(argc,argv,foo,"-k");
+
+    check(def_file);
+    check(imp_name);
+
+    int err = 0;
+    std::string export_file, archive_header_file, archive_footer_file;
+    std::vector<std::string> archive_member_files;
+    std::ostringstream make_exp;
+    std::ostringstream make_lib, archive_it;
+
+    f.setKillAt(kill_at);
+
+    in_def.open(def_file.c_str());
+    while( std::getline(in_def,line) )
+       if(!f.parse(++ln,line)) {
+           fprintf( stderr, "Ungrammatic def file\n" );
+           goto cleanup;
+       }
+    in_def.close();
+
+    unlink(imp_name.c_str());
+
+    export_file = maketemp("exports",".s",f.makeExportData());
+    archive_header_file =
maketemp("arch_hdr",".s",f.makeArchiveHeader());
+    archive_footer_file =
maketemp("arch_end",".s",f.makeArchiveFooter());
+    for( size_t i = 0; i < f.numFunctions(); i++ )
+       archive_member_files.push_back
+           (maketemp("arch_mem",".s",f.makePerImportData(i)));
+
+    if( exp_file.size() ) {
+       make_exp << as_name << " -mlittle -o " << exp_file
<< " " << export_file;
+
+       fprintf( stderr, "execute %s\n", make_exp.str().c_str() );
+
+       if( (err = system(make_exp.str().c_str())) ) {
+           fprintf(stderr, "Failed to execute %s\n", make_exp.str().c_str());
+           goto cleanup;
+       }
+    }
+
+    make_lib << as_name << " -mlittle -o " <<
archive_header_file << ".o "
+            << archive_header_file
+            << " && "
+            << as_name << " -mlittle -o " <<
archive_footer_file << ".o "
+            << archive_footer_file;
+
+    archive_it << ar_name << " " << imp_name << "
"
+              << archive_header_file << ".o";
+    for( size_t i = 0; i < f.numFunctions(); i++ ) {
+       make_lib << " && "
+                << as_name << " -mlittle -o "
+                << archive_member_files[i] << ".o "
+                << archive_member_files[i];
+       archive_it << " " << archive_member_files[i] <<
".o";
+    }
+
+    archive_it << " " << archive_footer_file <<
".o";
+    make_lib << " && " << archive_it.str();
+
+    fprintf( stderr, "execute %s\n", make_lib.str().c_str() );
+
+    if( (err = system(make_lib.str().c_str())) ) {
+       fprintf(stderr, "Failed to execute %s\n", make_exp.str().c_str());
+       goto cleanup;
+    }
+
+cleanup:
+    if( !dont_delete ) {
+       unlink(export_file.c_str());
+       unlink(archive_header_file.c_str());
+       unlink((archive_header_file + ".o").c_str());
+       unlink(archive_footer_file.c_str());
+       unlink((archive_footer_file + ".o").c_str());
+       for( size_t i = 0; i < f.numFunctions(); i++ ) {
+           unlink(archive_member_files[i].c_str());
+           unlink((archive_member_files[i] + ".o").c_str());
+       }
+    }
+
+    return err;
+}
Added: branches/powerpc/reactos/tools/ppc-build/compdvr/fork_execvp.h
URL:
http://svn.reactos.org/svn/reactos/branches/powerpc/reactos/tools/ppc-build…
==============================================================================
--- branches/powerpc/reactos/tools/ppc-build/compdvr/fork_execvp.h (added)
+++ branches/powerpc/reactos/tools/ppc-build/compdvr/fork_execvp.h Fri Jan  5 08:56:26
2007
@@ -1,0 +1,28 @@
+#ifndef FORK_EXECVP_H
+#define FORK_EXECVP_H
+
+#include <string>
+#include <vector>
+
+class ProcessHolder {
+public:
+    virtual ~ProcessHolder() { }
+    virtual std::string ReadStdError() = 0;
+    virtual bool ProcessStarted() const = 0;
+    virtual bool EndOfStream() const = 0;
+    virtual int  GetStatus() const = 0;
+};
+
+class Process {
+public:
+    Process( ProcessHolder *h ) : holder(h) { }
+    ~Process() { delete holder; }
+    ProcessHolder *operator -> () const { return holder; }
+    operator ProcessHolder *() const { return (holder &&
holder->ProcessStarted()) ? holder : NULL; }
+private:
+    ProcessHolder *holder;
+};
+
+ProcessHolder *fork_execvp( const std::vector<std::string> &args );
+
+#endif//FORK_EXECVP_H
Propchange: branches/powerpc/reactos/tools/ppc-build/compdvr/fork_execvp.h
------------------------------------------------------------------------------
    svn:executable = *
Added: branches/powerpc/reactos/tools/ppc-build/compdvr/fork_unix.cpp
URL:
http://svn.reactos.org/svn/reactos/branches/powerpc/reactos/tools/ppc-build…
==============================================================================
--- branches/powerpc/reactos/tools/ppc-build/compdvr/fork_unix.cpp (added)
+++ branches/powerpc/reactos/tools/ppc-build/compdvr/fork_unix.cpp Fri Jan  5 08:56:26
2007
@@ -1,0 +1,66 @@
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include "fork_execvp.h"
+
+class UnixProcessHolder : public ProcessHolder {
+public:
+    UnixProcessHolder( const std::vector<std::string> &args )
+       : read_fd(-1), child_pid(-1), at_end(false), status(-1) {
+       std::vector<char *> argvect(args.size()+1);
+       for( size_t i = 0; i < args.size(); i++ )
+           argvect[i] = (char *)args[i].c_str();
+       argvect[args.size()] = 0;
+
+       int err_fd[2];
+
+       if( pipe( err_fd ) == -1 )
+           return;
+
+       fflush(stdout);
+
+       child_pid = fork();
+
+       if( !child_pid ) {
+           dup2( err_fd[1], 2 );
+           close( err_fd[0] );
+           close( err_fd[1] );
+
+           execvp(args[0].c_str(), &argvect[0] );
+           exit(1);
+       } else {
+           close( err_fd[1] );
+           read_fd = err_fd[0];
+       }
+    }
+
+    ~UnixProcessHolder() {
+       close( read_fd );
+    }
+
+    std::string ReadStdError() {
+       char buf[1024];
+       int rl = read( read_fd, buf, sizeof(buf) );
+       if( rl < 1 ) {
+           at_end = true;
+           waitpid( child_pid, &status, 0 );
+           return "";
+       }
+       return std::string(buf, rl);
+    }
+
+    bool ProcessStarted() const { return child_pid != -1; }
+    bool EndOfStream() const { return at_end; }
+    int  GetStatus() const { return status; }
+
+private:
+    bool at_end;
+    int read_fd;
+    int child_pid;
+    int status;
+};
+
+ProcessHolder *fork_execvp( const std::vector<std::string> &args ) {
+    return new UnixProcessHolder( args );
+}
Propchange: branches/powerpc/reactos/tools/ppc-build/compdvr/fork_unix.cpp
------------------------------------------------------------------------------
    svn:executable = *
Added: branches/powerpc/reactos/tools/ppc-build/compdvr/fork_win32.cpp
URL:
http://svn.reactos.org/svn/reactos/branches/powerpc/reactos/tools/ppc-build…
==============================================================================
--- branches/powerpc/reactos/tools/ppc-build/compdvr/fork_win32.cpp (added)
+++ branches/powerpc/reactos/tools/ppc-build/compdvr/fork_win32.cpp Fri Jan  5 08:56:26
2007
@@ -1,0 +1,109 @@
+#include <windows.h>
+#include "fork_execvp.h"
+
+class Win32ProcessHolder : public ProcessHolder {
+public:
+    Win32ProcessHolder( const std::string &args )
+       : ErrorRead(INVALID_HANDLE_VALUE),
+         ProcessHandle(INVALID_HANDLE_VALUE),
+         StreamEnded(false) {
+       HANDLE ErrorWrite = NULL, ErrorReadTemp = NULL;
+       PROCESS_INFORMATION pi = { };
+       SECURITY_ATTRIBUTES sa = { };
+       STARTUPINFO si = { };
+
+       sa.nLength = sizeof(sa);
+       sa.lpSecurityDescriptor = NULL;
+       sa.bInheritHandle = TRUE;
+
+       if(!CreatePipe(&ErrorReadTemp, &ErrorWrite, &sa, 0)) return;
+
+       if(!DuplicateHandle(GetCurrentProcess(), ErrorReadTemp,
+                           GetCurrentProcess(), &ErrorRead,
+                           0, FALSE,
+                           DUPLICATE_SAME_ACCESS)) return;
+
+       CloseHandle(ErrorReadTemp);
+
+       si.cb = sizeof(si);
+       si.dwFlags = STARTF_USESTDHANDLES;
+       si.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
+       si.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
+       si.hStdError = ErrorWrite;
+
+       if(!CreateProcess(NULL, (char *)args.c_str(), NULL, NULL, TRUE,
+                         0, NULL, NULL, &si, &pi)) return;
+
+       ProcessHandle = pi.hProcess;
+
+       CloseHandle(ErrorWrite);
+    }
+
+    ~Win32ProcessHolder() {
+       CloseHandle( ErrorRead );
+       CloseHandle( ProcessHandle );
+    }
+
+    std::string ReadStdError() {
+       char Buf[1024];
+       DWORD ReadBytes;
+
+       if( StreamEnded ) return "";
+
+       StreamEnded =
+           !ReadFile(ErrorRead, Buf, sizeof(Buf), &ReadBytes, NULL) ||
+           !ReadBytes;
+
+       if( !StreamEnded ) return std::string(Buf, ReadBytes);
+       else return "";
+    }
+
+    bool EndOfStream() const {
+       return StreamEnded;
+    }
+
+    bool ProcessStarted() const {
+       return ProcessHandle != INVALID_HANDLE_VALUE;
+    }
+
+    int GetStatus() const {
+       DWORD Status = 1;
+       if( ProcessHandle != INVALID_HANDLE_VALUE ) {
+           WaitForSingleObject( ProcessHandle, INFINITE );
+           GetExitCodeProcess( ProcessHandle, &Status );
+       }
+       return Status;
+    }
+
+private:
+    bool StreamEnded;
+    HANDLE ErrorRead, ProcessHandle;
+};
+
+std::string quote_escape( const std::string &_str ) {
+    std::string str = _str;
+    size_t q;
+
+    q = str.find('\"');
+    while( q != std::string::npos ) {
+       str.replace(q, 1, "\\\"");
+       q = str.find('\"');
+    }
+
+    return std::string("\"") + str + "\"";
+}
+
+ProcessHolder *fork_execvp( const std::vector<std::string> &args ) {
+    std::string argstring;
+    ProcessHolder *holder;
+
+    for( std::vector<std::string>::const_iterator i = args.begin();
+        i != args.end();
+        i++ ) {
+       if( i != args.begin() )
+           argstring += " ";
+       argstring += quote_escape(*i);
+    }
+
+    return new Win32ProcessHolder( argstring );
+}
Propchange: branches/powerpc/reactos/tools/ppc-build/compdvr/fork_win32.cpp
------------------------------------------------------------------------------
    svn:executable = *