mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-05 16:46:26 +00:00
317 lines
7.6 KiB
C++
317 lines
7.6 KiB
C++
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
|
*
|
|
* The contents of this file are subject to the Netscape Public
|
|
* License Version 1.1 (the "License"); you may not use this file
|
|
* except in compliance with the License. You may obtain a copy of
|
|
* the License at http://www.mozilla.org/NPL/
|
|
*
|
|
* Software distributed under the License is distributed on an "AS
|
|
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
|
* implied. See the License for the specific language governing
|
|
* rights and limitations under the License.
|
|
*
|
|
* The Original Code is mozilla.org code.
|
|
*
|
|
* The Initial Developer of the Original Code is Netscape
|
|
* Communications Corporation. Portions created by Netscape are
|
|
* Copyright (C) 1998 Netscape Communications Corporation. All
|
|
* Rights Reserved.
|
|
*
|
|
* Contributor(s):
|
|
*/
|
|
#include "HeaderGenerator.h"
|
|
#include "plstr.h"
|
|
#include "prprf.h"
|
|
|
|
#include "CUtils.h"
|
|
#include "StringUtils.h"
|
|
#include "Pool.h"
|
|
#include "FieldOrMethod.h"
|
|
|
|
#ifdef USE_PR_IO
|
|
#define PR_fprintf fprintf
|
|
#define PR_Write fwrite
|
|
#define PRFileDesc FILE
|
|
#endif
|
|
|
|
HeaderGenerator::HeaderGenerator(ClassCentral ¢ral) : central(central)
|
|
{
|
|
/* Default directory to write stuff into is the current directory */
|
|
headerDir = PL_strdup(".");
|
|
tempDir = PL_strdup("/tmp");
|
|
}
|
|
|
|
HeaderGenerator::~HeaderGenerator()
|
|
{
|
|
//free(headerDir);
|
|
//free(tempDir);
|
|
}
|
|
|
|
|
|
void HeaderGenerator::setClassPath(const char *classPath)
|
|
{
|
|
central.setClassPath(classPath);
|
|
}
|
|
|
|
|
|
void HeaderGenerator::setOutputDir(const char *dir)
|
|
{
|
|
//free(headerDir);
|
|
|
|
headerDir = (dir) ? PL_strdup(dir) : PL_strdup(".");
|
|
}
|
|
|
|
void HeaderGenerator::setTempDir(const char *dir)
|
|
{
|
|
//free(tempDir);
|
|
|
|
tempDir = (dir) ? PL_strdup(dir) : PL_strdup("/tmp");
|
|
}
|
|
|
|
|
|
bool HeaderGenerator::writeFile(const char *className)
|
|
{
|
|
ClassFileSummary *summ;
|
|
|
|
try {
|
|
summ = ¢ral.addClass(className);
|
|
} catch (VerifyError err) {
|
|
#ifdef DEBUG
|
|
printf("VerifyError loading class %s: %d\n", className, err.cause);
|
|
#endif
|
|
return false;
|
|
}
|
|
|
|
TemporaryStringCopy copy(className);
|
|
char *cname = copy;
|
|
|
|
/* Replace slashes in the className with underscores */
|
|
mangleClassName(cname, '/');
|
|
|
|
/* The 2 at the end is for the NULL character and an extra slash at the
|
|
* end of the directory name
|
|
*/
|
|
uint32 fileLen = strlen(headerDir)+strlen(className)+sizeof(".h")+5;
|
|
|
|
TemporaryBuffer buffer(fileLen);
|
|
char *fileName = buffer;
|
|
|
|
PR_snprintf(fileName, fileLen, "%s/%s.h", headerDir, cname);
|
|
|
|
#ifndef USE_PR_IO
|
|
FileDesc desc(fileName, (PR_WRONLY | PR_CREATE_FILE), 00644);
|
|
PRFileDesc *fp = desc;
|
|
#else
|
|
FILE *fp = fopen(fileName, "w");
|
|
#endif
|
|
|
|
if (!fp)
|
|
return false;
|
|
|
|
writeHeader(cname, fp);
|
|
|
|
bool ret = genHeaderFile(*summ, fp);
|
|
|
|
if (!ret)
|
|
return false;
|
|
|
|
writeFooter(cname, fp);
|
|
|
|
#ifndef USE_PR_IO
|
|
desc.close();
|
|
#else
|
|
fclose (fp);
|
|
#endif
|
|
|
|
/* Write the headers for our parent objects if they exist */
|
|
if (needParents()) {
|
|
const char *parentName = getParentName(*summ->getReader());
|
|
|
|
if (parentName && !writeFile(parentName))
|
|
return false;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
void HeaderGenerator::writeHeader(const char *cname, PRFileDesc *fp)
|
|
{
|
|
PR_fprintf(fp, "#ifndef _%s_H_\n#define _%s_H_\n\n", cname, cname);
|
|
}
|
|
|
|
|
|
void HeaderGenerator::writeFooter(const char *cname, PRFileDesc *fp)
|
|
{
|
|
PR_fprintf(fp, "#endif /* _%s_H_ */\n", cname);
|
|
}
|
|
|
|
char *HeaderGenerator::getMangledName(const Type &type, bool asArray)
|
|
{
|
|
switch (type.typeKind) {
|
|
case tkChar:
|
|
return (asArray) ? PL_strdup("char") : PL_strdup("int32 /* char */");
|
|
break;
|
|
|
|
case tkShort:
|
|
return (asArray) ? PL_strdup("int16") : PL_strdup("int32 /* short */");
|
|
break;
|
|
|
|
case tkInt:
|
|
return PL_strdup("int32");
|
|
break;
|
|
|
|
case tkByte:
|
|
return (asArray) ? PL_strdup("uint8") : PL_strdup("uint32 /* byte */");
|
|
break;
|
|
|
|
case tkBoolean:
|
|
return (asArray) ? PL_strdup("char") : PL_strdup("uint32 /* bool */");
|
|
break;
|
|
|
|
case tkLong:
|
|
return PL_strdup("int64");
|
|
break;
|
|
|
|
case tkFloat:
|
|
return PL_strdup("Flt32");
|
|
break;
|
|
|
|
case tkDouble:
|
|
return PL_strdup("Flt64");
|
|
break;
|
|
|
|
case tkVoid:
|
|
return PL_strdup("void");
|
|
break;
|
|
|
|
case tkObject:
|
|
case tkInterface: {
|
|
Class &clazz = *const_cast<Class *>(static_cast<const Class *>(&type));
|
|
TemporaryStringCopy copy(clazz.getName());
|
|
char *nameCopy = copy;
|
|
mangleClassName(nameCopy, '.');
|
|
int32 objNameLen = strlen(nameCopy)+ 1 + sizeof("Java_");
|
|
char *objName = (char *) malloc(objNameLen);
|
|
PR_snprintf(objName, objNameLen, "Java_%s", nameCopy);
|
|
return objName;
|
|
}
|
|
|
|
case tkArray: {
|
|
const Array &atype = *static_cast<const Array *>(&type);
|
|
char *elementString = getMangledName(atype.componentType, true);
|
|
assert(elementString);
|
|
int32 len = sizeof("ArrayOf_")+strlen(elementString)+1;
|
|
char *arrayStr = (char *) malloc(len);
|
|
PR_snprintf(arrayStr, len, "ArrayOf_%s", elementString);
|
|
|
|
// NSPR needs to provide a way to free strings that it allocates
|
|
#ifdef DEBUG
|
|
free(elementString);
|
|
#endif
|
|
|
|
return arrayStr;
|
|
}
|
|
|
|
default:
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
char *HeaderGenerator::getArgString(const Type &type)
|
|
{
|
|
switch (type.typeKind) {
|
|
case tkObject: /* For objects, we always pass a pointer to the object */
|
|
case tkInterface:
|
|
case tkArray: {
|
|
char *objArg = getMangledName(type);
|
|
assert(objArg);
|
|
objArg = (char *) realloc(objArg, strlen(objArg)+3);
|
|
PL_strcat(objArg, " *");
|
|
return objArg;
|
|
}
|
|
|
|
|
|
default:
|
|
return getMangledName(type);
|
|
}
|
|
|
|
}
|
|
|
|
|
|
void HeaderGenerator::addMangledName(ClassFileSummary &summ,
|
|
const Type &type, StringPool &sp)
|
|
{
|
|
Type *ourType = summ.getThisClass();
|
|
|
|
/* No need to generate forward declarators for ourselves */
|
|
if (ourType == &type)
|
|
return;
|
|
|
|
/* XXX Note here that we still generate forward declarations for
|
|
* references to our parent types. These are infrequent, but still
|
|
* redundant. But they'll compile, so I'll come back some other day
|
|
* and filter them out -- kini
|
|
*/
|
|
|
|
char *mangledObjName = 0;
|
|
mangledObjName = getMangledName(type);
|
|
|
|
if (!mangledObjName)
|
|
verifyError(VerifyError::noClassDefFound);
|
|
|
|
sp.intern(mangledObjName);
|
|
free((void *) mangledObjName);
|
|
}
|
|
|
|
|
|
void HeaderGenerator::genForwards(ClassFileSummary &summ,
|
|
StringPool &sp)
|
|
{
|
|
/* So as not to generate duplicate forward declarations, we'll go
|
|
* through the fields and methods and put all object and array names into
|
|
* a StringPool, which we will use later to generate the actual
|
|
* forward declarations.
|
|
*/
|
|
|
|
/* Go through the fields */
|
|
const Field **fields = summ.getFields();
|
|
uint32 fieldCount = summ.getFieldCount();
|
|
|
|
uint32 i;
|
|
for (i = 0; i < fieldCount; i++) {
|
|
const Type &type = fields[i]->getType();
|
|
|
|
if (type.typeKind == tkObject || type.typeKind == tkInterface ||
|
|
type.typeKind == tkArray)
|
|
addMangledName(summ, type, sp);
|
|
}
|
|
|
|
const Method **methods = summ.getMethods();
|
|
uint32 methodCount = summ.getMethodCount();
|
|
|
|
for (i = 0; i < methodCount; i++) {
|
|
Method *m = (Method *) methods[i];
|
|
const Signature &sig = m->getSignature();
|
|
|
|
if ((m->getModifiers() & CR_METHOD_NATIVE)) {
|
|
/* Generate forward declarators for the return type, if neccessary */
|
|
if (sig.resultType->typeKind == tkObject ||
|
|
sig.resultType->typeKind == tkInterface ||
|
|
sig.resultType->typeKind == tkArray)
|
|
addMangledName(summ, *sig.resultType, sp);
|
|
|
|
for (uint32 j = 0; j < sig.nArguments; j++)
|
|
if (sig.argumentTypes[j]->typeKind == tkObject ||
|
|
sig.argumentTypes[j]->typeKind == tkInterface ||
|
|
sig.argumentTypes[j]->typeKind == tkArray)
|
|
addMangledName(summ, *sig.argumentTypes[j], sp);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|