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 = *