Had to change the mechanism for automatically generating most of the
boring syscall stuff. It has two phases now: The first one (gensyscallinfos) parses syscalls.h and generates a source file containing all the required information. This file is compiled and linked to gensyscalls, which generates the actual output files. Added to the build. git-svn-id: file:///srv/svn/repos/haiku/trunk/current@8697 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
cc868bc230
commit
efd87ab8df
|
@ -2,6 +2,7 @@ SubDir OBOS_TOP src tools ;
|
|||
|
||||
SubInclude OBOS_TOP src tools cppunit ;
|
||||
SubInclude OBOS_TOP src tools elfsymbolpatcher ;
|
||||
SubInclude OBOS_TOP src tools gensyscalls ;
|
||||
SubInclude OBOS_TOP src tools hey ;
|
||||
SubInclude OBOS_TOP src tools rc ;
|
||||
SubInclude OBOS_TOP src tools translation ;
|
||||
|
|
|
@ -1,4 +1,111 @@
|
|||
SubDir OBOS_TOP src tools gensyscalls ;
|
||||
|
||||
BuildPlatformMain gensyscalls : gensyscalls.cpp ;
|
||||
# build gensyscallinfos
|
||||
|
||||
BuildPlatformMain gensyscallinfos : gensyscallinfos.cpp ;
|
||||
LinkSharedOSLibs gensyscallinfos : stdc++.r4 ;
|
||||
|
||||
|
||||
# generate the syscall infos source file
|
||||
|
||||
SetupObjectsDir ;
|
||||
|
||||
local syscallsHeader = [ FGristFiles syscalls.h ] ;
|
||||
SEARCH on $(syscallsHeader) = [ FDirName $(OBOS_TOP) headers private kernel ] ;
|
||||
|
||||
local syscallsHeaderPP = [ FGristFiles syscalls.h.pp ] ;
|
||||
LOCATE on $(syscallsHeaderPP) = $(LOCATE_SOURCE) ;
|
||||
|
||||
local syscallInfos = [ FGristFiles gensyscalls_infos.c ] ;
|
||||
LOCATE on $(syscallInfos) = $(LOCATE_SOURCE) ;
|
||||
|
||||
rule GenSyscallInfos {
|
||||
Depends $(1) : gensyscallinfos $(2) ;
|
||||
GenSyscallInfos1 $(1) : gensyscallinfos $(2) ;
|
||||
}
|
||||
|
||||
actions GenSyscallInfos1 {
|
||||
$(2[1]) $(2[2]) $(1)
|
||||
}
|
||||
|
||||
GenSyscallInfos $(syscallInfos) : $(syscallsHeaderPP) ;
|
||||
|
||||
|
||||
# build gensyscalls
|
||||
|
||||
BuildPlatformMain gensyscalls : gensyscalls.cpp $(syscallInfos:S=$(SUFOBJ)) ;
|
||||
LinkSharedOSLibs gensyscalls : stdc++.r4 ;
|
||||
|
||||
|
||||
# generate the output files
|
||||
|
||||
# place them where there are needed
|
||||
local syscallFiles = <syscalls>syscalls.S.inc <syscalls>syscall_dispatcher.h ;
|
||||
MakeLocate <syscalls>syscalls.S.inc : [ FObjectsDir src kernel libroot os ] ;
|
||||
MakeLocate <syscalls>syscall_dispatcher.h : [ FObjectsDir src kernel core ] ;
|
||||
#Depends <syscalls>generatedFiles : $(syscallFiles) ;
|
||||
#NotFile <syscalls>generatedFiles ;
|
||||
|
||||
Depends <dir>objects/x86.R1/kernel/core : <dir>objects/x86.R1/kernel ;
|
||||
|
||||
rule GenSyscallsFile {
|
||||
Depends $(1) : gensyscalls ;
|
||||
GenSyscallsFile1 $(1) : gensyscalls ;
|
||||
}
|
||||
|
||||
actions GenSyscallsFile1 {
|
||||
$(2[1]) -c $(1)
|
||||
}
|
||||
|
||||
rule GenSyscallsDispatcher {
|
||||
Depends $(1) : gensyscalls ;
|
||||
GenSyscallsDispatcher1 $(1) : gensyscalls ;
|
||||
}
|
||||
|
||||
actions GenSyscallsDispatcher1 {
|
||||
$(2[1]) -d $(1)
|
||||
}
|
||||
|
||||
#GenSyscalls $(syscallFiles) ;
|
||||
GenSyscallsFile <syscalls>syscalls.S.inc ;
|
||||
GenSyscallsDispatcher <syscalls>syscall_dispatcher.h ;
|
||||
|
||||
|
||||
# preprocess the syscalls header
|
||||
|
||||
SetupIncludes ;
|
||||
UsePrivateHeaders kernel ;
|
||||
UseArchHeaders $(OBOS_ARCH) ;
|
||||
|
||||
rule Preprocess
|
||||
{
|
||||
Depends $(<) : $(>) ;
|
||||
|
||||
HDRS on $(<) = $(SEARCH_SOURCE) $(SUBDIRHDRS) $(HDRS) ;
|
||||
HDRRULE on $(>) = HdrRule ;
|
||||
HDRSCAN on $(>) = $(HDRPATTERN) ;
|
||||
HDRSEARCH on $(>) =
|
||||
$(SEARCH_SOURCE:E) $(SUBDIRHDRS) $(HDRS) $(STDHDRS) ;
|
||||
|
||||
HDRGRIST on $(>) = $(HDRGRIST) ;
|
||||
|
||||
DEFINES on $(<) += $(DEFINES) ;
|
||||
|
||||
CCFLAGS on $(<) += $(CCFLAGS) $(SUBDIRCCFLAGS) $(OPTIM)
|
||||
[ FDefines GEN_SYSCALL_INFOS_PROCESSING ] ;
|
||||
|
||||
CCHDRS on $(<) = [ on $(<) FIncludes $(HDRS) ] ;
|
||||
CCDEFS on $(<) = [ on $(<) FDefines $(DEFINES) ] ;
|
||||
}
|
||||
|
||||
actions Preprocess
|
||||
{
|
||||
$(CC) -E "$(2)" $(CCFLAGS) $(CCDEFS) $(CCHDRS) -o "$(1)" ;
|
||||
}
|
||||
|
||||
Preprocess $(syscallsHeaderPP) : $(syscallsHeader) ;
|
||||
|
||||
|
||||
# compile the syscall infos source file
|
||||
|
||||
Object $(syscallInfos:S=$(SUFOBJ)) : $(syscallInfos) ;
|
||||
|
|
|
@ -0,0 +1,521 @@
|
|||
// gensyscallinfos.cpp
|
||||
//
|
||||
// Copyright (c) 2004, Ingo Weinhold <bonefish@cs.tu-berlin.de>
|
||||
// All rights reserved. Distributed under the terms of the OpenBeOS License.
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <fstream>
|
||||
#include <list>
|
||||
#include <stack>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "gensyscalls_common.h"
|
||||
|
||||
// usage
|
||||
const char *kUsage =
|
||||
"Usage: gensyscallinfos <header> <calls> <dispatcher>\n"
|
||||
"\n"
|
||||
"Given the (preprocessed) header file that defines the syscall prototypes the\n"
|
||||
"command generates a source file consisting of syscall infos, which is needed\n"
|
||||
"to build gensyscalls, which in turn generates the assembly syscall\n"
|
||||
"definitions and code for the kernelland syscall dispatcher.\n"
|
||||
"\n"
|
||||
" <header> - Input: The preprocessed header file with the\n"
|
||||
" syscall prototypes.\n"
|
||||
" <syscall infos> - Output: The syscall infos source file needed to\n"
|
||||
" build gensyscalls.";
|
||||
|
||||
// print_usage
|
||||
static
|
||||
void
|
||||
print_usage(bool error)
|
||||
{
|
||||
fprintf((error ? stderr : stdout), kUsage);
|
||||
}
|
||||
|
||||
// Type
|
||||
struct Type {
|
||||
Type(const char *type) : type(type) {}
|
||||
Type(const string &type) : type(type) {}
|
||||
|
||||
string type;
|
||||
};
|
||||
|
||||
// Function
|
||||
class Function {
|
||||
public:
|
||||
Function() : fReturnType("") {}
|
||||
|
||||
void SetName(const string &name)
|
||||
{
|
||||
fName = name;
|
||||
}
|
||||
|
||||
const string &GetName() const
|
||||
{
|
||||
return fName;
|
||||
}
|
||||
|
||||
void AddParameter(const Type &type)
|
||||
{
|
||||
fParameters.push_back(type);
|
||||
}
|
||||
|
||||
int CountParameters() const
|
||||
{
|
||||
return fParameters.size();
|
||||
}
|
||||
|
||||
const Type &ParameterAt(int index) const
|
||||
{
|
||||
return fParameters[index];
|
||||
}
|
||||
|
||||
void SetReturnType(const Type &type)
|
||||
{
|
||||
fReturnType = type;
|
||||
}
|
||||
|
||||
const Type &GetReturnType() const
|
||||
{
|
||||
return fReturnType;
|
||||
}
|
||||
|
||||
protected:
|
||||
string fName;
|
||||
vector<Type> fParameters;
|
||||
Type fReturnType;
|
||||
};
|
||||
|
||||
// Syscall
|
||||
class Syscall : public Function {
|
||||
public:
|
||||
string GetKernelName() const
|
||||
{
|
||||
int baseIndex = 0;
|
||||
if (fName.find("_kern_") == 0)
|
||||
baseIndex = strlen("_kern_");
|
||||
else if (fName.find("sys_") == 0)
|
||||
baseIndex = strlen("sys_");
|
||||
string kernelName("_user_");
|
||||
kernelName.append(string(fName, baseIndex));
|
||||
return kernelName;
|
||||
}
|
||||
};
|
||||
|
||||
// Tokenizer
|
||||
class Tokenizer {
|
||||
public:
|
||||
Tokenizer(istream &input)
|
||||
: fInput(input),
|
||||
fHasCurrent(false)
|
||||
{
|
||||
}
|
||||
|
||||
string GetCurrentToken()
|
||||
{
|
||||
if (!fHasCurrent)
|
||||
throw Exception("GetCurrentToken(): No current token!");
|
||||
return fTokens.front();
|
||||
}
|
||||
|
||||
string GetNextToken()
|
||||
{
|
||||
return GetNextToken(NULL);
|
||||
}
|
||||
|
||||
string GetNextToken(stack<string> &skippedTokens)
|
||||
{
|
||||
return GetNextToken(&skippedTokens);
|
||||
}
|
||||
|
||||
string GetNextToken(stack<string> *skippedTokens)
|
||||
{
|
||||
if (fHasCurrent) {
|
||||
fTokens.pop_front();
|
||||
fHasCurrent = false;
|
||||
}
|
||||
while (fTokens.empty())
|
||||
_ReadLine();
|
||||
fHasCurrent = true;
|
||||
if (skippedTokens)
|
||||
skippedTokens->push(fTokens.front());
|
||||
return fTokens.front();
|
||||
}
|
||||
|
||||
void ExpectToken(const string &expectedToken)
|
||||
{
|
||||
string token = GetCurrentToken();
|
||||
if (expectedToken != token) {
|
||||
throw ParseException(string("Unexpected token `") + token
|
||||
+ "'. Expected was `" + expectedToken + "'.");
|
||||
}
|
||||
}
|
||||
|
||||
void ExpectNextToken(const string &expectedToken)
|
||||
{
|
||||
GetNextToken();
|
||||
ExpectToken(expectedToken);
|
||||
}
|
||||
|
||||
bool CheckToken(const string &expectedToken)
|
||||
{
|
||||
string token = GetCurrentToken();
|
||||
return (expectedToken == token);
|
||||
}
|
||||
|
||||
bool CheckNextToken(const string &expectedToken)
|
||||
{
|
||||
GetNextToken();
|
||||
bool result = CheckToken(expectedToken);
|
||||
if (!result)
|
||||
PutCurrentToken();
|
||||
return result;
|
||||
}
|
||||
|
||||
void PutCurrentToken()
|
||||
{
|
||||
if (!fHasCurrent)
|
||||
throw Exception("GetCurrentToken(): No current token!");
|
||||
fHasCurrent = false;
|
||||
}
|
||||
|
||||
void PutToken(string token)
|
||||
{
|
||||
if (fHasCurrent) {
|
||||
fTokens.pop_front();
|
||||
fHasCurrent = false;
|
||||
}
|
||||
fTokens.push_front(token);
|
||||
}
|
||||
|
||||
void PutTokens(stack<string> &tokens)
|
||||
{
|
||||
if (fHasCurrent) {
|
||||
fTokens.pop_front();
|
||||
fHasCurrent = false;
|
||||
}
|
||||
while (!tokens.empty()) {
|
||||
fTokens.push_front(tokens.top());
|
||||
tokens.pop();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
void _ReadLine()
|
||||
{
|
||||
// read the line
|
||||
char buffer[10240];
|
||||
if (!fInput.getline(buffer, sizeof(buffer)))
|
||||
throw EOFException("Unexpected end of input.");
|
||||
// parse it
|
||||
int len = strlen(buffer);
|
||||
int tokenStart = 0;
|
||||
for (int i = 0; i < len; i++) {
|
||||
char c = buffer[i];
|
||||
if (isspace(c)) {
|
||||
if (tokenStart < i)
|
||||
fTokens.push_back(string(buffer + tokenStart, buffer + i));
|
||||
tokenStart = i + 1;
|
||||
continue;
|
||||
}
|
||||
switch (buffer[i]) {
|
||||
case '#':
|
||||
case '(':
|
||||
case ')':
|
||||
case '*':
|
||||
case '&':
|
||||
case '[':
|
||||
case ']':
|
||||
case ';':
|
||||
case ',':
|
||||
if (tokenStart < i) {
|
||||
fTokens.push_back(string(buffer + tokenStart,
|
||||
buffer + i));
|
||||
}
|
||||
fTokens.push_back(string(buffer + i, buffer + i + 1));
|
||||
tokenStart = i + 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (tokenStart < len)
|
||||
fTokens.push_back(string(buffer + tokenStart, buffer + len));
|
||||
}
|
||||
|
||||
private:
|
||||
istream &fInput;
|
||||
list<string> fTokens;
|
||||
bool fHasCurrent;
|
||||
};
|
||||
|
||||
|
||||
// Main
|
||||
class Main {
|
||||
public:
|
||||
|
||||
int Run(int argc, char **argv)
|
||||
{
|
||||
// parse parameters
|
||||
if (argc >= 2
|
||||
&& (string(argv[1]) == "-h" || string(argv[1]) == "--help")) {
|
||||
print_usage(false);
|
||||
return 0;
|
||||
}
|
||||
if (argc != 3) {
|
||||
print_usage(true);
|
||||
return 1;
|
||||
}
|
||||
_ParseSyscalls(argv[1]);
|
||||
_WriteSyscallInfoFile(argv[2]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
void _ParseSyscalls(const char *filename)
|
||||
{
|
||||
// open the input file
|
||||
ifstream file(filename, ifstream::in);
|
||||
if (!file.is_open())
|
||||
throw new IOException(string("Failed to open `") + filename + "'.");
|
||||
// parse the syscalls
|
||||
Tokenizer tokenizer(file);
|
||||
// find "#pragma syscalls begin"
|
||||
while (true) {
|
||||
while (tokenizer.GetNextToken() != "#");
|
||||
stack<string> skippedTokens;
|
||||
if (tokenizer.GetNextToken(skippedTokens) == "pragma"
|
||||
&& tokenizer.GetNextToken(skippedTokens) == "syscalls"
|
||||
&& tokenizer.GetNextToken(skippedTokens) == "begin") {
|
||||
break;
|
||||
}
|
||||
tokenizer.PutTokens(skippedTokens);
|
||||
}
|
||||
// parse the functions
|
||||
while (!tokenizer.CheckNextToken("#")) {
|
||||
Syscall syscall;
|
||||
_ParseSyscall(tokenizer, syscall);
|
||||
fSyscalls.push_back(syscall);
|
||||
}
|
||||
// expect "pragma syscalls end"
|
||||
tokenizer.ExpectNextToken("pragma");
|
||||
tokenizer.ExpectNextToken("syscalls");
|
||||
tokenizer.ExpectNextToken("end");
|
||||
|
||||
// for (int i = 0; i < (int)fSyscalls.size(); i++) {
|
||||
// const Syscall &syscall = fSyscalls[i];
|
||||
// printf("syscall: `%s'\n", syscall.GetName().c_str());
|
||||
// for (int k = 0; k < (int)syscall.CountParameters(); k++)
|
||||
// printf(" arg: `%s'\n", syscall.ParameterAt(k).type.c_str());
|
||||
// printf(" return type: `%s'\n",
|
||||
// syscall.GetReturnType().type.c_str());
|
||||
// }
|
||||
// printf("Found %lu syscalls.\n", fSyscalls.size());
|
||||
}
|
||||
|
||||
void _WriteSyscallInfoFile(const char *filename)
|
||||
{
|
||||
// open the syscall info file
|
||||
ofstream file(filename, ofstream::out | ofstream::trunc);
|
||||
if (!file.is_open())
|
||||
throw new IOException(string("Failed to open `") + filename + "'.");
|
||||
// write preamble
|
||||
file << "#include \"gensyscalls.h\"" << endl;
|
||||
file << "#include \"syscalls.h\"" << endl;
|
||||
file << endl;
|
||||
// output the case statements
|
||||
for (int i = 0; i < (int)fSyscalls.size(); i++) {
|
||||
const Syscall &syscall = fSyscalls[i];
|
||||
string name = string("gensyscall_") + syscall.GetName();
|
||||
string paramInfoName = name + "_parameter_info";
|
||||
int paramCount = syscall.CountParameters();
|
||||
// write the parameter infos
|
||||
file << "static gensyscall_parameter_info " << paramInfoName
|
||||
<< "[] = {" << endl;
|
||||
for (int k = 0; k < paramCount; k++) {
|
||||
file << "\t{ \"" << syscall.ParameterAt(k).type << "\", 0, "
|
||||
<< "sizeof(" << syscall.ParameterAt(k).type << "), 0 },"
|
||||
<< endl;
|
||||
}
|
||||
file << "};" << endl;
|
||||
file << endl;
|
||||
// write the initialization function
|
||||
file << "static void " << name << "(";
|
||||
for (int k = 0; k < paramCount; k++) {
|
||||
if (k > 0)
|
||||
file << ", ";
|
||||
string type = syscall.ParameterAt(k).type;
|
||||
string::size_type pos = type.find(")");
|
||||
if (pos == string::npos) {
|
||||
file << type << " arg" << k;
|
||||
} else {
|
||||
// function pointer
|
||||
file << string(type, 0, pos) << " arg" << k
|
||||
<< string(type, pos, type.length() - pos);
|
||||
}
|
||||
}
|
||||
if (paramCount > 0)
|
||||
file << ", ";
|
||||
file << "int arg" << paramCount << ") {" << endl;
|
||||
for (int k = 0; k < paramCount; k++) {
|
||||
file << "\t" << paramInfoName << "[" << k << "].offset = "
|
||||
<< "(char*)&arg" << k << " - (char*)&arg0;" << endl;
|
||||
file << "\t" << paramInfoName << "[" << k << "].actual_size = "
|
||||
<< "(char*)&arg" << (k + 1) << " - (char*)&arg" << k << ";"
|
||||
<< endl;
|
||||
}
|
||||
file << "}" << endl;
|
||||
file << endl;
|
||||
}
|
||||
// write the syscall infos
|
||||
file << "static gensyscall_syscall_info "
|
||||
"gensyscall_syscall_infos[] = {" << endl;
|
||||
for (int i = 0; i < (int)fSyscalls.size(); i++) {
|
||||
const Syscall &syscall = fSyscalls[i];
|
||||
string name = string("gensyscall_") + syscall.GetName();
|
||||
string paramInfoName = name + "_parameter_info";
|
||||
file << "\t{ \"" << syscall.GetName() << "\", "
|
||||
<< "\"" << syscall.GetKernelName() << "\", "
|
||||
<< "\"" << syscall.GetReturnType().type << "\", "
|
||||
<< syscall.CountParameters() << ", "
|
||||
<< paramInfoName << " }," << endl;
|
||||
}
|
||||
file << "};" << endl;
|
||||
file << endl;
|
||||
// write the initialization function
|
||||
file << "gensyscall_syscall_info *gensyscall_get_infos(int *count);";
|
||||
file << "gensyscall_syscall_info *gensyscall_get_infos(int *count) {"
|
||||
<< endl;
|
||||
for (int i = 0; i < (int)fSyscalls.size(); i++) {
|
||||
const Syscall &syscall = fSyscalls[i];
|
||||
string name = string("gensyscall_") + syscall.GetName();
|
||||
file << "\t" << name << "(";
|
||||
int paramCount = syscall.CountParameters();
|
||||
// write the dummy parameters
|
||||
for (int k = 0; k < paramCount; k++)
|
||||
file << "(" << syscall.ParameterAt(k).type << ")0, ";
|
||||
file << "0);" << endl;
|
||||
}
|
||||
file << "\t*count = " << fSyscalls.size() << ";" << endl;
|
||||
file << "\treturn gensyscall_syscall_infos;" << endl;
|
||||
file << "}" << endl;
|
||||
}
|
||||
|
||||
void _ParseSyscall(Tokenizer &tokenizer, Syscall &syscall)
|
||||
{
|
||||
// get return type and function name
|
||||
vector<string> returnType;
|
||||
while (tokenizer.GetNextToken() != "(") {
|
||||
string token = tokenizer.GetCurrentToken();
|
||||
// strip leading "extern"
|
||||
if (!returnType.empty() || token != "extern")
|
||||
returnType.push_back(token);
|
||||
}
|
||||
if (returnType.size() < 2) {
|
||||
throw ParseException("Error while parsing function "
|
||||
"return type.");
|
||||
}
|
||||
syscall.SetName(returnType[returnType.size() - 1]);
|
||||
returnType.pop_back();
|
||||
string returnTypeString(returnType[0]);
|
||||
for (int i = 1; i < (int)returnType.size(); i++) {
|
||||
returnTypeString += " ";
|
||||
returnTypeString += returnType[i];
|
||||
}
|
||||
syscall.SetReturnType(returnTypeString);
|
||||
// get arguments
|
||||
if (!tokenizer.CheckNextToken(")")) {
|
||||
_ParseParameter(tokenizer, syscall);
|
||||
while (!tokenizer.CheckNextToken(")")) {
|
||||
tokenizer.ExpectNextToken(",");
|
||||
_ParseParameter(tokenizer, syscall);
|
||||
}
|
||||
}
|
||||
tokenizer.ExpectNextToken(";");
|
||||
}
|
||||
|
||||
void _ParseParameter(Tokenizer &tokenizer, Syscall &syscall)
|
||||
{
|
||||
vector<string> type;
|
||||
while (tokenizer.GetNextToken() != ")"
|
||||
&& tokenizer.GetCurrentToken() != ",") {
|
||||
string token = tokenizer.GetCurrentToken();
|
||||
type.push_back(token);
|
||||
if (token == "(") {
|
||||
// This must be a function pointer. We deal with that in a
|
||||
// separate method.
|
||||
_ParseFunctionPointerParameter(tokenizer, syscall, type);
|
||||
return;
|
||||
}
|
||||
}
|
||||
tokenizer.PutCurrentToken();
|
||||
if (type.size() < 2) {
|
||||
if (type.size() == 1 && type[0] == "void") {
|
||||
// that's OK
|
||||
return;
|
||||
}
|
||||
throw ParseException("Error while parsing function "
|
||||
"parameter.");
|
||||
}
|
||||
type.pop_back(); // last component is the parameter name
|
||||
string typeString(type[0]);
|
||||
for (int i = 1; i < (int)type.size(); i++) {
|
||||
typeString += " ";
|
||||
typeString += type[i];
|
||||
}
|
||||
syscall.AddParameter(typeString);
|
||||
}
|
||||
|
||||
void _ParseFunctionPointerParameter(Tokenizer &tokenizer, Syscall &syscall,
|
||||
vector<string> &type)
|
||||
{
|
||||
// When this method is entered, the return type and the opening
|
||||
// parenthesis must already be parse and stored in the supplied type
|
||||
// vector.
|
||||
if (type.size() < 2) {
|
||||
throw ParseException("Error parsing function parameter. "
|
||||
"No return type.");
|
||||
}
|
||||
// read all the "*"s there are
|
||||
while (tokenizer.CheckNextToken("*"))
|
||||
type.push_back("*");
|
||||
// now comes the parameter name, if specified -- skip it
|
||||
if (!tokenizer.CheckNextToken(")")) {
|
||||
tokenizer.GetNextToken();
|
||||
tokenizer.ExpectNextToken(")");
|
||||
}
|
||||
type.push_back(")");
|
||||
// the function parameters
|
||||
tokenizer.ExpectNextToken("(");
|
||||
type.push_back("(");
|
||||
while (!tokenizer.CheckNextToken(")"))
|
||||
type.push_back(tokenizer.GetNextToken());
|
||||
type.push_back(")");
|
||||
// compose the type string and add it to the syscall parameters
|
||||
string typeString(type[0]);
|
||||
for (int i = 1; i < (int)type.size(); i++) {
|
||||
typeString += " ";
|
||||
typeString += type[i];
|
||||
}
|
||||
syscall.AddParameter(typeString);
|
||||
}
|
||||
|
||||
private:
|
||||
vector<Syscall> fSyscalls;
|
||||
};
|
||||
|
||||
|
||||
// main
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
try {
|
||||
return Main().Run(argc, argv);
|
||||
} catch (Exception &exception) {
|
||||
fprintf(stderr, "%s\n", exception.what());
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,29 +1,24 @@
|
|||
// gensyscalls.cpp
|
||||
//
|
||||
// Copyright (c) 2004, Ingo Weinhold <bonefish@cs.tu-berlin.de>
|
||||
// All rights reserved. Distributed under the terms of the OpenBeOS License.
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <fstream>
|
||||
#include <list>
|
||||
#include <stack>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "gensyscalls.h"
|
||||
#include "gensyscalls_common.h"
|
||||
|
||||
extern "C" gensyscall_syscall_info *gensyscall_get_infos(int *count);
|
||||
|
||||
// usage
|
||||
const char *kUsage =
|
||||
"Usage: gensyscalls <header> <calls> <dispatcher>\n"
|
||||
"Usage: gensyscalls [ -c <calls> ] [ -d <dispatcher> ]\n"
|
||||
"\n"
|
||||
"Given the (preprocessed) header file that defines the syscall prototypes the\n"
|
||||
"command generates a piece of assembly source file that defines the actual\n"
|
||||
"syscalls and a piece of C source (cases of a switch statement) for the \n"
|
||||
"kernel syscall dispatcher. Either file is to be included from a respective\n"
|
||||
"skeleton source file.\n"
|
||||
"The command generates a piece of assembly source file that defines the\n"
|
||||
"actual syscalls and a piece of C source (cases of a switch statement) for"
|
||||
"the kernel syscall dispatcher. Either file is to be included from a"
|
||||
"respective skeleton source file.\n"
|
||||
"\n"
|
||||
" <header> - Input: The preprocessed header file with the\n"
|
||||
" syscall prototypes.\n"
|
||||
" <calls> - Output: The assembly source file implementing the\n"
|
||||
" actual syscalls."
|
||||
" <dispatcher> - Output: The C source file to be included by the\n"
|
||||
|
@ -37,343 +32,68 @@ print_usage(bool error)
|
|||
fprintf((error ? stderr : stdout), kUsage);
|
||||
}
|
||||
|
||||
// Type
|
||||
struct Type {
|
||||
Type(const char *type) : type(type) {}
|
||||
Type(const string &type) : type(type) {}
|
||||
|
||||
string type;
|
||||
};
|
||||
|
||||
// Function
|
||||
class Function {
|
||||
public:
|
||||
Function() : fReturnType("") {}
|
||||
|
||||
void SetName(const string &name)
|
||||
{
|
||||
fName = name;
|
||||
}
|
||||
|
||||
const string &GetName() const
|
||||
{
|
||||
return fName;
|
||||
}
|
||||
|
||||
void AddParameter(const Type &type)
|
||||
{
|
||||
fParameters.push_back(type);
|
||||
}
|
||||
|
||||
int CountParameters() const
|
||||
{
|
||||
return fParameters.size();
|
||||
}
|
||||
|
||||
const Type &ParameterAt(int index) const
|
||||
{
|
||||
return fParameters[index];
|
||||
}
|
||||
|
||||
void SetReturnType(const Type &type)
|
||||
{
|
||||
fReturnType = type;
|
||||
}
|
||||
|
||||
const Type &GetReturnType() const
|
||||
{
|
||||
return fReturnType;
|
||||
}
|
||||
|
||||
protected:
|
||||
string fName;
|
||||
vector<Type> fParameters;
|
||||
Type fReturnType;
|
||||
};
|
||||
|
||||
// Syscall
|
||||
class Syscall : public Function {
|
||||
public:
|
||||
string GetKernelName() const
|
||||
{
|
||||
int baseIndex = 0;
|
||||
if (fName.find("_kern_") == 0)
|
||||
baseIndex = strlen("_kern_");
|
||||
else if (fName.find("sys_") == 0)
|
||||
baseIndex = strlen("sys_");
|
||||
string kernelName("_user_");
|
||||
kernelName.append(string(fName, baseIndex));
|
||||
return kernelName;
|
||||
}
|
||||
};
|
||||
|
||||
// Exception
|
||||
struct Exception : exception {
|
||||
Exception()
|
||||
: fMessage()
|
||||
{
|
||||
}
|
||||
|
||||
Exception(const string &message)
|
||||
: fMessage(message)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~Exception() {}
|
||||
|
||||
virtual const char *what() const
|
||||
{
|
||||
return fMessage.c_str();
|
||||
}
|
||||
|
||||
private:
|
||||
string fMessage;
|
||||
};
|
||||
|
||||
// EOFException
|
||||
struct EOFException : public Exception {
|
||||
EOFException() {}
|
||||
EOFException(const string &message) : Exception(message) {}
|
||||
virtual ~EOFException() {}
|
||||
};
|
||||
|
||||
// IOException
|
||||
struct IOException : public Exception {
|
||||
IOException() {}
|
||||
IOException(const string &message) : Exception(message) {}
|
||||
virtual ~IOException() {}
|
||||
};
|
||||
|
||||
// ParseException
|
||||
struct ParseException : public Exception {
|
||||
ParseException() {}
|
||||
ParseException(const string &message) : Exception(message) {}
|
||||
virtual ~ParseException() {}
|
||||
};
|
||||
|
||||
|
||||
// Tokenizer
|
||||
class Tokenizer {
|
||||
public:
|
||||
Tokenizer(istream &input)
|
||||
: fInput(input),
|
||||
fHasCurrent(false)
|
||||
{
|
||||
}
|
||||
|
||||
string GetCurrentToken()
|
||||
{
|
||||
if (!fHasCurrent)
|
||||
throw Exception("GetCurrentToken(): No current token!");
|
||||
return fTokens.front();
|
||||
}
|
||||
|
||||
string GetNextToken()
|
||||
{
|
||||
return GetNextToken(NULL);
|
||||
}
|
||||
|
||||
string GetNextToken(stack<string> &skippedTokens)
|
||||
{
|
||||
return GetNextToken(&skippedTokens);
|
||||
}
|
||||
|
||||
string GetNextToken(stack<string> *skippedTokens)
|
||||
{
|
||||
if (fHasCurrent) {
|
||||
fTokens.pop_front();
|
||||
fHasCurrent = false;
|
||||
}
|
||||
while (fTokens.empty())
|
||||
_ReadLine();
|
||||
fHasCurrent = true;
|
||||
if (skippedTokens)
|
||||
skippedTokens->push(fTokens.front());
|
||||
return fTokens.front();
|
||||
}
|
||||
|
||||
void ExpectToken(const string &expectedToken)
|
||||
{
|
||||
string token = GetCurrentToken();
|
||||
if (expectedToken != token) {
|
||||
throw ParseException(string("Unexpected token `") + token
|
||||
+ "'. Expected was `" + expectedToken + "'.");
|
||||
}
|
||||
}
|
||||
|
||||
void ExpectNextToken(const string &expectedToken)
|
||||
{
|
||||
GetNextToken();
|
||||
ExpectToken(expectedToken);
|
||||
}
|
||||
|
||||
bool CheckToken(const string &expectedToken)
|
||||
{
|
||||
string token = GetCurrentToken();
|
||||
return (expectedToken == token);
|
||||
}
|
||||
|
||||
bool CheckNextToken(const string &expectedToken)
|
||||
{
|
||||
GetNextToken();
|
||||
bool result = CheckToken(expectedToken);
|
||||
if (!result)
|
||||
PutCurrentToken();
|
||||
return result;
|
||||
}
|
||||
|
||||
void PutCurrentToken()
|
||||
{
|
||||
if (!fHasCurrent)
|
||||
throw Exception("GetCurrentToken(): No current token!");
|
||||
fHasCurrent = false;
|
||||
}
|
||||
|
||||
void PutToken(string token)
|
||||
{
|
||||
if (fHasCurrent) {
|
||||
fTokens.pop_front();
|
||||
fHasCurrent = false;
|
||||
}
|
||||
fTokens.push_front(token);
|
||||
}
|
||||
|
||||
void PutTokens(stack<string> &tokens)
|
||||
{
|
||||
if (fHasCurrent) {
|
||||
fTokens.pop_front();
|
||||
fHasCurrent = false;
|
||||
}
|
||||
while (!tokens.empty()) {
|
||||
fTokens.push_front(tokens.top());
|
||||
tokens.pop();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
void _ReadLine()
|
||||
{
|
||||
// read the line
|
||||
char buffer[10240];
|
||||
if (!fInput.getline(buffer, sizeof(buffer)))
|
||||
throw EOFException("Unexpected end of input.");
|
||||
// parse it
|
||||
int len = strlen(buffer);
|
||||
int tokenStart = 0;
|
||||
for (int i = 0; i < len; i++) {
|
||||
char c = buffer[i];
|
||||
if (isspace(c)) {
|
||||
if (tokenStart < i)
|
||||
fTokens.push_back(string(buffer + tokenStart, buffer + i));
|
||||
tokenStart = i + 1;
|
||||
continue;
|
||||
}
|
||||
switch (buffer[i]) {
|
||||
case '#':
|
||||
case '(':
|
||||
case ')':
|
||||
case '*':
|
||||
case '&':
|
||||
case '[':
|
||||
case ']':
|
||||
case ';':
|
||||
case ',':
|
||||
if (tokenStart < i) {
|
||||
fTokens.push_back(string(buffer + tokenStart,
|
||||
buffer + i));
|
||||
}
|
||||
fTokens.push_back(string(buffer + i, buffer + i + 1));
|
||||
tokenStart = i + 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (tokenStart < len)
|
||||
fTokens.push_back(string(buffer + tokenStart, buffer + len));
|
||||
}
|
||||
|
||||
private:
|
||||
istream &fInput;
|
||||
list<string> fTokens;
|
||||
bool fHasCurrent;
|
||||
};
|
||||
|
||||
|
||||
// Main
|
||||
class Main {
|
||||
public:
|
||||
|
||||
int Run(int argc, char **argv)
|
||||
{
|
||||
// parse parameters
|
||||
if (argc >= 2
|
||||
&& (string(argv[1]) == "-h" || string(argv[1]) == "--help")) {
|
||||
print_usage(false);
|
||||
// parse arguments
|
||||
const char *syscallsFile = NULL;
|
||||
const char *dispatcherFile = NULL;
|
||||
for (int argi = 1; argi < argc; argi++) {
|
||||
string arg(argv[argi]);
|
||||
if (arg == "-h" || arg == "--help") {
|
||||
print_usage(false);
|
||||
return 0;
|
||||
} else if (arg == "-c") {
|
||||
if (argi + 1 >= argc) {
|
||||
print_usage(true);
|
||||
return 1;
|
||||
}
|
||||
syscallsFile = argv[++argi];
|
||||
} else if (arg == "-d") {
|
||||
if (argi + 1 >= argc) {
|
||||
print_usage(true);
|
||||
return 1;
|
||||
}
|
||||
dispatcherFile = argv[++argi];
|
||||
} else {
|
||||
print_usage(true);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
fSyscallInfos = gensyscall_get_infos(&fSyscallCount);
|
||||
if (!syscallsFile && !dispatcherFile) {
|
||||
printf("Found %d syscalls.\n", fSyscallCount);
|
||||
return 0;
|
||||
}
|
||||
if (argc != 4) {
|
||||
print_usage(true);
|
||||
return 1;
|
||||
}
|
||||
_ParseSyscalls(argv[1]);
|
||||
_WriteSyscallsFile(argv[2]);
|
||||
_WriteDispatcherFile(argv[3]);
|
||||
// generate the output
|
||||
if (syscallsFile)
|
||||
_WriteSyscallsFile(syscallsFile);
|
||||
if (dispatcherFile)
|
||||
_WriteDispatcherFile(dispatcherFile);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
void _ParseSyscalls(const char *filename)
|
||||
{
|
||||
// open the input file
|
||||
ifstream file(filename, ifstream::in);
|
||||
if (!file.is_open())
|
||||
throw new IOException(string("Failed to open `") + filename + "'.");
|
||||
// parse the syscalls
|
||||
Tokenizer tokenizer(file);
|
||||
// find "#pragma syscalls begin"
|
||||
while (true) {
|
||||
while (tokenizer.GetNextToken() != "#");
|
||||
stack<string> skippedTokens;
|
||||
if (tokenizer.GetNextToken(skippedTokens) == "pragma"
|
||||
&& tokenizer.GetNextToken(skippedTokens) == "syscalls"
|
||||
&& tokenizer.GetNextToken(skippedTokens) == "begin") {
|
||||
break;
|
||||
}
|
||||
tokenizer.PutTokens(skippedTokens);
|
||||
}
|
||||
// parse the functions
|
||||
while (!tokenizer.CheckNextToken("#")) {
|
||||
Syscall syscall;
|
||||
_ParseSyscall(tokenizer, syscall);
|
||||
fSyscalls.push_back(syscall);
|
||||
}
|
||||
// expect "pragma syscalls end"
|
||||
tokenizer.ExpectNextToken("pragma");
|
||||
tokenizer.ExpectNextToken("syscalls");
|
||||
tokenizer.ExpectNextToken("end");
|
||||
|
||||
// for (int i = 0; i < (int)fSyscalls.size(); i++) {
|
||||
// const Syscall &syscall = fSyscalls[i];
|
||||
// printf("syscall: `%s'\n", syscall.GetName().c_str());
|
||||
// for (int k = 0; k < (int)syscall.CountParameters(); k++)
|
||||
// printf(" arg: `%s'\n", syscall.ParameterAt(k).type.c_str());
|
||||
// printf(" return type: `%s'\n",
|
||||
// syscall.GetReturnType().type.c_str());
|
||||
// }
|
||||
// printf("Found %lu syscalls.\n", fSyscalls.size());
|
||||
}
|
||||
|
||||
void _WriteSyscallsFile(const char *filename)
|
||||
{
|
||||
// open the syscalls output file
|
||||
ofstream file(filename, ofstream::out | ofstream::trunc);
|
||||
if (!file.is_open())
|
||||
throw new IOException(string("Failed to open `") + filename + "'.");
|
||||
throw IOException(string("Failed to open `") + filename + "'.");
|
||||
// output the syscalls definitions
|
||||
for (int i = 0; i < (int)fSyscalls.size(); i++) {
|
||||
const Syscall &syscall = fSyscalls[i];
|
||||
file << "SYSCALL" << syscall.CountParameters() << "("
|
||||
<< syscall.GetName() << ", " << i << ")" << endl;
|
||||
for (int i = 0; i < fSyscallCount; i++) {
|
||||
const gensyscall_syscall_info &syscall = fSyscallInfos[i];
|
||||
int paramCount = syscall.parameter_count;
|
||||
int paramSize = 0;
|
||||
gensyscall_parameter_info* parameters = syscall.parameters;
|
||||
for (int k = 0; k < paramCount; k++) {
|
||||
int size = parameters[k].actual_size;
|
||||
paramSize += (size + 3) / 4 * 4;
|
||||
}
|
||||
file << "SYSCALL" << (paramSize / 4) << "("
|
||||
<< syscall.name << ", " << i << ")" << endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -382,129 +102,43 @@ private:
|
|||
// open the dispatcher output file
|
||||
ofstream file(filename, ofstream::out | ofstream::trunc);
|
||||
if (!file.is_open())
|
||||
throw new IOException(string("Failed to open `") + filename + "'.");
|
||||
throw IOException(string("Failed to open `") + filename + "'.");
|
||||
// output the case statements
|
||||
for (int i = 0; i < (int)fSyscalls.size(); i++) {
|
||||
const Syscall &syscall = fSyscalls[i];
|
||||
for (int i = 0; i < fSyscallCount; i++) {
|
||||
const gensyscall_syscall_info &syscall = fSyscallInfos[i];
|
||||
file << "case " << i << ":" << endl;
|
||||
file << "\t";
|
||||
if (syscall.GetReturnType().type != "void")
|
||||
if (string(syscall.return_type) != "void")
|
||||
file << "*call_ret = ";
|
||||
file << syscall.GetKernelName() << "(";
|
||||
if (syscall.CountParameters() > 0) {
|
||||
file << "(" << syscall.ParameterAt(0).type << ")arg0";
|
||||
for (int k = 1; k < (int)syscall.CountParameters(); k++)
|
||||
file << ", (" << syscall.ParameterAt(k).type << ")arg" << k;
|
||||
file << syscall.kernel_name << "(";
|
||||
int paramCount = syscall.parameter_count;
|
||||
if (paramCount > 0) {
|
||||
gensyscall_parameter_info* parameters = syscall.parameters;
|
||||
file << "*(" << _GetPointerType(parameters[0].type) << ")args";
|
||||
for (int k = 1; k < paramCount; k++) {
|
||||
file << ", *(" << _GetPointerType(parameters[k].type)
|
||||
<< ")((char*)args + " << parameters[k].offset << ")";
|
||||
}
|
||||
}
|
||||
file << ");" << endl;
|
||||
file << "\tbreak;" << endl;
|
||||
}
|
||||
}
|
||||
|
||||
void _ParseSyscall(Tokenizer &tokenizer, Syscall &syscall)
|
||||
static string _GetPointerType(const char *type)
|
||||
{
|
||||
// get return type and function name
|
||||
vector<string> returnType;
|
||||
while (tokenizer.GetNextToken() != "(") {
|
||||
string token = tokenizer.GetCurrentToken();
|
||||
// strip leading "extern"
|
||||
if (!returnType.empty() || token != "extern")
|
||||
returnType.push_back(token);
|
||||
}
|
||||
if (returnType.size() < 2) {
|
||||
throw ParseException("Error while parsing function "
|
||||
"return type.");
|
||||
}
|
||||
syscall.SetName(returnType[returnType.size() - 1]);
|
||||
returnType.pop_back();
|
||||
string returnTypeString(returnType[0]);
|
||||
for (int i = 1; i < (int)returnType.size(); i++) {
|
||||
returnTypeString += " ";
|
||||
returnTypeString += returnType[i];
|
||||
}
|
||||
syscall.SetReturnType(returnTypeString);
|
||||
// get arguments
|
||||
if (!tokenizer.CheckNextToken(")")) {
|
||||
_ParseParameter(tokenizer, syscall);
|
||||
while (!tokenizer.CheckNextToken(")")) {
|
||||
tokenizer.ExpectNextToken(",");
|
||||
_ParseParameter(tokenizer, syscall);
|
||||
}
|
||||
}
|
||||
tokenizer.ExpectNextToken(";");
|
||||
}
|
||||
|
||||
void _ParseParameter(Tokenizer &tokenizer, Syscall &syscall)
|
||||
{
|
||||
vector<string> type;
|
||||
while (tokenizer.GetNextToken() != ")"
|
||||
&& tokenizer.GetCurrentToken() != ",") {
|
||||
string token = tokenizer.GetCurrentToken();
|
||||
type.push_back(token);
|
||||
if (token == "(") {
|
||||
// This must be a function pointer. We deal with that in a
|
||||
// separate method.
|
||||
_ParseFunctionPointerParameter(tokenizer, syscall, type);
|
||||
return;
|
||||
}
|
||||
}
|
||||
tokenizer.PutCurrentToken();
|
||||
if (type.size() < 2) {
|
||||
if (type.size() == 1 && type[0] == "void") {
|
||||
// that's OK
|
||||
return;
|
||||
}
|
||||
throw ParseException("Error while parsing function "
|
||||
"parameter.");
|
||||
}
|
||||
type.pop_back(); // last component is the parameter name
|
||||
string typeString(type[0]);
|
||||
for (int i = 1; i < (int)type.size(); i++) {
|
||||
typeString += " ";
|
||||
typeString += type[i];
|
||||
}
|
||||
syscall.AddParameter(typeString);
|
||||
}
|
||||
|
||||
void _ParseFunctionPointerParameter(Tokenizer &tokenizer, Syscall &syscall,
|
||||
vector<string> &type)
|
||||
{
|
||||
// When this method is entered, the return type and the opening
|
||||
// parenthesis must already be parse and stored in the supplied type
|
||||
// vector.
|
||||
if (type.size() < 2) {
|
||||
throw ParseException("Error parsing function parameter. "
|
||||
"No return type.");
|
||||
}
|
||||
// read all the "*"s there are
|
||||
while (tokenizer.CheckNextToken("*"))
|
||||
type.push_back("*");
|
||||
// now comes the parameter name, if specified -- skip it
|
||||
if (!tokenizer.CheckNextToken(")")) {
|
||||
tokenizer.GetNextToken();
|
||||
tokenizer.ExpectNextToken(")");
|
||||
}
|
||||
type.push_back(")");
|
||||
// the function parameters
|
||||
tokenizer.ExpectNextToken("(");
|
||||
type.push_back("(");
|
||||
while (!tokenizer.CheckNextToken(")"))
|
||||
type.push_back(tokenizer.GetNextToken());
|
||||
type.push_back(")");
|
||||
// compose the type string and add it to the syscall parameters
|
||||
string typeString(type[0]);
|
||||
for (int i = 1; i < (int)type.size(); i++) {
|
||||
typeString += " ";
|
||||
typeString += type[i];
|
||||
}
|
||||
syscall.AddParameter(typeString);
|
||||
char *parenthesis = strchr(type, ')');
|
||||
if (!parenthesis)
|
||||
return string(type) + "*";
|
||||
// function pointer type
|
||||
return string(type, parenthesis - type) + "*" + parenthesis;
|
||||
}
|
||||
|
||||
private:
|
||||
vector<Syscall> fSyscalls;
|
||||
const gensyscall_syscall_info *fSyscallInfos;
|
||||
int fSyscallCount;
|
||||
};
|
||||
|
||||
|
||||
// main
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
|
@ -516,4 +150,3 @@ main(int argc, char **argv)
|
|||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
// gensyscalls.h
|
||||
|
||||
#ifndef _GEN_SYSCALLS_H
|
||||
#define _GEN_SYSCALLS_H
|
||||
|
||||
typedef struct gensyscall_parameter_info {
|
||||
const char *type;
|
||||
int offset;
|
||||
int size;
|
||||
int actual_size;
|
||||
} gensyscall_parameter_info;
|
||||
|
||||
typedef struct gensyscall_syscall_info {
|
||||
const char *name;
|
||||
const char *kernel_name;
|
||||
const char *return_type;
|
||||
int parameter_count;
|
||||
gensyscall_parameter_info *parameters;
|
||||
} gensyscall_syscall_info;
|
||||
|
||||
#endif // _GEN_SYSCALLS_H
|
|
@ -0,0 +1,55 @@
|
|||
// gensyscalls_common.h
|
||||
|
||||
#ifndef _GEN_SYSCALLS_COMMON_H
|
||||
#define _GEN_SYSCALLS_COMMON_H
|
||||
|
||||
#include <string>
|
||||
|
||||
// Exception
|
||||
struct Exception : exception {
|
||||
Exception()
|
||||
: fMessage()
|
||||
{
|
||||
}
|
||||
|
||||
Exception(const string &message)
|
||||
: fMessage(message)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~Exception() {}
|
||||
|
||||
virtual const char *what() const
|
||||
{
|
||||
return fMessage.c_str();
|
||||
}
|
||||
|
||||
private:
|
||||
string fMessage;
|
||||
};
|
||||
|
||||
// EOFException
|
||||
struct EOFException : public Exception {
|
||||
EOFException() {}
|
||||
EOFException(const string &message) : Exception(message) {}
|
||||
virtual ~EOFException() {}
|
||||
};
|
||||
|
||||
// IOException
|
||||
struct IOException : public Exception {
|
||||
IOException() {}
|
||||
IOException(const string &message) : Exception(message) {}
|
||||
virtual ~IOException() {}
|
||||
};
|
||||
|
||||
// ParseException
|
||||
struct ParseException : public Exception {
|
||||
ParseException() {}
|
||||
ParseException(const string &message) : Exception(message) {}
|
||||
virtual ~ParseException() {}
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
#endif // _GEN_SYSCALLS_COMMON_H
|
Loading…
Reference in New Issue