Draft of proj2make - BeIDE projects convertion tool

* The proj2make can extract most of data required by makefile-engine powered
  makefiles from the BeIDE project files making porting of the old BeOS
  software projects more easy;
* This tool was implemented during GCI2011 as the "undocumented data format
  investigation task" study work, so please be patient to it's incompleteness
  and not perfect design. Thank you for understanding!

Signed-off-by: Siarzhuk Zharski <[email protected]>
This commit is contained in:
Aleksas Pantechovskis
2012-01-16 23:03:37 +01:00
committed by Siarzhuk Zharski
parent 02085594e6
commit f2b4344867
2 changed files with 450 additions and 0 deletions
+140
View File
@@ -0,0 +1,140 @@
## BeOS Generic Makefile v2.5 ##
## Fill in this file to specify the project being created, and the referenced
## makefile-engine will do all of the hard work for you. This handles both
## Intel and PowerPC builds of the BeOS and Haiku.
## Application Specific Settings ---------------------------------------------
# specify the name of the binary
NAME=proj2make
# specify the type of binary
# APP: Application
# SHARED: Shared library or add-on
# STATIC: Static library archive
# DRIVER: Kernel Driver
TYPE=
# if you plan to use localization features
# specify the application MIME siganture
APP_MIME_SIG=
# add support for new Pe and Eddie features
# to fill in generic makefile
#%{
# @src->@
# specify the source files to use
# full paths or paths relative to the makefile can be included
# all files, regardless of directory, will have their object
# files created in the common object directory.
# Note that this means this makefile will not work correctly
# if two source files with the same name (source.c or source.cpp)
# are included from different directories. Also note that spaces
# in folder names do not work well with this makefile.
SRCS=proj2make.cpp
# specify the resource definition files to use
# full path or a relative path to the resource file can be used.
RDEFS=
# specify the resource files to use.
# full path or a relative path to the resource file can be used.
# both RDEFS and RSRCS can be defined in the same makefile.
RSRCS=
# @<-src@
#%}
# end support for Pe and Eddie
# specify additional libraries to link against
# there are two acceptable forms of library specifications
# - if your library follows the naming pattern of:
# libXXX.so or libXXX.a you can simply specify XXX
# library: libbe.so entry: be
#
# - for version-independent linking of standard C++ libraries please add
# $(STDCPPLIBS) instead of raw "stdc++[.r4] [supc++]" library names
#
# - for localization support add following libs:
# locale localestub
#
# - if your library does not follow the standard library
# naming scheme you need to specify the path to the library
# and it's name
# library: my_lib.a entry: my_lib.a or path/my_lib.a
LIBS=be root $(STDCPPLIBS)
# specify additional paths to directories following the standard
# libXXX.so or libXXX.a naming scheme. You can specify full paths
# or paths relative to the makefile. The paths included may not
# be recursive, so include all of the paths where libraries can
# be found. Directories where source files are found are
# automatically included.
LIBPATHS=
# additional paths to look for system headers
# thes use the form: #include <header>
# source file directories are NOT auto-included here
SYSTEM_INCLUDE_PATHS =
# additional paths to look for local headers
# thes use the form: #include "header"
# source file directories are automatically included
LOCAL_INCLUDE_PATHS =
# specify the level of optimization that you desire
# NONE, SOME, FULL
OPTIMIZE=
# specify here the codes for languages you are going
# to support in this application. The default "en"
# one must be provided too. "make catkeys" will recreate only
# locales/en.catkeys file. Use it as template for creating other
# languages catkeys. All localization files must be placed
# in "locales" sub-directory.
LOCALES=
# specify any preprocessor symbols to be defined. The symbols will not
# have their values set automatically; you must supply the value (if any)
# to use. For example, setting DEFINES to "DEBUG=1" will cause the
# compiler option "-DDEBUG=1" to be used. Setting DEFINES to "DEBUG"
# would pass "-DDEBUG" on the compiler's command line.
DEFINES=
# specify special warning levels
# if unspecified default warnings will be used
# NONE = supress all warnings
# ALL = enable all warnings
WARNINGS =
# specify whether image symbols will be created
# so that stack crawls in the debugger are meaningful
# if TRUE symbols will be created
SYMBOLS = TRUE
# specify debug settings
# if TRUE will allow application to be run from a source-level
# debugger. Note that this will disable all optimzation.
DEBUGGER = TRUE
# specify additional compiler flags for all files
COMPILER_FLAGS =
# specify additional linker flags
LINKER_FLAGS =
# specify the version of this particular item
# (for example, -app 3 4 0 d 0 -short 340 -long "340 "`echo -n -e '\302\251'`"1999 GNU GPL")
# This may also be specified in a resource.
APP_VERSION =
# (for TYPE == DRIVER only) Specify desired location of driver in the /dev
# hierarchy. Used by the driverinstall rule. E.g., DRIVER_PATH = video/usb will
# instruct the driverinstall rule to place a symlink to your driver's binary in
# ~/add-ons/kernel/drivers/dev/video/usb, so that your driver will appear at
# /dev/video/usb when loaded. Default is "misc".
DRIVER_PATH =
## include the makefile-engine
include $(BUILDHOME)/etc/makefile-engine
+310
View File
@@ -0,0 +1,310 @@
/*
* Copyright 2012 Aleksas Pantechovskis, <[email protected]>
* All rights reserved. Distributed under the terms of the MIT License.
*/
#include <exception>
#include <fstream>
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string>
#include <string.h>
#include <ByteOrder.h>
#include <FindDirectory.h>
#include <Path.h>
#include <String.h>
#include <TypeConstants.h>
using namespace std;
const char* kUsageMessage = \
"proj2make usage:\n"
"# proj2make <projPath> [makePath]\n"
"# if makePath parameter doesn't specified makefile will be created in\n"
"# the same directory as .proj file\n"
"# example: proj2make /boot/home/myprog/myprog.proj\n";
fstream gProjFile;
uint32 gProjLength;
uint8* gProjData;
fstream gMakeFile;
fstream gTemplateFile;
string gSPthString;
string gPPthString;
string gFil1String;
string gLinkString;
string gPLnkString;
const char* gAppTypes[] = {
"APP",
"SHARED",
"STAITC",
"DRIVER"
};
uint8 gAppType;
string gAppName;
struct hdr
{
uint32 Id() { return
static_cast<uint32>(B_BENDIAN_TO_HOST_INT32(fId)); }
uint32 Size() { return
static_cast<uint32>(B_BENDIAN_TO_HOST_INT32(fSize)); }
const char* Data() { return (char*)(this + 1); }
private:
uint32 fId;
uint32 fSize;
};
class Error : public std::exception
{
BString fWhat;
public:
Error(const char* what, ...);
virtual ~Error() throw() {}
virtual const char* what() const throw() { return fWhat.String(); }
};
Error::Error(const char* what, ...)
{
const int size = 1024;
va_list args;
va_start(args, what);
vsnprintf(fWhat.LockBuffer(size), size, what, args);
fWhat.UnlockBuffer();
va_end(args);
}
void
CheckFiles(const char* projPath, const char* makePath)
{
gProjFile.open(projPath, fstream::in | fstream::binary);
if (!gProjFile.is_open())
throw Error("%s not found", projPath);
gProjFile.seekg(0, ios::end);
uint32 projFileLength = gProjFile.tellg();
gProjFile.seekg(0, ios::beg);
char* name = new char[5];
gProjFile.read(name, 4);
uint32 length;
gProjFile.read((char*)&length, 4);
name[4] = '\0';
length = static_cast<uint32>(B_BENDIAN_TO_HOST_INT32(length));
gProjLength = length + 8;
if (strcmp(name, "MIDE") != 0 || gProjLength > projFileLength)
throw Error("File corrupted or it is not BeIDE *.proj file");
gMakeFile.open(makePath, fstream::in);
if (gMakeFile.is_open())
throw Error("%s already exists", makePath);
gMakeFile.open(makePath, fstream::out);
if (!gMakeFile.is_open())
throw Error("Can not create makefile");
BPath templateFileName;
// not supporter yet in my haiku rev
// find_directory(B_SYSTEM_DEVELOP_DIR, &templateFileName);
// templateFileName.Append("etc/makefile");
templateFileName.SetTo("/boot/develop/etc/makefile");
gTemplateFile.open(templateFileName.Path(), fstream::in);
if (!gTemplateFile.is_open())
throw Error("Can not open template %s", templateFileName.Path());
}
void
ParseGenB(hdr* data)
{
hdr* child = (hdr*)data->Data();
char* name = (char*)(child + 1);
int len = strlen(name) + 1;
uint32 u = child->Id();
char* c = (char*)&u;
printf("\t%c%c%c%c:%d:%s\n", c[3], c[2], c[1], c[0], child->Size(), name);
if (strncmp(name, "ProjectPrefsx86", len - 1) == 0) {
const char* type = child->Data() + len + 8;
if (*type <= 3)
gAppType = *type;
type++;
type += 64; // skip the mime type name
gAppName = type;
}
}
class _l {
static string _s;
public:
_l() { _s += " " ; }
~_l() { _s.resize(_s.size() - 1); }
char* str() { _s.c_str(); }
};
string _l::_s;
void
Parse(hdr* current, hdr* parent)
{
_l l;
uint32 u = current->Id();
char* c = (char*)&u;
printf("%#06x:%s%c%c%c%c:%d\n",
(uint8*)current - gProjData, l.str(),
c[3], c[2], c[1], c[0], current->Size());
bool useGrandParent = false;
size_t off = 0;
switch(current->Id()) {
case 'Fil1':
case 'Link':
case 'PLnk':
off = 24;
break;
case 'MIDE':
case 'DPrf':
case 'GPrf':
break;
case 'MSFl':
off = 8;
useGrandParent = true;
break;
case 'SPth':
gSPthString += " \\\n\t";
gSPthString += &current->Data()[5];
return;
case 'PPth':
gPPthString += " \\\n\t";
gPPthString += &current->Data()[5];
return;
case 'Name':
if (parent->Id() == 'Fil1') {
gFil1String += " \\\n\t";
gFil1String += &current->Data()[4];
} else if (parent->Id() == 'Link') {
gLinkString += " \\\n\t";
gLinkString += &current->Data()[4];
} else if (parent->Id() == 'PLnk') {
gPLnkString += " \\\n\t";
gPLnkString += &current->Data()[4];
}
return;
case 'GenB':
ParseGenB(current);
return;
default:
return;
}
hdr* child = (hdr*)(current->Data() + off);
while (off < current->Size()) {
Parse(child, useGrandParent ? parent : current);
off += child->Size() + sizeof(hdr);
child = (hdr*)(child->Data() + child->Size());
}
}
void
ReadProj()
{
gProjFile.seekg(0, ios::beg);
gProjData = new uint8[gProjLength];
gProjFile.read((char*)gProjData, gProjLength);
gProjFile.close();
Parse((hdr*)gProjData, NULL);
}
void
Proj2Make()
{
gFil1String = " ";
gLinkString = " ";
gPLnkString = " ";
gSPthString = " ";
gPPthString = " ";
ReadProj();
string str;
while (gTemplateFile.good()) {
getline(gTemplateFile, str);
if (str.find("SRCS") == 0)
str = str + gFil1String;
else if (str.find("LIBS") == 0)
str = str + gLinkString;
else if (str.find("SYSTEM_INCLUDE_PATHS") == 0)
str = str + gSPthString;
else if (str.find("LOCAL_INCLUDE_PATHS") == 0)
str = str + gPPthString;
else if (str.find("TYPE") == 0)
str = str + gAppTypes[gAppType];
else if (str.find("NAME") == 0)
str = str + gAppName;
else if (str.find("RSRCS") == 0)
str = str + gPLnkString;
gMakeFile << str << endl;
}
gMakeFile.close();
gTemplateFile.close();
}
int
main(int argc, char** argv)
{
try {
if (argc <= 1 || (argc > 1 && strcmp(argv[1], "--help") == 0))
throw Error("");
BString projPath = argv[1];
BString makePath;
// if makefile path specified
if (argc > 2)
makePath = argv[2];
// default makefile path
else {
BPath path(argv[1]);
path.GetParent(&path);
path.Append("makefile");
makePath = path.Path();
}
CheckFiles(projPath.String(), makePath.String());
Proj2Make();
} catch(exception& exc) {
cerr << argv[0] << " : " << exc.what() << endl;
cerr << kUsageMessage;
return B_ERROR;
}
return B_OK;
}