Commit d8eb2119 authored by Guido van Rossum's avatar Guido van Rossum

Adding the BeOS port. More checkins to follow.

parent 3f7b6fce
<html>
<head>
<title>PyImport_BeImageID()</title>
</head>
<body text="#000000" bgcolor="#ffffff">
<h1>PyImport_BeImageID()</h1>
<dl compact>
<dt><strong>NOTE:</strong><dt>
<dd>This is documentation for the BeOS-specific
<code>PyImport_BeImageID()</code> function defined in
<tt>Python/importdl.c</tt>; it should be merged with the
<cite>Importing Modules</cite> section of the <cite>Python/C API</cite>
reference (or it should be the first member of a BeOS-specific
document in the <tt>BeOS</tt> directory).</dd>
</dl>
<dl compact
<dt><code>image_id <b>PyImport_BeImageID</b>( char *<i>name</i> )</code></dt>
<dd>Return the BeOS image ID (see the
<a href="file:///boot/beos/documentation/Be%20Book/The%20Kernel%20Kit/Images.html">Images</a>
section in the
<a href="file:///boot/beos/documentation/Be%20Book/The%20Kernel%20Kit/index.html">Kernel
Kit</a>) for the module object corresponding to a module <i>name</i>.
If the specified module is not dynamically loaded,
<code>PyImport_BeImageID()</code> will return <code>B_ERROR</code>,
otherwise it will return a valid <code>image_id</code>.
<p>Using <code>PyImport_BeImageID()</code> outside of a BeOS-specific
module is probably a very bad idea.</p></dd>
</dl>
<hr>
<p>Function added by Donn Cave
(<a href="mailto:donn@u.washington.edu"><tt>donn@u.washington.edu</tt></a>),
documented by Chris Herborth
(<a href="mailto:chrish@qnx.com"><tt>chrish@qnx.com</tt></a>).</p>
</body>
</html>
Python 1.5.1 for BeOS
This directory contains several useful things to help you build your own
version of Python for BeOS.
At this time, Python only supports BeOS on the PowerPC platform; if you'd
like to help me port it to the x86 platform, please let me know (I only
have limited access to BeOS on an x86 system). If you'd like to lend
me an x86 laptop running BeOS to do the port, _definitely_ let me know! :-)
I'll even give it back when I'm done.
What's Here?
ar-1.1 - An "ar" command with a POSIX 1003.2 interface; you'll need
this for building the Python libraries under BeOS
(/bin/ar just won't cut it).
linkcc - A shell script used by the build process to build the Python
shared library.
linkmodule - A shell script used by the build process to build the
shared library versions of the standard modules; you'll
probably need this if you want to build dynamically loaded
modules from the Python archives.
PyImport_BeImageID.html - Documentation for a function added to the
Python interpreter under BeOS; not interesting
unless you're writing your own BeOS-specific
modules for dealing with dynamically-loaded
Python modules.
README - This file (obviously!).
README.readline-2.2 - Instructions for compiling/installing GNU readline 2.2.
You'll have to grab the GNU readline source code from
prep.ai.mit.edu:/pub/GNU or any other GNU mirror.
The Python interpreter is much nicer to work with
interactively if you've got readline installed. Highly
recommended.
Compiling Your Own Version
To compile your own version of Python 1.5.1 for BeOS (with any luck,
Python 1.6 will compile "out of the box" on BeOS), try this:
1) Get the Python 1.5.1 source code from ftp.python.org.
2) Get the Python 1.5.1 diffs from my web pages
(http://www.qnx.com/~chrish/Be/software/); if you can't get them through
a web browser, send me email and I'll mail them back to you. These
diffs should also be available at ftp.python.org along with the BeOS
binary archive.
Run autoconf. If you don't have autoconf, you can get a precompiled
version from GeekGadgets (ftp://ftp.ninemoons.com/pub/geekgadgets/...).
3) Compile and install the POSIX ar from the ar-1.1 directory; see the
README in there for details.
4) Configure with:
AR=ar-posix RANLIB=: ./configure --verbose --without-gcc \
--prefix=/boot/home/config --with-thread
The only strange thing that happens during the configure is that
we fail the "genuine getopt()" test; this is odd because we've got
a real live GNU getopt() in the system libs. Other packages built
using configure (such as all of the goodies in GeekGadgets) suffer
the same fate though, so it's not a Python problem.
5) Copy Modules/Setup.in to Modules/Setup.
6) Edit Modules/Setup to turn on all the modules you want built. I've
personally built the following modules:
array, audioop, binascii, cPickle, cStringIO, cmath, crypt, curses,
errno, fcntl, gdbm, grp, imageop, math, md5, new, operator, parser,
pcre, posix, pwd, readline, regex, reop, rgbimg, rotor, select,
signal, socket, soundex, strop, struct, syslog, termios, thread,
time, timing, zlib
Newly compiled/tested with 1.5.1:
_locale
You can get precompiled gdbm, ncurses, and zlib libraries from the
GeekGadgets repository (ftp://ftp.ninemoons.com/pub/geekgadgets/...).
Make sure you use _socket instead of socket for the name of the
socketmodule on BeOS.
7) Make:
make
or, if you feel the need for speed:
make OPT="-O7 -opt schedule604"
You can safely ignore any warnings you see during the build (and you'll
see several if you use full warnings; I compiled the distribution with
-w9 -ansi strict and cleaned up any errors...).
8) Test:
make test
Expect the following errors:
test_builtin failed -- round(1000000000.0)
test_fcntl skipped -- an optional feature could not be imported
test_grp crashed -- exceptions.KeyError : getgrnam(): name not found
test_pwd failed -- Writing: 'fakename', expected: 'caught e'
test_socket crashed -- exceptions.AttributeError : SOCK_RAW
These are all due to either partial support for certain things (like
sockets), or valid differences between systems (like the round()
error; different CPUs represent floating point numbers differently,
which can cause minor rounding errors).
9) Install:
make install
10) Enjoy!
NOTE
If you're going to build your own C/C++-based Python modules, link them
against the libpython1.5.so shared library (in /boot/home/config/lib)
instead of the libpython1.5.a (in /boot/home/config/lib/python1.5/config),
unless you're building a statically-linked python interpreter (then you
could try linking against _APP_ instead).
Mixing modules linked against the shared library with a statically-linked
interpreter is a bad idea (and it'll fail in _interesting_ ways).
- Chris Herborth (chrish@qnx.com)
April 25, 1998
GNU readline 2.2 for BeOS
You can get the original GNU readline 2.2 source code from your favourite
GNU software repository, such as ftp://prep.ai.mit.edu/pub/gnu/.
You can get the only-slightly-modified-for-BeOS version of GNU readline 2.2
from the GeekGadgets repository; ftp://ftp.ninemoons.com/pub/geekgadgets/.
BUILDING libreadline for BeOS hosts
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Note that we don't build a shared library version of libreadline and
libhistory. That's left as an exercise for the reader.
You won't be able to link against libreadline.a using the limited linker.
1) If you're on a PowerPC system, install the POSIX ar from
http://www.qnx.com/~chrish/Be/software/index.html#programming
(note that it's currently packaged with Python, in the BeOS/ar-1.1
directory).
If you're on an x86 system, you can leave out the "AR=ar-posix" part
of the following instructions. In fact, you'll have to...
2) For PowerPC, configure with:
CC=mwcc CFLAGS="-O7 -i- -I." AR=ar-posix RANLIB=: ./configure --verbose \
--without-gcc --prefix=/boot/home/config powerpc-*-beos
For x86, configure with:
CC=mwcc CFLAGS="-O2 -i- -I." RANLIB=: ./configure --verbose \
--without-gcc --prefix=/boot/home/config x86-*-beos
Don't worry about the warnings/errors configure spews for
powerpc-*-beos or x86-*-beos; readline doesn't actually use this host
information for anything, although configure will die if you don't
specify it.
3) Edit config.h to comment out "#define HAVE_SELECT 1"; select() on
BeOS doesn't work on file descriptors (such as stdin).
4) For PowerPC, make with:
make AR=ar-posix
For x86, make with:
make
5) Install with:
make install
- Chris Herborth (chrish@qnx.com)
April 21, 1998
######################################################################
# Makefile for ar
#
# Dec. 14, 1997 Chris Herborth (chrish@kagi.com)
#
# $Id$
######################################################################
AR_VERSION=1.1
# Make variables
CC=mwcc
LD=mwcc
CFLAGS=-w9 -rostr -O3 -g
CFLAGS_O=-w9 -rostr -O7 -opt schedule604
LDFLAGS=-g -map ar.xMAP
LDFLAGS_O=
INSTALL=install -m 755
DESTINATION=/boot/home/config/bin
PARTS=main.o mwlib.o commands.o copy_attrs.o
all: ar
nodebug:
-rm -f ar $(PARTS) ar.dbg ar.xSYM
$(MAKE) CFLAGS="$(CFLAGS_O) -DNO_DEBUG" LDFLAGS="$(LDFLAGS_O)" ar
ar: $(PARTS)
$(LD) $(LDFLAGS) -o $@ $(PARTS)
install: ar
$(INSTALL) ar $(DESTINATION)
ln -sf $(DESTINATION)/ar $(DESTINATION)/ar-posix
clean:
-rm -f $(PARTS) ar ar.dbg ar.xSYM
zip:
(cd .. ; zip -9ry ar-$(AR_VERSION).zip ar-$(AR_VERSION) \
-x ar-$(AR_VERSION)/RCS -x ar-$(AR_VERSION)/docs/RCS \
-x ar-$(AR_VERSION)/RCS/\* -x ar-$(AR_VERSION)/docs/RCS/\*)
%.o: %.c
$(CC) $(CFLAGS) -c $< -o $@
docs/ar.html
\ No newline at end of file
ar - POSIX 1003.2 interface to library files
Here's the source and PowerPC binary for a POSIX 1003.2 interface "ar"
command; this is extremely useful when you're porting complex UNIX/POSIX
software to BeOS for PowerPC (I originally wrote it to support my Python
port).
To build/install ar, do this in a Terminal:
make nodebug install
This will create ar and ar-posix (a symlink to ar) in ~/config/bin. The
ar-posix symlink is to make things a little easier if you happen to
have GeekGadgets (see www.ninemoons.com) installed; it comes with an
ar that only works on objects/libraries produced by GNU C for BeOS.
To use the POSIX ar with your port, do something like this:
AR=ar-posix ./configure ... normal configure arguments ...
and then:
make AR=ar-posix
You may need to check the Makefiles; people seem to be quite sloppy about
using just plain "ar cr libfoo.a ..." instead of "$(AR) cr libfoo.a ...".
- Chris Herborth, April 18, 1998
(chrish@kagi.com)
File added
This diff is collapsed.
This diff is collapsed.
/*
** commands.h - POSIX 1003.2 "ar" command
**
** $Id$
**
** This isn't a pure POSIX 1003.2 ar; it only manipulates Metrowerks
** Library files, not general-purpose POSIX 1003.2 format archives.
**
** Dec. 14, 1997 Chris Herborth (chrish@kagi.com)
**
** This code is donated to the PUBLIC DOMAIN. You can use, abuse, modify,
** redistribute, steal, or otherwise manipulate this code. No restrictions
** at all. If you laugh at this code, you can't use it.
**
** This "ar" was implemented using IEEE Std 1003.2-1992 as the basis for
** the interface, and Metrowerk's published docs detailing their library
** format. Look inside for clues about how reality differs from MW's
** documentation on BeOS...
*/
#include <be/support/SupportDefs.h>
status_t do_delete( const char *archive_name, char **files, int verbose );
status_t do_print( const char *archive_name, char **files, int verbose );
status_t do_replace( const char *archive_name, char **files, int verbose,
int create, int update );
status_t do_table( const char *archive_name, char **files, int verbose );
status_t do_extract( const char *archive_name, char **files, int verobse );
/*
** copy_attrs.h - copy BeFS attributes from one file to another
**
** Jan. 11, 1998 Chris Herborth (chrish@qnx.com)
**
** This code is donated to the PUBLIC DOMAIN. You can use, abuse, modify,
** redistribute, steal, or otherwise manipulate this code. No restrictions
** at all. If you laugh at this code, you can't use it.
*/
#include <support/Errors.h>
#ifndef NO_DEBUG
#include <assert.h>
#define ASSERT(cond) assert(cond)
#else
#define ASSERT(cond) ((void)0)
#endif
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <limits.h>
#include <string.h>
#include <errno.h>
#include <kernel/fs_attr.h>
#include <fcntl.h>
#include "copy_attrs.h"
static const char *rcs_version_id = "$Id$";
/* ----------------------------------------------------------------------
** Copy file attributes from src_file to dst_file.
*/
status_t copy_attrs( const char *dst_file, const char *src_file )
{
int dst_fd, src_fd;
status_t retval = B_OK;
DIR *fa_dir = NULL;
struct dirent *fa_ent = NULL;
char *buff = NULL;
struct attr_info fa_info;
off_t read_bytes, wrote_bytes;
ASSERT( dst_file != NULL );
ASSERT( src_file != NULL );
/* Attempt to open the files.
*/
src_fd = open( src_file, O_RDONLY );
if( src_fd < 0 ) {
return B_FILE_NOT_FOUND;
}
dst_fd = open( dst_file, O_WRONLY );
if( dst_fd < 0 ) {
close( src_fd );
return B_FILE_NOT_FOUND;
}
/* Read the attributes, and write them to the destination file.
*/
fa_dir = fs_fopen_attr_dir( src_fd );
if( fa_dir == NULL ) {
retval = B_IO_ERROR;
goto close_return;
}
fa_ent = fs_read_attr_dir( fa_dir );
while( fa_ent != NULL ) {
retval = fs_stat_attr( src_fd, fa_ent->d_name, &fa_info );
if( retval != B_OK ) {
/* TODO: Print warning message?
*/
goto read_next_attr;
}
if( fa_info.size > (off_t)UINT_MAX ) {
/* TODO: That's too big. Print a warning message? You could
** copy it in chunks...
*/
goto read_next_attr;
}
if( fa_info.size > (off_t)0 ) {
buff = malloc( (size_t)fa_info.size );
if( buff == NULL ) {
/* TODO: Can't allocate memory for this attribute. Warning?
*/
goto read_next_attr;
}
read_bytes = fs_read_attr( src_fd, fa_ent->d_name, fa_info.type,
0, buff, fa_info.size );
if( read_bytes != fa_info.size ) {
/* TODO: Couldn't read entire attribute. Warning?
*/
goto free_attr_buff;
}
wrote_bytes = fs_write_attr( dst_fd, fa_ent->d_name, fa_info.type,
0, buff, fa_info.size );
if( wrote_bytes != fa_info.size ) {
/* TODO: Couldn't write entire attribute. Warning?
*/
;
}
free_attr_buff:
free( buff );
retval = B_OK;
}
/* Read the next entry.
*/
read_next_attr:
fa_ent = fs_read_attr_dir( fa_dir );
}
close_return:
close( dst_fd );
close( src_fd );
return retval;
}
/*
** copy_attrs.h - copy BeFS attributes from one file to another
**
** $Id$
**
** Jan. 11, 1998 Chris Herborth (chrish@qnx.com)
**
** This code is donated to the PUBLIC DOMAIN. You can use, abuse, modify,
** redistribute, steal, or otherwise manipulate this code. No restrictions
** at all. If you laugh at this code, you can't use it.
*/
/* ----------------------------------------------------------------------
** Function prototypes
**
** copy_attrs() - copy BeFS attributes from one file to another
**
** Returns:
** B_OK - all is well
** B_FILE_NOT_FOUND - can't open one of the named files
** B_IO_ERROR - can't read/write some of the file attributes
** B_NO_MEMORY - unable to allocate a buffer for the attribute data
*/
status_t copy_attrs( const char *dest_file, const char *src_file );
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML3.2//EN">
<!-- $Id$ -->
<html> <head>
<title>ar - create and maintain library archives</title>
</head>
<body bgcolor="#ffffcb">
<h1>ar</h1>
<h4 align="right">create and maintain library archives</h4>
<h2>Synopsis</h2>
<pre>
ar [-][dprtx][cuv] <i>archive</i> [<i>file</i> ...]
</pre>
<h2>Options</h2>
<table>
<tr>
<td valign="top"><b>-</b></td>
<td valign="top">
The <b>-</b> is optional for introducing <tt>ar</tt> command-line
arguments; this is a POSIX requirement, and I've never seen anyone
use it.</td>
</tr>
<tr>
<td valign="top"><b>c</b></td>
<td valign="top">
Don't print a diagnostic message to <i>stderr</i> when
<i>archive</i> is created.</td>
</tr>
<tr>
<td valign="top"><b>d</b></td>
<td valign="top">
Delete <i>file(s)</i> from <i>archive</i>.</td>
</tr>
<tr>
<td valign="top"><b>p</b></td>
<td valign="top">
Write the contents of the named <i>file(s)</i> to <i>stdout</i>.
If no <i>file(s)</i> are specified, all of the files in
<i>archive</i> are written in the order of the archive.</td>
</tr>
<tr>
<td valign="top"><b>r</b></td>
<td valign="top">
Replace or add <i>file(s)</i> to the <i>archive</i>. This will
create <i>archive</i> if it doesn't already exist.</td>
</tr>
<tr>
<td valign="top"><b>t</b></td>
<td valign="top">
Write the table of contents of <i>archive</i> to <i>stdout</i>.
If not <i>file(s)</i> are specified, list all of the files,
otherwise only list the specified files.</td>
</tr>
<tr>
<td valign="top"><b>u</b></td>
<td valign="top">
Update older files. When used with the <b>r</b> option, files
within the archive are only replaced if <i>file</i> has a
modification date at least as new as the <i>file</i> already in
the archive.</td>
</tr>
<tr>
<td valign="top"><b>v</b></td>
<td valign="top">Give verbose output.</td>
</tr>
<tr>
<td valign="top"><b>x</b></td>
<td valign="top">
Extract <i>file(s)</i> from the <i>archive</i>. If no
<i>file(s)</i> are specified, all of the files in <i>archive</i>
are extracted.</td>
</tr>
<tr>
<td valign="top"><i>archive</i></td>
<td valign="top">
The pathname of an archive file.</td>
</tr>
<tr>
<td valign="top"><i>file</i></td>
<td valign="top">
One more more pathnames of object files; only the file name is
used when comparing against the names of files in the
archive.</td>
</tr>
</table>
<h2>Description</h2>
<p>The <tt>ar</tt> utility creates and maintains groups of files
combined into a library. Once a library has been created, you can
add new files, and extract, delete, or replace existing files.</p>
<h2>Exit status</h2>
<p><tt>ar</tt> exits with one of the following values:</p>
<table>
<tr><td valign="top">0</td>
<td valign="top">Successful completion.</td></tr>
<tr><td valign="top">&gt; 0</td>
<td>An error occurred.</td></tr>
</table>
<h2>Bugs</h2>
<p>No known bugs, but <em>please</em> read the comments in the code if
you want to use it in another application.</p>
<h2>Comments</h2>
<p>This is a POSIX 1003.2-1992 based <tt>ar</tt> command; it's not
100% POSIX 1003.2 because POSIX specifies a file format for
<tt>ar</tt> archives. The BeOS <tt>ar</tt> produces library files
compatible (at least in theory <tt>:-)</tt>) with Metrowerks
CodeWarrior for PowerPC.</p>
<p>This <tt>ar</tt> and its source code were written as a service to
the Be developer community, to make it easier for us to port UNIX
applications and libraries. The code was written from scratch, after
reverse-engineering the Metrowerks library and object file format
(mostly because the library/object file format documentation was
incorrect).</p>
<p>If you find this useful, please
<a href="mailto:chrish@kagi.com">let me know</a>, and tell me what
you're working on. Be sure to include a URL for your homepage or your
product homepages for my
<a href="http://www.qnx.com/~chrish/Be/community/">Be Community</a>
pages.</p>
<p>If you find any bugs, please try to fix them, and send me a context
diff (use <tt>diff -c original_file fixed_file</tt>) so I can include
your fixes in the next update. I <i>have</i> tested this, but these
things have a way of slipping though.</p>
<p>If you'd like to know what other things I'm working on, take a look
at my <a href="http://www.qnx.com/~chrish/Be/software/">Be
Software</a> pages, and my
<a href="http://www.qnx.com/~chrish/Be/">Be Happy!</a> pages.</p>
<h2>License</h2>
<p>This program binary and its source code have been donated to the
BeOS Developer Community by Arcane Dragon Software free of charge.
You can do whatever you want with it.</p>
<p>If you <em>really</em> want to show your appreciation, you could
always send me a gift of some sort; cool software you wrote, nice
pictures for my desktop, ZIP drive disks, RAM, hard drives, post
cards, a pointer to a really cool/useful/interesting web site,
an MPEG audio file of an interesting band (make sure you can give me
enough information to track down their CDs if I like it!), <i>etc.</i>
Send me some <a href="mailto:chrish@kagi.com">email</a> and I'll let you
know where to send it.</p>
<p>But you don't have to do anything. Just write good BeOS software.
But you're already doing that, right?</p>
<h2>Disclaimer</h2>
<p>You use this at your own risk. I've tried to ensure that the code
is correct, but software usually has bugs. If <tt>ar</tt> destroys
your valuable data, formats your hard drive, kicks your cat, and lets
the air out of your tires, I'm not responsible for it. The code is
here, so you should feel fairly safe that there's nothing evil going
on.</p>
<p>And, as I learned once again in December 1997, you really should
keep backups of everything. I only lost a day's work, but it was
still annoying, and it could've been much, much worse.</p>
<h3>A word about the code</h3>
<p>This code isn't meant to be the ultimate in efficiency or speed,
it's intended to be fairly easy to understand and maintain
(hopefully). I was also quite keen on having something that was
correct, without jumping through a lot of unnecessary hoops.</p>
<p>If you think this code sucks, don't use it. You're already applying
this to your choice of operating system! <tt>:-)</tt></p>
<h2>Versions</h2>
<dl compact>
<dt><strong>1.1 (April 18, 1998)</strong></dt>
<dd>Changes include:
<ul>
<li>Extract option (<b>x</b>) will preserve a file's mode bits
when overwriting an existing file (this may go away if it's
not POSIX behaviour).</li>
<li>Extracted files will now have the proper file type.</li>
<li>Removed attempt to use <i>umask()</i> to set newly created
archive's mode bits; apparently, I'm not sure how it
works and my POSIX manual isn't helping.</li>
<li>Should be 100% endian-neutral now; using this on BeOS for
x86 is only useful if you're manipulating <em>PowerPC</em>
objects though. The <tt>ar</tt> in
<a href="http://www.ninemoons.com/GG/index.html">GeekGadgets</a>
should work fine for x86 objects/libraries.</li>
<li>Updated the <tt>README.txt</tt> file; now it's got useful
information about building/using the POSIX ar.</li>
</ul></dd>
<dt><strong>1.0 (January 13, 1998)</strong></dt>
<dd>Initial release.</dd>
</dl>
<hr>
<p>Chris Herborth (<a href="mailto:chrish@qnx.com">chrish@qnx.com</a>)</p>
<!-- hhmts start -->
Last modified: $Date$
<!-- hhmts end -->
</body> </html>
#! /bin/env python
""" Dump data about a Metrowerks archive file.
$Id$
Based on reverse-engineering the library file format.
Copyright (C) 1997 Chris Herborth (chrish@qnx.com)
"""
# ----------------------------------------------------------------------
# Standard modules
import sys
import getopt
import string
import time
# ----------------------------------------------------------------------
def usage():
""" Display a usage message and exit.
"""
print "dumpar [-v] library1 [library2 ... libraryn]"
print
print "Attempt to display some useful information about the contents"
print "of the given Metrowerks library file(s)."
print
print "-v Be verbose (displays offsets along with the data)"
raise SystemExit
# ----------------------------------------------------------------------
def mk_long( str ):
""" convert a 4-byte string into a number
Assumes big-endian!
"""
if len( str ) < 4:
raise ValueError, "str must be 4 bytes long"
num = ord( str[3] )
num = num + ord( str[2] ) * 0x100
num = num + ord( str[1] ) * 0x10000
num = num + ord( str[0] ) * 0x1000000
return num
# ----------------------------------------------------------------------
def str2hex( str ):
""" convert a string into a string of hex numbers
"""
ret = []
for c in str:
h = hex( ord( c ) )
ret.append( string.zfill( "%s" % ( h[2:] ), 2 ) )
return string.join( ret )
# ----------------------------------------------------------------------
def print_offset( offset ):
""" print the offset nicely
"""
# Turn the offset into a hex number and strip off the leading "0x".
val = "%s" % ( hex( offset ) )
val = val[2:]
out = "0x" + string.zfill( val, 8 )
print out,
# ----------------------------------------------------------------------
def get_string( data ):
""" dig a C string out of a data stream
returns the string
"""
len = 0
while data[len] != '\0':
len = len + 1
return data[:len]
# ----------------------------------------------------------------------
def dump_lib( file, verbose ):
""" dump information about a Metrowerks library file
"""
offset = 0
print "Dumping library:", file
# Attempt to read the data.
try:
data = open( file ).read()
except IOError, retval:
print "*** Unable to open file %s: %s" % ( file, retval[1] )
return
# Check the magic number.
if verbose:
print_offset( offset )
print "Magic:",
magic = data[offset:offset + 8]
print "'%s'" % ( magic )
if magic != "MWOBPPC ":
print "*** Invalid magic number!"
return
offset = offset + 8
# File flags
if verbose:
print_offset( offset )
print "file flags:",
print mk_long( data[offset:offset + 4] )
offset = offset + 4
if verbose:
print_offset( offset )
print "file version:",
print mk_long( data[offset:offset + 4] )
offset = offset + 4
# code size
if verbose:
print_offset( offset )
print "code size:", mk_long( data[offset:offset + 4] )
offset = offset + 4
# data size
if verbose:
print_offset( offset )
print "data size:", mk_long( data[offset:offset + 4] )
offset = offset + 4
# number of objects
if verbose:
print_offset( offset )
print "number of objects:",
num_objs = mk_long( data[offset:offset + 4] )
print num_objs
offset = offset + 4
print
# Now loop through the objects.
obj_sizes = [ 0, ] * num_objs
obj_data_offsets = [ 0, ] * num_objs
for obj in range( num_objs ):
# Magic?
if verbose:
print_offset( offset )
print "modification time:",
modtime = mk_long( data[offset:offset + 4] )
print "[%s]" % ( ( time.localtime( modtime ), ) )
offset = offset + 4
# Offsets?
if verbose:
print_offset( offset )
print "file name offset 1:",
file_offset1 = mk_long( data[offset:offset + 4] )
unknown = "%s" % ( hex( file_offset1 ) )
print "%s (%s)" % ( unknown, str2hex( data[offset:offset + 4] ) )
offset = offset + 4
if verbose:
print_offset( offset )
print "file name offset 2:",
file_offset2 = mk_long( data[offset:offset + 4] )
unknown = "%s" % ( hex( file_offset2 ) )
print "%s (%s)" % ( unknown, str2hex( data[offset:offset + 4] ) )
offset = offset + 4
# Extra -1 for NUL character.
print " >>>> File name should be %s characters." % \
( file_offset2 - file_offset1 - 1)
if verbose:
print_offset( offset )
print "object data offset:",
file_data_offset = mk_long( data[offset:offset + 4] )
unknown = "%s" % ( hex( file_data_offset ) )
print "%s (%s)" % ( unknown, str2hex( data[offset:offset + 4] ) )
obj_data_offsets[obj] = file_data_offset
offset = offset + 4
# object size
if verbose:
print_offset( offset )
print "object size:",
obj_sizes[obj] = mk_long( data[offset:offset + 4] )
print "%s bytes" % ( obj_sizes[obj] )
offset = offset + 4
print
# Now loop through the object names.
for obj in range( num_objs ):
# First name
if verbose:
print_offset( offset )
print "object",
print obj,
print "name 1:",
name1 = get_string( data[offset:] )
print "[%s] %s chars" % ( name1, len( name1 ) )
offset = offset + len( name1 ) + 1
# Second name
if verbose:
print_offset( offset )
print "object",
print obj,
print "name 2:",
name2 = get_string( data[offset:] )
print "[%s] %s chars" % ( name2, len( name1 ) )
offset = offset + len( name2 ) + 1
# See if we've got a magic cookie in the object data
if verbose:
print_offset( obj_data_offsets[obj] )
cookie = data[obj_data_offsets[obj]:obj_data_offsets[obj] + 8]
print "object",
print obj,
print "cookie: '%s'" % ( cookie )
print
# Now loop through the data and check for magic numbers there.
return
# ----------------------------------------------------------------------
def main():
""" mainline
"""
# Set up some defaults
be_verbose = 0
# First, check the command-line arguments
try:
opt, args = getopt.getopt( sys.argv[1:], "vh?" )
except getopt.error:
print "*** Error parsing command-line options!"
usage()
for o in opt:
if o[0] == "-h" or o[0] == "-?":
usage()
elif o[0] == "-v":
be_verbose = 1
else:
print "*** Unknown command-line option!"
usage()
# Now we can attempt to dump info about the arguments.
for lib in args:
dump_lib( lib, be_verbose )
if __name__ == "__main__":
main()
#! /bin/env python
""" Dump data about a Metrowerks object file.
Based on reverse-engineering the library file format, since the docs are
wrong.
Copyright (C) 1997 Chris Herborth (chrish@qnx.com)
"""
# ----------------------------------------------------------------------
# Standard modules
import sys, getopt, string, time
# ----------------------------------------------------------------------
# Extra goodies
from dumpar import mk_long, str2hex, print_offset, get_string
# ----------------------------------------------------------------------
def mk_short( str ):
""" convert a 2-byte string into a number
Assumes big-endian!
"""
if len( str ) < 2:
raise ValueError, "str must be 2 bytes long"
num = ord( str[1] )
num = num + ord( str[0] ) * 0x100
return num
# ----------------------------------------------------------------------
def usage():
""" Display a usage message and exit.
"""
print "dumpo [-v] object1 [object2 ... objectn]"
print
print "Attempt to display some useful information about the contents"
print "of the given Metrowerks object file(s)."
print
print "-v Be verbose (displays offsets along with the data)"
raise SystemExit
# ----------------------------------------------------------------------
def dump_o( file, verbose ):
""" dump information about a Metrowerks object file
Note that there is more info there, 6 more quads before the file name.
"""
offset = 0
print "Dumping object:", file
# Attempt to read the data.
try:
data = open( file ).read()
except IOError, retval:
print "*** Unable to open file %s: %s" % ( file, retval[1] )
return
# Check the magic number.
if verbose:
print_offset( offset )
print "Magic:",
magic = data[offset:offset + 8]
print "'%s'" % ( magic )
if magic != "MWOBPPC ":
print "*** Invalid magic number!"
return
offset = offset + 8
# version
if verbose:
print_offset( offset )
print "version:", mk_long( data[offset:offset + 4] )
offset = offset + 4
# flags
if verbose:
print_offset( offset )
print "flags:", str2hex( data[offset:offset + 4] )
offset = offset + 4
# code size
if verbose:
print_offset( offset )
print "code size:", mk_long( data[offset:offset + 4] )
offset = offset + 4
# data size
if verbose:
print_offset( offset )
print "data size:", mk_long( data[offset:offset + 4] )
offset = offset + 4
# ----------------------------------------------------------------------
def main():
""" mainline
"""
# Set up some defaults
be_verbose = 0
# First, check the command-line arguments
try:
opt, args = getopt.getopt( sys.argv[1:], "vh?" )
except getopt.error:
print "*** Error parsing command-line options!"
usage()
for o in opt:
if o[0] == "-h" or o[0] == "-?":
usage()
elif o[0] == "-v":
be_verbose = 1
else:
print "*** Unknown command-line option!"
usage()
# Now we can attempt to dump info about the arguments.
for obj in args:
dump_o( obj, be_verbose )
if __name__ == "__main__":
main()
MW library layout:
header
magic word, magic processor flag ('MWOBPPC ') - 2x 4 bytes
magic flags, version (file format version?) - 2x 4 bytes
code size - 4 bytes
data size - 4 bytes
# of objects - 4 bytes
header for file 1 - 20 bytes
- modification time - 4 bytes
- offset to filename - 4 bytes
- offset to full path - 4 bytes (NOTE: NOT a full path in reality!)
- offset to object data - 4 bytes
- size of object data - 4 bytes
...
header for file n - 20 bytes
file 1 name + NUL - variable
file 1 name + NUL - variable
file 2 name + NUL - variable
file 2 name + NUL - variable
...
file n name + NUL - variable
file n name + NUL - variable
padding to multiple of 4 bytes - 0 - 3 bytes
file 1 data - variable (padded to 4-byte boundary)
file 2 data - variable (padded to 4-byte boundary)
...
file n data - variable (padded to 4-byte boundary)
/*
** main.c - POSIX 1003.2 "ar" command
**
** This isn't a pure POSIX 1003.2 ar; it only manipulates Metrowerks
** Library files, not general-purpose POSIX 1003.2 format archives.
**
** Dec. 14, 1997 Chris Herborth (chrish@kagi.com)
**
** This code is donated to the PUBLIC DOMAIN. You can use, abuse, modify,
** redistribute, steal, or otherwise manipulate this code. No restrictions
** at all. If you laugh at this code, you can't use it.
**
** This "ar" was implemented using IEEE Std 1003.2-1992 as the basis for
** the interface, and Metrowerk's published docs detailing their library
** format. Look inside for clues about how reality differs from MW's
** documentation on BeOS...
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <getopt.h>
#include "commands.h"
static const char *rcs_version_id = "$Id$";
static const char *ar_version_id = "1.0 " __DATE__;
/* ---------------------------------------------------------------------- */
typedef enum {
delete_cmd,
print_cmd,
replace_cmd,
table_cmd,
extract_cmd,
no_cmd = -1 } command;
/* ----------------------------------------------------------------------
** Prototypes
*/
void usage( void );
void version( void );
void check_command( command *cmd, int arg );
/* ----------------------------------------------------------------------
** Print a usage message and exit.
*/
void usage( void )
{
printf( "ar [dprtx][cuv] archive [file ...]\n" );
exit( EXIT_FAILURE );
}
/* ----------------------------------------------------------------------
** Print a version message and exit.
*/
void version( void )
{
printf( "ar (POSIX 1003.2-1992), version %s\n", ar_version_id );
printf( "by Chris Herborth (chrish@qnx.com)\n" );
printf( "This code has been donated to the BeOS developer community.\n" );
return;
}
/* ----------------------------------------------------------------------
** Set *cmd to the appropriate command enum if it isn't already set.
*/
void check_command( command *cmd, int arg )
{
if( *cmd == no_cmd ) {
switch( arg ) {
case 'd':
*cmd = delete_cmd;
break;
case 'p':
*cmd = print_cmd;
break;
case 'r':
*cmd = replace_cmd;
break;
case 't':
*cmd = table_cmd;
break;
case 'x':
*cmd = extract_cmd;
break;
}
} else {
printf( "ar: you can only specify one command at a time\n" );
usage();
}
}
/* ----------------------------------------------------------------------
** Mainline
*/
int main( int argc, char **argv )
{
command cmd = no_cmd;
int verbose_flag = 0;
int create_flag = 0; /* these two only apply to replace_cmd */
int update_flag = 0;
int c = 0;
char *archive_name;
char **files_list;
int num_files;
int idx;
status_t retval;
/* The argument parsing is a little hairier than usual; the idea is
** to support the POSIX 1003.2 style of arguments, and the much more
** common traditional argument style.
*/
if( argc < 3 ) {
printf( "ar: invalid number of arguments\n" );
usage();
}
/* Do we have traditional or POSIX-style args? */
if( argv[1][0] == '-' ) {
while( ( c = getopt( argc, argv, "dprtxcuvV" ) ) != EOF ) {
switch( c ) {
case 'd': /* fall-through */
case 'p': /* fall-through */
case 'r': /* fall-through */
case 't': /* fall-through */
case 'x': /* fall-through */
check_command( &cmd, c );
break;
case 'v':
verbose_flag = 1;
break;
case 'c':
if( cmd != no_cmd && cmd != replace_cmd ) {
printf( "ar: invalid option, -c\n" );
usage();
} else {
create_flag = 1;
}
break;
case 'u':
if( cmd != no_cmd && cmd != replace_cmd ) {
printf( "ar: invalid option, -u\n" );
usage();
} else {
update_flag = 1;
}
break;
case 'V':
version();
break;
default:
printf( "ar: invalid option, -%c\n", c );
usage();
break;
}
idx = optind;
}
} else {
/* In the traditional way, arguments ar:
**
** argv[1] = [dprtx][cuv]
** argv[2] = archive
** argv[...] = file ...
**/
char *ptr;
idx = 1;
ptr = argv[idx++];
while( *ptr != '\0' ) {
switch( *ptr ) {
case 'd': /* fall-through */
case 'p': /* fall-through */
case 'r': /* fall-through */
case 't': /* fall-through */
case 'x': /* fall-through */
check_command( &cmd, *ptr );
break;
case 'v':
verbose_flag = 1;
break;
case 'c':
if( cmd != no_cmd && cmd != replace_cmd ) {
printf( "ar: invalid option, -c\n" );
usage();
} else {
create_flag = 1;
}
break;
case 'u':
if( cmd != no_cmd && cmd != replace_cmd ) {
printf( "ar: invalid option, -u\n" );
usage();
} else {
update_flag = 1;
}
break;
case 'V':
version();
break;
default:
printf( "ar: invalid option, -%c\n", c );
usage();
break;
}
ptr++;
}
}
/* Next arg is the archive. */
archive_name = argv[idx++];
/* Next are the files. */
num_files = argc - idx;
if( num_files == 0 ) {
files_list = NULL;
} else {
int ctr = 0;
files_list = (char **)malloc( ( num_files + 1 ) * sizeof( char * ) );
while( idx < argc ) {
files_list[ctr++] = argv[idx++];
}
files_list[idx] = NULL;
}
/* Now we can attempt to manipulate the archive. */
switch( cmd ) {
case delete_cmd:
retval = do_delete( archive_name, files_list, verbose_flag );
break;
case print_cmd:
retval = do_print( archive_name, files_list, verbose_flag );
break;
case replace_cmd:
retval = do_replace( archive_name, files_list, verbose_flag,
create_flag, update_flag );
break;
case table_cmd:
retval = do_table( archive_name, files_list, verbose_flag );
break;
case extract_cmd:
retval = do_extract( archive_name, files_list, verbose_flag );
break;
default:
printf( "ar: you must specify a command\n" );
usage();
break;
}
/* Check the return value.
*/
switch( retval ) {
case B_OK:
break;
case B_FILE_NOT_FOUND:
printf( "can't open the file %s\n", archive_name );
return EXIT_FAILURE;
break;
case B_IO_ERROR:
printf( "can't read from %s\n", archive_name );
return EXIT_FAILURE;
break;
case B_BAD_VALUE:
printf( "invalid magic word\n" );
return EXIT_FAILURE;
break;
case B_MISMATCHED_VALUES:
printf( "invalid processor value, or magicflags, or version\n" );
return EXIT_FAILURE;
break;
case B_NO_MEMORY:
printf( "unable to allocate memory\n" );
return EXIT_FAILURE;
break;
case B_ERROR:
printf( "error during processing\n" );
return EXIT_FAILURE;
default:
printf( "unknown error: %ld\n", retval );
return EXIT_FAILURE;
break;
}
return EXIT_SUCCESS;
}
This diff is collapsed.
/*
** mwlib.h - POSIX 1003.2 "ar" command
**
** $Id$
**
** This isn't a pure POSIX 1003.2 ar; it only manipulates Metrowerks
** Library files, not general-purpose POSIX 1003.2 format archives.
**
** Dec. 14, 1997 Chris Herborth (chrish@qnx.com)
**
** This code is donated to the PUBLIC DOMAIN. You can use, abuse, modify,
** redistribute, steal, or otherwise manipulate this code. No restrictions
** at all. If you laugh at this code, you can't use it.
**
** This "ar" was implemented using IEEE Std 1003.2-1992 as the basis for
** the interface, and Metrowerk's published docs detailing their library
** format. Look inside for clues about how reality differs from MW's
** documentation on BeOS...
*/
#include <support/SupportDefs.h>
#include <time.h>
/* ----------------------------------------------------------------------
** Constants
**
*/
#define MWLIB_MAGIC_WORD 'MWOB'
#define MWLIB_MAGIC_PROC 'PPC '
/* ----------------------------------------------------------------------
** Structures
**
** This is based on the "Metrowerks CodeWarrior Library Reference
** Specification", which isn't 100% accurate for BeOS.
*/
typedef struct MWLibHeader {
uint32 magicword;
uint32 magicproc;
uint32 magicflags;
uint32 version;
uint32 code_size;
uint32 data_size;
uint32 num_objects;
} MWLibHeader;
typedef struct MWLibFile {
time_t m_time;
uint32 off_filename;
uint32 off_fullpath;
uint32 off_object;
uint32 object_size;
} MWLibFile;
typedef struct MWLib {
MWLibHeader header;
MWLibFile *files;
char **names;
char **data;
} MWLib;
/* This bears no resemblance to what's in the Metrowerks docs.
**
** Note that this is incomplete; this is all the info I needed for
** ar though.
*/
typedef struct MWObject {
uint32 magic_word; /* 'MWOB' */
uint32 arch; /* 'PPC '; this isn't in the docs */
uint32 version;
uint32 flags;
uint32 code_size;
uint32 data_size;
} MWObject;
/* ----------------------------------------------------------------------
** Function prototypes
**
** load_MW_lib() - load a Metrowerks library
**
** Returns:
** B_OK - all is well
** B_FILE_NOT_FOUND - can't open the given file
** B_IO_ERROR - can't read from the given file
** B_BAD_VALUE - invalid magic word in the file
** B_MISMATCHED_VALUES - invalid processor value (ie, not a PowerPC lib),
** or the magicflags member is not 0, or the file
** version number isn't 1.
** B_NO_MEMORY - unable to allocate memory while loading the lib
**
** write_MW_lib() - write a Metrowerks library
**
** Returns:
** B_OK - all is well
**
** write_MW_lib() - write a Metrowerks library file
**
** Returns:
** B_OK - all is well; doesn't necessarily mean the file was written
** properly, just that you didn't lose any data
** B_NO_MEMORY - unable to allocate offset buffers
** B_ERROR - problem with backup file (can't rename existing file)
**
** Note:
** If you use this in a long-lived program, it leaks memory; the MWLib
** contents are never free()'d.
*/
status_t load_MW_lib( MWLib *lib, const char *filename );
status_t write_MW_lib( MWLib *lib, const char *filename );
void setfiletype( const char *filename, const char *type );
#! /bin/sh
#
# linkcc for Python
# Chris Herborth (chrish@qnx.com)
#
# This is covered by the same copyright/licensing terms as the rest of
# Python.
#
# Shell script to build the Python shared library properly; if we haven't
# already built the export list, we'll need to link twice (argh...) so we
# can eliminate some unwatnted global symbols from the system glue/init
# objects.
#
# This is called by the Modules/Makefile as part of $(LINKCC):
#
# $(LINKCC) $(LDFLAGS) $(LINKFORSHARED) $(MAINOBJ) \
# -L.. -lpython$(VERSION) $(MODLIBS) $(LIBS) $(SYSLIBS) -o python $(LDLAST)
#
# In 1.5.1 this changed to:
#
# $(LINKCC) $(LDFLAGS) $(LINKFORSHARED) $(MAINOBJ) \
# $(LIBRARY) $(MODLIBS) $(LIBS) $(SYSLIBS) -o python $(LDLAST)
#
# For BeOS we should set $(LINKCC) to this in configure (similar to the
# AIX situation):
#
# $(srcdir)../BeOS/linkcc $(LIBRARY) $(PURIFY) $(CC) -nodup $(OPT)
#
# -L.. -lpython$(VERSION) will automagically pick up the shared library.
# Check to make sure we know what we're doing.
system="`uname -m`"
if [ "$system" != "BeMac" ] && [ "$system" != "BeBox" ] ; then
echo "Sorry, BeOS Python doesn't support x86 yet."
exit 1
fi
LIBRARY="$1"; shift
# What we want to end up with.
EXPORTS=${LIBRARY%.a}.exp
DYNAMIC=${LIBRARY%.a}.so
LINK_DYNAMIC="-l`echo ${DYNAMIC%.so} | sed -e s,\\\.\\\./,, -e s,lib,,`"
# Grab the rest of the args and build them into the command used to
# link the python binary. Make sure we link against the shared lib
# and not the static lib.
LINK_CMD=""
while [ "$#" != "0" ] ; do
case "$1" in
$LIBRARY)
LINK_CMD="$LINK_CMD -L.. $LINK_DYNAMIC"
shift
;;
*)
LINK_CMD="$LINK_CMD $1"
shift
;;
esac
done
# The shared libraries and glue objects we need to link against.
LIBS="-lbe -lnet -lroot"
GLUE="/boot/develop/lib/ppc/glue-noinit.a /boot/develop/lib/ppc/init_term_dyn.o"
# Unwanted symbols we need to eliminate; these are regular expressions
# passed to egrep.
SYMS="opterr optind optarg getopt __.* longjmp _.*_"
# Check to see if we've already got an exports file, and delete it if
# it's older than the lib.
if [ -e $EXPORTS ] && [ $LIBRARY -nt $EXPORTS ] ; then
echo "Deleting old exports file for $DYNAMIC..."
rm -f $EXPORTS
fi
if [ ! -e $EXPORTS ] ; then
# First link; create the exports file with the unwanted global symbols
# in it. It's a pity we don't have "nm" or something like that...
rm -f temp-exports.exp
mwcc -xms -f temp-exports.exp -o $DYNAMIC $LIBRARY $GLUE $LIBS -nodup
# Now clean out those bad symbols.
for sym in $SYMS ; do
rm -f temp-exports.exp2
egrep -v "^$sym$" < temp-exports.exp > temp-exports.exp2
mv -f temp-exports.exp2 temp-exports.exp
done
rm -f temp-exports.exp2
mv -f temp-exports.exp $EXPORTS
fi
# Now link against the clean exports file.
mwcc -xms -f $EXPORTS -o $DYNAMIC $LIBRARY $GLUE $LIBS -nodup
# We'll need this or the python binary won't load libpython.so...
( cd .. ; ln -sf `pwd` lib )
# Now build the python binary.
echo "Link command: $LINK_CMD"
$LINK_CMD
#! /bin/sh
#
# linkmodule for Python
# Chris Herborth (chrish@qnx.com)
#
# This is covered by the same copyright/licensing terms as the rest of
# Python
#
# Shell script to build shared library versions of the modules; the
# idea is to build an export list containing only the init*() function
# for the module. We _could_ assume for foomodule.o it was initfoo, but
# that's asking for trouble... this is a little less efficient but correct.
#
# This is called by the Modules/Makefile as $(LDSHARED):
#
# $(LDSHARED) foomodule.o -o foomodule$(SO)
#
# Could also be called as:
#
# $(LDSHARED) readline.o -L/boot/home/config/lib -lreadline -ltermcap \
# -o readline$(SO)
# Check to make sure we know what we're doing.
system="`uname -m`"
if [ "$system" != "BeMac" ] && [ "$system" != "BeBox" ] ; then
echo "Sorry, BeOS Python doesn't support x86 yet."
exit 1
fi
# Make sure we got reasonable arguments.
TARGET=""
ARGS=""
while [ "$#" != "0" ]; do
case "$1" in
-o) TARGET="$2"; shift; shift;;
*) ARGS="$ARGS $1"; shift;;
esac
done
if [ "$TARGET" = "" ] ; then
echo "Usage:"
echo
echo " $0 [args] -o foomodule.so [args] foomodule.o [args]"
echo
echo "Where:"
echo
echo " [args] normal mwcc arguments"
exit 1
fi
EXPORTS=${TARGET%.so}.exp
# The shared libraries and glue objects we need to link against; these
# libs are overkill for most of the standard modules, but it makes life
# in this shell script easier.
LIBS="-L.. -lpython1.5 -lbe -lnet -lroot"
GLUE="/boot/develop/lib/ppc/glue-noinit.a /boot/develop/lib/ppc/init_term_dyn.o"
# Check to see if we've already got an exports file; we don't need to
# update this once we've got it because we only ever want to export
# one symbol.
if [ ! -e $EXPORTS ] ; then
# The init*() function has to be related to the module's .so name
# for importdl to work.
echo init${TARGET%.so} | sed -e s/module// > $EXPORTS
fi
# Now link against the clean exports file.
mwcc -xms -f $EXPORTS -o $TARGET $ARGS $GLUE $LIBS -nodup
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment