Compare commits
2 Commits
NSPR_4_6_B
...
regalloc_c
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1c43d4984f | ||
|
|
cfe021ff88 |
134
mozilla/ef/Compiler/RegisterAllocator/BitSet.cpp
Normal file
134
mozilla/ef/Compiler/RegisterAllocator/BitSet.cpp
Normal file
@@ -0,0 +1,134 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* 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 "Fundamentals.h"
|
||||
#include "BitSet.h"
|
||||
|
||||
// Return the next bit after index set to true or -1 if none.
|
||||
//
|
||||
Int32 BitSet::nextOne(Int32 pos) const
|
||||
{
|
||||
++pos;
|
||||
|
||||
if (pos < 0 || Uint32(pos) >= universeSize)
|
||||
return -1;
|
||||
|
||||
Uint32 offset = getWordOffset(pos);
|
||||
Uint8 index = getBitOffset(pos);
|
||||
Word* ptr = &word[offset];
|
||||
Word currentWord = *ptr++ >> index;
|
||||
|
||||
if (currentWord != Word(0)) {
|
||||
while ((currentWord & Word(1)) == 0) {
|
||||
++index;
|
||||
currentWord >>= 1;
|
||||
}
|
||||
return (offset << nBitsInWordLog2) + index;
|
||||
}
|
||||
|
||||
Word* limit = &word[getSizeInWords(universeSize)];
|
||||
while (ptr < limit) {
|
||||
++offset;
|
||||
currentWord = *ptr++;
|
||||
if (currentWord != Word(0)) {
|
||||
index = 0;
|
||||
while ((currentWord & Word(1)) == 0) {
|
||||
++index;
|
||||
currentWord >>= 1;
|
||||
}
|
||||
return (offset << nBitsInWordLog2) + index;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Return the next bit after index set to false or -1 if none.
|
||||
//
|
||||
Int32 BitSet::nextZero(Int32 pos) const
|
||||
{
|
||||
++pos;
|
||||
|
||||
if (pos < 0 || Uint32(pos) >= universeSize)
|
||||
return -1;
|
||||
|
||||
Uint32 offset = getWordOffset(pos);
|
||||
Uint8 index = getBitOffset(pos);
|
||||
Word* ptr = &word[offset];
|
||||
Word currentWord = *ptr++ >> index;
|
||||
|
||||
if (currentWord != Word(~0)) {
|
||||
for (; index < nBitsInWord; ++index) {
|
||||
if ((currentWord & Word(1)) == 0) {
|
||||
Int32 ret = (offset << nBitsInWordLog2) + index;
|
||||
return (Uint32(ret) < universeSize) ? ret : -1;
|
||||
}
|
||||
currentWord >>= 1;
|
||||
}
|
||||
}
|
||||
|
||||
Word* limit = &word[getSizeInWords(universeSize)];
|
||||
while (ptr < limit) {
|
||||
++offset;
|
||||
currentWord = *ptr++;
|
||||
if (currentWord != Word(~0)) {
|
||||
for (index = 0; index < nBitsInWord; ++index) {
|
||||
if ((currentWord & Word(1)) == 0) {
|
||||
Int32 ret = (offset << nBitsInWordLog2) + index;
|
||||
return (Uint32(ret) < universeSize) ? ret : -1;
|
||||
}
|
||||
currentWord >>= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_LOG
|
||||
|
||||
// Print the set.
|
||||
//
|
||||
void BitSet::printPretty(LogModuleObject log)
|
||||
{
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("[ "));
|
||||
|
||||
for (Int32 i = firstOne(); i != -1; i = nextOne(i)) {
|
||||
Int32 currentBit = i;
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("%d", currentBit));
|
||||
|
||||
Int32 nextBit = nextOne(currentBit);
|
||||
if (nextBit != currentBit + 1) {
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, (" "));
|
||||
continue;
|
||||
}
|
||||
|
||||
while ((nextBit != -1) && (nextBit == (currentBit + 1))) {
|
||||
currentBit = nextBit;
|
||||
nextBit = nextOne(nextBit);
|
||||
}
|
||||
|
||||
if (currentBit > (i+1))
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("-%d ", currentBit));
|
||||
else
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, (" %d ", currentBit));
|
||||
|
||||
i = currentBit;
|
||||
}
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("]\n"));
|
||||
}
|
||||
|
||||
#endif // DEBUG_LOG
|
||||
195
mozilla/ef/Compiler/RegisterAllocator/BitSet.h
Normal file
195
mozilla/ef/Compiler/RegisterAllocator/BitSet.h
Normal file
@@ -0,0 +1,195 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef _BITSET_H_
|
||||
#define _BITSET_H_
|
||||
|
||||
#include "Fundamentals.h"
|
||||
#include "LogModule.h"
|
||||
#include "Pool.h"
|
||||
#include <string.h>
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// BitSet -
|
||||
|
||||
class BitSet
|
||||
{
|
||||
private:
|
||||
|
||||
#if (PR_BITS_PER_WORD == 64)
|
||||
typedef Uint64 Word;
|
||||
#elif (PR_BITS_PER_WORD == 32)
|
||||
typedef Uint32 Word;
|
||||
#endif
|
||||
|
||||
static const nBitsInWord = PR_BITS_PER_WORD;
|
||||
static const nBytesInWord = PR_BYTES_PER_WORD;
|
||||
static const nBitsInWordLog2 = PR_BITS_PER_WORD_LOG2;
|
||||
static const nBytesInWordLog2 = PR_BYTES_PER_WORD_LOG2;
|
||||
|
||||
// Return the number of Word need to store the universe.
|
||||
static Uint32 getSizeInWords(Uint32 sizeOfUniverse) {return (sizeOfUniverse + (nBitsInWord - 1)) >> nBitsInWordLog2;}
|
||||
// Return the given element offset in its containing Word.
|
||||
static Uint32 getBitOffset(Uint32 element) {return element & (nBitsInWord - 1);}
|
||||
// Return the Word offset for the given element int the universe.
|
||||
static Uint32 getWordOffset(Uint32 element) {return element >> nBitsInWordLog2;}
|
||||
// Return the mask for the given bit index.
|
||||
static Word getMask(Uint8 index) {return Word(1) << index;}
|
||||
|
||||
private:
|
||||
|
||||
Uint32 universeSize; // Size of the universe
|
||||
Word* word; // universe memory.
|
||||
|
||||
private:
|
||||
|
||||
// No copy constructor.
|
||||
BitSet(const BitSet&);
|
||||
|
||||
// Check if the given set's universe is of the same size than this universe.
|
||||
void checkUniverseCompatibility(const BitSet& set) const {assert(set.universeSize == universeSize);}
|
||||
// Check if pos is valid for this set's universe.
|
||||
void checkMember(Int32 pos) const {assert(pos >=0 && Uint32(pos) < universeSize);}
|
||||
|
||||
public:
|
||||
|
||||
// Create a bitset of universeSize bits.
|
||||
BitSet(Pool& pool, Uint32 universeSize) : universeSize(universeSize) {word = new(pool) Word[getSizeInWords(universeSize)]; clear();}
|
||||
|
||||
// Return the size of this bitset.
|
||||
Uint32 getSize() const {return universeSize;}
|
||||
|
||||
// Clear the bitset.
|
||||
void clear() {memset(word, 0x00, getSizeInWords(universeSize) << nBytesInWordLog2);}
|
||||
// Clear the bit at index.
|
||||
void clear(Uint32 index) {checkMember(index); word[getWordOffset(index)] &= ~getMask(index);}
|
||||
// Set the bitset.
|
||||
void set() {memset(word, 0xFF, getSizeInWords(universeSize) << nBytesInWordLog2);}
|
||||
// Set the bit at index.
|
||||
void set(Uint32 index) {checkMember(index); word[getWordOffset(index)] |= getMask(index);}
|
||||
// Return true if the bit at index is set.
|
||||
bool test(Uint32 index) const {checkMember(index); return (word[getWordOffset(index)] & getMask(index)) != 0;}
|
||||
// Union with the given bitset.
|
||||
inline void or(const BitSet& set);
|
||||
// Intersection with the given bitset.
|
||||
inline void and(const BitSet& set);
|
||||
// Difference with the given bitset.
|
||||
inline void difference(const BitSet& set);
|
||||
// Copy set.
|
||||
inline BitSet& operator = (const BitSet& set);
|
||||
// Return true if the bitset are identical.
|
||||
friend bool operator == (const BitSet& set1, const BitSet& set2);
|
||||
// Return true if the bitset are different.
|
||||
friend bool operator != (const BitSet& set1, const BitSet& set2);
|
||||
|
||||
// Logical operators.
|
||||
BitSet& operator |= (const BitSet& set) {or(set); return *this;}
|
||||
BitSet& operator &= (const BitSet& set) {and(set); return *this;}
|
||||
BitSet& operator -= (const BitSet& set) {difference(set); return *this;}
|
||||
|
||||
// Return the first bit at set to true or -1 if none.
|
||||
Int32 firstOne() const {return nextOne(-1);}
|
||||
// Return the next bit after index set to true or -1 if none.
|
||||
Int32 nextOne(Int32 pos) const;
|
||||
// Return the first bit at set to false or -1 if none.
|
||||
Int32 firstZero() const {return nextZero(-1);}
|
||||
// Return the next bit after index set to false or -1 if none.
|
||||
Int32 nextZero(Int32 pos) const;
|
||||
|
||||
// Iterator to conform with the set API.
|
||||
typedef Int32 iterator;
|
||||
// Return true if the walk is ordered.
|
||||
static bool isOrdered() {return true;}
|
||||
// Return the iterator for the first element of this set.
|
||||
iterator begin() const {return firstOne();}
|
||||
// Return the next iterator.
|
||||
iterator advance(iterator pos) const {return nextOne(pos);}
|
||||
// Return true if the iterator is at the end of the set.
|
||||
bool done(iterator pos) const {return pos == -1;}
|
||||
// Return the element corresponding to the given iterator.
|
||||
Uint32 get(iterator pos) const {return pos;}
|
||||
|
||||
#ifdef DEBUG_LOG
|
||||
// Print the set.
|
||||
void printPretty(LogModuleObject log);
|
||||
#endif // DEBUG_LOG
|
||||
};
|
||||
|
||||
// Union with the given bitset.
|
||||
//
|
||||
inline void BitSet::or(const BitSet& set)
|
||||
{
|
||||
checkUniverseCompatibility(set);
|
||||
Word* src = set.word;
|
||||
Word* dst = word;
|
||||
Word* limit = &src[getSizeInWords(universeSize)];
|
||||
|
||||
while (src < limit)
|
||||
*dst++ |= *src++;
|
||||
}
|
||||
|
||||
// Intersection with the given bitset.
|
||||
//
|
||||
inline void BitSet::and(const BitSet& set)
|
||||
{
|
||||
checkUniverseCompatibility(set);
|
||||
Word* src = set.word;
|
||||
Word* dst = word;
|
||||
Word* limit = &src[getSizeInWords(universeSize)];
|
||||
|
||||
while (src < limit)
|
||||
*dst++ &= *src++;
|
||||
}
|
||||
|
||||
// Difference with the given bitset.
|
||||
//
|
||||
inline void BitSet::difference(const BitSet& set)
|
||||
{
|
||||
checkUniverseCompatibility(set);
|
||||
Word* src = set.word;
|
||||
Word* dst = word;
|
||||
Word* limit = &src[getSizeInWords(universeSize)];
|
||||
|
||||
while (src < limit)
|
||||
*dst++ &= ~*src++;
|
||||
}
|
||||
|
||||
// Copy the given set into this set.
|
||||
//
|
||||
inline BitSet& BitSet::operator = (const BitSet& set)
|
||||
{
|
||||
checkUniverseCompatibility(set);
|
||||
if (this != &set)
|
||||
memcpy(word, set.word, getSizeInWords(universeSize) << nBytesInWordLog2);
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Return true if the given set is identical to this set.
|
||||
inline bool operator == (const BitSet& set1, const BitSet& set2)
|
||||
{
|
||||
set1.checkUniverseCompatibility(set2);
|
||||
|
||||
if (&set1 == &set2)
|
||||
return true;
|
||||
|
||||
return memcmp(set1.word, set2.word, BitSet::getSizeInWords(set1.universeSize) << BitSet::nBytesInWordLog2) == 0;
|
||||
}
|
||||
|
||||
inline bool operator != (const BitSet& set1, const BitSet& set2) {return !(set1 == set2);}
|
||||
|
||||
#endif // _BITSET_H
|
||||
159
mozilla/ef/Compiler/RegisterAllocator/Coalescing.h
Normal file
159
mozilla/ef/Compiler/RegisterAllocator/Coalescing.h
Normal file
@@ -0,0 +1,159 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef _COALESCING_H_
|
||||
#define _COALESCING_H_
|
||||
|
||||
#include "Fundamentals.h"
|
||||
#include "Pool.h"
|
||||
#include "RegisterPressure.h"
|
||||
#include "InterferenceGraph.h"
|
||||
#include "ControlGraph.h"
|
||||
#include "ControlNodes.h"
|
||||
#include "Instruction.h"
|
||||
#include "SparseSet.h"
|
||||
#include "RegisterAllocator.h"
|
||||
#include "RegisterAllocatorTools.h"
|
||||
|
||||
#if 1
|
||||
// Performing an ultra conservative coalescing meens that when we look at
|
||||
// candidates (source,destination) for coalescing we need to make sure
|
||||
// that the combined interference of the source and destination register
|
||||
// will not exceed the total number of register available for the register
|
||||
// class.
|
||||
#define ULTRA_CONSERVATIVE_COALESCING
|
||||
#else
|
||||
// If we are not doing an ultra conservative coalescing we have to make sure
|
||||
// that the total number of neighbor whose degree is greater than the total
|
||||
// number of register is not greater than the total number of register.
|
||||
#undef ULTRA_CONSERVATIVE_COALESCING
|
||||
#endif
|
||||
|
||||
template <class RegisterPressure>
|
||||
struct Coalescing
|
||||
{
|
||||
static bool coalesce(RegisterAllocator& registerAllocator);
|
||||
};
|
||||
|
||||
template <class RegisterPressure>
|
||||
bool Coalescing<RegisterPressure>::coalesce(RegisterAllocator& registerAllocator)
|
||||
{
|
||||
Pool& pool = registerAllocator.pool;
|
||||
|
||||
// Initialize the lookup table
|
||||
//
|
||||
Uint32 rangeCount = registerAllocator.rangeCount;
|
||||
RegisterName* newRange = new RegisterName[2 * rangeCount];
|
||||
RegisterName* coalescedRange = &newRange[rangeCount];
|
||||
RegisterName* name2range = registerAllocator.name2range;
|
||||
|
||||
init(coalescedRange, rangeCount);
|
||||
|
||||
SparseSet interferences(pool, rangeCount);
|
||||
InterferenceGraph<RegisterPressure>& iGraph = registerAllocator.iGraph;
|
||||
bool removedInstructions = false;
|
||||
|
||||
ControlGraph& controlGraph = registerAllocator.controlGraph;
|
||||
ControlNode** nodes = controlGraph.lndList;
|
||||
Uint32 nNodes = controlGraph.nNodes;
|
||||
|
||||
|
||||
// Walk the nodes in the loop nesting depth list.
|
||||
for (Int32 n = nNodes - 1; n >= 0; n--) {
|
||||
InstructionList& instructions = nodes[n]->getInstructions();
|
||||
|
||||
InstructionList::iterator it = instructions.begin();
|
||||
while (!instructions.done(it)) {
|
||||
Instruction& instruction = instructions.get(it);
|
||||
it = instructions.advance(it);
|
||||
|
||||
if ((instruction.getFlags() & ifCopy) != 0) {
|
||||
assert(instruction.getInstructionUseBegin() != instruction.getInstructionUseEnd() && instruction.getInstructionUseBegin()[0].isRegister());
|
||||
assert(instruction.getInstructionDefineBegin() != instruction.getInstructionDefineEnd() && instruction.getInstructionDefineBegin()[0].isRegister());
|
||||
|
||||
RegisterName source = findRoot(name2range[instruction.getInstructionUseBegin()[0].getRegisterName()], coalescedRange);
|
||||
RegisterName destination = findRoot(name2range[instruction.getInstructionDefineBegin()[0].getRegisterName()], coalescedRange);
|
||||
|
||||
if (source == destination) {
|
||||
instruction.remove();
|
||||
} else if (!iGraph.interfere(source, destination)) {
|
||||
InterferenceVector* sourceVector = iGraph.getInterferenceVector(source);
|
||||
InterferenceVector* destinationVector = iGraph.getInterferenceVector(destination);
|
||||
|
||||
#ifdef ULTRA_CONSERVATIVE_COALESCING
|
||||
interferences.clear();
|
||||
|
||||
InterferenceVector* vector;
|
||||
for (vector = sourceVector; vector != NULL; vector = vector->next) {
|
||||
RegisterName* neighbors = vector->neighbors;
|
||||
for (Uint32 i = 0; i < vector->count; i++)
|
||||
interferences.set(findRoot(neighbors[i], coalescedRange));
|
||||
}
|
||||
for (vector = destinationVector; vector != NULL; vector = vector->next) {
|
||||
RegisterName* neighbors = vector->neighbors;
|
||||
for (Uint32 i = 0; i < vector->count; i++)
|
||||
interferences.set(findRoot(neighbors[i], coalescedRange));
|
||||
}
|
||||
|
||||
Uint32 count = interferences.getSize();
|
||||
#else // ULTRA_CONSERVATIVE_COALESCING
|
||||
trespass("not implemented");
|
||||
Uint32 count = 0;
|
||||
#endif // ULTRA_CONSERVATIVE_COALESCING
|
||||
|
||||
if (count < 6 /* FIX: should get the number from the class */) {
|
||||
// Update the interferences vector.
|
||||
if (sourceVector == NULL) {
|
||||
iGraph.setInterferenceVector(source, destinationVector);
|
||||
sourceVector = destinationVector;
|
||||
} else if (destinationVector == NULL)
|
||||
iGraph.setInterferenceVector(destination, sourceVector);
|
||||
else {
|
||||
InterferenceVector* last = NULL;
|
||||
for (InterferenceVector* v = sourceVector; v != NULL; v = v->next)
|
||||
last = v;
|
||||
assert(last);
|
||||
last->next = destinationVector;
|
||||
iGraph.setInterferenceVector(destination, sourceVector);
|
||||
}
|
||||
// Update the interference matrix.
|
||||
for (InterferenceVector* v = sourceVector; v != NULL; v = v->next) {
|
||||
RegisterName* neighbors = v->neighbors;
|
||||
for (Uint32 i = 0; i < v->count; i++) {
|
||||
RegisterName neighbor = findRoot(neighbors[i], coalescedRange);
|
||||
iGraph.setInterference(neighbor, source);
|
||||
iGraph.setInterference(neighbor, destination);
|
||||
}
|
||||
}
|
||||
|
||||
instruction.remove();
|
||||
coalescedRange[source] = destination;
|
||||
removedInstructions = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
registerAllocator.rangeCount = compress(registerAllocator.name2range, coalescedRange, registerAllocator.nameCount, rangeCount);
|
||||
delete newRange;
|
||||
|
||||
return removedInstructions;
|
||||
}
|
||||
|
||||
#endif // _COALESCING_H_
|
||||
283
mozilla/ef/Compiler/RegisterAllocator/Coloring.cpp
Normal file
283
mozilla/ef/Compiler/RegisterAllocator/Coloring.cpp
Normal file
@@ -0,0 +1,283 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef NEW_LAURENTM_CODE
|
||||
|
||||
#include "Coloring.h"
|
||||
#include "VirtualRegister.h"
|
||||
#include "FastBitSet.h"
|
||||
#include "FastBitMatrix.h"
|
||||
#include "CpuInfo.h"
|
||||
|
||||
bool Coloring::
|
||||
assignRegisters(FastBitMatrix& interferenceMatrix)
|
||||
{
|
||||
PRUint32 *stackPtr = new(pool) PRUint32[vRegManager.count()];
|
||||
|
||||
return select(interferenceMatrix, stackPtr, simplify(interferenceMatrix, stackPtr));
|
||||
}
|
||||
|
||||
PRInt32 Coloring::
|
||||
getLowestSpillCostRegister(FastBitSet& bitset)
|
||||
{
|
||||
PRInt32 lowest = bitset.firstOne();
|
||||
if (lowest != -1)
|
||||
{
|
||||
Flt32 cost = vRegManager.getVirtualRegister(lowest).spillInfo.spillCost;
|
||||
for (PRInt32 r = bitset.nextOne(lowest); r != -1; r = bitset.nextOne(r))
|
||||
{
|
||||
VirtualRegister& vReg = vRegManager.getVirtualRegister(r);
|
||||
if (!vReg.spillInfo.infiniteSpillCost && (vReg.spillInfo.spillCost < cost))
|
||||
{
|
||||
cost = vReg.spillInfo.spillCost;
|
||||
lowest = r;
|
||||
}
|
||||
}
|
||||
}
|
||||
return lowest;
|
||||
}
|
||||
|
||||
PRUint32* Coloring::
|
||||
simplify(FastBitMatrix interferenceMatrix, PRUint32* stackPtr)
|
||||
{
|
||||
// first we construct the sets low and high. low contains all nodes of degree
|
||||
// inferior to the number of register available on the processor. All the
|
||||
// nodes with an high degree and a finite spill cost are placed in high.
|
||||
// Nodes of high degree and infinite spill cost are not included in either sets.
|
||||
|
||||
PRUint32 nRegisters = vRegManager.count();
|
||||
FastBitSet low(pool, nRegisters);
|
||||
FastBitSet high(pool, nRegisters);
|
||||
FastBitSet stack(pool, nRegisters);
|
||||
|
||||
for (VirtualRegisterManager::iterator i = vRegManager.begin(); !vRegManager.done(i); i = vRegManager.advance(i))
|
||||
{
|
||||
VirtualRegister& vReg = vRegManager.getVirtualRegister(i);
|
||||
|
||||
if (vReg.getClass() == vrcStackSlot)
|
||||
{
|
||||
stack.set(i);
|
||||
vReg.colorRegister(nRegisters);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (vReg.colorInfo.interferenceDegree < NUMBER_OF_REGISTERS)
|
||||
low.set(i);
|
||||
else // if (!vReg.spillInfo.infiniteSpillCost)
|
||||
high.set(i);
|
||||
|
||||
// Set coloring info.
|
||||
vReg.spillInfo.willSpill = false;
|
||||
|
||||
switch(vReg.getClass())
|
||||
{
|
||||
case vrcInteger:
|
||||
vReg.colorRegister(LAST_GREGISTER + 1);
|
||||
break;
|
||||
case vrcFloatingPoint:
|
||||
case vrcFixedPoint:
|
||||
vReg.colorRegister(LAST_FPREGISTER + 1);
|
||||
break;
|
||||
default:
|
||||
PR_ASSERT(false); // Cannot happen.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// push the stack registers
|
||||
PRInt32 j;
|
||||
for (j = stack.firstOne(); j != -1; j = stack.nextOne(j))
|
||||
*stackPtr++ = j;
|
||||
|
||||
// simplify
|
||||
while (true)
|
||||
{
|
||||
PRInt32 r;
|
||||
while ((r = getLowestSpillCostRegister(low)) != -1)
|
||||
{
|
||||
VirtualRegister& vReg = vRegManager.getVirtualRegister(r);
|
||||
|
||||
/* update low and high */
|
||||
FastBitSet inter(interferenceMatrix.getRow(r), nRegisters);
|
||||
for (j = inter.firstOne(); j != -1; j = inter.nextOne(j))
|
||||
{
|
||||
VirtualRegister& neighbor = vRegManager.getVirtualRegister(j);
|
||||
// if the new interference degree of one of his neighbor becomes
|
||||
// NUMBER_OF_REGISTERS - 1 then it is added to the set 'low'.
|
||||
|
||||
PRUint32 maxInterference = 0;
|
||||
switch (neighbor.getClass())
|
||||
{
|
||||
case vrcInteger:
|
||||
maxInterference = NUMBER_OF_GREGISTERS;
|
||||
break;
|
||||
case vrcFloatingPoint:
|
||||
case vrcFixedPoint:
|
||||
maxInterference = NUMBER_OF_FPREGISTERS;
|
||||
break;
|
||||
default:
|
||||
PR_ASSERT(false);
|
||||
}
|
||||
if ((vRegManager.getVirtualRegister(j).colorInfo.interferenceDegree-- == maxInterference))
|
||||
{
|
||||
high.clear(j);
|
||||
low.set(j);
|
||||
}
|
||||
vReg.colorInfo.interferenceDegree--;
|
||||
interferenceMatrix.clear(r, j);
|
||||
interferenceMatrix.clear(j, r);
|
||||
}
|
||||
low.clear(r);
|
||||
|
||||
// Push this register.
|
||||
*stackPtr++ = r;
|
||||
}
|
||||
if ((r = getLowestSpillCostRegister(high)) != -1)
|
||||
{
|
||||
high.clear(r);
|
||||
low.set(r);
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
return stackPtr;
|
||||
}
|
||||
|
||||
bool Coloring::
|
||||
select(FastBitMatrix& interferenceMatrix, PRUint32* stackBase, PRUint32* stackPtr)
|
||||
{
|
||||
PRUint32 nRegisters = vRegManager.count();
|
||||
FastBitSet usedRegisters(NUMBER_OF_REGISTERS + 1); // usedRegisters if used for both GR & FPR.
|
||||
FastBitSet preColoredRegisters(NUMBER_OF_REGISTERS + 1);
|
||||
FastBitSet usedStack(nRegisters + 1);
|
||||
bool success = true;
|
||||
Int32 lastUsedSSR = -1;
|
||||
|
||||
// select
|
||||
while (stackPtr != stackBase)
|
||||
{
|
||||
// Pop one register.
|
||||
PRUint32 r = *--stackPtr;
|
||||
VirtualRegister& vReg = vRegManager.getVirtualRegister(r);
|
||||
|
||||
FastBitSet neighbors(interferenceMatrix.getRow(r), nRegisters);
|
||||
|
||||
if (vReg.getClass() == vrcStackSlot)
|
||||
// Stack slots coloring.
|
||||
{
|
||||
usedStack.clear();
|
||||
|
||||
for (PRInt32 i = neighbors.firstOne(); i != -1; i = neighbors.nextOne(i))
|
||||
usedStack.set(vRegManager.getVirtualRegister(i).getColor());
|
||||
|
||||
Int32 color = usedStack.firstZero();
|
||||
vReg.colorRegister(color);
|
||||
if (color > lastUsedSSR)
|
||||
lastUsedSSR = color;
|
||||
}
|
||||
else
|
||||
// Integer & Floating point register coloring.
|
||||
{
|
||||
usedRegisters.clear();
|
||||
preColoredRegisters.clear();
|
||||
|
||||
for (PRInt32 i = neighbors.firstOne(); i != -1; i = neighbors.nextOne(i))
|
||||
{
|
||||
VirtualRegister& nvReg = vRegManager.getVirtualRegister(i);
|
||||
usedRegisters.set(nvReg.getColor());
|
||||
if (nvReg.isPreColored())
|
||||
preColoredRegisters.set(nvReg.getPreColor());
|
||||
}
|
||||
if (vReg.hasSpecialInterference)
|
||||
usedRegisters |= vReg.specialInterference;
|
||||
|
||||
PRInt8 c = -1;
|
||||
PRInt8 maxColor = 0;
|
||||
PRInt8 firstColor = 0;
|
||||
switch (vReg.getClass())
|
||||
{
|
||||
case vrcInteger:
|
||||
firstColor = FIRST_GREGISTER;
|
||||
maxColor = LAST_GREGISTER;
|
||||
break;
|
||||
case vrcFloatingPoint:
|
||||
case vrcFixedPoint:
|
||||
firstColor = FIRST_FPREGISTER;
|
||||
maxColor = LAST_FPREGISTER;
|
||||
break;
|
||||
default:
|
||||
PR_ASSERT(false);
|
||||
}
|
||||
|
||||
if (vReg.isPreColored())
|
||||
{
|
||||
c = vReg.getPreColor();
|
||||
if (usedRegisters.test(c))
|
||||
c = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (c = usedRegisters.nextZero(firstColor - 1); (c >= 0) && (c <= maxColor) && (preColoredRegisters.test(c));
|
||||
c = usedRegisters.nextZero(c)) {}
|
||||
}
|
||||
|
||||
if ((c >= 0) && (c <= maxColor))
|
||||
{
|
||||
vReg.colorRegister(c);
|
||||
}
|
||||
else
|
||||
{
|
||||
VirtualRegister& stackRegister = vRegManager.newVirtualRegister(vrcStackSlot);
|
||||
vReg.equivalentRegister[vrcStackSlot] = &stackRegister;
|
||||
vReg.spillInfo.willSpill = true;
|
||||
success = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
if (success)
|
||||
{
|
||||
for (VirtualRegisterManager::iterator i = vRegManager.begin(); !vRegManager.done(i); i = vRegManager.advance(i))
|
||||
{
|
||||
VirtualRegister& vReg = vRegManager.getVirtualRegister(i);
|
||||
switch (vReg.getClass())
|
||||
{
|
||||
case vrcInteger:
|
||||
if (vReg.getColor() > LAST_GREGISTER)
|
||||
PR_ASSERT(false);
|
||||
break;
|
||||
case vrcFloatingPoint:
|
||||
case vrcFixedPoint:
|
||||
#if NUMBER_OF_FPREGISTERS != 0
|
||||
if (vReg.getColor() > LAST_FPREGISTER)
|
||||
PR_ASSERT(false);
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
vRegManager.nUsedStackSlots = lastUsedSSR + 1;
|
||||
return success;
|
||||
}
|
||||
#endif // NEW_LAURENTM_CODE
|
||||
284
mozilla/ef/Compiler/RegisterAllocator/Coloring.h
Normal file
284
mozilla/ef/Compiler/RegisterAllocator/Coloring.h
Normal file
@@ -0,0 +1,284 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* 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 "Fundamentals.h"
|
||||
#include "ControlGraph.h"
|
||||
#include "ControlNodes.h"
|
||||
#include "Instruction.h"
|
||||
#include "RegisterAllocator.h"
|
||||
#include "VirtualRegister.h"
|
||||
#include "InterferenceGraph.h"
|
||||
#include "SparseSet.h"
|
||||
#include "Spilling.h"
|
||||
#include "Splits.h"
|
||||
|
||||
UT_EXTERN_LOG_MODULE(RegAlloc);
|
||||
|
||||
template <class RegisterPressure>
|
||||
class Coloring
|
||||
{
|
||||
private:
|
||||
static RegisterName* simplify(RegisterAllocator& registerAllocator, RegisterName* coloringStack);
|
||||
static bool select(RegisterAllocator& registerAllocator, RegisterName* coloringStack, RegisterName* coloringStackPtr);
|
||||
|
||||
public:
|
||||
static bool color(RegisterAllocator& registerAllocator);
|
||||
static void finalColoring(RegisterAllocator& registerAllocator);
|
||||
};
|
||||
|
||||
|
||||
template <class RegisterPressure>
|
||||
void Coloring<RegisterPressure>::finalColoring(RegisterAllocator& registerAllocator)
|
||||
{
|
||||
RegisterName* color = registerAllocator.color;
|
||||
RegisterName* name2range = registerAllocator.name2range;
|
||||
|
||||
ControlGraph& controlGraph = registerAllocator.controlGraph;
|
||||
ControlNode** nodes = controlGraph.dfsList;
|
||||
Uint32 nNodes = controlGraph.nNodes;
|
||||
|
||||
for (Uint32 n = 0; n < nNodes; n++) {
|
||||
InstructionList& instructions = nodes[n]->getInstructions();
|
||||
|
||||
for (InstructionList::iterator i = instructions.begin(); !instructions.done(i); i = instructions.advance(i)) {
|
||||
Instruction& instruction = instructions.get(i);
|
||||
|
||||
InstructionUse* useEnd = instruction.getInstructionUseEnd();
|
||||
for (InstructionUse* usePtr = instruction.getInstructionUseBegin(); usePtr < useEnd; usePtr++)
|
||||
if (usePtr->isRegister()) {
|
||||
usePtr->setRegisterName(color[name2range[usePtr->getRegisterName()]]);
|
||||
#ifdef DEBUG
|
||||
RegisterID rid = usePtr->getRegisterID();
|
||||
setColoredRegister(rid);
|
||||
usePtr->setRegisterID(rid);
|
||||
#endif // DEBUG
|
||||
}
|
||||
|
||||
InstructionDefine* defineEnd = instruction.getInstructionDefineEnd();
|
||||
for (InstructionDefine* definePtr = instruction.getInstructionDefineBegin(); definePtr < defineEnd; definePtr++)
|
||||
if (definePtr->isRegister()) {
|
||||
definePtr->setRegisterName(color[name2range[definePtr->getRegisterName()]]);
|
||||
#ifdef DEBUG
|
||||
RegisterID rid = definePtr->getRegisterID();
|
||||
setColoredRegister(rid);
|
||||
definePtr->setRegisterID(rid);
|
||||
#endif // DEBUG
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <class RegisterPressure>
|
||||
bool Coloring<RegisterPressure>::select(RegisterAllocator& registerAllocator, RegisterName* coloringStack, RegisterName* coloringStackPtr)
|
||||
{
|
||||
Uint32 rangeCount = registerAllocator.rangeCount;
|
||||
RegisterName* color = new RegisterName[rangeCount];
|
||||
registerAllocator.color = color;
|
||||
|
||||
for (Uint32 r = 1; r < rangeCount; r++)
|
||||
color[r] = RegisterName(6); // FIX;
|
||||
|
||||
// Color the preColored registers.
|
||||
//
|
||||
VirtualRegisterManager& vrManager = registerAllocator.vrManager;
|
||||
RegisterName* name2range = registerAllocator.name2range;
|
||||
PreColoredRegister* machineEnd = vrManager.getMachineRegistersEnd();
|
||||
for (PreColoredRegister* machinePtr = vrManager.getMachineRegistersBegin(); machinePtr < machineEnd; machinePtr++)
|
||||
if (machinePtr->id != invalidID) {
|
||||
color[name2range[getName(machinePtr->id)]] = machinePtr->color;
|
||||
UT_OBJECTLOG(UT_LOG_MODULE(RegAlloc), PR_LOG_ALWAYS, ("\twill preColor range %d as %d\n", name2range[getName(machinePtr->id)], machinePtr->color));
|
||||
}
|
||||
|
||||
SpillCost* cost = registerAllocator.spillCost;
|
||||
Pool& pool = registerAllocator.pool;
|
||||
SparseSet& spill = *new(pool) SparseSet(pool, rangeCount);
|
||||
registerAllocator.willSpill = &spill;
|
||||
SparseSet neighborColors(pool, 6); // FIX
|
||||
InterferenceGraph<RegisterPressure>& iGraph = registerAllocator.iGraph;
|
||||
|
||||
bool coloringFailed = false;
|
||||
while (coloringStackPtr > coloringStack) {
|
||||
RegisterName range = *--coloringStackPtr;
|
||||
|
||||
if (!cost[range].infinite && cost[range].cost < 0) {
|
||||
coloringFailed = true;
|
||||
spill.set(range);
|
||||
UT_OBJECTLOG(UT_LOG_MODULE(RegAlloc), PR_LOG_ALWAYS, ("\tfailed to color %d, will spill.\n", range));
|
||||
} else {
|
||||
neighborColors.clear();
|
||||
|
||||
for (InterferenceVector* vector = iGraph.getInterferenceVector(range); vector != NULL; vector = vector->next)
|
||||
for (Int32 i = vector->count - 1; i >= 0; --i) {
|
||||
RegisterName neighborColor = color[vector->neighbors[i]];
|
||||
if (neighborColor < 6) // FIX
|
||||
neighborColors.set(neighborColor);
|
||||
}
|
||||
|
||||
if (neighborColors.getSize() == 6) { // FIX
|
||||
coloringFailed = true;
|
||||
UT_OBJECTLOG(UT_LOG_MODULE(RegAlloc), PR_LOG_ALWAYS, ("\tfailed to color %d, ", range));
|
||||
|
||||
if (!Splits<RegisterPressure>::findSplit(registerAllocator, color, range)) {
|
||||
UT_OBJECTLOG(UT_LOG_MODULE(RegAlloc), PR_LOG_ALWAYS, ("will spill.\n"));
|
||||
spill.set(range);
|
||||
} else
|
||||
UT_OBJECTLOG(UT_LOG_MODULE(RegAlloc), PR_LOG_ALWAYS, ("will split.\n"));
|
||||
} else {
|
||||
for (Uint32 i = 0; i < 6; i++) // FIX
|
||||
if (!neighborColors.test(i)) {
|
||||
fprintf(stdout, "\twill color %d as %d\n", range, i);
|
||||
color[range] = RegisterName(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG_LOG
|
||||
if (coloringFailed) {
|
||||
UT_OBJECTLOG(UT_LOG_MODULE(RegAlloc), PR_LOG_ALWAYS, ("Coloring failed:\n"));
|
||||
UT_OBJECTLOG(UT_LOG_MODULE(RegAlloc), PR_LOG_ALWAYS, ("\twill spill: "));
|
||||
spill.printPretty(UT_LOG_MODULE(RegAlloc));
|
||||
} else {
|
||||
UT_OBJECTLOG(UT_LOG_MODULE(RegAlloc), PR_LOG_ALWAYS, ("Coloring succeeded:\n"));
|
||||
for (Uint32 i = 1; i < rangeCount; i++)
|
||||
UT_OBJECTLOG(UT_LOG_MODULE(RegAlloc), PR_LOG_ALWAYS, ("\trange %d colored as %d\n", i, color[i]));
|
||||
}
|
||||
#endif
|
||||
|
||||
return !coloringFailed;
|
||||
}
|
||||
|
||||
template <class RegisterPressure>
|
||||
RegisterName* Coloring<RegisterPressure>::simplify(RegisterAllocator& registerAllocator, RegisterName* coloringStack)
|
||||
{
|
||||
InterferenceGraph<RegisterPressure>& iGraph = registerAllocator.iGraph;
|
||||
SpillCost* spillCost = registerAllocator.spillCost;
|
||||
Uint32 rangeCount = registerAllocator.rangeCount;
|
||||
|
||||
Uint32* degree = new Uint32[rangeCount];
|
||||
for (RegisterName i = RegisterName(1); i < rangeCount; i = RegisterName(i + 1)) {
|
||||
InterferenceVector* vector = iGraph.getInterferenceVector(i);
|
||||
degree[i] = (vector != NULL) ? vector->count : 0;
|
||||
}
|
||||
|
||||
Pool& pool = registerAllocator.pool;
|
||||
SparseSet low(pool, rangeCount);
|
||||
SparseSet high(pool, rangeCount);
|
||||
SparseSet highInfinite(pool, rangeCount);
|
||||
SparseSet preColored(pool, rangeCount);
|
||||
|
||||
// Get the precolored registers.
|
||||
//
|
||||
VirtualRegisterManager& vrManager = registerAllocator.vrManager;
|
||||
RegisterName* name2range = registerAllocator.name2range;
|
||||
PreColoredRegister* machineEnd = vrManager.getMachineRegistersEnd();
|
||||
for (PreColoredRegister* machinePtr = vrManager.getMachineRegistersBegin(); machinePtr < machineEnd; machinePtr++)
|
||||
if (machinePtr->id != invalidID)
|
||||
preColored.set(name2range[getName(machinePtr->id)]);
|
||||
|
||||
// Insert the live ranges in the sets.
|
||||
//
|
||||
for (Uint32 range = 1; range < rangeCount; range++)
|
||||
if (!preColored.test(range))
|
||||
if (degree[range] < 6) // FIX
|
||||
low.set(range);
|
||||
else if (!spillCost[range].infinite)
|
||||
high.set(range);
|
||||
else
|
||||
highInfinite.set(range);
|
||||
|
||||
#ifdef DEBUG_LOG
|
||||
UT_OBJECTLOG(UT_LOG_MODULE(RegAlloc), PR_LOG_ALWAYS, ("Coloring sets:\n\tlow = "));
|
||||
low.printPretty(UT_LOG_MODULE(RegAlloc));
|
||||
UT_OBJECTLOG(UT_LOG_MODULE(RegAlloc), PR_LOG_ALWAYS, ("\thigh = "));
|
||||
high.printPretty(UT_LOG_MODULE(RegAlloc));
|
||||
UT_OBJECTLOG(UT_LOG_MODULE(RegAlloc), PR_LOG_ALWAYS, ("\thighInfinite = "));
|
||||
highInfinite.printPretty(UT_LOG_MODULE(RegAlloc));
|
||||
UT_OBJECTLOG(UT_LOG_MODULE(RegAlloc), PR_LOG_ALWAYS, ("\tpreColored = "));
|
||||
preColored.printPretty(UT_LOG_MODULE(RegAlloc));
|
||||
#endif // DEBUG_LOG
|
||||
|
||||
RegisterName* coloringStackPtr = coloringStack;
|
||||
|
||||
while (low.getSize() != 0 || high.getSize() != 0) {
|
||||
while (low.getSize() != 0) {
|
||||
RegisterName range = RegisterName(low.getOne());
|
||||
low.clear(range);
|
||||
*coloringStackPtr++ = range;
|
||||
|
||||
for (InterferenceVector* vector = iGraph.getInterferenceVector(range); vector != NULL; vector = vector->next)
|
||||
for (Int32 i = (vector->count - 1); i >= 0; --i) {
|
||||
RegisterName neighbor = vector->neighbors[i];
|
||||
degree[neighbor]--;
|
||||
|
||||
if (degree[neighbor] < 6) // FIX
|
||||
if (high.test(neighbor)) {
|
||||
high.clear(neighbor);
|
||||
low.set(neighbor);
|
||||
} else if (highInfinite.test(neighbor)) {
|
||||
highInfinite.clear(neighbor);
|
||||
low.set(neighbor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (high.getSize() != 0) {
|
||||
RegisterName best = RegisterName(high.getOne());
|
||||
double bestCost = spillCost[best].cost;
|
||||
double bestDegree = degree[best];
|
||||
|
||||
// Choose the next best candidate.
|
||||
//
|
||||
for (SparseSet::iterator i = high.begin(); !high.done(i); i = high.advance(i)) {
|
||||
RegisterName range = RegisterName(high.get(i));
|
||||
double thisCost = spillCost[range].cost;
|
||||
double thisDegree = degree[range];
|
||||
|
||||
if (thisCost * bestDegree < bestCost * thisDegree) {
|
||||
best = range;
|
||||
bestCost = thisCost;
|
||||
bestDegree = thisDegree;
|
||||
}
|
||||
}
|
||||
|
||||
high.clear(best);
|
||||
low.set(best);
|
||||
}
|
||||
}
|
||||
assert(highInfinite.getSize() == 0);
|
||||
|
||||
delete degree;
|
||||
|
||||
#ifdef DEBUG_LOG
|
||||
UT_OBJECTLOG(UT_LOG_MODULE(RegAlloc), PR_LOG_ALWAYS, ("Coloring stack:\n\t"));
|
||||
for (RegisterName* sp = coloringStack; sp < coloringStackPtr; ++sp)
|
||||
UT_OBJECTLOG(UT_LOG_MODULE(RegAlloc), PR_LOG_ALWAYS, ("%d ", *sp));
|
||||
UT_OBJECTLOG(UT_LOG_MODULE(RegAlloc), PR_LOG_ALWAYS, ("\n"));
|
||||
#endif // DEBUG_LOG
|
||||
|
||||
return coloringStackPtr;
|
||||
}
|
||||
|
||||
|
||||
template <class RegisterPressure>
|
||||
bool Coloring<RegisterPressure>::color(RegisterAllocator& registerAllocator)
|
||||
{
|
||||
RegisterName* coloringStack = new RegisterName[registerAllocator.rangeCount];
|
||||
return select(registerAllocator, coloringStack, simplify(registerAllocator, coloringStack));
|
||||
}
|
||||
212
mozilla/ef/Compiler/RegisterAllocator/DominatorGraph.cpp
Normal file
212
mozilla/ef/Compiler/RegisterAllocator/DominatorGraph.cpp
Normal file
@@ -0,0 +1,212 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* 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 "Fundamentals.h"
|
||||
#include <string.h>
|
||||
#include "ControlGraph.h"
|
||||
#include "ControlNodes.h"
|
||||
|
||||
#include "DominatorGraph.h"
|
||||
|
||||
DominatorGraph::DominatorGraph(ControlGraph& controlGraph) : controlGraph(controlGraph)
|
||||
{
|
||||
Uint32 nNodes = controlGraph.nNodes;
|
||||
|
||||
GtoV = new Uint32[nNodes + 1];
|
||||
VtoG = new Uint32[nNodes + 1];
|
||||
|
||||
Uint32 v = 1;
|
||||
for (Uint32 n = 0; n < nNodes; n++) {
|
||||
VtoG[v] = n;
|
||||
GtoV[n] = v++;
|
||||
}
|
||||
|
||||
// Initialize all the 1-based arrays.
|
||||
//
|
||||
parent = new Uint32[v];
|
||||
semi = new Uint32[v];
|
||||
vertex = new Uint32[v];
|
||||
label = new Uint32[v];
|
||||
size = new Uint32[v];
|
||||
ancestor = new Uint32[v];
|
||||
child = new Uint32[v];
|
||||
dom = new Uint32[v];
|
||||
bucket = new DGLinkedList*[v];
|
||||
|
||||
memset(semi, '\0', v * sizeof(Uint32));
|
||||
memset(bucket, '\0', v * sizeof(DGLinkedList*));
|
||||
|
||||
vCount = v;
|
||||
|
||||
build();
|
||||
|
||||
delete parent;
|
||||
delete semi;
|
||||
delete vertex;
|
||||
delete label;
|
||||
delete size;
|
||||
delete ancestor;
|
||||
delete child;
|
||||
delete dom;
|
||||
delete bucket;
|
||||
}
|
||||
|
||||
Uint32 DominatorGraph::DFS(Uint32 vx, Uint32 n)
|
||||
{
|
||||
semi[vx] = ++n;
|
||||
vertex[n] = label[vx] = vx;
|
||||
ancestor[vx] = child[vx] = 0;
|
||||
size[vx] = 1;
|
||||
|
||||
|
||||
ControlNode& node = *controlGraph.dfsList[VtoG[vx]];
|
||||
ControlEdge* successorEnd = node.getSuccessorsEnd();
|
||||
for (ControlEdge* successorPtr = node.getSuccessorsBegin(); successorPtr < successorEnd; successorPtr++) {
|
||||
Uint32 w = GtoV[successorPtr->getTarget().dfsNum];
|
||||
if (semi[w] == 0) {
|
||||
parent[w] = vx;
|
||||
n = DFS(w, n);
|
||||
}
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
void DominatorGraph::LINK(Uint32 vx, Uint32 w)
|
||||
{
|
||||
Uint32 s = w;
|
||||
|
||||
while (semi[label[w]] < semi[label[child[s]]]) {
|
||||
if (size[s] + size[child[child[s]]] >= (size[child[s]] << 1)) {
|
||||
ancestor[child[s]] = s;
|
||||
child[s] = child[child[s]];
|
||||
} else {
|
||||
size[child[s]] = size[s];
|
||||
s = ancestor[s] = child[s];
|
||||
}
|
||||
}
|
||||
label[s] = label[w];
|
||||
size[vx] += size[w];
|
||||
if(size[vx] < (size[w] << 1)) {
|
||||
Uint32 t = s;
|
||||
s = child[vx];
|
||||
child[vx] = t;
|
||||
}
|
||||
while( s != 0 ) {
|
||||
ancestor[s] = vx;
|
||||
s = child[s];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void DominatorGraph::COMPRESS(Uint32 vx)
|
||||
{
|
||||
if(ancestor[ancestor[vx]] != 0) {
|
||||
COMPRESS(ancestor[vx]);
|
||||
if(semi[label[ancestor[vx]]] < semi[label[vx]])
|
||||
label[vx] = label[ancestor[vx]];
|
||||
ancestor[vx] = ancestor[ancestor[vx]];
|
||||
}
|
||||
}
|
||||
|
||||
Uint32 DominatorGraph::EVAL(Uint32 vx)
|
||||
{
|
||||
if(ancestor[vx] == 0)
|
||||
return label[vx];
|
||||
COMPRESS(vx);
|
||||
return (semi[label[ancestor[vx]]] >= semi[label[vx]]) ? label[vx] : label[ancestor[vx]];
|
||||
}
|
||||
|
||||
void DominatorGraph::build()
|
||||
{
|
||||
Uint32 n = DFS(GtoV[0], 0);
|
||||
size[0] = label[0] = semi[0];
|
||||
|
||||
for (Uint32 i = n; i >= 2; i--) {
|
||||
Uint32 w = vertex[i];
|
||||
|
||||
ControlNode& node = *controlGraph.dfsList[VtoG[w]];
|
||||
const DoublyLinkedList<ControlEdge>& predecessors = node.getPredecessors();
|
||||
for (DoublyLinkedList<ControlEdge>::iterator p = predecessors.begin(); !predecessors.done(p); p = predecessors.advance(p)) {
|
||||
Uint32 vx = GtoV[predecessors.get(p).getSource().dfsNum];
|
||||
Uint32 u = EVAL(vx);
|
||||
|
||||
if(semi[u] < semi[w])
|
||||
semi[w] = semi[u];
|
||||
}
|
||||
|
||||
DGLinkedList* elem = new DGLinkedList();
|
||||
elem->next = bucket[vertex[semi[w]]];
|
||||
elem->index = w;
|
||||
bucket[vertex[semi[w]]] = elem;
|
||||
|
||||
LINK(parent[w], w);
|
||||
|
||||
elem = bucket[parent[w]];
|
||||
while(elem != NULL) {
|
||||
Uint32 vx = elem->index;
|
||||
Uint32 u = EVAL(vx);
|
||||
dom[vx] = (semi[u] < semi[vx]) ? u : parent[w];
|
||||
elem = elem->next;
|
||||
}
|
||||
}
|
||||
|
||||
memset(size, '\0', n * sizeof(Uint32));
|
||||
Pool& pool = controlGraph.pool;
|
||||
nodes = new(pool) DGNode[n];
|
||||
|
||||
for(Uint32 j = 2; j <= n; j++) {
|
||||
Uint32 w = vertex[j];
|
||||
Uint32 d = dom[w];
|
||||
if(d != vertex[semi[w]]) {
|
||||
d = dom[d];
|
||||
dom[w] = d;
|
||||
}
|
||||
size[d]++;
|
||||
}
|
||||
dom[GtoV[0]] = 0;
|
||||
|
||||
for (Uint32 k = 1; k <= n; k++) {
|
||||
DGNode& node = nodes[VtoG[k]];
|
||||
Uint32 count = size[k];
|
||||
node.successorsEnd = node.successorsBegin = (count) ? new(pool) Uint32[count] : (Uint32*) 0;
|
||||
}
|
||||
|
||||
for (Uint32 l = 2; l <= n; l++)
|
||||
*(nodes[VtoG[dom[l]]].successorsEnd)++ = VtoG[l];
|
||||
}
|
||||
|
||||
#ifdef DEBUG_LOG
|
||||
void DominatorGraph::printPretty(LogModuleObject log)
|
||||
{
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("Dominator Graph:\n"));
|
||||
Uint32 nNodes = controlGraph.nNodes;
|
||||
for (Uint32 i = 0; i < nNodes; i++) {
|
||||
DGNode& node = nodes[i];
|
||||
if (node.successorsBegin != node.successorsEnd) {
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("\tN%d dominates ", i));
|
||||
for (Uint32* successorsPtr = node.successorsBegin; successorsPtr < node.successorsEnd; successorsPtr++)
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("N%d ", *successorsPtr));
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("\n"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // DEBUG_LOG
|
||||
|
||||
|
||||
|
||||
80
mozilla/ef/Compiler/RegisterAllocator/DominatorGraph.h
Normal file
80
mozilla/ef/Compiler/RegisterAllocator/DominatorGraph.h
Normal file
@@ -0,0 +1,80 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef _DOMINATOR_GRAPH_H_
|
||||
#define _DOMINATOR_GRAPH_H_
|
||||
|
||||
#include "LogModule.h"
|
||||
|
||||
class ControlGraph;
|
||||
|
||||
struct DGNode
|
||||
{
|
||||
Uint32* successorsBegin;
|
||||
Uint32* successorsEnd;
|
||||
};
|
||||
|
||||
struct DGLinkedList
|
||||
{
|
||||
DGLinkedList* next;
|
||||
Uint32 index;
|
||||
};
|
||||
|
||||
class DominatorGraph
|
||||
{
|
||||
private:
|
||||
|
||||
ControlGraph& controlGraph;
|
||||
|
||||
Uint32 vCount;
|
||||
|
||||
Uint32* VtoG;
|
||||
Uint32* GtoV;
|
||||
Uint32* parent;
|
||||
Uint32* semi;
|
||||
Uint32* vertex;
|
||||
Uint32* label;
|
||||
Uint32* size;
|
||||
Uint32* ancestor;
|
||||
Uint32* child;
|
||||
Uint32* dom;
|
||||
DGLinkedList** bucket;
|
||||
DGNode* nodes;
|
||||
|
||||
private:
|
||||
|
||||
void build();
|
||||
|
||||
Uint32 DFS(Uint32 vx, Uint32 n);
|
||||
void LINK(Uint32 vx, Uint32 w);
|
||||
void COMPRESS(Uint32 vx);
|
||||
Uint32 EVAL(Uint32 vx);
|
||||
|
||||
public:
|
||||
|
||||
DominatorGraph(ControlGraph& controlGraph);
|
||||
|
||||
Uint32* getSuccessorsBegin(Uint32 n) const {return nodes[n].successorsBegin;}
|
||||
Uint32* getSuccessorsEnd(Uint32 n) const {return nodes[n].successorsEnd;}
|
||||
|
||||
#ifdef DEBUG_LOG
|
||||
void printPretty(LogModuleObject log);
|
||||
#endif // DEBUG_LOG
|
||||
};
|
||||
|
||||
#endif // _DOMINATOR_GRAPH_H_
|
||||
20
mozilla/ef/Compiler/RegisterAllocator/HashSet.cpp
Normal file
20
mozilla/ef/Compiler/RegisterAllocator/HashSet.cpp
Normal file
@@ -0,0 +1,20 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* 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 "Fundamentals.h"
|
||||
#include "HashSet.h"
|
||||
97
mozilla/ef/Compiler/RegisterAllocator/HashSet.h
Normal file
97
mozilla/ef/Compiler/RegisterAllocator/HashSet.h
Normal file
@@ -0,0 +1,97 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef _HASH_SET_H_
|
||||
#define _HASH_SET_H_
|
||||
|
||||
#include "Fundamentals.h"
|
||||
#include "Pool.h"
|
||||
#include <string.h>
|
||||
|
||||
struct HashSetElement
|
||||
{
|
||||
Uint32 index;
|
||||
HashSetElement* next;
|
||||
};
|
||||
|
||||
class HashSet
|
||||
{
|
||||
private:
|
||||
|
||||
static const hashSize = 64;
|
||||
|
||||
// Return the hash code for the given element index.
|
||||
static Uint32 getHashCode(Uint32 index) {return index & (hashSize - 1);} // Could be better !
|
||||
|
||||
private:
|
||||
|
||||
Pool& allocationPool;
|
||||
HashSetElement** bucket;
|
||||
HashSetElement* free;
|
||||
|
||||
private:
|
||||
|
||||
// No copy constructor.
|
||||
HashSet(const HashSet&);
|
||||
// No copy operator.
|
||||
void operator = (const HashSet&);
|
||||
|
||||
public:
|
||||
|
||||
// Create a new HashSet.
|
||||
inline HashSet(Pool& pool, Uint32 universeSize);
|
||||
|
||||
// Clear the hashset.
|
||||
void clear();
|
||||
// Clear the element for the given index.
|
||||
void clear(Uint32 index);
|
||||
// Set the element for the given index.
|
||||
void set(Uint32 index);
|
||||
// Return true if the element at index is a member.
|
||||
bool test(Uint32 index) const;
|
||||
// Union with the given hashset.
|
||||
inline void or(const HashSet& set);
|
||||
// Intersection with the given hashset.
|
||||
inline void and(const HashSet& set);
|
||||
// Difference with the given hashset.
|
||||
inline void difference(const HashSet& set);
|
||||
|
||||
// Logical operators.
|
||||
HashSet& operator |= (const HashSet& set) {or(set); return *this;}
|
||||
HashSet& operator &= (const HashSet& set) {and(set); return *this;}
|
||||
HashSet& operator -= (const HashSet& set) {difference(set); return *this;}
|
||||
|
||||
// Iterator to conform with the set API.
|
||||
typedef HashSetElement* iterator;
|
||||
// Return the iterator for the first element of this set.
|
||||
iterator begin() const;
|
||||
// Return the next iterator.
|
||||
iterator advance(iterator pos) const;
|
||||
// Return true if the iterator is at the end of the set.
|
||||
bool done(iterator pos) const {return pos == NULL;}
|
||||
};
|
||||
|
||||
|
||||
inline HashSet::HashSet(Pool& pool, Uint32 /*universeSize*/)
|
||||
: allocationPool(pool), free(NULL)
|
||||
{
|
||||
bucket = new(pool) HashSetElement*[hashSize];
|
||||
memset(bucket, '\0', sizeof(HashSetElement*));
|
||||
}
|
||||
|
||||
#endif // _HASH_SET_H_
|
||||
213
mozilla/ef/Compiler/RegisterAllocator/IndexedPool.h
Normal file
213
mozilla/ef/Compiler/RegisterAllocator/IndexedPool.h
Normal file
@@ -0,0 +1,213 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef _INDEXED_POOL_H_
|
||||
#define _INDEXED_POOL_H_
|
||||
|
||||
#include "Fundamentals.h"
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// IndexedPool<IndexedObjectSubclass> is an indexed pool of objects. The
|
||||
// template parameter 'IndexedObjectSubclass' must be a subclass of the struct
|
||||
// IndexedObject.
|
||||
//
|
||||
// When the indexed pool is ask to allocate and initialize a new object (using
|
||||
// the operator new(anIndexedPool) it will zero the memory used to store the
|
||||
// object and initialize the field 'index' of this object to its position in
|
||||
// the pool.
|
||||
//
|
||||
// An object allocated by the indexed pool can be freed by calling the method
|
||||
// IndexedPool::release(IndexedElement& objectIndex).
|
||||
//
|
||||
// example:
|
||||
//
|
||||
// IndexedPool<IndexedElement> elementPool;
|
||||
//
|
||||
// IndexedElement& element1 = *new(elementPool) IndexedElement();
|
||||
// IndexedElement& element2 = *new(elementPool) IndexedElement();
|
||||
//
|
||||
// indexedPool.release(element1);
|
||||
// IndexedElement& element3 = *new(elementPool) IndexedElement();
|
||||
//
|
||||
// At this point element1 is no longer a valid object, element2 is at
|
||||
// index 2 and element3 is at index 1.
|
||||
//
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// IndexedObject -
|
||||
//
|
||||
|
||||
template<class Object>
|
||||
struct IndexedObject
|
||||
{
|
||||
Uint32 index; // Index in the pool.
|
||||
Object* next; // Used to link IndexedObject together.
|
||||
|
||||
Uint32 getIndex() {return index;}
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// IndexedPool<IndexedObject> -
|
||||
//
|
||||
|
||||
template <class IndexedObject>
|
||||
class IndexedPool
|
||||
{
|
||||
private:
|
||||
|
||||
static const blockSize = 4; // Size of one block.
|
||||
|
||||
Uint32 nBlocks; // Number of blocks in the pool.
|
||||
IndexedObject** block; // Array of block pointers.
|
||||
IndexedObject* freeObjects; // Chained list of free IndexedObjects.
|
||||
Uint32 nextIndex; // Index of the next free object in the last block.
|
||||
|
||||
private:
|
||||
|
||||
void allocateAnotherBlock();
|
||||
IndexedObject& newObject();
|
||||
|
||||
public:
|
||||
|
||||
IndexedPool() : nBlocks(0), block(NULL), freeObjects(NULL), nextIndex(1) {}
|
||||
~IndexedPool();
|
||||
|
||||
IndexedObject& get(Uint32 index) const;
|
||||
void release(IndexedObject& object);
|
||||
|
||||
void setSize(Uint32 size) {assert(size < nextIndex); nextIndex = size;}
|
||||
|
||||
// Return the universe size.
|
||||
Uint32 getSize() {return nextIndex;}
|
||||
|
||||
friend void* operator new(size_t, IndexedPool<IndexedObject>& pool); // Needs to call newObject().
|
||||
};
|
||||
|
||||
// Free all the memory allocated for this object.
|
||||
//
|
||||
template <class IndexedObject>
|
||||
IndexedPool<IndexedObject>::~IndexedPool()
|
||||
{
|
||||
for (Uint32 n = 0; n < nBlocks; n++)
|
||||
free(&((IndexedObject **) &block[n][n*blockSize])[-(n + 1)]);
|
||||
}
|
||||
|
||||
// Release the given. This object will be iserted in the chained
|
||||
// list of free IndexedObjects. To minimize the fragmentation the chained list
|
||||
// is ordered by ascending indexes.
|
||||
//
|
||||
template <class IndexedObject>
|
||||
void IndexedPool<IndexedObject>::release(IndexedObject& object)
|
||||
{
|
||||
Uint32 index = object.index;
|
||||
IndexedObject* list = freeObjects;
|
||||
|
||||
assert(&object == &get(index)); // Make sure that object is owned by this pool.
|
||||
|
||||
if (list == NULL) { // The list is empty.
|
||||
freeObjects = &object;
|
||||
object.next = NULL;
|
||||
} else { // The list contains at least 1 element.
|
||||
if (index < list->index) { // insert as first element.
|
||||
freeObjects = &object;
|
||||
object.next = list;
|
||||
} else { // Find this object's place.
|
||||
while ((list->next) != NULL && (list->next->index < index))
|
||||
list = list->next;
|
||||
|
||||
object.next = list->next;
|
||||
list->next = &object;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
// Sanity check to be sure that the list is correctly ordered.
|
||||
for (IndexedObject* obj = freeObjects; obj != NULL; obj = obj->next)
|
||||
if (obj->next != NULL)
|
||||
assert(obj->index < obj->next->index);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Create a new block of IndexedObjects. We will allocate the memory to
|
||||
// store IndexedPool::blockSize IndexedObject and the new Array of block
|
||||
// pointers.
|
||||
// The newly created IndexedObjects will not be initialized.
|
||||
//
|
||||
template <class IndexedObject>
|
||||
void IndexedPool<IndexedObject>::allocateAnotherBlock()
|
||||
{
|
||||
void* memory = (void *) malloc((nBlocks + 1) * sizeof(Uint32) + blockSize * sizeof(IndexedObject));
|
||||
|
||||
memcpy(memory, block, nBlocks * sizeof(Uint32));
|
||||
|
||||
block = (IndexedObject **) memory;
|
||||
IndexedObject* objects = (IndexedObject *) &block[nBlocks + 1];
|
||||
|
||||
block[nBlocks] = &objects[-(nBlocks * blockSize)];
|
||||
nBlocks++;
|
||||
}
|
||||
|
||||
// Return the IndexedObject at the position 'index' in the pool.
|
||||
//
|
||||
template <class IndexedObject>
|
||||
IndexedObject& IndexedPool<IndexedObject>::get(Uint32 index) const
|
||||
{
|
||||
Uint32 blockIndex = index / blockSize;
|
||||
assert(blockIndex < nBlocks);
|
||||
|
||||
return block[blockIndex][index];
|
||||
}
|
||||
|
||||
// Return the reference of an unused object in the pool.
|
||||
//
|
||||
template <class IndexedObject>
|
||||
IndexedObject& IndexedPool<IndexedObject>::newObject()
|
||||
{
|
||||
if (freeObjects != NULL) {
|
||||
IndexedObject& newObject = *freeObjects;
|
||||
freeObjects = newObject.next;
|
||||
return newObject;
|
||||
}
|
||||
|
||||
Uint32 nextIndex = this->nextIndex++;
|
||||
Uint32 blockIndex = nextIndex / blockSize;
|
||||
|
||||
while (blockIndex >= nBlocks)
|
||||
allocateAnotherBlock();
|
||||
|
||||
IndexedObject& newObject = block[blockIndex][nextIndex];
|
||||
newObject.index = nextIndex;
|
||||
|
||||
return newObject;
|
||||
}
|
||||
|
||||
// Return the address of the next unsused object in the given
|
||||
// indexed pool. The field index of the newly allocated object
|
||||
// will be initialized to the corresponding index of this object
|
||||
// in the pool.
|
||||
//
|
||||
template <class IndexedObject>
|
||||
void* operator new(size_t size, IndexedPool<IndexedObject>& pool)
|
||||
{
|
||||
assert(size == sizeof(IndexedObject));
|
||||
return (void *) &pool.newObject();
|
||||
}
|
||||
|
||||
#endif // _INDEXED_POOL_H_
|
||||
258
mozilla/ef/Compiler/RegisterAllocator/InterferenceGraph.h
Normal file
258
mozilla/ef/Compiler/RegisterAllocator/InterferenceGraph.h
Normal file
@@ -0,0 +1,258 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef _INTERFERENCE_GRAPH_H_
|
||||
#define _INTERFERENCE_GRAPH_H_
|
||||
|
||||
#include "Fundamentals.h"
|
||||
#include "ControlGraph.h"
|
||||
#include "Primitives.h"
|
||||
#include "Instruction.h"
|
||||
#include "VirtualRegister.h"
|
||||
#include "RegisterPressure.h"
|
||||
#include "SparseSet.h"
|
||||
#include <string.h>
|
||||
|
||||
struct InterferenceVector
|
||||
{
|
||||
Uint32 count;
|
||||
InterferenceVector* next;
|
||||
RegisterName* neighbors;
|
||||
|
||||
InterferenceVector() : count(0), next(NULL) {}
|
||||
};
|
||||
|
||||
class RegisterAllocator;
|
||||
|
||||
template <class RegisterPressure>
|
||||
class InterferenceGraph
|
||||
{
|
||||
private:
|
||||
|
||||
RegisterAllocator& registerAllocator;
|
||||
|
||||
RegisterPressure::Set* interferences;
|
||||
InterferenceVector** vector;
|
||||
Uint32* offset;
|
||||
Uint32 rangeCount;
|
||||
|
||||
private:
|
||||
|
||||
// No copy constructor.
|
||||
InterferenceGraph(const InterferenceGraph&);
|
||||
// No copy operator.
|
||||
void operator = (const InterferenceGraph&);
|
||||
|
||||
// Check if reg is a member of the universe.
|
||||
void checkMember(RegisterName name) {assert(name < rangeCount);}
|
||||
// Return the edge index for the interference between name1 and name2.
|
||||
Uint32 getEdgeIndex(RegisterName name1, RegisterName name2);
|
||||
|
||||
public:
|
||||
InterferenceGraph(RegisterAllocator& registerAllocator) : registerAllocator(registerAllocator) {}
|
||||
|
||||
// Calculate the interferences.
|
||||
void build();
|
||||
// Return true if reg1 and reg2 interfere.
|
||||
bool interfere(RegisterName name1, RegisterName name2);
|
||||
// Return the interference vector for the given register or NULL if there is none.
|
||||
InterferenceVector* getInterferenceVector(RegisterName name) {return vector[name];}
|
||||
// Set the interference between name1 and name2.
|
||||
void setInterference(RegisterName name1, RegisterName name2);
|
||||
// Set the interference vector for the given register.
|
||||
void setInterferenceVector(RegisterName name, InterferenceVector* v) {vector[name] = v;}
|
||||
|
||||
|
||||
#ifdef DEBUG_LOG
|
||||
// Print the interferences.
|
||||
void printPretty(LogModuleObject log);
|
||||
#endif // DEBUG_LOG
|
||||
};
|
||||
|
||||
template <class RegisterPressure>
|
||||
void InterferenceGraph<RegisterPressure>::build()
|
||||
{
|
||||
Pool& pool = registerAllocator.pool;
|
||||
Uint32 rangeCount = registerAllocator.rangeCount;
|
||||
this->rangeCount = rangeCount;
|
||||
|
||||
// Initialize the structures.
|
||||
//
|
||||
offset = new(pool) Uint32[rangeCount + 1];
|
||||
vector = new(pool) InterferenceVector*[rangeCount];
|
||||
memset(vector, '\0', sizeof(InterferenceVector*) * rangeCount);
|
||||
|
||||
Uint32 o = 0;
|
||||
offset[0] = 0;
|
||||
for (Uint32 i = 1; i <= rangeCount; ++i) {
|
||||
offset[i] = o;
|
||||
o += i;
|
||||
}
|
||||
|
||||
interferences = new(pool) RegisterPressure::Set(pool, (rangeCount * rangeCount) / 2);
|
||||
|
||||
ControlGraph& controlGraph = registerAllocator.controlGraph;
|
||||
ControlNode** nodes = controlGraph.dfsList;
|
||||
Uint32 nNodes = controlGraph.nNodes;
|
||||
|
||||
RegisterName* name2range = registerAllocator.name2range;
|
||||
LivenessInfo<RegisterPressure> liveness = Liveness<RegisterPressure>::analysis(controlGraph, rangeCount, name2range);
|
||||
registerAllocator.liveness = liveness;
|
||||
SparseSet currentLive(pool, rangeCount);
|
||||
|
||||
for (Uint32 n = 0; n < nNodes; n++) {
|
||||
ControlNode& node = *nodes[n];
|
||||
currentLive = liveness.liveOut[n];
|
||||
|
||||
InstructionList& instructions = node.getInstructions();
|
||||
for (InstructionList::iterator i = instructions.end(); !instructions.done(i); i = instructions.retreat(i)) {
|
||||
Instruction& instruction = instructions.get(i);
|
||||
|
||||
InstructionUse* useBegin = instruction.getInstructionUseBegin();
|
||||
InstructionUse* useEnd = instruction.getInstructionUseEnd();
|
||||
InstructionUse* usePtr;
|
||||
InstructionDefine* defineBegin = instruction.getInstructionDefineBegin();
|
||||
InstructionDefine* defineEnd = instruction.getInstructionDefineEnd();
|
||||
InstructionDefine* definePtr;
|
||||
|
||||
// Handle the copy instruction to avoid unnecessary interference between the 2 registers.
|
||||
if ((instruction.getFlags() & ifCopy) != 0) {
|
||||
assert(useBegin != useEnd && useBegin[0].isRegister());
|
||||
currentLive.clear(name2range[useBegin[0].getRegisterName()]);
|
||||
}
|
||||
|
||||
// Create the interferences.
|
||||
for (definePtr = defineBegin; definePtr < defineEnd; definePtr++)
|
||||
if (definePtr->isRegister()) {
|
||||
RegisterName define = name2range[definePtr->getRegisterName()];
|
||||
|
||||
for (SparseSet::iterator e = currentLive.begin(); !currentLive.done(e); e = currentLive.advance(e)) {
|
||||
RegisterName live = RegisterName(currentLive.get(e));
|
||||
|
||||
if ((live != define) && !interfere(live, define) && registerAllocator.canInterfere(live, define)) {
|
||||
|
||||
if (vector[define] == NULL)
|
||||
vector[define] = new(pool) InterferenceVector();
|
||||
vector[define]->count++;
|
||||
|
||||
if (vector[live] == NULL)
|
||||
vector[live] = new(pool) InterferenceVector();
|
||||
vector[live]->count++;
|
||||
|
||||
setInterference(live, define);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Now update the liveness.
|
||||
//
|
||||
for (definePtr = defineBegin; definePtr < defineEnd; definePtr++)
|
||||
if (definePtr->isRegister())
|
||||
currentLive.clear(name2range[definePtr->getRegisterName()]);
|
||||
|
||||
for (usePtr = useBegin; usePtr < useEnd; usePtr++)
|
||||
if (usePtr->isRegister())
|
||||
currentLive.set(name2range[usePtr->getRegisterName()]);
|
||||
}
|
||||
}
|
||||
|
||||
// Allocate the memory to store the interferences.
|
||||
//
|
||||
for (Uint32 e = 0; e < rangeCount; e++)
|
||||
if (vector[e] != NULL) {
|
||||
InterferenceVector& v = *vector[e];
|
||||
v.neighbors = new(pool) RegisterName[v.count];
|
||||
v.count = 0;
|
||||
}
|
||||
|
||||
// Initialize the edges.
|
||||
//
|
||||
if (RegisterPressure::Set::isOrdered()) {
|
||||
RegisterName name1 = RegisterName(0);
|
||||
|
||||
for (RegisterPressure::Set::iterator i = interferences->begin(); !interferences->done(i); i = interferences->advance(i)) {
|
||||
Uint32 interferenceIndex = interferences->get(i);
|
||||
|
||||
while(interferenceIndex >= offset[name1 + 1])
|
||||
name1 = RegisterName(name1 + 1);
|
||||
|
||||
assert((interferenceIndex >= offset[name1]) && (interferenceIndex < offset[name1 + 1]));
|
||||
|
||||
RegisterName name2 = RegisterName(interferenceIndex - offset[name1]);
|
||||
|
||||
assert(interfere(name1, name2));
|
||||
|
||||
InterferenceVector& vector1 = *vector[name1];
|
||||
vector1.neighbors[vector1.count++] = name2;
|
||||
|
||||
InterferenceVector& vector2 = *vector[name2];
|
||||
vector2.neighbors[vector2.count++] = name1;
|
||||
}
|
||||
} else {
|
||||
trespass("not Implemented"); // FIX: need one more pass to initialize the vectors.
|
||||
}
|
||||
}
|
||||
|
||||
template <class RegisterPressure>
|
||||
Uint32 InterferenceGraph<RegisterPressure>::getEdgeIndex(RegisterName name1, RegisterName name2)
|
||||
{
|
||||
checkMember(name1); checkMember(name2);
|
||||
assert(name1 != name2); // This is not possible.
|
||||
return (name1 < name2) ? offset[name2] + name1 : offset[name1] + name2;
|
||||
}
|
||||
|
||||
template <class RegisterPressure>
|
||||
void InterferenceGraph<RegisterPressure>::setInterference(RegisterName name1, RegisterName name2)
|
||||
{
|
||||
interferences->set(getEdgeIndex(name1, name2));
|
||||
}
|
||||
|
||||
template <class RegisterPressure>
|
||||
bool InterferenceGraph<RegisterPressure>::interfere(RegisterName name1, RegisterName name2)
|
||||
{
|
||||
return interferences->test(getEdgeIndex(name1, name2));
|
||||
}
|
||||
|
||||
#ifdef DEBUG_LOG
|
||||
template <class RegisterPressure>
|
||||
void InterferenceGraph<RegisterPressure>::printPretty(LogModuleObject log)
|
||||
{
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("Interference Vectors:\n"));
|
||||
for (Uint32 i = 1; i < rangeCount; i++) {
|
||||
if (vector[i] != NULL) {
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("\tvr%d: (", i));
|
||||
for (InterferenceVector* v = vector[i]; v != NULL; v = v->next)
|
||||
for (Uint32 j = 0; j < v->count; j++) {
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("%d", v->neighbors[j]));
|
||||
if (v->next != NULL || j != (v->count - 1))
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, (","));
|
||||
}
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, (")\n"));
|
||||
}
|
||||
}
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("Interference Matrix:\n"));
|
||||
for (RegisterName name1 = RegisterName(1); name1 < rangeCount; name1 = RegisterName(name1 + 1)) {
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("\t%d:\t", name1));
|
||||
for (RegisterName name2 = RegisterName(1); name2 < rangeCount; name2 = RegisterName(name2 + 1))
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("%c", ((name1 != name2) && interfere(name1, name2)) ? '1' : '0'));
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("\n"));
|
||||
}
|
||||
}
|
||||
#endif // DEBUG_LOG
|
||||
|
||||
#endif // _INTERFERENCE_GRAPH_H_
|
||||
87
mozilla/ef/Compiler/RegisterAllocator/LiveRange.h
Normal file
87
mozilla/ef/Compiler/RegisterAllocator/LiveRange.h
Normal file
@@ -0,0 +1,87 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef _LIVE_RANGE_H_
|
||||
#define _LIVE_RANGE_H_
|
||||
|
||||
#include "Fundamentals.h"
|
||||
#include "ControlGraph.h"
|
||||
#include "ControlNodes.h"
|
||||
#include "Primitives.h"
|
||||
#include "Instruction.h"
|
||||
#include "RegisterAllocator.h"
|
||||
#include "RegisterAllocatorTools.h"
|
||||
|
||||
template <class RegisterPressure>
|
||||
struct LiveRange
|
||||
{
|
||||
static void build(RegisterAllocator& registerAllocator);
|
||||
};
|
||||
|
||||
template <class RegisterPressure>
|
||||
void LiveRange<RegisterPressure>::build(RegisterAllocator& registerAllocator)
|
||||
{
|
||||
// Intialize the lookup table.
|
||||
//
|
||||
Uint32 nameCount = registerAllocator.nameCount;
|
||||
RegisterName* nameTable = new(registerAllocator.pool) RegisterName[2*nameCount];
|
||||
RegisterName* rangeName = &nameTable[nameCount];
|
||||
|
||||
init(rangeName, nameCount);
|
||||
|
||||
// Walk the graph.
|
||||
//
|
||||
ControlGraph& controlGraph = registerAllocator.controlGraph;
|
||||
ControlNode** nodes = controlGraph.dfsList;
|
||||
Uint32 nNodes = controlGraph.nNodes;
|
||||
|
||||
SparseSet destination(registerAllocator.pool, nameCount);
|
||||
|
||||
for (Uint32 n = 0; n < nNodes; n++) {
|
||||
InstructionList& phiNodes = nodes[n]->getPhiNodeInstructions();
|
||||
|
||||
destination.clear();
|
||||
for (InstructionList::iterator i = phiNodes.begin(); !phiNodes.done(i); i = phiNodes.advance(i)) {
|
||||
Instruction& phiNode = phiNodes.get(i);
|
||||
assert(phiNode.getInstructionDefineBegin() != phiNode.getInstructionDefineEnd() && phiNode.getInstructionDefineBegin()[0].isRegister());
|
||||
destination.set(findRoot(phiNode.getInstructionDefineBegin()[0].getRegisterName(), rangeName));
|
||||
}
|
||||
|
||||
for (InstructionList::iterator p = phiNodes.begin(); !phiNodes.done(p); p = phiNodes.advance(p)) {
|
||||
Instruction& phiNode = phiNodes.get(p);
|
||||
|
||||
assert(phiNode.getInstructionDefineBegin() != phiNode.getInstructionDefineEnd() && phiNode.getInstructionDefineBegin()[0].isRegister());
|
||||
RegisterName destinationName = phiNode.getInstructionDefineBegin()[0].getRegisterName();
|
||||
RegisterName destinationRoot = findRoot(destinationName, rangeName);
|
||||
|
||||
InstructionUse* useEnd = phiNode.getInstructionUseEnd();
|
||||
for (InstructionUse* usePtr = phiNode.getInstructionUseBegin(); usePtr < useEnd; usePtr++) {
|
||||
assert(usePtr->isRegister());
|
||||
RegisterName sourceName = usePtr->getRegisterName();
|
||||
RegisterName sourceRoot = findRoot(sourceName, rangeName);
|
||||
|
||||
if (sourceRoot != destinationRoot && !destination.test(sourceRoot))
|
||||
rangeName[sourceRoot] = destinationRoot;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
registerAllocator.rangeCount = compress(registerAllocator.name2range, rangeName, nameCount, nameCount);
|
||||
}
|
||||
|
||||
#endif // _LIVE_RANGE_H_
|
||||
163
mozilla/ef/Compiler/RegisterAllocator/LiveRangeGraph.h
Normal file
163
mozilla/ef/Compiler/RegisterAllocator/LiveRangeGraph.h
Normal file
@@ -0,0 +1,163 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef _LIVE_RANGE_GRAPH_
|
||||
#define _LIVE_RANGE_GRAPH_
|
||||
|
||||
#include "Fundamentals.h"
|
||||
#include "Pool.h"
|
||||
#include "ControlGraph.h"
|
||||
#include "ControlNodes.h"
|
||||
#include "Instruction.h"
|
||||
#include "RegisterTypes.h"
|
||||
|
||||
class RegisterAllocator;
|
||||
|
||||
template <class RegisterPressure>
|
||||
class LiveRangeGraph
|
||||
{
|
||||
private:
|
||||
|
||||
RegisterAllocator& registerAllocator;
|
||||
|
||||
RegisterPressure::Set* edges;
|
||||
Uint32 rangeCount;
|
||||
|
||||
public:
|
||||
//
|
||||
//
|
||||
LiveRangeGraph(RegisterAllocator& registerAllocator) : registerAllocator(registerAllocator) {}
|
||||
|
||||
//
|
||||
//
|
||||
void build();
|
||||
|
||||
//
|
||||
//
|
||||
void addEdge(RegisterName name1, RegisterName name2);
|
||||
|
||||
//
|
||||
//
|
||||
bool haveEdge(RegisterName name1, RegisterName name2);
|
||||
|
||||
#ifdef DEBUG_LOG
|
||||
//
|
||||
//
|
||||
void printPretty(LogModuleObject log);
|
||||
#endif // DEBUG_LOG
|
||||
};
|
||||
|
||||
template <class RegisterPressure>
|
||||
void LiveRangeGraph<RegisterPressure>::build()
|
||||
{
|
||||
Pool& pool = registerAllocator.pool;
|
||||
Uint32 rangeCount = registerAllocator.rangeCount;
|
||||
this->rangeCount = rangeCount;
|
||||
|
||||
edges = new(pool) RegisterPressure::Set(pool, rangeCount * rangeCount);
|
||||
|
||||
ControlGraph& controlGraph = registerAllocator.controlGraph;
|
||||
ControlNode** nodes = controlGraph.dfsList;
|
||||
Uint32 nNodes = controlGraph.nNodes;
|
||||
|
||||
RegisterName* name2range = registerAllocator.name2range;
|
||||
LivenessInfo<RegisterPressure>& liveness = registerAllocator.liveness;
|
||||
SparseSet currentLive(pool, rangeCount);
|
||||
|
||||
for (Uint32 n = 0; n < nNodes; n++) {
|
||||
ControlNode& node = *nodes[n];
|
||||
currentLive = liveness.liveOut[n];
|
||||
|
||||
InstructionList& instructions = node.getInstructions();
|
||||
for (InstructionList::iterator i = instructions.end(); !instructions.done(i); i = instructions.retreat(i)) {
|
||||
Instruction& instruction = instructions.get(i);
|
||||
|
||||
InstructionUse* useBegin = instruction.getInstructionUseBegin();
|
||||
InstructionUse* useEnd = instruction.getInstructionUseEnd();
|
||||
InstructionUse* usePtr;
|
||||
InstructionDefine* defineBegin = instruction.getInstructionDefineBegin();
|
||||
InstructionDefine* defineEnd = instruction.getInstructionDefineEnd();
|
||||
InstructionDefine* definePtr;
|
||||
|
||||
if ((instruction.getFlags() & ifCopy) != 0) {
|
||||
assert(useBegin != useEnd && useBegin[0].isRegister());
|
||||
currentLive.clear(name2range[useBegin[0].getRegisterName()]);
|
||||
}
|
||||
|
||||
for (definePtr = defineBegin; definePtr < defineEnd; definePtr++)
|
||||
if (definePtr->isRegister()) {
|
||||
RegisterName define = name2range[definePtr->getRegisterName()];
|
||||
|
||||
for (SparseSet::iterator l = currentLive.begin(); !currentLive.done(l); l = currentLive.advance(l)) {
|
||||
RegisterName live = RegisterName(currentLive.get(l));
|
||||
if (define != live && registerAllocator.canInterfere(define, live))
|
||||
addEdge(define, live);
|
||||
}
|
||||
}
|
||||
|
||||
for (definePtr = defineBegin; definePtr < defineEnd; definePtr++)
|
||||
if (definePtr->isRegister())
|
||||
currentLive.clear(name2range[definePtr->getRegisterName()]);
|
||||
|
||||
for (usePtr = useBegin; usePtr < useEnd; usePtr++)
|
||||
if (usePtr->isRegister())
|
||||
currentLive.set(name2range[usePtr->getRegisterName()]);
|
||||
|
||||
for (usePtr = useBegin; usePtr < useEnd; usePtr++)
|
||||
if (usePtr->isRegister()) {
|
||||
RegisterName use = name2range[usePtr->getRegisterName()];
|
||||
|
||||
for (SparseSet::iterator l = currentLive.begin(); !currentLive.done(l); l = currentLive.advance(l)) {
|
||||
RegisterName live = RegisterName(currentLive.get(l));
|
||||
if (use != live && registerAllocator.canInterfere(use, live))
|
||||
addEdge(use, live);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <class RegisterPressure>
|
||||
void LiveRangeGraph<RegisterPressure>::addEdge(RegisterName name1, RegisterName name2)
|
||||
{
|
||||
assert(name1 != name2);
|
||||
edges->set(name1 * rangeCount + name2);
|
||||
}
|
||||
|
||||
template <class RegisterPressure>
|
||||
bool LiveRangeGraph<RegisterPressure>::haveEdge(RegisterName name1, RegisterName name2)
|
||||
{
|
||||
assert(name1 != name2);
|
||||
return edges->test(name1 * rangeCount + name2);
|
||||
}
|
||||
|
||||
#ifdef DEBUG_LOG
|
||||
template <class RegisterPressure>
|
||||
void LiveRangeGraph<RegisterPressure>::printPretty(LogModuleObject log)
|
||||
{
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("Live ranges graph:\n"));
|
||||
for (RegisterName name1 = RegisterName(1); name1 < rangeCount; name1 = RegisterName(name1 + 1)) {
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("\t%d:\t", name1));
|
||||
for (RegisterName name2 = RegisterName(1); name2 < rangeCount; name2 = RegisterName(name2 + 1))
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("%c", ((name1 != name2) && haveEdge(name1, name2)) ? '1' : '0'));
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("\n"));
|
||||
}
|
||||
}
|
||||
#endif // DEBUG_LOG
|
||||
|
||||
#endif // _LIVE_RANGE_GRAPH_
|
||||
21
mozilla/ef/Compiler/RegisterAllocator/Liveness.cpp
Normal file
21
mozilla/ef/Compiler/RegisterAllocator/Liveness.cpp
Normal file
@@ -0,0 +1,21 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* 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 "Fundamentals.h"
|
||||
#include "Liveness.h"
|
||||
|
||||
301
mozilla/ef/Compiler/RegisterAllocator/Liveness.h
Normal file
301
mozilla/ef/Compiler/RegisterAllocator/Liveness.h
Normal file
@@ -0,0 +1,301 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef _LIVENESS_H_
|
||||
#define _LIVENESS_H_
|
||||
|
||||
#include "Fundamentals.h"
|
||||
#include "ControlGraph.h"
|
||||
#include "ControlNodes.h"
|
||||
#include "Instruction.h"
|
||||
#include "RegisterTypes.h"
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// LivenessInfo -
|
||||
|
||||
template <class RegisterPressure>
|
||||
struct LivenessInfo
|
||||
{
|
||||
RegisterPressure::Set* liveIn;
|
||||
RegisterPressure::Set* liveOut;
|
||||
DEBUG_LOG_ONLY(Uint32 size);
|
||||
|
||||
#ifdef DEBUG_LOG
|
||||
void printPretty(LogModuleObject log);
|
||||
#endif // DEBUG_LOG
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Liveness
|
||||
//
|
||||
// The liveness is defined by the following data-flow equations:
|
||||
//
|
||||
// LiveIn(n) = LocalLive(n) U (LiveOut(n) - Killed(n)).
|
||||
// LiveOut(n) = U LiveIn(s) (s a successor of n).
|
||||
//
|
||||
// where LocalLive(n) is the set of used registers in the block n, Killed(n)
|
||||
// is the set of defined registers in the block n, LiveIn(n) is the set of
|
||||
// live registers at the begining of the block n and LiveOut(n) is the set
|
||||
// of live registers at the end of the block n.
|
||||
//
|
||||
//
|
||||
// We will compute the liveness analysis in two stages:
|
||||
//
|
||||
// 1- Build LocalLive(n) (wich is an approximation of LiveIn(n)) and Killed(n)
|
||||
// for each block n.
|
||||
// 2- Perform a backward data-flow analysis to propagate the liveness information
|
||||
// through the entire control-flow graph.
|
||||
//
|
||||
|
||||
template <class RegisterPressure>
|
||||
struct Liveness
|
||||
{
|
||||
static LivenessInfo<RegisterPressure> analysis(ControlGraph& controlGraph, Uint32 rangeCount, const RegisterName* name2range);
|
||||
static LivenessInfo<RegisterPressure> analysis(ControlGraph& controlGraph, Uint32 nameCount);
|
||||
};
|
||||
|
||||
template <class RegisterPressure>
|
||||
LivenessInfo<RegisterPressure> Liveness<RegisterPressure>::analysis(ControlGraph& controlGraph, Uint32 rangeCount, const RegisterName* name2range)
|
||||
{
|
||||
Pool& pool = controlGraph.pool;
|
||||
ControlNode** nodes = controlGraph.dfsList;
|
||||
Uint32 nNodes = controlGraph.nNodes;
|
||||
|
||||
// Allocate the temporary sets.
|
||||
RegisterPressure::Set* killed = new(pool) RegisterPressure::Set[nNodes](pool, rangeCount);
|
||||
|
||||
// Allocate the globals sets.
|
||||
RegisterPressure::Set* liveIn = new(pool) RegisterPressure::Set[nNodes](pool, rangeCount);
|
||||
RegisterPressure::Set* liveOut = new(pool) RegisterPressure::Set[nNodes](pool, rangeCount);
|
||||
|
||||
// First stage of the liveness analysis: Compute the sets LocalLive(stored in LiveIn) and Killed.
|
||||
//
|
||||
for (Uint32 n = 0; n < (nNodes - 1); n++) {
|
||||
ControlNode& node = *nodes[n];
|
||||
|
||||
RegisterPressure::Set& currentLocalLive = liveIn[n];
|
||||
RegisterPressure::Set& currentKilled = killed[n];
|
||||
|
||||
// Find the instructions contributions to the sets LocalLive and Killed.
|
||||
//
|
||||
InstructionList& instructions = node.getInstructions();
|
||||
for (InstructionList::iterator i = instructions.begin(); !instructions.done(i); i = instructions.advance(i)) {
|
||||
Instruction& instruction = instructions.get(i);
|
||||
|
||||
// If a VirtualRegister is 'used' before being 'defined' then we add it to set LocalLive.
|
||||
|
||||
InstructionUse* useEnd = instruction.getInstructionUseEnd();
|
||||
for (InstructionUse* usePtr = instruction.getInstructionUseBegin(); usePtr < useEnd; usePtr++)
|
||||
if (usePtr->isRegister()) {
|
||||
Uint32 index = name2range[usePtr->getRegisterName()];
|
||||
|
||||
if (!currentKilled.test(index))
|
||||
currentLocalLive.set(index);
|
||||
}
|
||||
|
||||
// If a Virtualregister is 'defined' then we add it to the set Killed.
|
||||
InstructionDefine* defineEnd = instruction.getInstructionDefineEnd();
|
||||
for (InstructionDefine* definePtr = instruction.getInstructionDefineBegin(); definePtr < defineEnd; definePtr++)
|
||||
if (definePtr->isRegister())
|
||||
currentKilled.set(name2range[definePtr->getRegisterName()]);
|
||||
}
|
||||
}
|
||||
|
||||
// Second stage of the liveness analysis: We propagate the LiveIn & LiveOut through the entire
|
||||
// control-flow graph.
|
||||
//
|
||||
RegisterPressure::Set temp(pool, rangeCount);
|
||||
|
||||
bool changed;
|
||||
do {
|
||||
changed = false;
|
||||
|
||||
// For all nodes is this graph except the endNode.
|
||||
for (Int32 n = (nNodes - 2); n >= 0; n--) {
|
||||
ControlNode& node = *nodes[n];
|
||||
|
||||
RegisterPressure::Set& currentLiveIn = liveIn[n];
|
||||
RegisterPressure::Set& currentLiveOut = liveOut[n];
|
||||
|
||||
// Compute temp = Union of LiveIn(s) (s a successor of this node) | usedByPhiNodes(n).
|
||||
// temp will be the new LiveOut(n).
|
||||
Uint32 nSuccessors = node.nSuccessors();
|
||||
if (nSuccessors != 0) {
|
||||
temp = liveIn[node.nthSuccessor(0).getTarget().dfsNum];
|
||||
for (Uint32 s = 1; s < nSuccessors; s++)
|
||||
temp |= liveIn[node.nthSuccessor(s).getTarget().dfsNum];
|
||||
} else
|
||||
temp.clear();
|
||||
|
||||
// If temp and LiveOut(n) differ then set LiveOut(n) = temp and recalculate the
|
||||
// new LiveIn(n).
|
||||
if (currentLiveOut != temp) {
|
||||
currentLiveOut = temp;
|
||||
temp -= killed[n]; // FIX: could be optimized with one call to unionDiff !
|
||||
temp |= currentLiveIn;
|
||||
|
||||
if (currentLiveIn != temp) {
|
||||
currentLiveIn = temp;
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
} while(changed);
|
||||
|
||||
LivenessInfo<RegisterPressure> liveness;
|
||||
liveness.liveIn = liveIn;
|
||||
liveness.liveOut = liveOut;
|
||||
DEBUG_LOG_ONLY(liveness.size = nNodes);
|
||||
return liveness;
|
||||
}
|
||||
|
||||
template <class RegisterPressure>
|
||||
LivenessInfo<RegisterPressure> Liveness<RegisterPressure>::analysis(ControlGraph& controlGraph, Uint32 nameCount)
|
||||
{
|
||||
Pool& pool = controlGraph.pool;
|
||||
ControlNode** nodes = controlGraph.dfsList;
|
||||
Uint32 nNodes = controlGraph.nNodes;
|
||||
|
||||
// Allocate the temporary sets.
|
||||
RegisterPressure::Set* killed = new(pool) RegisterPressure::Set[nNodes](pool, nameCount);
|
||||
RegisterPressure::Set* usedByPhiNodes = NULL;
|
||||
|
||||
// Allocate the globals sets.
|
||||
RegisterPressure::Set* liveIn = new(pool) RegisterPressure::Set[nNodes](pool, nameCount);
|
||||
RegisterPressure::Set* liveOut = new(pool) RegisterPressure::Set[nNodes](pool, nameCount);
|
||||
|
||||
// First stage of the liveness analysis: Compute the sets LocalLive(stored in LiveIn) and Killed.
|
||||
//
|
||||
for (Uint32 n = 0; n < (nNodes - 1); n++) {
|
||||
ControlNode& node = *nodes[n];
|
||||
|
||||
RegisterPressure::Set& currentLocalLive = liveIn[n];
|
||||
RegisterPressure::Set& currentKilled = killed[n];
|
||||
|
||||
InstructionList& phiNodes = node.getPhiNodeInstructions();
|
||||
|
||||
if ((usedByPhiNodes == NULL) && !phiNodes.empty())
|
||||
usedByPhiNodes = new(pool) RegisterPressure::Set[nNodes](pool, nameCount);
|
||||
|
||||
for (InstructionList::iterator p = phiNodes.begin(); !phiNodes.done(p); p = phiNodes.advance(p)) {
|
||||
Instruction& phiNode = phiNodes.get(p);
|
||||
|
||||
InstructionDefine& define = phiNode.getInstructionDefineBegin()[0];
|
||||
currentKilled.set(define.getRegisterName());
|
||||
|
||||
typedef DoublyLinkedList<ControlEdge> ControlEdgeList;
|
||||
const ControlEdgeList& predecessors = node.getPredecessors();
|
||||
ControlEdgeList::iterator p = predecessors.begin();
|
||||
InstructionUse* useEnd = phiNode.getInstructionUseEnd();
|
||||
for (InstructionUse* usePtr = phiNode.getInstructionUseBegin(); usePtr < useEnd; usePtr++, p = predecessors.advance(p))
|
||||
if (usePtr->isRegister())
|
||||
usedByPhiNodes[predecessors.get(p).getSource().dfsNum].set(usePtr->getRegisterName());
|
||||
}
|
||||
|
||||
// Find the instructions contributions to the sets LocalLive and Killed.
|
||||
//
|
||||
InstructionList& instructions = node.getInstructions();
|
||||
for (InstructionList::iterator i = instructions.begin(); !instructions.done(i); i = instructions.advance(i)) {
|
||||
Instruction& instruction = instructions.get(i);
|
||||
|
||||
// If a VirtualRegister is 'used' before being 'defined' then we add it to set LocalLive.
|
||||
|
||||
InstructionUse* useEnd = instruction.getInstructionUseEnd();
|
||||
for (InstructionUse* usePtr = instruction.getInstructionUseBegin(); usePtr < useEnd; usePtr++)
|
||||
if (usePtr->isRegister()) {
|
||||
Uint32 index = usePtr->getRegisterName();
|
||||
|
||||
if (!currentKilled.test(index))
|
||||
currentLocalLive.set(index);
|
||||
}
|
||||
|
||||
// If a Virtualregister is 'defined' then we add it to the set Killed.
|
||||
InstructionDefine* defineEnd = instruction.getInstructionDefineEnd();
|
||||
for (InstructionDefine* definePtr = instruction.getInstructionDefineBegin(); definePtr < defineEnd; definePtr++)
|
||||
if (definePtr->isRegister())
|
||||
currentKilled.set(definePtr->getRegisterName());
|
||||
}
|
||||
}
|
||||
|
||||
// Second stage of the liveness analysis: We propagate the LiveIn & LiveOut through the entire
|
||||
// control-flow graph.
|
||||
//
|
||||
RegisterPressure::Set temp(pool, nameCount);
|
||||
|
||||
bool changed;
|
||||
do {
|
||||
changed = false;
|
||||
|
||||
// For all nodes is this graph except the endNode.
|
||||
for (Int32 n = (nNodes - 2); n >= 0; n--) {
|
||||
ControlNode& node = *nodes[n];
|
||||
|
||||
RegisterPressure::Set& currentLiveIn = liveIn[n];
|
||||
RegisterPressure::Set& currentLiveOut = liveOut[n];
|
||||
|
||||
// Compute temp = Union of LiveIn(s) (s a successor of this node) | usedByPhiNodes(n).
|
||||
// temp will be the new LiveOut(n).
|
||||
Uint32 nSuccessors = node.nSuccessors();
|
||||
if (nSuccessors != 0) {
|
||||
temp = liveIn[node.nthSuccessor(0).getTarget().dfsNum];
|
||||
for (Uint32 s = 1; s < nSuccessors; s++)
|
||||
temp |= liveIn[node.nthSuccessor(s).getTarget().dfsNum];
|
||||
} else
|
||||
temp.clear();
|
||||
|
||||
// Insert the phiNodes contribution.
|
||||
if (usedByPhiNodes != NULL)
|
||||
temp |= usedByPhiNodes[n];
|
||||
|
||||
// If temp and LiveOut(n) differ then set LiveOut(n) = temp and recalculate the
|
||||
// new LiveIn(n).
|
||||
if (currentLiveOut != temp) {
|
||||
currentLiveOut = temp;
|
||||
temp -= killed[n]; // FIX: could be optimized with one call to unionDiff !
|
||||
temp |= currentLiveIn;
|
||||
|
||||
if (currentLiveIn != temp) {
|
||||
currentLiveIn = temp;
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
} while(changed);
|
||||
|
||||
LivenessInfo<RegisterPressure> liveness;
|
||||
liveness.liveIn = liveIn;
|
||||
liveness.liveOut = liveOut;
|
||||
DEBUG_LOG_ONLY(liveness.size = nNodes);
|
||||
return liveness;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_LOG
|
||||
template <class RegisterPressure>
|
||||
void LivenessInfo<RegisterPressure>::printPretty(LogModuleObject log)
|
||||
{
|
||||
for (Uint32 n = 0; n < size; n++) {
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("Node N%d:\n\tliveIn = ", n));
|
||||
liveIn[n].printPretty(log);
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("\tliveOut = "));
|
||||
liveOut[n].printPretty(log);
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("\n"));
|
||||
}
|
||||
}
|
||||
#endif // DEBUG_LOG
|
||||
|
||||
#endif // _LIVENESS_H_
|
||||
40
mozilla/ef/Compiler/RegisterAllocator/Makefile
Normal file
40
mozilla/ef/Compiler/RegisterAllocator/Makefile
Normal file
@@ -0,0 +1,40 @@
|
||||
#! gmake
|
||||
|
||||
DEPTH = ../..
|
||||
|
||||
MODULE_NAME = RegisterAllocator
|
||||
|
||||
include $(DEPTH)/config/config.mk
|
||||
|
||||
INCLUDES += \
|
||||
-I$(DEPTH)/Utilities/General \
|
||||
-I$(DEPTH)/Utilities/zlib \
|
||||
-I$(DEPTH)/Runtime/ClassReader \
|
||||
-I$(DEPTH)/Runtime/NativeMethods \
|
||||
-I$(DEPTH)/Runtime/System \
|
||||
-I$(DEPTH)/Runtime/ClassInfo \
|
||||
-I$(DEPTH)/Runtime/FileReader \
|
||||
-I$(DEPTH)/Compiler/PrimitiveGraph \
|
||||
-I$(DEPTH)/Compiler/FrontEnd \
|
||||
-I$(DEPTH)/Compiler/Optimizer \
|
||||
-I$(DEPTH)/Compiler/CodeGenerator \
|
||||
-I$(DEPTH)/Compiler/CodeGenerator/md \
|
||||
-I$(DEPTH)/Compiler/CodeGenerator/md/$(CPU_ARCH) \
|
||||
-I$(DEPTH)/Compiler/RegisterAllocator \
|
||||
-I$(DEPTH)/Driver/StandAloneJava \
|
||||
-I$(DEPTH)/Debugger \
|
||||
$(NULL)
|
||||
|
||||
CXXSRCS = \
|
||||
RegisterAllocator.cpp \
|
||||
RegisterAllocatorTools.cpp \
|
||||
DominatorGraph.cpp \
|
||||
VirtualRegister.cpp \
|
||||
BitSet.cpp \
|
||||
SparseSet.cpp \
|
||||
$(NULL)
|
||||
|
||||
|
||||
include $(DEPTH)/config/rules.mk
|
||||
|
||||
libs:: $(MODULE)
|
||||
392
mozilla/ef/Compiler/RegisterAllocator/PhiNodeRemover.h
Normal file
392
mozilla/ef/Compiler/RegisterAllocator/PhiNodeRemover.h
Normal file
@@ -0,0 +1,392 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef _PHI_NODE_REMOVER_H_
|
||||
#define _PHI_NODE_REMOVER_H_
|
||||
|
||||
#include "Fundamentals.h"
|
||||
#include "Pool.h"
|
||||
#include "ControlGraph.h"
|
||||
#include "DominatorGraph.h"
|
||||
#include "VirtualRegister.h"
|
||||
#include "RegisterPressure.h"
|
||||
#include "Liveness.h"
|
||||
#include "Instruction.h"
|
||||
#include "InstructionEmitter.h"
|
||||
#include "SparseSet.h"
|
||||
#include <string.h>
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// RegisterNameNode -
|
||||
|
||||
struct RegisterNameNode
|
||||
{
|
||||
RegisterNameNode* next;
|
||||
RegisterName newName;
|
||||
Uint32 nextPushed;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// CopyData -
|
||||
|
||||
struct CopyData
|
||||
{
|
||||
RegisterName source;
|
||||
RegisterClassKind classKind;
|
||||
Uint32 useCount;
|
||||
bool isLiveOut;
|
||||
RegisterName sourceNameToUse;
|
||||
RegisterName temporaryName;
|
||||
RegisterNameNode* newName;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// PhiNodeRemover<RegisterPressure> -
|
||||
|
||||
template <class RegisterPressure>
|
||||
struct PhiNodeRemover
|
||||
{
|
||||
// Replace the phi nodes by copy instructions.
|
||||
static void replacePhiNodes(ControlGraph& controlGraph, VirtualRegisterManager& vrManager, InstructionEmitter& emitter);
|
||||
};
|
||||
|
||||
// Split some of the critical edges and return true if there are still some
|
||||
// in the graph after that.
|
||||
//
|
||||
static bool splitCriticalEdges(ControlGraph& /*cg*/)
|
||||
{
|
||||
// FIX: not implemented.
|
||||
return true;
|
||||
}
|
||||
|
||||
inline void pushName(Pool& pool, RegisterNameNode** stack, SparseSet& pushed, Uint32* nodeListPointer, RegisterName oldName, RegisterName newName)
|
||||
{
|
||||
RegisterNameNode& newNode = *new(pool) RegisterNameNode();
|
||||
|
||||
if (pushed.test(oldName))
|
||||
(*stack)->newName = newName;
|
||||
else {
|
||||
newNode.newName = newName;
|
||||
newNode.nextPushed = *nodeListPointer;
|
||||
*nodeListPointer = oldName;
|
||||
newNode.next = *stack;
|
||||
*stack = &newNode;
|
||||
pushed.set(oldName);
|
||||
}
|
||||
}
|
||||
|
||||
template <class RegisterPressure>
|
||||
void PhiNodeRemover<RegisterPressure>::replacePhiNodes(ControlGraph& controlGraph, VirtualRegisterManager& vrManager, InstructionEmitter& emitter)
|
||||
{
|
||||
Pool& pool = controlGraph.pool;
|
||||
ControlNode** nodes = controlGraph.dfsList;
|
||||
Uint32 nNodes = controlGraph.nNodes;
|
||||
|
||||
// Initialize the local variables.
|
||||
//
|
||||
|
||||
// When we insert the copies we will also need to create new VirtualRegisters for
|
||||
// the insertion of temporaries. The maximum number of temporary register will not
|
||||
// exceed the number of phiNodes in the primitive graph.
|
||||
Uint32 nameCount = vrManager.getSize();
|
||||
Uint32 maxNameCount = nameCount;
|
||||
for (Uint32 n = 0; n < nNodes; n++)
|
||||
maxNameCount += nodes[n]->getPhiNodes().length();
|
||||
|
||||
// If the CFG contains some critical edges (backward edge which source has more than one
|
||||
// outgoing edge and destination has more than one incomimg edge) then we need the liveness
|
||||
// information to be able to insert temporary copies.
|
||||
RegisterPressure::Set* liveOut = NULL;
|
||||
if (splitCriticalEdges(controlGraph))
|
||||
liveOut = Liveness<LowRegisterPressure>::analysis(controlGraph, nameCount).liveOut;
|
||||
|
||||
DominatorGraph dGraph(controlGraph);
|
||||
|
||||
SparseSet pushed(pool, maxNameCount);
|
||||
SparseSet destinationList(pool, maxNameCount);
|
||||
SparseSet workList(pool, maxNameCount);
|
||||
|
||||
CopyData* copyStats = new(pool) CopyData[maxNameCount];
|
||||
memset(copyStats, '\0', maxNameCount*sizeof(CopyData));
|
||||
|
||||
struct NodeStack {
|
||||
Uint32* next;
|
||||
Uint32* limit;
|
||||
Uint32 pushedList;
|
||||
};
|
||||
|
||||
// Allocate the node stack and initialize the node stack pointer.
|
||||
NodeStack* nodeStack = new(pool) NodeStack[nNodes + 1];
|
||||
NodeStack* nodeStackPtr = nodeStack;
|
||||
|
||||
// We start by the begin node.
|
||||
Uint32 startNode = 0;
|
||||
Uint32* next = &startNode;
|
||||
Uint32* limit = &startNode + 1;
|
||||
|
||||
while (true) {
|
||||
|
||||
if (next == limit) {
|
||||
// If there are no more node in the sibling, we have to pop the current
|
||||
// frame from the stack and update the copyStats of the pushed nodes.
|
||||
//
|
||||
if (nodeStackPtr == nodeStack)
|
||||
// We are at the bottom of the stack and there are no more nodes
|
||||
// to look at. We are done !
|
||||
break;
|
||||
|
||||
--nodeStackPtr;
|
||||
// We are done with all the children of this node in the dominator tree.
|
||||
// We need to update the copy information of all the new names pushed
|
||||
// during the walk over this node.
|
||||
Uint32 pushedList = nodeStackPtr->pushedList;
|
||||
while (pushedList != 0) {
|
||||
Uint32 nextName = copyStats[pushedList].newName->nextPushed;
|
||||
copyStats[pushedList].newName = copyStats[pushedList].newName->next;
|
||||
pushedList = nextName;
|
||||
}
|
||||
|
||||
// restore the previous frame.
|
||||
next = nodeStackPtr->next;
|
||||
limit = nodeStackPtr->limit;
|
||||
} else {
|
||||
Uint32 currentNode = *next++;
|
||||
Uint32 pushedList = 0;
|
||||
|
||||
|
||||
// Initialize the sets.
|
||||
pushed.clear();
|
||||
destinationList.clear();
|
||||
|
||||
// STEP1:
|
||||
// Walk the instruction list and to replace all the instruction uses with their new name.
|
||||
// If the instruction is a phi node and its defined register is alive at the end of this
|
||||
// block then we push the defined register into the stack.
|
||||
//
|
||||
ControlNode& node = *nodes[currentNode];
|
||||
RegisterPressure::Set* currentLiveOut = (liveOut != NULL) ? &liveOut[currentNode] : (RegisterPressure::Set*) 0;
|
||||
|
||||
InstructionList& phiNodes = node.getPhiNodeInstructions();
|
||||
for (InstructionList::iterator p = phiNodes.begin(); !phiNodes.done(p); p = phiNodes.advance(p)) {
|
||||
Instruction& phiNode = phiNodes.get(p);
|
||||
|
||||
InstructionUse* useEnd = phiNode.getInstructionUseEnd();
|
||||
for (InstructionUse* usePtr = phiNode.getInstructionUseBegin(); usePtr < useEnd; usePtr++) {
|
||||
assert(usePtr->isRegister());
|
||||
RegisterName name = usePtr->getRegisterName();
|
||||
|
||||
if (copyStats[name].newName != NULL && copyStats[name].newName->newName != name)
|
||||
usePtr->setRegisterName(copyStats[name].newName->newName);
|
||||
}
|
||||
|
||||
if (currentLiveOut != NULL) {
|
||||
// This is a phi node and we have to push its defined name if it is live
|
||||
// at the end of the node. We only need to do this if the CFG has critical edges.
|
||||
assert(phiNode.getInstructionDefineBegin() != phiNode.getInstructionDefineEnd() && phiNode.getInstructionDefineBegin()[0].isRegister());
|
||||
RegisterName name = phiNode.getInstructionDefineBegin()[0].getRegisterName();
|
||||
|
||||
if (currentLiveOut->test(name))
|
||||
pushName(pool, &(copyStats[name].newName), pushed, &pushedList, name, name);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
InstructionList& instructions = node.getInstructions();
|
||||
for (InstructionList::iterator i = instructions.begin(); !instructions.done(i); i = instructions.advance(i)) {
|
||||
Instruction& instruction = instructions.get(i);
|
||||
|
||||
InstructionUse* useEnd = instruction.getInstructionUseEnd();
|
||||
for (InstructionUse* usePtr = instruction.getInstructionUseBegin(); usePtr < useEnd; usePtr++)
|
||||
if (usePtr->isRegister()) {
|
||||
RegisterName name = usePtr->getRegisterName();
|
||||
|
||||
if (copyStats[name].newName != NULL && copyStats[name].newName->newName != name)
|
||||
usePtr->setRegisterName(copyStats[name].newName->newName);
|
||||
}
|
||||
}
|
||||
|
||||
// STEP2:
|
||||
// Look at this node's successors' phiNodes. We keep track of the number of time
|
||||
// a VR will be used by another copy instruction and insert each definition into the
|
||||
// destinationList. This is the only pass over this node's successors as we will
|
||||
// get all the information we need in the CopyData structures.
|
||||
//
|
||||
ControlEdge* successorEdgeEnd = node.getSuccessorsEnd();
|
||||
for (ControlEdge* successorEdgePtr = node.getSuccessorsBegin(); successorEdgePtr < successorEdgeEnd; successorEdgePtr++) {
|
||||
Uint32 useIndex = successorEdgePtr->getIndex();
|
||||
ControlNode& successor = successorEdgePtr->getTarget();
|
||||
|
||||
// Look at its phi nodes. The phi nodes are at the top of the instruction list. We exit
|
||||
// as soon as we find an instruction which is not a phi node
|
||||
InstructionList& phiNodes = successor.getPhiNodeInstructions();
|
||||
for (InstructionList::iterator p = phiNodes.begin(); !phiNodes.done(p); p = phiNodes.advance(p)) {
|
||||
Instruction& phiNode = phiNodes.get(p);
|
||||
|
||||
assert((phiNode.getInstructionUseBegin() + useIndex) < phiNode.getInstructionUseEnd());
|
||||
assert(phiNode.getInstructionDefineBegin() != phiNode.getInstructionDefineEnd());
|
||||
|
||||
InstructionUse& source = phiNode.getInstructionUseBegin()[useIndex];
|
||||
InstructionDefine& destination = phiNode.getInstructionDefineBegin()[0];
|
||||
|
||||
assert(source.isRegister() && destination.isRegister());
|
||||
|
||||
RegisterName sourceName = source.getRegisterName();
|
||||
RegisterName destinationName = destination.getRegisterName();
|
||||
|
||||
// Get the correct name for the source.
|
||||
if (copyStats[sourceName].newName != NULL)
|
||||
sourceName = copyStats[sourceName].newName->newName;
|
||||
|
||||
// Update the CopyData structures.
|
||||
if ((sourceName != rnInvalid) && (sourceName != destinationName)) {
|
||||
copyStats[destinationName].source = sourceName;
|
||||
copyStats[destinationName].classKind = destination.getRegisterClass();
|
||||
copyStats[destinationName].isLiveOut = (currentLiveOut != NULL) ? currentLiveOut->test(destinationName) : false;
|
||||
copyStats[destinationName].sourceNameToUse = destinationName;
|
||||
copyStats[sourceName].sourceNameToUse = sourceName;
|
||||
copyStats[sourceName].useCount++;
|
||||
destinationList.set(destinationName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// STEP3:
|
||||
// Insert into the worklist only the destination registers that will be not used in
|
||||
// another copy instruction in this block.
|
||||
//
|
||||
assert(workList.getSize() == 0);
|
||||
for (SparseSet::iterator d = destinationList.begin(); !destinationList.done(d); d = destinationList.advance(d)) {
|
||||
Uint32 dest = destinationList.get(d);
|
||||
if (copyStats[dest].useCount == 0)
|
||||
workList.set(dest);
|
||||
}
|
||||
|
||||
// STEP4:
|
||||
// Insert the copy instructions.
|
||||
//
|
||||
Uint32 destinationListSize = destinationList.getSize();
|
||||
InstructionList::iterator endOfTheNode = instructions.end();
|
||||
|
||||
// Find the right place to insert the copy instructions.
|
||||
if (destinationListSize != 0)
|
||||
while (instructions.get(endOfTheNode).getFlags() & ifControl)
|
||||
endOfTheNode = instructions.retreat(endOfTheNode);
|
||||
|
||||
while (destinationListSize != 0) {
|
||||
while(workList.getSize()) {
|
||||
RegisterName destinationName = RegisterName(workList.getOne());
|
||||
RegisterName sourceName = copyStats[destinationName].source;
|
||||
|
||||
workList.clear(destinationName);
|
||||
if (copyStats[destinationName].isLiveOut && !copyStats[destinationName].temporaryName) {
|
||||
// Lost copy problem.
|
||||
copyStats[destinationName].isLiveOut = false;
|
||||
|
||||
RegisterName sourceName = destinationName;
|
||||
RegisterClassKind classKind = copyStats[sourceName].classKind;
|
||||
RegisterName destinationName = getName(vrManager.newVirtualRegister(classKind));
|
||||
assert(destinationName < maxNameCount);
|
||||
|
||||
copyStats[destinationName].classKind = classKind;
|
||||
copyStats[sourceName].useCount = 0;
|
||||
|
||||
// We need to insert a copy to a temporary register to keep the
|
||||
// source register valid at the end of the node defining it.
|
||||
// This copy will be inserted right after the phi node defining it.
|
||||
RegisterName from = copyStats[sourceName].sourceNameToUse;
|
||||
Instruction* definingPhiNode = vrManager.getVirtualRegister(from).getDefiningInstruction();
|
||||
assert(definingPhiNode && (definingPhiNode->getFlags() & ifPhiNode) != 0);
|
||||
|
||||
RegisterID fromID = buildRegisterID(from, classKind);
|
||||
RegisterID toID = buildRegisterID(destinationName, classKind);
|
||||
Instruction& copy = emitter.newCopy(*definingPhiNode->getPrimitive(), fromID, toID);
|
||||
vrManager.getVirtualRegister(destinationName).setDefiningInstruction(copy);
|
||||
definingPhiNode->getPrimitive()->getContainer()->getInstructions().addFirst(copy);
|
||||
|
||||
copyStats[sourceName].temporaryName = destinationName;
|
||||
copyStats[sourceName].sourceNameToUse = destinationName;
|
||||
pushName(pool, &(copyStats[sourceName].newName), pushed, &pushedList, sourceName, destinationName);
|
||||
}
|
||||
|
||||
// Insert the copy instruction at the end of the current node.
|
||||
RegisterName from = copyStats[sourceName].sourceNameToUse;
|
||||
|
||||
RegisterClassKind classKind = copyStats[destinationName].classKind;
|
||||
RegisterID fromID = buildRegisterID(from, classKind);
|
||||
RegisterID toID = buildRegisterID(destinationName, classKind);
|
||||
Instruction& copy = emitter.newCopy(*vrManager.getVirtualRegister(from).getDefiningInstruction()->getPrimitive(), fromID, toID);
|
||||
instructions.insertAfter(copy, endOfTheNode);
|
||||
endOfTheNode = instructions.advance(endOfTheNode);
|
||||
|
||||
copyStats[sourceName].useCount = 0;
|
||||
if (destinationList.test(sourceName) && copyStats[sourceName].isLiveOut)
|
||||
pushName(pool, &(copyStats[sourceName].newName), pushed, &pushedList, sourceName, destinationName);
|
||||
copyStats[sourceName].isLiveOut = false;
|
||||
copyStats[sourceName].sourceNameToUse = destinationName;
|
||||
|
||||
if (destinationList.test(sourceName))
|
||||
workList.set(sourceName);
|
||||
destinationList.clear(destinationName);
|
||||
}
|
||||
|
||||
destinationListSize = destinationList.getSize();
|
||||
if (destinationListSize != 0) {
|
||||
RegisterName sourceName = RegisterName(destinationList.getOne());
|
||||
RegisterName destinationName;
|
||||
|
||||
if (!copyStats[sourceName].temporaryName) {
|
||||
// Cycle problem.
|
||||
RegisterClassKind classKind = copyStats[sourceName].classKind;
|
||||
destinationName = getName(vrManager.newVirtualRegister(classKind));
|
||||
assert(destinationName < maxNameCount);
|
||||
|
||||
copyStats[destinationName].classKind = classKind;
|
||||
copyStats[sourceName].temporaryName = destinationName;
|
||||
|
||||
// Insert the copy instruction at the end of the current node.
|
||||
RegisterName from = copyStats[sourceName].sourceNameToUse;
|
||||
|
||||
RegisterID fromID = buildRegisterID(from, classKind);
|
||||
RegisterID toID = buildRegisterID(destinationName, classKind);
|
||||
Instruction& copy = emitter.newCopy(*vrManager.getVirtualRegister(from).getDefiningInstruction()->getPrimitive(), fromID, toID);
|
||||
vrManager.getVirtualRegister(destinationName).setDefiningInstruction(copy);
|
||||
instructions.insertAfter(copy, endOfTheNode);
|
||||
endOfTheNode = instructions.advance(endOfTheNode);
|
||||
} else
|
||||
destinationName = copyStats[sourceName].temporaryName;
|
||||
|
||||
copyStats[sourceName].useCount = 0;
|
||||
copyStats[sourceName].isLiveOut = false;
|
||||
copyStats[sourceName].sourceNameToUse = destinationName;
|
||||
pushName(pool, &(copyStats[sourceName].newName), pushed, &pushedList, sourceName, destinationName);
|
||||
|
||||
workList.set(sourceName);
|
||||
}
|
||||
}
|
||||
|
||||
nodeStackPtr->pushedList = pushedList;
|
||||
nodeStackPtr->next = next;
|
||||
nodeStackPtr->limit = limit;
|
||||
++nodeStackPtr;
|
||||
next = dGraph.getSuccessorsBegin(currentNode);
|
||||
limit = dGraph.getSuccessorsEnd(currentNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // _PHI_NODE_REMOVER_H_
|
||||
155
mozilla/ef/Compiler/RegisterAllocator/RegisterAllocator.cpp
Normal file
155
mozilla/ef/Compiler/RegisterAllocator/RegisterAllocator.cpp
Normal file
@@ -0,0 +1,155 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* 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 "Fundamentals.h"
|
||||
#include "LogModule.h"
|
||||
#include "RegisterAllocator.h"
|
||||
#include "RegisterPressure.h"
|
||||
#include "RegisterAllocatorTools.h"
|
||||
#include "PhiNodeRemover.h"
|
||||
#include "LiveRange.h"
|
||||
#include "Liveness.h"
|
||||
#include "InterferenceGraph.h"
|
||||
#include "LiveRangeGraph.h"
|
||||
#include "Coalescing.h"
|
||||
#include "Spilling.h"
|
||||
#include "Coloring.h"
|
||||
#include "Splits.h"
|
||||
|
||||
class Pool;
|
||||
class ControlGraph;
|
||||
class VirtualRegisterManager;
|
||||
class InstructionEmitter;
|
||||
|
||||
UT_DEFINE_LOG_MODULE(RegAlloc);
|
||||
|
||||
void RegisterAllocator::allocateRegisters(Pool& pool, ControlGraph& controlGraph, VirtualRegisterManager& vrManager, InstructionEmitter& emitter)
|
||||
{
|
||||
// Insert the phi node instructions. We want to do this to have a single defined register per instruction.
|
||||
// If we keep the PhiNode (as a DataNode) and a PhiNode is of DoubleWordKind then we have to execute
|
||||
// some special code for the high word annotation.
|
||||
//
|
||||
RegisterAllocatorTools::insertPhiNodeInstructions(controlGraph, emitter);
|
||||
|
||||
// Perform some tests on the instruction graph.
|
||||
//
|
||||
DEBUG_ONLY(RegisterAllocatorTools::testTheInstructionGraph(controlGraph, vrManager));
|
||||
|
||||
// Replace the phi node instructions by their equivalent copy instructions.
|
||||
//
|
||||
PhiNodeRemover<LowRegisterPressure>::replacePhiNodes(controlGraph, vrManager, emitter);
|
||||
|
||||
// Do the register allocation.
|
||||
//
|
||||
RegisterAllocator registerAllocator(pool, controlGraph, vrManager, emitter);
|
||||
registerAllocator.doGraphColoring();
|
||||
}
|
||||
|
||||
void RegisterAllocator::doGraphColoring()
|
||||
{
|
||||
// Initialize the liverange map.
|
||||
//
|
||||
initLiveRanges();
|
||||
|
||||
// Build the live ranges. We do this to compress the number of RegisterNames
|
||||
// used in the insterference graph.
|
||||
//
|
||||
LiveRange<LowRegisterPressure>::build(*this);
|
||||
|
||||
// Remove unnecessary copies.
|
||||
//
|
||||
RegisterAllocatorTools::removeUnnecessaryCopies(*this);
|
||||
|
||||
for (Uint8 loop = 0; loop < 10; loop++) {
|
||||
|
||||
UT_OBJECTLOG(UT_LOG_MODULE(RegAlloc), PR_LOG_ALWAYS, ("********* RegisterAllocator loop %d *********\n", loop));
|
||||
|
||||
while(true) {
|
||||
// Build the interference graph.
|
||||
//
|
||||
iGraph.build();
|
||||
|
||||
// Coalesce the copy instructions.
|
||||
//
|
||||
if (!Coalescing<LowRegisterPressure>::coalesce(*this))
|
||||
break;
|
||||
}
|
||||
|
||||
// Print the interference graph.
|
||||
//
|
||||
DEBUG_LOG_ONLY(iGraph.printPretty(UT_LOG_MODULE(RegAlloc)));
|
||||
|
||||
// Calculate the spill costs.
|
||||
//
|
||||
Spilling<LowRegisterPressure>::calculateSpillCosts(*this);
|
||||
DEBUG_LOG_ONLY(RegisterAllocatorTools::printSpillCosts(*this));
|
||||
|
||||
// Calculate the split costs.
|
||||
//
|
||||
Splits<LowRegisterPressure>::calculateSplitCosts(*this);
|
||||
DEBUG_LOG_ONLY(RegisterAllocatorTools::printSplitCosts(*this));
|
||||
|
||||
// Build the live range graph.
|
||||
//
|
||||
lGraph.build();
|
||||
DEBUG_LOG_ONLY(lGraph.printPretty(UT_LOG_MODULE(RegAlloc)));
|
||||
|
||||
// Color the graph. If it succeeds then we're done with the
|
||||
// register allocation.
|
||||
//
|
||||
if (Coloring<LowRegisterPressure>::color(*this)) {
|
||||
// Write the final colors in the instruction graph.
|
||||
//
|
||||
Coloring<LowRegisterPressure>::finalColoring(*this);
|
||||
|
||||
UT_OBJECTLOG(UT_LOG_MODULE(RegAlloc), PR_LOG_ALWAYS, ("********** RegisterAllocator done **********\n"));
|
||||
DEBUG_LOG_ONLY(RegisterAllocatorTools::printInstructions(*this));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// We need to spill some registers.
|
||||
//
|
||||
Spilling<LowRegisterPressure>::insertSpillCode(*this);
|
||||
|
||||
// Insert the split instructions.
|
||||
//
|
||||
Splits<LowRegisterPressure>::insertSplitCode(*this);
|
||||
|
||||
// Update the live ranges.
|
||||
//
|
||||
// FIX
|
||||
}
|
||||
|
||||
#ifdef DEBUG_LOG
|
||||
RegisterAllocatorTools::updateInstructionGraph(*this);
|
||||
RegisterAllocatorTools::printInstructions(*this);
|
||||
#endif
|
||||
fprintf(stderr, "!!! Coloring failed after 10 loops !!!\n");
|
||||
abort();
|
||||
}
|
||||
|
||||
void RegisterAllocator::initLiveRanges()
|
||||
{
|
||||
Uint32 count = this->nameCount;
|
||||
RegisterName* name2range = new(pool) RegisterName[nameCount];
|
||||
for (RegisterName r = RegisterName(1); r < count; r = RegisterName(r + 1))
|
||||
name2range[r] = r;
|
||||
this->name2range = name2range;
|
||||
rangeCount = count;
|
||||
}
|
||||
88
mozilla/ef/Compiler/RegisterAllocator/RegisterAllocator.h
Normal file
88
mozilla/ef/Compiler/RegisterAllocator/RegisterAllocator.h
Normal file
@@ -0,0 +1,88 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef _REGISTER_ALLOCATOR_H_
|
||||
#define _REGISTER_ALLOCATOR_H_
|
||||
|
||||
class Pool;
|
||||
class ControlGraph;
|
||||
class InstructionEmitter;
|
||||
struct SpillCost;
|
||||
struct SplitCost;
|
||||
|
||||
#include "Liveness.h"
|
||||
#include "VirtualRegister.h"
|
||||
#include "RegisterPressure.h" // This should included by Backend.cpp
|
||||
#include "InterferenceGraph.h"
|
||||
#include "LiveRangeGraph.h"
|
||||
|
||||
//template <class RegisterPressure>
|
||||
class RegisterAllocator
|
||||
{
|
||||
public:
|
||||
|
||||
Pool& pool; //
|
||||
ControlGraph& controlGraph; //
|
||||
VirtualRegisterManager& vrManager; //
|
||||
InstructionEmitter& emitter; //
|
||||
|
||||
RegisterName* name2range; //
|
||||
RegisterName* color; //
|
||||
SpillCost* spillCost; //
|
||||
SparseSet* willSpill; //
|
||||
SplitCost* splitCost; //
|
||||
NameLinkedList** splitAround; //
|
||||
InterferenceGraph<LowRegisterPressure> iGraph; //
|
||||
LiveRangeGraph<LowRegisterPressure> lGraph; //
|
||||
LivenessInfo<LowRegisterPressure> liveness; //
|
||||
Uint32 nameCount; //
|
||||
Uint32 rangeCount; //
|
||||
bool splitFound; //
|
||||
|
||||
private:
|
||||
|
||||
//
|
||||
//
|
||||
void doGraphColoring();
|
||||
|
||||
public:
|
||||
|
||||
//
|
||||
//
|
||||
inline RegisterAllocator(Pool& pool, ControlGraph& controlGraph, VirtualRegisterManager& vrManager, InstructionEmitter& emitter);
|
||||
|
||||
//
|
||||
//
|
||||
bool canInterfere(RegisterName /*name1*/, RegisterName /*name2*/) const {return true;}
|
||||
|
||||
//
|
||||
//
|
||||
void initLiveRanges();
|
||||
|
||||
//
|
||||
//
|
||||
static void allocateRegisters(Pool& pool, ControlGraph& controlGraph, VirtualRegisterManager& vrManager, InstructionEmitter& emitter);
|
||||
};
|
||||
|
||||
//
|
||||
//
|
||||
inline RegisterAllocator::RegisterAllocator(Pool& pool, ControlGraph& controlGraph, VirtualRegisterManager& vrManager, InstructionEmitter& emitter)
|
||||
: pool(pool), controlGraph(controlGraph), vrManager(vrManager), emitter(emitter), iGraph(*this), lGraph(*this), nameCount(vrManager.getSize()) {}
|
||||
|
||||
#endif // _REGISTER_ALLOCATOR_H_
|
||||
|
||||
355
mozilla/ef/Compiler/RegisterAllocator/RegisterAllocatorTools.cpp
Normal file
355
mozilla/ef/Compiler/RegisterAllocator/RegisterAllocatorTools.cpp
Normal file
@@ -0,0 +1,355 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* 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 "Fundamentals.h"
|
||||
#include "LogModule.h"
|
||||
#include "RegisterAllocatorTools.h"
|
||||
#include "Pool.h"
|
||||
#include "ControlGraph.h"
|
||||
#include "ControlNodes.h"
|
||||
#include "Primitives.h"
|
||||
#include "InstructionEmitter.h"
|
||||
#include "Instruction.h"
|
||||
#include "RegisterAllocator.h"
|
||||
#include "Spilling.h"
|
||||
#include "Splits.h"
|
||||
#include "BitSet.h"
|
||||
|
||||
UT_EXTERN_LOG_MODULE(RegAlloc);
|
||||
|
||||
#ifdef DEBUG
|
||||
void RegisterAllocatorTools::testTheInstructionGraph(ControlGraph& controlGraph, VirtualRegisterManager& vrManager)
|
||||
{
|
||||
// Test the declared VirtualRegisters. The register allocator tries to condense the register universe.
|
||||
// Any gap in the VirtualRegister names will be a loss of efficiency !!!!
|
||||
|
||||
Uint32 nameCount = vrManager.getSize();
|
||||
BitSet registerSeen(controlGraph.pool, nameCount);
|
||||
|
||||
ControlNode** nodes = controlGraph.dfsList;
|
||||
Uint32 nNodes = controlGraph.nNodes;
|
||||
|
||||
for (Uint32 n = 0; n < nNodes; n++) {
|
||||
|
||||
InstructionList& instructions = nodes[n]->getInstructions();
|
||||
for (InstructionList::iterator i = instructions.begin(); !instructions.done(i); i = instructions.advance(i)) {
|
||||
Instruction& instruction = instructions.get(i);
|
||||
|
||||
InstructionUse* useEnd = instruction.getInstructionUseEnd();
|
||||
for (InstructionUse* usePtr = instruction.getInstructionUseBegin(); usePtr < useEnd; usePtr++)
|
||||
if (usePtr->isRegister())
|
||||
registerSeen.set(usePtr->getRegisterName());
|
||||
|
||||
InstructionDefine* defineEnd = instruction.getInstructionDefineEnd();
|
||||
for (InstructionDefine* definePtr = instruction.getInstructionDefineBegin(); definePtr < defineEnd; definePtr++)
|
||||
if (definePtr->isRegister())
|
||||
registerSeen.set(definePtr->getRegisterName());
|
||||
}
|
||||
|
||||
InstructionList& phiNodes = nodes[n]->getPhiNodeInstructions();
|
||||
for (InstructionList::iterator p = phiNodes.begin(); !phiNodes.done(p); p = phiNodes.advance(p)) {
|
||||
Instruction& instruction = phiNodes.get(p);
|
||||
|
||||
InstructionUse* useEnd = instruction.getInstructionUseEnd();
|
||||
for (InstructionUse* usePtr = instruction.getInstructionUseBegin(); usePtr < useEnd; usePtr++)
|
||||
if (usePtr->isRegister())
|
||||
registerSeen.set(usePtr->getRegisterName());
|
||||
|
||||
InstructionDefine* defineEnd = instruction.getInstructionDefineEnd();
|
||||
for (InstructionDefine* definePtr = instruction.getInstructionDefineBegin(); definePtr < defineEnd; definePtr++)
|
||||
if (definePtr->isRegister())
|
||||
registerSeen.set(definePtr->getRegisterName());
|
||||
}
|
||||
}
|
||||
|
||||
bool renameRegisters = false;
|
||||
for (BitSet::iterator i = registerSeen.nextZero(0); !registerSeen.done(i); i = registerSeen.nextZero(i)) {
|
||||
renameRegisters = true;
|
||||
fprintf(stderr,
|
||||
"WARNING: The VirtualRegister vr%d has been allocated during CodeGeneration but\n"
|
||||
" is never used nor defined by any instruction in the instruction graph\n"
|
||||
" PLEASE FIX \n",
|
||||
i);
|
||||
}
|
||||
if (renameRegisters) {
|
||||
Instruction** definingInstruction = new Instruction*[nameCount];
|
||||
memset(definingInstruction, '\0', nameCount * sizeof(Instruction*));
|
||||
RegisterName* newName = new RegisterName[nameCount];
|
||||
memset(newName, '\0', nameCount * sizeof(RegisterName));
|
||||
RegisterName nextName = RegisterName(1);
|
||||
|
||||
for (Uint32 n = 0; n < nNodes; n++) {
|
||||
|
||||
InstructionList& instructions = nodes[n]->getInstructions();
|
||||
for (InstructionList::iterator i = instructions.begin(); !instructions.done(i); i = instructions.advance(i)) {
|
||||
Instruction& instruction = instructions.get(i);
|
||||
|
||||
InstructionUse* useEnd = instruction.getInstructionUseEnd();
|
||||
for (InstructionUse* usePtr = instruction.getInstructionUseBegin(); usePtr < useEnd; usePtr++)
|
||||
if (usePtr->isRegister()) {
|
||||
RegisterName name = usePtr->getRegisterName();
|
||||
if (newName[name] == rnInvalid) {
|
||||
newName[name] = nextName;
|
||||
definingInstruction[nextName] = vrManager.getVirtualRegister(name).getDefiningInstruction();
|
||||
nextName = RegisterName(nextName + 1);
|
||||
}
|
||||
usePtr->setRegisterName(newName[name]);
|
||||
}
|
||||
|
||||
InstructionDefine* defineEnd = instruction.getInstructionDefineEnd();
|
||||
for (InstructionDefine* definePtr = instruction.getInstructionDefineBegin(); definePtr < defineEnd; definePtr++)
|
||||
if (definePtr->isRegister()) {
|
||||
RegisterName name = definePtr->getRegisterName();
|
||||
if (newName[name] == rnInvalid) {
|
||||
newName[name] = nextName;
|
||||
definingInstruction[nextName] = vrManager.getVirtualRegister(name).getDefiningInstruction();
|
||||
nextName = RegisterName(nextName + 1);
|
||||
}
|
||||
definePtr->setRegisterName(newName[name]);
|
||||
}
|
||||
}
|
||||
|
||||
InstructionList& phiNodes = nodes[n]->getPhiNodeInstructions();
|
||||
for (InstructionList::iterator p = phiNodes.begin(); !phiNodes.done(p); p = phiNodes.advance(p)) {
|
||||
Instruction& instruction = phiNodes.get(p);
|
||||
|
||||
InstructionUse* useEnd = instruction.getInstructionUseEnd();
|
||||
for (InstructionUse* usePtr = instruction.getInstructionUseBegin(); usePtr < useEnd; usePtr++)
|
||||
if (usePtr->isRegister()) {
|
||||
RegisterName name = usePtr->getRegisterName();
|
||||
if (newName[name] == rnInvalid) {
|
||||
newName[name] = nextName;
|
||||
definingInstruction[nextName] = vrManager.getVirtualRegister(name).getDefiningInstruction();
|
||||
nextName = RegisterName(nextName + 1);
|
||||
}
|
||||
usePtr->setRegisterName(newName[name]);
|
||||
}
|
||||
|
||||
InstructionDefine* defineEnd = instruction.getInstructionDefineEnd();
|
||||
for (InstructionDefine* definePtr = instruction.getInstructionDefineBegin(); definePtr < defineEnd; definePtr++)
|
||||
if (definePtr->isRegister()) {
|
||||
RegisterName name = definePtr->getRegisterName();
|
||||
if (newName[name] == rnInvalid) {
|
||||
newName[name] = nextName;
|
||||
definingInstruction[nextName] = vrManager.getVirtualRegister(name).getDefiningInstruction();
|
||||
nextName = RegisterName(nextName + 1);
|
||||
}
|
||||
definePtr->setRegisterName(newName[name]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
vrManager.setSize(nextName);
|
||||
|
||||
for (RegisterName r = RegisterName(1); r < nextName; r = RegisterName(r + 1))
|
||||
vrManager.getVirtualRegister(r).definingInstruction = definingInstruction[r];
|
||||
|
||||
UT_OBJECTLOG(UT_LOG_MODULE(RegAlloc), PR_LOG_ALWAYS, ("RegisterMap:\n"));
|
||||
for (Uint32 i = 1; i < nameCount; i++)
|
||||
if (newName[i] != 0)
|
||||
UT_OBJECTLOG(UT_LOG_MODULE(RegAlloc), PR_LOG_ALWAYS, ("\tvr%d becomes vr%d.\n", i, newName[i]));
|
||||
else
|
||||
UT_OBJECTLOG(UT_LOG_MODULE(RegAlloc), PR_LOG_ALWAYS, ("\tvr%d is dead.\n", i));
|
||||
|
||||
|
||||
delete newName;
|
||||
delete definingInstruction;
|
||||
}
|
||||
|
||||
}
|
||||
#endif // DEBUG
|
||||
|
||||
void RegisterAllocatorTools::removeUnnecessaryCopies(RegisterAllocator& registerAllocator)
|
||||
{
|
||||
ControlGraph& controlGraph = registerAllocator.controlGraph;
|
||||
ControlNode** nodes = controlGraph.dfsList;
|
||||
Uint32 nNodes = controlGraph.nNodes;
|
||||
RegisterName* name2range = registerAllocator.name2range;
|
||||
|
||||
for (Uint32 n = 0; n < nNodes; n++) {
|
||||
InstructionList& instructions = nodes[n]->getInstructions();
|
||||
for (InstructionList::iterator i = instructions.begin(); !instructions.done(i);) {
|
||||
Instruction& instruction = instructions.get(i);
|
||||
i = instructions.advance(i);
|
||||
|
||||
if (instruction.getFlags() & ifCopy) {
|
||||
assert(instruction.getInstructionUseBegin() != instruction.getInstructionUseEnd() && instruction.getInstructionUseBegin()[0].isRegister());
|
||||
assert(instruction.getInstructionDefineBegin() != instruction.getInstructionDefineEnd() && instruction.getInstructionDefineBegin()[0].isRegister());
|
||||
|
||||
RegisterName source = name2range[instruction.getInstructionUseBegin()[0].getRegisterName()];
|
||||
RegisterName destination = name2range[instruction.getInstructionDefineBegin()[0].getRegisterName()];
|
||||
|
||||
if (source == destination)
|
||||
instruction.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void RegisterAllocatorTools::updateInstructionGraph(RegisterAllocator& registerAllocator)
|
||||
{
|
||||
ControlGraph& controlGraph = registerAllocator.controlGraph;
|
||||
ControlNode** nodes = controlGraph.dfsList;
|
||||
Uint32 nNodes = controlGraph.nNodes;
|
||||
RegisterName* name2range = registerAllocator.name2range;
|
||||
|
||||
for (Uint32 n = 0; n < nNodes; n++) {
|
||||
InstructionList& instructions = nodes[n]->getInstructions();
|
||||
for (InstructionList::iterator i = instructions.begin(); !instructions.done(i); i = instructions.advance(i)) {
|
||||
Instruction& instruction = instructions.get(i);
|
||||
|
||||
InstructionUse* useEnd = instruction.getInstructionUseEnd();
|
||||
for (InstructionUse* usePtr = instruction.getInstructionUseBegin(); usePtr < useEnd; usePtr++)
|
||||
if (usePtr->isRegister())
|
||||
usePtr->setRegisterName(name2range[usePtr->getRegisterName()]);
|
||||
|
||||
InstructionDefine* defineEnd = instruction.getInstructionDefineEnd();
|
||||
for (InstructionDefine* definePtr = instruction.getInstructionDefineBegin(); definePtr < defineEnd; definePtr++)
|
||||
if (definePtr->isRegister())
|
||||
definePtr->setRegisterName(name2range[definePtr->getRegisterName()]);
|
||||
}
|
||||
|
||||
InstructionList& phiNodes = nodes[n]->getPhiNodeInstructions();
|
||||
for (InstructionList::iterator p = phiNodes.begin(); !phiNodes.done(p); p = phiNodes.advance(p)) {
|
||||
Instruction& instruction = phiNodes.get(p);
|
||||
|
||||
InstructionUse* useEnd = instruction.getInstructionUseEnd();
|
||||
for (InstructionUse* usePtr = instruction.getInstructionUseBegin(); usePtr < useEnd; usePtr++)
|
||||
if (usePtr->isRegister())
|
||||
usePtr->setRegisterName(name2range[usePtr->getRegisterName()]);
|
||||
|
||||
InstructionDefine* defineEnd = instruction.getInstructionDefineEnd();
|
||||
for (InstructionDefine* definePtr = instruction.getInstructionDefineBegin(); definePtr < defineEnd; definePtr++)
|
||||
if (definePtr->isRegister())
|
||||
definePtr->setRegisterName(name2range[definePtr->getRegisterName()]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void RegisterAllocatorTools::insertPhiNodeInstructions(ControlGraph& controlGraph, InstructionEmitter& emitter)
|
||||
{
|
||||
Pool& pool = controlGraph.pool;
|
||||
ControlNode** nodes = controlGraph.dfsList;
|
||||
Uint32 nNodes = controlGraph.nNodes;
|
||||
|
||||
for (Uint32 n = 0; n < nNodes; n++) {
|
||||
ControlNode& node = *nodes[n];
|
||||
DoublyLinkedList<PhiNode>& phiNodes = node.getPhiNodes();
|
||||
|
||||
if (!phiNodes.empty()) {
|
||||
|
||||
// Set the index of the incoming edges.
|
||||
Uint32 index = 0;
|
||||
const DoublyLinkedList<ControlEdge>& predecessors = node.getPredecessors();
|
||||
for (DoublyLinkedList<ControlEdge>::iterator p = predecessors.begin(); !predecessors.done(p); p = predecessors.advance(p))
|
||||
predecessors.get(p).setIndex(index++);
|
||||
|
||||
// Insert the phi node instruction in the instruction list.
|
||||
for (DoublyLinkedList<PhiNode>::iterator i = phiNodes.begin(); !phiNodes.done(i); i = phiNodes.advance(i)) {
|
||||
PhiNode& phiNode = phiNodes.get(i);
|
||||
ValueKind kind = phiNode.getKind();
|
||||
|
||||
if (!isStorableKind(kind))
|
||||
continue;
|
||||
|
||||
RegisterClassKind classKind = rckGeneral; // FIX: get class kind from phi node kind.
|
||||
Uint32 nInputs = phiNode.nInputs();
|
||||
|
||||
PhiNodeInstruction& phiNodeInstruction = *new(pool) PhiNodeInstruction(&phiNode, pool, nInputs);
|
||||
|
||||
emitter.defineProducer(phiNode, phiNodeInstruction, 0, classKind, drLow);
|
||||
for (Uint32 whichInput = 0; whichInput < nInputs; whichInput++)
|
||||
emitter.useProducer(phiNode.nthInputVariable(whichInput), phiNodeInstruction, whichInput, classKind, drLow);
|
||||
|
||||
node.addPhiNodeInstruction(phiNodeInstruction);
|
||||
|
||||
if (isDoublewordKind(kind)) {
|
||||
PhiNodeInstruction& phiNodeInstruction = *new(pool) PhiNodeInstruction(&phiNode, pool, nInputs);
|
||||
|
||||
emitter.defineProducer(phiNode, phiNodeInstruction, 0, classKind, drHigh);
|
||||
for (Uint32 whichInput = 0; whichInput < nInputs; whichInput++)
|
||||
emitter.useProducer(phiNode.nthInputVariable(whichInput), phiNodeInstruction, whichInput, classKind, drHigh);
|
||||
|
||||
node.addPhiNodeInstruction(phiNodeInstruction);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG_LOG
|
||||
|
||||
void RegisterAllocatorTools::printSpillCosts(RegisterAllocator& registerAllocator)
|
||||
{
|
||||
LogModuleObject log = UT_LOG_MODULE(RegAlloc);
|
||||
Uint32 rangeCount = registerAllocator.rangeCount;
|
||||
SpillCost* cost = registerAllocator.spillCost;
|
||||
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("Spill costs:\n"));
|
||||
for (Uint32 i = 1; i < rangeCount; i++) {
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("\trange %d : ", i));
|
||||
if (cost[i].infinite)
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("infinite\n"));
|
||||
else
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("%f\n", cost[i].cost));
|
||||
}
|
||||
}
|
||||
|
||||
void RegisterAllocatorTools::printSplitCosts(RegisterAllocator& registerAllocator)
|
||||
{
|
||||
LogModuleObject log = UT_LOG_MODULE(RegAlloc);
|
||||
Uint32 rangeCount = registerAllocator.rangeCount;
|
||||
SplitCost* cost = registerAllocator.splitCost;
|
||||
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("Split costs:\n"));
|
||||
for (Uint32 i = 1; i < rangeCount; i++) {
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("\trange %d : loads = %f stores = %f\n", i, cost[i].loads, cost[i].stores));
|
||||
}
|
||||
}
|
||||
|
||||
void RegisterAllocatorTools::printInstructions(RegisterAllocator& registerAllocator)
|
||||
{
|
||||
LogModuleObject log = UT_LOG_MODULE(RegAlloc);
|
||||
ControlNode** nodes = registerAllocator.controlGraph.dfsList;
|
||||
Uint32 nNodes = registerAllocator.controlGraph.nNodes;
|
||||
|
||||
for (Uint32 n = 0; n < nNodes; n++) {
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("N%d:\n", n));
|
||||
|
||||
InstructionList& phiNodes = nodes[n]->getPhiNodeInstructions();
|
||||
InstructionList& instructions = nodes[n]->getInstructions();
|
||||
|
||||
if (!phiNodes.empty()) {
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, (" PhiNodes:\n", n));
|
||||
for(InstructionList::iterator i = phiNodes.begin(); !phiNodes.done(i); i = phiNodes.advance(i)) {
|
||||
phiNodes.get(i).printPretty(log);
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("\n"));
|
||||
}
|
||||
if (!instructions.empty())
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, (" Instructions:\n", n));
|
||||
}
|
||||
|
||||
for(InstructionList::iterator i = instructions.begin(); !instructions.done(i); i = instructions.advance(i)) {
|
||||
instructions.get(i).printPretty(log);
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("\n"));
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // DEBUG_LOG
|
||||
117
mozilla/ef/Compiler/RegisterAllocator/RegisterAllocatorTools.h
Normal file
117
mozilla/ef/Compiler/RegisterAllocator/RegisterAllocatorTools.h
Normal file
@@ -0,0 +1,117 @@
|
||||
// -*- mode:C++; tab-width:4; truncate-lines:t -*-
|
||||
//
|
||||
// CONFIDENTIAL AND PROPRIETARY SOURCE CODE OF
|
||||
// NETSCAPE COMMUNICATIONS CORPORATION
|
||||
// Copyright © 1996, 1997 Netscape Communications Corporation. All Rights
|
||||
// Reserved. Use of this Source Code is subject to the terms of the
|
||||
// applicable license agreement from Netscape Communications Corporation.
|
||||
// The copyright notice(s) in this Source Code does not indicate actual or
|
||||
// intended publication of this Source Code.
|
||||
//
|
||||
// $Id: RegisterAllocatorTools.h,v 1.1.2.1 1999-03-02 16:12:05 fur%netscape.com Exp $
|
||||
//
|
||||
|
||||
#ifndef _REGISTER_ALLOCATOR_TOOLS_H_
|
||||
#define _REGISTER_ALLOCATOR_TOOLS_H_
|
||||
|
||||
#include "LogModule.h"
|
||||
#include "RegisterTypes.h"
|
||||
#include <string.h>
|
||||
|
||||
class RegisterAllocator;
|
||||
class ControlGraph;
|
||||
class InstructionEmitter;
|
||||
class VirtualRegisterManager;
|
||||
|
||||
struct RegisterAllocatorTools
|
||||
{
|
||||
//
|
||||
//
|
||||
static void insertPhiNodeInstructions(ControlGraph& controlGraph, InstructionEmitter& emitter);
|
||||
|
||||
//
|
||||
//
|
||||
static void updateInstructionGraph(RegisterAllocator& registerAllocator);
|
||||
|
||||
//
|
||||
//
|
||||
static void removeUnnecessaryCopies(RegisterAllocator& registerAllocator);
|
||||
|
||||
#ifdef DEBUG
|
||||
//
|
||||
//
|
||||
static void testTheInstructionGraph(ControlGraph& controlGraph, VirtualRegisterManager& vrManager);
|
||||
#endif // DEBUG
|
||||
|
||||
#ifdef DEBUG_LOG
|
||||
//
|
||||
//
|
||||
static void printInstructions(RegisterAllocator& registerAllocator);
|
||||
|
||||
//
|
||||
//
|
||||
static void printSpillCosts(RegisterAllocator& registerAllocator);
|
||||
|
||||
//
|
||||
//
|
||||
static void printSplitCosts(RegisterAllocator& registerAllocator);
|
||||
#endif // DEBUG_LOG
|
||||
};
|
||||
|
||||
//
|
||||
// FIX: this should go in a class (LookupTable ?)
|
||||
//
|
||||
|
||||
inline RegisterName findRoot(RegisterName name, RegisterName* table)
|
||||
{
|
||||
RegisterName* stack = table;
|
||||
RegisterName* stackPtr = stack;
|
||||
|
||||
RegisterName newName;
|
||||
while((newName = table[name]) != name) {
|
||||
*--stackPtr = name;
|
||||
name = newName;
|
||||
}
|
||||
|
||||
while (stackPtr != stack)
|
||||
table[*stackPtr++] = name;
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
inline void init(RegisterName* table, Uint32 nameCount)
|
||||
{
|
||||
for (RegisterName r = RegisterName(0); r < nameCount; r = RegisterName(r + 1))
|
||||
table[r] = r;
|
||||
}
|
||||
|
||||
inline Uint32 compress(RegisterName* name2range, RegisterName* table, Uint32 nameCount, Uint32 tableSize)
|
||||
{
|
||||
RegisterName* liveRange = new RegisterName[tableSize];
|
||||
memset(liveRange, '\0', tableSize * sizeof(RegisterName));
|
||||
|
||||
// Update the lookup table.
|
||||
for (RegisterName r = RegisterName(1); r < tableSize; r = RegisterName(r + 1))
|
||||
findRoot(r, table);
|
||||
|
||||
// Count the liveranges.
|
||||
Uint32 liveRangeCount = 1;
|
||||
for (RegisterName s = RegisterName(1); s < tableSize; s = RegisterName(s + 1))
|
||||
if (table[s] == s)
|
||||
liveRange[s] = RegisterName(liveRangeCount++);
|
||||
|
||||
for (RegisterName t = RegisterName(1); t < nameCount; t = RegisterName(t + 1))
|
||||
name2range[t] = liveRange[table[name2range[t]]];
|
||||
|
||||
return liveRangeCount;
|
||||
}
|
||||
|
||||
inline double doLog10(Uint32 power)
|
||||
{
|
||||
double log = 1.0;
|
||||
while (power--)
|
||||
log *= 10.0;
|
||||
return log;
|
||||
}
|
||||
|
||||
#endif // _REGISTER_ALLOCATOR_TOOLS_H_
|
||||
38
mozilla/ef/Compiler/RegisterAllocator/RegisterAssigner.h
Normal file
38
mozilla/ef/Compiler/RegisterAllocator/RegisterAssigner.h
Normal file
@@ -0,0 +1,38 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef _REGISTER_ASSIGNER_H_
|
||||
#define _REGISTER_ASSIGNER_H_
|
||||
|
||||
#include "Fundamentals.h"
|
||||
#include "VirtualRegister.h"
|
||||
|
||||
class FastBitMatrix;
|
||||
|
||||
class RegisterAssigner
|
||||
{
|
||||
protected:
|
||||
VirtualRegisterManager& vRegManager;
|
||||
|
||||
public:
|
||||
RegisterAssigner(VirtualRegisterManager& vrMan) : vRegManager(vrMan) {}
|
||||
|
||||
virtual bool assignRegisters(FastBitMatrix& interferenceMatrix) = 0;
|
||||
};
|
||||
|
||||
#endif /* _REGISTER_ASSIGNER_H_ */
|
||||
25
mozilla/ef/Compiler/RegisterAllocator/RegisterClass.h
Normal file
25
mozilla/ef/Compiler/RegisterAllocator/RegisterClass.h
Normal file
@@ -0,0 +1,25 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef _REGISTER_CLASS_H_
|
||||
#define _REGISTER_CLASS_H_
|
||||
|
||||
#include "Fundamentals.h"
|
||||
#include "RegisterTypes.h"
|
||||
|
||||
#endif // _REGISTER_CLASS_H_
|
||||
37
mozilla/ef/Compiler/RegisterAllocator/RegisterPressure.h
Normal file
37
mozilla/ef/Compiler/RegisterAllocator/RegisterPressure.h
Normal file
@@ -0,0 +1,37 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef _REGISTER_PRESSURE_H_
|
||||
#define _REGISTER_PRESSURE_H_
|
||||
|
||||
#include "BitSet.h"
|
||||
#include "HashSet.h"
|
||||
|
||||
struct LowRegisterPressure
|
||||
{
|
||||
typedef BitSet Set;
|
||||
static const bool setIsOrdered = true;
|
||||
};
|
||||
|
||||
struct HighRegisterPressure
|
||||
{
|
||||
typedef HashSet Set;
|
||||
static const bool setIsOrdered = false;
|
||||
};
|
||||
|
||||
#endif // _REGISTER_PRESSURE_H_
|
||||
104
mozilla/ef/Compiler/RegisterAllocator/RegisterTypes.h
Normal file
104
mozilla/ef/Compiler/RegisterAllocator/RegisterTypes.h
Normal file
@@ -0,0 +1,104 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef _REGISTER_TYPES_H_
|
||||
#define _REGISTER_TYPES_H_
|
||||
|
||||
#include "Fundamentals.h"
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// RegisterName -
|
||||
//
|
||||
|
||||
enum RegisterName {
|
||||
rnInvalid = 0,
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// RegisterClassKind -
|
||||
//
|
||||
|
||||
enum RegisterClassKind {
|
||||
rckInvalid = 0,
|
||||
rckGeneral,
|
||||
rckStackSlot,
|
||||
|
||||
nRegisterClassKind
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// RegisterID -
|
||||
//
|
||||
|
||||
enum RegisterID {
|
||||
invalidID = 0
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// RegisterKind -
|
||||
//
|
||||
|
||||
enum RegisterKind {
|
||||
rkCallerSave = 0,
|
||||
rkCalleeSave,
|
||||
};
|
||||
|
||||
struct NameLinkedList {
|
||||
RegisterName name;
|
||||
NameLinkedList* next;
|
||||
};
|
||||
|
||||
#ifdef DEBUG
|
||||
|
||||
const registerNameMask = 0x03ffffff;
|
||||
const coloredRegisterMask = 0x04000000;
|
||||
const machineRegisterMask = 0x08000000;
|
||||
const registerClassMask = 0xf0000000;
|
||||
|
||||
const registerNameShift = 0;
|
||||
const coloredRegisterShift = 26;
|
||||
const machineRegisterShift = 27;
|
||||
const registerClassShift = 28;
|
||||
|
||||
#else // DEBUG
|
||||
|
||||
const registerNameMask = 0x0fffffff;
|
||||
const registerClassMask = 0xf0000000;
|
||||
|
||||
const registerNameShift = 0;
|
||||
const registerClassShift = 28;
|
||||
|
||||
#endif // DEBUG
|
||||
|
||||
|
||||
inline RegisterClassKind getClass(RegisterID registerID) {return RegisterClassKind((registerID & registerClassMask) >> registerClassShift);}
|
||||
inline RegisterName getName(RegisterID registerID) {return RegisterName((registerID & registerNameMask) >> registerNameShift);}
|
||||
inline void setClass(RegisterID& registerID, RegisterClassKind classKind) {registerID = RegisterID((registerID & ~registerClassMask) | ((classKind << registerClassShift) & registerClassMask));}
|
||||
inline void setName(RegisterID& registerID, RegisterName name) {assert((name & ~registerNameMask) == 0); registerID = RegisterID((registerID & ~registerNameMask) | ((name << registerNameShift) & registerNameMask));}
|
||||
inline RegisterID buildRegisterID(RegisterName name, RegisterClassKind classKind) {return RegisterID(((classKind << registerClassShift) & registerClassMask) | ((name << registerNameShift) & registerNameMask));}
|
||||
|
||||
#ifdef DEBUG
|
||||
|
||||
inline bool isMachineRegister(RegisterID rid) {return (rid & machineRegisterMask) != 0;}
|
||||
inline void setMachineRegister(RegisterID& rid) {rid = RegisterID(rid | machineRegisterMask);}
|
||||
inline bool isColoredRegister(RegisterID rid) {return (rid & coloredRegisterMask) != 0;}
|
||||
inline void setColoredRegister(RegisterID& rid) {rid = RegisterID(rid | coloredRegisterMask);}
|
||||
|
||||
#endif // DEBUG
|
||||
|
||||
#endif // _REGISTER_TYPES_H_
|
||||
32
mozilla/ef/Compiler/RegisterAllocator/SSATools.cpp
Normal file
32
mozilla/ef/Compiler/RegisterAllocator/SSATools.cpp
Normal file
@@ -0,0 +1,32 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* 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 "Fundamentals.h"
|
||||
#include "SSATools.h"
|
||||
#include "ControlGraph.h"
|
||||
#include "VirtualRegister.h"
|
||||
#include "Liveness.h"
|
||||
|
||||
void replacePhiNodes(ControlGraph& controlGraph, VirtualRegisterManager& vrManager)
|
||||
{
|
||||
if (!controlGraph.hasBackEdges)
|
||||
return;
|
||||
|
||||
Liveness liveness(controlGraph.pool);
|
||||
liveness.buildLivenessAnalysis(controlGraph, vrManager);
|
||||
}
|
||||
29
mozilla/ef/Compiler/RegisterAllocator/SSATools.h
Normal file
29
mozilla/ef/Compiler/RegisterAllocator/SSATools.h
Normal file
@@ -0,0 +1,29 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef _SSA_TOOLS_H_
|
||||
#define _SSA_TOOLS_H_
|
||||
|
||||
#include "Fundamentals.h"
|
||||
|
||||
class ControlGraph;
|
||||
class VirtualRegisterManager;
|
||||
|
||||
extern void replacePhiNodes(ControlGraph& controlGraph, VirtualRegisterManager& vrManager);
|
||||
|
||||
#endif // _SSA_TOOLS_H_
|
||||
37
mozilla/ef/Compiler/RegisterAllocator/SparseSet.cpp
Normal file
37
mozilla/ef/Compiler/RegisterAllocator/SparseSet.cpp
Normal file
@@ -0,0 +1,37 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* 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 "Fundamentals.h"
|
||||
#include "SparseSet.h"
|
||||
#include "BitSet.h"
|
||||
#include "Pool.h"
|
||||
|
||||
#ifdef DEBUG_LOG
|
||||
// Print the set.
|
||||
//
|
||||
void SparseSet::printPretty(LogModuleObject log)
|
||||
{
|
||||
Pool pool;
|
||||
BitSet set(pool, universeSize);
|
||||
|
||||
for (Uint32 i = 0; i < count; i++)
|
||||
set.set(node[i].element);
|
||||
|
||||
set.printPretty(log);
|
||||
}
|
||||
#endif // DEBUG_LOG
|
||||
168
mozilla/ef/Compiler/RegisterAllocator/SparseSet.h
Normal file
168
mozilla/ef/Compiler/RegisterAllocator/SparseSet.h
Normal file
@@ -0,0 +1,168 @@
|
||||
// -*- mode:C++; tab-width:4; truncate-lines:t -*-
|
||||
//
|
||||
// CONFIDENTIAL AND PROPRIETARY SOURCE CODE OF
|
||||
// NETSCAPE COMMUNICATIONS CORPORATION
|
||||
// Copyright © 1996, 1997 Netscape Communications Corporation. All Rights
|
||||
// Reserved. Use of this Source Code is subject to the terms of the
|
||||
// applicable license agreement from Netscape Communications Corporation.
|
||||
// The copyright notice(s) in this Source Code does not indicate actual or
|
||||
// intended publication of this Source Code.
|
||||
//
|
||||
// $Id: SparseSet.h,v 1.1.2.1 1999-03-02 16:12:07 fur%netscape.com Exp $
|
||||
//
|
||||
|
||||
#ifndef _SPARSE_SET_H_
|
||||
#define _SPARSE_SET_H_
|
||||
|
||||
#include "Fundamentals.h"
|
||||
#include "Pool.h"
|
||||
#include "LogModule.h"
|
||||
#include "BitSet.h"
|
||||
|
||||
class SparseSet
|
||||
{
|
||||
private:
|
||||
|
||||
struct Node {
|
||||
Uint32 element;
|
||||
Uint32 stackIndex;
|
||||
};
|
||||
|
||||
Node* node;
|
||||
Uint32 count;
|
||||
Uint32 universeSize;
|
||||
|
||||
private:
|
||||
|
||||
// No copy constructor.
|
||||
SparseSet(const SparseSet&);
|
||||
|
||||
// Check if the given set's universe is of the same size than this universe.
|
||||
void checkUniverseCompatibility(const SparseSet& set) const {assert(set.universeSize == universeSize);}
|
||||
// Check if pos is valid for this set's universe.
|
||||
void checkMember(Int32 pos) const {assert(pos >=0 && Uint32(pos) < universeSize);}
|
||||
|
||||
public:
|
||||
|
||||
SparseSet(Pool& pool, Uint32 universeSize) : universeSize(universeSize) {node = new(pool) Node[universeSize]; clear();}
|
||||
|
||||
// Clear the sparse set.
|
||||
void clear() {count = 0;}
|
||||
// Clear the element at index.
|
||||
inline void clear(Uint32 index);
|
||||
// Set the element at index.
|
||||
inline void set(Uint32 index);
|
||||
// Return true if the element at index is set.
|
||||
inline bool test(Uint32 index) const;
|
||||
// Union with the given sparse set.
|
||||
inline void or(const SparseSet& set);
|
||||
// Intersection with the given sparse set.
|
||||
inline void and(const SparseSet& set);
|
||||
// Difference with the given sparse set.
|
||||
inline void difference(const SparseSet& set);
|
||||
// Copy set.
|
||||
inline SparseSet& operator = (const SparseSet& set);
|
||||
inline SparseSet& operator = (const BitSet& set);
|
||||
// Return true if the sparse sets are identical.
|
||||
friend bool operator == (const SparseSet& set1, const SparseSet& set2);
|
||||
// Return true if the sparse sets are different.
|
||||
friend bool operator != (const SparseSet& set1, const SparseSet& set2);
|
||||
|
||||
// Logical operators.
|
||||
SparseSet& operator |= (const SparseSet& set) {or(set); return *this;}
|
||||
SparseSet& operator &= (const SparseSet& set) {and(set); return *this;}
|
||||
SparseSet& operator -= (const SparseSet& set) {difference(set); return *this;}
|
||||
|
||||
// Iterator to conform with the set API.
|
||||
typedef Int32 iterator;
|
||||
// Return the iterator for the first element of this set.
|
||||
iterator begin() const {return count - 1;}
|
||||
// Return the next iterator.
|
||||
iterator advance(iterator pos) const {return --pos;}
|
||||
// Return true if the iterator is at the end of the set.
|
||||
bool done(iterator pos) const {return pos < 0;}
|
||||
// Return the element for the given iterator;
|
||||
Uint32 get(iterator pos) const {return node[pos].element;}
|
||||
// Return one element of this set.
|
||||
Uint32 getOne() const {assert(count > 0); return node[0].element;}
|
||||
// Return the size of this set.
|
||||
Uint32 getSize() const {return count;}
|
||||
|
||||
#ifdef DEBUG_LOG
|
||||
// Print the set.
|
||||
void printPretty(LogModuleObject log);
|
||||
#endif // DEBUG_LOG
|
||||
};
|
||||
|
||||
inline void SparseSet::clear(Uint32 element)
|
||||
{
|
||||
checkMember(element);
|
||||
Uint32 count = this->count;
|
||||
Node* node = this->node;
|
||||
|
||||
Uint32 stackIndex = node[element].stackIndex;
|
||||
|
||||
if ((stackIndex < count) && (node[stackIndex].element == element)) {
|
||||
Uint32 stackTop = node[count - 1].element;
|
||||
|
||||
node[stackIndex].element = stackTop;
|
||||
node[stackTop].stackIndex = stackIndex;
|
||||
this->count = count - 1;
|
||||
}
|
||||
}
|
||||
|
||||
inline void SparseSet::set(Uint32 element)
|
||||
{
|
||||
checkMember(element);
|
||||
Uint32 count = this->count;
|
||||
Node* node = this->node;
|
||||
|
||||
Uint32 stackIndex = node[element].stackIndex;
|
||||
|
||||
if ((stackIndex >= count) || (node[stackIndex].element != element)) {
|
||||
node[count].element = element;
|
||||
node[element].stackIndex = count;
|
||||
this->count = count + 1;
|
||||
}
|
||||
}
|
||||
|
||||
inline bool SparseSet::test(Uint32 element) const
|
||||
{
|
||||
checkMember(element);
|
||||
Node* node = this->node;
|
||||
|
||||
Uint32 stackIndex = node[element].stackIndex;
|
||||
return ((stackIndex < count) && (node[stackIndex].element == element));
|
||||
}
|
||||
|
||||
inline SparseSet& SparseSet::operator = (const SparseSet& set)
|
||||
{
|
||||
checkUniverseCompatibility(set);
|
||||
Uint32 sourceCount = set.getSize();
|
||||
Node* node = this->node;
|
||||
|
||||
memcpy(node, set.node, sourceCount * sizeof(Node));
|
||||
|
||||
for (Uint32 i = 0; i < sourceCount; i++) {
|
||||
Uint32 element = node[i].element;
|
||||
node[element].stackIndex = i;
|
||||
}
|
||||
|
||||
count = sourceCount;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
inline SparseSet& SparseSet::operator = (const BitSet& set)
|
||||
{
|
||||
// FIX: there's room for optimization here.
|
||||
assert(universeSize == set.getSize());
|
||||
|
||||
clear();
|
||||
for (Int32 i = set.firstOne(); i != -1; i = set.nextOne(i))
|
||||
this->set(i);
|
||||
return *this;
|
||||
}
|
||||
|
||||
#endif // _SPARSE_SET_H_
|
||||
270
mozilla/ef/Compiler/RegisterAllocator/Spilling.cpp
Normal file
270
mozilla/ef/Compiler/RegisterAllocator/Spilling.cpp
Normal file
@@ -0,0 +1,270 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef NEW_LAURENTM_CODE
|
||||
#define INCLUDE_EMITTER
|
||||
#include "CpuInfo.h"
|
||||
#include "Fundamentals.h"
|
||||
#include "ControlNodes.h"
|
||||
#include "Instruction.h"
|
||||
#include "InstructionEmitter.h"
|
||||
#include "Spilling.h"
|
||||
|
||||
|
||||
void Spilling::
|
||||
insertSpillCode(ControlNode** dfsList, Uint32 nNodes)
|
||||
{
|
||||
PRUint32 nVirtualRegisters = vRegManager.count();
|
||||
FastBitSet currentLive(vRegManager.pool, nVirtualRegisters);
|
||||
FastBitSet usedInThisInstruction(vRegManager.pool, nVirtualRegisters);
|
||||
RegisterFifo grNeedLoad(nVirtualRegisters);
|
||||
RegisterFifo fpNeedLoad(nVirtualRegisters);
|
||||
|
||||
for (PRInt32 n = nNodes - 1; n >= 0; n--)
|
||||
{
|
||||
PR_ASSERT(grNeedLoad.empty() & fpNeedLoad.empty());
|
||||
ControlNode& node = *dfsList[n];
|
||||
|
||||
currentLive = node.liveAtEnd;
|
||||
|
||||
PRUint32 nGeneralAlive = 0;
|
||||
PRUint32 nFloatingPointAlive = 0;
|
||||
|
||||
// Get the number of registers alive at the end of this node.
|
||||
for (PRInt32 j = currentLive.firstOne(); j != -1; j = currentLive.nextOne(j))
|
||||
{
|
||||
VirtualRegister& vReg = vRegManager.getVirtualRegister(j);
|
||||
if (vReg.spillInfo.willSpill)
|
||||
{
|
||||
currentLive.clear(j);
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (vReg.getClass())
|
||||
{
|
||||
case vrcInteger:
|
||||
nGeneralAlive++;
|
||||
break;
|
||||
case vrcFloatingPoint:
|
||||
case vrcFixedPoint:
|
||||
nFloatingPointAlive++;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if(node.dfsNum == 8) printf("\n________Begin Node %d________\n", node.dfsNum);
|
||||
|
||||
InstructionList& instructions = node.getInstructions();
|
||||
for (InstructionList::iterator i = instructions.end(); !instructions.done(i); i = instructions.retreat(i))
|
||||
{
|
||||
Instruction& instruction = instructions.get(i);
|
||||
InstructionUse* useBegin = instruction.getInstructionUseBegin();
|
||||
InstructionUse* useEnd = instruction.getInstructionUseEnd();
|
||||
InstructionUse* usePtr;
|
||||
InstructionDefine* defBegin = instruction.getInstructionDefineBegin();
|
||||
InstructionDefine* defEnd = instruction.getInstructionDefineEnd();
|
||||
InstructionDefine* defPtr;
|
||||
|
||||
// if(node.dfsNum == 8) { printf("\n");
|
||||
// instruction.printPretty(stdout);
|
||||
// printf("\n"); }
|
||||
|
||||
// Handle definitions
|
||||
for (defPtr = defBegin; defPtr < defEnd; defPtr++)
|
||||
if (defPtr->isVirtualRegister())
|
||||
{
|
||||
VirtualRegister& vReg = defPtr->getVirtualRegister();
|
||||
currentLive.clear(vReg.getRegisterIndex());
|
||||
switch (vReg.getClass())
|
||||
{
|
||||
case vrcInteger:
|
||||
nGeneralAlive--;
|
||||
break;
|
||||
case vrcFloatingPoint:
|
||||
case vrcFixedPoint:
|
||||
nFloatingPointAlive--;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Check for deaths
|
||||
for (usePtr = useBegin; usePtr < useEnd; usePtr++)
|
||||
if (usePtr->isVirtualRegister())
|
||||
{
|
||||
VirtualRegister& vReg = usePtr->getVirtualRegister();
|
||||
if (!currentLive.test(vReg.getRegisterIndex()))
|
||||
// This is the last use of this register.
|
||||
{
|
||||
currentLive.set(vReg.getRegisterIndex());
|
||||
switch (vReg.getClass())
|
||||
{
|
||||
case vrcInteger:
|
||||
nGeneralAlive++;
|
||||
while (/*(nGeneralAlive > NUMBER_OF_GREGISTERS) &&*/ !grNeedLoad.empty())
|
||||
{
|
||||
PRUint32 toLoad = grNeedLoad.get();
|
||||
currentLive.clear(toLoad);
|
||||
nGeneralAlive--;
|
||||
|
||||
VirtualRegister& nReg = vRegManager.getVirtualRegister(toLoad);
|
||||
Instruction& lastUsingInstruction = *nReg.spillInfo.lastUsingInstruction;
|
||||
emitter.emitLoadAfter(*lastUsingInstruction.getPrimitive(), lastUsingInstruction.getLinks().prev,
|
||||
nReg.getAlias(), *nReg.equivalentRegister[vrcStackSlot]);
|
||||
nReg.releaseSelf();
|
||||
}
|
||||
break;
|
||||
case vrcFloatingPoint:
|
||||
case vrcFixedPoint:
|
||||
nFloatingPointAlive++;
|
||||
while (/*(nFloatingPointAlive > NUMBER_OF_FPREGISTERS) &&*/ !fpNeedLoad.empty())
|
||||
{
|
||||
PRUint32 toLoad = fpNeedLoad.get();
|
||||
currentLive.clear(toLoad);
|
||||
nFloatingPointAlive--;
|
||||
|
||||
VirtualRegister& nReg = vRegManager.getVirtualRegister(toLoad);
|
||||
Instruction& lastUsingInstruction = *nReg.spillInfo.lastUsingInstruction;
|
||||
emitter.emitLoadAfter(*lastUsingInstruction.getPrimitive(), lastUsingInstruction.getLinks().prev,
|
||||
nReg.getAlias(), *nReg.equivalentRegister[vrcStackSlot]);
|
||||
nReg.releaseSelf();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Handle uses
|
||||
for (usePtr = useBegin; usePtr < useEnd; usePtr++)
|
||||
if (usePtr->isVirtualRegister())
|
||||
{
|
||||
VirtualRegister& vReg = usePtr->getVirtualRegister();
|
||||
PRUint32 registerIndex = vReg.getRegisterIndex();
|
||||
|
||||
if (vReg.spillInfo.willSpill) {
|
||||
#if defined(GENERATE_FOR_X86)
|
||||
if (!instruction.switchUseToSpill((usePtr - useBegin), *vReg.equivalentRegister[vrcStackSlot]))
|
||||
#endif
|
||||
{
|
||||
switch (vReg.getClass())
|
||||
{
|
||||
case vrcInteger:
|
||||
if (!grNeedLoad.test(registerIndex))
|
||||
{
|
||||
grNeedLoad.put(registerIndex);
|
||||
VirtualRegister& alias = vRegManager.newVirtualRegister(vrcInteger);
|
||||
if (vReg.isPreColored())
|
||||
alias.preColorRegister(vReg.getPreColor());
|
||||
/* if (vReg.hasSpecialInterference) {
|
||||
alias.specialInterference.sizeTo(NUMBER_OF_REGISTERS);
|
||||
alias.specialInterference = vReg.specialInterference;
|
||||
alias.hasSpecialInterference = true;
|
||||
} */
|
||||
vReg.setAlias(alias);
|
||||
vReg.retainSelf();
|
||||
}
|
||||
break;
|
||||
case vrcFloatingPoint:
|
||||
case vrcFixedPoint:
|
||||
if (!fpNeedLoad.test(registerIndex))
|
||||
{
|
||||
fpNeedLoad.put(registerIndex);
|
||||
VirtualRegister& alias = vRegManager.newVirtualRegister(vReg.getClass());
|
||||
if (vReg.isPreColored())
|
||||
alias.preColorRegister(vReg.getPreColor());
|
||||
/*if (vReg.hasSpecialInterference) {
|
||||
alias.specialInterference.sizeTo(NUMBER_OF_REGISTERS);
|
||||
alias.specialInterference = vReg.specialInterference;
|
||||
alias.hasSpecialInterference = true;
|
||||
} */
|
||||
vReg.setAlias(alias);
|
||||
vReg.retainSelf();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
usePtr->getVirtualRegisterPtr().initialize(vReg.getAlias());
|
||||
usedInThisInstruction.set(registerIndex);
|
||||
vReg.spillInfo.lastUsingInstruction = &instruction;
|
||||
}
|
||||
currentLive.clear(registerIndex);
|
||||
} else { // will not spill
|
||||
currentLive.set(registerIndex);
|
||||
}
|
||||
}
|
||||
|
||||
// Handle definitions
|
||||
for (defPtr = defBegin; defPtr < defEnd; defPtr++)
|
||||
if (defPtr->isVirtualRegister())
|
||||
{
|
||||
VirtualRegister& vReg = defPtr->getVirtualRegister();
|
||||
|
||||
if (vReg.spillInfo.willSpill)
|
||||
#if defined(GENERATE_FOR_X86)
|
||||
if (!instruction.switchDefineToSpill((defPtr - defBegin), *vReg.equivalentRegister[vrcStackSlot]))
|
||||
#endif
|
||||
{
|
||||
if (usedInThisInstruction.test(vReg.getRegisterIndex()))
|
||||
// this virtualRegister was used in this instruction and is also defined. We need to move
|
||||
// this virtual register to its alias first and then save it to memory.
|
||||
{
|
||||
emitter.emitStoreAfter(*instruction.getPrimitive(), &instruction.getLinks(),
|
||||
vReg.getAlias(), *vReg.equivalentRegister[vrcStackSlot]);
|
||||
defPtr->getVirtualRegisterPtr().initialize(vReg.getAlias());
|
||||
}
|
||||
else
|
||||
{
|
||||
emitter.emitStoreAfter(*instruction.getPrimitive(), &instruction.getLinks(),
|
||||
vReg, *vReg.equivalentRegister[vrcStackSlot]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
while (!grNeedLoad.empty())
|
||||
{
|
||||
PRUint32 nl = grNeedLoad.get();
|
||||
VirtualRegister& nlReg = vRegManager.getVirtualRegister(nl);
|
||||
Instruction& lastUse = *nlReg.spillInfo.lastUsingInstruction;
|
||||
|
||||
emitter.emitLoadAfter(*lastUse.getPrimitive(), lastUse.getLinks().prev,
|
||||
nlReg.getAlias(), *nlReg.equivalentRegister[vrcStackSlot]);
|
||||
nlReg.releaseSelf();
|
||||
}
|
||||
while (!fpNeedLoad.empty())
|
||||
{
|
||||
PRUint32 nl = fpNeedLoad.get();
|
||||
VirtualRegister& nlReg = vRegManager.getVirtualRegister(nl);
|
||||
Instruction& lastUse = *nlReg.spillInfo.lastUsingInstruction;
|
||||
|
||||
emitter.emitLoadAfter(*lastUse.getPrimitive(), lastUse.getLinks().prev,
|
||||
nlReg.getAlias(), *nlReg.equivalentRegister[vrcStackSlot]);
|
||||
nlReg.releaseSelf();
|
||||
}
|
||||
|
||||
// if(node.dfsNum == 8) printf("\n________End Node %d________\n", node.dfsNum);
|
||||
|
||||
}
|
||||
}
|
||||
#endif
|
||||
269
mozilla/ef/Compiler/RegisterAllocator/Spilling.h
Normal file
269
mozilla/ef/Compiler/RegisterAllocator/Spilling.h
Normal file
@@ -0,0 +1,269 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef _SPILLING_H_
|
||||
#define _SPILLING_H_
|
||||
|
||||
#include "Fundamentals.h"
|
||||
#include <string.h>
|
||||
#include "RegisterAllocator.h"
|
||||
#include "RegisterAllocatorTools.h"
|
||||
#include "ControlGraph.h"
|
||||
#include "ControlNodes.h"
|
||||
#include "Instruction.h"
|
||||
#include "SparseSet.h"
|
||||
|
||||
template <class RegisterPressure>
|
||||
class Spilling
|
||||
{
|
||||
private:
|
||||
static void insertStoreAfter(Instruction& instruction, RegisterName name);
|
||||
static void insertLoadBefore(Instruction& instruction, RegisterName name);
|
||||
|
||||
public:
|
||||
static void calculateSpillCosts(RegisterAllocator& registerAllocator);
|
||||
static void insertSpillCode(RegisterAllocator& registerAllocator);
|
||||
};
|
||||
|
||||
struct SpillCost
|
||||
{
|
||||
double loads;
|
||||
double stores;
|
||||
double copies;
|
||||
double cost;
|
||||
bool infinite;
|
||||
};
|
||||
|
||||
template <class RegisterPressure>
|
||||
void Spilling<RegisterPressure>::insertSpillCode(RegisterAllocator& registerAllocator)
|
||||
{
|
||||
Uint32 rangeCount = registerAllocator.rangeCount;
|
||||
RegisterName* name2range = registerAllocator.name2range;
|
||||
|
||||
Pool& pool = registerAllocator.pool;
|
||||
SparseSet currentLive(pool, rangeCount);
|
||||
SparseSet needLoad(pool, rangeCount);
|
||||
SparseSet mustSpill(pool, rangeCount);
|
||||
SparseSet& willSpill = *registerAllocator.willSpill;
|
||||
|
||||
ControlGraph& controlGraph = registerAllocator.controlGraph;
|
||||
RegisterPressure::Set* liveOut = registerAllocator.liveness.liveOut;
|
||||
ControlNode** nodes = controlGraph.dfsList;
|
||||
Uint32 nNodes = controlGraph.nNodes;
|
||||
|
||||
for (Uint32 n = 0; n < nNodes; n++) {
|
||||
|
||||
needLoad.clear();
|
||||
currentLive = liveOut[n];
|
||||
mustSpill = currentLive;
|
||||
|
||||
InstructionList& instructions = nodes[n]->getInstructions();
|
||||
for (InstructionList::iterator i = instructions.end(); !instructions.done(i);) {
|
||||
Instruction& instruction = instructions.get(i);
|
||||
i = instructions.retreat(i);
|
||||
|
||||
InstructionUse* useBegin = instruction.getInstructionUseBegin();
|
||||
InstructionUse* useEnd = instruction.getInstructionUseEnd();
|
||||
InstructionUse* usePtr;
|
||||
InstructionDefine* defineBegin = instruction.getInstructionDefineBegin();
|
||||
InstructionDefine* defineEnd = instruction.getInstructionDefineEnd();
|
||||
InstructionDefine* definePtr;
|
||||
|
||||
bool foundLiveDefine = false;
|
||||
for (definePtr = defineBegin; definePtr < defineEnd; definePtr++)
|
||||
if (definePtr->isRegister()) {
|
||||
if (currentLive.test(name2range[definePtr->getRegisterName()])) {
|
||||
foundLiveDefine = true;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
foundLiveDefine = true;
|
||||
break;
|
||||
}
|
||||
if (defineBegin != defineEnd && !foundLiveDefine) {
|
||||
fprintf(stderr, "!!! Removed instruction because it was only defining unused registers !!!\n");
|
||||
instruction.remove();
|
||||
}
|
||||
|
||||
for (definePtr = defineBegin; definePtr < defineEnd; definePtr++)
|
||||
if (definePtr->isRegister()) {
|
||||
RegisterName range = name2range[definePtr->getRegisterName()];
|
||||
#ifdef DEBUG
|
||||
if (needLoad.test(range))
|
||||
if (!mustSpill.test(range) && registerAllocator.spillCost[range].infinite && willSpill.test(range)) {
|
||||
fprintf(stderr, "Tried to spill a register with infinite spill cost\n");
|
||||
abort();
|
||||
}
|
||||
#endif // DEBUG
|
||||
if (willSpill.test(range))
|
||||
insertStoreAfter(instruction, range);
|
||||
|
||||
needLoad.clear(range);
|
||||
}
|
||||
|
||||
if (instruction.getFlags() & ifCopy)
|
||||
for (usePtr = useBegin; usePtr < useEnd; usePtr++)
|
||||
if (usePtr->isRegister()) {
|
||||
RegisterName range = name2range[usePtr->getRegisterName()];
|
||||
if (!currentLive.test(range))
|
||||
for (SparseSet::iterator r = needLoad.begin(); !needLoad.done(r); r = needLoad.advance(r)) {
|
||||
RegisterName load = RegisterName(needLoad.get(r));
|
||||
if (willSpill.test(load))
|
||||
insertLoadBefore(instruction, load);
|
||||
mustSpill.set(load);
|
||||
}
|
||||
needLoad.clear();
|
||||
}
|
||||
|
||||
for (definePtr = defineBegin; definePtr < defineEnd; definePtr++)
|
||||
if (definePtr->isRegister())
|
||||
currentLive.clear(name2range[definePtr->getRegisterName()]);
|
||||
|
||||
|
||||
for (usePtr = useBegin; usePtr < useEnd; usePtr++)
|
||||
if (usePtr->isRegister()) {
|
||||
RegisterName range = name2range[usePtr->getRegisterName()];
|
||||
currentLive.set(range);
|
||||
needLoad.set(range);
|
||||
}
|
||||
}
|
||||
|
||||
for (SparseSet::iterator l = needLoad.begin(); !needLoad.done(l); l = needLoad.advance(l)) {
|
||||
RegisterName load = RegisterName(needLoad.get(l));
|
||||
if (willSpill.test(load))
|
||||
insertLoadBefore(instructions.first(), load);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <class RegisterPressure>
|
||||
void Spilling<RegisterPressure>::insertLoadBefore(Instruction& /*instruction*/, RegisterName name)
|
||||
{
|
||||
fprintf(stdout, "will insert load for range %d\n", name);
|
||||
}
|
||||
|
||||
template <class RegisterPressure>
|
||||
void Spilling<RegisterPressure>::insertStoreAfter(Instruction& /*instruction*/, RegisterName name)
|
||||
{
|
||||
fprintf(stdout, "will insert store for range %d\n", name);
|
||||
}
|
||||
|
||||
template <class RegisterPressure>
|
||||
void Spilling<RegisterPressure>::calculateSpillCosts(RegisterAllocator& registerAllocator)
|
||||
{
|
||||
Uint32 rangeCount = registerAllocator.rangeCount;
|
||||
RegisterName* name2range = registerAllocator.name2range;
|
||||
|
||||
Pool& pool = registerAllocator.pool;
|
||||
SparseSet live(pool, rangeCount);
|
||||
SparseSet needLoad(pool, rangeCount);
|
||||
SparseSet mustSpill(pool, rangeCount);
|
||||
|
||||
SparseSet alreadyStored(pool, rangeCount); // FIX: should get this from previous spilling.
|
||||
|
||||
SpillCost* cost = new SpillCost[rangeCount];
|
||||
memset(cost, '\0', rangeCount * sizeof(SpillCost));
|
||||
|
||||
ControlGraph& controlGraph = registerAllocator.controlGraph;
|
||||
RegisterPressure::Set* liveOut = registerAllocator.liveness.liveOut;
|
||||
ControlNode** nodes = controlGraph.dfsList;
|
||||
Uint32 nNodes = controlGraph.nNodes;
|
||||
|
||||
for (Uint32 n = 0; n < nNodes; n++) {
|
||||
ControlNode& node = *nodes[n];
|
||||
|
||||
double weight = doLog10(node.loopDepth);
|
||||
|
||||
needLoad.clear();
|
||||
live = liveOut[n];
|
||||
mustSpill = live;
|
||||
|
||||
InstructionList& instructions = nodes[n]->getInstructions();
|
||||
for (InstructionList::iterator i = instructions.end(); !instructions.done(i); i = instructions.retreat(i)) {
|
||||
Instruction& instruction = instructions.get(i);
|
||||
|
||||
InstructionUse* useBegin = instruction.getInstructionUseBegin();
|
||||
InstructionUse* useEnd = instruction.getInstructionUseEnd();
|
||||
InstructionUse* usePtr;
|
||||
InstructionDefine* defineBegin = instruction.getInstructionDefineBegin();
|
||||
InstructionDefine* defineEnd = instruction.getInstructionDefineEnd();
|
||||
InstructionDefine* definePtr;
|
||||
|
||||
for (definePtr = defineBegin; definePtr < defineEnd; definePtr++)
|
||||
if (definePtr->isRegister()) {
|
||||
RegisterName range = name2range[definePtr->getRegisterName()];
|
||||
|
||||
if (needLoad.test(range))
|
||||
if (!mustSpill.test(range))
|
||||
cost[range].infinite = true;
|
||||
|
||||
if ((false /* !rematerializable(range) */ || !needLoad.test(range)) && !alreadyStored.test(range))
|
||||
cost[range].stores += weight;
|
||||
|
||||
needLoad.clear(range);
|
||||
}
|
||||
|
||||
if (instruction.getFlags() & ifCopy)
|
||||
for (usePtr = useBegin; usePtr < useEnd; usePtr++)
|
||||
if (usePtr->isRegister())
|
||||
if (!live.test(name2range[usePtr->getRegisterName()])) {
|
||||
for (SparseSet::iterator l = needLoad.begin(); !needLoad.done(l); l = needLoad.advance(l)) {
|
||||
Uint32 range = needLoad.get(l);
|
||||
cost[range].loads += weight;
|
||||
mustSpill.set(range);
|
||||
}
|
||||
needLoad.clear();
|
||||
}
|
||||
|
||||
for (definePtr = defineBegin; definePtr < defineEnd; definePtr++)
|
||||
if (definePtr->isRegister())
|
||||
live.clear(name2range[definePtr->getRegisterName()]);
|
||||
|
||||
for (usePtr = useBegin; usePtr < useEnd; usePtr++)
|
||||
if (usePtr->isRegister()) {
|
||||
RegisterName range = name2range[usePtr->getRegisterName()];
|
||||
|
||||
live.set(range);
|
||||
needLoad.set(range);
|
||||
}
|
||||
|
||||
if (instruction.getFlags() & ifCopy) {
|
||||
assert(useBegin != useEnd && useBegin[0].isRegister());
|
||||
assert(defineBegin != defineEnd && defineBegin[0].isRegister());
|
||||
|
||||
RegisterName source = name2range[useBegin[0].getRegisterName()];
|
||||
RegisterName destination = name2range[defineBegin[0].getRegisterName()];
|
||||
|
||||
cost[source].copies += weight;
|
||||
cost[destination].copies += weight;
|
||||
}
|
||||
}
|
||||
|
||||
for (SparseSet::iterator s = needLoad.begin(); !needLoad.done(s); s = needLoad.advance(s))
|
||||
cost[needLoad.get(s)].loads += weight;
|
||||
}
|
||||
|
||||
for (Uint32 r = 0; r < rangeCount; r++) {
|
||||
SpillCost& c = cost[r];
|
||||
c.cost = 2 * (c.loads + c.stores) - c.copies;
|
||||
}
|
||||
|
||||
registerAllocator.spillCost = cost;
|
||||
}
|
||||
|
||||
#endif // _SPILLING_H_
|
||||
239
mozilla/ef/Compiler/RegisterAllocator/Splits.h
Normal file
239
mozilla/ef/Compiler/RegisterAllocator/Splits.h
Normal file
@@ -0,0 +1,239 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef _SPLITS_H_
|
||||
#define _SPLITS_H_
|
||||
|
||||
#include "Fundamentals.h"
|
||||
#include <string.h>
|
||||
#include "Pool.h"
|
||||
#include "ControlGraph.h"
|
||||
#include "ControlNodes.h"
|
||||
#include "Instruction.h"
|
||||
#include "RegisterAllocator.h"
|
||||
#include "RegisterAllocatorTools.h"
|
||||
|
||||
UT_EXTERN_LOG_MODULE(RegAlloc);
|
||||
|
||||
template <class RegisterPressure>
|
||||
struct Splits
|
||||
{
|
||||
static void calculateSplitCosts(RegisterAllocator& registerAllocator);
|
||||
static bool findSplit(RegisterAllocator& registerAllocator, RegisterName* color, RegisterName range);
|
||||
static void insertSplitCode(RegisterAllocator& registerAllocator);
|
||||
};
|
||||
|
||||
struct SplitCost
|
||||
{
|
||||
double loads;
|
||||
double stores;
|
||||
};
|
||||
|
||||
template <class RegisterPressure>
|
||||
void Splits<RegisterPressure>::insertSplitCode(RegisterAllocator& /*registerAllocator*/)
|
||||
{
|
||||
// FIX
|
||||
}
|
||||
|
||||
template <class RegisterPressure>
|
||||
bool Splits<RegisterPressure>::findSplit(RegisterAllocator& registerAllocator, RegisterName* color, RegisterName range)
|
||||
{
|
||||
Pool& pool = registerAllocator.pool;
|
||||
NameLinkedList** neighborsWithColor = new(pool) NameLinkedList*[6]; // FIX
|
||||
memset(neighborsWithColor, '\0', 6 * sizeof(NameLinkedList*));
|
||||
|
||||
InterferenceGraph<RegisterPressure>& iGraph = registerAllocator.iGraph;
|
||||
|
||||
for (InterferenceVector* vector = iGraph.getInterferenceVector(range); vector != NULL; vector = vector->next)
|
||||
for (Int32 i = vector->count - 1; i >=0; --i) {
|
||||
RegisterName neighbor = vector->neighbors[i];
|
||||
RegisterName c = color[neighbor];
|
||||
|
||||
if (c < 6) { // FIX
|
||||
NameLinkedList* node = new(pool) NameLinkedList();
|
||||
node->name = neighbor;
|
||||
node->next = neighborsWithColor[c];
|
||||
neighborsWithColor[c] = node;
|
||||
}
|
||||
}
|
||||
|
||||
bool splitAroundName = true;
|
||||
|
||||
LiveRangeGraph<RegisterPressure>& lGraph = registerAllocator.lGraph;
|
||||
RegisterName bestColor = RegisterName(6); // FIX
|
||||
double bestCost = registerAllocator.spillCost[range].cost;
|
||||
SplitCost* splitCost = registerAllocator.splitCost;
|
||||
|
||||
for (RegisterName i = RegisterName(0); i < 6; i = RegisterName(i + 1)) { // FIX
|
||||
|
||||
double splitAroundNameCost = 0.0;
|
||||
bool canSplitAroundName = true;
|
||||
|
||||
SplitCost& sCost = splitCost[range];
|
||||
double addedCost = 2.0 * (sCost.stores + sCost.loads);
|
||||
|
||||
for (NameLinkedList* node = neighborsWithColor[i]; node != NULL; node = node->next) {
|
||||
RegisterName neighbor = node->name;
|
||||
if (lGraph.haveEdge(neighbor, range)) {
|
||||
canSplitAroundName = false;
|
||||
break;
|
||||
} else
|
||||
splitAroundNameCost += addedCost;
|
||||
}
|
||||
if (canSplitAroundName && splitAroundNameCost < bestCost) {
|
||||
bestCost = splitAroundNameCost;
|
||||
bestColor = i;
|
||||
splitAroundName = true;
|
||||
}
|
||||
|
||||
double splitAroundColorCost = 0.0;
|
||||
bool canSplitAroundColor = true;
|
||||
|
||||
for (NameLinkedList* node = neighborsWithColor[i]; node != NULL; node = node->next) {
|
||||
RegisterName neighbor = node->name;
|
||||
if (lGraph.haveEdge(range, neighbor)) {
|
||||
canSplitAroundColor = false;
|
||||
break;
|
||||
} else {
|
||||
SplitCost& sCost = splitCost[neighbor];
|
||||
double addedCost = 2.0 * (sCost.stores + sCost.loads);
|
||||
splitAroundColorCost += addedCost;
|
||||
}
|
||||
}
|
||||
if (canSplitAroundColor && splitAroundColorCost < bestCost) {
|
||||
bestCost = splitAroundColorCost;
|
||||
bestColor = i;
|
||||
splitAroundName = false;
|
||||
}
|
||||
}
|
||||
if (bestColor < RegisterName(6)) {
|
||||
color[range] = bestColor;
|
||||
registerAllocator.splitFound = true;
|
||||
|
||||
NameLinkedList** splitAround = registerAllocator.splitAround;
|
||||
|
||||
if (splitAroundName)
|
||||
for (NameLinkedList* node = neighborsWithColor[bestColor]; node != NULL; node = node->next) {
|
||||
NameLinkedList* newNode = new(pool) NameLinkedList();
|
||||
newNode->name = node->name;
|
||||
newNode->next = splitAround[range];
|
||||
splitAround[range] = newNode;
|
||||
}
|
||||
else
|
||||
for (NameLinkedList* node = neighborsWithColor[bestColor]; node != NULL; node = node->next) {
|
||||
NameLinkedList* newNode = new(pool) NameLinkedList();
|
||||
RegisterName neighbor = node->name;
|
||||
newNode->name = range;
|
||||
newNode->next = splitAround[neighbor];
|
||||
splitAround[neighbor] = newNode;
|
||||
}
|
||||
|
||||
trespass("Found a split");
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
template <class RegisterPressure>
|
||||
void Splits<RegisterPressure>::calculateSplitCosts(RegisterAllocator& registerAllocator)
|
||||
{
|
||||
Pool& pool = registerAllocator.pool;
|
||||
Uint32 rangeCount = registerAllocator.rangeCount;
|
||||
RegisterName* name2range = registerAllocator.name2range;
|
||||
|
||||
SplitCost* splitCost = new(pool) SplitCost[rangeCount];
|
||||
memset(splitCost, '\0', rangeCount * sizeof(SplitCost));
|
||||
|
||||
SparseSet live(pool, rangeCount);
|
||||
RegisterPressure::Set* liveIn = registerAllocator.liveness.liveIn;
|
||||
RegisterPressure::Set* liveOut = registerAllocator.liveness.liveOut;
|
||||
|
||||
ControlGraph& controlGraph = registerAllocator.controlGraph;
|
||||
ControlNode** nodes = controlGraph.dfsList;
|
||||
Uint32 nNodes = controlGraph.nNodes;
|
||||
|
||||
for (Uint32 n = 0; n < nNodes; n++) {
|
||||
ControlNode& node = *nodes[n];
|
||||
double weight = doLog10(node.loopDepth);
|
||||
|
||||
live = liveOut[n];
|
||||
|
||||
ControlEdge* successorsEnd = node.getSuccessorsEnd();
|
||||
for (ControlEdge* successorsPtr = node.getSuccessorsBegin(); successorsPtr < successorsEnd; successorsPtr++) {
|
||||
ControlNode& successor = successorsPtr->getTarget();
|
||||
|
||||
if (successor.getControlKind() != ckEnd) {
|
||||
RegisterPressure::Set& successorLiveIn = liveIn[successor.dfsNum];
|
||||
|
||||
for (SparseSet::iterator i = live.begin(); !live.done(i); i = live.advance(i)) {
|
||||
RegisterName name = RegisterName(live.get(i));
|
||||
if (!successorLiveIn.test(name))
|
||||
splitCost[name].loads += doLog10(successor.loopDepth);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
InstructionList& instructions = node.getInstructions();
|
||||
for (InstructionList::iterator i = instructions.end(); !instructions.done(i); i = instructions.retreat(i)) {
|
||||
Instruction& instruction = instructions.get(i);
|
||||
|
||||
InstructionUse* useBegin = instruction.getInstructionUseBegin();
|
||||
InstructionUse* useEnd = instruction.getInstructionUseEnd();
|
||||
InstructionUse* usePtr;
|
||||
InstructionDefine* defineBegin = instruction.getInstructionDefineBegin();
|
||||
InstructionDefine* defineEnd = instruction.getInstructionDefineEnd();
|
||||
InstructionDefine* definePtr;
|
||||
|
||||
for (definePtr = defineBegin; definePtr < defineEnd; definePtr++)
|
||||
if (definePtr->isRegister())
|
||||
splitCost[name2range[definePtr->getRegisterName()]].stores += weight;
|
||||
|
||||
for (usePtr = useBegin; usePtr < useEnd; usePtr++)
|
||||
if (usePtr->isRegister()) {
|
||||
RegisterName range = name2range[usePtr->getRegisterName()];
|
||||
if (!live.test(range)) {
|
||||
if (&instruction != &instructions.last())
|
||||
splitCost[range].loads += weight;
|
||||
else {
|
||||
ControlEdge* successorsEnd = node.getSuccessorsEnd();
|
||||
for (ControlEdge* successorsPtr = node.getSuccessorsBegin(); successorsPtr < successorsEnd; successorsPtr++)
|
||||
splitCost[range].loads += doLog10(successorsPtr->getTarget().loopDepth);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (definePtr = defineBegin; definePtr < defineEnd; definePtr++)
|
||||
if (definePtr->isRegister())
|
||||
live.clear(name2range[definePtr->getRegisterName()]);
|
||||
|
||||
for (usePtr = useBegin; usePtr < useEnd; usePtr++)
|
||||
if (usePtr->isRegister())
|
||||
live.set(name2range[usePtr->getRegisterName()]);
|
||||
}
|
||||
}
|
||||
|
||||
NameLinkedList** splitAround = new(pool) NameLinkedList*[rangeCount];
|
||||
memset(splitAround, '\0', rangeCount * sizeof(NameLinkedList*));
|
||||
registerAllocator.splitAround = splitAround;
|
||||
|
||||
registerAllocator.splitCost = splitCost;
|
||||
registerAllocator.splitFound = false;
|
||||
}
|
||||
|
||||
#endif // _SPLITS_H_
|
||||
186
mozilla/ef/Compiler/RegisterAllocator/Timer.cpp
Normal file
186
mozilla/ef/Compiler/RegisterAllocator/Timer.cpp
Normal file
@@ -0,0 +1,186 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* 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 "Fundamentals.h"
|
||||
#include "HashTable.h"
|
||||
#include "Timer.h"
|
||||
#include "Pool.h"
|
||||
|
||||
static Pool pool; // Pool for the Timer class.
|
||||
static HashTable<TimerEntry*> timerEntries(pool); // Timers hashtable.
|
||||
|
||||
const nTimersInABlock = 128; // Number of timers in a block.
|
||||
static PRTime *timers = new(pool) PRTime[nTimersInABlock]; // A block of timers.
|
||||
static Uint8 nextTimer = 0; // nextAvailableTimer.
|
||||
|
||||
//
|
||||
// Calibrate the call to PR_Now().
|
||||
//
|
||||
static PRTime calibrate()
|
||||
{
|
||||
PRTime t = PR_Now();
|
||||
PRTime& a = *new(pool) PRTime();
|
||||
|
||||
// Call 10 times the PR_Now() function.
|
||||
a = PR_Now(); a = PR_Now(); a = PR_Now(); a = PR_Now(); a = PR_Now(); a = PR_Now();
|
||||
a = PR_Now(); a = PR_Now(); a = PR_Now(); a = PR_Now(); a = PR_Now(); a = PR_Now();
|
||||
t = (PR_Now() - t + 9) / 10;
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
static PRTime adjust = calibrate();
|
||||
|
||||
//
|
||||
// Return the named timer..
|
||||
//
|
||||
TimerEntry& Timer::getTimerEntry(const char* name)
|
||||
{
|
||||
if (!timerEntries.exists(name)) {
|
||||
TimerEntry* newEntry = new(pool) TimerEntry();
|
||||
newEntry->accumulator = 0;
|
||||
newEntry->running = false;
|
||||
timerEntries.add(name, newEntry);
|
||||
}
|
||||
|
||||
return *timerEntries[name];
|
||||
}
|
||||
|
||||
//
|
||||
// Return a reference to a new timer.
|
||||
//
|
||||
PRTime& Timer::getNewTimer()
|
||||
{
|
||||
if (nextTimer >= nTimersInABlock) {
|
||||
timers = new(pool) PRTime[nTimersInABlock];
|
||||
nextTimer = 0;
|
||||
}
|
||||
return timers[nextTimer++];
|
||||
}
|
||||
|
||||
static Uint32 timersAreFrozen = 0;
|
||||
|
||||
//
|
||||
// Start the named timer.
|
||||
//
|
||||
void Timer::start(const char* name)
|
||||
{
|
||||
if (timersAreFrozen)
|
||||
return;
|
||||
|
||||
freezeTimers();
|
||||
|
||||
TimerEntry& timer = getTimerEntry(name);
|
||||
PR_ASSERT(!timer.running);
|
||||
|
||||
timer.accumulator = 0;
|
||||
timer.running = true;
|
||||
timer.done = false;
|
||||
|
||||
unfreezeTimers();
|
||||
}
|
||||
|
||||
//
|
||||
// Stop the named timer.
|
||||
//
|
||||
void Timer::stop(const char* name)
|
||||
{
|
||||
if (timersAreFrozen)
|
||||
return;
|
||||
|
||||
freezeTimers();
|
||||
|
||||
TimerEntry& timer = getTimerEntry(name);
|
||||
PR_ASSERT(timer.running);
|
||||
timer.running = false;
|
||||
timer.done = true;
|
||||
|
||||
unfreezeTimers();
|
||||
}
|
||||
|
||||
//
|
||||
// Freeze all the running timers.
|
||||
//
|
||||
void Timer::freezeTimers()
|
||||
{
|
||||
PRTime when = PR_Now() - adjust;
|
||||
|
||||
if (timersAreFrozen == 0) {
|
||||
Vector<TimerEntry*> entries = timerEntries;
|
||||
Uint32 count = entries.size();
|
||||
|
||||
for (Uint32 i = 0; i < count; i++) {
|
||||
TimerEntry& entry = *entries[i];
|
||||
if (entry.running) {
|
||||
entry.accumulator += (when - *entry.startTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
timersAreFrozen++;
|
||||
}
|
||||
|
||||
//
|
||||
// Unfreeze all the running timers.
|
||||
//
|
||||
void Timer::unfreezeTimers()
|
||||
{
|
||||
PR_ASSERT(timersAreFrozen != 0);
|
||||
timersAreFrozen--;
|
||||
|
||||
if (timersAreFrozen == 0) {
|
||||
Vector<TimerEntry *> entries = timerEntries;
|
||||
Uint32 count = entries.size();
|
||||
|
||||
PRTime& newStart = getNewTimer();
|
||||
|
||||
for (Uint32 i = 0; i < count; i++) {
|
||||
TimerEntry& entry = *entries[i];
|
||||
if (entry.running) {
|
||||
entry.startTime = &newStart;
|
||||
}
|
||||
}
|
||||
|
||||
newStart = PR_Now();
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Print the named timer in the file f.
|
||||
//
|
||||
void Timer::print(FILE* f, const char *name)
|
||||
{
|
||||
if (timersAreFrozen)
|
||||
return;
|
||||
|
||||
freezeTimers();
|
||||
|
||||
TimerEntry& timer = getTimerEntry(name);
|
||||
|
||||
PR_ASSERT(timer.done);
|
||||
PRTime elapsed = timer.accumulator;
|
||||
|
||||
if (elapsed >> 32) {
|
||||
fprintf(f, "[timer %s out of range]\n", name);
|
||||
} else {
|
||||
fprintf(f, "[%dus in %s]\n", Uint32(elapsed), name);
|
||||
}
|
||||
fflush(f);
|
||||
|
||||
unfreezeTimers();
|
||||
}
|
||||
|
||||
80
mozilla/ef/Compiler/RegisterAllocator/Timer.h
Normal file
80
mozilla/ef/Compiler/RegisterAllocator/Timer.h
Normal file
@@ -0,0 +1,80 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef _TIMER_H_
|
||||
#define _TIMER_H_
|
||||
|
||||
#include "Fundamentals.h"
|
||||
#include "HashTable.h"
|
||||
#include "prtime.h"
|
||||
|
||||
//
|
||||
// Naming convention:
|
||||
// As the class Timer contains only static methods, the timer's name should start with the
|
||||
// module name. Otherwise starting 2 timers with the same name will assert.
|
||||
//
|
||||
|
||||
#ifndef NO_TIMER
|
||||
|
||||
struct TimerEntry
|
||||
{
|
||||
PRTime *startTime; // Current time when we start the timer.
|
||||
PRTime accumulator; // Time spent in this timer.
|
||||
bool running; // True if the timer is running.
|
||||
bool done; // True if the timer was running and was stopped.
|
||||
};
|
||||
|
||||
class Timer
|
||||
{
|
||||
private:
|
||||
|
||||
// Return the named timer.
|
||||
static TimerEntry& getTimerEntry(const char* name);
|
||||
// Return a reference to a new Timer.
|
||||
static PRTime& getNewTimer();
|
||||
|
||||
public:
|
||||
|
||||
// Start the timer.
|
||||
static void start(const char* name);
|
||||
// Stop the timer.
|
||||
static void stop(const char* name);
|
||||
// Freeze all the running timers.
|
||||
static void freezeTimers();
|
||||
// Unfreeze all the running timers.
|
||||
static void unfreezeTimers();
|
||||
// Print the timer.
|
||||
static void print(FILE* f, const char *name);
|
||||
};
|
||||
|
||||
inline void startTimer(const char* name) {Timer::start(name);}
|
||||
inline void stopTimer(const char* name) {Timer::stop(name); Timer::print(stdout, name);}
|
||||
#define START_TIMER_SAFE Timer::freezeTimers();
|
||||
#define END_TIMER_SAFE Timer::unfreezeTimers();
|
||||
#define TIMER_SAFE(x) START_TIMER_SAFE x; END_TIMER_SAFE
|
||||
|
||||
#else /* NO_TIMER */
|
||||
|
||||
inline void startTimer(const char* /*name*/) {}
|
||||
inline void stopTimer(const char* /*name*/) {}
|
||||
#define START_TIMER_SAFE
|
||||
#define END_TIMER_SAFE
|
||||
#define TIMER_SAFE(x) x;
|
||||
|
||||
#endif /* NO_TIMER */
|
||||
#endif /* _TIMER_H_ */
|
||||
40
mozilla/ef/Compiler/RegisterAllocator/VirtualRegister.cpp
Normal file
40
mozilla/ef/Compiler/RegisterAllocator/VirtualRegister.cpp
Normal file
@@ -0,0 +1,40 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* 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 "Fundamentals.h"
|
||||
#include "VirtualRegister.h"
|
||||
#include "Instruction.h"
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// VirtualRegister -
|
||||
|
||||
#ifdef MANUAL_TEMPLATES
|
||||
template class IndexedPool<VirtualRegister>;
|
||||
#endif
|
||||
|
||||
// Set the defining instruction.
|
||||
//
|
||||
void VirtualRegister::setDefiningInstruction(Instruction& instruction)
|
||||
{
|
||||
if (definingInstruction != NULL) {
|
||||
if ((instruction.getFlags() & ifCopy) && (definingInstruction->getFlags() & ifPhiNode))
|
||||
return;
|
||||
}
|
||||
definingInstruction = &instruction;
|
||||
}
|
||||
|
||||
116
mozilla/ef/Compiler/RegisterAllocator/VirtualRegister.h
Normal file
116
mozilla/ef/Compiler/RegisterAllocator/VirtualRegister.h
Normal file
@@ -0,0 +1,116 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef _VIRTUAL_REGISTER_H_
|
||||
#define _VIRTUAL_REGISTER_H_
|
||||
|
||||
#include "Fundamentals.h"
|
||||
#include "IndexedPool.h"
|
||||
#include <string.h>
|
||||
|
||||
#include "RegisterTypes.h"
|
||||
#include "RegisterClass.h"
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// VirtualRegister - 24b
|
||||
|
||||
class Instruction;
|
||||
|
||||
class VirtualRegister : public IndexedObject<VirtualRegister>
|
||||
{
|
||||
public:
|
||||
|
||||
Instruction* definingInstruction; // Instruction defining this VR.
|
||||
|
||||
// Initialize a VR of the given classKind.
|
||||
VirtualRegister(RegisterClassKind /*classKind*/) : definingInstruction(NULL) {}
|
||||
|
||||
// Return the defining instruction for this VR.
|
||||
Instruction* getDefiningInstruction() const {return definingInstruction;}
|
||||
// Set the defining instruction.
|
||||
void setDefiningInstruction(Instruction& insn);
|
||||
};
|
||||
|
||||
// Return true if the VirtualRegisters are equals. The only way 2 VRs can be equal is if
|
||||
// they have the same index. If they have the same index then they are at the same
|
||||
// address in the indexed pool.
|
||||
//
|
||||
inline bool operator == (const VirtualRegister& regA, const VirtualRegister& regB) {return ®A == ®B;}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// VirtualRegisterManager -
|
||||
|
||||
struct PreColoredRegister
|
||||
{
|
||||
RegisterID id;
|
||||
RegisterName color;
|
||||
};
|
||||
|
||||
class VirtualRegisterManager
|
||||
{
|
||||
private:
|
||||
|
||||
IndexedPool<VirtualRegister> registerPool;
|
||||
PreColoredRegister machineRegister[6];
|
||||
|
||||
public:
|
||||
VirtualRegisterManager()
|
||||
{
|
||||
for (Uint32 i = 0; i < 6; i++)
|
||||
machineRegister[i].id = invalidID;
|
||||
}
|
||||
|
||||
// Return the VirtualRegister at the given index.
|
||||
VirtualRegister& getVirtualRegister(RegisterName name) const {return registerPool.get(name);}
|
||||
|
||||
// Return a new VirtualRegister.
|
||||
RegisterID newVirtualRegister(RegisterClassKind classKind)
|
||||
{
|
||||
VirtualRegister& vReg = *new(registerPool) VirtualRegister(classKind);
|
||||
RegisterID rid;
|
||||
|
||||
setName(rid, RegisterName(vReg.getIndex()));
|
||||
setClass(rid, classKind);
|
||||
return rid;
|
||||
}
|
||||
|
||||
RegisterID newMachineRegister(RegisterName name, RegisterClassKind classKind)
|
||||
{
|
||||
RegisterID rid = machineRegister[name].id;
|
||||
|
||||
if (rid == invalidID) {
|
||||
rid = newVirtualRegister(classKind);
|
||||
DEBUG_ONLY(setMachineRegister(rid));
|
||||
machineRegister[name].id = rid;
|
||||
machineRegister[name].color = name;
|
||||
}
|
||||
|
||||
return rid;
|
||||
}
|
||||
|
||||
PreColoredRegister* getMachineRegistersBegin() const {return (PreColoredRegister*) machineRegister;} // FIX
|
||||
PreColoredRegister* getMachineRegistersEnd() const {return (PreColoredRegister*) &machineRegister[6];} // FIX
|
||||
|
||||
// Return the VirtualRegister universe size.
|
||||
Uint32 getSize() {return registerPool.getSize();}
|
||||
|
||||
void setSize(Uint32 size) {registerPool.setSize(size);}
|
||||
};
|
||||
|
||||
#endif // _VIRTUAL_REGISTER_H_
|
||||
@@ -1,152 +0,0 @@
|
||||
#! gmake
|
||||
|
||||
#
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla 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/MPL/
|
||||
#
|
||||
# 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 the Netscape Portable Runtime (NSPR).
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Netscape Communications Corporation.
|
||||
# Portions created by the Initial Developer are Copyright (C) 1998-2000
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
|
||||
MOD_DEPTH = .
|
||||
topsrcdir = @top_srcdir@
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
include $(MOD_DEPTH)/config/autoconf.mk
|
||||
|
||||
MAKE := $(patsubst -j%,,$(MAKE)) -j1
|
||||
|
||||
DIRS = config pr lib
|
||||
|
||||
ifdef MOZILLA_CLIENT
|
||||
# Make nsinstall use absolute symlinks by default for Mozilla OSX builds
|
||||
# http://bugzilla.mozilla.org/show_bug.cgi?id=193164
|
||||
ifeq ($(OS_ARCH),Darwin)
|
||||
ifndef NSDISTMODE
|
||||
NSDISTMODE=absolute_symlink
|
||||
export NSDISTMODE
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
DIST_GARBAGE = config.cache config.log config.status
|
||||
|
||||
all:: config.status export
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
config.status:: configure
|
||||
ifeq ($(OS_ARCH),WINNT)
|
||||
sh $(srcdir)/configure --no-create --no-recursion
|
||||
else
|
||||
./config.status --recheck && ./config.status
|
||||
endif
|
||||
|
||||
#
|
||||
# The -ll option of zip converts CR LF to LF.
|
||||
#
|
||||
ifeq ($(OS_ARCH),WINNT)
|
||||
ZIP_ASCII_OPT = -ll
|
||||
endif
|
||||
|
||||
# Delete config/autoconf.mk last because it is included by every makefile.
|
||||
distclean::
|
||||
@echo "cd pr/tests; $(MAKE) $@"
|
||||
@$(MAKE) -C pr/tests $@
|
||||
rm -f config/autoconf.mk
|
||||
rm -f `cat unallmakefiles` unallmakefiles
|
||||
|
||||
release::
|
||||
echo $(BUILD_NUMBER) > $(RELEASE_DIR)/$(BUILD_NUMBER)/version.df
|
||||
@if test -f imports.df; then \
|
||||
echo "cp -f imports.df $(RELEASE_DIR)/$(BUILD_NUMBER)/imports.df"; \
|
||||
cp -f imports.df $(RELEASE_DIR)/$(BUILD_NUMBER)/imports.df; \
|
||||
else \
|
||||
echo "echo > $(RELEASE_DIR)/$(BUILD_NUMBER)/imports.df"; \
|
||||
echo > $(RELEASE_DIR)/$(BUILD_NUMBER)/imports.df; \
|
||||
fi
|
||||
cd $(RELEASE_DIR)/$(BUILD_NUMBER)/$(OBJDIR_NAME); \
|
||||
rm -rf META-INF; mkdir META-INF; cd META-INF; \
|
||||
echo "Manifest-Version: 1.0" > MANIFEST.MF; \
|
||||
echo "" >> MANIFEST.MF; \
|
||||
cd ..; rm -f mdbinary.jar; zip -r mdbinary.jar META-INF bin lib; \
|
||||
rm -rf META-INF; \
|
||||
cd include; \
|
||||
rm -rf META-INF; mkdir META-INF; cd META-INF; \
|
||||
echo "Manifest-Version: 1.0" > MANIFEST.MF; \
|
||||
echo "" >> MANIFEST.MF; \
|
||||
cd ..; rm -f mdheader.jar; zip $(ZIP_ASCII_OPT) -r mdheader.jar *; \
|
||||
rm -rf META-INF
|
||||
ifeq ($(OS_ARCH),WINNT)
|
||||
@if test ! -d $(MDIST)/$(MOD_NAME)/$(BUILD_NUMBER); then \
|
||||
rm -rf $(MDIST)/$(MOD_NAME)/$(BUILD_NUMBER); \
|
||||
echo "making directory $(MDIST)/$(MOD_NAME)/$(BUILD_NUMBER)"; \
|
||||
$(topsrcdir)/config/prmkdir.bat $(MDIST_DOS)\\$(MOD_NAME)\\$(BUILD_NUMBER); \
|
||||
fi
|
||||
@if test ! -d $(MDIST)/$(MOD_NAME)/$(BUILD_NUMBER)/$(RELEASE_OBJDIR_NAME); then \
|
||||
rm -rf $(MDIST)/$(MOD_NAME)/$(BUILD_NUMBER)/$(RELEASE_OBJDIR_NAME); \
|
||||
echo "making directory $(MDIST)/$(MOD_NAME)/$(BUILD_NUMBER)/$(RELEASE_OBJDIR_NAME)"; \
|
||||
$(topsrcdir)/config/prmkdir.bat $(MDIST_DOS)\\$(MOD_NAME)\\$(BUILD_NUMBER)\\$(RELEASE_OBJDIR_NAME); \
|
||||
fi
|
||||
else
|
||||
@if test ! -d $(MDIST)/$(MOD_NAME)/$(BUILD_NUMBER); then \
|
||||
rm -rf $(MDIST)/$(MOD_NAME)/$(BUILD_NUMBER); \
|
||||
echo "making directory $(MDIST)/$(MOD_NAME)/$(BUILD_NUMBER)"; \
|
||||
$(NSINSTALL) -D $(MDIST)/$(MOD_NAME)/$(BUILD_NUMBER); \
|
||||
chmod 775 $(MDIST)/$(MOD_NAME)/$(BUILD_NUMBER); \
|
||||
fi
|
||||
@if test ! -d $(MDIST)/$(MOD_NAME)/$(BUILD_NUMBER)/$(RELEASE_OBJDIR_NAME); then \
|
||||
rm -rf $(MDIST)/$(MOD_NAME)/$(BUILD_NUMBER)/$(RELEASE_OBJDIR_NAME); \
|
||||
echo "making directory $(MDIST)/$(MOD_NAME)/$(BUILD_NUMBER)/$(RELEASE_OBJDIR_NAME)"; \
|
||||
$(NSINSTALL) -D $(MDIST)/$(MOD_NAME)/$(BUILD_NUMBER)/$(RELEASE_OBJDIR_NAME); \
|
||||
chmod 775 $(MDIST)/$(MOD_NAME)/$(BUILD_NUMBER)/$(RELEASE_OBJDIR_NAME); \
|
||||
fi
|
||||
endif
|
||||
cd $(RELEASE_DIR)/$(BUILD_NUMBER); \
|
||||
cp -f version.df imports.df $(MDIST)/$(MOD_NAME)/$(BUILD_NUMBER); \
|
||||
chmod 664 $(MDIST)/$(MOD_NAME)/$(BUILD_NUMBER)/version.df; \
|
||||
chmod 664 $(MDIST)/$(MOD_NAME)/$(BUILD_NUMBER)/imports.df; \
|
||||
cd $(OBJDIR_NAME); \
|
||||
cp -f mdbinary.jar $(MDIST)/$(MOD_NAME)/$(BUILD_NUMBER)/$(RELEASE_OBJDIR_NAME); \
|
||||
chmod 664 $(MDIST)/$(MOD_NAME)/$(BUILD_NUMBER)/$(RELEASE_OBJDIR_NAME)/mdbinary.jar; \
|
||||
cd include; \
|
||||
cp -f mdheader.jar $(MDIST)/$(MOD_NAME)/$(BUILD_NUMBER)/$(RELEASE_OBJDIR_NAME); \
|
||||
chmod 664 $(MDIST)/$(MOD_NAME)/$(BUILD_NUMBER)/$(RELEASE_OBJDIR_NAME)/mdheader.jar
|
||||
|
||||
package:
|
||||
@echo "cd pkg; $(MAKE) publish"
|
||||
$(MAKE) -C pkg publish
|
||||
|
||||
depend:
|
||||
@echo "NSPR20 has no dependencies. Skipped."
|
||||
@@ -1,75 +0,0 @@
|
||||
#!/bin/perl
|
||||
#
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla 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/MPL/
|
||||
#
|
||||
# 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 the Netscape Portable Runtime (NSPR).
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Netscape Communications Corporation.
|
||||
# Portions created by the Initial Developer are Copyright (C) 1998-2001
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
# -----------------------------------------------------------------
|
||||
#
|
||||
# explode.pl -- Unpack .jar files into bin, lib, include directories
|
||||
#
|
||||
# syntax: perl explode.pl
|
||||
#
|
||||
# Description:
|
||||
# explode.pl unpacks the .jar files created by the NSPR build
|
||||
# procedure.
|
||||
#
|
||||
# Suggested use: After copying the platform directories to
|
||||
# /s/b/c/nspr20/<release>. CD to /s/b/c/nspr20/<release> and
|
||||
# run explode.pl. This will unpack the jar files into bin, lib,
|
||||
# include directories.
|
||||
#
|
||||
# -----------------------------------------------------------------
|
||||
|
||||
@dirs = `ls -d *.OBJ*`;
|
||||
|
||||
foreach $dir (@dirs) {
|
||||
chop($dir);
|
||||
if (-l $dir) {
|
||||
print "Skipping symbolic link $dir\n";
|
||||
next;
|
||||
}
|
||||
print "Unzipping $dir/mdbinary.jar\n";
|
||||
system ("unzip", "-o", "$dir/mdbinary.jar",
|
||||
"-d", "$dir");
|
||||
system ("rm", "-rf", "$dir/META-INF");
|
||||
mkdir "$dir/include", 0755;
|
||||
print "Unzipping $dir/mdheader.jar\n";
|
||||
system ("unzip", "-o", "-aa",
|
||||
"$dir/mdheader.jar",
|
||||
"-d", "$dir/include");
|
||||
system ("rm", "-rf", "$dir/include/META-INF");
|
||||
}
|
||||
# --- end explode.pl ----------------------------------------------
|
||||
@@ -1,79 +0,0 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla 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/MPL/
|
||||
#
|
||||
# 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 the Netscape Portable Runtime (NSPR).
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Netscape Communications Corporation.
|
||||
# Portions created by the Initial Developer are Copyright (C) 1998-2001
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
# -----------------------------------------------------------------
|
||||
# makeTargetDirs.sh -- Create target directories for building NSPR
|
||||
#
|
||||
# syntax: makeTargetDirs.sh
|
||||
#
|
||||
# Description:
|
||||
# makeTargetDirs.sh creates a set of directories intended for use
|
||||
# with NSPR's autoconf based build system.
|
||||
#
|
||||
# The enumerated directories are the same as those built for NSPR
|
||||
# 4.1.1. Adjust as needed.
|
||||
#
|
||||
# -----------------------------------------------------------------
|
||||
|
||||
mkdir AIX4.3_64_DBG.OBJ
|
||||
mkdir AIX4.3_64_OPT.OBJ
|
||||
mkdir AIX4.3_DBG.OBJ
|
||||
mkdir AIX4.3_OPT.OBJ
|
||||
mkdir HP-UXB.11.00_64_DBG.OBJ
|
||||
mkdir HP-UXB.11.00_64_OPT.OBJ
|
||||
mkdir HP-UXB.11.00_DBG.OBJ
|
||||
mkdir HP-UXB.11.00_OPT.OBJ
|
||||
mkdir IRIX6.5_n32_PTH_DBG.OBJ
|
||||
mkdir IRIX6.5_n32_PTH_OPT.OBJ
|
||||
mkdir Linux2.2_x86_glibc_PTH_DBG.OBJ
|
||||
mkdir Linux2.2_x86_glibc_PTH_OPT.OBJ
|
||||
mkdir Linux2.4_x86_glibc_PTH_DBG.OBJ
|
||||
mkdir Linux2.4_x86_glibc_PTH_OPT.OBJ
|
||||
mkdir OSF1V4.0D_DBG.OBJ
|
||||
mkdir OSF1V4.0D_OPT.OBJ
|
||||
mkdir SunOS5.6_DBG.OBJ
|
||||
mkdir SunOS5.6_OPT.OBJ
|
||||
mkdir SunOS5.7_64_DBG.OBJ
|
||||
mkdir SunOS5.7_64_OPT.OBJ
|
||||
mkdir WIN954.0_DBG.OBJ
|
||||
mkdir WIN954.0_DBG.OBJD
|
||||
mkdir WIN954.0_OPT.OBJ
|
||||
mkdir WINNT4.0_DBG.OBJ
|
||||
mkdir WINNT4.0_DBG.OBJD
|
||||
mkdir WINNT4.0_OPT.OBJ
|
||||
# --- end makeTargetDirs.sh ---------------------------------------
|
||||
@@ -1,211 +0,0 @@
|
||||
#! /bin/sh
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla 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/MPL/
|
||||
#
|
||||
# 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 the Netscape Portable Runtime (NSPR).
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Netscape Communications Corporation.
|
||||
# Portions created by the Initial Developer are Copyright (C) 1998-2001
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# repackage.sh -- Repackage NSPR from /s/b/c to mozilla.org format
|
||||
#
|
||||
# syntax: repackage.sh
|
||||
#
|
||||
# Description:
|
||||
# repackage.sh creates NSPR binary distributions for mozilla.org from
|
||||
# the internal binary distributions in /share/builds/components/nspr20.
|
||||
# There are reasons why we can't just push the internal binary distributions
|
||||
# to mozilla.org. External developers prefer to use the common archive
|
||||
# file format for their platforms, rather than the jar files we use internally.
|
||||
#
|
||||
# On Unix, we create a tar.gz file. On Windows, we create a zip file.
|
||||
# For example: NSPR 4.1.1, these would be nspr-4.1.1.tar.gz and nspr-4.1.1.zip.
|
||||
#
|
||||
# When unpacked, nspr-4.1.1.tar.gz or nspr-4.1.1.zip should expand to a
|
||||
# nspr-4.1.1 directory that contains three subdirectories: include, lib,
|
||||
# and bin. The header files, with the correct line endings for the
|
||||
# platform, are in nspr-4.1.1/include. The libraries are in nspr-4.1.1/lib.
|
||||
# The executable programs are in nspr-4.1.1/bin.
|
||||
#
|
||||
# Note! Files written with Gnu tar are not readable by some non-Gnu
|
||||
# versions. Sun, in particular.
|
||||
#
|
||||
#
|
||||
#
|
||||
#
|
||||
# ------------------------------------------------------------------
|
||||
|
||||
FROMTOP=/share/builds/components/nspr20/v4.6.9
|
||||
TOTOP=./v4.6.9
|
||||
NSPRDIR=nspr-4.6.9
|
||||
SOURCETAG=NSPR_4_6_9_RTM
|
||||
|
||||
#
|
||||
# enumerate Unix object directories on /s/b/c
|
||||
UNIX_OBJDIRS="
|
||||
HP-UXB.11.11_64_DBG.OBJ
|
||||
HP-UXB.11.11_64_OPT.OBJ
|
||||
HP-UXB.11.11_DBG.OBJ
|
||||
HP-UXB.11.11_OPT.OBJ
|
||||
HP-UXB.11.23_ia64_32_DBG.OBJ
|
||||
HP-UXB.11.23_ia64_32_OPT.OBJ
|
||||
HP-UXB.11.23_ia64_64_DBG.OBJ
|
||||
HP-UXB.11.23_ia64_64_OPT.OBJ
|
||||
Linux2.4_x86_glibc_PTH_DBG.OBJ
|
||||
Linux2.4_x86_glibc_PTH_OPT.OBJ
|
||||
Linux2.6_x86_64_glibc_PTH_DBG.OBJ
|
||||
Linux2.6_x86_64_glibc_PTH_OPT.OBJ
|
||||
Linux2.6_x86_glibc_PTH_DBG.OBJ
|
||||
Linux2.6_x86_glibc_PTH_OPT.OBJ
|
||||
SunOS5.9_64_DBG.OBJ
|
||||
SunOS5.9_64_OPT.OBJ
|
||||
SunOS5.9_DBG.OBJ
|
||||
SunOS5.9_OPT.OBJ
|
||||
"
|
||||
#
|
||||
# enumerate Windows object directories on /s/b/c
|
||||
WIN_OBJDIRS="
|
||||
WIN954.0_DBG.OBJ
|
||||
WIN954.0_DBG.OBJD
|
||||
WIN954.0_OPT.OBJ
|
||||
WINNT5.0_DBG.OBJ
|
||||
WINNT5.0_DBG.OBJD
|
||||
WINNT5.0_OPT.OBJ
|
||||
"
|
||||
|
||||
#
|
||||
# Create the destination directory.
|
||||
#
|
||||
echo "removing directory $TOTOP"
|
||||
rm -rf $TOTOP
|
||||
echo "creating directory $TOTOP"
|
||||
mkdir -p $TOTOP
|
||||
|
||||
#
|
||||
# Generate the tar.gz files for Unix platforms.
|
||||
#
|
||||
for OBJDIR in $UNIX_OBJDIRS; do
|
||||
echo "removing directory $NSPRDIR"
|
||||
rm -rf $NSPRDIR
|
||||
echo "creating directory $NSPRDIR"
|
||||
mkdir $NSPRDIR
|
||||
|
||||
echo "creating directory $NSPRDIR/include"
|
||||
mkdir $NSPRDIR/include
|
||||
echo "copying $FROMTOP/$OBJDIR/include"
|
||||
cp -r $FROMTOP/$OBJDIR/include $NSPRDIR
|
||||
|
||||
echo "copying $FROMTOP/$OBJDIR/lib"
|
||||
cp -r $FROMTOP/$OBJDIR/lib $NSPRDIR
|
||||
|
||||
echo "copying $FROMTOP/$OBJDIR/bin"
|
||||
cp -r $FROMTOP/$OBJDIR/bin $NSPRDIR
|
||||
|
||||
echo "creating directory $TOTOP/$OBJDIR"
|
||||
mkdir $TOTOP/$OBJDIR
|
||||
echo "creating $TOTOP/$OBJDIR/$NSPRDIR.tar"
|
||||
tar cvf $TOTOP/$OBJDIR/$NSPRDIR.tar $NSPRDIR
|
||||
echo "gzipping $TOTOP/$OBJDIR/$NSPRDIR.tar"
|
||||
gzip $TOTOP/$OBJDIR/$NSPRDIR.tar
|
||||
done
|
||||
|
||||
#
|
||||
# Generate the zip files for Windows platforms.
|
||||
#
|
||||
for OBJDIR in $WIN_OBJDIRS; do
|
||||
echo "removing directory $NSPRDIR"
|
||||
rm -rf $NSPRDIR
|
||||
echo "creating directory $NSPRDIR"
|
||||
mkdir $NSPRDIR
|
||||
|
||||
echo "creating directory $NSPRDIR/include"
|
||||
mkdir $NSPRDIR/include
|
||||
echo "creating directory $NSPRDIR/include/private"
|
||||
mkdir $NSPRDIR/include/private
|
||||
echo "creating directory $NSPRDIR/include/obsolete"
|
||||
mkdir $NSPRDIR/include/obsolete
|
||||
|
||||
# copy headers and adjust unix line-end to Windows line-end
|
||||
# Note: Watch out for the "sed" command line.
|
||||
# when editing the command, take care to preserve the "^M" as the literal
|
||||
# cntl-M character! in vi, use "cntl-v cntl-m" to enter it!
|
||||
#
|
||||
headers=`ls $FROMTOP/$OBJDIR/include/*.h`
|
||||
for header in $headers; do
|
||||
sed -e 's/$/
|
||||
/g' $header > $NSPRDIR/include/`basename $header`
|
||||
done
|
||||
headers=`ls $FROMTOP/$OBJDIR/include/obsolete/*.h`
|
||||
for header in $headers; do
|
||||
sed -e 's/$/
|
||||
/g' $header > $NSPRDIR/include/obsolete/`basename $header`
|
||||
done
|
||||
headers=`ls $FROMTOP/$OBJDIR/include/private/*.h`
|
||||
for header in $headers; do
|
||||
sed -e 's/$/
|
||||
/g' $header > $NSPRDIR/include/private/`basename $header`
|
||||
done
|
||||
|
||||
echo "copying $FROMTOP/$OBJDIR/lib"
|
||||
cp -r $FROMTOP/$OBJDIR/lib $NSPRDIR
|
||||
|
||||
echo "copying $FROMTOP/$OBJDIR/bin"
|
||||
cp -r $FROMTOP/$OBJDIR/bin $NSPRDIR
|
||||
|
||||
echo "creating directory $TOTOP/$OBJDIR"
|
||||
mkdir -p $TOTOP/$OBJDIR
|
||||
echo "creating $TOTOP/$OBJDIR/$NSPRDIR.zip"
|
||||
zip -r $TOTOP/$OBJDIR/$NSPRDIR.zip $NSPRDIR
|
||||
done
|
||||
|
||||
#
|
||||
# package the source from CVS
|
||||
#
|
||||
echo "Packaging source"
|
||||
echo "removing directory $NSPRDIR"
|
||||
rm -rf $NSPRDIR
|
||||
echo "creating directory $NSPRDIR"
|
||||
mkdir $NSPRDIR
|
||||
myWD=`pwd`
|
||||
cd $NSPRDIR
|
||||
echo "Pulling source from CVS with tag $SOURCETAG"
|
||||
cvs co -r $SOURCETAG mozilla/nsprpub
|
||||
cd $myWD
|
||||
mkdir $TOTOP/src
|
||||
echo "Creating source tar file: $TOTOP/src/$NSPRDIR.tar"
|
||||
tar cvf $TOTOP/src/$NSPRDIR.tar $NSPRDIR
|
||||
echo "gzip $TOTOP/src/$NSPRDIR.tar"
|
||||
gzip $TOTOP/src/$NSPRDIR.tar
|
||||
|
||||
#
|
||||
# Remove the working directory.
|
||||
#
|
||||
@@ -1,75 +0,0 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla 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/MPL/
|
||||
#
|
||||
# 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 the Netscape Portable Runtime (NSPR).
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Netscape Communications Corporation.
|
||||
# Portions created by the Initial Developer are Copyright (C) 1998-2001
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
# -----------------------------------------------------------------
|
||||
# symlinks.sh -- create links from NSPR builds
|
||||
#
|
||||
# syntax: symlinks.sh
|
||||
#
|
||||
# Description:
|
||||
# symlinks.sh creates some symbolic links for NSPR build targets
|
||||
# that are not actually build, but for which there are NSPR
|
||||
# binaries suitable for running on the intended target. ... got
|
||||
# that?
|
||||
#
|
||||
# Suggested use: After copying NSPR binaries to
|
||||
# /s/b/c/nspr20/<platform> run symlinks.sh to create the links
|
||||
# for all supported platforms.
|
||||
#
|
||||
# The symlinks in this script correspond to the NSPR 4.1.1
|
||||
# release. Adjust as necessary.
|
||||
#
|
||||
# -----------------------------------------------------------------
|
||||
|
||||
ln -s SunOS5.6_DBG.OBJ SunOS5.7_DBG.OBJ
|
||||
ln -s SunOS5.6_OPT.OBJ SunOS5.7_OPT.OBJ
|
||||
|
||||
ln -s SunOS5.6_DBG.OBJ SunOS5.8_DBG.OBJ
|
||||
ln -s SunOS5.6_OPT.OBJ SunOS5.8_OPT.OBJ
|
||||
|
||||
ln -s SunOS5.7_64_DBG.OBJ SunOS5.8_64_DBG.OBJ
|
||||
ln -s SunOS5.7_64_OPT.OBJ SunOS5.8_64_OPT.OBJ
|
||||
|
||||
ln -s OSF1V4.0D_DBG.OBJ OSF1V5.0_DBG.OBJ
|
||||
ln -s OSF1V4.0D_OPT.OBJ OSF1V5.0_OPT.OBJ
|
||||
|
||||
ln -s WINNT4.0_DBG.OBJ WINNT5.0_DBG.OBJ
|
||||
ln -s WINNT4.0_DBG.OBJD WINNT5.0_DBG.OBJD
|
||||
ln -s WINNT4.0_OPT.OBJ WINNT5.0_OPT.OBJ
|
||||
# --- end symlinks.sh ---------------------------------------------
|
||||
|
||||
1404
mozilla/nsprpub/build/autoconf/config.guess
vendored
1404
mozilla/nsprpub/build/autoconf/config.guess
vendored
File diff suppressed because it is too large
Load Diff
1505
mozilla/nsprpub/build/autoconf/config.sub
vendored
1505
mozilla/nsprpub/build/autoconf/config.sub
vendored
File diff suppressed because it is too large
Load Diff
@@ -1,119 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
#
|
||||
# install - install a program, script, or datafile
|
||||
# This comes from X11R5; it is not part of GNU.
|
||||
#
|
||||
# $XConsortium: install.sh,v 1.2 89/12/18 14:47:22 jim Exp $
|
||||
#
|
||||
# This script is compatible with the BSD install script, but was written
|
||||
# from scratch.
|
||||
#
|
||||
|
||||
|
||||
# set DOITPROG to echo to test this script
|
||||
|
||||
# Don't use :- since 4.3BSD and earlier shells don't like it.
|
||||
doit="${DOITPROG-}"
|
||||
|
||||
|
||||
# put in absolute paths if you don't have them in your path; or use env. vars.
|
||||
|
||||
mvprog="${MVPROG-mv}"
|
||||
cpprog="${CPPROG-cp}"
|
||||
chmodprog="${CHMODPROG-chmod}"
|
||||
chownprog="${CHOWNPROG-chown}"
|
||||
chgrpprog="${CHGRPPROG-chgrp}"
|
||||
stripprog="${STRIPPROG-strip}"
|
||||
rmprog="${RMPROG-rm}"
|
||||
|
||||
instcmd="$mvprog"
|
||||
chmodcmd=""
|
||||
chowncmd=""
|
||||
chgrpcmd=""
|
||||
stripcmd=""
|
||||
rmcmd="$rmprog -f"
|
||||
mvcmd="$mvprog"
|
||||
src=""
|
||||
dst=""
|
||||
|
||||
while [ x"$1" != x ]; do
|
||||
case $1 in
|
||||
-c) instcmd="$cpprog"
|
||||
shift
|
||||
continue;;
|
||||
|
||||
-m) chmodcmd="$chmodprog $2"
|
||||
shift
|
||||
shift
|
||||
continue;;
|
||||
|
||||
-o) chowncmd="$chownprog $2"
|
||||
shift
|
||||
shift
|
||||
continue;;
|
||||
|
||||
-g) chgrpcmd="$chgrpprog $2"
|
||||
shift
|
||||
shift
|
||||
continue;;
|
||||
|
||||
-s) stripcmd="$stripprog"
|
||||
shift
|
||||
continue;;
|
||||
|
||||
*) if [ x"$src" = x ]
|
||||
then
|
||||
src=$1
|
||||
else
|
||||
dst=$1
|
||||
fi
|
||||
shift
|
||||
continue;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [ x"$src" = x ]
|
||||
then
|
||||
echo "install: no input file specified"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ x"$dst" = x ]
|
||||
then
|
||||
echo "install: no destination specified"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
|
||||
# If destination is a directory, append the input filename; if your system
|
||||
# does not like double slashes in filenames, you may need to add some logic
|
||||
|
||||
if [ -d $dst ]
|
||||
then
|
||||
dst="$dst"/`basename $src`
|
||||
fi
|
||||
|
||||
# Make a temp file name in the proper directory.
|
||||
|
||||
dstdir=`dirname $dst`
|
||||
dsttmp=$dstdir/#inst.$$#
|
||||
|
||||
# Move or copy the file name to the temp name
|
||||
|
||||
$doit $instcmd $src $dsttmp
|
||||
|
||||
# and set any options; do chmod last to preserve setuid bits
|
||||
|
||||
if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; fi
|
||||
if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; fi
|
||||
if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; fi
|
||||
if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; fi
|
||||
|
||||
# Now rename the file to the real destination.
|
||||
|
||||
$doit $rmcmd $dst
|
||||
$doit $mvcmd $dsttmp $dst
|
||||
|
||||
|
||||
exit 0
|
||||
@@ -1,75 +0,0 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Stupid wrapper to avoid win32 dospath/cygdrive issues
|
||||
# Try not to spawn programs from within this file. If the stuff in here looks royally
|
||||
# confusing, see bug: http://bugzilla.mozilla.org/show_bug.cgi?id=206643
|
||||
# and look at the older versions of this file that are easier to read, but
|
||||
# do basically the same thing
|
||||
#
|
||||
|
||||
prog=$1
|
||||
shift
|
||||
if test -z "$prog"; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# If $CYGDRIVE_MOUNT was not set in configure, give $mountpoint the results of mount -p
|
||||
mountpoint=$CYGDRIVE_MOUNT
|
||||
if test -z "$mountpoint"; then
|
||||
mountpoint=`mount -p`
|
||||
if test -z "$mountpoint"; then
|
||||
print "Cannot determine cygwin mount points. Exiting"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
# Delete everything but "/cygdrive" (or other mountpoint) from mount=`mount -p`
|
||||
mountpoint=${mountpoint#*/}
|
||||
mountpoint=/${mountpoint%%[!A-Za-z0-9_]*}
|
||||
mountpoint=${mountpoint%/}
|
||||
|
||||
args=""
|
||||
up=""
|
||||
if test "${prog}" = "-up"; then
|
||||
up=1
|
||||
prog=${1}
|
||||
shift
|
||||
fi
|
||||
|
||||
process=1
|
||||
|
||||
# Convert the mountpoint in parameters to Win32 filenames
|
||||
# For instance: /cygdrive/c/foo -> c:/foo
|
||||
for i in "${@}"
|
||||
do
|
||||
if test "${i}" = "-wrap"; then
|
||||
process=1
|
||||
else
|
||||
if test "${i}" = "-nowrap"; then
|
||||
process=
|
||||
else
|
||||
if test -n "${process}"; then
|
||||
if test -n "${up}"; then
|
||||
pathname=${i#-I[a-zA-Z]:/}
|
||||
if ! test "${pathname}" = "${i}"; then
|
||||
no_i=${i#-I}
|
||||
driveletter=${no_i%%:*}
|
||||
i=-I${mountpoint}/${driveletter}/${pathname}
|
||||
fi
|
||||
else
|
||||
eval 'leader=${i%%'${mountpoint}'/[a-zA-Z]/*}'
|
||||
if ! test "${leader}" = "${i}"; then
|
||||
eval 'pathname=${i#'${leader}${mountpoint}'/[a-zA-Z]/}'
|
||||
eval 'no_mountpoint=${i#'${leader}${mountpoint}'/}'
|
||||
driveletter=${no_mountpoint%%/*}
|
||||
i=${leader}${driveletter}:/${pathname}
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
args="${args} ${i}"
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
exec $prog $args
|
||||
@@ -1,160 +0,0 @@
|
||||
#! gmake
|
||||
#
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla 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/MPL/
|
||||
#
|
||||
# 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 the Netscape Portable Runtime (NSPR).
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Netscape Communications Corporation.
|
||||
# Portions created by the Initial Developer are Copyright (C) 1998-2000
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
MOD_DEPTH = ..
|
||||
topsrcdir = @top_srcdir@
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
include $(MOD_DEPTH)/config/autoconf.mk
|
||||
|
||||
# Indicate that this directory builds build tools.
|
||||
INTERNAL_TOOLS = 1
|
||||
|
||||
# For sanity's sake, we compile nsinstall without the wrapped system
|
||||
# headers, so that we can use it to set up the wrapped system headers.
|
||||
VISIBILITY_FLAGS =
|
||||
|
||||
# autoconf.mk must be deleted last (from the top-level directory)
|
||||
# because it is included by every makefile.
|
||||
DIST_GARBAGE = nsprincl.mk nsprincl.sh nspr-config
|
||||
|
||||
RELEASE_BINS = nspr-config
|
||||
|
||||
include $(topsrcdir)/config/config.mk
|
||||
|
||||
CSRCS = now.c
|
||||
|
||||
# This version hasn't been ported for us; the one in mozilla/config has
|
||||
ifneq ($(OS_ARCH),OS2)
|
||||
CSRCS += nsinstall.c
|
||||
|
||||
PLSRCS = nfspwd.pl
|
||||
endif
|
||||
|
||||
ifeq (,$(CROSS_COMPILE)$(filter-out WINNT OS2,$(OS_ARCH)))
|
||||
PROG_SUFFIX = .exe
|
||||
else
|
||||
PROG_SUFFIX =
|
||||
endif
|
||||
|
||||
# Temporary workaround to disable the generation of
|
||||
# library build time because now.c uses the 'long long'
|
||||
# data type that's not available on some platforms.
|
||||
ifeq (,$(filter-out NEC NEXTSTEP QNX SCOOS UNIXWARE,$(OS_ARCH)))
|
||||
DEFINES += -DOMIT_LIB_BUILD_TIME
|
||||
endif
|
||||
|
||||
ifeq ($(OS_ARCH), IRIX)
|
||||
ifeq ($(basename $(OS_RELEASE)),6)
|
||||
ifndef NS_USE_GCC
|
||||
ifeq ($(USE_N32),1)
|
||||
XLDOPTS += -n32 -Wl,-woff,85
|
||||
else
|
||||
ifeq ($(USE_64),1)
|
||||
XLDOPTS += -64
|
||||
else
|
||||
XLDOPTS += -32
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(OS_ARCH), HP-UX)
|
||||
ifeq ($(USE_64),1)
|
||||
XLDOPTS += +DD64
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(MOZ_OS2_TOOLS),EMX)
|
||||
XCFLAGS = $(OS_CFLAGS)
|
||||
ifeq ($(MOZ_OS2_EMX_OBJECTFORMAT),OMF)
|
||||
XLDOPTS = -Zlinker /PM:VIO
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(MOZ_OS2_TOOLS),PGCC)
|
||||
XCFLAGS = $(OS_CFLAGS)
|
||||
XLDOPTS = -Zlinker /PM:VIO
|
||||
endif
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
PROGS = $(OBJDIR)/now$(PROG_SUFFIX)
|
||||
|
||||
ifeq (,$(CROSS_COMPILE)$(filter-out OS2 WINNT,$(OS_ARCH)))
|
||||
TARGETS = $(PROGS)
|
||||
else
|
||||
PROGS += $(OBJDIR)/nsinstall$(PROG_SUFFIX)
|
||||
TARGETS = $(PROGS) $(PLSRCS:.pl=)
|
||||
endif
|
||||
|
||||
OUTOPTION = -o # end of the line
|
||||
ifeq (,$(filter-out WINNT WIN95,$(OS_TARGET)))
|
||||
ifndef NS_USE_GCC
|
||||
OUTOPTION = -Fe
|
||||
endif
|
||||
endif
|
||||
|
||||
# Redefine MAKE_OBJDIR for just this directory
|
||||
define MAKE_OBJDIR
|
||||
if test ! -d $(@D); then rm -rf $(@D); mkdir $(@D); else true; fi
|
||||
endef
|
||||
|
||||
export:: $(TARGETS)
|
||||
rm -f $(dist_bindir)/nspr-config
|
||||
|
||||
ifdef WRAP_SYSTEM_INCLUDES
|
||||
export::
|
||||
if test ! -d system_wrappers; then mkdir system_wrappers; fi
|
||||
$(PERL) $(srcdir)/make-system-wrappers.pl system_wrappers < $(srcdir)/system-headers
|
||||
$(INSTALL) system_wrappers $(dist_includedir)
|
||||
endif
|
||||
|
||||
$(OBJDIR)/%$(PROG_SUFFIX): $(OBJDIR)/%.$(OBJ_SUFFIX)
|
||||
@$(MAKE_OBJDIR)
|
||||
ifeq ($(MOZ_OS2_TOOLS),VACPP)
|
||||
$(LD) $(EXEFLAGS) $<
|
||||
else
|
||||
$(CC) $(XCFLAGS) $< $(LDFLAGS) $(XLDOPTS) $(OUTOPTION)$@
|
||||
endif
|
||||
|
||||
real_install:: nspr.m4
|
||||
$(NSINSTALL) -D $(DESTDIR)$(datadir)/aclocal
|
||||
$(NSINSTALL) -t -m 0644 $< $(DESTDIR)$(datadir)/aclocal
|
||||
@@ -1,129 +0,0 @@
|
||||
# -*- Mode: Makefile -*-
|
||||
|
||||
INCLUDED_AUTOCONF_MK = 1
|
||||
USE_AUTOCONF = 1
|
||||
@SHELL_OVERRIDE@
|
||||
MOZILLA_CLIENT = @MOZILLA_CLIENT@
|
||||
|
||||
prefix = @prefix@
|
||||
exec_prefix = @exec_prefix@
|
||||
bindir = @bindir@
|
||||
includedir = @includedir@
|
||||
libdir = @libdir@
|
||||
datadir = @datadir@
|
||||
|
||||
dist_prefix = @dist_prefix@
|
||||
dist_bindir = @dist_bindir@
|
||||
dist_includedir = @dist_includedir@
|
||||
dist_libdir = @dist_libdir@
|
||||
|
||||
DIST = $(dist_prefix)
|
||||
|
||||
RELEASE_OBJDIR_NAME = @RELEASE_OBJDIR_NAME@
|
||||
OBJDIR_NAME = @OBJDIR_NAME@
|
||||
OBJDIR = @OBJDIR@
|
||||
OBJ_SUFFIX = @OBJ_SUFFIX@
|
||||
LIB_SUFFIX = @LIB_SUFFIX@
|
||||
DLL_SUFFIX = @DLL_SUFFIX@
|
||||
ASM_SUFFIX = @ASM_SUFFIX@
|
||||
MOD_NAME = @NSPR_MODNAME@
|
||||
|
||||
MOD_MAJOR_VERSION = @MOD_MAJOR_VERSION@
|
||||
MOD_MINOR_VERSION = @MOD_MINOR_VERSION@
|
||||
MOD_PATCH_VERSION = @MOD_PATCH_VERSION@
|
||||
|
||||
LIBNSPR = @LIBNSPR@
|
||||
LIBPLC = @LIBPLC@
|
||||
|
||||
CROSS_COMPILE = @CROSS_COMPILE@
|
||||
BUILD_OPT = @MOZ_OPTIMIZE@
|
||||
|
||||
USE_CPLUS = @USE_CPLUS@
|
||||
USE_IPV6 = @USE_IPV6@
|
||||
USE_N32 = @USE_N32@
|
||||
USE_64 = @USE_64@
|
||||
GC_LEAK_DETECTOR = @GC_LEAK_DETECTOR@
|
||||
ENABLE_STRIP = @ENABLE_STRIP@
|
||||
|
||||
USE_PTHREADS = @USE_PTHREADS@
|
||||
USE_BTHREADS = @USE_BTHREADS@
|
||||
PTHREADS_USER = @USE_USER_PTHREADS@
|
||||
CLASSIC_NSPR = @USE_NSPR_THREADS@
|
||||
|
||||
AS = @AS@
|
||||
ASFLAGS = @ASFLAGS@
|
||||
CC = @CC@
|
||||
CCC = @CXX@
|
||||
NS_USE_GCC = @GNU_CC@
|
||||
GCC_USE_GNU_LD = @GCC_USE_GNU_LD@
|
||||
MSC_VER = @MSC_VER@
|
||||
AR = @AR@
|
||||
AR_FLAGS = @AR_FLAGS@
|
||||
LD = @LD@
|
||||
RANLIB = @RANLIB@
|
||||
PERL = @PERL@
|
||||
RC = @RC@
|
||||
RCFLAGS = @RCFLAGS@
|
||||
STRIP = @STRIP@
|
||||
NSINSTALL = @NSINSTALL@
|
||||
FILTER = @FILTER@
|
||||
IMPLIB = @IMPLIB@
|
||||
CYGWIN_WRAPPER = @CYGWIN_WRAPPER@
|
||||
|
||||
OS_CPPFLAGS = @CPPFLAGS@
|
||||
OS_CFLAGS = $(OS_CPPFLAGS) @CFLAGS@ $(DSO_CFLAGS)
|
||||
OS_CXXFLAGS = $(OS_CPPFLAGS) @CXXFLAGS@ $(DSO_CFLAGS)
|
||||
OS_LIBS = @OS_LIBS@
|
||||
OS_LDFLAGS = @LDFLAGS@
|
||||
OS_DLLFLAGS = @OS_DLLFLAGS@
|
||||
DLLFLAGS = @DLLFLAGS@
|
||||
EXEFLAGS = @EXEFLAGS@
|
||||
OPTIMIZER = @OPTIMIZER@
|
||||
|
||||
MKSHLIB = @MKSHLIB@
|
||||
DSO_CFLAGS = @DSO_CFLAGS@
|
||||
DSO_LDOPTS = @DSO_LDOPTS@
|
||||
|
||||
RESOLVE_LINK_SYMBOLS = @RESOLVE_LINK_SYMBOLS@
|
||||
|
||||
HOST_CC = @HOST_CC@
|
||||
HOST_CFLAGS = @HOST_CFLAGS@
|
||||
HOST_LDFLAGS = @HOST_LDFLAGS@
|
||||
|
||||
DEFINES = @DEFINES@ @DEFS@
|
||||
|
||||
MDCPUCFG_H = @MDCPUCFG_H@
|
||||
PR_MD_CSRCS = @PR_MD_CSRCS@
|
||||
PR_MD_ASFILES = @PR_MD_ASFILES@
|
||||
PR_MD_ARCH_DIR = @PR_MD_ARCH_DIR@
|
||||
CPU_ARCH = @CPU_ARCH@
|
||||
|
||||
OS_TARGET = @OS_TARGET@
|
||||
OS_ARCH = @OS_ARCH@
|
||||
OS_RELEASE = @OS_RELEASE@
|
||||
OS_TEST = @OS_TEST@
|
||||
|
||||
NOSUCHFILE = @NOSUCHFILE@
|
||||
AIX_LINK_OPTS = @AIX_LINK_OPTS@
|
||||
MOZ_OBJFORMAT = @MOZ_OBJFORMAT@
|
||||
ULTRASPARC_LIBRARY = @ULTRASPARC_LIBRARY@
|
||||
|
||||
OBJECT_MODE = @OBJECT_MODE@
|
||||
ifdef OBJECT_MODE
|
||||
export OBJECT_MODE
|
||||
endif
|
||||
|
||||
VISIBILITY_FLAGS = @VISIBILITY_FLAGS@
|
||||
WRAP_SYSTEM_INCLUDES = @WRAP_SYSTEM_INCLUDES@
|
||||
|
||||
MACOSX_DEPLOYMENT_TARGET = @MACOSX_DEPLOYMENT_TARGET@
|
||||
ifdef MACOSX_DEPLOYMENT_TARGET
|
||||
export MACOSX_DEPLOYMENT_TARGET
|
||||
endif
|
||||
|
||||
MACOS_SDK_DIR = @MACOS_SDK_DIR@
|
||||
|
||||
NEXT_ROOT = @NEXT_ROOT@
|
||||
ifdef NEXT_ROOT
|
||||
export NEXT_ROOT
|
||||
endif
|
||||
@@ -1,164 +0,0 @@
|
||||
#! gmake
|
||||
#
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla 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/MPL/
|
||||
#
|
||||
# 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 the Netscape Portable Runtime (NSPR).
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Netscape Communications Corporation.
|
||||
# Portions created by the Initial Developer are Copyright (C) 1998-2000
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
# Configuration information for building in the NSPR source module
|
||||
|
||||
# Define an include-at-most-once-flag
|
||||
NSPR_CONFIG_MK = 1
|
||||
|
||||
#
|
||||
# The variable definitions in this file are inputs to NSPR's
|
||||
# build system. This file, if present, is included at the
|
||||
# beginning of config.mk.
|
||||
#
|
||||
# For example:
|
||||
#
|
||||
# BUILD_OPT=1
|
||||
# USE_PTHREADS=1
|
||||
# NS_USE_GCC=
|
||||
#
|
||||
ifndef topsrcdir
|
||||
topsrcdir=$(MOD_DEPTH)
|
||||
endif
|
||||
|
||||
ifndef srcdir
|
||||
srcdir=.
|
||||
endif
|
||||
|
||||
NFSPWD = $(MOD_DEPTH)/config/nfspwd
|
||||
|
||||
CFLAGS = $(VISIBILITY_FLAGS) $(CC_ONLY_FLAGS) $(OPTIMIZER)\
|
||||
$(OS_CFLAGS) $(XP_DEFINE) $(DEFINES) $(INCLUDES) $(XCFLAGS)
|
||||
CCCFLAGS = $(VISIBILITY_FLAGS) $(CCC_ONLY_FLAGS) $(OPTIMIZER)\
|
||||
$(OS_CFLAGS) $(XP_DEFINE) $(DEFINES) $(INCLUDES) $(XCFLAGS)
|
||||
# For purify
|
||||
NOMD_CFLAGS = $(CC_ONLY_FLAGS) $(OPTIMIZER) $(NOMD_OS_CFLAGS)\
|
||||
$(XP_DEFINE) $(DEFINES) $(INCLUDES) $(XCFLAGS)
|
||||
NOMD_CCFLAGS = $(CCC_ONLY_FLAGS) $(OPTIMIZER) $(NOMD_OS_CFLAGS)\
|
||||
$(XP_DEFINE) $(DEFINES) $(INCLUDES) $(XCFLAGS)
|
||||
|
||||
LDFLAGS = $(OS_LDFLAGS)
|
||||
|
||||
define MAKE_OBJDIR
|
||||
if test ! -d $(@D); then rm -rf $(@D); $(NSINSTALL) -D $(@D); fi
|
||||
endef
|
||||
|
||||
LINK_DLL = $(LD) $(OS_DLLFLAGS) $(DLLFLAGS)
|
||||
|
||||
ifeq ($(OS_ARCH),Darwin)
|
||||
PWD := $(shell pwd)
|
||||
endif
|
||||
|
||||
ifeq (,$(CROSS_COMPILE)$(filter-out WINNT OS2, $(OS_ARCH)))
|
||||
INSTALL = $(NSINSTALL)
|
||||
else
|
||||
ifeq ($(NSDISTMODE),copy)
|
||||
# copy files, but preserve source mtime
|
||||
INSTALL = $(NSINSTALL) -t
|
||||
else
|
||||
ifeq ($(NSDISTMODE),absolute_symlink)
|
||||
# install using absolute symbolic links
|
||||
ifeq ($(OS_ARCH),Darwin)
|
||||
INSTALL = $(NSINSTALL) -L $(PWD)
|
||||
else
|
||||
INSTALL = $(NSINSTALL) -L `$(NFSPWD)`
|
||||
endif
|
||||
else
|
||||
# install using relative symbolic links
|
||||
INSTALL = $(NSINSTALL) -R
|
||||
endif
|
||||
endif
|
||||
endif # (WINNT || OS2) && !CROSS_COMPILE
|
||||
|
||||
DEPENDENCIES = $(OBJDIR)/.md
|
||||
|
||||
ifdef BUILD_DEBUG_GC
|
||||
DEFINES += -DDEBUG_GC
|
||||
endif
|
||||
|
||||
GARBAGE += $(DEPENDENCIES) core $(wildcard core.[0-9]*)
|
||||
|
||||
DIST_GARBAGE += Makefile
|
||||
|
||||
####################################################################
|
||||
#
|
||||
# The NSPR-specific configuration
|
||||
#
|
||||
####################################################################
|
||||
|
||||
DEFINES += -DFORCE_PR_LOG
|
||||
|
||||
ifeq ($(_PR_NO_CLOCK_TIMER),1)
|
||||
DEFINES += -D_PR_NO_CLOCK_TIMER
|
||||
endif
|
||||
|
||||
ifeq ($(USE_PTHREADS), 1)
|
||||
DEFINES += -D_PR_PTHREADS -UHAVE_CVAR_BUILT_ON_SEM
|
||||
endif
|
||||
|
||||
ifeq ($(PTHREADS_USER), 1)
|
||||
DEFINES += -DPTHREADS_USER -UHAVE_CVAR_BUILT_ON_SEM
|
||||
endif
|
||||
|
||||
ifeq ($(USE_IPV6),1)
|
||||
DEFINES += -D_PR_INET6
|
||||
endif
|
||||
|
||||
ifeq ($(MOZ_UNICODE),1)
|
||||
DEFINES += -DMOZ_UNICODE
|
||||
endif
|
||||
|
||||
####################################################################
|
||||
#
|
||||
# Configuration for the release process
|
||||
#
|
||||
####################################################################
|
||||
|
||||
MDIST = /m/dist
|
||||
ifeq ($(OS_ARCH),WINNT)
|
||||
MDIST = //helium/dist
|
||||
MDIST_DOS = $(subst /,\\,$(MDIST))
|
||||
endif
|
||||
|
||||
# RELEASE_DIR is ns/dist/<module name>
|
||||
|
||||
RELEASE_DIR = $(MOD_DEPTH)/dist/release/$(MOD_NAME)
|
||||
|
||||
RELEASE_INCLUDE_DIR = $(RELEASE_DIR)/$(BUILD_NUMBER)/$(OBJDIR_NAME)/include
|
||||
RELEASE_BIN_DIR = $(RELEASE_DIR)/$(BUILD_NUMBER)/$(OBJDIR_NAME)/bin
|
||||
RELEASE_LIB_DIR = $(RELEASE_DIR)/$(BUILD_NUMBER)/$(OBJDIR_NAME)/lib
|
||||
@@ -1,2 +0,0 @@
|
||||
/* Begin all files as hidden visibility */
|
||||
#pragma GCC visibility push(hidden)
|
||||
@@ -1,158 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla 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/MPL/
|
||||
*
|
||||
* 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 the Netscape Portable Runtime (NSPR).
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998-2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/* libc_r.h -- macros, defines, etc. to make using reentrant libc calls */
|
||||
/* a bit easier. This was initially done for AIX pthreads, */
|
||||
/* but should be usable for anyone... */
|
||||
|
||||
/* Most of these use locally defined space instead of static library space. */
|
||||
/* Because of this, we use the _INIT_R to declare/allocate space (stack), */
|
||||
/* and the plain routines to actually do it..._WARNING_: avoid allocating */
|
||||
/* memory wherever possible. Memory allocation is fairly expensive, at */
|
||||
/* least on AIX...use arrays instead (which allocate from the stack.) */
|
||||
/* I know the names are a bit strange, but I wanted to be fairly certain */
|
||||
/* that we didn't have any namespace corruption...in general, the inits are */
|
||||
/* R_<name>_INIT_R(), and the actual calls are R_<name>_R(). */
|
||||
|
||||
#ifndef _LIBC_R_H
|
||||
#define _LIBC_R_H
|
||||
|
||||
/************/
|
||||
/* strtok */
|
||||
/************/
|
||||
#define R_STRTOK_INIT_R() \
|
||||
char *r_strtok_r=NULL
|
||||
|
||||
#define R_STRTOK_R(return,source,delim) \
|
||||
return=strtok_r(source,delim,&r_strtok_r)
|
||||
|
||||
#define R_STRTOK_NORET_R(source,delim) \
|
||||
strtok_r(source,delim,&r_strtok_r)
|
||||
|
||||
/**************/
|
||||
/* strerror */
|
||||
/**************/
|
||||
#define R_MAX_STRERROR_LEN_R 8192 /* Straight from limits.h */
|
||||
|
||||
#define R_STRERROR_INIT_R() \
|
||||
char r_strerror_r[R_MAX_STRERROR_LEN_R]
|
||||
|
||||
#define R_STRERROR_R(val) \
|
||||
strerror_r(val,r_strerror_r,R_MAX_STRERROR_LEN_R)
|
||||
|
||||
/*****************/
|
||||
/* time things */
|
||||
/*****************/
|
||||
#define R_ASCTIME_INIT_R() \
|
||||
char r_asctime_r[26]
|
||||
|
||||
#define R_ASCTIME_R(val) \
|
||||
asctime_r(val,r_asctime_r)
|
||||
|
||||
#define R_CTIME_INIT_R() \
|
||||
char r_ctime_r[26]
|
||||
|
||||
#define R_CTIME_R(val) \
|
||||
ctime_r(val,r_ctime_r)
|
||||
|
||||
#define R_GMTIME_INIT_R() \
|
||||
struct tm r_gmtime_r
|
||||
|
||||
#define R_GMTIME_R(time) \
|
||||
gmtime_r(time,&r_gmtime_r)
|
||||
|
||||
#define R_LOCALTIME_INIT_R() \
|
||||
struct tm r_localtime_r
|
||||
|
||||
#define R_LOCALTIME_R(val) \
|
||||
localtime_r(val,&r_localtime_r)
|
||||
|
||||
/***********/
|
||||
/* crypt */
|
||||
/***********/
|
||||
#include <crypt.h>
|
||||
#define R_CRYPT_INIT_R() \
|
||||
CRYPTD r_cryptd_r; \
|
||||
bzero(&r_cryptd_r,sizeof(CRYPTD))
|
||||
|
||||
#define R_CRYPT_R(pass,salt) \
|
||||
crypt_r(pass,salt,&r_cryptd_r)
|
||||
|
||||
/**************/
|
||||
/* pw stuff */
|
||||
/**************/
|
||||
#define R_MAX_PW_LEN_R 1024
|
||||
/* The following must be after the last declaration, but */
|
||||
/* before the first bit of code... */
|
||||
#define R_GETPWNAM_INIT_R(pw_ptr) \
|
||||
struct passwd r_getpwnam_pw_r; \
|
||||
char r_getpwnam_line_r[R_MAX_PW_LEN_R]; \
|
||||
pw_ptr = &r_getpwnam_pw_r
|
||||
|
||||
#define R_GETPWNAM_R(name) \
|
||||
getpwnam_r(name,&r_getpwnam_pw_r,r_getpwnam_line_r,R_MAX_PW_LEN_R)
|
||||
|
||||
/*******************/
|
||||
/* gethost stuff */
|
||||
/*******************/
|
||||
#define R_GETHOSTBYADDR_INIT_R() \
|
||||
struct hostent r_gethostbyaddr_r; \
|
||||
struct hostent_data r_gethostbyaddr_data_r
|
||||
|
||||
#define R_GETHOSTBYADDR_R(addr,len,type,xptr_ent) \
|
||||
bzero(&r_gethostbyaddr_r,sizeof(struct hostent)); \
|
||||
bzero(&r_gethostbyaddr_data_r,sizeof(struct hostent_data)); \
|
||||
xptr_ent = &r_gethostbyaddr_r; \
|
||||
if (gethostbyaddr_r(addr,len,type, \
|
||||
&r_gethostbyaddr_r,&r_gethostbyaddr_data_r) == -1) { \
|
||||
xptr_ent = NULL; \
|
||||
}
|
||||
|
||||
#define R_GETHOSTBYNAME_INIT_R() \
|
||||
struct hostent r_gethostbyname_r; \
|
||||
struct hostent_data r_gethostbyname_data_r
|
||||
|
||||
#define R_GETHOSTBYNAME_R(name,xptr_ent) \
|
||||
bzero(&r_gethostbyname_r,sizeof(struct hostent)); \
|
||||
bzero(&r_gethostbyname_data_r,sizeof(struct hostent_data)); \
|
||||
xptr_ent = &r_gethostbyname_r; \
|
||||
if (gethostbyname_r(name, \
|
||||
&r_gethostbyname_r,&r_gethostbyname_data_r) == -1) { \
|
||||
xptr_ent = NULL; \
|
||||
}
|
||||
|
||||
#endif /* _LIBC_R_H */
|
||||
@@ -1,59 +0,0 @@
|
||||
#!/usr/bin/perl
|
||||
#
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla 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/MPL/
|
||||
#
|
||||
# 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
|
||||
# IBM Corporation.
|
||||
# Portions created by the Initial Developer are Copyright (C) 2004
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
# Brian Ryner <bryner@brianryner.com>
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
$output_dir = shift;
|
||||
|
||||
while (<STDIN>) {
|
||||
chomp;
|
||||
if (-e "$output_dir/$_") {
|
||||
next;
|
||||
}
|
||||
|
||||
if (/(.*)\/[^\/*]/) {
|
||||
mkdir "$output_dir/$1";
|
||||
}
|
||||
|
||||
open OUT, ">$output_dir/$_";
|
||||
print OUT "#pragma GCC system_header\n"; # suppress include_next warning
|
||||
print OUT "#pragma GCC visibility push(default)\n";
|
||||
print OUT "#include_next \<$_\>\n";
|
||||
print OUT "#pragma GCC visibility pop\n";
|
||||
close OUT;
|
||||
}
|
||||
|
||||
@@ -1,50 +0,0 @@
|
||||
#! perl
|
||||
#
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla 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/MPL/
|
||||
#
|
||||
# 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 the Netscape Portable Runtime (NSPR).
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Netscape Communications Corporation.
|
||||
# Portions created by the Initial Developer are Copyright (C) 1998-2000
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
require "fastcwd.pl";
|
||||
|
||||
$_ = &fastcwd;
|
||||
if (m@^/[uh]/@o || s@^/tmp_mnt/@/@o) {
|
||||
print("$_\n");
|
||||
} elsif ((($user, $rest) = m@^/usr/people/(\w+)/(.*)@o)
|
||||
&& readlink("/u/$user") eq "/usr/people/$user") {
|
||||
print("/u/$user/$rest\n");
|
||||
} else {
|
||||
chop($host = `hostname`);
|
||||
print("/h/$host$_\n");
|
||||
}
|
||||
@@ -1,142 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla 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/MPL/
|
||||
*
|
||||
* 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 the Netscape Portable Runtime (NSPR).
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998-2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#if defined(VMS)
|
||||
#include <sys/timeb.h>
|
||||
#elif defined(XP_UNIX) || defined(XP_OS2_EMX) || defined(XP_BEOS)
|
||||
#include <sys/time.h>
|
||||
#elif defined(WIN32)
|
||||
#include <windows.h>
|
||||
#elif defined(XP_OS2_VACPP)
|
||||
#include <sys/timeb.h>
|
||||
#else
|
||||
#error "Architecture not supported"
|
||||
#endif
|
||||
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
#if defined(OMIT_LIB_BUILD_TIME)
|
||||
/*
|
||||
* Some platforms don't have any 64-bit integer type
|
||||
* such as 'long long'. Because we can't use NSPR's
|
||||
* PR_snprintf in this program, it is difficult to
|
||||
* print a static initializer for PRInt64 (a struct).
|
||||
* So we print nothing. The makefiles that build the
|
||||
* shared libraries will detect the empty output string
|
||||
* of this program and omit the library build time
|
||||
* in PRVersionDescription.
|
||||
*/
|
||||
#elif defined(VMS)
|
||||
long long now;
|
||||
struct timeb b;
|
||||
ftime(&b);
|
||||
now = b.time;
|
||||
now *= 1000000;
|
||||
now += (1000 * b.millitm);
|
||||
fprintf(stdout, "%Ld", now);
|
||||
#elif defined(XP_UNIX) || defined(XP_OS2_EMX) || defined(XP_BEOS)
|
||||
long long now;
|
||||
struct timeval tv;
|
||||
#ifdef HAVE_SVID_GETTOD
|
||||
gettimeofday(&tv);
|
||||
#else
|
||||
gettimeofday(&tv, NULL);
|
||||
#endif
|
||||
now = ((1000000LL) * tv.tv_sec) + (long long)tv.tv_usec;
|
||||
#if defined(OSF1)
|
||||
fprintf(stdout, "%ld", now);
|
||||
#elif defined(BEOS) && defined(__POWERPC__)
|
||||
fprintf(stdout, "%Ld", now); /* Metroworks on BeOS PPC */
|
||||
#else
|
||||
fprintf(stdout, "%lld", now);
|
||||
#endif
|
||||
|
||||
#elif defined(WIN32)
|
||||
__int64 now;
|
||||
FILETIME ft;
|
||||
GetSystemTimeAsFileTime(&ft);
|
||||
CopyMemory(&now, &ft, sizeof(now));
|
||||
/*
|
||||
* 116444736000000000 is the number of 100-nanosecond intervals
|
||||
* between Jan. 1, 1601 and Jan. 1, 1970.
|
||||
*/
|
||||
#ifdef __GNUC__
|
||||
now = (now - 116444736000000000LL) / 10LL;
|
||||
fprintf(stdout, "%lld", now);
|
||||
#else
|
||||
now = (now - 116444736000000000i64) / 10i64;
|
||||
fprintf(stdout, "%I64d", now);
|
||||
#endif
|
||||
|
||||
#elif defined(XP_OS2_VACPP)
|
||||
/* no long long or i64 so we use a string */
|
||||
#include <string.h>
|
||||
char buf[24];
|
||||
char tbuf[7];
|
||||
time_t now;
|
||||
long mtime;
|
||||
int i;
|
||||
|
||||
struct timeb b;
|
||||
ftime(&b);
|
||||
now = b.time;
|
||||
_ltoa(now, buf, 10);
|
||||
|
||||
mtime = b.millitm * 1000;
|
||||
if (mtime == 0){
|
||||
++now;
|
||||
strcat(buf, "000000");
|
||||
} else {
|
||||
_ltoa(mtime, tbuf, 10);
|
||||
for (i = strlen(tbuf); i < 6; ++i)
|
||||
strcat(buf, "0");
|
||||
strcat(buf, tbuf);
|
||||
}
|
||||
fprintf(stdout, "%s", buf);
|
||||
|
||||
#else
|
||||
#error "Architecture not supported"
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
} /* main */
|
||||
|
||||
/* now.c */
|
||||
@@ -1,602 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla 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/MPL/
|
||||
*
|
||||
* 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 the Netscape Portable Runtime (NSPR).
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998-2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/*
|
||||
** Netscape portable install command.
|
||||
**
|
||||
** Brendan Eich, 7/20/95
|
||||
*/
|
||||
#include <stdio.h> /* OSF/1 requires this before grp.h, so put it first */
|
||||
#include <assert.h>
|
||||
#include <fcntl.h>
|
||||
#include <grp.h>
|
||||
#include <pwd.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <utime.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <dirent.h>
|
||||
#include <errno.h>
|
||||
#include <stdarg.h>
|
||||
#ifdef USE_REENTRANT_LIBC
|
||||
#include "libc_r.h"
|
||||
#endif /* USE_REENTRANT_LIBC */
|
||||
|
||||
#include "pathsub.h"
|
||||
|
||||
#define HAVE_FCHMOD
|
||||
|
||||
#if defined(BEOS)
|
||||
#undef HAVE_FCHMOD
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Does getcwd() take NULL as the first argument and malloc
|
||||
* the result buffer?
|
||||
*/
|
||||
#if !defined(DARWIN) && !defined(NEXTSTEP) && !defined(VMS)
|
||||
#define GETCWD_CAN_MALLOC
|
||||
#endif
|
||||
|
||||
#ifdef NEXTSTEP
|
||||
#include <bsd/libc.h>
|
||||
|
||||
/*
|
||||
** balazs.pataki@sztaki.hu: The getcwd is broken in NEXTSTEP (returns 0),
|
||||
** when called on a mounted fs. Did anyone notice this? Here's an ugly
|
||||
** workaround ...
|
||||
*/
|
||||
#define getcwd(b,s) my_getcwd(b,s)
|
||||
|
||||
static char *
|
||||
my_getcwd (char *buf, size_t size)
|
||||
{
|
||||
FILE *pwd = popen("pwd", "r");
|
||||
char *result = fgets(buf, size, pwd);
|
||||
|
||||
if (result) {
|
||||
buf[strlen(buf)-1] = '\0';
|
||||
}
|
||||
pclose (pwd);
|
||||
return buf;
|
||||
}
|
||||
#endif /* NEXTSTEP */
|
||||
|
||||
#ifdef LINUX
|
||||
#include <getopt.h>
|
||||
#endif
|
||||
|
||||
#if defined(SCO) || defined(UNIXWARE) || defined(SNI) || defined(NCR) || defined(NEC) || defined(NEXTSTEP)
|
||||
#if !defined(S_ISLNK) && defined(S_IFLNK)
|
||||
#define S_ISLNK(a) (((a) & S_IFMT) == S_IFLNK)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(SNI)
|
||||
extern int fchmod(int fildes, mode_t mode);
|
||||
#endif
|
||||
|
||||
#ifdef QNX
|
||||
#define d_ino d_stat.st_ino
|
||||
#endif
|
||||
|
||||
static void
|
||||
usage(void)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"usage: %s [-C cwd] [-L linkprefix] [-m mode] [-o owner] [-g group]\n"
|
||||
" %*s [-DdltR] file [file ...] directory\n",
|
||||
program, (int)strlen(program), "");
|
||||
exit(2);
|
||||
}
|
||||
|
||||
static int
|
||||
mkdirs(char *path, mode_t mode)
|
||||
{
|
||||
char *cp;
|
||||
struct stat sb;
|
||||
int res;
|
||||
|
||||
while (*path == '/' && path[1] == '/')
|
||||
path++;
|
||||
while ((cp = strrchr(path, '/')) && cp[1] == '\0')
|
||||
*cp = '\0';
|
||||
if (cp && cp != path) {
|
||||
*cp = '\0';
|
||||
if ((stat(path, &sb) < 0 || !S_ISDIR(sb.st_mode)) &&
|
||||
mkdirs(path, mode) < 0) {
|
||||
return -1;
|
||||
}
|
||||
*cp = '/';
|
||||
}
|
||||
res = mkdir(path, mode);
|
||||
if ((res != 0) && (errno == EEXIST))
|
||||
return 0;
|
||||
else
|
||||
return res;
|
||||
}
|
||||
|
||||
static uid_t
|
||||
touid(char *owner)
|
||||
{
|
||||
struct passwd *pw;
|
||||
uid_t uid;
|
||||
char *cp;
|
||||
|
||||
pw = getpwnam(owner);
|
||||
if (pw)
|
||||
return pw->pw_uid;
|
||||
uid = strtol(owner, &cp, 0);
|
||||
if (uid == 0 && cp == owner)
|
||||
fail("cannot find uid for %s", owner);
|
||||
return uid;
|
||||
}
|
||||
|
||||
static gid_t
|
||||
togid(char *group)
|
||||
{
|
||||
struct group *gr;
|
||||
gid_t gid;
|
||||
char *cp;
|
||||
|
||||
gr = getgrnam(group);
|
||||
if (gr)
|
||||
return gr->gr_gid;
|
||||
gid = strtol(group, &cp, 0);
|
||||
if (gid == 0 && cp == group)
|
||||
fail("cannot find gid for %s", group);
|
||||
return gid;
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
int onlydir, dodir, dolink, dorelsymlink, dotimes, opt, len, lplen, tdlen, bnlen, exists, fromfd, tofd, cc, wc;
|
||||
mode_t mode = 0755;
|
||||
char *linkprefix, *owner, *group, *cp, *cwd, *todir, *toname, *name, *base, *linkname, *bp, buf[BUFSIZ];
|
||||
uid_t uid;
|
||||
gid_t gid;
|
||||
struct stat sb, tosb;
|
||||
struct utimbuf utb;
|
||||
|
||||
program = argv[0];
|
||||
cwd = linkname = linkprefix = owner = group = 0;
|
||||
onlydir = dodir = dolink = dorelsymlink = dotimes = lplen = 0;
|
||||
|
||||
while ((opt = getopt(argc, argv, "C:DdlL:Rm:o:g:t")) != EOF) {
|
||||
switch (opt) {
|
||||
case 'C':
|
||||
cwd = optarg;
|
||||
break;
|
||||
case 'D':
|
||||
onlydir = 1;
|
||||
break;
|
||||
case 'd':
|
||||
dodir = 1;
|
||||
break;
|
||||
case 'l':
|
||||
dolink = 1;
|
||||
break;
|
||||
case 'L':
|
||||
linkprefix = optarg;
|
||||
lplen = strlen(linkprefix);
|
||||
dolink = 1;
|
||||
break;
|
||||
case 'R':
|
||||
dolink = dorelsymlink = 1;
|
||||
break;
|
||||
case 'm':
|
||||
mode = strtoul(optarg, &cp, 8);
|
||||
if (mode == 0 && cp == optarg)
|
||||
usage();
|
||||
break;
|
||||
case 'o':
|
||||
owner = optarg;
|
||||
break;
|
||||
case 'g':
|
||||
group = optarg;
|
||||
break;
|
||||
case 't':
|
||||
dotimes = 1;
|
||||
break;
|
||||
default:
|
||||
usage();
|
||||
}
|
||||
}
|
||||
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
if (argc < 2 - onlydir)
|
||||
usage();
|
||||
|
||||
todir = argv[argc-1];
|
||||
if ((stat(todir, &sb) < 0 || !S_ISDIR(sb.st_mode)) &&
|
||||
mkdirs(todir, 0777) < 0) {
|
||||
fail("cannot make directory %s", todir);
|
||||
}
|
||||
if (onlydir)
|
||||
return 0;
|
||||
|
||||
if (!cwd) {
|
||||
#ifdef GETCWD_CAN_MALLOC
|
||||
cwd = getcwd(0, PATH_MAX);
|
||||
#else
|
||||
cwd = malloc(PATH_MAX + 1);
|
||||
cwd = getcwd(cwd, PATH_MAX);
|
||||
#endif
|
||||
}
|
||||
xchdir(todir);
|
||||
#ifdef GETCWD_CAN_MALLOC
|
||||
todir = getcwd(0, PATH_MAX);
|
||||
#else
|
||||
todir = malloc(PATH_MAX + 1);
|
||||
todir = getcwd(todir, PATH_MAX);
|
||||
#endif
|
||||
tdlen = strlen(todir);
|
||||
xchdir(cwd);
|
||||
tdlen = strlen(todir);
|
||||
|
||||
uid = owner ? touid(owner) : -1;
|
||||
gid = group ? togid(group) : -1;
|
||||
|
||||
while (--argc > 0) {
|
||||
name = *argv++;
|
||||
len = strlen(name);
|
||||
base = xbasename(name);
|
||||
bnlen = strlen(base);
|
||||
toname = (char*)xmalloc(tdlen + 1 + bnlen + 1);
|
||||
sprintf(toname, "%s/%s", todir, base);
|
||||
exists = (lstat(toname, &tosb) == 0);
|
||||
|
||||
if (dodir) {
|
||||
/* -d means create a directory, always */
|
||||
if (exists && !S_ISDIR(tosb.st_mode)) {
|
||||
(void) unlink(toname);
|
||||
exists = 0;
|
||||
}
|
||||
if (!exists && mkdir(toname, mode) < 0)
|
||||
fail("cannot make directory %s", toname);
|
||||
if ((owner || group) && chown(toname, uid, gid) < 0)
|
||||
fail("cannot change owner of %s", toname);
|
||||
} else if (dolink) {
|
||||
if (*name == '/') {
|
||||
/* source is absolute pathname, link to it directly */
|
||||
linkname = 0;
|
||||
} else {
|
||||
if (linkprefix) {
|
||||
/* -L implies -l and prefixes names with a $cwd arg. */
|
||||
len += lplen + 1;
|
||||
linkname = (char*)xmalloc(len + 1);
|
||||
sprintf(linkname, "%s/%s", linkprefix, name);
|
||||
} else if (dorelsymlink) {
|
||||
/* Symlink the relative path from todir to source name. */
|
||||
linkname = (char*)xmalloc(PATH_MAX);
|
||||
|
||||
if (*todir == '/') {
|
||||
/* todir is absolute: skip over common prefix. */
|
||||
lplen = relatepaths(todir, cwd, linkname);
|
||||
strcpy(linkname + lplen, name);
|
||||
} else {
|
||||
/* todir is named by a relative path: reverse it. */
|
||||
reversepath(todir, name, len, linkname);
|
||||
xchdir(cwd);
|
||||
}
|
||||
|
||||
len = strlen(linkname);
|
||||
}
|
||||
name = linkname;
|
||||
}
|
||||
|
||||
/* Check for a pre-existing symlink with identical content. */
|
||||
if (exists &&
|
||||
(!S_ISLNK(tosb.st_mode) ||
|
||||
readlink(toname, buf, sizeof buf) != len ||
|
||||
strncmp(buf, name, len) != 0)) {
|
||||
(void) (S_ISDIR(tosb.st_mode) ? rmdir : unlink)(toname);
|
||||
exists = 0;
|
||||
}
|
||||
if (!exists && symlink(name, toname) < 0)
|
||||
fail("cannot make symbolic link %s", toname);
|
||||
#ifdef HAVE_LCHOWN
|
||||
if ((owner || group) && lchown(toname, uid, gid) < 0)
|
||||
fail("cannot change owner of %s", toname);
|
||||
#endif
|
||||
|
||||
if (linkname) {
|
||||
free(linkname);
|
||||
linkname = 0;
|
||||
}
|
||||
} else {
|
||||
/* Copy from name to toname, which might be the same file. */
|
||||
fromfd = open(name, O_RDONLY);
|
||||
if (fromfd < 0 || fstat(fromfd, &sb) < 0)
|
||||
fail("cannot access %s", name);
|
||||
if (exists && (!S_ISREG(tosb.st_mode) || access(toname, W_OK) < 0))
|
||||
(void) (S_ISDIR(tosb.st_mode) ? rmdir : unlink)(toname);
|
||||
tofd = open(toname, O_CREAT | O_WRONLY, 0666);
|
||||
if (tofd < 0)
|
||||
fail("cannot create %s", toname);
|
||||
|
||||
bp = buf;
|
||||
while ((cc = read(fromfd, bp, sizeof buf)) > 0) {
|
||||
while ((wc = write(tofd, bp, cc)) > 0) {
|
||||
if ((cc -= wc) == 0)
|
||||
break;
|
||||
bp += wc;
|
||||
}
|
||||
if (wc < 0)
|
||||
fail("cannot write to %s", toname);
|
||||
}
|
||||
if (cc < 0)
|
||||
fail("cannot read from %s", name);
|
||||
|
||||
if (ftruncate(tofd, sb.st_size) < 0)
|
||||
fail("cannot truncate %s", toname);
|
||||
/*
|
||||
** On OpenVMS we can't chmod() until the file is closed, and we
|
||||
** have to utime() last since fchown/chmod alter the timestamps.
|
||||
*/
|
||||
#ifndef VMS
|
||||
if (dotimes) {
|
||||
utb.actime = sb.st_atime;
|
||||
utb.modtime = sb.st_mtime;
|
||||
if (utime(toname, &utb) < 0)
|
||||
fail("cannot set times of %s", toname);
|
||||
}
|
||||
#ifdef HAVE_FCHMOD
|
||||
if (fchmod(tofd, mode) < 0)
|
||||
#else
|
||||
if (chmod(toname, mode) < 0)
|
||||
#endif
|
||||
fail("cannot change mode of %s", toname);
|
||||
#endif
|
||||
if ((owner || group) && fchown(tofd, uid, gid) < 0)
|
||||
fail("cannot change owner of %s", toname);
|
||||
|
||||
/* Must check for delayed (NFS) write errors on close. */
|
||||
if (close(tofd) < 0)
|
||||
fail("cannot write to %s", toname);
|
||||
close(fromfd);
|
||||
#ifdef VMS
|
||||
if (chmod(toname, mode) < 0)
|
||||
fail("cannot change mode of %s", toname);
|
||||
if (dotimes) {
|
||||
utb.actime = sb.st_atime;
|
||||
utb.modtime = sb.st_mtime;
|
||||
if (utime(toname, &utb) < 0)
|
||||
fail("cannot set times of %s", toname);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
free(toname);
|
||||
}
|
||||
|
||||
free(cwd);
|
||||
free(todir);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
** Pathname subroutines.
|
||||
**
|
||||
** Brendan Eich, 8/29/95
|
||||
*/
|
||||
|
||||
char *program;
|
||||
|
||||
void
|
||||
fail(char *format, ...)
|
||||
{
|
||||
int error;
|
||||
va_list ap;
|
||||
|
||||
#ifdef USE_REENTRANT_LIBC
|
||||
R_STRERROR_INIT_R();
|
||||
#endif
|
||||
|
||||
error = errno;
|
||||
fprintf(stderr, "%s: ", program);
|
||||
va_start(ap, format);
|
||||
vfprintf(stderr, format, ap);
|
||||
va_end(ap);
|
||||
if (error)
|
||||
|
||||
#ifdef USE_REENTRANT_LIBC
|
||||
R_STRERROR_R(errno);
|
||||
fprintf(stderr, ": %s", r_strerror_r);
|
||||
#else
|
||||
fprintf(stderr, ": %s", strerror(errno));
|
||||
#endif
|
||||
|
||||
putc('\n', stderr);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
char *
|
||||
getcomponent(char *path, char *name)
|
||||
{
|
||||
if (*path == '\0')
|
||||
return 0;
|
||||
if (*path == '/') {
|
||||
*name++ = '/';
|
||||
} else {
|
||||
do {
|
||||
*name++ = *path++;
|
||||
} while (*path != '/' && *path != '\0');
|
||||
}
|
||||
*name = '\0';
|
||||
while (*path == '/')
|
||||
path++;
|
||||
return path;
|
||||
}
|
||||
|
||||
#ifdef UNIXWARE_READDIR_BUFFER_TOO_SMALL
|
||||
/* Sigh. The static buffer in Unixware's readdir is too small. */
|
||||
struct dirent * readdir(DIR *d)
|
||||
{
|
||||
static struct dirent *buf = NULL;
|
||||
#define MAX_PATH_LEN 1024
|
||||
|
||||
|
||||
if(buf == NULL)
|
||||
buf = (struct dirent *) malloc(sizeof(struct dirent) + MAX_PATH_LEN)
|
||||
;
|
||||
return(readdir_r(d, buf));
|
||||
}
|
||||
#endif
|
||||
|
||||
char *
|
||||
ino2name(ino_t ino, char *dir)
|
||||
{
|
||||
DIR *dp;
|
||||
struct dirent *ep;
|
||||
char *name;
|
||||
|
||||
dp = opendir("..");
|
||||
if (!dp)
|
||||
fail("cannot read parent directory");
|
||||
for (;;) {
|
||||
if (!(ep = readdir(dp)))
|
||||
fail("cannot find current directory");
|
||||
if (ep->d_ino == ino)
|
||||
break;
|
||||
}
|
||||
name = xstrdup(ep->d_name);
|
||||
closedir(dp);
|
||||
return name;
|
||||
}
|
||||
|
||||
void *
|
||||
xmalloc(size_t size)
|
||||
{
|
||||
void *p = malloc(size);
|
||||
if (!p)
|
||||
fail("cannot allocate %u bytes", size);
|
||||
return p;
|
||||
}
|
||||
|
||||
char *
|
||||
xstrdup(char *s)
|
||||
{
|
||||
return strcpy((char*)xmalloc(strlen(s) + 1), s);
|
||||
}
|
||||
|
||||
char *
|
||||
xbasename(char *path)
|
||||
{
|
||||
char *cp;
|
||||
|
||||
while ((cp = strrchr(path, '/')) && cp[1] == '\0')
|
||||
*cp = '\0';
|
||||
if (!cp) return path;
|
||||
return cp + 1;
|
||||
}
|
||||
|
||||
void
|
||||
xchdir(char *dir)
|
||||
{
|
||||
if (chdir(dir) < 0)
|
||||
fail("cannot change directory to %s", dir);
|
||||
}
|
||||
|
||||
int
|
||||
relatepaths(char *from, char *to, char *outpath)
|
||||
{
|
||||
char *cp, *cp2;
|
||||
int len;
|
||||
char buf[NAME_MAX];
|
||||
|
||||
assert(*from == '/' && *to == '/');
|
||||
for (cp = to, cp2 = from; *cp == *cp2; cp++, cp2++)
|
||||
if (*cp == '\0')
|
||||
break;
|
||||
while (cp[-1] != '/')
|
||||
cp--, cp2--;
|
||||
if (cp - 1 == to) {
|
||||
/* closest common ancestor is /, so use full pathname */
|
||||
len = strlen(strcpy(outpath, to));
|
||||
if (outpath[len] != '/') {
|
||||
outpath[len++] = '/';
|
||||
outpath[len] = '\0';
|
||||
}
|
||||
} else {
|
||||
len = 0;
|
||||
while ((cp2 = getcomponent(cp2, buf)) != 0) {
|
||||
strcpy(outpath + len, "../");
|
||||
len += 3;
|
||||
}
|
||||
while ((cp = getcomponent(cp, buf)) != 0) {
|
||||
sprintf(outpath + len, "%s/", buf);
|
||||
len += strlen(outpath + len);
|
||||
}
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
void
|
||||
reversepath(char *inpath, char *name, int len, char *outpath)
|
||||
{
|
||||
char *cp, *cp2;
|
||||
char buf[NAME_MAX];
|
||||
struct stat sb;
|
||||
|
||||
cp = strcpy(outpath + PATH_MAX - (len + 1), name);
|
||||
cp2 = inpath;
|
||||
while ((cp2 = getcomponent(cp2, buf)) != 0) {
|
||||
if (strcmp(buf, ".") == 0)
|
||||
continue;
|
||||
if (strcmp(buf, "..") == 0) {
|
||||
if (stat(".", &sb) < 0)
|
||||
fail("cannot stat current directory");
|
||||
name = ino2name(sb.st_ino, "..");
|
||||
len = strlen(name);
|
||||
cp -= len + 1;
|
||||
strcpy(cp, name);
|
||||
cp[len] = '/';
|
||||
free(name);
|
||||
xchdir("..");
|
||||
} else {
|
||||
cp -= 3;
|
||||
strncpy(cp, "../", 3);
|
||||
xchdir(buf);
|
||||
}
|
||||
}
|
||||
strcpy(outpath, cp);
|
||||
}
|
||||
@@ -1,143 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
prefix=@prefix@
|
||||
|
||||
major_version=@MOD_MAJOR_VERSION@
|
||||
minor_version=@MOD_MINOR_VERSION@
|
||||
patch_version=@MOD_PATCH_VERSION@
|
||||
|
||||
usage()
|
||||
{
|
||||
cat <<EOF
|
||||
Usage: nspr-config [OPTIONS] [LIBRARIES]
|
||||
Options:
|
||||
[--prefix[=DIR]]
|
||||
[--exec-prefix[=DIR]]
|
||||
[--includedir[=DIR]]
|
||||
[--libdir[=DIR]]
|
||||
[--version]
|
||||
[--libs]
|
||||
[--cflags]
|
||||
Libraries:
|
||||
nspr
|
||||
plc
|
||||
plds
|
||||
EOF
|
||||
exit $1
|
||||
}
|
||||
|
||||
if test $# -eq 0; then
|
||||
usage 1 1>&2
|
||||
fi
|
||||
|
||||
lib_nspr=yes
|
||||
lib_plc=yes
|
||||
lib_plds=yes
|
||||
|
||||
while test $# -gt 0; do
|
||||
case "$1" in
|
||||
-*=*) optarg=`echo "$1" | sed 's/[-_a-zA-Z0-9]*=//'` ;;
|
||||
*) optarg= ;;
|
||||
esac
|
||||
|
||||
case $1 in
|
||||
--prefix=*)
|
||||
prefix=$optarg
|
||||
;;
|
||||
--prefix)
|
||||
echo_prefix=yes
|
||||
;;
|
||||
--exec-prefix=*)
|
||||
exec_prefix=$optarg
|
||||
;;
|
||||
--exec-prefix)
|
||||
echo_exec_prefix=yes
|
||||
;;
|
||||
--includedir=*)
|
||||
includedir=$optarg
|
||||
;;
|
||||
--includedir)
|
||||
echo_includedir=yes
|
||||
;;
|
||||
--libdir=*)
|
||||
libdir=$optarg
|
||||
;;
|
||||
--libdir)
|
||||
echo_libdir=yes
|
||||
;;
|
||||
--version)
|
||||
echo ${major_version}.${minor_version}.${patch_version}
|
||||
;;
|
||||
--cflags)
|
||||
echo_cflags=yes
|
||||
;;
|
||||
--libs)
|
||||
echo_libs=yes
|
||||
;;
|
||||
nspr)
|
||||
lib_nspr=yes
|
||||
;;
|
||||
plc)
|
||||
lib_plc=yes
|
||||
;;
|
||||
plds)
|
||||
lib_plds=yes
|
||||
;;
|
||||
*)
|
||||
usage 1 1>&2
|
||||
;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
# Set variables that may be dependent upon other variables
|
||||
if test -z "$exec_prefix"; then
|
||||
exec_prefix=@exec_prefix@
|
||||
fi
|
||||
if test -z "$includedir"; then
|
||||
includedir=@includedir@
|
||||
fi
|
||||
if test -z "$libdir"; then
|
||||
libdir=@libdir@
|
||||
fi
|
||||
|
||||
if test "$echo_prefix" = "yes"; then
|
||||
echo $prefix
|
||||
fi
|
||||
|
||||
if test "$echo_exec_prefix" = "yes"; then
|
||||
echo $exec_prefix
|
||||
fi
|
||||
|
||||
if test "$echo_includedir" = "yes"; then
|
||||
echo $includedir
|
||||
fi
|
||||
|
||||
if test "$echo_libdir" = "yes"; then
|
||||
echo $libdir
|
||||
fi
|
||||
|
||||
if test "$echo_cflags" = "yes"; then
|
||||
echo -I$includedir
|
||||
fi
|
||||
|
||||
if test "$echo_libs" = "yes"; then
|
||||
libdirs=-L$libdir
|
||||
if test -n "$lib_plds"; then
|
||||
libdirs="$libdirs -lplds${major_version}"
|
||||
fi
|
||||
if test -n "$lib_plc"; then
|
||||
libdirs="$libdirs -lplc${major_version}"
|
||||
fi
|
||||
if test -n "$lib_nspr"; then
|
||||
libdirs="$libdirs -lnspr${major_version}"
|
||||
fi
|
||||
os_ldflags="@LDFLAGS@"
|
||||
for i in $os_ldflags ; do
|
||||
if echo $i | grep \^-L >/dev/null; then
|
||||
libdirs="$libdirs $i"
|
||||
fi
|
||||
done
|
||||
echo $libdirs @OS_LIBS@
|
||||
fi
|
||||
|
||||
@@ -1,67 +0,0 @@
|
||||
# -*- tab-width: 4; -*-
|
||||
# Configure paths for NSPR
|
||||
# Public domain - Chris Seawood <cls@seawood.org> 2001-04-05
|
||||
# Based upon gtk.m4 (also PD) by Owen Taylor
|
||||
|
||||
dnl AM_PATH_NSPR([MINIMUM-VERSION, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]])
|
||||
dnl Test for NSPR, and define NSPR_CFLAGS and NSPR_LIBS
|
||||
AC_DEFUN(AM_PATH_NSPR,
|
||||
[dnl
|
||||
|
||||
AC_ARG_WITH(nspr-prefix,
|
||||
[ --with-nspr-prefix=PFX Prefix where NSPR is installed],
|
||||
nspr_config_prefix="$withval",
|
||||
nspr_config_prefix="")
|
||||
|
||||
AC_ARG_WITH(nspr-exec-prefix,
|
||||
[ --with-nspr-exec-prefix=PFX
|
||||
Exec prefix where NSPR is installed],
|
||||
nspr_config_exec_prefix="$withval",
|
||||
nspr_config_exec_prefix="")
|
||||
|
||||
if test -n "$nspr_config_exec_prefix"; then
|
||||
nspr_config_args="$nspr_config_args --exec-prefix=$nspr_config_exec_prefix"
|
||||
if test -z "$NSPR_CONFIG"; then
|
||||
NSPR_CONFIG=$nspr_config_exec_prefix/bin/nspr-config
|
||||
fi
|
||||
fi
|
||||
if test -n "$nspr_config_prefix"; then
|
||||
nspr_config_args="$nspr_config_args --prefix=$nspr_config_prefix"
|
||||
if test -z "$NSPR_CONFIG"; then
|
||||
NSPR_CONFIG=$nspr_config_prefix/bin/nspr-config
|
||||
fi
|
||||
fi
|
||||
|
||||
unset ac_cv_path_NSPR_CONFIG
|
||||
AC_PATH_PROG(NSPR_CONFIG, nspr-config, no)
|
||||
min_nspr_version=ifelse([$1], ,4.0.0,$1)
|
||||
AC_MSG_CHECKING(for NSPR - version >= $min_nspr_version (skipping))
|
||||
|
||||
no_nspr=""
|
||||
if test "$NSPR_CONFIG" = "no"; then
|
||||
no_nspr="yes"
|
||||
else
|
||||
NSPR_CFLAGS=`$NSPR_CONFIG $nspr_config_args --cflags`
|
||||
NSPR_LIBS=`$NSPR_CONFIG $nspr_config_args --libs`
|
||||
|
||||
dnl Skip version check for now
|
||||
nspr_config_major_version=`$NSPR_CONFIG $nspr_config_args --version | \
|
||||
sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'`
|
||||
nspr_config_minor_version=`$NSPR_CONFIG $nspr_config_args --version | \
|
||||
sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'`
|
||||
nspr_config_micro_version=`$NSPR_CONFIG $nspr_config_args --version | \
|
||||
sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'`
|
||||
fi
|
||||
|
||||
if test -z "$no_nspr"; then
|
||||
AC_MSG_RESULT(yes)
|
||||
ifelse([$2], , :, [$2])
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
fi
|
||||
|
||||
|
||||
AC_SUBST(NSPR_CFLAGS)
|
||||
AC_SUBST(NSPR_LIBS)
|
||||
|
||||
])
|
||||
@@ -1,5 +0,0 @@
|
||||
# Include in Makefiles to define NSPR variables
|
||||
|
||||
NSPR_VERSION = @NSPR_VERSION@
|
||||
NSPR_LIB = -lnspr@NSPR_VERSION@
|
||||
NSPR_EXTRA_LIBS = @EXTRA_LIBS@
|
||||
@@ -1,5 +0,0 @@
|
||||
# Include in shell scripts to define NSPR variables
|
||||
|
||||
NSPR_VERSION=@NSPR_VERSION@
|
||||
NSPR_LIB=-lnspr$NSPR_VERSION
|
||||
NSPR_EXTRA_LIBS="@EXTRA_LIBS@"
|
||||
@@ -1,78 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla 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/MPL/
|
||||
*
|
||||
* 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 the Netscape Portable Runtime (NSPR).
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998-2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef pathsub_h___
|
||||
#define pathsub_h___
|
||||
/*
|
||||
** Pathname subroutines.
|
||||
**
|
||||
** Brendan Eich, 8/29/95
|
||||
*/
|
||||
#include <limits.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#if SUNOS4
|
||||
#include "../pr/include/md/sunos4.h"
|
||||
#endif
|
||||
|
||||
#ifndef PATH_MAX
|
||||
#define PATH_MAX 1024
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Just prevent stupidity
|
||||
*/
|
||||
#undef NAME_MAX
|
||||
#define NAME_MAX 256
|
||||
|
||||
extern char *program;
|
||||
|
||||
extern void fail(char *format, ...);
|
||||
extern char *getcomponent(char *path, char *name);
|
||||
extern char *ino2name(ino_t ino, char *dir);
|
||||
extern void *xmalloc(size_t size);
|
||||
extern char *xstrdup(char *s);
|
||||
extern char *xbasename(char *path);
|
||||
extern void xchdir(char *dir);
|
||||
|
||||
/* Relate absolute pathnames from and to returning the result in outpath. */
|
||||
extern int relatepaths(char *from, char *to, char *outpath);
|
||||
|
||||
/* XXX changes current working directory -- caveat emptor */
|
||||
extern void reversepath(char *inpath, char *name, int len, char *outpath);
|
||||
|
||||
#endif /* pathsub_h___ */
|
||||
@@ -1,44 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla 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/MPL/
|
||||
*
|
||||
* 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 the Netscape Portable Runtime (NSPR).
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/*
|
||||
* A dummy header file that is a dependency for all the object files.
|
||||
* Used to force a full recompilation of NSPR in Mozilla's Tinderbox
|
||||
* depend builds. See comments in rules.mk.
|
||||
*/
|
||||
|
||||
#error "Do not include this header file."
|
||||
@@ -1,38 +0,0 @@
|
||||
REM
|
||||
REM ***** BEGIN LICENSE BLOCK *****
|
||||
REM Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
REM
|
||||
REM The contents of this file are subject to the Mozilla Public License Version
|
||||
REM 1.1 (the "License"); you may not use this file except in compliance with
|
||||
REM the License. You may obtain a copy of the License at
|
||||
REM http://www.mozilla.org/MPL/
|
||||
REM
|
||||
REM Software distributed under the License is distributed on an "AS IS" basis,
|
||||
REM WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
REM for the specific language governing rights and limitations under the
|
||||
REM License.
|
||||
REM
|
||||
REM The Original Code is the Netscape Portable Runtime (NSPR).
|
||||
REM
|
||||
REM The Initial Developer of the Original Code is
|
||||
REM Netscape Communications Corporation.
|
||||
REM Portions created by the Initial Developer are Copyright (C) 1998-2000
|
||||
REM the Initial Developer. All Rights Reserved.
|
||||
REM
|
||||
REM Contributor(s):
|
||||
REM
|
||||
REM Alternatively, the contents of this file may be used under the terms of
|
||||
REM either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
REM the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
REM in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
REM of those above. If you wish to allow use of your version of this file only
|
||||
REM under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
REM use your version of this file under the terms of the MPL, indicate your
|
||||
REM decision by deleting the provisions above and replace them with the notice
|
||||
REM and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
REM the provisions above, a recipient may use your version of this file under
|
||||
REM the terms of any one of the MPL, the GPL or the LGPL.
|
||||
REM
|
||||
REM ***** END LICENSE BLOCK *****
|
||||
|
||||
mkdir %1
|
||||
@@ -1,515 +0,0 @@
|
||||
#! gmake
|
||||
#
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla 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/MPL/
|
||||
#
|
||||
# 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 the Netscape Portable Runtime (NSPR).
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Netscape Communications Corporation.
|
||||
# Portions created by the Initial Developer are Copyright (C) 1998-2000
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
################################################################################
|
||||
# We have a 4 pass build process:
|
||||
#
|
||||
# Pass 1. export - Create generated headers and stubs. Publish public headers to
|
||||
# dist/<arch>/include.
|
||||
#
|
||||
# Pass 2. libs - Create libraries. Publish libraries to dist/<arch>/lib.
|
||||
#
|
||||
# Pass 3. all - Create programs.
|
||||
#
|
||||
# Pass 4. install - Publish programs to dist/<arch>/bin.
|
||||
#
|
||||
# Parameters to this makefile (set these before including):
|
||||
#
|
||||
# a)
|
||||
# TARGETS -- the target to create
|
||||
# (defaults to $LIBRARY $PROGRAM)
|
||||
# b)
|
||||
# DIRS -- subdirectories for make to recurse on
|
||||
# (the 'all' rule builds $TARGETS $DIRS)
|
||||
# c)
|
||||
# CSRCS -- .c files to compile
|
||||
# (used to define $OBJS)
|
||||
# d)
|
||||
# PROGRAM -- the target program name to create from $OBJS
|
||||
# ($OBJDIR automatically prepended to it)
|
||||
# e)
|
||||
# LIBRARY -- the target library name to create from $OBJS
|
||||
# ($OBJDIR automatically prepended to it)
|
||||
#
|
||||
################################################################################
|
||||
|
||||
ifndef topsrcdir
|
||||
topsrcdir=$(MOD_DEPTH)
|
||||
endif
|
||||
|
||||
ifndef srcdir
|
||||
srcdir=.
|
||||
endif
|
||||
|
||||
ifndef NSPR_CONFIG_MK
|
||||
include $(topsrcdir)/config/config.mk
|
||||
endif
|
||||
|
||||
ifdef USE_AUTOCONF
|
||||
ifdef CROSS_COMPILE
|
||||
ifdef INTERNAL_TOOLS
|
||||
CC=$(HOST_CC)
|
||||
CCC=$(HOST_CXX)
|
||||
CFLAGS=$(HOST_CFLAGS)
|
||||
CXXFLAGS=$(HOST_CXXFLAGS)
|
||||
LDFLAGS=$(HOST_LDFLAGS)
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
#
|
||||
# This makefile contains rules for building the following kinds of
|
||||
# libraries:
|
||||
# - LIBRARY: a static (archival) library
|
||||
# - SHARED_LIBRARY: a shared (dynamic link) library
|
||||
# - IMPORT_LIBRARY: an import library, used only on Windows and OS/2
|
||||
#
|
||||
# The names of these libraries can be generated by simply specifying
|
||||
# LIBRARY_NAME and LIBRARY_VERSION.
|
||||
#
|
||||
|
||||
ifdef LIBRARY_NAME
|
||||
ifeq (,$(filter-out WINNT OS2,$(OS_ARCH)))
|
||||
|
||||
#
|
||||
# Win95, Win16, and OS/2 require library names conforming to the 8.3 rule.
|
||||
# other platforms do not.
|
||||
#
|
||||
ifeq (,$(filter-out WIN95 OS2,$(OS_TARGET)))
|
||||
LIBRARY = $(OBJDIR)/$(LIBRARY_NAME)$(LIBRARY_VERSION)_s.$(LIB_SUFFIX)
|
||||
SHARED_LIBRARY = $(OBJDIR)/$(LIBRARY_NAME)$(LIBRARY_VERSION).$(DLL_SUFFIX)
|
||||
IMPORT_LIBRARY = $(OBJDIR)/$(LIBRARY_NAME)$(LIBRARY_VERSION).$(LIB_SUFFIX)
|
||||
SHARED_LIB_PDB = $(OBJDIR)/$(LIBRARY_NAME)$(LIBRARY_VERSION).pdb
|
||||
else
|
||||
LIBRARY = $(OBJDIR)/lib$(LIBRARY_NAME)$(LIBRARY_VERSION)_s.$(LIB_SUFFIX)
|
||||
SHARED_LIBRARY = $(OBJDIR)/lib$(LIBRARY_NAME)$(LIBRARY_VERSION).$(DLL_SUFFIX)
|
||||
IMPORT_LIBRARY = $(OBJDIR)/lib$(LIBRARY_NAME)$(LIBRARY_VERSION).$(LIB_SUFFIX)
|
||||
SHARED_LIB_PDB = $(OBJDIR)/lib$(LIBRARY_NAME)$(LIBRARY_VERSION).pdb
|
||||
endif
|
||||
|
||||
else
|
||||
|
||||
LIBRARY = $(OBJDIR)/lib$(LIBRARY_NAME)$(LIBRARY_VERSION).$(LIB_SUFFIX)
|
||||
ifeq ($(OS_ARCH)$(OS_RELEASE), AIX4.1)
|
||||
SHARED_LIBRARY = $(OBJDIR)/lib$(LIBRARY_NAME)$(LIBRARY_VERSION)_shr.a
|
||||
else
|
||||
ifdef MKSHLIB
|
||||
SHARED_LIBRARY = $(OBJDIR)/lib$(LIBRARY_NAME)$(LIBRARY_VERSION).$(DLL_SUFFIX)
|
||||
endif
|
||||
endif
|
||||
|
||||
endif
|
||||
endif
|
||||
|
||||
ifndef TARGETS
|
||||
ifeq (,$(filter-out WINNT OS2,$(OS_ARCH)))
|
||||
TARGETS = $(LIBRARY) $(SHARED_LIBRARY) $(IMPORT_LIBRARY)
|
||||
ifndef BUILD_OPT
|
||||
ifdef MSC_VER
|
||||
ifneq (,$(filter-out 1100 1200,$(MSC_VER)))
|
||||
TARGETS += $(SHARED_LIB_PDB)
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
else
|
||||
TARGETS = $(LIBRARY) $(SHARED_LIBRARY)
|
||||
endif
|
||||
endif
|
||||
|
||||
#
|
||||
# OBJS is the list of object files. It can be constructed by
|
||||
# specifying CSRCS (list of C source files) and ASFILES (list
|
||||
# of assembly language source files).
|
||||
#
|
||||
|
||||
ifndef OBJS
|
||||
OBJS = $(addprefix $(OBJDIR)/,$(CSRCS:.c=.$(OBJ_SUFFIX))) \
|
||||
$(addprefix $(OBJDIR)/,$(ASFILES:.$(ASM_SUFFIX)=.$(OBJ_SUFFIX)))
|
||||
endif
|
||||
|
||||
ifeq ($(MOZ_OS2_TOOLS),VACPP)
|
||||
EXTRA_LIBS := $(patsubst -l%,$(DIST)/lib/%.$(LIB_SUFFIX),$(EXTRA_LIBS))
|
||||
endif
|
||||
|
||||
ALL_TRASH = $(TARGETS) $(OBJS) $(RES) $(filter-out . .., $(OBJDIR)) LOGS TAGS $(GARBAGE) \
|
||||
$(NOSUCHFILE) \
|
||||
so_locations
|
||||
|
||||
ifeq ($(OS_ARCH),OpenVMS)
|
||||
ALL_TRASH += $(wildcard *.c*_defines)
|
||||
ifdef SHARED_LIBRARY
|
||||
VMS_SYMVEC_FILE = $(SHARED_LIBRARY:.$(DLL_SUFFIX)=_symvec.opt)
|
||||
VMS_SYMVEC_FILE_MODULE = $(srcdir)/$(LIBRARY_NAME)_symvec.opt
|
||||
ALL_TRASH += $(VMS_SYMVEC_FILE)
|
||||
endif
|
||||
endif
|
||||
|
||||
ifndef RELEASE_LIBS_DEST
|
||||
RELEASE_LIBS_DEST = $(RELEASE_LIB_DIR)
|
||||
endif
|
||||
|
||||
ifdef DIRS
|
||||
LOOP_OVER_DIRS = \
|
||||
@for d in $(DIRS); do \
|
||||
if test -d $$d; then \
|
||||
set -e; \
|
||||
echo "cd $$d; $(MAKE) $@"; \
|
||||
$(MAKE) -C $$d $@; \
|
||||
set +e; \
|
||||
else \
|
||||
echo "Skipping non-directory $$d..."; \
|
||||
fi; \
|
||||
done
|
||||
endif
|
||||
|
||||
################################################################################
|
||||
|
||||
all:: export
|
||||
|
||||
export::
|
||||
+$(LOOP_OVER_DIRS)
|
||||
|
||||
libs:: export
|
||||
|
||||
install:: export
|
||||
|
||||
clean::
|
||||
rm -rf $(OBJS) $(RES) so_locations $(NOSUCHFILE) $(GARBAGE)
|
||||
+$(LOOP_OVER_DIRS)
|
||||
|
||||
clobber::
|
||||
rm -rf $(OBJS) $(RES) $(TARGETS) $(filter-out . ..,$(OBJDIR)) $(GARBAGE) so_locations $(NOSUCHFILE)
|
||||
+$(LOOP_OVER_DIRS)
|
||||
|
||||
realclean clobber_all::
|
||||
rm -rf $(wildcard *.OBJ *.OBJD) dist $(ALL_TRASH)
|
||||
+$(LOOP_OVER_DIRS)
|
||||
|
||||
distclean::
|
||||
rm -rf $(wildcard *.OBJ *.OBJD) dist $(ALL_TRASH) $(DIST_GARBAGE)
|
||||
+$(LOOP_OVER_DIRS)
|
||||
|
||||
real_install:: $(RELEASE_BINS) $(RELEASE_HEADERS) $(RELEASE_LIBS)
|
||||
ifdef RELEASE_BINS
|
||||
$(NSINSTALL) -t -m 0755 $(RELEASE_BINS) $(DESTDIR)$(bindir)
|
||||
endif
|
||||
ifdef RELEASE_HEADERS
|
||||
$(NSINSTALL) -t -m 0644 $(RELEASE_HEADERS) $(DESTDIR)$(includedir)/$(include_subdir)
|
||||
endif
|
||||
ifdef RELEASE_LIBS
|
||||
$(NSINSTALL) -t -m 0755 $(RELEASE_LIBS) $(DESTDIR)$(libdir)/$(lib_subdir)
|
||||
endif
|
||||
+$(LOOP_OVER_DIRS)
|
||||
|
||||
release:: export
|
||||
ifdef RELEASE_BINS
|
||||
@echo "Copying executable programs and scripts to release directory"
|
||||
@if test -z "$(BUILD_NUMBER)"; then \
|
||||
echo "BUILD_NUMBER must be defined"; \
|
||||
false; \
|
||||
else \
|
||||
true; \
|
||||
fi
|
||||
@if test ! -d $(RELEASE_BIN_DIR); then \
|
||||
rm -rf $(RELEASE_BIN_DIR); \
|
||||
$(NSINSTALL) -D $(RELEASE_BIN_DIR);\
|
||||
else \
|
||||
true; \
|
||||
fi
|
||||
cp $(RELEASE_BINS) $(RELEASE_BIN_DIR)
|
||||
endif
|
||||
ifdef RELEASE_LIBS
|
||||
@echo "Copying libraries to release directory"
|
||||
@if test -z "$(BUILD_NUMBER)"; then \
|
||||
echo "BUILD_NUMBER must be defined"; \
|
||||
false; \
|
||||
else \
|
||||
true; \
|
||||
fi
|
||||
@if test ! -d $(RELEASE_LIBS_DEST); then \
|
||||
rm -rf $(RELEASE_LIBS_DEST); \
|
||||
$(NSINSTALL) -D $(RELEASE_LIBS_DEST);\
|
||||
else \
|
||||
true; \
|
||||
fi
|
||||
cp $(RELEASE_LIBS) $(RELEASE_LIBS_DEST)
|
||||
endif
|
||||
ifdef RELEASE_HEADERS
|
||||
@echo "Copying header files to release directory"
|
||||
@if test -z "$(BUILD_NUMBER)"; then \
|
||||
echo "BUILD_NUMBER must be defined"; \
|
||||
false; \
|
||||
else \
|
||||
true; \
|
||||
fi
|
||||
@if test ! -d $(RELEASE_HEADERS_DEST); then \
|
||||
rm -rf $(RELEASE_HEADERS_DEST); \
|
||||
$(NSINSTALL) -D $(RELEASE_HEADERS_DEST);\
|
||||
else \
|
||||
true; \
|
||||
fi
|
||||
cp $(RELEASE_HEADERS) $(RELEASE_HEADERS_DEST)
|
||||
endif
|
||||
+$(LOOP_OVER_DIRS)
|
||||
|
||||
alltags:
|
||||
rm -f TAGS tags
|
||||
find . -name dist -prune -o \( -name '*.[hc]' -o -name '*.cp' -o -name '*.cpp' \) -print | xargs etags -a
|
||||
find . -name dist -prune -o \( -name '*.[hc]' -o -name '*.cp' -o -name '*.cpp' \) -print | xargs ctags -a
|
||||
|
||||
$(NFSPWD):
|
||||
cd $(@D); $(MAKE) $(@F)
|
||||
|
||||
$(PROGRAM): $(OBJS)
|
||||
@$(MAKE_OBJDIR)
|
||||
ifeq ($(NS_USE_GCC)_$(OS_ARCH),_WINNT)
|
||||
$(CC) $(OBJS) -Fe$@ -link $(LDFLAGS) $(OS_LIBS) $(EXTRA_LIBS)
|
||||
else
|
||||
ifeq ($(MOZ_OS2_TOOLS),VACPP)
|
||||
$(CC) $(OBJS) -Fe$@ $(LDFLAGS) $(OS_LIBS) $(EXTRA_LIBS)
|
||||
else
|
||||
$(CC) -o $@ $(CFLAGS) $(OBJS) $(LDFLAGS)
|
||||
endif
|
||||
endif
|
||||
ifdef ENABLE_STRIP
|
||||
$(STRIP) $@
|
||||
endif
|
||||
|
||||
$(LIBRARY): $(OBJS)
|
||||
@$(MAKE_OBJDIR)
|
||||
rm -f $@
|
||||
ifeq ($(MOZ_OS2_TOOLS),VACPP)
|
||||
$(AR) $(subst /,\\,$(OBJS)) $(AR_FLAGS)
|
||||
else
|
||||
$(AR) $(AR_FLAGS) $(OBJS) $(AR_EXTRA_ARGS)
|
||||
endif
|
||||
$(RANLIB) $@
|
||||
|
||||
ifeq ($(OS_TARGET), OS2)
|
||||
$(IMPORT_LIBRARY): $(MAPFILE)
|
||||
rm -f $@
|
||||
$(IMPLIB) $@ $(MAPFILE)
|
||||
endif
|
||||
|
||||
$(SHARED_LIBRARY): $(OBJS) $(RES) $(MAPFILE)
|
||||
@$(MAKE_OBJDIR)
|
||||
rm -f $@
|
||||
ifeq ($(OS_ARCH)$(OS_RELEASE), AIX4.1)
|
||||
echo "#!" > $(OBJDIR)/lib$(LIBRARY_NAME)_syms
|
||||
nm -B -C -g $(OBJS) \
|
||||
| awk '/ [T,D] / {print $$3}' \
|
||||
| sed -e 's/^\.//' \
|
||||
| sort -u >> $(OBJDIR)/lib$(LIBRARY_NAME)_syms
|
||||
$(LD) $(XCFLAGS) -o $@ $(OBJS) -bE:$(OBJDIR)/lib$(LIBRARY_NAME)_syms \
|
||||
-bM:SRE -bnoentry $(OS_LIBS) $(EXTRA_LIBS)
|
||||
else # AIX 4.1
|
||||
ifeq ($(NS_USE_GCC)_$(OS_ARCH),_WINNT)
|
||||
$(LINK_DLL) -MAP $(DLLBASE) $(DLL_LIBS) $(EXTRA_LIBS) $(OBJS) $(RES)
|
||||
else
|
||||
ifeq ($(MOZ_OS2_TOOLS),VACPP)
|
||||
$(LINK_DLL) $(DLLBASE) $(OBJS) $(OS_LIBS) $(EXTRA_LIBS) $(MAPFILE)
|
||||
else # !os2 vacpp
|
||||
ifeq ($(OS_TARGET), OpenVMS)
|
||||
@if test ! -f $(VMS_SYMVEC_FILE); then \
|
||||
if test -f $(VMS_SYMVEC_FILE_MODULE); then \
|
||||
echo Creating component options file $(VMS_SYMVEC_FILE); \
|
||||
cp $(VMS_SYMVEC_FILE_MODULE) $(VMS_SYMVEC_FILE); \
|
||||
fi; \
|
||||
fi
|
||||
endif # OpenVMS
|
||||
$(MKSHLIB) $(OBJS) $(RES) $(EXTRA_LIBS)
|
||||
endif # OS2 vacpp
|
||||
endif # WINNT
|
||||
endif # AIX 4.1
|
||||
ifdef ENABLE_STRIP
|
||||
$(STRIP) $@
|
||||
endif
|
||||
|
||||
ifeq ($(OS_ARCH),WINNT)
|
||||
$(RES): $(RESNAME)
|
||||
@$(MAKE_OBJDIR)
|
||||
# The resource compiler does not understand the -U option.
|
||||
ifdef NS_USE_GCC
|
||||
$(RC) $(RCFLAGS) $(filter-out -U%,$(DEFINES)) $(INCLUDES:-I%=--include-dir %) -o $@ $<
|
||||
else
|
||||
$(RC) $(RCFLAGS) $(filter-out -U%,$(DEFINES)) $(INCLUDES) -Fo$@ $<
|
||||
endif # GCC
|
||||
@echo $(RES) finished
|
||||
endif
|
||||
|
||||
$(MAPFILE): $(LIBRARY_NAME).def
|
||||
@$(MAKE_OBJDIR)
|
||||
ifeq ($(OS_ARCH),SunOS)
|
||||
grep -v ';-' $< | \
|
||||
sed -e 's,;+,,' -e 's; DATA ;;' -e 's,;;,,' -e 's,;.*,;,' > $@
|
||||
endif
|
||||
ifeq ($(OS_ARCH),OS2)
|
||||
echo LIBRARY $(LIBRARY_NAME)$(LIBRARY_VERSION) INITINSTANCE TERMINSTANCE > $@
|
||||
echo PROTMODE >> $@
|
||||
echo CODE LOADONCALL MOVEABLE DISCARDABLE >> $@
|
||||
echo DATA PRELOAD MOVEABLE MULTIPLE NONSHARED >> $@
|
||||
echo EXPORTS >> $@
|
||||
ifeq ($(MOZ_OS2_TOOLS),VACPP)
|
||||
grep -v ';+' $< | grep -v ';-' | \
|
||||
sed -e 's; DATA ;;' -e 's,;;,,' -e 's,;.*,,' >> $@
|
||||
else
|
||||
grep -v ';+' $< | grep -v ';-' | \
|
||||
sed -e 's; DATA ;;' -e 's,;;,,' -e 's,;.*,,' -e 's,\([\t ]*\),\1_,' | \
|
||||
awk 'BEGIN {ord=1;} { print($$0 " @" ord " RESIDENTNAME"); ord++;}' >> $@
|
||||
$(ADD_TO_DEF_FILE)
|
||||
endif
|
||||
endif
|
||||
|
||||
#
|
||||
# Translate source filenames to absolute paths. This is required for
|
||||
# debuggers under Windows and OS/2 to find source files automatically.
|
||||
#
|
||||
|
||||
ifeq (,$(filter-out AIX OS2,$(OS_ARCH)))
|
||||
NEED_ABSOLUTE_PATH = 1
|
||||
endif
|
||||
|
||||
ifeq ($(NS_USE_GCC)_$(OS_ARCH),_WINNT)
|
||||
NEED_ABSOLUTE_PATH = 1
|
||||
endif
|
||||
|
||||
ifdef NEED_ABSOLUTE_PATH
|
||||
PWD := $(shell pwd)
|
||||
abspath = $(if $(findstring :,$(1)),$(1),$(if $(filter /%,$(1)),$(1),$(PWD)/$(1)))
|
||||
endif
|
||||
|
||||
$(OBJDIR)/%.$(OBJ_SUFFIX): %.cpp
|
||||
@$(MAKE_OBJDIR)
|
||||
ifeq ($(NS_USE_GCC)_$(OS_ARCH),_WINNT)
|
||||
$(CCC) -Fo$@ -c $(CCCFLAGS) $(call abspath,$<)
|
||||
else
|
||||
ifeq ($(MOZ_OS2_TOOLS),VACPP)
|
||||
$(CCC) -Fo$@ -c $(CCCFLAGS) $(call abspath,$<)
|
||||
else
|
||||
ifdef NEED_ABSOLUTE_PATH
|
||||
$(CCC) -o $@ -c $(CCCFLAGS) $(call abspath,$<)
|
||||
else
|
||||
$(CCC) -o $@ -c $(CCCFLAGS) $<
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
WCCFLAGS1 = $(subst /,\\,$(CFLAGS))
|
||||
WCCFLAGS2 = $(subst -I,-i=,$(WCCFLAGS1))
|
||||
WCCFLAGS3 = $(subst -D,-d,$(WCCFLAGS2))
|
||||
$(OBJDIR)/%.$(OBJ_SUFFIX): %.c
|
||||
@$(MAKE_OBJDIR)
|
||||
ifeq ($(NS_USE_GCC)_$(OS_ARCH),_WINNT)
|
||||
$(CC) -Fo$@ -c $(CFLAGS) $(call abspath,$<)
|
||||
else
|
||||
ifeq ($(MOZ_OS2_TOOLS),VACPP)
|
||||
$(CC) -Fo$@ -c $(CFLAGS) $(call abspath,$<)
|
||||
else
|
||||
ifdef NEED_ABSOLUTE_PATH
|
||||
$(CC) -o $@ -c $(CFLAGS) $(call abspath,$<)
|
||||
else
|
||||
$(CC) -o $@ -c $(CFLAGS) $<
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
|
||||
$(OBJDIR)/%.$(OBJ_SUFFIX): %.s
|
||||
@$(MAKE_OBJDIR)
|
||||
$(AS) -o $@ $(ASFLAGS) -c $<
|
||||
|
||||
ifeq ($(MOZ_OS2_TOOLS),VACPP)
|
||||
$(OBJDIR)/%.$(OBJ_SUFFIX): %.asm
|
||||
@$(MAKE_OBJDIR)
|
||||
$(AS) -Fdo:./$(OBJDIR) $(ASFLAGS) $<
|
||||
endif
|
||||
|
||||
%.i: %.c
|
||||
$(CC) -C -E $(CFLAGS) $< > $*.i
|
||||
|
||||
%: %.pl
|
||||
rm -f $@; cp $< $@; chmod +x $@
|
||||
|
||||
#
|
||||
# HACK ALERT
|
||||
#
|
||||
# The only purpose of this rule is to pass Mozilla's Tinderbox depend
|
||||
# builds (http://tinderbox.mozilla.org/showbuilds.cgi). Mozilla's
|
||||
# Tinderbox builds NSPR continuously as part of the Mozilla client.
|
||||
# Because NSPR's make depend is not implemented, whenever we change
|
||||
# an NSPR header file, the depend build does not recompile the NSPR
|
||||
# files that depend on the header.
|
||||
#
|
||||
# This rule makes all the objects depend on a dummy header file.
|
||||
# Touch this dummy header file to force the depend build to recompile
|
||||
# everything.
|
||||
#
|
||||
# This rule should be removed when make depend is implemented.
|
||||
#
|
||||
|
||||
DUMMY_DEPEND_H = $(topsrcdir)/config/prdepend.h
|
||||
|
||||
$(filter $(OBJDIR)/%.$(OBJ_SUFFIX),$(OBJS)): $(OBJDIR)/%.$(OBJ_SUFFIX): $(DUMMY_DEPEND_H)
|
||||
|
||||
# END OF HACK
|
||||
|
||||
################################################################################
|
||||
# Special gmake rules.
|
||||
################################################################################
|
||||
|
||||
#
|
||||
# Re-define the list of default suffixes, so gmake won't have to churn through
|
||||
# hundreds of built-in suffix rules for stuff we don't need.
|
||||
#
|
||||
.SUFFIXES:
|
||||
.SUFFIXES: .a .$(OBJ_SUFFIX) .c .cpp .s .h .i .pl
|
||||
|
||||
#
|
||||
# Fake targets. Always run these rules, even if a file/directory with that
|
||||
# name already exists.
|
||||
#
|
||||
.PHONY: all alltags clean export install libs realclean release
|
||||
|
||||
#
|
||||
# List the target pattern of an implicit rule as a dependency of the
|
||||
# special target .PRECIOUS to preserve intermediate files made by
|
||||
# implicit rules whose target patterns match that file's name.
|
||||
# (See GNU Make documentation, Edition 0.51, May 1996, Sec. 10.4,
|
||||
# p. 107.)
|
||||
#
|
||||
.PRECIOUS: $(OBJDIR)/%.$(OBJ_SUFFIX)
|
||||
@@ -1,172 +0,0 @@
|
||||
Aliases.h
|
||||
arpa/inet.h
|
||||
assert.h
|
||||
bsd/libc.h
|
||||
bsd/syscall.h
|
||||
bstring.h
|
||||
builtin.h
|
||||
c_asm.h
|
||||
cf.h
|
||||
CFBundle.h
|
||||
CFData.h
|
||||
CFDictionary.h
|
||||
CFString.h
|
||||
CFURL.h
|
||||
CodeFragments.h
|
||||
commdlg.h
|
||||
crt_externs.h
|
||||
crypt.h
|
||||
ctype.h
|
||||
descrip.h
|
||||
Devices.h
|
||||
direct.h
|
||||
dirent.h
|
||||
dlfcn.h
|
||||
dl.h
|
||||
DriverServices.h
|
||||
dvidef.h
|
||||
errno.h
|
||||
Errors.h
|
||||
Events.h
|
||||
fcntl.h
|
||||
fibdef.h
|
||||
files.h
|
||||
Files.h
|
||||
float.h
|
||||
Folders.h
|
||||
Gestalt.h
|
||||
getopt.h
|
||||
grp.h
|
||||
ia64/sys/inline.h
|
||||
ifaddrs.h
|
||||
image.h
|
||||
ints.h
|
||||
iodef.h
|
||||
io.h
|
||||
iostream.h
|
||||
kernel/OS.h
|
||||
lib$routines.h
|
||||
limits.h
|
||||
loader.h
|
||||
locale.h
|
||||
LowMem.h
|
||||
MacErrors.h
|
||||
machine/builtins.h
|
||||
machine/clock.h
|
||||
machine/endian.h
|
||||
machine/inline.h
|
||||
mach/mach_init.h
|
||||
mach/mach_host.h
|
||||
mach-o/dyld.h
|
||||
MacTypes.h
|
||||
Math64.h
|
||||
math.h
|
||||
mbstring.h
|
||||
memory.h
|
||||
MixedMode.h
|
||||
model.h
|
||||
mswsock.h
|
||||
Multiprocessing.h
|
||||
mutex.h
|
||||
netdb.h
|
||||
net/if.h
|
||||
netinet/in.h
|
||||
netinet/in_systm.h
|
||||
netinet/tcp.h
|
||||
OpenTptInternet.h
|
||||
OpenTransport.h
|
||||
os2.h
|
||||
OS.h
|
||||
osreldate.h
|
||||
OSUtils.h
|
||||
poll.h
|
||||
PPCToolbox.h
|
||||
Processes.h
|
||||
process.h
|
||||
pthread.h
|
||||
pwd.h
|
||||
QDOffscreen.h
|
||||
Resources.h
|
||||
rld_interface.h
|
||||
rpc/types.h
|
||||
semaphore.h
|
||||
setjmp.h
|
||||
share.h
|
||||
signal.h
|
||||
ssdef.h
|
||||
starlet.h
|
||||
stat.h
|
||||
stdarg.h
|
||||
stddef.h
|
||||
stdio.h
|
||||
stdlib.h
|
||||
string.h
|
||||
stropts.h
|
||||
stsdef.h
|
||||
support/SupportDefs.h
|
||||
support/TLS.h
|
||||
synch.h
|
||||
sys/atomic_op.h
|
||||
syscall.h
|
||||
sys/cfgodm.h
|
||||
sys/file.h
|
||||
sys/filio.h
|
||||
sys/immu.h
|
||||
sys/ioctl.h
|
||||
sys/ipc.h
|
||||
sys/ldr.h
|
||||
sys/locking.h
|
||||
sys/lwp.h
|
||||
sys/mman.h
|
||||
sys/mpctl.h
|
||||
sys/param.h
|
||||
sys/pda.h
|
||||
sys/poll.h
|
||||
sys/prctl.h
|
||||
sys/priv.h
|
||||
sys/procfs.h
|
||||
sys/pstat.h
|
||||
sys/regset.h
|
||||
sys/resource.h
|
||||
sys/sched.h
|
||||
sys/select.h
|
||||
sys/sem.h
|
||||
sys/sendfile.h
|
||||
sys/shm.h
|
||||
sys/socket.h
|
||||
sys/stack.h
|
||||
sys/stat.h
|
||||
sys/statvfs.h
|
||||
sys/syscall.h
|
||||
sys/sysctl.h
|
||||
sys/sysmp.h
|
||||
sys/syssgi.h
|
||||
sys/systeminfo.h
|
||||
sys/timeb.h
|
||||
sys/time.h
|
||||
sys/times.h
|
||||
sys/types.h
|
||||
sys/ucontext.h
|
||||
sys/uio.h
|
||||
sys/utsname.h
|
||||
sys/wait.h
|
||||
task.h
|
||||
TextUtils.h
|
||||
thread.h
|
||||
time.h
|
||||
Timer.h
|
||||
types.h
|
||||
Types.h
|
||||
ucontext.h
|
||||
ucx$inetdef.h
|
||||
ulocks.h
|
||||
unistd.h
|
||||
unix.h
|
||||
unixlib.h
|
||||
utime.h
|
||||
wchar.h
|
||||
winbase.h
|
||||
win/compobj.h
|
||||
windef.h
|
||||
windows.h
|
||||
winsock.h
|
||||
6270
mozilla/nsprpub/configure
vendored
6270
mozilla/nsprpub/configure
vendored
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,56 +0,0 @@
|
||||
#
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla 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/MPL/
|
||||
#
|
||||
# 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 the Netscape Portable Runtime (NSPR).
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Netscape Communications Corporation.
|
||||
# Portions created by the Initial Developer are Copyright (C) 1998-2000
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
#! gmake
|
||||
|
||||
MOD_DEPTH = ..
|
||||
topsrcdir = @top_srcdir@
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
include $(MOD_DEPTH)/config/autoconf.mk
|
||||
|
||||
export NSPR20=1
|
||||
|
||||
include $(topsrcdir)/config/config.mk
|
||||
|
||||
DIRS = ds libc
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
export:: $(TARGETS)
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
#
|
||||
# This is a list of local files which get copied to the mozilla:dist directory
|
||||
#
|
||||
|
||||
plarenas.h
|
||||
plarena.h
|
||||
plhash.h
|
||||
@@ -1,197 +0,0 @@
|
||||
#
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla 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/MPL/
|
||||
#
|
||||
# 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 the Netscape Portable Runtime (NSPR).
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Netscape Communications Corporation.
|
||||
# Portions created by the Initial Developer are Copyright (C) 1998-2000
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
#! gmake
|
||||
|
||||
MOD_DEPTH = ../..
|
||||
topsrcdir = @top_srcdir@
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
include $(MOD_DEPTH)/config/autoconf.mk
|
||||
|
||||
include $(topsrcdir)/config/config.mk
|
||||
|
||||
INCLUDES = -I$(dist_includedir) -I$(topsrcdir)/pr/include
|
||||
|
||||
CSRCS = \
|
||||
plarena.c \
|
||||
plhash.c \
|
||||
plvrsion.c \
|
||||
$(NULL)
|
||||
|
||||
HEADERS = \
|
||||
plarenas.h \
|
||||
plarena.h \
|
||||
plhash.h \
|
||||
$(NULL)
|
||||
|
||||
HEADERS := $(addprefix $(srcdir)/, $(HEADERS))
|
||||
|
||||
ifeq ($(OS_ARCH), WINNT)
|
||||
RES=$(OBJDIR)/plds.res
|
||||
RESNAME=plds.rc
|
||||
endif # WINNT
|
||||
|
||||
ifeq ($(OS_ARCH), AIX)
|
||||
ifeq ($(CLASSIC_NSPR),1)
|
||||
OS_LIBS = -lc
|
||||
else
|
||||
OS_LIBS = -lc_r
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(OS_ARCH),IRIX)
|
||||
OS_LIBS = -lc
|
||||
endif
|
||||
|
||||
ifeq ($(OS_ARCH),SunOS)
|
||||
OS_LIBS = -lc
|
||||
MAPFILE = $(OBJDIR)/pldsmap.sun
|
||||
GARBAGE += $(MAPFILE)
|
||||
ifdef NS_USE_GCC
|
||||
ifdef GCC_USE_GNU_LD
|
||||
MKSHLIB += -Wl,--version-script,$(MAPFILE)
|
||||
else
|
||||
MKSHLIB += -Wl,-M,$(MAPFILE)
|
||||
endif
|
||||
else
|
||||
MKSHLIB += -M $(MAPFILE)
|
||||
endif
|
||||
# The -R '$ORIGIN' linker option instructs this library to search for its
|
||||
# dependencies in the same directory where it resides.
|
||||
MKSHLIB += -R '$$ORIGIN'
|
||||
endif
|
||||
|
||||
ifeq ($(OS_ARCH),OS2)
|
||||
MAPFILE = $(OBJDIR)/$(LIBRARY_NAME)$(LIBRARY_VERSION).def
|
||||
GARBAGE += $(MAPFILE)
|
||||
MKSHLIB += $(MAPFILE)
|
||||
endif
|
||||
|
||||
EXTRA_LIBS = $(LIBNSPR)
|
||||
|
||||
# On NCR and SCOOS, we can't link with extra libraries when
|
||||
# we build a shared library. If we do so, the linker doesn't
|
||||
# complain, but we would run into weird problems at run-time.
|
||||
# Therefore on these platforms, we link just the .o files.
|
||||
ifeq ($(OS_ARCH),NCR)
|
||||
EXTRA_LIBS =
|
||||
endif
|
||||
ifeq ($(OS_ARCH),SCOOS)
|
||||
EXTRA_LIBS =
|
||||
endif
|
||||
|
||||
ifdef RESOLVE_LINK_SYMBOLS
|
||||
EXTRA_LIBS += $(OS_LIBS)
|
||||
endif
|
||||
|
||||
LIBRARY_NAME = plds
|
||||
LIBRARY_VERSION = $(MOD_MAJOR_VERSION)
|
||||
|
||||
RELEASE_HEADERS = $(HEADERS)
|
||||
RELEASE_HEADERS_DEST = $(RELEASE_INCLUDE_DIR)
|
||||
RELEASE_LIBS = $(TARGETS)
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
#
|
||||
# Version information generation (begin)
|
||||
#
|
||||
ECHO = echo
|
||||
TINC = $(OBJDIR)/_pl_bld.h
|
||||
PROD = $(notdir $(SHARED_LIBRARY))
|
||||
NOW = $(MOD_DEPTH)/config/$(OBJDIR)/now
|
||||
SH_DATE = $(shell date "+%Y-%m-%d %T")
|
||||
SH_NOW = $(shell $(NOW))
|
||||
|
||||
ifeq ($(NS_USE_GCC)_$(OS_ARCH),_WINNT)
|
||||
SUF = i64
|
||||
else
|
||||
SUF = LL
|
||||
endif
|
||||
|
||||
GARBAGE += $(TINC)
|
||||
|
||||
$(TINC):
|
||||
@$(MAKE_OBJDIR)
|
||||
@$(ECHO) '#define _BUILD_STRING "$(SH_DATE)"' > $(TINC)
|
||||
@if test ! -z "$(SH_NOW)"; then \
|
||||
$(ECHO) '#define _BUILD_TIME $(SH_NOW)$(SUF)' >> $(TINC); \
|
||||
else \
|
||||
true; \
|
||||
fi
|
||||
@$(ECHO) '#define _PRODUCTION "$(PROD)"' >> $(TINC)
|
||||
|
||||
|
||||
$(OBJDIR)/plvrsion.$(OBJ_SUFFIX): plvrsion.c $(TINC)
|
||||
ifeq ($(NS_USE_GCC)_$(OS_ARCH),_WINNT)
|
||||
$(CC) -Fo$@ -c $(CFLAGS) -I$(OBJDIR) $<
|
||||
else
|
||||
ifeq ($(MOZ_OS2_TOOLS), VACPP)
|
||||
$(CC) -Fo$@ -c $(CFLAGS) -I$(OBJDIR) $<
|
||||
else
|
||||
$(CC) -o $@ -c $(CFLAGS) -I$(OBJDIR) $<
|
||||
endif
|
||||
endif
|
||||
#
|
||||
# Version information generation (end)
|
||||
#
|
||||
|
||||
#
|
||||
# The Client build wants the shared libraries in $(dist_bindir),
|
||||
# so we also install them there.
|
||||
#
|
||||
|
||||
export:: $(TARGETS)
|
||||
$(INSTALL) -m 444 $(HEADERS) $(dist_includedir)
|
||||
$(INSTALL) -m 444 $(TARGETS) $(dist_libdir)
|
||||
ifdef SHARED_LIBRARY
|
||||
ifeq ($(OS_ARCH),HP-UX)
|
||||
$(INSTALL) -m 755 $(SHARED_LIBRARY) $(dist_libdir)
|
||||
$(INSTALL) -m 755 $(SHARED_LIBRARY) $(dist_bindir)
|
||||
else
|
||||
$(INSTALL) -m 444 $(SHARED_LIBRARY) $(dist_bindir)
|
||||
endif
|
||||
endif
|
||||
ifeq ($(MOZ_BITS),16)
|
||||
$(INSTALL) -m 444 $(HEADERS) $(MOZ_INCL)
|
||||
$(INSTALL) -m 444 $(TARGETS) $(MOZ_DIST)/lib
|
||||
$(INSTALL) -m 444 $(TARGETS) $(MOZ_DIST)/bin
|
||||
endif
|
||||
|
||||
|
||||
@@ -1,432 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla 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/MPL/
|
||||
*
|
||||
* 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 the Netscape Portable Runtime (NSPR).
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998-2000 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
/*
|
||||
* Lifetime-based fast allocation, inspired by much prior art, including
|
||||
* "Fast Allocation and Deallocation of Memory Based on Object Lifetimes"
|
||||
* David R. Hanson, Software -- Practice and Experience, Vol. 20(1).
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "plarena.h"
|
||||
#include "prmem.h"
|
||||
#include "prbit.h"
|
||||
#include "prlog.h"
|
||||
#include "prlock.h"
|
||||
#include "prinit.h"
|
||||
|
||||
static PLArena *arena_freelist;
|
||||
|
||||
#ifdef PL_ARENAMETER
|
||||
static PLArenaStats *arena_stats_list;
|
||||
|
||||
#define COUNT(pool,what) (pool)->stats.what++
|
||||
#else
|
||||
#define COUNT(pool,what) /* nothing */
|
||||
#endif
|
||||
|
||||
#define PL_ARENA_DEFAULT_ALIGN sizeof(double)
|
||||
|
||||
static PRLock *arenaLock;
|
||||
static PRCallOnceType once;
|
||||
|
||||
/*
|
||||
** InitializeArenas() -- Initialize arena operations.
|
||||
**
|
||||
** InitializeArenas() is called exactly once and only once from
|
||||
** LockArena(). This function creates the arena protection
|
||||
** lock: arenaLock.
|
||||
**
|
||||
** Note: If the arenaLock cannot be created, InitializeArenas()
|
||||
** fails quietly, returning only PR_FAILURE. This percolates up
|
||||
** to the application using the Arena API. He gets no arena
|
||||
** from PL_ArenaAllocate(). It's up to him to fail gracefully
|
||||
** or recover.
|
||||
**
|
||||
*/
|
||||
static PRStatus InitializeArenas( void )
|
||||
{
|
||||
PR_ASSERT( arenaLock == NULL );
|
||||
arenaLock = PR_NewLock();
|
||||
if ( arenaLock == NULL )
|
||||
return PR_FAILURE;
|
||||
else
|
||||
return PR_SUCCESS;
|
||||
} /* end ArenaInitialize() */
|
||||
|
||||
static PRStatus LockArena( void )
|
||||
{
|
||||
PRStatus rc = PR_CallOnce( &once, InitializeArenas );
|
||||
|
||||
if ( PR_FAILURE != rc )
|
||||
PR_Lock( arenaLock );
|
||||
return(rc);
|
||||
} /* end LockArena() */
|
||||
|
||||
static void UnlockArena( void )
|
||||
{
|
||||
PR_Unlock( arenaLock );
|
||||
return;
|
||||
} /* end UnlockArena() */
|
||||
|
||||
PR_IMPLEMENT(void) PL_InitArenaPool(
|
||||
PLArenaPool *pool, const char *name, PRUint32 size, PRUint32 align)
|
||||
{
|
||||
#if defined(XP_MAC)
|
||||
#pragma unused (name)
|
||||
#endif
|
||||
|
||||
if (align == 0)
|
||||
align = PL_ARENA_DEFAULT_ALIGN;
|
||||
pool->mask = PR_BITMASK(PR_CeilingLog2(align));
|
||||
pool->first.next = NULL;
|
||||
pool->first.base = pool->first.avail = pool->first.limit =
|
||||
(PRUword)PL_ARENA_ALIGN(pool, &pool->first + 1);
|
||||
pool->current = &pool->first;
|
||||
pool->arenasize = size;
|
||||
#ifdef PL_ARENAMETER
|
||||
memset(&pool->stats, 0, sizeof pool->stats);
|
||||
pool->stats.name = strdup(name);
|
||||
pool->stats.next = arena_stats_list;
|
||||
arena_stats_list = &pool->stats;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** PL_ArenaAllocate() -- allocate space from an arena pool
|
||||
**
|
||||
** Description: PL_ArenaAllocate() allocates space from an arena
|
||||
** pool.
|
||||
**
|
||||
** First, try to satisfy the request from arenas starting at
|
||||
** pool->current.
|
||||
**
|
||||
** If there is not enough space in the arena pool->current, try
|
||||
** to claim an arena, on a first fit basis, from the global
|
||||
** freelist (arena_freelist).
|
||||
**
|
||||
** If no arena in arena_freelist is suitable, then try to
|
||||
** allocate a new arena from the heap.
|
||||
**
|
||||
** Returns: pointer to allocated space or NULL
|
||||
**
|
||||
** Notes: The original implementation had some difficult to
|
||||
** solve bugs; the code was difficult to read. Sometimes it's
|
||||
** just easier to rewrite it. I did that. larryh.
|
||||
**
|
||||
** See also: bugzilla: 45343.
|
||||
**
|
||||
*/
|
||||
|
||||
PR_IMPLEMENT(void *) PL_ArenaAllocate(PLArenaPool *pool, PRUint32 nb)
|
||||
{
|
||||
PLArena *a;
|
||||
char *rp; /* returned pointer */
|
||||
|
||||
PR_ASSERT((nb & pool->mask) == 0);
|
||||
|
||||
nb = (PRUword)PL_ARENA_ALIGN(pool, nb); /* force alignment */
|
||||
|
||||
/* attempt to allocate from arenas at pool->current */
|
||||
{
|
||||
a = pool->current;
|
||||
do {
|
||||
if ( a->avail +nb <= a->limit ) {
|
||||
pool->current = a;
|
||||
rp = (char *)a->avail;
|
||||
a->avail += nb;
|
||||
return rp;
|
||||
}
|
||||
} while( NULL != (a = a->next) );
|
||||
}
|
||||
|
||||
/* attempt to allocate from arena_freelist */
|
||||
{
|
||||
PLArena *p; /* previous pointer, for unlinking from freelist */
|
||||
|
||||
/* lock the arena_freelist. Make access to the freelist MT-Safe */
|
||||
if ( PR_FAILURE == LockArena())
|
||||
return(0);
|
||||
|
||||
for ( a = arena_freelist, p = NULL; a != NULL ; p = a, a = a->next ) {
|
||||
if ( a->base +nb <= a->limit ) {
|
||||
if ( p == NULL )
|
||||
arena_freelist = a->next;
|
||||
else
|
||||
p->next = a->next;
|
||||
UnlockArena();
|
||||
a->avail = a->base;
|
||||
rp = (char *)a->avail;
|
||||
a->avail += nb;
|
||||
/* the newly allocated arena is linked after pool->current
|
||||
* and becomes pool->current */
|
||||
a->next = pool->current->next;
|
||||
pool->current->next = a;
|
||||
pool->current = a;
|
||||
if ( NULL == pool->first.next )
|
||||
pool->first.next = a;
|
||||
return(rp);
|
||||
}
|
||||
}
|
||||
UnlockArena();
|
||||
}
|
||||
|
||||
/* attempt to allocate from the heap */
|
||||
{
|
||||
PRUint32 sz = PR_MAX(pool->arenasize, nb);
|
||||
sz += sizeof *a + pool->mask; /* header and alignment slop */
|
||||
a = (PLArena*)PR_MALLOC(sz);
|
||||
if ( NULL != a ) {
|
||||
a->limit = (PRUword)a + sz;
|
||||
a->base = a->avail = (PRUword)PL_ARENA_ALIGN(pool, a + 1);
|
||||
rp = (char *)a->avail;
|
||||
a->avail += nb;
|
||||
/* the newly allocated arena is linked after pool->current
|
||||
* and becomes pool->current */
|
||||
a->next = pool->current->next;
|
||||
pool->current->next = a;
|
||||
pool->current = a;
|
||||
if ( NULL == pool->first.next )
|
||||
pool->first.next = a;
|
||||
PL_COUNT_ARENA(pool,++);
|
||||
COUNT(pool, nmallocs);
|
||||
return(rp);
|
||||
}
|
||||
}
|
||||
|
||||
/* we got to here, and there's no memory to allocate */
|
||||
return(NULL);
|
||||
} /* --- end PL_ArenaAllocate() --- */
|
||||
|
||||
PR_IMPLEMENT(void *) PL_ArenaGrow(
|
||||
PLArenaPool *pool, void *p, PRUint32 size, PRUint32 incr)
|
||||
{
|
||||
void *newp;
|
||||
|
||||
PL_ARENA_ALLOCATE(newp, pool, size + incr);
|
||||
if (newp)
|
||||
memcpy(newp, p, size);
|
||||
return newp;
|
||||
}
|
||||
|
||||
/*
|
||||
* Free tail arenas linked after head, which may not be the true list head.
|
||||
* Reset pool->current to point to head in case it pointed at a tail arena.
|
||||
*/
|
||||
static void FreeArenaList(PLArenaPool *pool, PLArena *head, PRBool reallyFree)
|
||||
{
|
||||
PLArena **ap, *a;
|
||||
|
||||
ap = &head->next;
|
||||
a = *ap;
|
||||
if (!a)
|
||||
return;
|
||||
|
||||
#ifdef DEBUG
|
||||
do {
|
||||
PR_ASSERT(a->base <= a->avail && a->avail <= a->limit);
|
||||
a->avail = a->base;
|
||||
PL_CLEAR_UNUSED(a);
|
||||
} while ((a = a->next) != 0);
|
||||
a = *ap;
|
||||
#endif
|
||||
|
||||
if (reallyFree) {
|
||||
do {
|
||||
*ap = a->next;
|
||||
PL_CLEAR_ARENA(a);
|
||||
PL_COUNT_ARENA(pool,--);
|
||||
PR_DELETE(a);
|
||||
} while ((a = *ap) != 0);
|
||||
} else {
|
||||
/* Insert the whole arena chain at the front of the freelist. */
|
||||
do {
|
||||
ap = &(*ap)->next;
|
||||
} while (*ap);
|
||||
LockArena();
|
||||
*ap = arena_freelist;
|
||||
arena_freelist = a;
|
||||
head->next = 0;
|
||||
UnlockArena();
|
||||
}
|
||||
|
||||
pool->current = head;
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(void) PL_ArenaRelease(PLArenaPool *pool, char *mark)
|
||||
{
|
||||
PLArena *a;
|
||||
|
||||
for (a = pool->first.next; a; a = a->next) {
|
||||
if (PR_UPTRDIFF(mark, a->base) < PR_UPTRDIFF(a->avail, a->base)) {
|
||||
a->avail = (PRUword)PL_ARENA_ALIGN(pool, mark);
|
||||
FreeArenaList(pool, a, PR_FALSE);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(void) PL_FreeArenaPool(PLArenaPool *pool)
|
||||
{
|
||||
FreeArenaList(pool, &pool->first, PR_FALSE);
|
||||
COUNT(pool, ndeallocs);
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(void) PL_FinishArenaPool(PLArenaPool *pool)
|
||||
{
|
||||
FreeArenaList(pool, &pool->first, PR_TRUE);
|
||||
#ifdef PL_ARENAMETER
|
||||
{
|
||||
PLArenaStats *stats, **statsp;
|
||||
|
||||
if (pool->stats.name)
|
||||
PR_DELETE(pool->stats.name);
|
||||
for (statsp = &arena_stats_list; (stats = *statsp) != 0;
|
||||
statsp = &stats->next) {
|
||||
if (stats == &pool->stats) {
|
||||
*statsp = stats->next;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(void) PL_CompactArenaPool(PLArenaPool *ap)
|
||||
{
|
||||
#if XP_MAC
|
||||
#pragma unused (ap)
|
||||
#if 0
|
||||
PRArena *curr = &(ap->first);
|
||||
while (curr) {
|
||||
reallocSmaller(curr, curr->avail - (uprword_t)curr);
|
||||
curr->limit = curr->avail;
|
||||
curr = curr->next;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(void) PL_ArenaFinish(void)
|
||||
{
|
||||
PLArena *a, *next;
|
||||
|
||||
for (a = arena_freelist; a; a = next) {
|
||||
next = a->next;
|
||||
PR_DELETE(a);
|
||||
}
|
||||
arena_freelist = NULL;
|
||||
|
||||
if (arenaLock) {
|
||||
PR_DestroyLock(arenaLock);
|
||||
arenaLock = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef PL_ARENAMETER
|
||||
PR_IMPLEMENT(void) PL_ArenaCountAllocation(PLArenaPool *pool, PRUint32 nb)
|
||||
{
|
||||
pool->stats.nallocs++;
|
||||
pool->stats.nbytes += nb;
|
||||
if (nb > pool->stats.maxalloc)
|
||||
pool->stats.maxalloc = nb;
|
||||
pool->stats.variance += nb * nb;
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(void) PL_ArenaCountInplaceGrowth(
|
||||
PLArenaPool *pool, PRUint32 size, PRUint32 incr)
|
||||
{
|
||||
pool->stats.ninplace++;
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(void) PL_ArenaCountGrowth(
|
||||
PLArenaPool *pool, PRUint32 size, PRUint32 incr)
|
||||
{
|
||||
pool->stats.ngrows++;
|
||||
pool->stats.nbytes += incr;
|
||||
pool->stats.variance -= size * size;
|
||||
size += incr;
|
||||
if (size > pool->stats.maxalloc)
|
||||
pool->stats.maxalloc = size;
|
||||
pool->stats.variance += size * size;
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(void) PL_ArenaCountRelease(PLArenaPool *pool, char *mark)
|
||||
{
|
||||
pool->stats.nreleases++;
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(void) PL_ArenaCountRetract(PLArenaPool *pool, char *mark)
|
||||
{
|
||||
pool->stats.nfastrels++;
|
||||
}
|
||||
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
|
||||
PR_IMPLEMENT(void) PL_DumpArenaStats(FILE *fp)
|
||||
{
|
||||
PLArenaStats *stats;
|
||||
double mean, variance;
|
||||
|
||||
for (stats = arena_stats_list; stats; stats = stats->next) {
|
||||
if (stats->nallocs != 0) {
|
||||
mean = (double)stats->nbytes / stats->nallocs;
|
||||
variance = fabs(stats->variance / stats->nallocs - mean * mean);
|
||||
} else {
|
||||
mean = variance = 0;
|
||||
}
|
||||
|
||||
fprintf(fp, "\n%s allocation statistics:\n", stats->name);
|
||||
fprintf(fp, " number of arenas: %u\n", stats->narenas);
|
||||
fprintf(fp, " number of allocations: %u\n", stats->nallocs);
|
||||
fprintf(fp, " number of free arena reclaims: %u\n", stats->nreclaims);
|
||||
fprintf(fp, " number of malloc calls: %u\n", stats->nmallocs);
|
||||
fprintf(fp, " number of deallocations: %u\n", stats->ndeallocs);
|
||||
fprintf(fp, " number of allocation growths: %u\n", stats->ngrows);
|
||||
fprintf(fp, " number of in-place growths: %u\n", stats->ninplace);
|
||||
fprintf(fp, "number of released allocations: %u\n", stats->nreleases);
|
||||
fprintf(fp, " number of fast releases: %u\n", stats->nfastrels);
|
||||
fprintf(fp, " total bytes allocated: %u\n", stats->nbytes);
|
||||
fprintf(fp, " mean allocation size: %g\n", mean);
|
||||
fprintf(fp, " standard deviation: %g\n", sqrt(variance));
|
||||
fprintf(fp, " maximum allocation size: %u\n", stats->maxalloc);
|
||||
}
|
||||
}
|
||||
#endif /* PL_ARENAMETER */
|
||||
@@ -1,213 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla 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/MPL/
|
||||
*
|
||||
* 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 the Netscape Portable Runtime (NSPR).
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998-2000 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
#ifndef plarena_h___
|
||||
#define plarena_h___
|
||||
/*
|
||||
* Lifetime-based fast allocation, inspired by much prior art, including
|
||||
* "Fast Allocation and Deallocation of Memory Based on Object Lifetimes"
|
||||
* David R. Hanson, Software -- Practice and Experience, Vol. 20(1).
|
||||
*
|
||||
* Also supports LIFO allocation (PL_ARENA_MARK/PL_ARENA_RELEASE).
|
||||
*/
|
||||
#include "prtypes.h"
|
||||
#include "plarenas.h"
|
||||
|
||||
PR_BEGIN_EXTERN_C
|
||||
|
||||
typedef struct PLArena PLArena;
|
||||
|
||||
struct PLArena {
|
||||
PLArena *next; /* next arena for this lifetime */
|
||||
PRUword base; /* aligned base address, follows this header */
|
||||
PRUword limit; /* one beyond last byte in arena */
|
||||
PRUword avail; /* points to next available byte */
|
||||
};
|
||||
|
||||
#ifdef PL_ARENAMETER
|
||||
typedef struct PLArenaStats PLArenaStats;
|
||||
|
||||
struct PLArenaStats {
|
||||
PLArenaStats *next; /* next in arenaStats list */
|
||||
char *name; /* name for debugging */
|
||||
PRUint32 narenas; /* number of arenas in pool */
|
||||
PRUint32 nallocs; /* number of PL_ARENA_ALLOCATE() calls */
|
||||
PRUint32 nreclaims; /* number of reclaims from freeArenas */
|
||||
PRUint32 nmallocs; /* number of malloc() calls */
|
||||
PRUint32 ndeallocs; /* number of lifetime deallocations */
|
||||
PRUint32 ngrows; /* number of PL_ARENA_GROW() calls */
|
||||
PRUint32 ninplace; /* number of in-place growths */
|
||||
PRUint32 nreleases; /* number of PL_ARENA_RELEASE() calls */
|
||||
PRUint32 nfastrels; /* number of "fast path" releases */
|
||||
PRUint32 nbytes; /* total bytes allocated */
|
||||
PRUint32 maxalloc; /* maximum allocation size in bytes */
|
||||
PRFloat64 variance; /* size variance accumulator */
|
||||
};
|
||||
#endif
|
||||
|
||||
struct PLArenaPool {
|
||||
PLArena first; /* first arena in pool list */
|
||||
PLArena *current; /* arena from which to allocate space */
|
||||
PRUint32 arenasize; /* net exact size of a new arena */
|
||||
PRUword mask; /* alignment mask (power-of-2 - 1) */
|
||||
#ifdef PL_ARENAMETER
|
||||
PLArenaStats stats;
|
||||
#endif
|
||||
};
|
||||
|
||||
/*
|
||||
* If the including .c file uses only one power-of-2 alignment, it may define
|
||||
* PL_ARENA_CONST_ALIGN_MASK to the alignment mask and save a few instructions
|
||||
* per ALLOCATE and GROW.
|
||||
*/
|
||||
#ifdef PL_ARENA_CONST_ALIGN_MASK
|
||||
#define PL_ARENA_ALIGN(pool, n) (((PRUword)(n) + PL_ARENA_CONST_ALIGN_MASK) \
|
||||
& ~PL_ARENA_CONST_ALIGN_MASK)
|
||||
|
||||
#define PL_INIT_ARENA_POOL(pool, name, size) \
|
||||
PL_InitArenaPool(pool, name, size, PL_ARENA_CONST_ALIGN_MASK + 1)
|
||||
#else
|
||||
#define PL_ARENA_ALIGN(pool, n) (((PRUword)(n) + (pool)->mask) & ~(pool)->mask)
|
||||
#endif
|
||||
|
||||
#define PL_ARENA_ALLOCATE(p, pool, nb) \
|
||||
PR_BEGIN_MACRO \
|
||||
PLArena *_a = (pool)->current; \
|
||||
PRUint32 _nb = PL_ARENA_ALIGN(pool, nb); \
|
||||
PRUword _p = _a->avail; \
|
||||
PRUword _q = _p + _nb; \
|
||||
if (_q > _a->limit) \
|
||||
_p = (PRUword)PL_ArenaAllocate(pool, _nb); \
|
||||
else \
|
||||
_a->avail = _q; \
|
||||
p = (void *)_p; \
|
||||
PL_ArenaCountAllocation(pool, nb); \
|
||||
PR_END_MACRO
|
||||
|
||||
#define PL_ARENA_GROW(p, pool, size, incr) \
|
||||
PR_BEGIN_MACRO \
|
||||
PLArena *_a = (pool)->current; \
|
||||
PRUint32 _incr = PL_ARENA_ALIGN(pool, incr); \
|
||||
PRUword _p = _a->avail; \
|
||||
PRUword _q = _p + _incr; \
|
||||
if (_p == (PRUword)(p) + PL_ARENA_ALIGN(pool, size) && \
|
||||
_q <= _a->limit) { \
|
||||
_a->avail = _q; \
|
||||
PL_ArenaCountInplaceGrowth(pool, size, incr); \
|
||||
} else { \
|
||||
p = PL_ArenaGrow(pool, p, size, incr); \
|
||||
} \
|
||||
PL_ArenaCountGrowth(pool, size, incr); \
|
||||
PR_END_MACRO
|
||||
|
||||
#define PL_ARENA_MARK(pool) ((void *) (pool)->current->avail)
|
||||
#define PR_UPTRDIFF(p,q) ((PRUword)(p) - (PRUword)(q))
|
||||
|
||||
#ifdef DEBUG
|
||||
#define PL_FREE_PATTERN 0xDA
|
||||
#define PL_CLEAR_UNUSED(a) (PR_ASSERT((a)->avail <= (a)->limit), \
|
||||
memset((void*)(a)->avail, PL_FREE_PATTERN, \
|
||||
(a)->limit - (a)->avail))
|
||||
#define PL_CLEAR_ARENA(a) memset((void*)(a), PL_FREE_PATTERN, \
|
||||
(a)->limit - (PRUword)(a))
|
||||
#else
|
||||
#define PL_CLEAR_UNUSED(a)
|
||||
#define PL_CLEAR_ARENA(a)
|
||||
#endif
|
||||
|
||||
#define PL_ARENA_RELEASE(pool, mark) \
|
||||
PR_BEGIN_MACRO \
|
||||
char *_m = (char *)(mark); \
|
||||
PLArena *_a = (pool)->current; \
|
||||
if (PR_UPTRDIFF(_m, _a->base) <= PR_UPTRDIFF(_a->avail, _a->base)) { \
|
||||
_a->avail = (PRUword)PL_ARENA_ALIGN(pool, _m); \
|
||||
PL_CLEAR_UNUSED(_a); \
|
||||
PL_ArenaCountRetract(pool, _m); \
|
||||
} else { \
|
||||
PL_ArenaRelease(pool, _m); \
|
||||
} \
|
||||
PL_ArenaCountRelease(pool, _m); \
|
||||
PR_END_MACRO
|
||||
|
||||
#ifdef PL_ARENAMETER
|
||||
#define PL_COUNT_ARENA(pool,op) ((pool)->stats.narenas op)
|
||||
#else
|
||||
#define PL_COUNT_ARENA(pool,op)
|
||||
#endif
|
||||
|
||||
#define PL_ARENA_DESTROY(pool, a, pnext) \
|
||||
PR_BEGIN_MACRO \
|
||||
PL_COUNT_ARENA(pool,--); \
|
||||
if ((pool)->current == (a)) (pool)->current = &(pool)->first; \
|
||||
*(pnext) = (a)->next; \
|
||||
PL_CLEAR_ARENA(a); \
|
||||
free(a); \
|
||||
(a) = 0; \
|
||||
PR_END_MACRO
|
||||
|
||||
#ifdef PL_ARENAMETER
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
PR_EXTERN(void) PL_ArenaCountAllocation(PLArenaPool *pool, PRUint32 nb);
|
||||
|
||||
PR_EXTERN(void) PL_ArenaCountInplaceGrowth(
|
||||
PLArenaPool *pool, PRUint32 size, PRUint32 incr);
|
||||
|
||||
PR_EXTERN(void) PL_ArenaCountGrowth(
|
||||
PLArenaPool *pool, PRUint32 size, PRUint32 incr);
|
||||
|
||||
PR_EXTERN(void) PL_ArenaCountRelease(PLArenaPool *pool, char *mark);
|
||||
|
||||
PR_EXTERN(void) PL_ArenaCountRetract(PLArenaPool *pool, char *mark);
|
||||
|
||||
PR_EXTERN(void) PL_DumpArenaStats(FILE *fp);
|
||||
|
||||
#else /* !PL_ARENAMETER */
|
||||
|
||||
#define PL_ArenaCountAllocation(ap, nb) /* nothing */
|
||||
#define PL_ArenaCountInplaceGrowth(ap, size, incr) /* nothing */
|
||||
#define PL_ArenaCountGrowth(ap, size, incr) /* nothing */
|
||||
#define PL_ArenaCountRelease(ap, mark) /* nothing */
|
||||
#define PL_ArenaCountRetract(ap, mark) /* nothing */
|
||||
|
||||
#endif /* !PL_ARENAMETER */
|
||||
|
||||
PR_END_EXTERN_C
|
||||
|
||||
#endif /* plarena_h___ */
|
||||
@@ -1,115 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla 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/MPL/
|
||||
*
|
||||
* 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 the Netscape Portable Runtime (NSPR).
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998-2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#if defined(PLARENAS_H)
|
||||
#else /* defined(PLARENAS_H) */
|
||||
#define PLARENAS_H
|
||||
|
||||
PR_BEGIN_EXTERN_C
|
||||
|
||||
typedef struct PLArenaPool PLArenaPool;
|
||||
|
||||
/*
|
||||
** Allocate an arena pool as specified by the parameters.
|
||||
**
|
||||
** This is equivelant to allocating the space yourself and then
|
||||
** calling PL_InitArenaPool().
|
||||
**
|
||||
** This function may fail (and return a NULL) for a variety of
|
||||
** reasons. The reason for a particular failure can be discovered
|
||||
** by calling PR_GetError().
|
||||
*/
|
||||
#if 0 /* Not implemented */
|
||||
PR_EXTERN(PLArenaPool*) PL_AllocArenaPool(
|
||||
const char *name, PRUint32 size, PRUint32 align);
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Destroy an arena pool previously allocated by PL_AllocArenaPool().
|
||||
**
|
||||
** This function may fail if the arena is not empty and the caller
|
||||
** wishes to check for empty upon descruction.
|
||||
*/
|
||||
#if 0 /* Not implemented */
|
||||
PR_EXTERN(PRStatus) PL_DestroyArenaPool(PLArenaPool *pool, PRBool checkEmpty);
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
** Initialize an arena pool with the given name for debugging and metering,
|
||||
** with a minimum size per arena of size bytes.
|
||||
**/
|
||||
PR_EXTERN(void) PL_InitArenaPool(
|
||||
PLArenaPool *pool, const char *name, PRUint32 size, PRUint32 align);
|
||||
|
||||
/*
|
||||
** Finish using arenas, freeing all memory associated with them.
|
||||
**/
|
||||
PR_EXTERN(void) PL_ArenaFinish(void);
|
||||
|
||||
/*
|
||||
** Free the arenas in pool. The user may continue to allocate from pool
|
||||
** after calling this function. There is no need to call PL_InitArenaPool()
|
||||
** again unless PL_FinishArenaPool(pool) has been called.
|
||||
**/
|
||||
PR_EXTERN(void) PL_FreeArenaPool(PLArenaPool *pool);
|
||||
|
||||
/*
|
||||
** Free the arenas in pool and finish using it altogether.
|
||||
**/
|
||||
PR_EXTERN(void) PL_FinishArenaPool(PLArenaPool *pool);
|
||||
|
||||
/*
|
||||
** Compact all of the arenas in a pool so that no space is wasted.
|
||||
**/
|
||||
PR_EXTERN(void) PL_CompactArenaPool(PLArenaPool *pool);
|
||||
|
||||
/*
|
||||
** Friend functions used by the PL_ARENA_*() macros.
|
||||
**/
|
||||
PR_EXTERN(void *) PL_ArenaAllocate(PLArenaPool *pool, PRUint32 nb);
|
||||
|
||||
PR_EXTERN(void *) PL_ArenaGrow(
|
||||
PLArenaPool *pool, void *p, PRUint32 size, PRUint32 incr);
|
||||
|
||||
PR_EXTERN(void) PL_ArenaRelease(PLArenaPool *pool, char *mark);
|
||||
|
||||
PR_END_EXTERN_C
|
||||
|
||||
#endif /* defined(PLARENAS_H) */
|
||||
|
||||
/* plarenas */
|
||||
@@ -1,83 +0,0 @@
|
||||
;+#
|
||||
;+# ***** BEGIN LICENSE BLOCK *****
|
||||
;+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
;+#
|
||||
;+# The contents of this file are subject to the Mozilla 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/MPL/
|
||||
;+#
|
||||
;+# 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 the Netscape Portable Runtime (NSPR).
|
||||
;+#
|
||||
;+# The Initial Developer of the Original Code is
|
||||
;+# Netscape Communications Corporation.
|
||||
;+# Portions created by the Initial Developer are Copyright (C) 2002-2003
|
||||
;+# the Initial Developer. All Rights Reserved.
|
||||
;+#
|
||||
;+# Contributor(s):
|
||||
;+#
|
||||
;+# Alternatively, the contents of this file may be used under the terms of
|
||||
;+# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
;+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
;+# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
;+# of those above. If you wish to allow use of your version of this file only
|
||||
;+# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
;+# use your version of this file under the terms of the MPL, indicate your
|
||||
;+# decision by deleting the provisions above and replace them with the notice
|
||||
;+# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
;+# the provisions above, a recipient may use your version of this file under
|
||||
;+# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
;+#
|
||||
;+# ***** END LICENSE BLOCK *****
|
||||
;+#
|
||||
;+# OK, this file is meant to support SUN, LINUX, AIX, OS/2 and WINDOWS
|
||||
;+# 1. For all unix platforms, the string ";-" means "remove this line"
|
||||
;+# 2. For all unix platforms, the string " DATA " will be removed from any
|
||||
;+# line on which it occurs.
|
||||
;+# 3. Lines containing ";+" will have ";+" removed on SUN and LINUX.
|
||||
;+# On AIX, lines containing ";+" will be removed.
|
||||
;+# 4. For all unix platforms, the string ";;" will thave the ";;" removed.
|
||||
;+# 5. For all unix platforms, after the above processing has taken place,
|
||||
;+# all characters after the first ";" on the line will be removed.
|
||||
;+# And for AIX, the first ";" will also be removed.
|
||||
;+# This file is passed directly to windows. Since ';' is a comment, all UNIX
|
||||
;+# directives are hidden behind ";", ";+", and ";-"
|
||||
;+NSPR_4.0 {
|
||||
;+ global:
|
||||
LIBRARY plds4 ;-
|
||||
EXPORTS ;-
|
||||
PL_ArenaAllocate;
|
||||
PL_ArenaFinish;
|
||||
PL_ArenaGrow;
|
||||
PL_ArenaRelease;
|
||||
PL_CompactArenaPool;
|
||||
PL_CompareStrings;
|
||||
PL_CompareValues;
|
||||
PL_FinishArenaPool;
|
||||
PL_FreeArenaPool;
|
||||
PL_HashString;
|
||||
PL_HashTableAdd;
|
||||
PL_HashTableDestroy;
|
||||
PL_HashTableDump;
|
||||
PL_HashTableEnumerateEntries;
|
||||
PL_HashTableLookup;
|
||||
PL_HashTableRawAdd;
|
||||
PL_HashTableRawLookup;
|
||||
PL_HashTableRawRemove;
|
||||
PL_HashTableRemove;
|
||||
PL_InitArenaPool;
|
||||
PL_NewHashTable;
|
||||
libVersionPoint;
|
||||
;+ local: *;
|
||||
;+};
|
||||
;+
|
||||
;+NSPR_4.1 {
|
||||
;+ global:
|
||||
PL_HashTableLookupConst;
|
||||
PL_HashTableRawLookupConst;
|
||||
;+} NSPR_4.0;
|
||||
@@ -1,102 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla 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/MPL/
|
||||
*
|
||||
* 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 the Netscape Portable Runtime (NSPR).
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1999-2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "prinit.h"
|
||||
#include <winver.h>
|
||||
|
||||
#define MY_LIBNAME "plds"
|
||||
#define MY_FILEDESCRIPTION "PLDS Library"
|
||||
|
||||
#define STRINGIZE(x) #x
|
||||
#define STRINGIZE2(x) STRINGIZE(x)
|
||||
#define PR_VMAJOR_STR STRINGIZE2(PR_VMAJOR)
|
||||
|
||||
#ifdef _DEBUG
|
||||
#define MY_DEBUG_STR " (debug)"
|
||||
#define MY_FILEFLAGS_1 VS_FF_DEBUG
|
||||
#else
|
||||
#define MY_DEBUG_STR ""
|
||||
#define MY_FILEFLAGS_1 0x0L
|
||||
#endif
|
||||
#if PR_BETA
|
||||
#define MY_FILEFLAGS_2 MY_FILEFLAGS_1|VS_FF_PRERELEASE
|
||||
#else
|
||||
#define MY_FILEFLAGS_2 MY_FILEFLAGS_1
|
||||
#endif
|
||||
|
||||
#ifdef WINNT
|
||||
#define MY_FILEOS VOS_NT_WINDOWS32
|
||||
#define MY_INTERNAL_NAME "lib" MY_LIBNAME PR_VMAJOR_STR
|
||||
#else
|
||||
#define MY_FILEOS VOS__WINDOWS32
|
||||
#define MY_INTERNAL_NAME MY_LIBNAME PR_VMAJOR_STR
|
||||
#endif
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Version-information resource
|
||||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION PR_VMAJOR,PR_VMINOR,PR_VPATCH,0
|
||||
PRODUCTVERSION PR_VMAJOR,PR_VMINOR,PR_VPATCH,0
|
||||
FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
|
||||
FILEFLAGS MY_FILEFLAGS_2
|
||||
FILEOS MY_FILEOS
|
||||
FILETYPE VFT_DLL
|
||||
FILESUBTYPE 0x0L // not used
|
||||
|
||||
BEGIN
|
||||
BLOCK "StringFileInfo"
|
||||
BEGIN
|
||||
BLOCK "040904B0" // Lang=US English, CharSet=Unicode
|
||||
BEGIN
|
||||
VALUE "CompanyName", "Netscape Communications Corporation\0"
|
||||
VALUE "FileDescription", MY_FILEDESCRIPTION MY_DEBUG_STR "\0"
|
||||
VALUE "FileVersion", PR_VERSION "\0"
|
||||
VALUE "InternalName", MY_INTERNAL_NAME "\0"
|
||||
VALUE "LegalCopyright", "Copyright \251 1996-2000 Netscape Communications Corporation\0"
|
||||
VALUE "OriginalFilename", MY_INTERNAL_NAME ".dll\0"
|
||||
VALUE "ProductName", "Netscape Portable Runtime\0"
|
||||
VALUE "ProductVersion", PR_VERSION "\0"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
BEGIN
|
||||
VALUE "Translation", 0x409, 1200
|
||||
END
|
||||
END
|
||||
@@ -1,37 +0,0 @@
|
||||
! Fixed section of symbol vector for LIBPLDS4
|
||||
!
|
||||
GSMATCH=LEQUAL,2,2
|
||||
case_sensitive=YES
|
||||
!
|
||||
! --------------------------------------------------------------------------
|
||||
! Ident 2,2 introduced for Mozilla 1.3
|
||||
! Previously this was empty. Now we include everything that's specified in
|
||||
! plds.def.
|
||||
! --------------------------------------------------------------------------
|
||||
!
|
||||
! NSPR 4.0
|
||||
SYMBOL_VECTOR=(PL_ArenaAllocate=PROCEDURE)
|
||||
SYMBOL_VECTOR=(PL_ArenaFinish=PROCEDURE)
|
||||
SYMBOL_VECTOR=(PL_ArenaGrow=PROCEDURE)
|
||||
SYMBOL_VECTOR=(PL_ArenaRelease=PROCEDURE)
|
||||
SYMBOL_VECTOR=(PL_CompactArenaPool=PROCEDURE)
|
||||
SYMBOL_VECTOR=(PL_CompareStrings=PROCEDURE)
|
||||
SYMBOL_VECTOR=(PL_CompareValues=PROCEDURE)
|
||||
SYMBOL_VECTOR=(PL_FinishArenaPool=PROCEDURE)
|
||||
SYMBOL_VECTOR=(PL_FreeArenaPool=PROCEDURE)
|
||||
SYMBOL_VECTOR=(PL_HashString=PROCEDURE)
|
||||
SYMBOL_VECTOR=(PL_HashTableAdd=PROCEDURE)
|
||||
SYMBOL_VECTOR=(PL_HashTableDestroy=PROCEDURE)
|
||||
SYMBOL_VECTOR=(PL_HashTableDump=PROCEDURE)
|
||||
SYMBOL_VECTOR=(PL_HashTableEnumerateEntries=PROCEDURE)
|
||||
SYMBOL_VECTOR=(PL_HashTableLookup=PROCEDURE)
|
||||
SYMBOL_VECTOR=(PL_HashTableRawAdd=PROCEDURE)
|
||||
SYMBOL_VECTOR=(PL_HashTableRawLookup=PROCEDURE)
|
||||
SYMBOL_VECTOR=(PL_HashTableRawRemove=PROCEDURE)
|
||||
SYMBOL_VECTOR=(PL_HashTableRemove=PROCEDURE)
|
||||
SYMBOL_VECTOR=(PL_InitArenaPool=PROCEDURE)
|
||||
SYMBOL_VECTOR=(PL_NewHashTable=PROCEDURE)
|
||||
SYMBOL_VECTOR=(libVersionPoint=PROCEDURE)
|
||||
! NSPR 4.1
|
||||
SYMBOL_VECTOR=(PL_HashTableLookupConst=PROCEDURE)
|
||||
SYMBOL_VECTOR=(PL_HashTableRawLookupConst=PROCEDURE)
|
||||
@@ -1,541 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla 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/MPL/
|
||||
*
|
||||
* 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 the Netscape Portable Runtime (NSPR).
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998-2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/*
|
||||
* PL hash table package.
|
||||
*/
|
||||
#include "plhash.h"
|
||||
#include "prbit.h"
|
||||
#include "prlog.h"
|
||||
#include "prmem.h"
|
||||
#include "prtypes.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
/* Compute the number of buckets in ht */
|
||||
#define NBUCKETS(ht) (1 << (PL_HASH_BITS - (ht)->shift))
|
||||
|
||||
/* The smallest table has 16 buckets */
|
||||
#define MINBUCKETSLOG2 4
|
||||
#define MINBUCKETS (1 << MINBUCKETSLOG2)
|
||||
|
||||
/* Compute the maximum entries given n buckets that we will tolerate, ~90% */
|
||||
#define OVERLOADED(n) ((n) - ((n) >> 3))
|
||||
|
||||
/* Compute the number of entries below which we shrink the table by half */
|
||||
#define UNDERLOADED(n) (((n) > MINBUCKETS) ? ((n) >> 2) : 0)
|
||||
|
||||
/*
|
||||
** Stubs for default hash allocator ops.
|
||||
*/
|
||||
static void * PR_CALLBACK
|
||||
DefaultAllocTable(void *pool, PRSize size)
|
||||
{
|
||||
#if defined(XP_MAC)
|
||||
#pragma unused (pool)
|
||||
#endif
|
||||
|
||||
return PR_MALLOC(size);
|
||||
}
|
||||
|
||||
static void PR_CALLBACK
|
||||
DefaultFreeTable(void *pool, void *item)
|
||||
{
|
||||
#if defined(XP_MAC)
|
||||
#pragma unused (pool)
|
||||
#endif
|
||||
|
||||
PR_Free(item);
|
||||
}
|
||||
|
||||
static PLHashEntry * PR_CALLBACK
|
||||
DefaultAllocEntry(void *pool, const void *key)
|
||||
{
|
||||
#if defined(XP_MAC)
|
||||
#pragma unused (pool,key)
|
||||
#endif
|
||||
|
||||
return PR_NEW(PLHashEntry);
|
||||
}
|
||||
|
||||
static void PR_CALLBACK
|
||||
DefaultFreeEntry(void *pool, PLHashEntry *he, PRUintn flag)
|
||||
{
|
||||
#if defined(XP_MAC)
|
||||
#pragma unused (pool)
|
||||
#endif
|
||||
|
||||
if (flag == HT_FREE_ENTRY)
|
||||
PR_Free(he);
|
||||
}
|
||||
|
||||
static PLHashAllocOps defaultHashAllocOps = {
|
||||
DefaultAllocTable, DefaultFreeTable,
|
||||
DefaultAllocEntry, DefaultFreeEntry
|
||||
};
|
||||
|
||||
PR_IMPLEMENT(PLHashTable *)
|
||||
PL_NewHashTable(PRUint32 n, PLHashFunction keyHash,
|
||||
PLHashComparator keyCompare, PLHashComparator valueCompare,
|
||||
const PLHashAllocOps *allocOps, void *allocPriv)
|
||||
{
|
||||
PLHashTable *ht;
|
||||
PRSize nb;
|
||||
|
||||
if (n <= MINBUCKETS) {
|
||||
n = MINBUCKETSLOG2;
|
||||
} else {
|
||||
n = PR_CeilingLog2(n);
|
||||
if ((PRInt32)n < 0)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!allocOps) allocOps = &defaultHashAllocOps;
|
||||
|
||||
ht = (PLHashTable*)((*allocOps->allocTable)(allocPriv, sizeof *ht));
|
||||
if (!ht)
|
||||
return 0;
|
||||
memset(ht, 0, sizeof *ht);
|
||||
ht->shift = PL_HASH_BITS - n;
|
||||
n = 1 << n;
|
||||
#if defined(WIN16)
|
||||
if (n > 16000) {
|
||||
(*allocOps->freeTable)(allocPriv, ht);
|
||||
return 0;
|
||||
}
|
||||
#endif /* WIN16 */
|
||||
nb = n * sizeof(PLHashEntry *);
|
||||
ht->buckets = (PLHashEntry**)((*allocOps->allocTable)(allocPriv, nb));
|
||||
if (!ht->buckets) {
|
||||
(*allocOps->freeTable)(allocPriv, ht);
|
||||
return 0;
|
||||
}
|
||||
memset(ht->buckets, 0, nb);
|
||||
|
||||
ht->keyHash = keyHash;
|
||||
ht->keyCompare = keyCompare;
|
||||
ht->valueCompare = valueCompare;
|
||||
ht->allocOps = allocOps;
|
||||
ht->allocPriv = allocPriv;
|
||||
return ht;
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(void)
|
||||
PL_HashTableDestroy(PLHashTable *ht)
|
||||
{
|
||||
PRUint32 i, n;
|
||||
PLHashEntry *he, *next;
|
||||
const PLHashAllocOps *allocOps = ht->allocOps;
|
||||
void *allocPriv = ht->allocPriv;
|
||||
|
||||
n = NBUCKETS(ht);
|
||||
for (i = 0; i < n; i++) {
|
||||
for (he = ht->buckets[i]; he; he = next) {
|
||||
next = he->next;
|
||||
(*allocOps->freeEntry)(allocPriv, he, HT_FREE_ENTRY);
|
||||
}
|
||||
}
|
||||
#ifdef DEBUG
|
||||
memset(ht->buckets, 0xDB, n * sizeof ht->buckets[0]);
|
||||
#endif
|
||||
(*allocOps->freeTable)(allocPriv, ht->buckets);
|
||||
#ifdef DEBUG
|
||||
memset(ht, 0xDB, sizeof *ht);
|
||||
#endif
|
||||
(*allocOps->freeTable)(allocPriv, ht);
|
||||
}
|
||||
|
||||
/*
|
||||
** Multiplicative hash, from Knuth 6.4.
|
||||
*/
|
||||
#define GOLDEN_RATIO 0x9E3779B9U /* 2/(1+sqrt(5))*(2^32) */
|
||||
|
||||
PR_IMPLEMENT(PLHashEntry **)
|
||||
PL_HashTableRawLookup(PLHashTable *ht, PLHashNumber keyHash, const void *key)
|
||||
{
|
||||
PLHashEntry *he, **hep, **hep0;
|
||||
PLHashNumber h;
|
||||
|
||||
#ifdef HASHMETER
|
||||
ht->nlookups++;
|
||||
#endif
|
||||
h = keyHash * GOLDEN_RATIO;
|
||||
h >>= ht->shift;
|
||||
hep = hep0 = &ht->buckets[h];
|
||||
while ((he = *hep) != 0) {
|
||||
if (he->keyHash == keyHash && (*ht->keyCompare)(key, he->key)) {
|
||||
/* Move to front of chain if not already there */
|
||||
if (hep != hep0) {
|
||||
*hep = he->next;
|
||||
he->next = *hep0;
|
||||
*hep0 = he;
|
||||
}
|
||||
return hep0;
|
||||
}
|
||||
hep = &he->next;
|
||||
#ifdef HASHMETER
|
||||
ht->nsteps++;
|
||||
#endif
|
||||
}
|
||||
return hep;
|
||||
}
|
||||
|
||||
/*
|
||||
** Same as PL_HashTableRawLookup but doesn't reorder the hash entries.
|
||||
*/
|
||||
PR_IMPLEMENT(PLHashEntry **)
|
||||
PL_HashTableRawLookupConst(PLHashTable *ht, PLHashNumber keyHash,
|
||||
const void *key)
|
||||
{
|
||||
PLHashEntry *he, **hep;
|
||||
PLHashNumber h;
|
||||
|
||||
#ifdef HASHMETER
|
||||
ht->nlookups++;
|
||||
#endif
|
||||
h = keyHash * GOLDEN_RATIO;
|
||||
h >>= ht->shift;
|
||||
hep = &ht->buckets[h];
|
||||
while ((he = *hep) != 0) {
|
||||
if (he->keyHash == keyHash && (*ht->keyCompare)(key, he->key)) {
|
||||
break;
|
||||
}
|
||||
hep = &he->next;
|
||||
#ifdef HASHMETER
|
||||
ht->nsteps++;
|
||||
#endif
|
||||
}
|
||||
return hep;
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(PLHashEntry *)
|
||||
PL_HashTableRawAdd(PLHashTable *ht, PLHashEntry **hep,
|
||||
PLHashNumber keyHash, const void *key, void *value)
|
||||
{
|
||||
PRUint32 i, n;
|
||||
PLHashEntry *he, *next, **oldbuckets;
|
||||
PRSize nb;
|
||||
|
||||
/* Grow the table if it is overloaded */
|
||||
n = NBUCKETS(ht);
|
||||
if (ht->nentries >= OVERLOADED(n)) {
|
||||
oldbuckets = ht->buckets;
|
||||
#if defined(WIN16)
|
||||
if (2 * n > 16000)
|
||||
return 0;
|
||||
#endif /* WIN16 */
|
||||
nb = 2 * n * sizeof(PLHashEntry *);
|
||||
ht->buckets = (PLHashEntry**)
|
||||
((*ht->allocOps->allocTable)(ht->allocPriv, nb));
|
||||
if (!ht->buckets) {
|
||||
ht->buckets = oldbuckets;
|
||||
return 0;
|
||||
}
|
||||
memset(ht->buckets, 0, nb);
|
||||
#ifdef HASHMETER
|
||||
ht->ngrows++;
|
||||
#endif
|
||||
ht->shift--;
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
for (he = oldbuckets[i]; he; he = next) {
|
||||
next = he->next;
|
||||
hep = PL_HashTableRawLookup(ht, he->keyHash, he->key);
|
||||
PR_ASSERT(*hep == 0);
|
||||
he->next = 0;
|
||||
*hep = he;
|
||||
}
|
||||
}
|
||||
#ifdef DEBUG
|
||||
memset(oldbuckets, 0xDB, n * sizeof oldbuckets[0]);
|
||||
#endif
|
||||
(*ht->allocOps->freeTable)(ht->allocPriv, oldbuckets);
|
||||
hep = PL_HashTableRawLookup(ht, keyHash, key);
|
||||
}
|
||||
|
||||
/* Make a new key value entry */
|
||||
he = (*ht->allocOps->allocEntry)(ht->allocPriv, key);
|
||||
if (!he)
|
||||
return 0;
|
||||
he->keyHash = keyHash;
|
||||
he->key = key;
|
||||
he->value = value;
|
||||
he->next = *hep;
|
||||
*hep = he;
|
||||
ht->nentries++;
|
||||
return he;
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(PLHashEntry *)
|
||||
PL_HashTableAdd(PLHashTable *ht, const void *key, void *value)
|
||||
{
|
||||
PLHashNumber keyHash;
|
||||
PLHashEntry *he, **hep;
|
||||
|
||||
keyHash = (*ht->keyHash)(key);
|
||||
hep = PL_HashTableRawLookup(ht, keyHash, key);
|
||||
if ((he = *hep) != 0) {
|
||||
/* Hit; see if values match */
|
||||
if ((*ht->valueCompare)(he->value, value)) {
|
||||
/* key,value pair is already present in table */
|
||||
return he;
|
||||
}
|
||||
if (he->value)
|
||||
(*ht->allocOps->freeEntry)(ht->allocPriv, he, HT_FREE_VALUE);
|
||||
he->value = value;
|
||||
return he;
|
||||
}
|
||||
return PL_HashTableRawAdd(ht, hep, keyHash, key, value);
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(void)
|
||||
PL_HashTableRawRemove(PLHashTable *ht, PLHashEntry **hep, PLHashEntry *he)
|
||||
{
|
||||
PRUint32 i, n;
|
||||
PLHashEntry *next, **oldbuckets;
|
||||
PRSize nb;
|
||||
|
||||
*hep = he->next;
|
||||
(*ht->allocOps->freeEntry)(ht->allocPriv, he, HT_FREE_ENTRY);
|
||||
|
||||
/* Shrink table if it's underloaded */
|
||||
n = NBUCKETS(ht);
|
||||
if (--ht->nentries < UNDERLOADED(n)) {
|
||||
oldbuckets = ht->buckets;
|
||||
nb = n * sizeof(PLHashEntry*) / 2;
|
||||
ht->buckets = (PLHashEntry**)(
|
||||
(*ht->allocOps->allocTable)(ht->allocPriv, nb));
|
||||
if (!ht->buckets) {
|
||||
ht->buckets = oldbuckets;
|
||||
return;
|
||||
}
|
||||
memset(ht->buckets, 0, nb);
|
||||
#ifdef HASHMETER
|
||||
ht->nshrinks++;
|
||||
#endif
|
||||
ht->shift++;
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
for (he = oldbuckets[i]; he; he = next) {
|
||||
next = he->next;
|
||||
hep = PL_HashTableRawLookup(ht, he->keyHash, he->key);
|
||||
PR_ASSERT(*hep == 0);
|
||||
he->next = 0;
|
||||
*hep = he;
|
||||
}
|
||||
}
|
||||
#ifdef DEBUG
|
||||
memset(oldbuckets, 0xDB, n * sizeof oldbuckets[0]);
|
||||
#endif
|
||||
(*ht->allocOps->freeTable)(ht->allocPriv, oldbuckets);
|
||||
}
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(PRBool)
|
||||
PL_HashTableRemove(PLHashTable *ht, const void *key)
|
||||
{
|
||||
PLHashNumber keyHash;
|
||||
PLHashEntry *he, **hep;
|
||||
|
||||
keyHash = (*ht->keyHash)(key);
|
||||
hep = PL_HashTableRawLookup(ht, keyHash, key);
|
||||
if ((he = *hep) == 0)
|
||||
return PR_FALSE;
|
||||
|
||||
/* Hit; remove element */
|
||||
PL_HashTableRawRemove(ht, hep, he);
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(void *)
|
||||
PL_HashTableLookup(PLHashTable *ht, const void *key)
|
||||
{
|
||||
PLHashNumber keyHash;
|
||||
PLHashEntry *he, **hep;
|
||||
|
||||
keyHash = (*ht->keyHash)(key);
|
||||
hep = PL_HashTableRawLookup(ht, keyHash, key);
|
||||
if ((he = *hep) != 0) {
|
||||
return he->value;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
** Same as PL_HashTableLookup but doesn't reorder the hash entries.
|
||||
*/
|
||||
PR_IMPLEMENT(void *)
|
||||
PL_HashTableLookupConst(PLHashTable *ht, const void *key)
|
||||
{
|
||||
PLHashNumber keyHash;
|
||||
PLHashEntry *he, **hep;
|
||||
|
||||
keyHash = (*ht->keyHash)(key);
|
||||
hep = PL_HashTableRawLookupConst(ht, keyHash, key);
|
||||
if ((he = *hep) != 0) {
|
||||
return he->value;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
** Iterate over the entries in the hash table calling func for each
|
||||
** entry found. Stop if "f" says to (return value & PR_ENUMERATE_STOP).
|
||||
** Return a count of the number of elements scanned.
|
||||
*/
|
||||
PR_IMPLEMENT(int)
|
||||
PL_HashTableEnumerateEntries(PLHashTable *ht, PLHashEnumerator f, void *arg)
|
||||
{
|
||||
PLHashEntry *he, **hep;
|
||||
PRUint32 i, nbuckets;
|
||||
int rv, n = 0;
|
||||
PLHashEntry *todo = 0;
|
||||
|
||||
nbuckets = NBUCKETS(ht);
|
||||
for (i = 0; i < nbuckets; i++) {
|
||||
hep = &ht->buckets[i];
|
||||
while ((he = *hep) != 0) {
|
||||
rv = (*f)(he, n, arg);
|
||||
n++;
|
||||
if (rv & (HT_ENUMERATE_REMOVE | HT_ENUMERATE_UNHASH)) {
|
||||
*hep = he->next;
|
||||
if (rv & HT_ENUMERATE_REMOVE) {
|
||||
he->next = todo;
|
||||
todo = he;
|
||||
}
|
||||
} else {
|
||||
hep = &he->next;
|
||||
}
|
||||
if (rv & HT_ENUMERATE_STOP) {
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
hep = &todo;
|
||||
while ((he = *hep) != 0) {
|
||||
PL_HashTableRawRemove(ht, hep, he);
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
#ifdef HASHMETER
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
|
||||
PR_IMPLEMENT(void)
|
||||
PL_HashTableDumpMeter(PLHashTable *ht, PLHashEnumerator dump, FILE *fp)
|
||||
{
|
||||
double mean, variance;
|
||||
PRUint32 nchains, nbuckets;
|
||||
PRUint32 i, n, maxChain, maxChainLen;
|
||||
PLHashEntry *he;
|
||||
|
||||
variance = 0;
|
||||
nchains = 0;
|
||||
maxChainLen = 0;
|
||||
nbuckets = NBUCKETS(ht);
|
||||
for (i = 0; i < nbuckets; i++) {
|
||||
he = ht->buckets[i];
|
||||
if (!he)
|
||||
continue;
|
||||
nchains++;
|
||||
for (n = 0; he; he = he->next)
|
||||
n++;
|
||||
variance += n * n;
|
||||
if (n > maxChainLen) {
|
||||
maxChainLen = n;
|
||||
maxChain = i;
|
||||
}
|
||||
}
|
||||
mean = (double)ht->nentries / nchains;
|
||||
variance = fabs(variance / nchains - mean * mean);
|
||||
|
||||
fprintf(fp, "\nHash table statistics:\n");
|
||||
fprintf(fp, " number of lookups: %u\n", ht->nlookups);
|
||||
fprintf(fp, " number of entries: %u\n", ht->nentries);
|
||||
fprintf(fp, " number of grows: %u\n", ht->ngrows);
|
||||
fprintf(fp, " number of shrinks: %u\n", ht->nshrinks);
|
||||
fprintf(fp, " mean steps per hash: %g\n", (double)ht->nsteps
|
||||
/ ht->nlookups);
|
||||
fprintf(fp, "mean hash chain length: %g\n", mean);
|
||||
fprintf(fp, " standard deviation: %g\n", sqrt(variance));
|
||||
fprintf(fp, " max hash chain length: %u\n", maxChainLen);
|
||||
fprintf(fp, " max hash chain: [%u]\n", maxChain);
|
||||
|
||||
for (he = ht->buckets[maxChain], i = 0; he; he = he->next, i++)
|
||||
if ((*dump)(he, i, fp) != HT_ENUMERATE_NEXT)
|
||||
break;
|
||||
}
|
||||
#endif /* HASHMETER */
|
||||
|
||||
PR_IMPLEMENT(int)
|
||||
PL_HashTableDump(PLHashTable *ht, PLHashEnumerator dump, FILE *fp)
|
||||
{
|
||||
int count;
|
||||
|
||||
count = PL_HashTableEnumerateEntries(ht, dump, fp);
|
||||
#ifdef HASHMETER
|
||||
PL_HashTableDumpMeter(ht, dump, fp);
|
||||
#endif
|
||||
return count;
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(PLHashNumber)
|
||||
PL_HashString(const void *key)
|
||||
{
|
||||
PLHashNumber h;
|
||||
const PRUint8 *s;
|
||||
|
||||
h = 0;
|
||||
for (s = (const PRUint8*)key; *s; s++)
|
||||
h = (h >> 28) ^ (h << 4) ^ *s;
|
||||
return h;
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(int)
|
||||
PL_CompareStrings(const void *v1, const void *v2)
|
||||
{
|
||||
return strcmp((const char*)v1, (const char*)v2) == 0;
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(int)
|
||||
PL_CompareValues(const void *v1, const void *v2)
|
||||
{
|
||||
return v1 == v2;
|
||||
}
|
||||
@@ -1,165 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla 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/MPL/
|
||||
*
|
||||
* 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 the Netscape Portable Runtime (NSPR).
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998-2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef plhash_h___
|
||||
#define plhash_h___
|
||||
/*
|
||||
* API to portable hash table code.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include "prtypes.h"
|
||||
|
||||
PR_BEGIN_EXTERN_C
|
||||
|
||||
typedef struct PLHashEntry PLHashEntry;
|
||||
typedef struct PLHashTable PLHashTable;
|
||||
typedef PRUint32 PLHashNumber;
|
||||
#define PL_HASH_BITS 32 /* Number of bits in PLHashNumber */
|
||||
typedef PLHashNumber (PR_CALLBACK *PLHashFunction)(const void *key);
|
||||
typedef PRIntn (PR_CALLBACK *PLHashComparator)(const void *v1, const void *v2);
|
||||
|
||||
#if defined(XP_OS2_VACPP) && defined(VACPP_FLIP) /* for nsSpaceManager.cpp */
|
||||
PR_END_EXTERN_C /* and nsHTMLDocument.cpp */
|
||||
#endif
|
||||
typedef PRIntn (PR_CALLBACK *PLHashEnumerator)(PLHashEntry *he, PRIntn i, void *arg);
|
||||
|
||||
#if defined(XP_OS2_VACPP) && defined(VACPP_FLIP)
|
||||
PR_BEGIN_EXTERN_C
|
||||
#endif
|
||||
|
||||
/* Flag bits in PLHashEnumerator's return value */
|
||||
#define HT_ENUMERATE_NEXT 0 /* continue enumerating entries */
|
||||
#define HT_ENUMERATE_STOP 1 /* stop enumerating entries */
|
||||
#define HT_ENUMERATE_REMOVE 2 /* remove and free the current entry */
|
||||
#define HT_ENUMERATE_UNHASH 4 /* just unhash the current entry */
|
||||
|
||||
typedef struct PLHashAllocOps {
|
||||
void * (PR_CALLBACK *allocTable)(void *pool, PRSize size);
|
||||
void (PR_CALLBACK *freeTable)(void *pool, void *item);
|
||||
PLHashEntry * (PR_CALLBACK *allocEntry)(void *pool, const void *key);
|
||||
void (PR_CALLBACK *freeEntry)(void *pool, PLHashEntry *he, PRUintn flag);
|
||||
} PLHashAllocOps;
|
||||
|
||||
#define HT_FREE_VALUE 0 /* just free the entry's value */
|
||||
#define HT_FREE_ENTRY 1 /* free value and entire entry */
|
||||
|
||||
struct PLHashEntry {
|
||||
PLHashEntry *next; /* hash chain linkage */
|
||||
PLHashNumber keyHash; /* key hash function result */
|
||||
const void *key; /* ptr to opaque key */
|
||||
void *value; /* ptr to opaque value */
|
||||
};
|
||||
|
||||
struct PLHashTable {
|
||||
PLHashEntry **buckets; /* vector of hash buckets */
|
||||
PRUint32 nentries; /* number of entries in table */
|
||||
PRUint32 shift; /* multiplicative hash shift */
|
||||
PLHashFunction keyHash; /* key hash function */
|
||||
PLHashComparator keyCompare; /* key comparison function */
|
||||
PLHashComparator valueCompare; /* value comparison function */
|
||||
const PLHashAllocOps *allocOps; /* allocation operations */
|
||||
void *allocPriv; /* allocation private data */
|
||||
#ifdef HASHMETER
|
||||
PRUint32 nlookups; /* total number of lookups */
|
||||
PRUint32 nsteps; /* number of hash chains traversed */
|
||||
PRUint32 ngrows; /* number of table expansions */
|
||||
PRUint32 nshrinks; /* number of table contractions */
|
||||
#endif
|
||||
};
|
||||
|
||||
/*
|
||||
* Create a new hash table.
|
||||
* If allocOps is null, use default allocator ops built on top of malloc().
|
||||
*/
|
||||
PR_EXTERN(PLHashTable *)
|
||||
PL_NewHashTable(PRUint32 numBuckets, PLHashFunction keyHash,
|
||||
PLHashComparator keyCompare, PLHashComparator valueCompare,
|
||||
const PLHashAllocOps *allocOps, void *allocPriv);
|
||||
|
||||
PR_EXTERN(void)
|
||||
PL_HashTableDestroy(PLHashTable *ht);
|
||||
|
||||
/* Higher level access methods */
|
||||
PR_EXTERN(PLHashEntry *)
|
||||
PL_HashTableAdd(PLHashTable *ht, const void *key, void *value);
|
||||
|
||||
PR_EXTERN(PRBool)
|
||||
PL_HashTableRemove(PLHashTable *ht, const void *key);
|
||||
|
||||
PR_EXTERN(void *)
|
||||
PL_HashTableLookup(PLHashTable *ht, const void *key);
|
||||
|
||||
PR_EXTERN(void *)
|
||||
PL_HashTableLookupConst(PLHashTable *ht, const void *key);
|
||||
|
||||
PR_EXTERN(PRIntn)
|
||||
PL_HashTableEnumerateEntries(PLHashTable *ht, PLHashEnumerator f, void *arg);
|
||||
|
||||
/* General-purpose C string hash function. */
|
||||
PR_EXTERN(PLHashNumber)
|
||||
PL_HashString(const void *key);
|
||||
|
||||
/* Compare strings using strcmp(), return true if equal. */
|
||||
PR_EXTERN(PRIntn)
|
||||
PL_CompareStrings(const void *v1, const void *v2);
|
||||
|
||||
/* Stub function just returns v1 == v2 */
|
||||
PR_EXTERN(PRIntn)
|
||||
PL_CompareValues(const void *v1, const void *v2);
|
||||
|
||||
/* Low level access methods */
|
||||
PR_EXTERN(PLHashEntry **)
|
||||
PL_HashTableRawLookup(PLHashTable *ht, PLHashNumber keyHash, const void *key);
|
||||
|
||||
PR_EXTERN(PLHashEntry **)
|
||||
PL_HashTableRawLookupConst(PLHashTable *ht, PLHashNumber keyHash,
|
||||
const void *key);
|
||||
|
||||
PR_EXTERN(PLHashEntry *)
|
||||
PL_HashTableRawAdd(PLHashTable *ht, PLHashEntry **hep, PLHashNumber keyHash,
|
||||
const void *key, void *value);
|
||||
|
||||
PR_EXTERN(void)
|
||||
PL_HashTableRawRemove(PLHashTable *ht, PLHashEntry **hep, PLHashEntry *he);
|
||||
|
||||
/* This can be trivially implemented using PL_HashTableEnumerateEntries. */
|
||||
PR_EXTERN(PRIntn)
|
||||
PL_HashTableDump(PLHashTable *ht, PLHashEnumerator dump, FILE *fp);
|
||||
|
||||
PR_END_EXTERN_C
|
||||
|
||||
#endif /* plhash_h___ */
|
||||
@@ -1,125 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla 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/MPL/
|
||||
*
|
||||
* 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 the Netscape Portable Runtime (NSPR).
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998-2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "prinit.h"
|
||||
#include "prvrsion.h"
|
||||
|
||||
/************************************************************************/
|
||||
/**************************IDENTITY AND VERSIONING***********************/
|
||||
/************************************************************************/
|
||||
#include "_pl_bld.h"
|
||||
#if !defined(_BUILD_TIME)
|
||||
#ifdef HAVE_LONG_LONG
|
||||
#define _BUILD_TIME 0
|
||||
#else
|
||||
#define _BUILD_TIME {0, 0}
|
||||
#endif
|
||||
#endif
|
||||
#if !defined(_BUILD_STRING)
|
||||
#define _BUILD_STRING ""
|
||||
#endif
|
||||
#if !defined(_PRODUCTION)
|
||||
#define _PRODUCTION ""
|
||||
#endif
|
||||
#if defined(DEBUG)
|
||||
#define _DEBUG_STRING " (debug)"
|
||||
#else
|
||||
#define _DEBUG_STRING ""
|
||||
#endif
|
||||
|
||||
/*
|
||||
* A trick to expand the PR_VMAJOR macro before concatenation.
|
||||
*/
|
||||
#define CONCAT(x, y) x ## y
|
||||
#define CONCAT2(x, y) CONCAT(x, y)
|
||||
#define VERSION_DESC_NAME CONCAT2(prVersionDescription_libplds, PR_VMAJOR)
|
||||
|
||||
PRVersionDescription VERSION_DESC_NAME =
|
||||
{
|
||||
/* version */ 2, /* this is the only one supported */
|
||||
/* buildTime */ _BUILD_TIME, /* usecs since midnight 1/1/1970 GMT */
|
||||
/* buildTimeString */ _BUILD_STRING, /* ditto, but human readable */
|
||||
/* vMajor */ PR_VMAJOR, /* NSPR's version number */
|
||||
/* vMinor */ PR_VMINOR, /* and minor version */
|
||||
/* vPatch */ PR_VPATCH, /* and patch */
|
||||
/* beta */ PR_BETA, /* beta build boolean */
|
||||
#if defined(DEBUG)
|
||||
/* debug */ PR_TRUE, /* a debug build */
|
||||
#else
|
||||
/* debug */ PR_FALSE, /* an optomized build */
|
||||
#endif
|
||||
/* special */ PR_FALSE, /* they're all special, but ... */
|
||||
/* filename */ _PRODUCTION, /* the produced library name */
|
||||
/* description */ "Portable runtime", /* what we are */
|
||||
/* security */ "N/A", /* not applicable here */
|
||||
/* copywrite */ "Copyright (c) 1998 Netscape Communications Corporation. All Rights Reserved",
|
||||
/* comment */ "http://www.mozilla.org/MPL/",
|
||||
/* specialString */ ""
|
||||
};
|
||||
|
||||
#ifdef XP_UNIX
|
||||
|
||||
/*
|
||||
* Version information for the 'ident' and 'what commands
|
||||
*
|
||||
* NOTE: the first component of the concatenated rcsid string
|
||||
* must not end in a '$' to prevent rcs keyword substitution.
|
||||
*/
|
||||
static char rcsid[] = "$Header: NSPR " PR_VERSION _DEBUG_STRING
|
||||
" " _BUILD_STRING " $";
|
||||
static char sccsid[] = "@(#)NSPR " PR_VERSION _DEBUG_STRING
|
||||
" " _BUILD_STRING;
|
||||
|
||||
#endif /* XP_UNIX */
|
||||
|
||||
PR_IMPLEMENT(const PRVersionDescription*) libVersionPoint()
|
||||
{
|
||||
#ifdef XP_UNIX
|
||||
/*
|
||||
* Add dummy references to rcsid and sccsid to prevent them
|
||||
* from being optimized away as unused variables.
|
||||
*/
|
||||
const char *dummy;
|
||||
|
||||
dummy = rcsid;
|
||||
dummy = sccsid;
|
||||
#endif
|
||||
return &VERSION_DESC_NAME;
|
||||
} /* versionEntryPointType */
|
||||
|
||||
/* plvrsion.c */
|
||||
|
||||
@@ -1,56 +0,0 @@
|
||||
#
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla 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/MPL/
|
||||
#
|
||||
# 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 the Netscape Portable Runtime (NSPR).
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Netscape Communications Corporation.
|
||||
# Portions created by the Initial Developer are Copyright (C) 1998-2000
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
#! gmake
|
||||
|
||||
MOD_DEPTH = ../..
|
||||
topsrcdir = @top_srcdir@
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
include $(MOD_DEPTH)/config/autoconf.mk
|
||||
|
||||
export NSPR20=1
|
||||
|
||||
include $(topsrcdir)/config/config.mk
|
||||
|
||||
DIRS = include src
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
export:: $(TARGETS)
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
NSPR 2.0 libc functions
|
||||
-----------------------
|
||||
|
||||
Last edited: AOF 04 March 1997
|
||||
|
||||
This directory contains various libc-types of functions. All functions in
|
||||
this directory are platform independent, thread friendly (both safe and
|
||||
efficient). They are contributed from various sources, though the contri-
|
||||
butions are monitored by the NSPR group (mailto:freier).
|
||||
|
||||
All API items exported by these functions will contain the same three
|
||||
character prefix, "PL_" (Portable Library). Internal function names
|
||||
that are not exported (static) are of little concern, though some caution
|
||||
must be used on those elements that are 'extern' but not really intended
|
||||
to be part of the API. Those should all have a prefix of "_PL_" (is that
|
||||
legal?).
|
||||
|
||||
The responsibility for contributions in this area are distributed among
|
||||
all interested parties.
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
#
|
||||
# This is a list of local files which get copied to the mozilla:dist directory
|
||||
#
|
||||
|
||||
plbase64.h
|
||||
plerror.h
|
||||
plgetopt.h
|
||||
plresolv.h
|
||||
plstr.h
|
||||
@@ -1,61 +0,0 @@
|
||||
#
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla 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/MPL/
|
||||
#
|
||||
# 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 the Netscape Portable Runtime (NSPR).
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Netscape Communications Corporation.
|
||||
# Portions created by the Initial Developer are Copyright (C) 1998-2000
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
#! gmake
|
||||
|
||||
MOD_DEPTH = ../../..
|
||||
topsrcdir = @top_srcdir@
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
include $(MOD_DEPTH)/config/autoconf.mk
|
||||
include $(topsrcdir)/config/config.mk
|
||||
|
||||
HEADERS = $(wildcard $(srcdir)/*.h)
|
||||
|
||||
RELEASE_HEADERS = $(HEADERS)
|
||||
RELEASE_HEADERS_DEST = $(RELEASE_INCLUDE_DIR)
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
export:: $(HEADERS)
|
||||
$(INSTALL) -m 444 $(HEADERS) $(dist_includedir)
|
||||
ifeq ($(MOZ_BITS),16)
|
||||
$(INSTALL) -m 444 $(HEADERS) $(MOZ_INCL)
|
||||
endif
|
||||
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
NSPR 2.0 libc functions
|
||||
-----------------------
|
||||
|
||||
Last edited: AOF 04 March 1997
|
||||
|
||||
This directory contains the API for various libc-types of functions.
|
||||
|
||||
@@ -1,98 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla 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/MPL/
|
||||
*
|
||||
* 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 the Netscape Portable Runtime (NSPR).
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998-2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef _plbase64_h
|
||||
#define _plbase64_h
|
||||
|
||||
#include "prtypes.h"
|
||||
|
||||
PR_BEGIN_EXTERN_C
|
||||
|
||||
/*
|
||||
* PL_Base64Encode
|
||||
*
|
||||
* This routine encodes the data pointed to by the "src" parameter using the
|
||||
* base64 algorithm, and returns a pointer to the result. If the "srclen"
|
||||
* parameter is not zero, it specifies the length of the source data. If it
|
||||
* is zero, the source data is assumed to be null-terminated, and PL_strlen
|
||||
* is used to determine the source length. If the "dest" parameter is not
|
||||
* null, it is assumed to point to a buffer of sufficient size (which may be
|
||||
* calculated: ((srclen + 2)/3)*4) into which the encoded data is placed
|
||||
* (without any termination). If the "dest" parameter is null, a buffer is
|
||||
* allocated from the heap to hold the encoded data, and the result *will*
|
||||
* be terminated with an extra null character. It is the caller's
|
||||
* responsibility to free the result when it is allocated. A null is returned
|
||||
* if the allocation fails.
|
||||
*/
|
||||
|
||||
PR_EXTERN(char *)
|
||||
PL_Base64Encode
|
||||
(
|
||||
const char *src,
|
||||
PRUint32 srclen,
|
||||
char *dest
|
||||
);
|
||||
|
||||
/*
|
||||
* PL_Base64Decode
|
||||
*
|
||||
* This routine decodes the data pointed to by the "src" parameter using
|
||||
* the base64 algorithm, and returns a pointer to the result. The source
|
||||
* may either include or exclude any trailing '=' characters. If the
|
||||
* "srclen" parameter is not zero, it specifies the length of the source
|
||||
* data. If it is zero, PL_strlen will be used to determine the source
|
||||
* length. If the "dest" parameter is not null, it is assumed to point to
|
||||
* a buffer of sufficient size (which may be calculated: (srclen * 3)/4
|
||||
* when srclen includes the '=' characters) into which the decoded data
|
||||
* is placed (without any termination). If the "dest" parameter is null,
|
||||
* a buffer is allocated from the heap to hold the decoded data, and the
|
||||
* result *will* be terminated with an extra null character. It is the
|
||||
* caller's responsibility to free the result when it is allocated. A null
|
||||
* is retuned if the allocation fails, or if the source is not well-coded.
|
||||
*/
|
||||
|
||||
PR_EXTERN(char *)
|
||||
PL_Base64Decode
|
||||
(
|
||||
const char *src,
|
||||
PRUint32 srclen,
|
||||
char *dest
|
||||
);
|
||||
|
||||
PR_END_EXTERN_C
|
||||
|
||||
#endif /* _plbase64_h */
|
||||
@@ -1,66 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla 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/MPL/
|
||||
*
|
||||
* 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 the Netscape Portable Runtime (NSPR).
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998-2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/*
|
||||
** File: plerror.h
|
||||
** Description: Simple routine to print translate the calling thread's
|
||||
** error numbers and print them.
|
||||
*/
|
||||
|
||||
#if defined(PLERROR_H)
|
||||
#else
|
||||
#define PLERROR_H
|
||||
|
||||
#include "prio.h"
|
||||
#include "prtypes.h"
|
||||
|
||||
PR_BEGIN_EXTERN_C
|
||||
/*
|
||||
** Print the messages to "syserr" prepending 'msg' if not NULL.
|
||||
*/
|
||||
PR_EXTERN(void) PL_PrintError(const char *msg);
|
||||
|
||||
/*
|
||||
** Print the messages to specified output file prepending 'msg' if not NULL.
|
||||
*/
|
||||
PR_EXTERN(void) PL_FPrintError(PRFileDesc *output, const char *msg);
|
||||
|
||||
PR_END_EXTERN_C
|
||||
|
||||
#endif /* defined(PLERROR_H) */
|
||||
|
||||
/* plerror.h */
|
||||
@@ -1,81 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla 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/MPL/
|
||||
*
|
||||
* 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 the Netscape Portable Runtime (NSPR).
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998-2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/*
|
||||
** File: plgetopt.h
|
||||
** Description: utilities to parse argc/argv
|
||||
*/
|
||||
|
||||
#if defined(PLGETOPT_H_)
|
||||
#else
|
||||
#define PLGETOPT_H_
|
||||
|
||||
#include "prtypes.h"
|
||||
|
||||
PR_BEGIN_EXTERN_C
|
||||
|
||||
typedef struct PLOptionInternal PLOptionInternal;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
PL_OPT_OK, /* all's well with the option */
|
||||
PL_OPT_EOL, /* end of options list */
|
||||
PL_OPT_BAD /* invalid option (and value) */
|
||||
} PLOptStatus;
|
||||
|
||||
typedef struct PLOptState
|
||||
{
|
||||
char option; /* the name of the option */
|
||||
const char *value; /* the value of that option | NULL */
|
||||
|
||||
PLOptionInternal *internal; /* private processing state */
|
||||
|
||||
} PLOptState;
|
||||
|
||||
PR_EXTERN(PLOptState*) PL_CreateOptState(
|
||||
PRIntn argc, char **argv, const char *options);
|
||||
|
||||
PR_EXTERN(void) PL_DestroyOptState(PLOptState *opt);
|
||||
|
||||
PR_EXTERN(PLOptStatus) PL_GetNextOpt(PLOptState *opt);
|
||||
|
||||
PR_END_EXTERN_C
|
||||
|
||||
#endif /* defined(PLGETOPT_H_) */
|
||||
|
||||
/* plgetopt.h */
|
||||
|
||||
@@ -1,108 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla 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/MPL/
|
||||
*
|
||||
* 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 the Netscape Portable Runtime (NSPR).
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998-2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/*
|
||||
* plresolv.h - asynchronous name resolution using DNS
|
||||
*/
|
||||
|
||||
#ifndef _PLRESOLV_H_
|
||||
#define _PLRESOLV_H_
|
||||
|
||||
/*
|
||||
** THIS IS WORK IN PROGRESS. DO NOT ATTEMPT TO USE ANY PORTION OF THIS
|
||||
** API UNTIL THIS MESSAGE NO LONGER EXISTS. IF YOU DO, THEN YOU SURRENDER
|
||||
** THE RIGHT TO COMPLAIN ABOUT ANY CONTENT.
|
||||
*/
|
||||
|
||||
#if defined(XP_UNIX)
|
||||
|
||||
#include <prtypes.h>
|
||||
#include <prnetdb.h>
|
||||
|
||||
NSPR_BEGIN_EXTERN_C
|
||||
|
||||
#define PL_RESOLVE_MAXHOSTENTBUF 1024
|
||||
#define PL_RESOLVE_DEFAULT_TIMEOUT 0
|
||||
|
||||
/* Error return codes */
|
||||
#define PL_RESOLVE_OK 0
|
||||
#define PL_RESOLVE_EWINIT 1 /* Failed to initialize window */
|
||||
#define PL_RESOLVE_EMAKE 2 /* Failed to create request */
|
||||
#define PL_RESOLVE_ELAUNCH 3 /* Error launching Async request */
|
||||
#define PL_RESOLVE_ETIMEDOUT 4 /* Request timed-out */
|
||||
#define PL_RESOLVE_EINVAL 5 /* Invalid argument */
|
||||
#define PL_RESOLVE_EOVERFLOW 6 /* Buffer Overflow */
|
||||
#define PL_RESOLVE_EUNKNOWN 7 /* berserk error */
|
||||
|
||||
/* ----------- Function Prototypes ----------------*/
|
||||
|
||||
PR_EXTERN(PRStatus) PL_ResolveName(
|
||||
const char *name, unsigned char *buf,
|
||||
PRIntn bufsize, PRIntervalTime timeout,
|
||||
PRHostEnt *hostentry, PRIntervalTime *ttl);
|
||||
|
||||
PR_EXTERN(PRStatus) PL_ResolveAddr(
|
||||
const PRNetAddr *address, unsigned char *buf,
|
||||
PRIntn bufsize, PRIntervalTime timeout,
|
||||
PRHostEnt *hostentry, PRIntervalTime *ttl);
|
||||
|
||||
typedef struct PLResolveStats {
|
||||
int re_errors;
|
||||
int re_nu_look;
|
||||
int re_na_look;
|
||||
int re_replies;
|
||||
int re_requests;
|
||||
int re_resends;
|
||||
int re_sent;
|
||||
int re_timeouts;
|
||||
} PLResolveStats;
|
||||
|
||||
typedef struct PLResoveInfo {
|
||||
PRBool enabled;
|
||||
PRUint32 numNameLookups;
|
||||
PRUint32 numAddrLookups;
|
||||
PRUint32 numLookupsInProgress;
|
||||
PLResolveStats stats;
|
||||
} PLResoveInfo;
|
||||
|
||||
PR_EXTERN(void) PL_ResolveInfo(PLResoveInfo *info);
|
||||
|
||||
NSPR_END_EXTERN_C
|
||||
|
||||
#endif /* defined(XP_UNIX) */
|
||||
|
||||
#endif /* _PLRESOLV_H_ */
|
||||
@@ -1,470 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla 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/MPL/
|
||||
*
|
||||
* 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 the Netscape Portable Runtime (NSPR).
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998-2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Roland Mainz <roland mainz@informatik.med.uni-giessen.de>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef _plstr_h
|
||||
#define _plstr_h
|
||||
|
||||
/*
|
||||
* plstr.h
|
||||
*
|
||||
* This header file exports the API to the NSPR portable library or string-
|
||||
* handling functions.
|
||||
*
|
||||
* This API was not designed as an "optimal" or "ideal" string library; it
|
||||
* was based on the good ol' unix string.3 functions, and was written to
|
||||
*
|
||||
* 1) replace the libc functions, for cross-platform consistency,
|
||||
* 2) complete the API on platforms lacking common functions (e.g.,
|
||||
* strcase*), and
|
||||
* 3) to implement some obvious "closure" functions that I've seen
|
||||
* people hacking around in our code.
|
||||
*
|
||||
* Point number three largely means that most functions have an "strn"
|
||||
* limited-length version, and all comparison routines have a non-case-
|
||||
* sensitive version available.
|
||||
*/
|
||||
|
||||
#include "prtypes.h"
|
||||
|
||||
PR_BEGIN_EXTERN_C
|
||||
/*
|
||||
* PL_strlen
|
||||
*
|
||||
* Returns the length of the provided string, not including the trailing '\0'.
|
||||
*/
|
||||
|
||||
PR_EXTERN(PRUint32)
|
||||
PL_strlen(const char *str);
|
||||
|
||||
/*
|
||||
* PL_strnlen
|
||||
*
|
||||
* Returns the length of the provided string, not including the trailing '\0',
|
||||
* up to the indicated maximum. The string will not be examined beyond the
|
||||
* maximum; if no terminating '\0' is found, the maximum will be returned.
|
||||
*/
|
||||
|
||||
PR_EXTERN(PRUint32)
|
||||
PL_strnlen(const char *str, PRUint32 max);
|
||||
|
||||
/*
|
||||
* PL_strcpy
|
||||
*
|
||||
* Copies the source string, up to and including the trailing '\0', into the
|
||||
* destination buffer. It does not (can not) verify that the destination
|
||||
* buffer is large enough. It returns the "dest" argument.
|
||||
*/
|
||||
|
||||
PR_EXTERN(char *)
|
||||
PL_strcpy(char *dest, const char *src);
|
||||
|
||||
/*
|
||||
* PL_strncpy
|
||||
*
|
||||
* Copies the source string into the destination buffer, up to and including
|
||||
* the trailing '\0' or up to and including the max'th character, whichever
|
||||
* comes first. It does not (can not) verify that the destination buffer is
|
||||
* large enough. If the source string is longer than the maximum length,
|
||||
* the result will *not* be null-terminated (JLRU).
|
||||
*/
|
||||
|
||||
PR_EXTERN(char *)
|
||||
PL_strncpy(char *dest, const char *src, PRUint32 max);
|
||||
|
||||
/*
|
||||
* PL_strncpyz
|
||||
*
|
||||
* Copies the source string into the destination buffer, up to and including
|
||||
* the trailing '\0' or up but not including the max'th character, whichever
|
||||
* comes first. It does not (can not) verify that the destination buffer is
|
||||
* large enough. The destination string is always terminated with a '\0',
|
||||
* unlike the traditional libc implementation. It returns the "dest" argument.
|
||||
*
|
||||
* NOTE: If you call this with a source "abcdefg" and a max of 5, the
|
||||
* destination will end up with "abcd\0" (i.e., its strlen length will be 4)!
|
||||
*
|
||||
* This means you can do this:
|
||||
*
|
||||
* char buffer[ SOME_SIZE ];
|
||||
* PL_strncpyz(buffer, src, sizeof(buffer));
|
||||
*
|
||||
* and the result will be properly terminated.
|
||||
*/
|
||||
|
||||
PR_EXTERN(char *)
|
||||
PL_strncpyz(char *dest, const char *src, PRUint32 max);
|
||||
|
||||
/*
|
||||
* PL_strdup
|
||||
*
|
||||
* Returns a pointer to a malloc'd extent of memory containing a duplicate
|
||||
* of the argument string. The size of the allocated extent is one greater
|
||||
* than the length of the argument string, because of the terminator. A
|
||||
* null argument, like a zero-length argument, will result in a pointer to
|
||||
* a one-byte extent containing the null value. This routine returns null
|
||||
* upon malloc failure.
|
||||
*/
|
||||
|
||||
PR_EXTERN(char *)
|
||||
PL_strdup(const char *s);
|
||||
|
||||
/*
|
||||
* PL_strfree
|
||||
*
|
||||
* Free memory allocated by PL_strdup
|
||||
*/
|
||||
|
||||
PR_EXTERN(void)
|
||||
PL_strfree(char *s);
|
||||
|
||||
/*
|
||||
* PL_strndup
|
||||
*
|
||||
* Returns a pointer to a malloc'd extent of memory containing a duplicate
|
||||
* of the argument string, up to the maximum specified. If the argument
|
||||
* string has a length greater than the value of the specified maximum, the
|
||||
* return value will be a pointer to an extent of memory of length one
|
||||
* greater than the maximum specified. A null string, a zero-length string,
|
||||
* or a zero maximum will all result in a pointer to a one-byte extent
|
||||
* containing the null value. This routine returns null upon malloc failure.
|
||||
*/
|
||||
|
||||
PR_EXTERN(char *)
|
||||
PL_strndup(const char *s, PRUint32 max);
|
||||
|
||||
/*
|
||||
* PL_strcat
|
||||
*
|
||||
* Appends a copy of the string pointed to by the second argument to the
|
||||
* end of the string pointed to by the first. The destination buffer is
|
||||
* not (can not be) checked for sufficient size. A null destination
|
||||
* argument returns null; otherwise, the first argument is returned.
|
||||
*/
|
||||
|
||||
PR_EXTERN(char *)
|
||||
PL_strcat(char *dst, const char *src);
|
||||
|
||||
/*
|
||||
* PL_strncat
|
||||
*
|
||||
* Appends a copy of the string pointed to by the second argument, up to
|
||||
* the maximum size specified, to the end of the string pointed to by the
|
||||
* first. The destination buffer is not (can not be) checked for sufficient
|
||||
* size. A null destination argument returns null; otherwise, the first
|
||||
* argument is returned. If the maximum size limits the copy, then the
|
||||
* result will *not* be null-terminated (JLRU). A null destination
|
||||
* returns null; otherwise, the destination argument is returned.
|
||||
*/
|
||||
|
||||
PR_EXTERN(char *)
|
||||
PL_strncat(char *dst, const char *src, PRUint32 max);
|
||||
|
||||
/*
|
||||
* PL_strcatn
|
||||
*
|
||||
* Appends a copy of the string pointed to by the third argument, to the
|
||||
* end of the string pointed to by the first. The second argument specifies
|
||||
* the maximum size of the destination buffer, including the null termination.
|
||||
* If the existing string in dst is longer than the max, no action is taken.
|
||||
* The resulting string will be null-terminated. A null destination returns
|
||||
* null; otherwise, the destination argument is returned.
|
||||
*/
|
||||
|
||||
PR_EXTERN(char *)
|
||||
PL_strcatn(char *dst, PRUint32 max, const char *src);
|
||||
|
||||
/*
|
||||
* PL_strcmp
|
||||
*
|
||||
* Returns an integer, the sign of which -- positive, zero, or negative --
|
||||
* reflects the lexical sorting order of the two strings indicated. The
|
||||
* result is positive if the first string comes after the second. The
|
||||
* NSPR implementation is not i18n.
|
||||
*/
|
||||
|
||||
PR_EXTERN(PRIntn)
|
||||
PL_strcmp(const char *a, const char *b);
|
||||
|
||||
/*
|
||||
* PL_strncmp
|
||||
*
|
||||
* Returns an integer, the sign of which -- positive, zero, or negative --
|
||||
* reflects the lexical sorting order of the two strings indicated, up to
|
||||
* the maximum specified. The result is positive if the first string comes
|
||||
* after the second. The NSPR implementation is not i18n. If the maximum
|
||||
* is zero, only the existance or non-existance (pointer is null) of the
|
||||
* strings is compared.
|
||||
*/
|
||||
|
||||
PR_EXTERN(PRIntn)
|
||||
PL_strncmp(const char *a, const char *b, PRUint32 max);
|
||||
|
||||
/*
|
||||
* PL_strcasecmp
|
||||
*
|
||||
* Returns an integer, the sign of which -- positive, zero or negative --
|
||||
* reflects the case-insensitive lexical sorting order of the two strings
|
||||
* indicated. The result is positive if the first string comes after the
|
||||
* second. The NSPR implementation is not i18n.
|
||||
*/
|
||||
|
||||
PR_EXTERN(PRIntn)
|
||||
PL_strcasecmp(const char *a, const char *b);
|
||||
|
||||
/*
|
||||
* PL_strncasecmp
|
||||
*
|
||||
* Returns an integer, the sign of which -- positive, zero or negative --
|
||||
* reflects the case-insensitive lexical sorting order of the first n characters
|
||||
* of the two strings indicated. The result is positive if the first string comes
|
||||
* after the second. The NSPR implementation is not i18n.
|
||||
*/
|
||||
|
||||
PR_EXTERN(PRIntn)
|
||||
PL_strncasecmp(const char *a, const char *b, PRUint32 max);
|
||||
|
||||
/*
|
||||
* PL_strchr
|
||||
*
|
||||
* Returns a pointer to the first instance of the specified character in the
|
||||
* provided string. It returns null if the character is not found, or if the
|
||||
* provided string is null. The character may be the null character.
|
||||
*/
|
||||
|
||||
PR_EXTERN(char *)
|
||||
PL_strchr(const char *s, char c);
|
||||
|
||||
/*
|
||||
* PL_strrchr
|
||||
*
|
||||
* Returns a pointer to the last instance of the specified character in the
|
||||
* provided string. It returns null if the character is not found, or if the
|
||||
* provided string is null. The character may be the null character.
|
||||
*/
|
||||
|
||||
PR_EXTERN(char *)
|
||||
PL_strrchr(const char *s, char c);
|
||||
|
||||
/*
|
||||
* PL_strnchr
|
||||
*
|
||||
* Returns a pointer to the first instance of the specified character within the
|
||||
* first n characters of the provided string. It returns null if the character
|
||||
* is not found, or if the provided string is null. The character may be the
|
||||
* null character.
|
||||
*/
|
||||
|
||||
PR_EXTERN(char *)
|
||||
PL_strnchr(const char *s, char c, PRUint32 n);
|
||||
|
||||
/*
|
||||
* PL_strnrchr
|
||||
*
|
||||
* Returns a pointer to the last instance of the specified character within the
|
||||
* first n characters of the provided string. It returns null if the character is
|
||||
* not found, or if the provided string is null. The character may be the null
|
||||
* character.
|
||||
*/
|
||||
|
||||
PR_EXTERN(char *)
|
||||
PL_strnrchr(const char *s, char c, PRUint32 n);
|
||||
|
||||
/*
|
||||
* NOTE: Looking for strcasechr, strcaserchr, strncasechr, or strncaserchr?
|
||||
* Use strpbrk, strprbrk, strnpbrk or strnprbrk.
|
||||
*/
|
||||
|
||||
/*
|
||||
* PL_strpbrk
|
||||
*
|
||||
* Returns a pointer to the first instance in the first string of any character
|
||||
* (not including the terminating null character) of the second string. It returns
|
||||
* null if either string is null.
|
||||
*/
|
||||
|
||||
PR_EXTERN(char *)
|
||||
PL_strpbrk(const char *s, const char *list);
|
||||
|
||||
/*
|
||||
* PL_strprbrk
|
||||
*
|
||||
* Returns a pointer to the last instance in the first string of any character
|
||||
* (not including the terminating null character) of the second string. It returns
|
||||
* null if either string is null.
|
||||
*/
|
||||
|
||||
PR_EXTERN(char *)
|
||||
PL_strprbrk(const char *s, const char *list);
|
||||
|
||||
/*
|
||||
* PL_strnpbrk
|
||||
*
|
||||
* Returns a pointer to the first instance (within the first n characters) of any
|
||||
* character (not including the terminating null character) of the second string.
|
||||
* It returns null if either string is null.
|
||||
*/
|
||||
|
||||
PR_EXTERN(char *)
|
||||
PL_strnpbrk(const char *s, const char *list, PRUint32 n);
|
||||
|
||||
/*
|
||||
* PL_strnprbrk
|
||||
*
|
||||
* Returns a pointer to the last instance (within the first n characters) of any
|
||||
* character (not including the terminating null character) of the second string.
|
||||
* It returns null if either string is null.
|
||||
*/
|
||||
|
||||
PR_EXTERN(char *)
|
||||
PL_strnprbrk(const char *s, const char *list, PRUint32 n);
|
||||
|
||||
/*
|
||||
* PL_strstr
|
||||
*
|
||||
* Returns a pointer to the first instance of the little string within the
|
||||
* big one. It returns null if either string is null.
|
||||
*/
|
||||
|
||||
PR_EXTERN(char *)
|
||||
PL_strstr(const char *big, const char *little);
|
||||
|
||||
/*
|
||||
* PL_strrstr
|
||||
*
|
||||
* Returns a pointer to the last instance of the little string within the big one.
|
||||
* It returns null if either string is null.
|
||||
*/
|
||||
|
||||
PR_EXTERN(char *)
|
||||
PL_strrstr(const char *big, const char *little);
|
||||
|
||||
/*
|
||||
* PL_strnstr
|
||||
*
|
||||
* Returns a pointer to the first instance of the little string within the first
|
||||
* n characters of the big one. It returns null if either string is null. It
|
||||
* returns null if the length of the little string is greater than n.
|
||||
*/
|
||||
|
||||
PR_EXTERN(char *)
|
||||
PL_strnstr(const char *big, const char *little, PRUint32 n);
|
||||
|
||||
/*
|
||||
* PL_strnrstr
|
||||
*
|
||||
* Returns a pointer to the last instance of the little string within the first
|
||||
* n characters of the big one. It returns null if either string is null. It
|
||||
* returns null if the length of the little string is greater than n.
|
||||
*/
|
||||
|
||||
PR_EXTERN(char *)
|
||||
PL_strnrstr(const char *big, const char *little, PRUint32 max);
|
||||
|
||||
/*
|
||||
* PL_strcasestr
|
||||
*
|
||||
* Returns a pointer to the first instance of the little string within the big one,
|
||||
* ignoring case. It returns null if either string is null.
|
||||
*/
|
||||
|
||||
PR_EXTERN(char *)
|
||||
PL_strcasestr(const char *big, const char *little);
|
||||
|
||||
/*
|
||||
* PL_strcaserstr
|
||||
*
|
||||
* Returns a pointer to the last instance of the little string within the big one,
|
||||
* ignoring case. It returns null if either string is null.
|
||||
*/
|
||||
|
||||
PR_EXTERN(char *)
|
||||
PL_strcaserstr(const char *big, const char *little);
|
||||
|
||||
/*
|
||||
* PL_strncasestr
|
||||
*
|
||||
* Returns a pointer to the first instance of the little string within the first
|
||||
* n characters of the big one, ignoring case. It returns null if either string is
|
||||
* null. It returns null if the length of the little string is greater than n.
|
||||
*/
|
||||
|
||||
PR_EXTERN(char *)
|
||||
PL_strncasestr(const char *big, const char *little, PRUint32 max);
|
||||
|
||||
/*
|
||||
* PL_strncaserstr
|
||||
*
|
||||
* Returns a pointer to the last instance of the little string within the first
|
||||
* n characters of the big one, ignoring case. It returns null if either string is
|
||||
* null. It returns null if the length of the little string is greater than n.
|
||||
*/
|
||||
|
||||
PR_EXTERN(char *)
|
||||
PL_strncaserstr(const char *big, const char *little, PRUint32 max);
|
||||
|
||||
/*
|
||||
* PL_strtok_r
|
||||
*
|
||||
* Splits the string s1 into tokens, separated by one or more characters
|
||||
* from the separator string s2. The argument lasts points to a
|
||||
* user-supplied char * pointer in which PL_strtok_r stores information
|
||||
* for it to continue scanning the same string.
|
||||
*
|
||||
* In the first call to PL_strtok_r, s1 points to a string and the value
|
||||
* of *lasts is ignored. PL_strtok_r returns a pointer to the first
|
||||
* token, writes '\0' into the character following the first token, and
|
||||
* updates *lasts.
|
||||
*
|
||||
* In subsequent calls, s1 is null and lasts must stay unchanged from the
|
||||
* previous call. The separator string s2 may be different from call to
|
||||
* call. PL_strtok_r returns a pointer to the next token in s1. When no
|
||||
* token remains in s1, PL_strtok_r returns null.
|
||||
*/
|
||||
|
||||
PR_EXTERN(char *)
|
||||
PL_strtok_r(char *s1, const char *s2, char **lasts);
|
||||
|
||||
/*
|
||||
* Things not (yet?) included: strspn/strcspn, strsep.
|
||||
* memchr, memcmp, memcpy, memccpy, index, rindex, bcmp, bcopy, bzero.
|
||||
* Any and all i18n/l10n stuff.
|
||||
*/
|
||||
|
||||
PR_END_EXTERN_C
|
||||
|
||||
#endif /* _plstr_h */
|
||||
@@ -1,197 +0,0 @@
|
||||
#
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla 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/MPL/
|
||||
#
|
||||
# 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 the Netscape Portable Runtime (NSPR).
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Netscape Communications Corporation.
|
||||
# Portions created by the Initial Developer are Copyright (C) 1998-2000
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
|
||||
#! gmake
|
||||
|
||||
MOD_DEPTH = ../../..
|
||||
topsrcdir = @top_srcdir@
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
include $(MOD_DEPTH)/config/autoconf.mk
|
||||
|
||||
include $(topsrcdir)/config/config.mk
|
||||
|
||||
INCLUDES = -I$(dist_includedir)
|
||||
|
||||
CSRCS =\
|
||||
plvrsion.c \
|
||||
strlen.c \
|
||||
strcpy.c \
|
||||
strdup.c \
|
||||
strcat.c \
|
||||
strcmp.c \
|
||||
strccmp.c \
|
||||
strchr.c \
|
||||
strpbrk.c \
|
||||
strstr.c \
|
||||
strcstr.c \
|
||||
strtok.c \
|
||||
base64.c \
|
||||
plerror.c \
|
||||
plgetopt.c \
|
||||
$(NULL)
|
||||
|
||||
LIBRARY_NAME = plc
|
||||
LIBRARY_VERSION = $(MOD_MAJOR_VERSION)
|
||||
|
||||
RELEASE_LIBS = $(TARGETS)
|
||||
|
||||
ifeq ($(OS_ARCH),WINNT)
|
||||
RES=$(OBJDIR)/plc.res
|
||||
RESNAME=plc.rc
|
||||
endif # WINNT
|
||||
|
||||
ifeq ($(OS_ARCH), AIX)
|
||||
ifeq ($(CLASSIC_NSPR),1)
|
||||
OS_LIBS = -lc
|
||||
else
|
||||
OS_LIBS = -lc_r
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(OS_ARCH),IRIX)
|
||||
OS_LIBS = -lc
|
||||
endif
|
||||
|
||||
ifeq ($(OS_ARCH),SunOS)
|
||||
OS_LIBS = -lc
|
||||
MAPFILE = $(OBJDIR)/plcmap.sun
|
||||
GARBAGE += $(MAPFILE)
|
||||
ifdef NS_USE_GCC
|
||||
ifdef GCC_USE_GNU_LD
|
||||
MKSHLIB += -Wl,--version-script,$(MAPFILE)
|
||||
else
|
||||
MKSHLIB += -Wl,-M,$(MAPFILE)
|
||||
endif
|
||||
else
|
||||
MKSHLIB += -M $(MAPFILE)
|
||||
endif
|
||||
# The -R '$ORIGIN' linker option instructs this library to search for its
|
||||
# dependencies in the same directory where it resides.
|
||||
MKSHLIB += -R '$$ORIGIN'
|
||||
endif
|
||||
|
||||
ifeq ($(OS_ARCH),OS2)
|
||||
MAPFILE = $(OBJDIR)/$(LIBRARY_NAME)$(LIBRARY_VERSION).def
|
||||
GARBAGE += $(MAPFILE)
|
||||
MKSHLIB += $(MAPFILE)
|
||||
endif
|
||||
|
||||
EXTRA_LIBS = $(LIBNSPR)
|
||||
|
||||
# On NCR and SCOOS, we can't link with extra libraries when
|
||||
# we build a shared library. If we do so, the linker doesn't
|
||||
# complain, but we would run into weird problems at run-time.
|
||||
# Therefore on these platforms, we link just the .o files.
|
||||
ifeq ($(OS_ARCH),NCR)
|
||||
EXTRA_LIBS =
|
||||
endif
|
||||
ifeq ($(OS_ARCH),SCOOS)
|
||||
EXTRA_LIBS =
|
||||
endif
|
||||
|
||||
ifdef RESOLVE_LINK_SYMBOLS
|
||||
EXTRA_LIBS += $(OS_LIBS)
|
||||
endif
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
#
|
||||
# Version information generation (begin)
|
||||
#
|
||||
ECHO = echo
|
||||
TINC = $(OBJDIR)/_pl_bld.h
|
||||
PROD = $(notdir $(SHARED_LIBRARY))
|
||||
NOW = $(MOD_DEPTH)/config/$(OBJDIR)/now
|
||||
SH_DATE = $(shell date "+%Y-%m-%d %T")
|
||||
SH_NOW = $(shell $(NOW))
|
||||
|
||||
ifeq ($(NS_USE_GCC)_$(OS_ARCH),_WINNT)
|
||||
SUF = i64
|
||||
else
|
||||
SUF = LL
|
||||
endif
|
||||
|
||||
GARBAGE += $(TINC)
|
||||
|
||||
$(TINC):
|
||||
@$(MAKE_OBJDIR)
|
||||
@$(ECHO) '#define _BUILD_STRING "$(SH_DATE)"' > $(TINC)
|
||||
@if test ! -z "$(SH_NOW)"; then \
|
||||
$(ECHO) '#define _BUILD_TIME $(SH_NOW)$(SUF)' >> $(TINC); \
|
||||
else \
|
||||
true; \
|
||||
fi
|
||||
@$(ECHO) '#define _PRODUCTION "$(PROD)"' >> $(TINC)
|
||||
|
||||
|
||||
$(OBJDIR)/plvrsion.$(OBJ_SUFFIX): plvrsion.c $(TINC)
|
||||
ifeq ($(NS_USE_GCC)_$(OS_ARCH),_WINNT)
|
||||
$(CC) -Fo$@ -c $(CFLAGS) -I$(OBJDIR) $<
|
||||
else
|
||||
ifeq ($(MOZ_OS2_TOOLS), VACPP)
|
||||
$(CC) -Fo$@ -c $(CFLAGS) -I$(OBJDIR) $<
|
||||
else
|
||||
$(CC) -o $@ -c $(CFLAGS) -I$(OBJDIR) $<
|
||||
endif
|
||||
endif
|
||||
#
|
||||
# Version information generation (end)
|
||||
#
|
||||
|
||||
#
|
||||
# The Client build wants the shared libraries in $(dist_bindir),
|
||||
# so we also install them there.
|
||||
#
|
||||
|
||||
export:: $(TARGETS)
|
||||
$(INSTALL) -m 444 $(TARGETS) $(dist_libdir)
|
||||
ifdef SHARED_LIBRARY
|
||||
ifeq ($(OS_ARCH),HP-UX)
|
||||
$(INSTALL) -m 755 $(SHARED_LIBRARY) $(dist_libdir)
|
||||
$(INSTALL) -m 755 $(SHARED_LIBRARY) $(dist_bindir)
|
||||
else
|
||||
$(INSTALL) -m 444 $(SHARED_LIBRARY) $(dist_bindir)
|
||||
endif
|
||||
endif
|
||||
ifeq ($(MOZ_BITS),16)
|
||||
$(INSTALL) -m 444 $(TARGETS) $(MOZ_DIST)/lib
|
||||
$(INSTALL) -m 444 $(TARGETS) $(MOZ_DIST)/bin
|
||||
endif
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
NSPR 2.0 libc functions
|
||||
-----------------------
|
||||
|
||||
Last edited: AOF 04 March 1997
|
||||
|
||||
This directory contains various libc-types of functions. All functions in
|
||||
this directory are platform independent, thread friendly (both safe and
|
||||
efficient). They are contributed from various sources, though the contri-
|
||||
butions are monitored by the NSPR group (mailto:freier).
|
||||
|
||||
All API items exported by these functions will contain the same three
|
||||
character prefix, "PL_" (Portable Library). Internal function names
|
||||
that are not exported (static) are of little concern, though some caution
|
||||
must be used on those elements that are 'extern' but not really intended
|
||||
to be part of the API. Those should all have a prefix of "_PL_" (is that
|
||||
legal?).
|
||||
|
||||
The responsibility for contributions in this area are distributed among
|
||||
all interested parties.
|
||||
|
||||
@@ -1,428 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla 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/MPL/
|
||||
*
|
||||
* 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 the Netscape Portable Runtime (NSPR).
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998-2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "plbase64.h"
|
||||
#include "prlog.h" /* For PR_NOT_REACHED */
|
||||
#include "prmem.h" /* for malloc / PR_MALLOC */
|
||||
#include "plstr.h" /* for PL_strlen */
|
||||
|
||||
static unsigned char *base = (unsigned char *)"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||
|
||||
static void
|
||||
encode3to4
|
||||
(
|
||||
const unsigned char *src,
|
||||
unsigned char *dest
|
||||
)
|
||||
{
|
||||
PRUint32 b32 = (PRUint32)0;
|
||||
PRIntn i, j = 18;
|
||||
|
||||
for( i = 0; i < 3; i++ )
|
||||
{
|
||||
b32 <<= 8;
|
||||
b32 |= (PRUint32)src[i];
|
||||
}
|
||||
|
||||
for( i = 0; i < 4; i++ )
|
||||
{
|
||||
dest[i] = base[ (PRUint32)((b32>>j) & 0x3F) ];
|
||||
j -= 6;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
encode2to4
|
||||
(
|
||||
const unsigned char *src,
|
||||
unsigned char *dest
|
||||
)
|
||||
{
|
||||
dest[0] = base[ (PRUint32)((src[0]>>2) & 0x3F) ];
|
||||
dest[1] = base[ (PRUint32)(((src[0] & 0x03) << 4) | ((src[1] >> 4) & 0x0F)) ];
|
||||
dest[2] = base[ (PRUint32)((src[1] & 0x0F) << 2) ];
|
||||
dest[3] = (unsigned char)'=';
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
encode1to4
|
||||
(
|
||||
const unsigned char *src,
|
||||
unsigned char *dest
|
||||
)
|
||||
{
|
||||
dest[0] = base[ (PRUint32)((src[0]>>2) & 0x3F) ];
|
||||
dest[1] = base[ (PRUint32)((src[0] & 0x03) << 4) ];
|
||||
dest[2] = (unsigned char)'=';
|
||||
dest[3] = (unsigned char)'=';
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
encode
|
||||
(
|
||||
const unsigned char *src,
|
||||
PRUint32 srclen,
|
||||
unsigned char *dest
|
||||
)
|
||||
{
|
||||
while( srclen >= 3 )
|
||||
{
|
||||
encode3to4(src, dest);
|
||||
src += 3;
|
||||
dest += 4;
|
||||
srclen -= 3;
|
||||
}
|
||||
|
||||
switch( srclen )
|
||||
{
|
||||
case 2:
|
||||
encode2to4(src, dest);
|
||||
break;
|
||||
case 1:
|
||||
encode1to4(src, dest);
|
||||
break;
|
||||
case 0:
|
||||
break;
|
||||
default:
|
||||
PR_NOT_REACHED("coding error");
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* PL_Base64Encode
|
||||
*
|
||||
* If the destination argument is NULL, a return buffer is
|
||||
* allocated, and the data therein will be null-terminated.
|
||||
* If the destination argument is not NULL, it is assumed to
|
||||
* be of sufficient size, and the contents will not be null-
|
||||
* terminated by this routine.
|
||||
*
|
||||
* Returns null if the allocation fails.
|
||||
*/
|
||||
|
||||
PR_IMPLEMENT(char *)
|
||||
PL_Base64Encode
|
||||
(
|
||||
const char *src,
|
||||
PRUint32 srclen,
|
||||
char *dest
|
||||
)
|
||||
{
|
||||
if( 0 == srclen )
|
||||
{
|
||||
srclen = PL_strlen(src);
|
||||
}
|
||||
|
||||
if( (char *)0 == dest )
|
||||
{
|
||||
PRUint32 destlen = ((srclen + 2)/3) * 4;
|
||||
dest = (char *)PR_MALLOC(destlen + 1);
|
||||
if( (char *)0 == dest )
|
||||
{
|
||||
return (char *)0;
|
||||
}
|
||||
dest[ destlen ] = (char)0; /* null terminate */
|
||||
}
|
||||
|
||||
encode((const unsigned char *)src, srclen, (unsigned char *)dest);
|
||||
return dest;
|
||||
}
|
||||
|
||||
static PRInt32
|
||||
codetovalue
|
||||
(
|
||||
unsigned char c
|
||||
)
|
||||
{
|
||||
if( (c >= (unsigned char)'A') && (c <= (unsigned char)'Z') )
|
||||
{
|
||||
return (PRInt32)(c - (unsigned char)'A');
|
||||
}
|
||||
else if( (c >= (unsigned char)'a') && (c <= (unsigned char)'z') )
|
||||
{
|
||||
return ((PRInt32)(c - (unsigned char)'a') +26);
|
||||
}
|
||||
else if( (c >= (unsigned char)'0') && (c <= (unsigned char)'9') )
|
||||
{
|
||||
return ((PRInt32)(c - (unsigned char)'0') +52);
|
||||
}
|
||||
else if( (unsigned char)'+' == c )
|
||||
{
|
||||
return (PRInt32)62;
|
||||
}
|
||||
else if( (unsigned char)'/' == c )
|
||||
{
|
||||
return (PRInt32)63;
|
||||
}
|
||||
else
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
static PRStatus
|
||||
decode4to3
|
||||
(
|
||||
const unsigned char *src,
|
||||
unsigned char *dest
|
||||
)
|
||||
{
|
||||
PRUint32 b32 = (PRUint32)0;
|
||||
PRInt32 bits;
|
||||
PRIntn i;
|
||||
|
||||
for( i = 0; i < 4; i++ )
|
||||
{
|
||||
bits = codetovalue(src[i]);
|
||||
if( bits < 0 )
|
||||
{
|
||||
return PR_FAILURE;
|
||||
}
|
||||
|
||||
b32 <<= 6;
|
||||
b32 |= bits;
|
||||
}
|
||||
|
||||
dest[0] = (unsigned char)((b32 >> 16) & 0xFF);
|
||||
dest[1] = (unsigned char)((b32 >> 8) & 0xFF);
|
||||
dest[2] = (unsigned char)((b32 ) & 0xFF);
|
||||
|
||||
return PR_SUCCESS;
|
||||
}
|
||||
|
||||
static PRStatus
|
||||
decode3to2
|
||||
(
|
||||
const unsigned char *src,
|
||||
unsigned char *dest
|
||||
)
|
||||
{
|
||||
PRUint32 b32 = (PRUint32)0;
|
||||
PRInt32 bits;
|
||||
PRUint32 ubits;
|
||||
|
||||
bits = codetovalue(src[0]);
|
||||
if( bits < 0 )
|
||||
{
|
||||
return PR_FAILURE;
|
||||
}
|
||||
|
||||
b32 = (PRUint32)bits;
|
||||
b32 <<= 6;
|
||||
|
||||
bits = codetovalue(src[1]);
|
||||
if( bits < 0 )
|
||||
{
|
||||
return PR_FAILURE;
|
||||
}
|
||||
|
||||
b32 |= (PRUint32)bits;
|
||||
b32 <<= 4;
|
||||
|
||||
bits = codetovalue(src[2]);
|
||||
if( bits < 0 )
|
||||
{
|
||||
return PR_FAILURE;
|
||||
}
|
||||
|
||||
ubits = (PRUint32)bits;
|
||||
b32 |= (ubits >> 2);
|
||||
|
||||
dest[0] = (unsigned char)((b32 >> 8) & 0xFF);
|
||||
dest[1] = (unsigned char)((b32 ) & 0xFF);
|
||||
|
||||
return PR_SUCCESS;
|
||||
}
|
||||
|
||||
static PRStatus
|
||||
decode2to1
|
||||
(
|
||||
const unsigned char *src,
|
||||
unsigned char *dest
|
||||
)
|
||||
{
|
||||
PRUint32 b32;
|
||||
PRUint32 ubits;
|
||||
PRInt32 bits;
|
||||
|
||||
bits = codetovalue(src[0]);
|
||||
if( bits < 0 )
|
||||
{
|
||||
return PR_FAILURE;
|
||||
}
|
||||
|
||||
ubits = (PRUint32)bits;
|
||||
b32 = (ubits << 2);
|
||||
|
||||
bits = codetovalue(src[1]);
|
||||
if( bits < 0 )
|
||||
{
|
||||
return PR_FAILURE;
|
||||
}
|
||||
|
||||
ubits = (PRUint32)bits;
|
||||
b32 |= (ubits >> 4);
|
||||
|
||||
dest[0] = (unsigned char)b32;
|
||||
|
||||
return PR_SUCCESS;
|
||||
}
|
||||
|
||||
static PRStatus
|
||||
decode
|
||||
(
|
||||
const unsigned char *src,
|
||||
PRUint32 srclen,
|
||||
unsigned char *dest
|
||||
)
|
||||
{
|
||||
PRStatus rv;
|
||||
|
||||
while( srclen >= 4 )
|
||||
{
|
||||
rv = decode4to3(src, dest);
|
||||
if( PR_SUCCESS != rv )
|
||||
{
|
||||
return PR_FAILURE;
|
||||
}
|
||||
|
||||
src += 4;
|
||||
dest += 3;
|
||||
srclen -= 4;
|
||||
}
|
||||
|
||||
switch( srclen )
|
||||
{
|
||||
case 3:
|
||||
rv = decode3to2(src, dest);
|
||||
break;
|
||||
case 2:
|
||||
rv = decode2to1(src, dest);
|
||||
break;
|
||||
case 1:
|
||||
rv = PR_FAILURE;
|
||||
break;
|
||||
case 0:
|
||||
rv = PR_SUCCESS;
|
||||
break;
|
||||
default:
|
||||
PR_NOT_REACHED("coding error");
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
/*
|
||||
* PL_Base64Decode
|
||||
*
|
||||
* If the destination argument is NULL, a return buffer is
|
||||
* allocated and the data therein will be null-terminated.
|
||||
* If the destination argument is not null, it is assumed
|
||||
* to be of sufficient size, and the data will not be null-
|
||||
* terminated by this routine.
|
||||
*
|
||||
* Returns null if the allocation fails, or if the source string is
|
||||
* not well-formed.
|
||||
*/
|
||||
|
||||
PR_IMPLEMENT(char *)
|
||||
PL_Base64Decode
|
||||
(
|
||||
const char *src,
|
||||
PRUint32 srclen,
|
||||
char *dest
|
||||
)
|
||||
{
|
||||
PRStatus status;
|
||||
PRBool allocated = PR_FALSE;
|
||||
|
||||
if( (char *)0 == src )
|
||||
{
|
||||
return (char *)0;
|
||||
}
|
||||
|
||||
if( 0 == srclen )
|
||||
{
|
||||
srclen = PL_strlen(src);
|
||||
}
|
||||
|
||||
if( srclen && (0 == (srclen & 3)) )
|
||||
{
|
||||
if( (char)'=' == src[ srclen-1 ] )
|
||||
{
|
||||
if( (char)'=' == src[ srclen-2 ] )
|
||||
{
|
||||
srclen -= 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
srclen -= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( (char *)0 == dest )
|
||||
{
|
||||
PRUint32 destlen = ((srclen * 3) / 4);
|
||||
dest = (char *)PR_MALLOC(destlen + 1);
|
||||
if( (char *)0 == dest )
|
||||
{
|
||||
return (char *)0;
|
||||
}
|
||||
dest[ destlen ] = (char)0; /* null terminate */
|
||||
allocated = PR_TRUE;
|
||||
}
|
||||
|
||||
status = decode((const unsigned char *)src, srclen, (unsigned char *)dest);
|
||||
if( PR_SUCCESS != status )
|
||||
{
|
||||
if( PR_TRUE == allocated )
|
||||
{
|
||||
PR_DELETE(dest);
|
||||
}
|
||||
|
||||
return (char *)0;
|
||||
}
|
||||
|
||||
return dest;
|
||||
}
|
||||
@@ -1,99 +0,0 @@
|
||||
;+#
|
||||
;+# ***** BEGIN LICENSE BLOCK *****
|
||||
;+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
;+#
|
||||
;+# The contents of this file are subject to the Mozilla 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/MPL/
|
||||
;+#
|
||||
;+# 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 the Netscape Portable Runtime (NSPR).
|
||||
;+#
|
||||
;+# The Initial Developer of the Original Code is
|
||||
;+# Netscape Communications Corporation.
|
||||
;+# Portions created by the Initial Developer are Copyright (C) 2002-2003
|
||||
;+# the Initial Developer. All Rights Reserved.
|
||||
;+#
|
||||
;+# Contributor(s):
|
||||
;+#
|
||||
;+# Alternatively, the contents of this file may be used under the terms of
|
||||
;+# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
;+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
;+# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
;+# of those above. If you wish to allow use of your version of this file only
|
||||
;+# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
;+# use your version of this file under the terms of the MPL, indicate your
|
||||
;+# decision by deleting the provisions above and replace them with the notice
|
||||
;+# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
;+# the provisions above, a recipient may use your version of this file under
|
||||
;+# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
;+#
|
||||
;+# ***** END LICENSE BLOCK *****
|
||||
;+#
|
||||
;+# OK, this file is meant to support SUN, LINUX, AIX, OS/2 and WINDOWS
|
||||
;+# 1. For all unix platforms, the string ";-" means "remove this line"
|
||||
;+# 2. For all unix platforms, the string " DATA " will be removed from any
|
||||
;+# line on which it occurs.
|
||||
;+# 3. Lines containing ";+" will have ";+" removed on SUN and LINUX.
|
||||
;+# On AIX, lines containing ";+" will be removed.
|
||||
;+# 4. For all unix platforms, the string ";;" will thave the ";;" removed.
|
||||
;+# 5. For all unix platforms, after the above processing has taken place,
|
||||
;+# all characters after the first ";" on the line will be removed.
|
||||
;+# And for AIX, the first ";" will also be removed.
|
||||
;+# This file is passed directly to windows. Since ';' is a comment, all UNIX
|
||||
;+# directives are hidden behind ";", ";+", and ";-"
|
||||
;+NSPR_4.0 {
|
||||
;+ global:
|
||||
LIBRARY plc4 ;-
|
||||
EXPORTS ;-
|
||||
PL_Base64Decode;
|
||||
PL_Base64Encode;
|
||||
PL_CreateOptState;
|
||||
PL_DestroyOptState;
|
||||
PL_FPrintError;
|
||||
PL_GetNextOpt;
|
||||
PL_PrintError;
|
||||
PL_strcasecmp;
|
||||
PL_strcaserstr;
|
||||
PL_strcasestr;
|
||||
PL_strcat;
|
||||
PL_strcatn;
|
||||
PL_strchr;
|
||||
PL_strcmp;
|
||||
PL_strcpy;
|
||||
PL_strdup;
|
||||
PL_strfree;
|
||||
PL_strlen;
|
||||
PL_strncasecmp;
|
||||
PL_strncaserstr;
|
||||
PL_strncasestr;
|
||||
PL_strncat;
|
||||
PL_strnchr;
|
||||
PL_strncmp;
|
||||
PL_strncpy;
|
||||
PL_strncpyz;
|
||||
PL_strndup;
|
||||
PL_strnlen;
|
||||
PL_strnpbrk;
|
||||
PL_strnprbrk;
|
||||
PL_strnrchr;
|
||||
PL_strnrstr;
|
||||
PL_strnstr;
|
||||
PL_strpbrk;
|
||||
PL_strprbrk;
|
||||
PL_strrchr;
|
||||
PL_strrstr;
|
||||
PL_strstr;
|
||||
libVersionPoint;
|
||||
;+ local: *;
|
||||
;+};
|
||||
;+
|
||||
;+NSPR_4.2 {
|
||||
;+ global:
|
||||
PL_strtok_r;
|
||||
;+} NSPR_4.0;
|
||||
@@ -1,103 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla 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/MPL/
|
||||
*
|
||||
* 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 the Netscape Portable Runtime (NSPR).
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1999-2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
|
||||
#include "prinit.h"
|
||||
#include <winver.h>
|
||||
|
||||
#define MY_LIBNAME "plc"
|
||||
#define MY_FILEDESCRIPTION "PLC Library"
|
||||
|
||||
#define STRINGIZE(x) #x
|
||||
#define STRINGIZE2(x) STRINGIZE(x)
|
||||
#define PR_VMAJOR_STR STRINGIZE2(PR_VMAJOR)
|
||||
|
||||
#ifdef _DEBUG
|
||||
#define MY_DEBUG_STR " (debug)"
|
||||
#define MY_FILEFLAGS_1 VS_FF_DEBUG
|
||||
#else
|
||||
#define MY_DEBUG_STR ""
|
||||
#define MY_FILEFLAGS_1 0x0L
|
||||
#endif
|
||||
#if PR_BETA
|
||||
#define MY_FILEFLAGS_2 MY_FILEFLAGS_1|VS_FF_PRERELEASE
|
||||
#else
|
||||
#define MY_FILEFLAGS_2 MY_FILEFLAGS_1
|
||||
#endif
|
||||
|
||||
#ifdef WINNT
|
||||
#define MY_FILEOS VOS_NT_WINDOWS32
|
||||
#define MY_INTERNAL_NAME "lib" MY_LIBNAME PR_VMAJOR_STR
|
||||
#else
|
||||
#define MY_FILEOS VOS__WINDOWS32
|
||||
#define MY_INTERNAL_NAME MY_LIBNAME PR_VMAJOR_STR
|
||||
#endif
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Version-information resource
|
||||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION PR_VMAJOR,PR_VMINOR,PR_VPATCH,0
|
||||
PRODUCTVERSION PR_VMAJOR,PR_VMINOR,PR_VPATCH,0
|
||||
FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
|
||||
FILEFLAGS MY_FILEFLAGS_2
|
||||
FILEOS MY_FILEOS
|
||||
FILETYPE VFT_DLL
|
||||
FILESUBTYPE 0x0L // not used
|
||||
|
||||
BEGIN
|
||||
BLOCK "StringFileInfo"
|
||||
BEGIN
|
||||
BLOCK "040904B0" // Lang=US English, CharSet=Unicode
|
||||
BEGIN
|
||||
VALUE "CompanyName", "Netscape Communications Corporation\0"
|
||||
VALUE "FileDescription", MY_FILEDESCRIPTION MY_DEBUG_STR "\0"
|
||||
VALUE "FileVersion", PR_VERSION "\0"
|
||||
VALUE "InternalName", MY_INTERNAL_NAME "\0"
|
||||
VALUE "LegalCopyright", "Copyright \251 1996-2000 Netscape Communications Corporation\0"
|
||||
VALUE "OriginalFilename", MY_INTERNAL_NAME ".dll\0"
|
||||
VALUE "ProductName", "Netscape Portable Runtime\0"
|
||||
VALUE "ProductVersion", PR_VERSION "\0"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
BEGIN
|
||||
VALUE "Translation", 0x409, 1200
|
||||
END
|
||||
END
|
||||
@@ -1,53 +0,0 @@
|
||||
! Fixed section of symbol vector for LIBPLC4
|
||||
!
|
||||
GSMATCH=LEQUAL,2,2
|
||||
case_sensitive=YES
|
||||
!
|
||||
! --------------------------------------------------------------------------
|
||||
! Ident 2,2 introduced for Mozilla 1.3
|
||||
! Previously this was empty. Now we include everything that's specified in
|
||||
! plc.def.
|
||||
! --------------------------------------------------------------------------
|
||||
!
|
||||
! NSPR 4.0
|
||||
SYMBOL_VECTOR=(PL_Base64Decode=PROCEDURE)
|
||||
SYMBOL_VECTOR=(PL_Base64Encode=PROCEDURE)
|
||||
SYMBOL_VECTOR=(PL_CreateOptState=PROCEDURE)
|
||||
SYMBOL_VECTOR=(PL_DestroyOptState=PROCEDURE)
|
||||
SYMBOL_VECTOR=(PL_FPrintError=PROCEDURE)
|
||||
SYMBOL_VECTOR=(PL_GetNextOpt=PROCEDURE)
|
||||
SYMBOL_VECTOR=(PL_PrintError=PROCEDURE)
|
||||
SYMBOL_VECTOR=(PL_strcasecmp=PROCEDURE)
|
||||
SYMBOL_VECTOR=(PL_strcaserstr=PROCEDURE)
|
||||
SYMBOL_VECTOR=(PL_strcasestr=PROCEDURE)
|
||||
SYMBOL_VECTOR=(PL_strcat=PROCEDURE)
|
||||
SYMBOL_VECTOR=(PL_strcatn=PROCEDURE)
|
||||
SYMBOL_VECTOR=(PL_strchr=PROCEDURE)
|
||||
SYMBOL_VECTOR=(PL_strcmp=PROCEDURE)
|
||||
SYMBOL_VECTOR=(PL_strcpy=PROCEDURE)
|
||||
SYMBOL_VECTOR=(PL_strdup=PROCEDURE)
|
||||
SYMBOL_VECTOR=(PL_strfree=PROCEDURE)
|
||||
SYMBOL_VECTOR=(PL_strlen=PROCEDURE)
|
||||
SYMBOL_VECTOR=(PL_strncasecmp=PROCEDURE)
|
||||
SYMBOL_VECTOR=(PL_strncaserstr=PROCEDURE)
|
||||
SYMBOL_VECTOR=(PL_strncasestr=PROCEDURE)
|
||||
SYMBOL_VECTOR=(PL_strncat=PROCEDURE)
|
||||
SYMBOL_VECTOR=(PL_strnchr=PROCEDURE)
|
||||
SYMBOL_VECTOR=(PL_strncmp=PROCEDURE)
|
||||
SYMBOL_VECTOR=(PL_strncpy=PROCEDURE)
|
||||
SYMBOL_VECTOR=(PL_strncpyz=PROCEDURE)
|
||||
SYMBOL_VECTOR=(PL_strndup=PROCEDURE)
|
||||
SYMBOL_VECTOR=(PL_strnlen=PROCEDURE)
|
||||
SYMBOL_VECTOR=(PL_strnpbrk=PROCEDURE)
|
||||
SYMBOL_VECTOR=(PL_strnprbrk=PROCEDURE)
|
||||
SYMBOL_VECTOR=(PL_strnrchr=PROCEDURE)
|
||||
SYMBOL_VECTOR=(PL_strnrstr=PROCEDURE)
|
||||
SYMBOL_VECTOR=(PL_strnstr=PROCEDURE)
|
||||
SYMBOL_VECTOR=(PL_strpbrk=PROCEDURE)
|
||||
SYMBOL_VECTOR=(PL_strprbrk=PROCEDURE)
|
||||
SYMBOL_VECTOR=(PL_strrchr=PROCEDURE)
|
||||
SYMBOL_VECTOR=(PL_strrstr=PROCEDURE)
|
||||
SYMBOL_VECTOR=(PL_strstr=PROCEDURE)
|
||||
SYMBOL_VECTOR=(libVersionPoint=PROCEDURE)
|
||||
! NSPR 4.2
|
||||
SYMBOL_VECTOR=(PL_strtok_r=PROCEDURE)
|
||||
@@ -1,168 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla 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/MPL/
|
||||
*
|
||||
* 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 the Netscape Portable Runtime (NSPR).
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998-2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/*
|
||||
** File:plerror.c
|
||||
** Description: Simple routine to print translate the calling thread's
|
||||
** error numbers and print them to "syserr".
|
||||
*/
|
||||
|
||||
#include "plerror.h"
|
||||
|
||||
#include "prprf.h"
|
||||
#include "prerror.h"
|
||||
|
||||
PR_IMPLEMENT(void) PL_FPrintError(PRFileDesc *fd, const char *msg)
|
||||
{
|
||||
static const char *tags[] =
|
||||
{
|
||||
"PR_OUT_OF_MEMORY_ERROR",
|
||||
"PR_BAD_DESCRIPTOR_ERROR",
|
||||
"PR_WOULD_BLOCK_ERROR",
|
||||
"PR_ACCESS_FAULT_ERROR",
|
||||
"PR_INVALID_METHOD_ERROR",
|
||||
"PR_ILLEGAL_ACCESS_ERROR",
|
||||
"PR_UNKNOWN_ERROR",
|
||||
"PR_PENDING_INTERRUPT_ERROR",
|
||||
"PR_NOT_IMPLEMENTED_ERROR",
|
||||
"PR_IO_ERROR",
|
||||
"PR_IO_TIMEOUT_ERROR",
|
||||
"PR_IO_PENDING_ERROR",
|
||||
"PR_DIRECTORY_OPEN_ERROR",
|
||||
"PR_INVALID_ARGUMENT_ERROR",
|
||||
"PR_ADDRESS_NOT_AVAILABLE_ERROR",
|
||||
"PR_ADDRESS_NOT_SUPPORTED_ERROR",
|
||||
"PR_IS_CONNECTED_ERROR",
|
||||
"PR_BAD_ADDRESS_ERROR",
|
||||
"PR_ADDRESS_IN_USE_ERROR",
|
||||
"PR_CONNECT_REFUSED_ERROR",
|
||||
"PR_NETWORK_UNREACHABLE_ERROR",
|
||||
"PR_CONNECT_TIMEOUT_ERROR",
|
||||
"PR_NOT_CONNECTED_ERROR",
|
||||
"PR_LOAD_LIBRARY_ERROR",
|
||||
"PR_UNLOAD_LIBRARY_ERROR",
|
||||
"PR_FIND_SYMBOL_ERROR",
|
||||
"PR_INSUFFICIENT_RESOURCES_ERROR",
|
||||
"PR_DIRECTORY_LOOKUP_ERROR",
|
||||
"PR_TPD_RANGE_ERROR",
|
||||
"PR_PROC_DESC_TABLE_FULL_ERROR",
|
||||
"PR_SYS_DESC_TABLE_FULL_ERROR",
|
||||
"PR_NOT_SOCKET_ERROR",
|
||||
"PR_NOT_TCP_SOCKET_ERROR",
|
||||
"PR_SOCKET_ADDRESS_IS_BOUND_ERROR",
|
||||
"PR_NO_ACCESS_RIGHTS_ERROR",
|
||||
"PR_OPERATION_NOT_SUPPORTED_ERROR",
|
||||
"PR_PROTOCOL_NOT_SUPPORTED_ERROR",
|
||||
"PR_REMOTE_FILE_ERROR",
|
||||
"PR_BUFFER_OVERFLOW_ERROR",
|
||||
"PR_CONNECT_RESET_ERROR",
|
||||
"PR_RANGE_ERROR",
|
||||
"PR_DEADLOCK_ERROR",
|
||||
"PR_FILE_IS_LOCKED_ERROR",
|
||||
"PR_FILE_TOO_BIG_ERROR",
|
||||
"PR_NO_DEVICE_SPACE_ERROR",
|
||||
"PR_PIPE_ERROR",
|
||||
"PR_NO_SEEK_DEVICE_ERROR",
|
||||
"PR_IS_DIRECTORY_ERROR",
|
||||
"PR_LOOP_ERROR",
|
||||
"PR_NAME_TOO_LONG_ERROR",
|
||||
"PR_FILE_NOT_FOUND_ERROR",
|
||||
"PR_NOT_DIRECTORY_ERROR",
|
||||
"PR_READ_ONLY_FILESYSTEM_ERROR",
|
||||
"PR_DIRECTORY_NOT_EMPTY_ERROR",
|
||||
"PR_FILESYSTEM_MOUNTED_ERROR",
|
||||
"PR_NOT_SAME_DEVICE_ERROR",
|
||||
"PR_DIRECTORY_CORRUPTED_ERROR",
|
||||
"PR_FILE_EXISTS_ERROR",
|
||||
"PR_MAX_DIRECTORY_ENTRIES_ERROR",
|
||||
"PR_INVALID_DEVICE_STATE_ERROR",
|
||||
"PR_DEVICE_IS_LOCKED_ERROR",
|
||||
"PR_NO_MORE_FILES_ERROR",
|
||||
"PR_END_OF_FILE_ERROR",
|
||||
"PR_FILE_SEEK_ERROR",
|
||||
"PR_FILE_IS_BUSY_ERROR",
|
||||
"<unused error code>",
|
||||
"PR_IN_PROGRESS_ERROR",
|
||||
"PR_ALREADY_INITIATED_ERROR",
|
||||
"PR_GROUP_EMPTY_ERROR",
|
||||
"PR_INVALID_STATE_ERROR",
|
||||
"PR_NETWORK_DOWN_ERROR",
|
||||
"PR_SOCKET_SHUTDOWN_ERROR",
|
||||
"PR_CONNECT_ABORTED_ERROR",
|
||||
"PR_HOST_UNREACHABLE_ERROR",
|
||||
"PR_MAX_ERROR"
|
||||
};
|
||||
|
||||
PRErrorCode error = PR_GetError();
|
||||
PRInt32 oserror = PR_GetOSError();
|
||||
PRIntn thoseIKnowAbout = sizeof(tags) / sizeof(char*);
|
||||
PRIntn lastError = PR_NSPR_ERROR_BASE + thoseIKnowAbout;
|
||||
|
||||
if (NULL != msg) PR_fprintf(fd, "%s: ", msg);
|
||||
if ((error < PR_NSPR_ERROR_BASE) || (error > lastError))
|
||||
PR_fprintf(
|
||||
fd, " (%d)OUT OF RANGE, oserror = %d\n", error, oserror);
|
||||
else
|
||||
PR_fprintf(
|
||||
fd, "%s(%d), oserror = %d\n",
|
||||
tags[error - PR_NSPR_ERROR_BASE], error, oserror);
|
||||
} /* PL_FPrintError */
|
||||
|
||||
PR_IMPLEMENT(void) PL_PrintError(const char *msg)
|
||||
{
|
||||
static PRFileDesc *fd = NULL;
|
||||
if (NULL == fd) fd = PR_GetSpecialFD(PR_StandardError);
|
||||
PL_FPrintError(fd, msg);
|
||||
} /* PL_PrintError */
|
||||
|
||||
#if defined(WIN16)
|
||||
/*
|
||||
** libmain() is a required function for win16
|
||||
**
|
||||
*/
|
||||
int CALLBACK LibMain( HINSTANCE hInst, WORD wDataSeg,
|
||||
WORD cbHeapSize, LPSTR lpszCmdLine )
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
#endif /* WIN16 */
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* plerror.c */
|
||||
@@ -1,184 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla 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/MPL/
|
||||
*
|
||||
* 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 the Netscape Portable Runtime (NSPR).
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998-2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/*
|
||||
** File: plgetopt.c
|
||||
** Description: utilities to parse argc/argv
|
||||
*/
|
||||
|
||||
#include "prmem.h"
|
||||
#include "prlog.h"
|
||||
#include "prerror.h"
|
||||
#include "plstr.h"
|
||||
#include "plgetopt.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
static char static_Nul = 0;
|
||||
|
||||
struct PLOptionInternal
|
||||
{
|
||||
const char *options; /* client options list specification */
|
||||
PRIntn argc; /* original number of arguments */
|
||||
char **argv; /* vector of pointers to arguments */
|
||||
PRIntn xargc; /* which one we're processing now */
|
||||
const char *xargv; /* where within *argv[xargc] */
|
||||
PRBool minus; /* do we already have the '-'? */
|
||||
};
|
||||
|
||||
/*
|
||||
** Create the state in which to parse the tokens.
|
||||
**
|
||||
** argc the sum of the number of options and their values
|
||||
** argv the options and their values
|
||||
** options vector of single character options w/ | w/o ':
|
||||
*/
|
||||
PR_IMPLEMENT(PLOptState*) PL_CreateOptState(
|
||||
PRIntn argc, char **argv, const char *options)
|
||||
{
|
||||
PLOptState *opt = NULL;
|
||||
if (NULL == options)
|
||||
PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
|
||||
else
|
||||
{
|
||||
opt = PR_NEWZAP(PLOptState);
|
||||
if (NULL == opt)
|
||||
PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
|
||||
else
|
||||
{
|
||||
PLOptionInternal *internal = PR_NEW(PLOptionInternal);
|
||||
if (NULL == internal)
|
||||
{
|
||||
PR_DELETE(opt);
|
||||
PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
opt->option = 0;
|
||||
opt->value = NULL;
|
||||
opt->internal = internal;
|
||||
|
||||
internal->argc = argc;
|
||||
internal->argv = argv;
|
||||
internal->xargc = 0;
|
||||
internal->xargv = &static_Nul;
|
||||
internal->minus = PR_FALSE;
|
||||
internal->options = options;
|
||||
}
|
||||
}
|
||||
}
|
||||
return opt;
|
||||
} /* PL_CreateOptState */
|
||||
|
||||
/*
|
||||
** Destroy object created by CreateOptState()
|
||||
*/
|
||||
PR_IMPLEMENT(void) PL_DestroyOptState(PLOptState *opt)
|
||||
{
|
||||
PR_DELETE(opt->internal);
|
||||
PR_DELETE(opt);
|
||||
} /* PL_DestroyOptState */
|
||||
|
||||
PR_IMPLEMENT(PLOptStatus) PL_GetNextOpt(PLOptState *opt)
|
||||
{
|
||||
PLOptionInternal *internal = opt->internal;
|
||||
PRIntn cop, eoo = PL_strlen(internal->options);
|
||||
|
||||
/*
|
||||
** If the current xarg points to nul, advance to the next
|
||||
** element of the argv vector. If the vector index is equal
|
||||
** to argc, we're out of arguments, so return an EOL.
|
||||
** Note whether the first character of the new argument is
|
||||
** a '-' and skip by it if it is.
|
||||
*/
|
||||
while (0 == *internal->xargv)
|
||||
{
|
||||
internal->xargc += 1;
|
||||
if (internal->xargc >= internal->argc)
|
||||
{
|
||||
opt->option = 0;
|
||||
opt->value = NULL;
|
||||
return PL_OPT_EOL;
|
||||
}
|
||||
internal->xargv = internal->argv[internal->xargc];
|
||||
internal->minus = ('-' == *internal->xargv ? PR_TRUE : PR_FALSE); /* not it */
|
||||
if (internal->minus) internal->xargv += 1; /* and consume */
|
||||
}
|
||||
|
||||
/*
|
||||
** If we already have a '-' in hand, xargv points to the next
|
||||
** option. See if we can find a match in the list of possible
|
||||
** options supplied.
|
||||
*/
|
||||
|
||||
if (internal->minus)
|
||||
{
|
||||
for (cop = 0; cop < eoo; ++cop)
|
||||
{
|
||||
if (internal->options[cop] == *internal->xargv)
|
||||
{
|
||||
opt->option = *internal->xargv;
|
||||
internal->xargv += 1;
|
||||
/*
|
||||
** if options indicates that there's an associated
|
||||
** value, this argv is finished and the next is the
|
||||
** option's value.
|
||||
*/
|
||||
if (':' == internal->options[cop + 1])
|
||||
{
|
||||
if (0 != *internal->xargv) return PL_OPT_BAD;
|
||||
opt->value = internal->argv[++(internal->xargc)];
|
||||
internal->xargv = &static_Nul;
|
||||
internal->minus = PR_FALSE;
|
||||
}
|
||||
else opt->value = NULL;
|
||||
return PL_OPT_OK;
|
||||
}
|
||||
}
|
||||
internal->xargv += 1; /* consume that option */
|
||||
return PL_OPT_BAD;
|
||||
}
|
||||
/*
|
||||
** No '-', so it must be a standalone value. The option is nul.
|
||||
*/
|
||||
opt->value = internal->argv[internal->xargc];
|
||||
internal->xargv = &static_Nul;
|
||||
opt->option = 0;
|
||||
return PL_OPT_OK;
|
||||
} /* PL_GetNextOpt */
|
||||
|
||||
/* plgetopt.c */
|
||||
@@ -1,125 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla 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/MPL/
|
||||
*
|
||||
* 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 the Netscape Portable Runtime (NSPR).
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998-2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "prinit.h"
|
||||
#include "prvrsion.h"
|
||||
|
||||
/************************************************************************/
|
||||
/**************************IDENTITY AND VERSIONING***********************/
|
||||
/************************************************************************/
|
||||
#include "_pl_bld.h"
|
||||
#if !defined(_BUILD_TIME)
|
||||
#ifdef HAVE_LONG_LONG
|
||||
#define _BUILD_TIME 0
|
||||
#else
|
||||
#define _BUILD_TIME {0, 0}
|
||||
#endif
|
||||
#endif
|
||||
#if !defined(_BUILD_STRING)
|
||||
#define _BUILD_STRING ""
|
||||
#endif
|
||||
#if !defined(_PRODUCTION)
|
||||
#define _PRODUCTION ""
|
||||
#endif
|
||||
#if defined(DEBUG)
|
||||
#define _DEBUG_STRING " (debug)"
|
||||
#else
|
||||
#define _DEBUG_STRING ""
|
||||
#endif
|
||||
|
||||
/*
|
||||
* A trick to expand the PR_VMAJOR macro before concatenation.
|
||||
*/
|
||||
#define CONCAT(x, y) x ## y
|
||||
#define CONCAT2(x, y) CONCAT(x, y)
|
||||
#define VERSION_DESC_NAME CONCAT2(prVersionDescription_libplc, PR_VMAJOR)
|
||||
|
||||
PRVersionDescription VERSION_DESC_NAME =
|
||||
{
|
||||
/* version */ 2, /* this is the only one supported */
|
||||
/* buildTime */ _BUILD_TIME, /* usecs since midnight 1/1/1970 GMT */
|
||||
/* buildTimeString */ _BUILD_STRING, /* ditto, but human readable */
|
||||
/* vMajor */ PR_VMAJOR, /* NSPR's version number */
|
||||
/* vMinor */ PR_VMINOR, /* and minor version */
|
||||
/* vPatch */ PR_VPATCH, /* and patch */
|
||||
/* beta */ PR_BETA, /* beta build boolean */
|
||||
#if defined(DEBUG)
|
||||
/* debug */ PR_TRUE, /* a debug build */
|
||||
#else
|
||||
/* debug */ PR_FALSE, /* an optomized build */
|
||||
#endif
|
||||
/* special */ PR_FALSE, /* they're all special, but ... */
|
||||
/* filename */ _PRODUCTION, /* the produced library name */
|
||||
/* description */ "Portable runtime", /* what we are */
|
||||
/* security */ "N/A", /* not applicable here */
|
||||
/* copywrite */ "Copyright (c) 1998 Netscape Communications Corporation. All Rights Reserved",
|
||||
/* comment */ "http://www.mozilla.org/MPL/",
|
||||
/* specialString */ ""
|
||||
};
|
||||
|
||||
#ifdef XP_UNIX
|
||||
|
||||
/*
|
||||
* Version information for the 'ident' and 'what commands
|
||||
*
|
||||
* NOTE: the first component of the concatenated rcsid string
|
||||
* must not end in a '$' to prevent rcs keyword substitution.
|
||||
*/
|
||||
static char rcsid[] = "$Header: NSPR " PR_VERSION _DEBUG_STRING
|
||||
" " _BUILD_STRING " $";
|
||||
static char sccsid[] = "@(#)NSPR " PR_VERSION _DEBUG_STRING
|
||||
" " _BUILD_STRING;
|
||||
|
||||
#endif /* XP_UNIX */
|
||||
|
||||
PR_IMPLEMENT(const PRVersionDescription*) libVersionPoint()
|
||||
{
|
||||
#ifdef XP_UNIX
|
||||
/*
|
||||
* Add dummy references to rcsid and sccsid to prevent them
|
||||
* from being optimized away as unused variables.
|
||||
*/
|
||||
const char *dummy;
|
||||
|
||||
dummy = rcsid;
|
||||
dummy = sccsid;
|
||||
#endif
|
||||
return &VERSION_DESC_NAME;
|
||||
} /* versionEntryPointType */
|
||||
|
||||
/* plvrsion.c */
|
||||
|
||||
@@ -1,81 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla 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/MPL/
|
||||
*
|
||||
* 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 the Netscape Portable Runtime (NSPR).
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998-2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "plstr.h"
|
||||
#include <string.h>
|
||||
|
||||
PR_IMPLEMENT(char *)
|
||||
PL_strcat(char *dest, const char *src)
|
||||
{
|
||||
if( ((char *)0 == dest) || ((const char *)0 == src) )
|
||||
return dest;
|
||||
|
||||
return strcat(dest, src);
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(char *)
|
||||
PL_strncat(char *dest, const char *src, PRUint32 max)
|
||||
{
|
||||
char *rv;
|
||||
|
||||
if( ((char *)0 == dest) || ((const char *)0 == src) || (0 == max) )
|
||||
return dest;
|
||||
|
||||
for( rv = dest; *dest; dest++ )
|
||||
;
|
||||
|
||||
(void)PL_strncpy(dest, src, max);
|
||||
return rv;
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(char *)
|
||||
PL_strcatn(char *dest, PRUint32 max, const char *src)
|
||||
{
|
||||
char *rv;
|
||||
PRUint32 dl;
|
||||
|
||||
if( ((char *)0 == dest) || ((const char *)0 == src) )
|
||||
return dest;
|
||||
|
||||
for( rv = dest, dl = 0; *dest; dest++, dl++ )
|
||||
;
|
||||
|
||||
if( max <= dl ) return rv;
|
||||
(void)PL_strncpyz(dest, src, max-dl);
|
||||
|
||||
return rv;
|
||||
}
|
||||
@@ -1,115 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla 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/MPL/
|
||||
*
|
||||
* 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 the Netscape Portable Runtime (NSPR).
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998-2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "plstr.h"
|
||||
|
||||
static const unsigned char uc[] =
|
||||
{
|
||||
'\000', '\001', '\002', '\003', '\004', '\005', '\006', '\007',
|
||||
'\010', '\011', '\012', '\013', '\014', '\015', '\016', '\017',
|
||||
'\020', '\021', '\022', '\023', '\024', '\025', '\026', '\027',
|
||||
'\030', '\031', '\032', '\033', '\034', '\035', '\036', '\037',
|
||||
' ', '!', '"', '#', '$', '%', '&', '\'',
|
||||
'(', ')', '*', '+', ',', '-', '.', '/',
|
||||
'0', '1', '2', '3', '4', '5', '6', '7',
|
||||
'8', '9', ':', ';', '<', '=', '>', '?',
|
||||
'@', 'A', 'B', 'C', 'D', 'E', 'F', 'G',
|
||||
'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
|
||||
'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
|
||||
'X', 'Y', 'Z', '[', '\\', ']', '^', '_',
|
||||
'`', 'A', 'B', 'C', 'D', 'E', 'F', 'G',
|
||||
'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
|
||||
'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
|
||||
'X', 'Y', 'Z', '{', '|', '}', '~', '\177',
|
||||
0200, 0201, 0202, 0203, 0204, 0205, 0206, 0207,
|
||||
0210, 0211, 0212, 0213, 0214, 0215, 0216, 0217,
|
||||
0220, 0221, 0222, 0223, 0224, 0225, 0226, 0227,
|
||||
0230, 0231, 0232, 0233, 0234, 0235, 0236, 0237,
|
||||
0240, 0241, 0242, 0243, 0244, 0245, 0246, 0247,
|
||||
0250, 0251, 0252, 0253, 0254, 0255, 0256, 0257,
|
||||
0260, 0261, 0262, 0263, 0264, 0265, 0266, 0267,
|
||||
0270, 0271, 0272, 0273, 0274, 0275, 0276, 0277,
|
||||
0300, 0301, 0302, 0303, 0304, 0305, 0306, 0307,
|
||||
0310, 0311, 0312, 0313, 0314, 0315, 0316, 0317,
|
||||
0320, 0321, 0322, 0323, 0324, 0325, 0326, 0327,
|
||||
0330, 0331, 0332, 0333, 0334, 0335, 0336, 0337,
|
||||
0340, 0341, 0342, 0343, 0344, 0345, 0346, 0347,
|
||||
0350, 0351, 0352, 0353, 0354, 0355, 0356, 0357,
|
||||
0360, 0361, 0362, 0363, 0364, 0365, 0366, 0367,
|
||||
0370, 0371, 0372, 0373, 0374, 0375, 0376, 0377
|
||||
};
|
||||
|
||||
PR_IMPLEMENT(PRIntn)
|
||||
PL_strcasecmp(const char *a, const char *b)
|
||||
{
|
||||
const unsigned char *ua = (const unsigned char *)a;
|
||||
const unsigned char *ub = (const unsigned char *)b;
|
||||
|
||||
if( ((const char *)0 == a) || (const char *)0 == b )
|
||||
return (PRIntn)(a-b);
|
||||
|
||||
while( (uc[*ua] == uc[*ub]) && ('\0' != *a) )
|
||||
{
|
||||
a++;
|
||||
ua++;
|
||||
ub++;
|
||||
}
|
||||
|
||||
return (PRIntn)(uc[*ua] - uc[*ub]);
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(PRIntn)
|
||||
PL_strncasecmp(const char *a, const char *b, PRUint32 max)
|
||||
{
|
||||
const unsigned char *ua = (const unsigned char *)a;
|
||||
const unsigned char *ub = (const unsigned char *)b;
|
||||
|
||||
if( ((const char *)0 == a) || (const char *)0 == b )
|
||||
return (PRIntn)(a-b);
|
||||
|
||||
while( max && (uc[*ua] == uc[*ub]) && ('\0' != *a) )
|
||||
{
|
||||
a++;
|
||||
ua++;
|
||||
ub++;
|
||||
max--;
|
||||
}
|
||||
|
||||
if( 0 == max ) return (PRIntn)0;
|
||||
|
||||
return (PRIntn)(uc[*ua] - uc[*ub]);
|
||||
}
|
||||
@@ -1,88 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla 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/MPL/
|
||||
*
|
||||
* 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 the Netscape Portable Runtime (NSPR).
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998-2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "plstr.h"
|
||||
#include <string.h>
|
||||
|
||||
PR_IMPLEMENT(char *)
|
||||
PL_strchr(const char *s, char c)
|
||||
{
|
||||
if( (const char *)0 == s ) return (char *)0;
|
||||
|
||||
return strchr(s, c);
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(char *)
|
||||
PL_strrchr(const char *s, char c)
|
||||
{
|
||||
if( (const char *)0 == s ) return (char *)0;
|
||||
|
||||
return strrchr(s, c);
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(char *)
|
||||
PL_strnchr(const char *s, char c, PRUint32 n)
|
||||
{
|
||||
if( (const char *)0 == s ) return (char *)0;
|
||||
|
||||
for( ; n && *s; s++, n-- )
|
||||
if( *s == c )
|
||||
return (char *)s;
|
||||
|
||||
if( ((char)0 == c) && (n > 0) && ((char)0 == *s) ) return (char *)s;
|
||||
|
||||
return (char *)0;
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(char *)
|
||||
PL_strnrchr(const char *s, char c, PRUint32 n)
|
||||
{
|
||||
const char *p;
|
||||
|
||||
if( (const char *)0 == s ) return (char *)0;
|
||||
|
||||
for( p = s; n && *p; p++, n-- )
|
||||
;
|
||||
|
||||
if( ((char)0 == c) && (n > 0) && ((char)0 == *p) ) return (char *)p;
|
||||
|
||||
for( p--; p >= s; p-- )
|
||||
if( *p == c )
|
||||
return (char *)p;
|
||||
|
||||
return (char *)0;
|
||||
}
|
||||
@@ -1,57 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla 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/MPL/
|
||||
*
|
||||
* 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 the Netscape Portable Runtime (NSPR).
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998-2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "plstr.h"
|
||||
#include <string.h>
|
||||
|
||||
PR_IMPLEMENT(PRIntn)
|
||||
PL_strcmp(const char *a, const char *b)
|
||||
{
|
||||
if( ((const char *)0 == a) || (const char *)0 == b )
|
||||
return (PRIntn)(a-b);
|
||||
|
||||
return (PRIntn)strcmp(a, b);
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(PRIntn)
|
||||
PL_strncmp(const char *a, const char *b, PRUint32 max)
|
||||
{
|
||||
if( ((const char *)0 == a) || (const char *)0 == b )
|
||||
return (PRIntn)(a-b);
|
||||
|
||||
return (PRIntn)strncmp(a, b, (size_t)max);
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user