1998-05-19 15:59:53 +00:00
|
|
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
|
|
|
*
|
|
|
|
* The contents of this file are subject to the Netscape Public License
|
|
|
|
* Version 1.0 (the "NPL"); you may not use this file except in
|
|
|
|
* compliance with the NPL. You may obtain a copy of the NPL at
|
|
|
|
* http://www.mozilla.org/NPL/
|
|
|
|
*
|
|
|
|
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
|
|
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
|
|
|
* for the specific language governing rights and limitations under the
|
|
|
|
* NPL.
|
|
|
|
*
|
|
|
|
* The Initial Developer of this code under the NPL is Netscape
|
|
|
|
* Communications Corporation. Portions created by Netscape are
|
|
|
|
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
|
|
|
* Reserved.
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <fstream.h>
|
|
|
|
#include <ctype.h>
|
1998-06-03 23:32:26 +00:00
|
|
|
#include "plhash.h"
|
1998-05-19 15:59:53 +00:00
|
|
|
#include "FileGen.h"
|
1998-06-03 23:32:26 +00:00
|
|
|
#include "IdlSpecification.h"
|
1998-05-19 15:59:53 +00:00
|
|
|
#include "IdlObject.h"
|
|
|
|
#include "IdlVariable.h"
|
|
|
|
#include "IdlParameter.h"
|
1998-06-03 23:32:26 +00:00
|
|
|
#include "IdlAttribute.h"
|
|
|
|
#include "IdlFunction.h"
|
1998-05-19 15:59:53 +00:00
|
|
|
#include "IdlInterface.h"
|
|
|
|
|
|
|
|
static const char *kNPLStr = \
|
1998-06-03 23:32:26 +00:00
|
|
|
"/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-\n"
|
|
|
|
" *\n"
|
|
|
|
" * The contents of this file are subject to the Netscape Public License\n"
|
|
|
|
" * Version 1.0 (the \"NPL\"); you may not use this file except in\n"
|
|
|
|
" * compliance with the NPL. You may obtain a copy of the NPL at\n"
|
|
|
|
" * http://www.mozilla.org/NPL/\n"
|
|
|
|
" *\n"
|
|
|
|
" * Software distributed under the NPL is distributed on an \"AS IS\" basis,\n"
|
|
|
|
" * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL\n"
|
|
|
|
" * for the specific language governing rights and limitations under the\n"
|
|
|
|
" * NPL.\n"
|
|
|
|
" *\n"
|
|
|
|
" * The Initial Developer of this code under the NPL is Netscape\n"
|
|
|
|
" * Communications Corporation. Portions created by Netscape are\n"
|
|
|
|
" * Copyright (C) 1998 Netscape Communications Corporation. All Rights\n"
|
|
|
|
" * Reserved.\n"
|
|
|
|
" */\n";
|
1998-05-19 15:59:53 +00:00
|
|
|
static const char *kDisclaimerStr = "/* AUTO-GENERATED. DO NOT EDIT!!! */\n";
|
|
|
|
static const char *kObjTypeStr = "nsIDOM%s*";
|
1998-06-03 23:32:26 +00:00
|
|
|
static const char *kObjTypePtrStr = "nsIDOM%sPtr";
|
1998-05-19 15:59:53 +00:00
|
|
|
static const char *kUuidStr = "NS_IDOM%s_IID";
|
1999-03-10 19:55:00 +00:00
|
|
|
static const char *kXPIDLObjTypeStr = "%s*";
|
|
|
|
static const char *kXPIDLObjTypePtrStr = "%sPtr";
|
|
|
|
static const char *kXPIDLUuidStr = "NS_I%s_IID";
|
1998-05-19 15:59:53 +00:00
|
|
|
|
|
|
|
FileGen::FileGen()
|
|
|
|
{
|
|
|
|
mOutputFile = new ofstream();
|
|
|
|
}
|
|
|
|
|
|
|
|
FileGen::~FileGen()
|
|
|
|
{
|
|
|
|
delete mOutputFile;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
FileGen::OpenFile(char *aFileName, char *aOutputDirName,
|
1998-06-03 23:32:26 +00:00
|
|
|
const char *aFilePrefix, const char *aFileSuffix)
|
1998-05-19 15:59:53 +00:00
|
|
|
{
|
|
|
|
char file_buf[512];
|
|
|
|
|
|
|
|
if (aOutputDirName) {
|
|
|
|
strcpy(file_buf, aOutputDirName);
|
|
|
|
strcat(file_buf, "/");
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
file_buf[0] = '\0';
|
|
|
|
}
|
|
|
|
strcat(file_buf, aFilePrefix);
|
|
|
|
strcat(file_buf, strtok(aFileName, "."));
|
|
|
|
strcat(file_buf, ".");
|
|
|
|
strcat(file_buf, aFileSuffix);
|
|
|
|
|
|
|
|
mOutputFile->open(file_buf);
|
|
|
|
return mOutputFile->is_open();
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
FileGen::CloseFile()
|
|
|
|
{
|
|
|
|
mOutputFile->close();
|
|
|
|
mOutputFile->clear();
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
FileGen::GenerateNPL()
|
|
|
|
{
|
|
|
|
*mOutputFile << kNPLStr;
|
|
|
|
*mOutputFile << kDisclaimerStr;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
1998-06-03 23:32:26 +00:00
|
|
|
FileGen::GetVariableTypeForMethodLocal(char *aBuffer, IdlVariable &aVariable)
|
1998-05-19 15:59:53 +00:00
|
|
|
{
|
|
|
|
switch (aVariable.GetType()) {
|
|
|
|
case TYPE_BOOLEAN:
|
1998-06-03 23:32:26 +00:00
|
|
|
strcpy(aBuffer, "PRBool");
|
|
|
|
break;
|
1998-05-19 15:59:53 +00:00
|
|
|
case TYPE_LONG:
|
1998-06-03 23:32:26 +00:00
|
|
|
strcpy(aBuffer, "PRInt32");
|
|
|
|
break;
|
1998-05-19 15:59:53 +00:00
|
|
|
case TYPE_SHORT:
|
1998-06-03 23:32:26 +00:00
|
|
|
strcpy(aBuffer, "PRInt32");
|
|
|
|
break;
|
1998-05-19 15:59:53 +00:00
|
|
|
case TYPE_ULONG:
|
1998-06-03 23:32:26 +00:00
|
|
|
strcpy(aBuffer, "PRUint32");
|
|
|
|
break;
|
1998-05-19 15:59:53 +00:00
|
|
|
case TYPE_USHORT:
|
1998-06-03 23:32:26 +00:00
|
|
|
strcpy(aBuffer, "PRUint32");
|
|
|
|
break;
|
1998-05-19 15:59:53 +00:00
|
|
|
case TYPE_CHAR:
|
1998-06-03 23:32:26 +00:00
|
|
|
strcpy(aBuffer, "PRUint32");
|
|
|
|
break;
|
1998-05-19 15:59:53 +00:00
|
|
|
case TYPE_INT:
|
1998-06-03 23:32:26 +00:00
|
|
|
strcpy(aBuffer, "PRInt32");
|
|
|
|
break;
|
1998-05-19 15:59:53 +00:00
|
|
|
case TYPE_UINT:
|
1998-06-03 23:32:26 +00:00
|
|
|
strcpy(aBuffer, "PRUint32");
|
|
|
|
break;
|
1998-05-19 15:59:53 +00:00
|
|
|
case TYPE_STRING:
|
1998-06-03 23:32:26 +00:00
|
|
|
strcpy(aBuffer, "nsAutoString");
|
|
|
|
break;
|
1998-05-19 15:59:53 +00:00
|
|
|
case TYPE_OBJECT:
|
1998-06-03 23:32:26 +00:00
|
|
|
sprintf(aBuffer, kObjTypePtrStr, aVariable.GetTypeName());
|
|
|
|
break;
|
1999-03-10 19:55:00 +00:00
|
|
|
case TYPE_XPIDL_OBJECT:
|
|
|
|
sprintf(aBuffer, kXPIDLObjTypePtrStr, aVariable.GetTypeName());
|
1999-03-28 22:19:42 +00:00
|
|
|
break;
|
|
|
|
case TYPE_FUNC:
|
|
|
|
sprintf(aBuffer, kObjTypeStr, aVariable.GetTypeName());
|
|
|
|
break;
|
1998-05-19 15:59:53 +00:00
|
|
|
default:
|
1998-06-03 23:32:26 +00:00
|
|
|
// XXX Fail for other cases
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
FileGen::GetVariableTypeForLocal(char *aBuffer, IdlVariable &aVariable)
|
|
|
|
{
|
|
|
|
switch (aVariable.GetType()) {
|
|
|
|
case TYPE_BOOLEAN:
|
|
|
|
strcpy(aBuffer, "PRBool");
|
|
|
|
break;
|
|
|
|
case TYPE_LONG:
|
|
|
|
strcpy(aBuffer, "PRInt32");
|
|
|
|
break;
|
|
|
|
case TYPE_SHORT:
|
|
|
|
strcpy(aBuffer, "PRInt16");
|
|
|
|
break;
|
|
|
|
case TYPE_ULONG:
|
|
|
|
strcpy(aBuffer, "PRUint32");
|
|
|
|
break;
|
|
|
|
case TYPE_USHORT:
|
|
|
|
strcpy(aBuffer, "PRUint16");
|
|
|
|
break;
|
|
|
|
case TYPE_CHAR:
|
|
|
|
strcpy(aBuffer, "PRUint8");
|
|
|
|
break;
|
|
|
|
case TYPE_INT:
|
|
|
|
strcpy(aBuffer, "PRInt32");
|
|
|
|
break;
|
|
|
|
case TYPE_UINT:
|
|
|
|
strcpy(aBuffer, "PRUint32");
|
|
|
|
break;
|
|
|
|
case TYPE_STRING:
|
|
|
|
strcpy(aBuffer, "nsAutoString");
|
|
|
|
break;
|
|
|
|
case TYPE_OBJECT:
|
|
|
|
sprintf(aBuffer, kObjTypeStr, aVariable.GetTypeName());
|
|
|
|
break;
|
1999-03-10 19:55:00 +00:00
|
|
|
case TYPE_XPIDL_OBJECT:
|
|
|
|
sprintf(aBuffer, kXPIDLObjTypeStr, aVariable.GetTypeName());
|
|
|
|
break;
|
1999-03-28 22:19:42 +00:00
|
|
|
case TYPE_FUNC:
|
|
|
|
sprintf(aBuffer, kObjTypeStr, aVariable.GetTypeName());
|
|
|
|
break;
|
1998-06-03 23:32:26 +00:00
|
|
|
default:
|
|
|
|
// XXX Fail for other cases
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
FileGen::GetVariableTypeForParameter(char *aBuffer, IdlVariable &aVariable)
|
|
|
|
{
|
|
|
|
switch (aVariable.GetType()) {
|
|
|
|
case TYPE_BOOLEAN:
|
|
|
|
strcpy(aBuffer, "PRBool");
|
|
|
|
break;
|
|
|
|
case TYPE_LONG:
|
|
|
|
strcpy(aBuffer, "PRInt32");
|
|
|
|
break;
|
|
|
|
case TYPE_SHORT:
|
|
|
|
strcpy(aBuffer, "PRInt16");
|
|
|
|
break;
|
|
|
|
case TYPE_ULONG:
|
|
|
|
strcpy(aBuffer, "PRUint32");
|
|
|
|
break;
|
|
|
|
case TYPE_USHORT:
|
|
|
|
strcpy(aBuffer, "PRUint16");
|
|
|
|
break;
|
|
|
|
case TYPE_CHAR:
|
|
|
|
strcpy(aBuffer, "PRUint8");
|
|
|
|
break;
|
|
|
|
case TYPE_INT:
|
|
|
|
strcpy(aBuffer, "PRInt32");
|
|
|
|
break;
|
|
|
|
case TYPE_UINT:
|
|
|
|
strcpy(aBuffer, "PRUint32");
|
|
|
|
break;
|
|
|
|
case TYPE_STRING:
|
|
|
|
strcpy(aBuffer, "nsString&");
|
|
|
|
break;
|
|
|
|
case TYPE_OBJECT:
|
|
|
|
sprintf(aBuffer, kObjTypeStr, aVariable.GetTypeName());
|
|
|
|
break;
|
1999-03-10 19:55:00 +00:00
|
|
|
case TYPE_XPIDL_OBJECT:
|
|
|
|
sprintf(aBuffer, kXPIDLObjTypeStr, aVariable.GetTypeName());
|
|
|
|
break;
|
1999-03-28 22:19:42 +00:00
|
|
|
case TYPE_FUNC:
|
|
|
|
sprintf(aBuffer, kObjTypeStr, aVariable.GetTypeName());
|
|
|
|
break;
|
1998-06-03 23:32:26 +00:00
|
|
|
default:
|
|
|
|
// XXX Fail for other cases
|
|
|
|
break;
|
1998-05-19 15:59:53 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
FileGen::GetParameterType(char *aBuffer, IdlParameter &aParameter)
|
|
|
|
{
|
1998-06-03 23:32:26 +00:00
|
|
|
GetVariableTypeForParameter(aBuffer, aParameter);
|
1998-05-19 15:59:53 +00:00
|
|
|
|
|
|
|
switch (aParameter.GetAttribute()) {
|
1998-07-14 18:44:44 +00:00
|
|
|
case IdlParameter::INPUT:
|
|
|
|
if (aParameter.GetType() == TYPE_STRING) {
|
|
|
|
char buf[256];
|
|
|
|
|
|
|
|
strcpy(buf, "const ");
|
|
|
|
strcat(buf, aBuffer);
|
|
|
|
strcpy(aBuffer, buf);
|
|
|
|
}
|
|
|
|
break;
|
1998-05-19 15:59:53 +00:00
|
|
|
case IdlParameter::OUTPUT:
|
|
|
|
case IdlParameter::INOUT:
|
|
|
|
if (aParameter.GetType() != TYPE_STRING) {
|
1998-06-03 23:32:26 +00:00
|
|
|
strcat (aBuffer, "*");
|
1998-05-19 15:59:53 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
1998-06-03 23:32:26 +00:00
|
|
|
FileGen::GetInterfaceIID(char *aBuffer, char *aInterfaceName)
|
1998-05-19 15:59:53 +00:00
|
|
|
{
|
|
|
|
char buf[256];
|
|
|
|
|
1998-06-03 23:32:26 +00:00
|
|
|
strcpy(buf, aInterfaceName);
|
|
|
|
StrUpr(buf);
|
1998-05-19 15:59:53 +00:00
|
|
|
|
|
|
|
sprintf(aBuffer, kUuidStr, buf);
|
|
|
|
}
|
|
|
|
|
1998-06-03 23:32:26 +00:00
|
|
|
void
|
|
|
|
FileGen::GetInterfaceIID(char *aBuffer, IdlInterface &aInterface)
|
|
|
|
{
|
|
|
|
GetInterfaceIID(aBuffer, aInterface.GetName());
|
|
|
|
}
|
|
|
|
|
1999-03-10 19:55:00 +00:00
|
|
|
void
|
|
|
|
FileGen::GetXPIDLInterfaceIID(char* aBuffer, char* aInterfaceName)
|
|
|
|
{
|
|
|
|
char buf[256];
|
|
|
|
|
|
|
|
strcpy(buf, aInterfaceName);
|
|
|
|
StrUpr(buf);
|
|
|
|
|
|
|
|
sprintf(aBuffer, kXPIDLUuidStr, buf);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
FileGen::GetXPIDLInterfaceIID(char* aBuffer, IdlInterface &aInterface)
|
|
|
|
{
|
|
|
|
GetInterfaceIID(aBuffer, aInterface.GetName());
|
|
|
|
}
|
|
|
|
|
1998-05-19 15:59:53 +00:00
|
|
|
void
|
|
|
|
FileGen::GetCapitalizedName(char *aBuffer, IdlObject &aObject)
|
|
|
|
{
|
|
|
|
strcpy(aBuffer, aObject.GetName());
|
|
|
|
if ((aBuffer[0] >= 'a') && (aBuffer[0] <= 'z')) {
|
|
|
|
aBuffer[0] += ('A' - 'a');
|
|
|
|
}
|
|
|
|
}
|
1998-06-03 23:32:26 +00:00
|
|
|
|
|
|
|
void
|
|
|
|
FileGen::StrUpr(char *aBuffer)
|
|
|
|
{
|
|
|
|
char *cur_ptr = aBuffer;
|
|
|
|
|
|
|
|
while (*cur_ptr != 0) {
|
|
|
|
if ((*cur_ptr >= 'a') && (*cur_ptr <= 'z')) {
|
|
|
|
*cur_ptr += ('A' - 'a');
|
|
|
|
}
|
|
|
|
cur_ptr++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1999-05-26 21:43:28 +00:00
|
|
|
void
|
|
|
|
FileGen::StrLwr(char *aBuffer)
|
|
|
|
{
|
|
|
|
char *cur_ptr = aBuffer;
|
|
|
|
|
|
|
|
while (*cur_ptr != 0) {
|
|
|
|
if ((*cur_ptr >= 'A') && (*cur_ptr <= 'Z')) {
|
|
|
|
*cur_ptr += ('a' - 'A');
|
|
|
|
}
|
|
|
|
cur_ptr++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1998-08-04 00:08:29 +00:00
|
|
|
void
|
|
|
|
FileGen::CollectAllInInterface(IdlInterface &aInterface,
|
|
|
|
PLHashTable *aTable)
|
|
|
|
{
|
|
|
|
int a, acount = aInterface.AttributeCount();
|
|
|
|
for (a = 0; a < acount; a++) {
|
|
|
|
IdlAttribute *attr = aInterface.GetAttributeAt(a);
|
|
|
|
|
1999-03-10 19:55:00 +00:00
|
|
|
if (((attr->GetType() == TYPE_OBJECT) || (attr->GetType() == TYPE_XPIDL_OBJECT)) &&
|
1998-08-04 00:08:29 +00:00
|
|
|
!PL_HashTableLookup(aTable, attr->GetTypeName())) {
|
1999-03-10 19:55:00 +00:00
|
|
|
PL_HashTableAdd(aTable, attr->GetTypeName(), (void *)(attr->GetType()));
|
1998-08-04 00:08:29 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int m, mcount = aInterface.FunctionCount();
|
|
|
|
for (m = 0; m < mcount; m++) {
|
|
|
|
IdlFunction *func = aInterface.GetFunctionAt(m);
|
|
|
|
IdlVariable *rval = func->GetReturnValue();
|
|
|
|
|
1999-03-10 19:55:00 +00:00
|
|
|
if (((rval->GetType() == TYPE_OBJECT) || (rval->GetType() == TYPE_XPIDL_OBJECT)) &&
|
1998-08-04 00:08:29 +00:00
|
|
|
!PL_HashTableLookup(aTable, rval->GetTypeName())) {
|
1999-03-10 19:55:00 +00:00
|
|
|
PL_HashTableAdd(aTable, rval->GetTypeName(), (void *)(rval->GetType()));
|
1998-08-04 00:08:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int p, pcount = func->ParameterCount();
|
|
|
|
for (p = 0; p < pcount; p++) {
|
|
|
|
IdlParameter *param = func->GetParameterAt(p);
|
|
|
|
|
1999-03-28 22:19:42 +00:00
|
|
|
if (((param->GetType() == TYPE_OBJECT) || (param->GetType() == TYPE_XPIDL_OBJECT)
|
|
|
|
|| (param->GetType() == TYPE_FUNC)) && !PL_HashTableLookup(aTable, param->GetTypeName())) {
|
1999-03-10 19:55:00 +00:00
|
|
|
PL_HashTableAdd(aTable, param->GetTypeName(), (void *)(param->GetType()));
|
1998-08-04 00:08:29 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
FileGen::EnumerateAllObjects(IdlInterface &aInterface,
|
|
|
|
PLHashEnumerator aEnumerator,
|
|
|
|
void *aArg)
|
|
|
|
{
|
|
|
|
PLHashTable *htable = PL_NewHashTable(10, PL_HashString,
|
|
|
|
PL_CompareStrings,
|
|
|
|
PL_CompareValues,
|
|
|
|
(PLHashAllocOps *)NULL, NULL);
|
|
|
|
|
|
|
|
CollectAllInInterface(aInterface, htable);
|
|
|
|
|
|
|
|
PL_HashTableEnumerateEntries(htable, aEnumerator, aArg);
|
|
|
|
PL_HashTableDestroy(htable);
|
|
|
|
}
|
|
|
|
|
1998-06-03 23:32:26 +00:00
|
|
|
void
|
|
|
|
FileGen::EnumerateAllObjects(IdlSpecification &aSpec,
|
|
|
|
PLHashEnumerator aEnumerator,
|
|
|
|
void *aArg,
|
|
|
|
PRBool aOnlyPrimary)
|
|
|
|
{
|
|
|
|
PLHashTable *htable = PL_NewHashTable(10, PL_HashString,
|
|
|
|
PL_CompareStrings,
|
|
|
|
PL_CompareValues,
|
|
|
|
(PLHashAllocOps *)NULL, NULL);
|
|
|
|
|
|
|
|
int i, icount = aSpec.InterfaceCount();
|
|
|
|
for (i = 0; i < icount; i++) {
|
|
|
|
IdlInterface *iface = aSpec.GetInterfaceAt(i);
|
|
|
|
|
|
|
|
if (((i == 0) || !aOnlyPrimary) &&
|
|
|
|
!PL_HashTableLookup(htable, iface->GetName())) {
|
1999-03-10 19:55:00 +00:00
|
|
|
PL_HashTableAdd(htable, iface->GetName(), (void *)(int)TYPE_OBJECT);
|
1998-06-03 23:32:26 +00:00
|
|
|
}
|
1998-08-04 00:08:29 +00:00
|
|
|
|
|
|
|
CollectAllInInterface(*iface, htable);
|
1998-06-03 23:32:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
PL_HashTableEnumerateEntries(htable, aEnumerator, aArg);
|
|
|
|
PL_HashTableDestroy(htable);
|
|
|
|
}
|
1998-09-17 01:53:52 +00:00
|
|
|
|
|
|
|
PRBool
|
|
|
|
FileGen::HasConstructor(IdlInterface &aInterface, IdlFunction **aConstructor)
|
|
|
|
{
|
|
|
|
int m, mcount = aInterface.FunctionCount();
|
|
|
|
for (m = 0; m < mcount; m++) {
|
|
|
|
IdlFunction *func = aInterface.GetFunctionAt(m);
|
|
|
|
if (strcmp(func->GetName(), aInterface.GetName()) == 0) {
|
|
|
|
if (NULL != aConstructor) {
|
|
|
|
*aConstructor = func;
|
|
|
|
}
|
|
|
|
return PR_TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return PR_FALSE;
|
|
|
|
}
|
|
|
|
|