Completed. Properly generates the desired outputs now.
git-svn-id: file:///srv/svn/repos/haiku/trunk/current@8622 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -14,15 +14,20 @@
|
|||||||
|
|
||||||
// usage
|
// usage
|
||||||
const char *kUsage =
|
const char *kUsage =
|
||||||
"Usage: gensyscalls <header> <dispatcher template> <calls> <dispatcher>\n"
|
"Usage: gensyscalls <header> <calls> <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"
|
||||||
"\n"
|
"\n"
|
||||||
" <header> - Input: The preprocessed header file with the\n"
|
" <header> - Input: The preprocessed header file with the\n"
|
||||||
" syscall prototypes.\n"
|
" syscall prototypes.\n"
|
||||||
" <dispatcher template> - Input: A template used to generate the syscall\n"
|
|
||||||
" dispatcher source file.\n"
|
|
||||||
" <calls> - Output: The assembly source file implementing the\n"
|
" <calls> - Output: The assembly source file implementing the\n"
|
||||||
" actual syscalls."
|
" actual syscalls."
|
||||||
" <dispatcher> - Output: The syscall dispatcher source file.\n";
|
" <dispatcher> - Output: The C source file to be included by the\n"
|
||||||
|
" syscall dispatcher source file.\n";
|
||||||
|
|
||||||
// print_usage
|
// print_usage
|
||||||
static
|
static
|
||||||
@@ -80,12 +85,28 @@ public:
|
|||||||
return fReturnType;
|
return fReturnType;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
protected:
|
||||||
string fName;
|
string fName;
|
||||||
vector<Type> fParameters;
|
vector<Type> fParameters;
|
||||||
Type fReturnType;
|
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
|
// Exception
|
||||||
struct Exception : exception {
|
struct Exception : exception {
|
||||||
Exception()
|
Exception()
|
||||||
@@ -168,7 +189,6 @@ public:
|
|||||||
fHasCurrent = true;
|
fHasCurrent = true;
|
||||||
if (skippedTokens)
|
if (skippedTokens)
|
||||||
skippedTokens->push(fTokens.front());
|
skippedTokens->push(fTokens.front());
|
||||||
printf("next token: `%s'\n", fTokens.front().c_str());
|
|
||||||
return fTokens.front();
|
return fTokens.front();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -290,38 +310,26 @@ public:
|
|||||||
print_usage(false);
|
print_usage(false);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (argc != 5) {
|
if (argc != 4) {
|
||||||
print_usage(true);
|
print_usage(true);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
// fDispatcherTemplateFile = argv[2];
|
_ParseSyscalls(argv[1]);
|
||||||
// fCallsFile = argv[3];
|
_WriteSyscallsFile(argv[2]);
|
||||||
// fDispatcherFile = argv[4];
|
_WriteDispatcherFile(argv[3]);
|
||||||
// open the files
|
|
||||||
fHeaderFile.open(argv[1], ifstream::in);
|
|
||||||
if (!fHeaderFile.is_open())
|
|
||||||
throw new IOException(string("Failed to open `") + argv[1] + "'.");
|
|
||||||
// parse the syscalls
|
|
||||||
vector<Function> syscalls;
|
|
||||||
_ParseSyscalls(syscalls);
|
|
||||||
for (int i = 0; i < (int)syscalls.size(); i++) {
|
|
||||||
const Function &syscall = syscalls[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", syscalls.size());
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void _ParseSyscalls(vector<Function> &syscalls)
|
void _ParseSyscalls(const char *filename)
|
||||||
{
|
{
|
||||||
Tokenizer tokenizer(fHeaderFile);
|
// 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"
|
// find "#pragma syscalls begin"
|
||||||
while (true) {
|
while (true) {
|
||||||
while (tokenizer.GetNextToken() != "#");
|
while (tokenizer.GetNextToken() != "#");
|
||||||
@@ -335,17 +343,65 @@ private:
|
|||||||
}
|
}
|
||||||
// parse the functions
|
// parse the functions
|
||||||
while (!tokenizer.CheckNextToken("#")) {
|
while (!tokenizer.CheckNextToken("#")) {
|
||||||
Function syscall;
|
Syscall syscall;
|
||||||
_ParseSyscall(tokenizer, syscall);
|
_ParseSyscall(tokenizer, syscall);
|
||||||
syscalls.push_back(syscall);
|
fSyscalls.push_back(syscall);
|
||||||
}
|
}
|
||||||
// expect "pragma syscalls end"
|
// expect "pragma syscalls end"
|
||||||
tokenizer.ExpectNextToken("pragma");
|
tokenizer.ExpectNextToken("pragma");
|
||||||
tokenizer.ExpectNextToken("syscalls");
|
tokenizer.ExpectNextToken("syscalls");
|
||||||
tokenizer.ExpectNextToken("end");
|
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 _ParseSyscall(Tokenizer &tokenizer, Function &syscall)
|
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 + "'.");
|
||||||
|
// 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void _WriteDispatcherFile(const char *filename)
|
||||||
|
{
|
||||||
|
// open the dispatcher output file
|
||||||
|
ofstream file(filename, ofstream::out | ofstream::trunc);
|
||||||
|
if (!file.is_open())
|
||||||
|
throw new IOException(string("Failed to open `") + filename + "'.");
|
||||||
|
// output the case statements
|
||||||
|
for (int i = 0; i < (int)fSyscalls.size(); i++) {
|
||||||
|
const Syscall &syscall = fSyscalls[i];
|
||||||
|
file << "case " << i << ":" << endl;
|
||||||
|
file << "\t";
|
||||||
|
if (syscall.GetReturnType().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 << ");" << endl;
|
||||||
|
file << "\tbreak;" << endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void _ParseSyscall(Tokenizer &tokenizer, Syscall &syscall)
|
||||||
{
|
{
|
||||||
// get return type and function name
|
// get return type and function name
|
||||||
vector<string> returnType;
|
vector<string> returnType;
|
||||||
@@ -378,7 +434,7 @@ private:
|
|||||||
tokenizer.ExpectNextToken(";");
|
tokenizer.ExpectNextToken(";");
|
||||||
}
|
}
|
||||||
|
|
||||||
void _ParseParameter(Tokenizer &tokenizer, Function &syscall)
|
void _ParseParameter(Tokenizer &tokenizer, Syscall &syscall)
|
||||||
{
|
{
|
||||||
vector<string> type;
|
vector<string> type;
|
||||||
while (tokenizer.GetNextToken() != ")"
|
while (tokenizer.GetNextToken() != ")"
|
||||||
@@ -410,7 +466,7 @@ private:
|
|||||||
syscall.AddParameter(typeString);
|
syscall.AddParameter(typeString);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _ParseFunctionPointerParameter(Tokenizer &tokenizer, Function &syscall,
|
void _ParseFunctionPointerParameter(Tokenizer &tokenizer, Syscall &syscall,
|
||||||
vector<string> &type)
|
vector<string> &type)
|
||||||
{
|
{
|
||||||
// When this method is entered, the return type and the opening
|
// When this method is entered, the return type and the opening
|
||||||
@@ -445,10 +501,7 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ifstream fHeaderFile;
|
vector<Syscall> fSyscalls;
|
||||||
const char *fDispatcherTemplateFile;
|
|
||||||
const char *fCallsFile;
|
|
||||||
const char *fDispatcherFile;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user