/* -*- 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 "NetscapeHeaderGenerator.h" #include "prprf.h" #include "plstr.h" #include "CUtils.h" #include "StringUtils.h" #include "JavaObject.h" #include "FieldOrMethod.h" #include "NetscapeManglers.h" #ifdef USE_PR_IO #define PR_fprintf fprintf #define PR_Write fwrite #define PRFileDesc FILE #endif bool NetscapeHeaderGenerator::genHeaderFile(ClassFileSummary &summ, PRFileDesc *fp) { const ClassFileReader &reader = *summ.getReader(); const char *className = reader.getThisClass()->getUtf()->getUtfString(); PR_fprintf(fp, "/* This file is machine-generated. Do not edit!! */\n"); PR_fprintf(fp, "\n/* Header for class %s */\n\n", className); PR_fprintf(fp, "#include \"prtypes.h\"\n"); PR_fprintf(fp, "#include \"NativeDefs.h\"\n"); /* If we have a parent, put in a #include so that we can access the * parent's struct as well */ const char *constParentName = getParentName(reader); char *parentCName = 0; if (constParentName) { TemporaryStringCopy pcopy(constParentName); char *parentName = pcopy; int32 parentLen = PL_strlen(parentName)+sizeof("Java_")+1; parentCName = (char *) malloc(parentLen+1); PL_strcpy(parentCName, mangleClassName(parentName, '/')); PR_fprintf(fp, "#include \"%s.h\"\n", parentCName); } PR_fprintf(fp, "\n\n"); /* Generate forward declarations */ Pool p; StringPool sp(p); genForwards(summ, sp); /* Now get all the keys in the string pool */ Vector &vec = sp; for (uint32 index = 0; index < vec.size(); index++) PR_fprintf(fp, "struct %s;\n", vec[index]); PR_fprintf(fp, "\n\n"); TemporaryStringCopy copy(className); char *mangledClassName = mangleClassName((char *) copy, '/'); if (parentCName) { PR_fprintf(fp, "struct Java_%s : Java_%s {\n", mangledClassName, parentCName); PR_fprintf(fp, "\tJava_%s(const Type &type) : Java_%s(type) { }\n", mangledClassName, parentCName); free(parentCName); } else { PR_fprintf(fp, "struct Java_%s : JavaObject {\n", mangledClassName); PR_fprintf(fp, "\tJava_%s(const Type &type) : JavaObject(type) { }\n", mangledClassName); } /* Go through each field and generate it's type */ const Field **fields = summ.getFields(); uint32 fieldCount = summ.getFieldCount(); uint32 i; for (i = 0; i < fieldCount; i++) { const char *fieldName = fields[i]->getName(); const Type &type = fields[i]->getType(); const char *typeStr = getArgString(type); if (!typeStr) return false; if (fields[i]->getModifiers() & CR_FIELD_STATIC) PR_fprintf(fp, "\t// static %s %s; \n", typeStr, fieldName); else PR_fprintf(fp, "\t%s %s;\n", typeStr, fieldName); // Currently kills the release build since NSPR needs to give us a // clean way of freeing strings that it allocates #ifdef DEBUG //free((void *) typeStr); /* getArgString() uses malloc to allocate */ #endif } PR_fprintf(fp, "};\n\n"); /* Generate a declaration for the array type corresponding to this class */ PR_fprintf(fp, "ARRAY_OF(Java_%s);\n", mangledClassName); const Method **methods = summ.getMethods(); uint32 methodCount = summ.getMethodCount(); /* Now go through each method and see if it is overloaded. */ TemporaryBuffer overbuf(methodCount*sizeof(bool)); bool *overloadedMethods = (bool *) (char *) overbuf; for (i = 0; i < methodCount; i++) { const char *methodName = methods[i]->getName(); overloadedMethods[i] = false; for (int j = 0; j < methodCount; ++j) if (i != j && strcmp(methodName, methods[j]->getName()) == 0) overloadedMethods[i] = true; } /* Now go through each native method and generate a declaration for it */ NetscapeShortMangler smangler; NetscapeLongMangler lmangler; /* extern "C" the generated method headers */ PR_fprintf(fp, "extern \"C\" {\n"); for (i = 0; i < methodCount; i++) { Method *m = (Method *) methods[i]; const Signature &sig = m->getSignature(); if ((m->getModifiers() & CR_METHOD_NATIVE)) { /* Generate the return type */ char *retString = getArgString(*sig.resultType); const char *methodName = m->getName(); const char *signature = const_cast(m)->getSignatureString(); if (!retString) return false; int32 len = PL_strlen(methodName) + PL_strlen(className)*2 + PL_strlen(signature)*2 + sizeof("Netscape_Java___"); TemporaryBuffer copy(len); char *mangledMethodName = copy; if (overloadedMethods[i]) { if (!lmangler.mangle(className, methodName, signature, mangledMethodName, len)) continue; } else { if (!smangler.mangle(className, methodName, signature, mangledMethodName, len)) continue; } PR_fprintf(fp, "\n/*\n"); PR_fprintf(fp, " * Class : %s\n", className); PR_fprintf(fp, " * Method : %s\n", methodName); PR_fprintf(fp, " * Signature : %s\n", signature); PR_fprintf(fp, " */\n"); PR_fprintf(fp, "NS_EXPORT NS_NATIVECALL(%s)\n%s(", retString, mangledMethodName); // Kills the release build since NSPR needs to give us a clean way to // free strings that it allocates #ifdef DEBUG //free(retString); #endif for (uint32 j = 0; j < sig.nArguments; j++) { char *typeString = getArgString(*sig.argumentTypes[j]); if (!typeString) return false; if (j == 0) PR_fprintf(fp, "%s", typeString); else PR_fprintf(fp, ", %s", typeString); // Currently does not work with the release build since NSPR needs to // give us a clean way of freeing strings that it allocates #ifdef DEBUG //free(typeString); #endif } PR_fprintf(fp, ");\n\n"); } } /* Matches the extern "C" declaration generated earlier */ PR_fprintf(fp, "}\n"); return true; }