Compare commits

..

2 Commits

Author SHA1 Message Date
rginda%netscape.com
90ec25ad49 first cut, works on unix, need to undo some s/STL/stl/ changes before final merge
git-svn-id: svn://10.0.0.236/branches/STLPORT_FUNFUNFUN@75136 18797224-902f-48f8-a5cc-f745e15eee43
2000-07-29 02:10:14 +00:00
(no author)
cc0938739a This commit was manufactured by cvs2svn to create branch
'STLPORT_FUNFUNFUN'.

git-svn-id: svn://10.0.0.236/branches/STLPORT_FUNFUNFUN@75135 18797224-902f-48f8-a5cc-f745e15eee43
2000-07-29 02:00:13 +00:00
2288 changed files with 56052 additions and 727334 deletions

View File

@@ -1,37 +0,0 @@
#
# The contents of this file are subject to the Netscape Public
# License Version 1.1 (the "License"); you may not use this file
# except in compliance with the License. You may obtain a copy of
# the License at http://www.mozilla.org/NPL/
#
# Software distributed under the License is distributed on an "AS
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
# implied. See the License for the specific language governing
# rights and limitations under the License.
#
# The Original Code is mozilla.org code.
#
# The Initial Developer of the Original Code is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s):
#
DEPTH = ..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
MODULE = dbm
DIRS = include src
ifdef ENABLE_TESTS
DIRS += tests
endif
include $(topsrcdir)/config/rules.mk

View File

@@ -1,55 +0,0 @@
#
# The contents of this file are subject to the Netscape Public
# License Version 1.1 (the "License"); you may not use this file
# except in compliance with the License. You may obtain a copy of
# the License at http://www.mozilla.org/NPL/
#
# Software distributed under the License is distributed on an "AS
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
# implied. See the License for the specific language governing
# rights and limitations under the License.
#
# The Original Code is mozilla.org code.
#
# The Initial Developer of the Original Code is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s):
#
DEPTH = ../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
MODULE = dbm
EXPORTS = \
nsres.h \
cdefs.h \
mcom_db.h \
ncompat.h \
winfile.h \
$(NULL)
EXPORTS := $(addprefix $(srcdir)/, $(EXPORTS))
PRIVATE_EXPORTS = \
hsearch.h \
page.h \
extern.h \
ndbm.h \
queue.h \
hash.h \
mpool.h \
search.h \
$(NULL)
PRIVATE_EXPORTS := $(addprefix $(srcdir)/, $(PRIVATE_EXPORTS))
include $(topsrcdir)/config/rules.mk

View File

@@ -1,60 +0,0 @@
# The contents of this file are subject to the Netscape Public
# License Version 1.1 (the "License"); you may not use this file
# except in compliance with the License. You may obtain a copy of
# the License at http://www.mozilla.org/NPL/
#
# Software distributed under the License is distributed on an "AS
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
# implied. See the License for the specific language governing
# rights and limitations under the License.
#
# The Original Code is mozilla.org code.
#
# The Initial Developer of the Original Code is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s):
#//------------------------------------------------------------------------
#//
#// Makefile to build the cert library
#//
#//------------------------------------------------------------------------
!if "$(MOZ_BITS)" == "16"
!ifndef MOZ_DEBUG
OPTIMIZER=-Os -UDEBUG -DNDEBUG
!endif
!endif
#//------------------------------------------------------------------------
#//
#// Specify the depth of the current directory relative to the
#// root of NS
#//
#//------------------------------------------------------------------------
DEPTH= ..\..
!ifndef MAKE_OBJ_TYPE
MAKE_OBJ_TYPE=EXE
!endif
#//------------------------------------------------------------------------
#//
#// install headers
#//
#//------------------------------------------------------------------------
EXPORTS=nsres.h cdefs.h mcom_db.h ncompat.h winfile.h
#//------------------------------------------------------------------------
#//
#// Include the common makefile rules
#//
#//------------------------------------------------------------------------
include <$(DEPTH)/config/rules.mak>
CFLAGS = $(CFLAGS) -DMOZILLA_CLIENT

View File

@@ -1,165 +0,0 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Netscape Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1998
* 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 NPL, 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 NPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
/*
* Copyright (c) 1991, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Berkeley Software Design, Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)cdefs.h 8.7 (Berkeley) 1/21/94
*/
#ifndef _CDEFS_H_
#define _CDEFS_H_
#if defined(__cplusplus)
#define __BEGIN_DECLS extern "C" {
#define __END_DECLS }
#else
#define __BEGIN_DECLS
#define __END_DECLS
#endif
/*
* The __CONCAT macro is used to concatenate parts of symbol names, e.g.
* with "#define OLD(foo) __CONCAT(old,foo)", OLD(foo) produces oldfoo.
* The __CONCAT macro is a bit tricky -- make sure you don't put spaces
* in between its arguments. __CONCAT can also concatenate double-quoted
* strings produced by the __STRING macro, but this only works with ANSI C.
*/
#if defined(__STDC__) || defined(__cplusplus) || defined(_WINDOWS) || defined(XP_OS2)
#define __P(protos) protos /* full-blown ANSI C */
#define __CONCAT(x,y) x ## y
#define __STRING(x) #x
/* On HP-UX 11.00, <sys/stdsyms.h> defines __const. */
#ifndef __const
#define __const const /* define reserved names to standard */
#endif /* __const */
#define __signed signed
#define __volatile volatile
#ifndef _WINDOWS
#if defined(__cplusplus)
#define __inline inline /* convert to C++ keyword */
#else
#if !defined(__GNUC__) && !defined(__MWERKS__)
#define __inline /* delete GCC keyword */
#endif /* !__GNUC__ */
#endif /* !__cplusplus */
#endif /* !_WINDOWS */
#else /* !(__STDC__ || __cplusplus) */
#define __P(protos) () /* traditional C preprocessor */
#define __CONCAT(x,y) x/**/y
#define __STRING(x) "x"
#ifndef __GNUC__
#define __const /* delete pseudo-ANSI C keywords */
#define __inline
#define __signed
#define __volatile
/*
* In non-ANSI C environments, new programs will want ANSI-only C keywords
* deleted from the program and old programs will want them left alone.
* When using a compiler other than gcc, programs using the ANSI C keywords
* const, inline etc. as normal identifiers should define -DNO_ANSI_KEYWORDS.
* When using "gcc -traditional", we assume that this is the intent; if
* __GNUC__ is defined but __STDC__ is not, we leave the new keywords alone.
*/
#ifndef NO_ANSI_KEYWORDS
#define const /* delete ANSI C keywords */
#define inline
#define signed
#define volatile
#endif
#endif /* !__GNUC__ */
#endif /* !(__STDC__ || __cplusplus) */
/*
* GCC1 and some versions of GCC2 declare dead (non-returning) and
* pure (no side effects) functions using "volatile" and "const";
* unfortunately, these then cause warnings under "-ansi -pedantic".
* GCC2 uses a new, peculiar __attribute__((attrs)) style. All of
* these work for GNU C++ (modulo a slight glitch in the C++ grammar
* in the distribution version of 2.5.5).
*/
#if !defined(__GNUC__) || __GNUC__ < 2 || __GNUC_MINOR__ < 5
#define __attribute__(x) /* delete __attribute__ if non-gcc or gcc1 */
#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
#define __dead __volatile
#define __pure __const
#endif
#endif
/* Delete pseudo-keywords wherever they are not available or needed. */
#ifndef __dead
#define __dead
#define __pure
#endif
#endif /* !_CDEFS_H_ */

View File

@@ -1,65 +0,0 @@
/*-
* Copyright (c) 1991, 1993, 1994
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)extern.h 8.4 (Berkeley) 6/16/94
*/
BUFHEAD *__add_ovflpage (HTAB *, BUFHEAD *);
int __addel (HTAB *, BUFHEAD *, const DBT *, const DBT *);
int __big_delete (HTAB *, BUFHEAD *);
int __big_insert (HTAB *, BUFHEAD *, const DBT *, const DBT *);
int __big_keydata (HTAB *, BUFHEAD *, DBT *, DBT *, int);
int __big_return (HTAB *, BUFHEAD *, int, DBT *, int);
int __big_split (HTAB *, BUFHEAD *, BUFHEAD *, BUFHEAD *,
uint32, uint32, SPLIT_RETURN *);
int __buf_free (HTAB *, int, int);
void __buf_init (HTAB *, int);
uint32 __call_hash (HTAB *, char *, size_t);
int __delpair (HTAB *, BUFHEAD *, int);
int __expand_table (HTAB *);
int __find_bigpair (HTAB *, BUFHEAD *, int, char *, int);
uint16 __find_last_page (HTAB *, BUFHEAD **);
void __free_ovflpage (HTAB *, BUFHEAD *);
BUFHEAD *__get_buf (HTAB *, uint32, BUFHEAD *, int);
int __get_page (HTAB *, char *, uint32, int, int, int);
int __ibitmap (HTAB *, int, int, int);
uint32 __log2 (uint32);
int __put_page (HTAB *, char *, uint32, int, int);
void __reclaim_buf (HTAB *, BUFHEAD *);
int __split_page (HTAB *, uint32, uint32);
/* Default hash routine. */
extern uint32 (*__default_hash) (const void *, size_t);
#ifdef HASH_STATISTICS
extern int hash_accesses, hash_collisions, hash_expansions, hash_overflows;
#endif

View File

@@ -1,337 +0,0 @@
/*-
* Copyright (c) 1990, 1993, 1994
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Margo Seltzer.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)hash.h 8.3 (Berkeley) 5/31/94
*/
/* Operations */
#include <stdio.h>
#include "mcom_db.h"
typedef enum {
HASH_GET, HASH_PUT, HASH_PUTNEW, HASH_DELETE, HASH_FIRST, HASH_NEXT
} ACTION;
/* Buffer Management structures */
typedef struct _bufhead BUFHEAD;
struct _bufhead {
BUFHEAD *prev; /* LRU links */
BUFHEAD *next; /* LRU links */
BUFHEAD *ovfl; /* Overflow page buffer header */
uint32 addr; /* Address of this page */
char *page; /* Actual page data */
char is_disk;
char flags;
#define BUF_MOD 0x0001
#define BUF_DISK 0x0002
#define BUF_BUCKET 0x0004
#define BUF_PIN 0x0008
};
#define IS_BUCKET(X) ((X) & BUF_BUCKET)
typedef BUFHEAD **SEGMENT;
typedef int DBFILE_PTR;
#define NO_FILE -1
#ifdef macintosh
#define DBFILE_OPEN(path, flag,mode) open((path), flag)
#define EXISTS(path)
#else
#define DBFILE_OPEN(path, flag,mode) open((path), (flag), (mode))
#endif
/* Hash Table Information */
typedef struct hashhdr { /* Disk resident portion */
int32 magic; /* Magic NO for hash tables */
int32 version; /* Version ID */
uint32 lorder; /* Byte Order */
int32 bsize; /* Bucket/Page Size */
int32 bshift; /* Bucket shift */
int32 dsize; /* Directory Size */
int32 ssize; /* Segment Size */
int32 sshift; /* Segment shift */
int32 ovfl_point; /* Where overflow pages are being
* allocated */
int32 last_freed; /* Last overflow page freed */
int32 max_bucket; /* ID of Maximum bucket in use */
int32 high_mask; /* Mask to modulo into entire table */
int32 low_mask; /* Mask to modulo into lower half of
* table */
int32 ffactor; /* Fill factor */
int32 nkeys; /* Number of keys in hash table */
int32 hdrpages; /* Size of table header */
uint32 h_charkey; /* value of hash(CHARKEY) */
#define NCACHED 32 /* number of bit maps and spare
* points */
int32 spares[NCACHED];/* spare pages for overflow */
uint16 bitmaps[NCACHED]; /* address of overflow page
* bitmaps */
} HASHHDR;
typedef struct htab { /* Memory resident data structure */
HASHHDR hdr; /* Header */
int nsegs; /* Number of allocated segments */
int exsegs; /* Number of extra allocated
* segments */
uint32 /* Hash function */
(*hash)(const void *, size_t);
int flags; /* Flag values */
DBFILE_PTR fp; /* File pointer */
char *filename;
char *tmp_buf; /* Temporary Buffer for BIG data */
char *tmp_key; /* Temporary Buffer for BIG keys */
BUFHEAD *cpage; /* Current page */
int cbucket; /* Current bucket */
int cndx; /* Index of next item on cpage */
int dbmerrno; /* Error Number -- for DBM
* compatability */
int new_file; /* Indicates if fd is backing store
* or no */
int save_file; /* Indicates whether we need to flush
* file at
* exit */
uint32 *mapp[NCACHED]; /* Pointers to page maps */
int nmaps; /* Initial number of bitmaps */
int nbufs; /* Number of buffers left to
* allocate */
BUFHEAD bufhead; /* Header of buffer lru list */
SEGMENT *dir; /* Hash Bucket directory */
off_t file_size; /* in bytes */
char is_temp; /* unlink file on close */
char updateEOF; /* force EOF update on flush */
} HTAB;
/*
* Constants
*/
#define DATABASE_CORRUPTED_ERROR -999 /* big ugly abort, delete database */
#define OLD_MAX_BSIZE 65536 /* 2^16 */
#define MAX_BSIZE 32l*1024l /* 2^15 */
#define MIN_BUFFERS 6
#define MINHDRSIZE 512
#define DEF_BUFSIZE 65536l /* 64 K */
#define DEF_BUCKET_SIZE 4096
#define DEF_BUCKET_SHIFT 12 /* log2(BUCKET) */
#define DEF_SEGSIZE 256
#define DEF_SEGSIZE_SHIFT 8 /* log2(SEGSIZE) */
#define DEF_DIRSIZE 256
#define DEF_FFACTOR 65536l
#define MIN_FFACTOR 4
#define SPLTMAX 8
#define CHARKEY "%$sniglet^&"
#define NUMKEY 1038583l
#define BYTE_SHIFT 3
#define INT_TO_BYTE 2
#define INT_BYTE_SHIFT 5
#define ALL_SET ((uint32)0xFFFFFFFF)
#define ALL_CLEAR 0
#define PTROF(X) ((ptrdiff_t)(X) == BUF_DISK ? 0 : (X))
#define ISDISK(X) ((X) ? ((ptrdiff_t)(X) == BUF_DISK ? BUF_DISK \
: (X)->is_disk) : 0)
#define BITS_PER_MAP 32
/* Given the address of the beginning of a big map, clear/set the nth bit */
#define CLRBIT(A, N) ((A)[(N)/BITS_PER_MAP] &= ~(1<<((N)%BITS_PER_MAP)))
#define SETBIT(A, N) ((A)[(N)/BITS_PER_MAP] |= (1<<((N)%BITS_PER_MAP)))
#define ISSET(A, N) ((A)[(N)/BITS_PER_MAP] & (1<<((N)%BITS_PER_MAP)))
/* Overflow management */
/*
* Overflow page numbers are allocated per split point. At each doubling of
* the table, we can allocate extra pages. So, an overflow page number has
* the top 5 bits indicate which split point and the lower 11 bits indicate
* which page at that split point is indicated (pages within split points are
* numberered starting with 1).
*/
#define SPLITSHIFT 11
#define SPLITMASK 0x7FF
#define SPLITNUM(N) (((uint32)(N)) >> SPLITSHIFT)
#define OPAGENUM(N) ((N) & SPLITMASK)
#define OADDR_OF(S,O) ((uint32)((uint32)(S) << SPLITSHIFT) + (O))
#define BUCKET_TO_PAGE(B) \
(B) + hashp->HDRPAGES + ((B) ? hashp->SPARES[__log2((uint32)((B)+1))-1] : 0)
#define OADDR_TO_PAGE(B) \
BUCKET_TO_PAGE ( (1 << SPLITNUM((B))) -1 ) + OPAGENUM((B));
/*
* page.h contains a detailed description of the page format.
*
* Normally, keys and data are accessed from offset tables in the top of
* each page which point to the beginning of the key and data. There are
* four flag values which may be stored in these offset tables which indicate
* the following:
*
*
* OVFLPAGE Rather than a key data pair, this pair contains
* the address of an overflow page. The format of
* the pair is:
* OVERFLOW_PAGE_NUMBER OVFLPAGE
*
* PARTIAL_KEY This must be the first key/data pair on a page
* and implies that page contains only a partial key.
* That is, the key is too big to fit on a single page
* so it starts on this page and continues on the next.
* The format of the page is:
* KEY_OFF PARTIAL_KEY OVFL_PAGENO OVFLPAGE
*
* KEY_OFF -- offset of the beginning of the key
* PARTIAL_KEY -- 1
* OVFL_PAGENO - page number of the next overflow page
* OVFLPAGE -- 0
*
* FULL_KEY This must be the first key/data pair on the page. It
* is used in two cases.
*
* Case 1:
* There is a complete key on the page but no data
* (because it wouldn't fit). The next page contains
* the data.
*
* Page format it:
* KEY_OFF FULL_KEY OVFL_PAGENO OVFL_PAGE
*
* KEY_OFF -- offset of the beginning of the key
* FULL_KEY -- 2
* OVFL_PAGENO - page number of the next overflow page
* OVFLPAGE -- 0
*
* Case 2:
* This page contains no key, but part of a large
* data field, which is continued on the next page.
*
* Page format it:
* DATA_OFF FULL_KEY OVFL_PAGENO OVFL_PAGE
*
* KEY_OFF -- offset of the beginning of the data on
* this page
* FULL_KEY -- 2
* OVFL_PAGENO - page number of the next overflow page
* OVFLPAGE -- 0
*
* FULL_KEY_DATA
* This must be the first key/data pair on the page.
* There are two cases:
*
* Case 1:
* This page contains a key and the beginning of the
* data field, but the data field is continued on the
* next page.
*
* Page format is:
* KEY_OFF FULL_KEY_DATA OVFL_PAGENO DATA_OFF
*
* KEY_OFF -- offset of the beginning of the key
* FULL_KEY_DATA -- 3
* OVFL_PAGENO - page number of the next overflow page
* DATA_OFF -- offset of the beginning of the data
*
* Case 2:
* This page contains the last page of a big data pair.
* There is no key, only the tail end of the data
* on this page.
*
* Page format is:
* DATA_OFF FULL_KEY_DATA <OVFL_PAGENO> <OVFLPAGE>
*
* DATA_OFF -- offset of the beginning of the data on
* this page
* FULL_KEY_DATA -- 3
* OVFL_PAGENO - page number of the next overflow page
* OVFLPAGE -- 0
*
* OVFL_PAGENO and OVFLPAGE are optional (they are
* not present if there is no next page).
*/
#define OVFLPAGE 0
#define PARTIAL_KEY 1
#define FULL_KEY 2
#define FULL_KEY_DATA 3
#define REAL_KEY 4
/* Short hands for accessing structure */
#undef BSIZE
#define BSIZE hdr.bsize
#undef BSHIFT
#define BSHIFT hdr.bshift
#define DSIZE hdr.dsize
#define SGSIZE hdr.ssize
#define SSHIFT hdr.sshift
#define LORDER hdr.lorder
#define OVFL_POINT hdr.ovfl_point
#define LAST_FREED hdr.last_freed
#define MAX_BUCKET hdr.max_bucket
#define FFACTOR hdr.ffactor
#define HIGH_MASK hdr.high_mask
#define LOW_MASK hdr.low_mask
#define NKEYS hdr.nkeys
#define HDRPAGES hdr.hdrpages
#define SPARES hdr.spares
#define BITMAPS hdr.bitmaps
#define VERSION hdr.version
#define MAGIC hdr.magic
#define NEXT_FREE hdr.next_free
#define H_CHARKEY hdr.h_charkey
extern uint32 (*__default_hash) (const void *, size_t);
void __buf_init(HTAB *hashp, int32 nbytes);
int __big_delete(HTAB *hashp, BUFHEAD *bufp);
BUFHEAD * __get_buf(HTAB *hashp, uint32 addr, BUFHEAD *prev_bp, int newpage);
uint32 __call_hash(HTAB *hashp, char *k, size_t len);
#include "page.h"
extern int __big_split(HTAB *hashp, BUFHEAD *op,BUFHEAD *np,
BUFHEAD *big_keyp,uint32 addr,uint32 obucket, SPLIT_RETURN *ret);
void __free_ovflpage(HTAB *hashp, BUFHEAD *obufp);
BUFHEAD * __add_ovflpage(HTAB *hashp, BUFHEAD *bufp);
int __big_insert(HTAB *hashp, BUFHEAD *bufp, const DBT *key, const DBT *val);
int __expand_table(HTAB *hashp);
uint32 __log2(uint32 num);
void __reclaim_buf(HTAB *hashp, BUFHEAD *bp);
int __get_page(HTAB *hashp, char * p, uint32 bucket, int is_bucket, int is_disk, int is_bitmap);
int __put_page(HTAB *hashp, char *p, uint32 bucket, int is_bucket, int is_bitmap);
int __ibitmap(HTAB *hashp, int pnum, int nbits, int ndx);
int __buf_free(HTAB *hashp, int do_free, int to_disk);
int __find_bigpair(HTAB *hashp, BUFHEAD *bufp, int ndx, char *key, int size);
uint16 __find_last_page(HTAB *hashp, BUFHEAD **bpp);
int __addel(HTAB *hashp, BUFHEAD *bufp, const DBT *key, const DBT * val);
int __big_return(HTAB *hashp, BUFHEAD *bufp, int ndx, DBT *val, int set_current);
int __delpair(HTAB *hashp, BUFHEAD *bufp, int ndx);
int __big_keydata(HTAB *hashp, BUFHEAD *bufp, DBT *key, DBT *val, int set);
int __split_page(HTAB *hashp, uint32 obucket, uint32 nbucket);

View File

@@ -1,51 +0,0 @@
/*-
* Copyright (c) 1990, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Margo Seltzer.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)search.h 8.1 (Berkeley) 6/4/93
*/
/* Backward compatibility to hsearch interface. */
typedef struct entry {
char *key;
char *data;
} ENTRY;
typedef enum {
FIND, ENTER
} ACTION;
int hcreate (unsigned int);
void hdestroy (void);
ENTRY *hsearch (ENTRY, ACTION);

View File

@@ -1,463 +0,0 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Netscape Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1998
* 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 NPL, 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 NPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
/*-
* Copyright (c) 1990, 1993, 1994
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)db.h 8.7 (Berkeley) 6/16/94
*/
#ifndef _DB_H_
#define _DB_H_
#ifdef WINCE
#define off_t long
#endif
#ifndef macintosh
#include <sys/types.h>
#endif
#include "prtypes.h"
#include <limits.h>
#ifdef __DBINTERFACE_PRIVATE
#ifdef HAVE_SYS_CDEFS_H
#include <sys/cdefs.h>
#else
#include "cdefs.h"
#endif
#ifdef HAVE_SYS_BYTEORDER_H
#include <sys/byteorder.h>
#endif
#if defined(__linux) || defined(__BEOS__)
#include <endian.h>
#ifndef BYTE_ORDER
#define BYTE_ORDER __BYTE_ORDER
#define BIG_ENDIAN __BIG_ENDIAN
#define LITTLE_ENDIAN __LITTLE_ENDIAN
#endif
#endif /* __linux */
#ifdef __sgi
#define BYTE_ORDER BIG_ENDIAN
#define BIG_ENDIAN 4321
#define LITTLE_ENDIAN 1234 /* LSB first: i386, vax, all NT risc */
#endif
#ifdef __sun
#define BIG_ENDIAN 4321
#define LITTLE_ENDIAN 1234 /* LSB first: i386, vax, all NT risc */
#ifndef __SVR4
/* compat.h is only in 4.1.3 machines. - dp */
#include <compat.h>
#endif
/* XXX - dp
* Need to find a general way of defining endian-ness in SunOS 5.3
* SunOS 5.4 defines _BIG_ENDIAN and _LITTLE_ENDIAN
* SunOS 5.3 does nothing like this.
*/
#ifndef BYTE_ORDER
#if defined(_BIG_ENDIAN)
#define BYTE_ORDER BIG_ENDIAN
#elif defined(_LITTLE_ENDIAN)
#define BYTE_ORDER LITTLE_ENDIAN
#elif !defined(__SVR4)
/* 4.1.3 is always BIG_ENDIAN as it was released only on sparc platforms. */
#define BYTE_ORDER BIG_ENDIAN
#elif !defined(vax) && !defined(ntohl) && !defined(lint) && !defined(i386)
/* 5.3 big endian. Copied this above line from sys/byteorder.h */
/* Now we are in a 5.3 SunOS rather non 5.4 or above SunOS */
#define BYTE_ORDER BIG_ENDIAN
#else
#define BYTE_ORDER LITTLE_ENDIAN
#endif
#endif /* !BYTE_ORDER */
#endif /* __sun */
#if defined(__hpux) || defined(__hppa)
#define BYTE_ORDER BIG_ENDIAN
#define BIG_ENDIAN 4321
#define LITTLE_ENDIAN 1234 /* LSB first: i386, vax, all NT risc */
#endif
#if defined(AIXV3) || defined(AIX)
/* BYTE_ORDER, LITTLE_ENDIAN, BIG_ENDIAN are all defined here */
#include <sys/machine.h>
#endif
/* Digital Unix */
#ifdef __osf__
#include <machine/endian.h>
#endif
#ifdef __alpha
#ifndef WIN32
#else
/* Alpha NT */
#define BYTE_ORDER LITTLE_ENDIAN
#define BIG_ENDIAN 4321
#define LITTLE_ENDIAN 1234
#endif
#endif
#ifdef NCR
#include <sys/endian.h>
#endif
#ifdef __QNX__
#ifdef __QNXNTO__
#include <sys/param.h>
#else
#define LITTLE_ENDIAN 1234
#define BIG_ENDIAN 4321
#define BYTE_ORDER LITTLE_ENDIAN
#endif
#endif
#ifdef SNI
/* #include <sys/hetero.h> */
#define BYTE_ORDER BIG_ENDIAN
#define BIG_ENDIAN 4321
#define LITTLE_ENDIAN 1234
#endif
#if defined(_WINDOWS) || defined(XP_OS2_VACPP)
#ifdef BYTE_ORDER
#undef BYTE_ORDER
#endif
#define BYTE_ORDER LITTLE_ENDIAN
#define LITTLE_ENDIAN 1234 /* LSB first: i386, vax, all NT risc */
#define BIG_ENDIAN 4321
#endif
#ifdef macintosh
#define BIG_ENDIAN 4321
#define LITTLE_ENDIAN 1234
#define BYTE_ORDER BIG_ENDIAN
#endif
#endif /* __DBINTERFACE_PRIVATE */
#ifdef SCO
#define MAXPATHLEN 1024
#endif
#include <fcntl.h>
#if defined(_WINDOWS) || defined(XP_OS2)
#include <stdio.h>
#include <io.h>
#ifndef XP_OS2
#define MAXPATHLEN 1024
#endif
#ifdef XP_OS2_VACPP
#include <os2.h>
#define MAXPATHLEN CCHMAXPATH
#define EPERM EINVAL
#define ENOTDIR EBADPOS
#define S_ISDIR(s) ((s) & S_IFDIR)
#endif
#define EFTYPE EINVAL /* POSIX 1003.1 format errno. */
#ifndef STDERR_FILENO
#define STDIN_FILENO 0 /* ANSI C #defines */
#define STDOUT_FILENO 1
#define STDERR_FILENO 2
#endif
#ifndef O_ACCMODE /* POSIX 1003.1 access mode mask. */
#define O_ACCMODE (O_RDONLY|O_WRONLY|O_RDWR)
#endif
#endif
#ifdef macintosh
#include <stdio.h>
#include "xp_mcom.h"
#define O_ACCMODE 3 /* Mask for file access modes */
#define EFTYPE 2000
PR_BEGIN_EXTERN_C
int mkstemp(const char *path);
PR_END_EXTERN_C
#endif /* MACINTOSH */
#if !defined(_WINDOWS) && !defined(macintosh)
#include <sys/stat.h>
#include <errno.h>
#endif
/* define EFTYPE since most don't */
#ifndef EFTYPE
#define EFTYPE EINVAL /* POSIX 1003.1 format errno. */
#endif
#define RET_ERROR -1 /* Return values. */
#define RET_SUCCESS 0
#define RET_SPECIAL 1
#define MAX_PAGE_NUMBER 0xffffffff /* >= # of pages in a file */
#ifndef __sgi
typedef uint32 pgno_t;
#endif
#define MAX_PAGE_OFFSET 65535 /* >= # of bytes in a page */
typedef uint16 indx_t;
#define MAX_REC_NUMBER 0xffffffff /* >= # of records in a tree */
typedef uint32 recno_t;
/* Key/data structure -- a Data-Base Thang. */
typedef struct {
void *data; /* data */
size_t size; /* data length */
} DBT;
/* Routine flags. */
#define R_CURSOR 1 /* del, put, seq */
#define __R_UNUSED 2 /* UNUSED */
#define R_FIRST 3 /* seq */
#define R_IAFTER 4 /* put (RECNO) */
#define R_IBEFORE 5 /* put (RECNO) */
#define R_LAST 6 /* seq (BTREE, RECNO) */
#define R_NEXT 7 /* seq */
#define R_NOOVERWRITE 8 /* put */
#define R_PREV 9 /* seq (BTREE, RECNO) */
#define R_SETCURSOR 10 /* put (RECNO) */
#define R_RECNOSYNC 11 /* sync (RECNO) */
typedef enum { DB_BTREE, DB_HASH, DB_RECNO } DBTYPE;
typedef enum { LockOutDatabase, UnlockDatabase } DBLockFlagEnum;
/*
* !!!
* The following flags are included in the dbopen(3) call as part of the
* open(2) flags. In order to avoid conflicts with the open flags, start
* at the top of the 16 or 32-bit number space and work our way down. If
* the open flags were significantly expanded in the future, it could be
* a problem. Wish I'd left another flags word in the dbopen call.
*
* !!!
* None of this stuff is implemented yet. The only reason that it's here
* is so that the access methods can skip copying the key/data pair when
* the DB_LOCK flag isn't set.
*/
#if UINT_MAX > 65535
#define DB_LOCK 0x20000000 /* Do locking. */
#define DB_SHMEM 0x40000000 /* Use shared memory. */
#define DB_TXN 0x80000000 /* Do transactions. */
#else
#define DB_LOCK 0x2000 /* Do locking. */
#define DB_SHMEM 0x4000 /* Use shared memory. */
#define DB_TXN 0x8000 /* Do transactions. */
#endif
/* Access method description structure. */
typedef struct __db {
DBTYPE type; /* Underlying db type. */
int (*close) (struct __db *);
int (*del) (const struct __db *, const DBT *, uint);
int (*get) (const struct __db *, const DBT *, DBT *, uint);
int (*put) (const struct __db *, DBT *, const DBT *, uint);
int (*seq) (const struct __db *, DBT *, DBT *, uint);
int (*sync) (const struct __db *, uint);
void *internal; /* Access method private. */
int (*fd) (const struct __db *);
} DB;
#define BTREEMAGIC 0x053162
#define BTREEVERSION 3
/* Structure used to pass parameters to the btree routines. */
typedef struct {
#define R_DUP 0x01 /* duplicate keys */
uint32 flags;
uint cachesize; /* bytes to cache */
int maxkeypage; /* maximum keys per page */
int minkeypage; /* minimum keys per page */
uint psize; /* page size */
int (*compare) /* comparison function */
(const DBT *, const DBT *);
size_t (*prefix) /* prefix function */
(const DBT *, const DBT *);
int lorder; /* byte order */
} BTREEINFO;
#define HASHMAGIC 0x061561
#define HASHVERSION 2
/* Structure used to pass parameters to the hashing routines. */
typedef struct {
uint bsize; /* bucket size */
uint ffactor; /* fill factor */
uint nelem; /* number of elements */
uint cachesize; /* bytes to cache */
uint32 /* hash function */
(*hash) (const void *, size_t);
int lorder; /* byte order */
} HASHINFO;
/* Structure used to pass parameters to the record routines. */
typedef struct {
#define R_FIXEDLEN 0x01 /* fixed-length records */
#define R_NOKEY 0x02 /* key not required */
#define R_SNAPSHOT 0x04 /* snapshot the input */
uint32 flags;
uint cachesize; /* bytes to cache */
uint psize; /* page size */
int lorder; /* byte order */
size_t reclen; /* record length (fixed-length records) */
uint8 bval; /* delimiting byte (variable-length records */
char *bfname; /* btree file name */
} RECNOINFO;
#ifdef __DBINTERFACE_PRIVATE
/*
* Little endian <==> big endian 32-bit swap macros.
* M_32_SWAP swap a memory location
* P_32_SWAP swap a referenced memory location
* P_32_COPY swap from one location to another
*/
#define M_32_SWAP(a) { \
uint32 _tmp = a; \
((char *)&a)[0] = ((char *)&_tmp)[3]; \
((char *)&a)[1] = ((char *)&_tmp)[2]; \
((char *)&a)[2] = ((char *)&_tmp)[1]; \
((char *)&a)[3] = ((char *)&_tmp)[0]; \
}
#define P_32_SWAP(a) { \
uint32 _tmp = *(uint32 *)a; \
((char *)a)[0] = ((char *)&_tmp)[3]; \
((char *)a)[1] = ((char *)&_tmp)[2]; \
((char *)a)[2] = ((char *)&_tmp)[1]; \
((char *)a)[3] = ((char *)&_tmp)[0]; \
}
#define P_32_COPY(a, b) { \
((char *)&(b))[0] = ((char *)&(a))[3]; \
((char *)&(b))[1] = ((char *)&(a))[2]; \
((char *)&(b))[2] = ((char *)&(a))[1]; \
((char *)&(b))[3] = ((char *)&(a))[0]; \
}
/*
* Little endian <==> big endian 16-bit swap macros.
* M_16_SWAP swap a memory location
* P_16_SWAP swap a referenced memory location
* P_16_COPY swap from one location to another
*/
#define M_16_SWAP(a) { \
uint16 _tmp = a; \
((char *)&a)[0] = ((char *)&_tmp)[1]; \
((char *)&a)[1] = ((char *)&_tmp)[0]; \
}
#define P_16_SWAP(a) { \
uint16 _tmp = *(uint16 *)a; \
((char *)a)[0] = ((char *)&_tmp)[1]; \
((char *)a)[1] = ((char *)&_tmp)[0]; \
}
#define P_16_COPY(a, b) { \
((char *)&(b))[0] = ((char *)&(a))[1]; \
((char *)&(b))[1] = ((char *)&(a))[0]; \
}
#endif
PR_BEGIN_EXTERN_C
#if defined(__WATCOMC__) || defined(__WATCOM_CPLUSPLUS__)
extern DB *
#else
PR_EXTERN(DB *)
#endif
dbopen (const char *, int, int, DBTYPE, const void *);
/* set or unset a global lock flag to disable the
* opening of any DBM file
*/
void dbSetOrClearDBLock(DBLockFlagEnum type);
#ifdef __DBINTERFACE_PRIVATE
DB *__bt_open (const char *, int, int, const BTREEINFO *, int);
DB *__hash_open (const char *, int, int, const HASHINFO *, int);
DB *__rec_open (const char *, int, int, const RECNOINFO *, int);
void __dbpanic (DB *dbp);
#endif
PR_END_EXTERN_C
#endif /* !_DB_H_ */

View File

@@ -1,99 +0,0 @@
/*-
* Copyright (c) 1991, 1993, 1994
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)mpool.h 8.2 (Berkeley) 7/14/94
*/
#include <sys/queue.h>
/*
* The memory pool scheme is a simple one. Each in-memory page is referenced
* by a bucket which is threaded in up to two of three ways. All active pages
* are threaded on a hash chain (hashed by page number) and an lru chain.
* Inactive pages are threaded on a free chain. Each reference to a memory
* pool is handed an opaque MPOOL cookie which stores all of this information.
*/
#define HASHSIZE 128
#define HASHKEY(pgno) ((pgno - 1) % HASHSIZE)
/* The BKT structures are the elements of the queues. */
typedef struct _bkt {
CIRCLEQ_ENTRY(_bkt) hq; /* hash queue */
CIRCLEQ_ENTRY(_bkt) q; /* lru queue */
void *page; /* page */
pgno_t pgno; /* page number */
#define MPOOL_DIRTY 0x01 /* page needs to be written */
#define MPOOL_PINNED 0x02 /* page is pinned into memory */
uint8 flags; /* flags */
} BKT;
typedef struct MPOOL {
CIRCLEQ_HEAD(_lqh, _bkt) lqh; /* lru queue head */
/* hash queue array */
CIRCLEQ_HEAD(_hqh, _bkt) hqh[HASHSIZE];
pgno_t curcache; /* current number of cached pages */
pgno_t maxcache; /* max number of cached pages */
pgno_t npages; /* number of pages in the file */
uint32 pagesize; /* file page size */
int fd; /* file descriptor */
/* page in conversion routine */
void (*pgin) (void *, pgno_t, void *);
/* page out conversion routine */
void (*pgout) (void *, pgno_t, void *);
void *pgcookie; /* cookie for page in/out routines */
#ifdef STATISTICS
uint32 cachehit;
uint32 cachemiss;
uint32 pagealloc;
uint32 pageflush;
uint32 pageget;
uint32 pagenew;
uint32 pageput;
uint32 pageread;
uint32 pagewrite;
#endif
} MPOOL;
__BEGIN_DECLS
MPOOL *mpool_open (void *, int, pgno_t, pgno_t);
void mpool_filter (MPOOL *, void (*)(void *, pgno_t, void *),
void (*)(void *, pgno_t, void *), void *);
void *mpool_new (MPOOL *, pgno_t *);
void *mpool_get (MPOOL *, pgno_t, uint);
int mpool_put (MPOOL *, void *, uint);
int mpool_sync (MPOOL *);
int mpool_close (MPOOL *);
#ifdef STATISTICS
void mpool_stat (MPOOL *);
#endif
__END_DECLS

View File

@@ -1,232 +0,0 @@
/*-
* Copyright (c) 1991, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)compat.h 8.13 (Berkeley) 2/21/94
*/
#ifndef _COMPAT_H_
#define _COMPAT_H_
#include <sys/types.h>
/*
* If your system doesn't typedef u_long, u_short, or u_char, change
* the 0 to a 1.
*/
#if 0
typedef unsigned char u_char; /* 4.[34]BSD names. */
typedef unsigned int u_int;
typedef unsigned long u_long;
typedef unsigned short u_short;
#endif
/* If your system doesn't typedef size_t, change the 0 to a 1. */
#if 0
typedef unsigned int size_t; /* POSIX, 4.[34]BSD names. */
#endif
/* If your system doesn't typedef ssize_t, change the 0 to a 1. */
#if 0
typedef int ssize_t; /* POSIX names. */
#endif
/*
* If your system doesn't have the POSIX type for a signal mask,
* change the 0 to a 1.
*/
#if 0 /* POSIX 1003.1 signal mask type. */
typedef unsigned int sigset_t;
#endif
/*
* If your system's vsprintf returns a char *, not an int,
* change the 0 to a 1.
*/
#if defined (__sun) && !defined(__SVR4) /* SUNOS */
#define VSPRINTF_CHARSTAR
#endif
/*
* If you don't have POSIX 1003.1 signals, the signal code surrounding the
* temporary file creation is intended to block all of the possible signals
* long enough to create the file and unlink it. All of this stuff is
* intended to use old-style BSD calls to fake POSIX 1003.1 calls.
*/
#ifdef NO_POSIX_SIGNALS
#define sigemptyset(set) (*(set) = 0)
#define sigfillset(set) (*(set) = ~(sigset_t)0, 0)
#define sigaddset(set,signo) (*(set) |= sigmask(signo), 0)
#define sigdelset(set,signo) (*(set) &= ~sigmask(signo), 0)
#define sigismember(set,signo) ((*(set) & sigmask(signo)) != 0)
#define SIG_BLOCK 1
#define SIG_UNBLOCK 2
#define SIG_SETMASK 3
static int __sigtemp; /* For the use of sigprocmask */
/* Repeated test of oset != NULL is to avoid "*0". */
#define sigprocmask(how, set, oset) \
((__sigtemp = \
(((how) == SIG_BLOCK) ? \
sigblock(0) | *(set) : \
(((how) == SIG_UNBLOCK) ? \
sigblock(0) & ~(*(set)) : \
((how) == SIG_SETMASK ? \
*(set) : sigblock(0))))), \
((oset) ? (*(oset ? oset : set) = sigsetmask(__sigtemp)) : \
sigsetmask(__sigtemp)), 0)
#endif
/*
* If your system doesn't have an include file with the appropriate
* byte order set, make sure you specify the correct one.
*/
#ifndef BYTE_ORDER
#define LITTLE_ENDIAN 1234 /* LSB first: i386, vax */
#define BIG_ENDIAN 4321 /* MSB first: 68000, ibm, net */
#define BYTE_ORDER BIG_ENDIAN /* Set for your system. */
#endif
#if defined(SYSV) || defined(SYSTEM5) || defined(__sun)
#define index(a, b) strchr(a, b)
#define rindex(a, b) strrchr(a, b)
#define bzero(a, b) memset(a, 0, b)
#define bcmp(a, b, n) memcmp(a, b, n)
#define bcopy(a, b, n) memmove(b, a, n)
#endif
#if defined(BSD) || defined(BSD4_3)
#define strchr(a, b) index(a, b)
#define strrchr(a, b) rindex(a, b)
#define memcmp(a, b, n) bcmp(a, b, n)
#define memmove(a, b, n) bcopy(b, a, n)
#endif
/*
* 32-bit machine. The db routines are theoretically independent of
* the size of u_shorts and u_longs, but I don't know that anyone has
* ever actually tried it. At a minimum, change the following #define's
* if you are trying to compile on a different type of system.
*/
#ifndef USHRT_MAX
#define USHRT_MAX 0xFFFF
#define ULONG_MAX 0xFFFFFFFF
#endif
#ifndef O_ACCMODE /* POSIX 1003.1 access mode mask. */
#define O_ACCMODE (O_RDONLY|O_WRONLY|O_RDWR)
#endif
#ifndef _POSIX2_RE_DUP_MAX /* POSIX 1003.2 RE limit. */
#define _POSIX2_RE_DUP_MAX 255
#endif
/*
* If you can't provide lock values in the open(2) call. Note, this
* allows races to happen.
*/
#ifndef O_EXLOCK /* 4.4BSD extension. */
#define O_EXLOCK 0
#endif
#ifndef O_SHLOCK /* 4.4BSD extension. */
#define O_SHLOCK 0
#endif
#ifndef EFTYPE
#define EFTYPE EINVAL /* POSIX 1003.1 format errno. */
#endif
#ifndef WCOREDUMP /* 4.4BSD extension */
#define WCOREDUMP(a) 0
#endif
#ifndef STDERR_FILENO
#define STDIN_FILENO 0 /* ANSI C #defines */
#define STDOUT_FILENO 1
#define STDERR_FILENO 2
#endif
#ifndef SEEK_END
#define SEEK_SET 0 /* POSIX 1003.1 seek values */
#define SEEK_CUR 1
#define SEEK_END 2
#endif
#ifndef _POSIX_VDISABLE /* POSIX 1003.1 disabling char. */
#define _POSIX_VDISABLE 0 /* Some systems used 0. */
#endif
#ifndef TCSASOFT /* 4.4BSD extension. */
#define TCSASOFT 0
#endif
#ifndef _POSIX2_RE_DUP_MAX /* POSIX 1003.2 values. */
#define _POSIX2_RE_DUP_MAX 255
#endif
#ifndef NULL /* ANSI C #defines NULL everywhere. */
#define NULL 0
#endif
#ifndef MAX /* Usually found in <sys/param.h>. */
#define MAX(_a,_b) ((_a)<(_b)?(_b):(_a))
#endif
#ifndef MIN /* Usually found in <sys/param.h>. */
#define MIN(_a,_b) ((_a)<(_b)?(_a):(_b))
#endif
/* Default file permissions. */
#ifndef DEFFILEMODE /* 4.4BSD extension. */
#define DEFFILEMODE (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)
#endif
#ifndef __sun
#ifndef S_ISDIR /* POSIX 1003.1 file type tests. */
#define S_ISDIR(m) ((m & 0170000) == 0040000) /* directory */
#define S_ISCHR(m) ((m & 0170000) == 0020000) /* char special */
#define S_ISBLK(m) ((m & 0170000) == 0060000) /* block special */
#define S_ISREG(m) ((m & 0170000) == 0100000) /* regular file */
#define S_ISFIFO(m) ((m & 0170000) == 0010000) /* fifo */
#endif
#ifndef S_ISLNK /* BSD POSIX 1003.1 extensions */
#define S_ISLNK(m) ((m & 0170000) == 0120000) /* symbolic link */
#define S_ISSOCK(m) ((m & 0170000) == 0140000) /* socket */
#endif
#endif /* __sun */
/* The type of a va_list. */
#ifndef _BSD_VA_LIST_ /* 4.4BSD #define. */
#define _BSD_VA_LIST_ char *
#endif
#endif /* !_COMPAT_H_ */

View File

@@ -1,77 +0,0 @@
/*-
* Copyright (c) 1990, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Margo Seltzer.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)ndbm.h 8.1 (Berkeley) 6/2/93
*/
#ifndef _NDBM_H_
#define _NDBM_H_
#include "mcom_db.h"
/* Map dbm interface onto db(3). */
#define DBM_RDONLY O_RDONLY
/* Flags to dbm_store(). */
#define DBM_INSERT 0
#define DBM_REPLACE 1
/*
* The db(3) support for ndbm(3) always appends this suffix to the
* file name to avoid overwriting the user's original database.
*/
#define DBM_SUFFIX ".db"
typedef struct {
char *dptr;
int dsize;
} datum;
typedef DB DBM;
#define dbm_pagfno(a) DBM_PAGFNO_NOT_AVAILABLE
__BEGIN_DECLS
void dbm_close (DBM *);
int dbm_delete (DBM *, datum);
datum dbm_fetch (DBM *, datum);
datum dbm_firstkey (DBM *);
long dbm_forder (DBM *, datum);
datum dbm_nextkey (DBM *);
DBM *dbm_open (const char *, int, int);
int dbm_store (DBM *, datum, datum, int);
int dbm_dirfno (DBM *);
__END_DECLS
#endif /* !_NDBM_H_ */

View File

@@ -1,41 +0,0 @@
#ifndef NSRES_H
#define NSRES_H
#include "mcom_db.h"
__BEGIN_DECLS
/* C version */
#define NSRESHANDLE void *
typedef void (*NSRESTHREADFUNC)(void *);
typedef struct NSRESTHREADINFO
{
void *lock;
NSRESTHREADFUNC fn_lock;
NSRESTHREADFUNC fn_unlock;
} NSRESTHREADINFO;
#define MAXBUFNUM 10
#define MAXSTRINGLEN 300
#define NSRES_CREATE 1
#define NSRES_OPEN 2
NSRESHANDLE NSResCreateTable(const char *filename, NSRESTHREADINFO *threadinfo);
NSRESHANDLE NSResOpenTable(const char *filename, NSRESTHREADINFO *threadinfo);
void NSResCloseTable(NSRESHANDLE handle);
char *NSResLoadString(NSRESHANDLE handle, const char * library, int32 id,
unsigned int charsetid, char *retbuf);
int32 NSResGetSize(NSRESHANDLE handle, const char *library, int32 id);
int32 NSResLoadResource(NSRESHANDLE handle, const char *library, int32 id, char *retbuf);
int NSResAddString(NSRESHANDLE handle, const char *library, int32 id, const char *string, unsigned int charset);
__END_DECLS
#endif

View File

@@ -1,96 +0,0 @@
/*-
* Copyright (c) 1990, 1993, 1994
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Margo Seltzer.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)page.h 8.2 (Berkeley) 5/31/94
*/
/*
* Definitions for hashing page file format.
*/
/*
* routines dealing with a data page
*
* page format:
* +------------------------------+
* p | n | keyoff | datoff | keyoff |
* +------------+--------+--------+
* | datoff | free | ptr | --> |
* +--------+---------------------+
* | F R E E A R E A |
* +--------------+---------------+
* | <---- - - - | data |
* +--------+-----+----+----------+
* | key | data | key |
* +--------+----------+----------+
*
* Pointer to the free space is always: p[p[0] + 2]
* Amount of free space on the page is: p[p[0] + 1]
*/
/*
* How many bytes required for this pair?
* 2 shorts in the table at the top of the page + room for the
* key and room for the data
*
* We prohibit entering a pair on a page unless there is also room to append
* an overflow page. The reason for this it that you can get in a situation
* where a single key/data pair fits on a page, but you can't append an
* overflow page and later you'd have to split the key/data and handle like
* a big pair.
* You might as well do this up front.
*/
#ifndef PAGE_H
#define PAGE_H
#define PAIRSIZE(K,D) (2*sizeof(uint16) + (K)->size + (D)->size)
#define BIGOVERHEAD (4*sizeof(uint16))
#define KEYSIZE(K) (4*sizeof(uint16) + (K)->size);
#define OVFLSIZE (2*sizeof(uint16))
#define FREESPACE(P) ((P)[(P)[0]+1])
#define OFFSET(P) ((P)[(P)[0]+2])
#define PAIRFITS(P,K,D) \
(((P)[2] >= REAL_KEY) && \
(PAIRSIZE((K),(D)) + OVFLSIZE) <= FREESPACE((P)))
#define PAGE_META(N) (((N)+3) * sizeof(uint16))
typedef struct {
BUFHEAD *newp;
BUFHEAD *oldp;
BUFHEAD *nextp;
uint16 next_addr;
} SPLIT_RETURN;
#endif

View File

@@ -1,245 +0,0 @@
/*
* Copyright (c) 1991, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)queue.h 8.3 (Berkeley) 12/13/93
*/
#ifndef _QUEUE_H_
#define _QUEUE_H_
/*
* This file defines three types of data structures: lists, tail queues,
* and circular queues.
*
* A list is headed by a single forward pointer (or an array of forward
* pointers for a hash table header). The elements are doubly linked
* so that an arbitrary element can be removed without a need to
* traverse the list. New elements can be added to the list after
* an existing element or at the head of the list. A list may only be
* traversed in the forward direction.
*
* A tail queue is headed by a pair of pointers, one to the head of the
* list and the other to the tail of the list. The elements are doubly
* linked so that an arbitrary element can be removed without a need to
* traverse the list. New elements can be added to the list after
* an existing element, at the head of the list, or at the end of the
* list. A tail queue may only be traversed in the forward direction.
*
* A circle queue is headed by a pair of pointers, one to the head of the
* list and the other to the tail of the list. The elements are doubly
* linked so that an arbitrary element can be removed without a need to
* traverse the list. New elements can be added to the list before or after
* an existing element, at the head of the list, or at the end of the list.
* A circle queue may be traversed in either direction, but has a more
* complex end of list detection.
*
* For details on the use of these macros, see the queue(3) manual page.
*/
/*
* List definitions.
*/
#define LIST_HEAD(name, type) \
struct name { \
struct type *lh_first; /* first element */ \
}
#define LIST_ENTRY(type) \
struct { \
struct type *le_next; /* next element */ \
struct type **le_prev; /* address of previous next element */ \
}
/*
* List functions.
*/
#define LIST_INIT(head) { \
(head)->lh_first = NULL; \
}
#define LIST_INSERT_AFTER(listelm, elm, field) { \
if (((elm)->field.le_next = (listelm)->field.le_next) != NULL) \
(listelm)->field.le_next->field.le_prev = \
&(elm)->field.le_next; \
(listelm)->field.le_next = (elm); \
(elm)->field.le_prev = &(listelm)->field.le_next; \
}
#define LIST_INSERT_HEAD(head, elm, field) { \
if (((elm)->field.le_next = (head)->lh_first) != NULL) \
(head)->lh_first->field.le_prev = &(elm)->field.le_next;\
(head)->lh_first = (elm); \
(elm)->field.le_prev = &(head)->lh_first; \
}
#define LIST_REMOVE(elm, field) { \
if ((elm)->field.le_next != NULL) \
(elm)->field.le_next->field.le_prev = \
(elm)->field.le_prev; \
*(elm)->field.le_prev = (elm)->field.le_next; \
}
/*
* Tail queue definitions.
*/
#define TAILQ_HEAD(name, type) \
struct name { \
struct type *tqh_first; /* first element */ \
struct type **tqh_last; /* addr of last next element */ \
}
#define TAILQ_ENTRY(type) \
struct { \
struct type *tqe_next; /* next element */ \
struct type **tqe_prev; /* address of previous next element */ \
}
/*
* Tail queue functions.
*/
#define TAILQ_INIT(head) { \
(head)->tqh_first = NULL; \
(head)->tqh_last = &(head)->tqh_first; \
}
#define TAILQ_INSERT_HEAD(head, elm, field) { \
if (((elm)->field.tqe_next = (head)->tqh_first) != NULL) \
(elm)->field.tqe_next->field.tqe_prev = \
&(elm)->field.tqe_next; \
else \
(head)->tqh_last = &(elm)->field.tqe_next; \
(head)->tqh_first = (elm); \
(elm)->field.tqe_prev = &(head)->tqh_first; \
}
#define TAILQ_INSERT_TAIL(head, elm, field) { \
(elm)->field.tqe_next = NULL; \
(elm)->field.tqe_prev = (head)->tqh_last; \
*(head)->tqh_last = (elm); \
(head)->tqh_last = &(elm)->field.tqe_next; \
}
#define TAILQ_INSERT_AFTER(head, listelm, elm, field) { \
if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != NULL)\
(elm)->field.tqe_next->field.tqe_prev = \
&(elm)->field.tqe_next; \
else \
(head)->tqh_last = &(elm)->field.tqe_next; \
(listelm)->field.tqe_next = (elm); \
(elm)->field.tqe_prev = &(listelm)->field.tqe_next; \
}
#define TAILQ_REMOVE(head, elm, field) { \
if (((elm)->field.tqe_next) != NULL) \
(elm)->field.tqe_next->field.tqe_prev = \
(elm)->field.tqe_prev; \
else \
(head)->tqh_last = (elm)->field.tqe_prev; \
*(elm)->field.tqe_prev = (elm)->field.tqe_next; \
}
/*
* Circular queue definitions.
*/
#define CIRCLEQ_HEAD(name, type) \
struct name { \
struct type *cqh_first; /* first element */ \
struct type *cqh_last; /* last element */ \
}
#define CIRCLEQ_ENTRY(type) \
struct { \
struct type *cqe_next; /* next element */ \
struct type *cqe_prev; /* previous element */ \
}
/*
* Circular queue functions.
*/
#define CIRCLEQ_INIT(head) { \
(head)->cqh_first = (void *)(head); \
(head)->cqh_last = (void *)(head); \
}
#define CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) { \
(elm)->field.cqe_next = (listelm)->field.cqe_next; \
(elm)->field.cqe_prev = (listelm); \
if ((listelm)->field.cqe_next == (void *)(head)) \
(head)->cqh_last = (elm); \
else \
(listelm)->field.cqe_next->field.cqe_prev = (elm); \
(listelm)->field.cqe_next = (elm); \
}
#define CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) { \
(elm)->field.cqe_next = (listelm); \
(elm)->field.cqe_prev = (listelm)->field.cqe_prev; \
if ((listelm)->field.cqe_prev == (void *)(head)) \
(head)->cqh_first = (elm); \
else \
(listelm)->field.cqe_prev->field.cqe_next = (elm); \
(listelm)->field.cqe_prev = (elm); \
}
#define CIRCLEQ_INSERT_HEAD(head, elm, field) { \
(elm)->field.cqe_next = (head)->cqh_first; \
(elm)->field.cqe_prev = (void *)(head); \
if ((head)->cqh_last == (void *)(head)) \
(head)->cqh_last = (elm); \
else \
(head)->cqh_first->field.cqe_prev = (elm); \
(head)->cqh_first = (elm); \
}
#define CIRCLEQ_INSERT_TAIL(head, elm, field) { \
(elm)->field.cqe_next = (void *)(head); \
(elm)->field.cqe_prev = (head)->cqh_last; \
if ((head)->cqh_first == (void *)(head)) \
(head)->cqh_first = (elm); \
else \
(head)->cqh_last->field.cqe_next = (elm); \
(head)->cqh_last = (elm); \
}
#define CIRCLEQ_REMOVE(head, elm, field) { \
if ((elm)->field.cqe_next == (void *)(head)) \
(head)->cqh_last = (elm)->field.cqe_prev; \
else \
(elm)->field.cqe_next->field.cqe_prev = \
(elm)->field.cqe_prev; \
if ((elm)->field.cqe_prev == (void *)(head)) \
(head)->cqh_first = (elm)->field.cqe_next; \
else \
(elm)->field.cqe_prev->field.cqe_next = \
(elm)->field.cqe_next; \
}
#endif /* !_QUEUE_H_ */

View File

@@ -1,51 +0,0 @@
/*-
* Copyright (c) 1990, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Margo Seltzer.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)search.h 8.1 (Berkeley) 6/4/93
*/
/* Backward compatibility to hsearch interface. */
typedef struct entry {
char *key;
char *data;
} ENTRY;
typedef enum {
FIND, ENTER
} ACTION;
int hcreate (unsigned int);
void hdestroy (void);
ENTRY *hsearch (ENTRY, ACTION);

View File

@@ -1,26 +0,0 @@
#if defined(__WATCOMC__) || defined(__WATCOM_CPLUSPLUS__)
#ifndef __WATCOM_FIX_H__
#define __WATCOM_FIX_H__ 1
/*
* WATCOM's C compiler doesn't default to "__cdecl" conventions for external
* symbols and functions. Rather than adding an explicit __cdecl modifier to
* every external symbol and function declaration and definition, we use the
* following pragma to (attempt to) change WATCOM c's default to __cdecl.
* These pragmas were taken from pages 180-181, 266 & 269 of the
* Watcom C/C++ version 11 User's Guide, 3rd edition.
*/
#if defined(XP_WIN16) || defined(WIN16)
#pragma aux default "_*" \
parm caller [] \
value struct float struct routine [ax] \
modify [ax bx cx dx es]
#else
#pragma aux default "_*" \
parm caller [] \
value struct float struct routine [eax] \
modify [eax ecx edx]
#endif
#pragma aux default far
#endif /* once */
#endif /* WATCOM compiler */

View File

@@ -1,112 +0,0 @@
/* ---------------------------------------------------------------------------
Stuff to fake unix file I/O on windows boxes
------------------------------------------------------------------------*/
#ifndef WINFILE_H
#define WINFILE_H
#ifdef _WINDOWS
/* hacked out of <dirent.h> on an SGI */
#if defined(XP_WIN32) || defined(_WIN32)
/* 32-bit stuff here */
#include <windows.h>
#include <stdlib.h>
#ifdef __MINGW32__
#include <sys/types.h>
#include <sys/stat.h>
#else
#include <sys\types.h>
#include <sys\stat.h>
#endif
typedef struct DIR_Struct {
void * directoryPtr;
WIN32_FIND_DATA data;
} DIR;
#define _ST_FSTYPSZ 16
#if !defined(__BORLANDC__) && !defined(__GNUC__)
typedef unsigned long mode_t;
typedef long uid_t;
typedef long gid_t;
#ifdef WINCE
typedef long ino_t;
#else
typedef long off_t;
#endif
typedef unsigned long nlink_t;
#endif
typedef struct timestruc {
time_t tv_sec; /* seconds */
long tv_nsec; /* and nanoseconds */
} timestruc_t;
struct dirent { /* data from readdir() */
ino_t d_ino; /* inode number of entry */
off_t d_off; /* offset of disk direntory entry */
unsigned short d_reclen; /* length of this record */
char d_name[_MAX_FNAME]; /* name of file */
};
#if !defined(__BORLANDC__) && !defined (__GNUC__)
#define S_ISDIR(s) ((s) & _S_IFDIR)
#endif
#else /* _WIN32 */
/* 16-bit windows stuff */
#include <sys\types.h>
#include <sys\stat.h>
#include <dos.h>
/* Getting cocky to support multiple file systems */
typedef struct dirStruct_tag {
struct _find_t file_data;
char c_checkdrive;
} dirStruct;
typedef struct DIR_Struct {
void * directoryPtr;
dirStruct data;
} DIR;
#define _ST_FSTYPSZ 16
typedef unsigned long mode_t;
typedef long uid_t;
typedef long gid_t;
typedef long off_t;
typedef unsigned long nlink_t;
typedef struct timestruc {
time_t tv_sec; /* seconds */
long tv_nsec; /* and nanoseconds */
} timestruc_t;
struct dirent { /* data from readdir() */
ino_t d_ino; /* inode number of entry */
off_t d_off; /* offset of disk direntory entry */
unsigned short d_reclen; /* length of this record */
#ifdef XP_WIN32
char d_name[_MAX_FNAME]; /* name of file */
#else
char d_name[20]; /* name of file */
#endif
};
#define S_ISDIR(s) ((s) & _S_IFDIR)
#endif /* 16-bit windows */
#define CONST const
#endif /* _WINDOWS */
#endif /* WINFILE_H */

View File

@@ -1,79 +0,0 @@
#
# The contents of this file are subject to the Netscape Public
# License Version 1.1 (the "License"); you may not use this file
# except in compliance with the License. You may obtain a copy of
# the License at http://www.mozilla.org/NPL/
#
# Software distributed under the License is distributed on an "AS
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
# implied. See the License for the specific language governing
# rights and limitations under the License.
#
# The Original Code is mozilla.org code.
#
# The Initial Developer of the Original Code is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s):
#
DEPTH = ../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
LIBRARY_NAME = mozdbm_s
LIB_IS_C_ONLY = 1
ifeq ($(OS_ARCH),WINNT)
LIBRARY_NAME = dbm$(MOZ_BITS)
endif
CSRCS = \
db.c \
h_bigkey.c \
h_func.c \
h_log2.c \
h_page.c \
hash.c \
hash_buf.c \
hsearch.c \
mktemp.c \
ndbm.c \
strerror.c \
nsres.c \
$(NULL)
ifeq ($(OS_ARCH),WINNT)
CSRCS += memmove.c snprintf.c
else
ifeq (,$(filter -DHAVE_MEMMOVE=1,$(ACDEFINES)))
CSRCS += memmove.c
endif
ifeq (,$(filter -DHAVE_SNPRINTF=1,$(ACDEFINES)))
CSRCS += snprintf.c
endif
endif # WINNT
LOCAL_INCLUDES = -I$(srcdir)/../include
FORCE_STATIC_LIB = 1
FORCE_USE_PIC = 1
include $(topsrcdir)/config/rules.mk
DEFINES += -DMEMMOVE -D__DBINTERFACE_PRIVATE $(SECURITY_FLAG)
ifeq ($(OS_ARCH),WINCE)
DEFINES += -D__STDC__ -DDBM_REOPEN_ON_FLUSH
endif
ifeq ($(OS_ARCH),AIX)
OS_LIBS += -lc_r
endif

View File

@@ -1,96 +0,0 @@
# The contents of this file are subject to the Netscape Public
# License Version 1.1 (the "License"); you may not use this file
# except in compliance with the License. You may obtain a copy of
# the License at http://www.mozilla.org/NPL/
#
# Software distributed under the License is distributed on an "AS
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
# implied. See the License for the specific language governing
# rights and limitations under the License.
#
# The Original Code is mozilla.org code.
#
# The Initial Developer of the Original Code is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s):
#//------------------------------------------------------------------------
#//
#// Makefile to build the cert library
#//
#//------------------------------------------------------------------------
!if "$(MOZ_BITS)" == "16"
!ifndef MOZ_DEBUG
OPTIMIZER=-Os -UDEBUG -DNDEBUG
!endif
!endif
#//------------------------------------------------------------------------
#//
#// Specify the depth of the current directory relative to the
#// root of NS
#//
#//------------------------------------------------------------------------
DEPTH= ..\..
!ifndef MAKE_OBJ_TYPE
MAKE_OBJ_TYPE=EXE
!endif
#//------------------------------------------------------------------------
#//
#// Define any Public Make Variables here: (ie. PDFFILE, MAPFILE, ...)
#//
#//------------------------------------------------------------------------
LIBNAME=dbm$(MOZ_BITS)
PDBFILE=$(LIBNAME).pdb
#//------------------------------------------------------------------------
#//
#// Define the files necessary to build the target (ie. OBJS)
#//
#//------------------------------------------------------------------------
OBJS= \
.\$(OBJDIR)\db.obj \
.\$(OBJDIR)\h_bigkey.obj \
.\$(OBJDIR)\h_func.obj \
.\$(OBJDIR)\h_log2.obj \
.\$(OBJDIR)\h_page.obj \
.\$(OBJDIR)\hash.obj \
.\$(OBJDIR)\hash_buf.obj \
.\$(OBJDIR)\hsearch.obj \
.\$(OBJDIR)\memmove.obj \
.\$(OBJDIR)\mktemp.obj \
.\$(OBJDIR)\ndbm.obj \
.\$(OBJDIR)\snprintf.obj \
.\$(OBJDIR)\strerror.obj \
.\$(OBJDIR)\nsres.obj \
$(NULL)
#//------------------------------------------------------------------------
#//
#// Define any Public Targets here (ie. PROGRAM, LIBRARY, DLL, ...)
#// (these must be defined before the common makefiles are included)
#//
#//------------------------------------------------------------------------
LIBRARY = .\$(OBJDIR)\$(LIBNAME).lib
LINCS = -I..\include
#//------------------------------------------------------------------------
#//
#// Include the common makefile rules
#//
#//------------------------------------------------------------------------
include <$(DEPTH)/config/rules.mak>
CFLAGS = $(CFLAGS) -DMOZILLA_CLIENT -D__DBINTERFACE_PRIVATE
install:: $(LIBRARY)
$(MAKE_INSTALL) $(LIBRARY) $(DIST)\lib

View File

@@ -1,144 +0,0 @@
/*-
* Copyright (c) 1991, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#if defined(LIBC_SCCS) && !defined(lint)
static char sccsid[] = "@(#)db.c 8.4 (Berkeley) 2/21/94";
#endif /* LIBC_SCCS and not lint */
#include "watcomfx.h"
#ifndef __DBINTERFACE_PRIVATE
#define __DBINTERFACE_PRIVATE
#endif
#ifdef macintosh
#include <unix.h>
#else
#include <sys/types.h>
#endif
#include <errno.h>
#include <fcntl.h>
#include <stddef.h>
#include <stdio.h>
#include "mcom_db.h"
/* a global flag that locks closed all databases */
int all_databases_locked_closed = 0;
/* set or unset a global lock flag to disable the
* opening of any DBM file
*/
void
dbSetOrClearDBLock(DBLockFlagEnum type)
{
if(type == LockOutDatabase)
all_databases_locked_closed = 1;
else
all_databases_locked_closed = 0;
}
#if defined(__WATCOMC__) || defined(__WATCOM_CPLUSPLUS__)
DB *
#else
PR_IMPLEMENT(DB *)
#endif
dbopen(const char *fname, int flags,int mode, DBTYPE type, const void *openinfo)
{
/* lock out all file databases. Let in-memory databases through
*/
if(all_databases_locked_closed && fname)
{
errno = EINVAL;
return(NULL);
}
#define DB_FLAGS (DB_LOCK | DB_SHMEM | DB_TXN)
#if 0 /* most systems dont have EXLOCK and SHLOCK */
#define USE_OPEN_FLAGS \
(O_CREAT | O_EXCL | O_EXLOCK | O_NONBLOCK | O_RDONLY | \
O_RDWR | O_SHLOCK | O_TRUNC)
#else
#define USE_OPEN_FLAGS \
(O_CREAT | O_EXCL | O_RDONLY | \
O_RDWR | O_TRUNC)
#endif
if ((flags & ~(USE_OPEN_FLAGS | DB_FLAGS)) == 0)
switch (type) {
/* we don't need btree and recno right now */
#if 0
case DB_BTREE:
return (__bt_open(fname, flags & USE_OPEN_FLAGS,
mode, openinfo, flags & DB_FLAGS));
case DB_RECNO:
return (__rec_open(fname, flags & USE_OPEN_FLAGS,
mode, openinfo, flags & DB_FLAGS));
#endif
case DB_HASH:
return (__hash_open(fname, flags & USE_OPEN_FLAGS,
mode, (const HASHINFO *)openinfo, flags & DB_FLAGS));
default:
break;
}
errno = EINVAL;
return (NULL);
}
static int
__dberr()
{
return (RET_ERROR);
}
/*
* __DBPANIC -- Stop.
*
* Parameters:
* dbp: pointer to the DB structure.
*/
void
__dbpanic(DB *dbp)
{
/* The only thing that can succeed is a close. */
dbp->del = (int (*)(const struct __db *, const DBT *, uint))__dberr;
dbp->fd = (int (*)(const struct __db *))__dberr;
dbp->get = (int (*)(const struct __db *, const DBT *, DBT *, uint))__dberr;
dbp->put = (int (*)(const struct __db *, DBT *, const DBT *, uint))__dberr;
dbp->seq = (int (*)(const struct __db *, DBT *, DBT *, uint))__dberr;
dbp->sync = (int (*)(const struct __db *, uint))__dberr;
}

View File

@@ -1,713 +0,0 @@
/*-
* Copyright (c) 1990, 1993, 1994
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Margo Seltzer.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#if defined(LIBC_SCCS) && !defined(lint)
static char sccsid[] = "@(#)hash_bigkey.c 8.3 (Berkeley) 5/31/94";
#endif /* LIBC_SCCS and not lint */
#include "watcomfx.h"
/*
* PACKAGE: hash
* DESCRIPTION:
* Big key/data handling for the hashing package.
*
* ROUTINES:
* External
* __big_keydata
* __big_split
* __big_insert
* __big_return
* __big_delete
* __find_last_page
* Internal
* collect_key
* collect_data
*/
#if !defined(_WIN32) && !defined(_WINDOWS) && !defined(macintosh) && !defined(XP_OS2_VACPP)
#include <sys/param.h>
#endif
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef DEBUG
#include <assert.h>
#endif
#include "mcom_db.h"
#include "hash.h"
#include "page.h"
/* #include "extern.h" */
static int collect_key __P((HTAB *, BUFHEAD *, int, DBT *, int));
static int collect_data __P((HTAB *, BUFHEAD *, int, int));
/*
* Big_insert
*
* You need to do an insert and the key/data pair is too big
*
* Returns:
* 0 ==> OK
*-1 ==> ERROR
*/
extern int
__big_insert(HTAB *hashp, BUFHEAD *bufp, const DBT *key, const DBT *val)
{
register uint16 *p;
uint key_size, n, val_size;
uint16 space, move_bytes, off;
char *cp, *key_data, *val_data;
cp = bufp->page; /* Character pointer of p. */
p = (uint16 *)cp;
key_data = (char *)key->data;
key_size = key->size;
val_data = (char *)val->data;
val_size = val->size;
/* First move the Key */
for (space = FREESPACE(p) - BIGOVERHEAD; key_size;
space = FREESPACE(p) - BIGOVERHEAD) {
move_bytes = PR_MIN(space, key_size);
off = OFFSET(p) - move_bytes;
memmove(cp + off, key_data, move_bytes);
key_size -= move_bytes;
key_data += move_bytes;
n = p[0];
p[++n] = off;
p[0] = ++n;
FREESPACE(p) = off - PAGE_META(n);
OFFSET(p) = off;
p[n] = PARTIAL_KEY;
bufp = __add_ovflpage(hashp, bufp);
if (!bufp)
return (-1);
n = p[0];
if (!key_size) {
if (FREESPACE(p)) {
move_bytes = PR_MIN(FREESPACE(p), val_size);
off = OFFSET(p) - move_bytes;
p[n] = off;
memmove(cp + off, val_data, move_bytes);
val_data += move_bytes;
val_size -= move_bytes;
p[n - 2] = FULL_KEY_DATA;
FREESPACE(p) = FREESPACE(p) - move_bytes;
OFFSET(p) = off;
} else
p[n - 2] = FULL_KEY;
}
p = (uint16 *)bufp->page;
cp = bufp->page;
bufp->flags |= BUF_MOD;
}
/* Now move the data */
for (space = FREESPACE(p) - BIGOVERHEAD; val_size;
space = FREESPACE(p) - BIGOVERHEAD) {
move_bytes = PR_MIN(space, val_size);
/*
* Here's the hack to make sure that if the data ends on the
* same page as the key ends, FREESPACE is at least one.
*/
if (space == val_size && val_size == val->size)
move_bytes--;
off = OFFSET(p) - move_bytes;
memmove(cp + off, val_data, move_bytes);
val_size -= move_bytes;
val_data += move_bytes;
n = p[0];
p[++n] = off;
p[0] = ++n;
FREESPACE(p) = off - PAGE_META(n);
OFFSET(p) = off;
if (val_size) {
p[n] = FULL_KEY;
bufp = __add_ovflpage(hashp, bufp);
if (!bufp)
return (-1);
cp = bufp->page;
p = (uint16 *)cp;
} else
p[n] = FULL_KEY_DATA;
bufp->flags |= BUF_MOD;
}
return (0);
}
/*
* Called when bufp's page contains a partial key (index should be 1)
*
* All pages in the big key/data pair except bufp are freed. We cannot
* free bufp because the page pointing to it is lost and we can't get rid
* of its pointer.
*
* Returns:
* 0 => OK
*-1 => ERROR
*/
extern int
__big_delete(HTAB *hashp, BUFHEAD *bufp)
{
register BUFHEAD *last_bfp, *rbufp;
uint16 *bp, pageno;
int key_done, n;
rbufp = bufp;
last_bfp = NULL;
bp = (uint16 *)bufp->page;
pageno = 0;
key_done = 0;
while (!key_done || (bp[2] != FULL_KEY_DATA)) {
if (bp[2] == FULL_KEY || bp[2] == FULL_KEY_DATA)
key_done = 1;
/*
* If there is freespace left on a FULL_KEY_DATA page, then
* the data is short and fits entirely on this page, and this
* is the last page.
*/
if (bp[2] == FULL_KEY_DATA && FREESPACE(bp))
break;
pageno = bp[bp[0] - 1];
rbufp->flags |= BUF_MOD;
rbufp = __get_buf(hashp, pageno, rbufp, 0);
if (last_bfp)
__free_ovflpage(hashp, last_bfp);
last_bfp = rbufp;
if (!rbufp)
return (-1); /* Error. */
bp = (uint16 *)rbufp->page;
}
/*
* If we get here then rbufp points to the last page of the big
* key/data pair. Bufp points to the first one -- it should now be
* empty pointing to the next page after this pair. Can't free it
* because we don't have the page pointing to it.
*/
/* This is information from the last page of the pair. */
n = bp[0];
pageno = bp[n - 1];
/* Now, bp is the first page of the pair. */
bp = (uint16 *)bufp->page;
if (n > 2) {
/* There is an overflow page. */
bp[1] = pageno;
bp[2] = OVFLPAGE;
bufp->ovfl = rbufp->ovfl;
} else
/* This is the last page. */
bufp->ovfl = NULL;
n -= 2;
bp[0] = n;
FREESPACE(bp) = hashp->BSIZE - PAGE_META(n);
OFFSET(bp) = hashp->BSIZE - 1;
bufp->flags |= BUF_MOD;
if (rbufp)
__free_ovflpage(hashp, rbufp);
if (last_bfp != rbufp)
__free_ovflpage(hashp, last_bfp);
hashp->NKEYS--;
return (0);
}
/*
* Returns:
* 0 = key not found
* -1 = get next overflow page
* -2 means key not found and this is big key/data
* -3 error
*/
extern int
__find_bigpair(HTAB *hashp, BUFHEAD *bufp, int ndx, char *key, int size)
{
register uint16 *bp;
register char *p;
int ksize;
uint16 bytes;
char *kkey;
bp = (uint16 *)bufp->page;
p = bufp->page;
ksize = size;
kkey = key;
for (bytes = hashp->BSIZE - bp[ndx];
bytes <= size && bp[ndx + 1] == PARTIAL_KEY;
bytes = hashp->BSIZE - bp[ndx]) {
if (memcmp(p + bp[ndx], kkey, bytes))
return (-2);
kkey += bytes;
ksize -= bytes;
bufp = __get_buf(hashp, bp[ndx + 2], bufp, 0);
if (!bufp)
return (-3);
p = bufp->page;
bp = (uint16 *)p;
ndx = 1;
}
if (bytes != ksize || memcmp(p + bp[ndx], kkey, bytes)) {
#ifdef HASH_STATISTICS
++hash_collisions;
#endif
return (-2);
} else
return (ndx);
}
/*
* Given the buffer pointer of the first overflow page of a big pair,
* find the end of the big pair
*
* This will set bpp to the buffer header of the last page of the big pair.
* It will return the pageno of the overflow page following the last page
* of the pair; 0 if there isn't any (i.e. big pair is the last key in the
* bucket)
*/
extern uint16
__find_last_page(HTAB *hashp, BUFHEAD **bpp)
{
BUFHEAD *bufp;
uint16 *bp, pageno;
uint n;
bufp = *bpp;
bp = (uint16 *)bufp->page;
for (;;) {
n = bp[0];
/*
* This is the last page if: the tag is FULL_KEY_DATA and
* either only 2 entries OVFLPAGE marker is explicit there
* is freespace on the page.
*/
if (bp[2] == FULL_KEY_DATA &&
((n == 2) || (bp[n] == OVFLPAGE) || (FREESPACE(bp))))
break;
/* LJM bound the size of n to reasonable limits
*/
if(n > hashp->BSIZE/sizeof(uint16))
return(0);
pageno = bp[n - 1];
bufp = __get_buf(hashp, pageno, bufp, 0);
if (!bufp)
return (0); /* Need to indicate an error! */
bp = (uint16 *)bufp->page;
}
*bpp = bufp;
if (bp[0] > 2)
return (bp[3]);
else
return (0);
}
/*
* Return the data for the key/data pair that begins on this page at this
* index (index should always be 1).
*/
extern int
__big_return(
HTAB *hashp,
BUFHEAD *bufp,
int ndx,
DBT *val,
int set_current)
{
BUFHEAD *save_p;
uint16 *bp, len, off, save_addr;
char *tp;
int save_flags;
bp = (uint16 *)bufp->page;
while (bp[ndx + 1] == PARTIAL_KEY) {
bufp = __get_buf(hashp, bp[bp[0] - 1], bufp, 0);
if (!bufp)
return (-1);
bp = (uint16 *)bufp->page;
ndx = 1;
}
if (bp[ndx + 1] == FULL_KEY) {
bufp = __get_buf(hashp, bp[bp[0] - 1], bufp, 0);
if (!bufp)
return (-1);
bp = (uint16 *)bufp->page;
save_p = bufp;
save_addr = save_p->addr;
off = bp[1];
len = 0;
} else
if (!FREESPACE(bp)) {
/*
* This is a hack. We can't distinguish between
* FULL_KEY_DATA that contains complete data or
* incomplete data, so we require that if the data
* is complete, there is at least 1 byte of free
* space left.
*/
off = bp[bp[0]];
len = bp[1] - off;
save_p = bufp;
save_addr = bufp->addr;
bufp = __get_buf(hashp, bp[bp[0] - 1], bufp, 0);
if (!bufp)
return (-1);
bp = (uint16 *)bufp->page;
} else {
/* The data is all on one page. */
tp = (char *)bp;
off = bp[bp[0]];
val->data = (uint8 *)tp + off;
val->size = bp[1] - off;
if (set_current) {
if (bp[0] == 2) { /* No more buckets in
* chain */
hashp->cpage = NULL;
hashp->cbucket++;
hashp->cndx = 1;
} else {
hashp->cpage = __get_buf(hashp,
bp[bp[0] - 1], bufp, 0);
if (!hashp->cpage)
return (-1);
hashp->cndx = 1;
if (!((uint16 *)
hashp->cpage->page)[0]) {
hashp->cbucket++;
hashp->cpage = NULL;
}
}
}
return (0);
}
/* pin our saved buf so that we don't lose if
* we run out of buffers */
save_flags = save_p->flags;
save_p->flags |= BUF_PIN;
val->size = collect_data(hashp, bufp, (int)len, set_current);
save_p->flags = save_flags;
if (val->size == (size_t)-1)
return (-1);
if (save_p->addr != save_addr) {
/* We are pretty short on buffers. */
errno = EINVAL; /* OUT OF BUFFERS */
return (-1);
}
memmove(hashp->tmp_buf, (save_p->page) + off, len);
val->data = (uint8 *)hashp->tmp_buf;
return (0);
}
/*
* Count how big the total datasize is by looping through the pages. Then
* allocate a buffer and copy the data in the second loop. NOTE: Our caller
* may already have a bp which it is holding onto. The caller is
* responsible for copying that bp into our temp buffer. 'len' is how much
* space to reserve for that buffer.
*/
static int
collect_data(
HTAB *hashp,
BUFHEAD *bufp,
int len, int set)
{
register uint16 *bp;
BUFHEAD *save_bufp;
int save_flags;
int mylen, totlen;
/*
* save the input buf head because we need to walk the list twice.
* pin it to make sure it doesn't leave the buffer pool.
* This has the effect of growing the buffer pool if necessary.
*/
save_bufp = bufp;
save_flags = save_bufp->flags;
save_bufp->flags |= BUF_PIN;
/* read the length of the buffer */
for (totlen = len; bufp ; bufp = __get_buf(hashp, bp[bp[0]-1], bufp, 0)) {
bp = (uint16 *)bufp->page;
mylen = hashp->BSIZE - bp[1];
/* if mylen ever goes negative it means that the
* page is screwed up.
*/
if (mylen < 0) {
save_bufp->flags = save_flags;
return (-1);
}
totlen += mylen;
if (bp[2] == FULL_KEY_DATA) { /* End of Data */
break;
}
}
if (!bufp) {
save_bufp->flags = save_flags;
return (-1);
}
/* allocate a temp buf */
if (hashp->tmp_buf)
free(hashp->tmp_buf);
if ((hashp->tmp_buf = (char *)malloc((size_t)totlen)) == NULL) {
save_bufp->flags = save_flags;
return (-1);
}
/* copy the buffers back into temp buf */
for (bufp = save_bufp; bufp ;
bufp = __get_buf(hashp, bp[bp[0]-1], bufp, 0)) {
bp = (uint16 *)bufp->page;
mylen = hashp->BSIZE - bp[1];
memmove(&hashp->tmp_buf[len], (bufp->page) + bp[1], (size_t)mylen);
len += mylen;
if (bp[2] == FULL_KEY_DATA) {
break;
}
}
/* 'clear' the pin flags */
save_bufp->flags = save_flags;
/* update the database cursor */
if (set) {
hashp->cndx = 1;
if (bp[0] == 2) { /* No more buckets in chain */
hashp->cpage = NULL;
hashp->cbucket++;
} else {
hashp->cpage = __get_buf(hashp, bp[bp[0] - 1], bufp, 0);
if (!hashp->cpage)
return (-1);
else if (!((uint16 *)hashp->cpage->page)[0]) {
hashp->cbucket++;
hashp->cpage = NULL;
}
}
}
return (totlen);
}
/*
* Fill in the key and data for this big pair.
*/
extern int
__big_keydata(
HTAB *hashp,
BUFHEAD *bufp,
DBT *key, DBT *val,
int set)
{
key->size = collect_key(hashp, bufp, 0, val, set);
if (key->size == (size_t)-1)
return (-1);
key->data = (uint8 *)hashp->tmp_key;
return (0);
}
/*
* Count how big the total key size is by recursing through the pages. Then
* collect the data, allocate a buffer and copy the key as you recurse up.
*/
static int
collect_key(
HTAB *hashp,
BUFHEAD *bufp,
int len,
DBT *val,
int set)
{
BUFHEAD *xbp;
char *p;
int mylen, totlen;
uint16 *bp, save_addr;
p = bufp->page;
bp = (uint16 *)p;
mylen = hashp->BSIZE - bp[1];
save_addr = bufp->addr;
totlen = len + mylen;
if (bp[2] == FULL_KEY || bp[2] == FULL_KEY_DATA) { /* End of Key. */
if (hashp->tmp_key != NULL)
free(hashp->tmp_key);
if ((hashp->tmp_key = (char *)malloc((size_t)totlen)) == NULL)
return (-1);
if (__big_return(hashp, bufp, 1, val, set))
return (-1);
} else {
xbp = __get_buf(hashp, bp[bp[0] - 1], bufp, 0);
if (!xbp || ((totlen =
collect_key(hashp, xbp, totlen, val, set)) < 1))
return (-1);
}
if (bufp->addr != save_addr) {
errno = EINVAL; /* MIS -- OUT OF BUFFERS */
return (-1);
}
memmove(&hashp->tmp_key[len], (bufp->page) + bp[1], (size_t)mylen);
return (totlen);
}
/*
* Returns:
* 0 => OK
* -1 => error
*/
extern int
__big_split(
HTAB *hashp,
BUFHEAD *op, /* Pointer to where to put keys that go in old bucket */
BUFHEAD *np, /* Pointer to new bucket page */
/* Pointer to first page containing the big key/data */
BUFHEAD *big_keyp,
uint32 addr, /* Address of big_keyp */
uint32 obucket,/* Old Bucket */
SPLIT_RETURN *ret)
{
register BUFHEAD *tmpp;
register uint16 *tp;
BUFHEAD *bp;
DBT key, val;
uint32 change;
uint16 free_space, n, off;
bp = big_keyp;
/* Now figure out where the big key/data goes */
if (__big_keydata(hashp, big_keyp, &key, &val, 0))
return (-1);
change = (__call_hash(hashp,(char*) key.data, key.size) != obucket);
if ((ret->next_addr = __find_last_page(hashp, &big_keyp))) {
if (!(ret->nextp =
__get_buf(hashp, ret->next_addr, big_keyp, 0)))
return (-1);;
} else
ret->nextp = NULL;
/* Now make one of np/op point to the big key/data pair */
#ifdef DEBUG
assert(np->ovfl == NULL);
#endif
if (change)
tmpp = np;
else
tmpp = op;
tmpp->flags |= BUF_MOD;
#ifdef DEBUG1
(void)fprintf(stderr,
"BIG_SPLIT: %d->ovfl was %d is now %d\n", tmpp->addr,
(tmpp->ovfl ? tmpp->ovfl->addr : 0), (bp ? bp->addr : 0));
#endif
tmpp->ovfl = bp; /* one of op/np point to big_keyp */
tp = (uint16 *)tmpp->page;
#if 0 /* this get's tripped on database corrupted error */
assert(FREESPACE(tp) >= OVFLSIZE);
#endif
if(FREESPACE(tp) < OVFLSIZE)
return(DATABASE_CORRUPTED_ERROR);
n = tp[0];
off = OFFSET(tp);
free_space = FREESPACE(tp);
tp[++n] = (uint16)addr;
tp[++n] = OVFLPAGE;
tp[0] = n;
OFFSET(tp) = off;
FREESPACE(tp) = free_space - OVFLSIZE;
/*
* Finally, set the new and old return values. BIG_KEYP contains a
* pointer to the last page of the big key_data pair. Make sure that
* big_keyp has no following page (2 elements) or create an empty
* following page.
*/
ret->newp = np;
ret->oldp = op;
tp = (uint16 *)big_keyp->page;
big_keyp->flags |= BUF_MOD;
if (tp[0] > 2) {
/*
* There may be either one or two offsets on this page. If
* there is one, then the overflow page is linked on normally
* and tp[4] is OVFLPAGE. If there are two, tp[4] contains
* the second offset and needs to get stuffed in after the
* next overflow page is added.
*/
n = tp[4];
free_space = FREESPACE(tp);
off = OFFSET(tp);
tp[0] -= 2;
FREESPACE(tp) = free_space + OVFLSIZE;
OFFSET(tp) = off;
tmpp = __add_ovflpage(hashp, big_keyp);
if (!tmpp)
return (-1);
tp[4] = n;
} else
tmpp = big_keyp;
if (change)
ret->newp = tmpp;
else
ret->oldp = tmpp;
return (0);
}

View File

@@ -1,211 +0,0 @@
/*-
* Copyright (c) 1990, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Margo Seltzer.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#if defined(LIBC_SCCS) && !defined(lint)
static char sccsid[] = "@(#)hash_func.c 8.2 (Berkeley) 2/21/94";
#endif /* LIBC_SCCS and not lint */
#include "watcomfx.h"
#ifndef macintosh
#include <sys/types.h>
#endif
#include "mcom_db.h"
#include "hash.h"
#include "page.h"
/* #include "extern.h" */
#if 0
static uint32 hash1 __P((const void *, size_t));
static uint32 hash2 __P((const void *, size_t));
static uint32 hash3 __P((const void *, size_t));
#endif
static uint32 hash4 __P((const void *, size_t));
/* Global default hash function */
uint32 (*__default_hash) __P((const void *, size_t)) = hash4;
/*
* HASH FUNCTIONS
*
* Assume that we've already split the bucket to which this key hashes,
* calculate that bucket, and check that in fact we did already split it.
*
* This came from ejb's hsearch.
*/
#define PRIME1 37
#define PRIME2 1048583
#if 0
static uint32
hash1(const void *keyarg, register size_t len)
{
register const uint8 *key;
register uint32 h;
/* Convert string to integer */
for (key = (const uint8 *)keyarg, h = 0; len--;)
h = h * PRIME1 ^ (*key++ - ' ');
h %= PRIME2;
return (h);
}
/*
* Phong's linear congruential hash
*/
#define dcharhash(h, c) ((h) = 0x63c63cd9*(h) + 0x9c39c33d + (c))
static uint32
hash2(const void *keyarg, size_t len)
{
register const uint8 *e, *key;
register uint32 h;
register uint8 c;
key = (const uint8 *)keyarg;
e = key + len;
for (h = 0; key != e;) {
c = *key++;
if (!c && key > e)
break;
dcharhash(h, c);
}
return (h);
}
/*
* This is INCREDIBLY ugly, but fast. We break the string up into 8 byte
* units. On the first time through the loop we get the "leftover bytes"
* (strlen % 8). On every other iteration, we perform 8 HASHC's so we handle
* all 8 bytes. Essentially, this saves us 7 cmp & branch instructions. If
* this routine is heavily used enough, it's worth the ugly coding.
*
* OZ's original sdbm hash
*/
static uint32
hash3(const void *keyarg, register size_t len)
{
register const uint8 *key;
register size_t loop;
register uint32 h;
#define HASHC h = *key++ + 65599 * h
h = 0;
key = (const uint8 *)keyarg;
if (len > 0) {
loop = (len + 8 - 1) >> 3;
switch (len & (8 - 1)) {
case 0:
do {
HASHC;
/* FALLTHROUGH */
case 7:
HASHC;
/* FALLTHROUGH */
case 6:
HASHC;
/* FALLTHROUGH */
case 5:
HASHC;
/* FALLTHROUGH */
case 4:
HASHC;
/* FALLTHROUGH */
case 3:
HASHC;
/* FALLTHROUGH */
case 2:
HASHC;
/* FALLTHROUGH */
case 1:
HASHC;
} while (--loop);
}
}
return (h);
}
#endif /* 0 */
/* Hash function from Chris Torek. */
static uint32
hash4(const void *keyarg, register size_t len)
{
register const uint8 *key;
register size_t loop;
register uint32 h;
#define HASH4a h = (h << 5) - h + *key++;
#define HASH4b h = (h << 5) + h + *key++;
#define HASH4 HASH4b
h = 0;
key = (const uint8 *)keyarg;
if (len > 0) {
loop = (len + 8 - 1) >> 3;
switch (len & (8 - 1)) {
case 0:
do {
HASH4;
/* FALLTHROUGH */
case 7:
HASH4;
/* FALLTHROUGH */
case 6:
HASH4;
/* FALLTHROUGH */
case 5:
HASH4;
/* FALLTHROUGH */
case 4:
HASH4;
/* FALLTHROUGH */
case 3:
HASH4;
/* FALLTHROUGH */
case 2:
HASH4;
/* FALLTHROUGH */
case 1:
HASH4;
} while (--loop);
}
}
return (h);
}

View File

@@ -1,56 +0,0 @@
/*-
* Copyright (c) 1990, 1993, 1994
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Margo Seltzer.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#if defined(LIBC_SCCS) && !defined(lint)
static char sccsid[] = "@(#)hash_log2.c 8.2 (Berkeley) 5/31/94";
#endif /* LIBC_SCCS and not lint */
#include "watcomfx.h"
#include <stdio.h>
#ifndef macintosh
#include <sys/types.h>
#endif
#include "mcom_db.h"
uint32 __log2(uint32 num)
{
register uint32 i, limit;
limit = 1;
for (i = 0; limit < num; limit = limit << 1, i++) {}
return (i);
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,414 +0,0 @@
/*-
* Copyright (c) 1990, 1993, 1994
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Margo Seltzer.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#if defined(LIBC_SCCS) && !defined(lint)
static char sccsid[] = "@(#)hash_buf.c 8.5 (Berkeley) 7/15/94";
#endif /* LIBC_SCCS and not lint */
#include "watcomfx.h"
/*
* PACKAGE: hash
*
* DESCRIPTION:
* Contains buffer management
*
* ROUTINES:
* External
* __buf_init
* __get_buf
* __buf_free
* __reclaim_buf
* Internal
* newbuf
*/
#if !defined(_WIN32) && !defined(_WINDOWS) && !defined(macintosh) && !defined(XP_OS2_VACPP)
#include <sys/param.h>
#endif
#include <errno.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef DEBUG
#include <assert.h>
#endif
#include "mcom_db.h"
#include "hash.h"
#include "page.h"
/* #include "extern.h" */
static BUFHEAD *newbuf __P((HTAB *, uint32, BUFHEAD *));
/* Unlink B from its place in the lru */
#define BUF_REMOVE(B) { \
(B)->prev->next = (B)->next; \
(B)->next->prev = (B)->prev; \
}
/* Insert B after P */
#define BUF_INSERT(B, P) { \
(B)->next = (P)->next; \
(B)->prev = (P); \
(P)->next = (B); \
(B)->next->prev = (B); \
}
#define MRU hashp->bufhead.next
#define LRU hashp->bufhead.prev
#define MRU_INSERT(B) BUF_INSERT((B), &hashp->bufhead)
#define LRU_INSERT(B) BUF_INSERT((B), LRU)
/*
* We are looking for a buffer with address "addr". If prev_bp is NULL, then
* address is a bucket index. If prev_bp is not NULL, then it points to the
* page previous to an overflow page that we are trying to find.
*
* CAVEAT: The buffer header accessed via prev_bp's ovfl field may no longer
* be valid. Therefore, you must always verify that its address matches the
* address you are seeking.
*/
extern BUFHEAD *
__get_buf(HTAB *hashp, uint32 addr, BUFHEAD *prev_bp, int newpage)
/* If prev_bp set, indicates a new overflow page. */
{
register BUFHEAD *bp;
register uint32 is_disk_mask;
register int is_disk, segment_ndx = 0;
SEGMENT segp = 0;
is_disk = 0;
is_disk_mask = 0;
if (prev_bp) {
bp = prev_bp->ovfl;
if (!bp || (bp->addr != addr))
bp = NULL;
if (!newpage)
is_disk = BUF_DISK;
} else {
/* Grab buffer out of directory */
segment_ndx = addr & (hashp->SGSIZE - 1);
/* valid segment ensured by __call_hash() */
segp = hashp->dir[addr >> hashp->SSHIFT];
#ifdef DEBUG
assert(segp != NULL);
#endif
bp = PTROF(segp[segment_ndx]);
is_disk_mask = ISDISK(segp[segment_ndx]);
is_disk = is_disk_mask || !hashp->new_file;
}
if (!bp) {
bp = newbuf(hashp, addr, prev_bp);
if (!bp)
return(NULL);
if(__get_page(hashp, bp->page, addr, !prev_bp, is_disk, 0))
{
/* free bp and its page */
if(prev_bp)
{
/* if prev_bp is set then the new page that
* failed is hooked onto prev_bp as an overflow page.
* if we don't remove the pointer to the bad page
* we may try and access it later and we will die
* horribly because it will have already been
* free'd and overwritten with bogus data.
*/
prev_bp->ovfl = NULL;
}
BUF_REMOVE(bp);
free(bp->page);
free(bp);
return (NULL);
}
if (!prev_bp)
{
#if 0
/* 16 bit windows and mac can't handle the
* oring of the is disk flag.
*/
segp[segment_ndx] =
(BUFHEAD *)((ptrdiff_t)bp | is_disk_mask);
#else
/* set the is_disk thing inside the structure
*/
bp->is_disk = is_disk_mask;
segp[segment_ndx] = bp;
#endif
}
} else {
BUF_REMOVE(bp);
MRU_INSERT(bp);
}
return (bp);
}
/*
* We need a buffer for this page. Either allocate one, or evict a resident
* one (if we have as many buffers as we're allowed) and put this one in.
*
* If newbuf finds an error (returning NULL), it also sets errno.
*/
static BUFHEAD *
newbuf(HTAB *hashp, uint32 addr, BUFHEAD *prev_bp)
{
register BUFHEAD *bp; /* The buffer we're going to use */
register BUFHEAD *xbp; /* Temp pointer */
register BUFHEAD *next_xbp;
SEGMENT segp;
int segment_ndx;
uint16 oaddr, *shortp;
oaddr = 0;
bp = LRU;
/*
* If LRU buffer is pinned, the buffer pool is too small. We need to
* allocate more buffers.
*/
if (hashp->nbufs || (bp->flags & BUF_PIN)) {
/* Allocate a new one */
if ((bp = (BUFHEAD *)malloc(sizeof(BUFHEAD))) == NULL)
return (NULL);
/* this memset is supposedly unnecessary but lets add
* it anyways.
*/
memset(bp, 0xff, sizeof(BUFHEAD));
if ((bp->page = (char *)malloc((size_t)hashp->BSIZE)) == NULL) {
free(bp);
return (NULL);
}
/* this memset is supposedly unnecessary but lets add
* it anyways.
*/
memset(bp->page, 0xff, (size_t)hashp->BSIZE);
if (hashp->nbufs)
hashp->nbufs--;
} else {
/* Kick someone out */
BUF_REMOVE(bp);
/*
* If this is an overflow page with addr 0, it's already been
* flushed back in an overflow chain and initialized.
*/
if ((bp->addr != 0) || (bp->flags & BUF_BUCKET)) {
/*
* Set oaddr before __put_page so that you get it
* before bytes are swapped.
*/
shortp = (uint16 *)bp->page;
if (shortp[0])
{
if(shortp[0] > (hashp->BSIZE / sizeof(uint16)))
{
return(NULL);
}
oaddr = shortp[shortp[0] - 1];
}
if ((bp->flags & BUF_MOD) && __put_page(hashp, bp->page,
bp->addr, (int)IS_BUCKET(bp->flags), 0))
return (NULL);
/*
* Update the pointer to this page (i.e. invalidate it).
*
* If this is a new file (i.e. we created it at open
* time), make sure that we mark pages which have been
* written to disk so we retrieve them from disk later,
* rather than allocating new pages.
*/
if (IS_BUCKET(bp->flags)) {
segment_ndx = bp->addr & (hashp->SGSIZE - 1);
segp = hashp->dir[bp->addr >> hashp->SSHIFT];
#ifdef DEBUG
assert(segp != NULL);
#endif
if (hashp->new_file &&
((bp->flags & BUF_MOD) ||
ISDISK(segp[segment_ndx])))
segp[segment_ndx] = (BUFHEAD *)BUF_DISK;
else
segp[segment_ndx] = NULL;
}
/*
* Since overflow pages can only be access by means of
* their bucket, free overflow pages associated with
* this bucket.
*/
for (xbp = bp; xbp->ovfl;) {
next_xbp = xbp->ovfl;
xbp->ovfl = 0;
xbp = next_xbp;
/* leave pinned pages alone, we are still using
* them. */
if (xbp->flags & BUF_PIN) {
continue;
}
/* Check that ovfl pointer is up date. */
if (IS_BUCKET(xbp->flags) ||
(oaddr != xbp->addr))
break;
shortp = (uint16 *)xbp->page;
if (shortp[0])
{
/* LJM is the number of reported
* pages way too much?
*/
if(shortp[0] > hashp->BSIZE/sizeof(uint16))
return NULL;
/* set before __put_page */
oaddr = shortp[shortp[0] - 1];
}
if ((xbp->flags & BUF_MOD) && __put_page(hashp,
xbp->page, xbp->addr, 0, 0))
return (NULL);
xbp->addr = 0;
xbp->flags = 0;
BUF_REMOVE(xbp);
LRU_INSERT(xbp);
}
}
}
/* Now assign this buffer */
bp->addr = addr;
#ifdef DEBUG1
(void)fprintf(stderr, "NEWBUF1: %d->ovfl was %d is now %d\n",
bp->addr, (bp->ovfl ? bp->ovfl->addr : 0), 0);
#endif
bp->ovfl = NULL;
if (prev_bp) {
/*
* If prev_bp is set, this is an overflow page, hook it in to
* the buffer overflow links.
*/
#ifdef DEBUG1
(void)fprintf(stderr, "NEWBUF2: %d->ovfl was %d is now %d\n",
prev_bp->addr, (prev_bp->ovfl ? bp->ovfl->addr : 0),
(bp ? bp->addr : 0));
#endif
prev_bp->ovfl = bp;
bp->flags = 0;
} else
bp->flags = BUF_BUCKET;
MRU_INSERT(bp);
return (bp);
}
extern void __buf_init(HTAB *hashp, int32 nbytes)
{
BUFHEAD *bfp;
int npages;
bfp = &(hashp->bufhead);
npages = (nbytes + hashp->BSIZE - 1) >> hashp->BSHIFT;
npages = PR_MAX(npages, MIN_BUFFERS);
hashp->nbufs = npages;
bfp->next = bfp;
bfp->prev = bfp;
/*
* This space is calloc'd so these are already null.
*
* bfp->ovfl = NULL;
* bfp->flags = 0;
* bfp->page = NULL;
* bfp->addr = 0;
*/
}
extern int
__buf_free(HTAB *hashp, int do_free, int to_disk)
{
BUFHEAD *bp;
int status = -1;
/* Need to make sure that buffer manager has been initialized */
if (!LRU)
return (0);
for (bp = LRU; bp != &hashp->bufhead;) {
/* Check that the buffer is valid */
if (bp->addr || IS_BUCKET(bp->flags)) {
if (to_disk && (bp->flags & BUF_MOD) &&
(status = __put_page(hashp, bp->page,
bp->addr, IS_BUCKET(bp->flags), 0))) {
if (do_free) {
if (bp->page)
free(bp->page);
BUF_REMOVE(bp);
free(bp);
}
return (status);
}
}
/* Check if we are freeing stuff */
if (do_free) {
if (bp->page)
free(bp->page);
BUF_REMOVE(bp);
free(bp);
bp = LRU;
} else
bp = bp->prev;
}
return (0);
}
extern void
__reclaim_buf(HTAB *hashp, BUFHEAD *bp)
{
bp->ovfl = 0;
bp->addr = 0;
bp->flags = 0;
BUF_REMOVE(bp);
LRU_INSERT(bp);
}

View File

@@ -1,108 +0,0 @@
/*-
* Copyright (c) 1990, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Margo Seltzer.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#if defined(LIBC_SCCS) && !defined(lint)
static char sccsid[] = "@(#)hsearch.c 8.4 (Berkeley) 7/21/94";
#endif /* LIBC_SCCS and not lint */
#include "watcomfx.h"
#ifndef macintosh
#include <sys/types.h>
#endif
#include <fcntl.h>
#include <string.h>
#include "mcom_db.h"
#include "hsearch.h"
static DB *dbp = NULL;
static ENTRY retval;
extern int
hcreate(uint nel)
{
HASHINFO info;
info.nelem = nel;
info.bsize = 256;
info.ffactor = 8;
info.cachesize = 0;
info.hash = NULL;
info.lorder = 0;
dbp = (DB *)__hash_open(NULL, O_CREAT | O_RDWR, 0600, &info, 0);
return ((int)dbp);
}
extern ENTRY *
hsearch(ENTRY item, ACTION action)
{
DBT key, val;
int status;
if (!dbp)
return (NULL);
key.data = (uint8 *)item.key;
key.size = strlen(item.key) + 1;
if (action == ENTER) {
val.data = (uint8 *)item.data;
val.size = strlen(item.data) + 1;
status = (dbp->put)(dbp, &key, &val, R_NOOVERWRITE);
if (status)
return (NULL);
} else {
/* FIND */
status = (dbp->get)(dbp, &key, &val, 0);
if (status)
return (NULL);
else
item.data = (char *)val.data;
}
retval.key = item.key;
retval.data = item.data;
return (&retval);
}
extern void
hdestroy()
{
if (dbp) {
(void)(dbp->close)(dbp);
dbp = NULL;
}
}

View File

@@ -1,150 +0,0 @@
#if defined(__sun) && !defined(__SVR4)
/*-
* Copyright (c) 1990, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Chris Torek.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#if defined(LIBC_SCCS) && !defined(lint)
static char sccsid[] = "@(#)bcopy.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include "watcomfx.h"
#ifdef HAVE_SYS_CDEFS_H
#include <sys/cdefs.h>
#else
#include "cdefs.h"
#endif
#include <string.h>
/*
* sizeof(word) MUST BE A POWER OF TWO
* SO THAT wmask BELOW IS ALL ONES
*/
typedef int word; /* "word" used for optimal copy speed */
#define wsize sizeof(word)
#define wmask (wsize - 1)
/*
* Copy a block of memory, handling overlap.
* This is the routine that actually implements
* (the portable versions of) bcopy, memcpy, and memmove.
*/
#ifdef MEMCOPY
void *
memcpy(dst0, src0, length)
#else
#ifdef MEMMOVE
void *
memmove(dst0, src0, length)
#else
void
bcopy(src0, dst0, length)
#endif
#endif
void *dst0;
const void *src0;
register size_t length;
{
register char *dst = dst0;
register const char *src = src0;
register size_t t;
if (length == 0 || dst == src) /* nothing to do */
goto done;
/*
* Macros: loop-t-times; and loop-t-times, t>0
*/
#define TLOOP(s) if (t) TLOOP1(s)
#define TLOOP1(s) do { s; } while (--t)
if ((unsigned long)dst < (unsigned long)src) {
/*
* Copy forward.
*/
t = (int)src; /* only need low bits */
if ((t | (int)dst) & wmask) {
/*
* Try to align operands. This cannot be done
* unless the low bits match.
*/
if ((t ^ (int)dst) & wmask || length < wsize)
t = length;
else
t = wsize - (t & wmask);
length -= t;
TLOOP1(*dst++ = *src++);
}
/*
* Copy whole words, then mop up any trailing bytes.
*/
t = length / wsize;
TLOOP(*(word *)dst = *(word *)src; src += wsize; dst += wsize);
t = length & wmask;
TLOOP(*dst++ = *src++);
} else {
/*
* Copy backwards. Otherwise essentially the same.
* Alignment works as before, except that it takes
* (t&wmask) bytes to align, not wsize-(t&wmask).
*/
src += length;
dst += length;
t = (int)src;
if ((t | (int)dst) & wmask) {
if ((t ^ (int)dst) & wmask || length <= wsize)
t = length;
else
t &= wmask;
length -= t;
TLOOP1(*--dst = *--src);
}
t = length / wsize;
TLOOP(src -= wsize; dst -= wsize; *(word *)dst = *(word *)src);
t = length & wmask;
TLOOP(*--dst = *--src);
}
done:
#if defined(MEMCOPY) || defined(MEMMOVE)
return (dst0);
#else
return;
#endif
}
#endif /* no __sgi */
/* Some compilers don't like an empty source file. */
static int dummy = 0;

View File

@@ -1,166 +0,0 @@
/*
* Copyright (c) 1987, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#if defined(LIBC_SCCS) && !defined(lint)
static char sccsid[] = "@(#)mktemp.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include "watcomfx.h"
#ifdef macintosh
#include <unix.h>
#else
#include <sys/types.h>
#include <sys/stat.h>
#endif
#include <fcntl.h>
#include <errno.h>
#include <stdio.h>
#include <ctype.h>
#include "mcom_db.h"
#if !defined(_WINDOWS) && !defined(XP_OS2_VACPP)
#include <unistd.h>
#endif
#ifdef XP_OS2_VACPP
#include <process.h>
#endif
#ifdef _WINDOWS
#include <process.h>
#include "winfile.h"
#endif
static int _gettemp(char *path, register int *doopen, int extraFlags);
int
mkstemp(char *path)
{
#ifdef XP_OS2
FILE *temp = tmpfile();
return (temp ? fileno(temp) : -1);
#else
int fd;
return (_gettemp(path, &fd, 0) ? fd : -1);
#endif
}
int
mkstempflags(char *path, int extraFlags)
{
int fd;
return (_gettemp(path, &fd, extraFlags) ? fd : -1);
}
char *
mktemp(char *path)
{
return(_gettemp(path, (int *)NULL, 0) ? path : (char *)NULL);
}
/* NB: This routine modifies its input string, and does not always restore it.
** returns 1 on success, 0 on failure.
*/
static int
_gettemp(char *path, register int *doopen, int extraFlags)
{
#if !defined(_WINDOWS) || defined(_WIN32)
extern int errno;
#endif
register char *start, *trv;
struct stat sbuf;
unsigned int pid;
pid = getpid();
for (trv = path; *trv; ++trv); /* extra X's get set to 0's */
while (*--trv == 'X') {
*trv = (pid % 10) + '0';
pid /= 10;
}
/*
* check the target directory; if you have six X's and it
* doesn't exist this runs for a *very* long time.
*/
for (start = trv + 1;; --trv) {
char saved;
if (trv <= path)
break;
saved = *trv;
if (saved == '/' || saved == '\\') {
int rv;
*trv = '\0';
rv = stat(path, &sbuf);
*trv = saved;
if (rv)
return(0);
if (!S_ISDIR(sbuf.st_mode)) {
errno = ENOTDIR;
return(0);
}
break;
}
}
for (;;) {
if (doopen) {
if ((*doopen =
open(path, O_CREAT|O_EXCL|O_RDWR|extraFlags, 0600)) >= 0)
return(1);
if (errno != EEXIST)
return(0);
}
else if (stat(path, &sbuf))
return(errno == ENOENT ? 1 : 0);
/* tricky little algorithm for backward compatibility */
for (trv = start;;) {
if (!*trv)
return(0);
if (*trv == 'z')
*trv++ = 'a';
else {
if (isdigit(*trv))
*trv = 'a';
else
++*trv;
break;
}
}
}
/*NOTREACHED*/
}

View File

@@ -1,195 +0,0 @@
/*-
* Copyright (c) 1990, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Margo Seltzer.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#if defined(LIBC_SCCS) && !defined(lint)
static char sccsid[] = "@(#)ndbm.c 8.4 (Berkeley) 7/21/94";
#endif /* LIBC_SCCS and not lint */
#include "watcomfx.h"
/*
* This package provides a dbm compatible interface to the new hashing
* package described in db(3).
*/
#if !defined(_WIN32) && !defined(_WINDOWS) && !defined(XP_OS2_VACPP)
#include <sys/param.h>
#endif
#if defined(__linux)
#include <linux/limits.h>
#endif
#include <stdio.h>
#include <string.h>
#include "ndbm.h"
#include "hash.h"
/*
* Returns:
* *DBM on success
* NULL on failure
*/
extern DBM *
dbm_open(const char *file, int flags, int mode)
{
HASHINFO info;
char path[MAXPATHLEN];
info.bsize = 4096;
info.ffactor = 40;
info.nelem = 1;
info.cachesize = 0;
info.hash = NULL;
info.lorder = 0;
(void)strcpy(path, file);
(void)strcat(path, DBM_SUFFIX);
return ((DBM *)__hash_open(path, flags, mode, &info, 0));
}
extern void
dbm_close(DBM *db)
{
(void)(db->close)(db);
}
/*
* Returns:
* DATUM on success
* NULL on failure
*/
extern datum
dbm_fetch(DBM *db, datum key)
{
datum retval;
int status;
status = (db->get)(db, (DBT *)&key, (DBT *)&retval, 0);
if (status) {
retval.dptr = NULL;
retval.dsize = 0;
}
return (retval);
}
/*
* Returns:
* DATUM on success
* NULL on failure
*/
extern datum
dbm_firstkey(DBM *db)
{
int status;
datum retdata, retkey;
status = (db->seq)(db, (DBT *)&retkey, (DBT *)&retdata, R_FIRST);
if (status)
retkey.dptr = NULL;
return (retkey);
}
/*
* Returns:
* DATUM on success
* NULL on failure
*/
extern datum
dbm_nextkey(DBM *db)
{
int status;
datum retdata, retkey;
status = (db->seq)(db, (DBT *)&retkey, (DBT *)&retdata, R_NEXT);
if (status)
retkey.dptr = NULL;
return (retkey);
}
/*
* Returns:
* 0 on success
* <0 failure
*/
extern int
dbm_delete(DBM *db, datum key)
{
int status;
status = (db->del)(db, (DBT *)&key, 0);
if (status)
return (-1);
else
return (0);
}
/*
* Returns:
* 0 on success
* <0 failure
* 1 if DBM_INSERT and entry exists
*/
extern int
dbm_store(DBM *db, datum key, datum content, int flags)
{
return ((db->put)(db, (DBT *)&key, (DBT *)&content,
(flags == DBM_INSERT) ? R_NOOVERWRITE : 0));
}
extern int
dbm_error(DBM *db)
{
HTAB *hp;
hp = (HTAB *)db->internal;
return (hp->dbmerrno);
}
extern int
dbm_clearerr(DBM *db)
{
HTAB *hp;
hp = (HTAB *)db->internal;
hp->dbmerrno = 0;
return (0);
}
extern int
dbm_dirfno(DBM *db)
{
return(((HTAB *)db->internal)->fp);
}

View File

@@ -1,305 +0,0 @@
#include "watcomfx.h"
#include "nsres.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct RESDATABASE
{
DB *hdb;
NSRESTHREADINFO *threadinfo;
char * pbuf[MAXBUFNUM];
} ;
typedef struct RESDATABASE * RESHANDLE;
typedef struct STRINGDATA
{
char *str;
unsigned int charsetid;
} STRINGDATA;
typedef unsigned int CHARSETTYPE;
#define RES_LOCK if (hres->threadinfo) hres->threadinfo->fn_lock(hres->threadinfo->lock);
#define RES_UNLOCK if (hres->threadinfo) hres->threadinfo->fn_unlock(hres->threadinfo->lock);
int GenKeyData(const char *library, int32 id, DBT *key);
/*
Right now, the page size used for resource is same as for Navigator cache
database
*/
HASHINFO res_hash_info = {
32*1024,
0,
0,
0,
0, /* 64 * 1024U */
0};
int GenKeyData(const char *library, int32 id, DBT *key)
{
char idstr[10];
static char * strdata = NULL;
size_t len;
if (strdata)
free (strdata);
if (id == 0)
idstr[0] = '\0';
else
{
sprintf(idstr, "%d", id);
/* itoa(id, idstr, 10); */
}
if (library == NULL)
len = strlen(idstr) + 1;
else
len = strlen(library) + strlen(idstr) + 1;
strdata = (char *) malloc (len);
strcpy(strdata, library);
strcat(strdata, idstr);
key->size = len;
key->data = strdata;
return 1;
}
NSRESHANDLE NSResCreateTable(const char *filename, NSRESTHREADINFO *threadinfo)
{
RESHANDLE hres;
int flag;
flag = O_RDWR | O_CREAT;
hres = (RESHANDLE) calloc ( 1, sizeof(struct RESDATABASE) );
if (threadinfo && threadinfo->lock && threadinfo->fn_lock
&& threadinfo->fn_unlock)
{
hres->threadinfo = (NSRESTHREADINFO *) malloc( sizeof(NSRESTHREADINFO) );
hres->threadinfo->lock = threadinfo->lock;
hres->threadinfo->fn_lock = threadinfo->fn_lock;
hres->threadinfo->fn_unlock = threadinfo->fn_unlock;
}
RES_LOCK
hres->hdb = dbopen(filename, flag, 0644, DB_HASH, &res_hash_info);
RES_UNLOCK
if(!hres->hdb)
return NULL;
return (NSRESHANDLE) hres;
}
NSRESHANDLE NSResOpenTable(const char *filename, NSRESTHREADINFO *threadinfo)
{
RESHANDLE hres;
int flag;
flag = O_RDONLY; /* only open database for reading */
hres = (RESHANDLE) calloc ( 1, sizeof(struct RESDATABASE) );
if (threadinfo && threadinfo->lock && threadinfo->fn_lock
&& threadinfo->fn_unlock)
{
hres->threadinfo = (NSRESTHREADINFO *) malloc( sizeof(NSRESTHREADINFO) );
hres->threadinfo->lock = threadinfo->lock;
hres->threadinfo->fn_lock = threadinfo->fn_lock;
hres->threadinfo->fn_unlock = threadinfo->fn_unlock;
}
RES_LOCK
hres->hdb = dbopen(filename, flag, 0644, DB_HASH, &res_hash_info);
RES_UNLOCK
if(!hres->hdb)
return NULL;
return (NSRESHANDLE) hres;
}
void NSResCloseTable(NSRESHANDLE handle)
{
RESHANDLE hres;
int i;
if (handle == NULL)
return;
hres = (RESHANDLE) handle;
RES_LOCK
(*hres->hdb->sync)(hres->hdb, 0);
(*hres->hdb->close)(hres->hdb);
RES_UNLOCK
for (i = 0; i < MAXBUFNUM; i++)
{
if (hres->pbuf[i])
free (hres->pbuf[i]);
}
if (hres->threadinfo)
free (hres->threadinfo);
free (hres);
}
char *NSResLoadString(NSRESHANDLE handle, const char * library, int32 id,
unsigned int charsetid, char *retbuf)
{
int status;
RESHANDLE hres;
DBT key, data;
if (handle == NULL)
return NULL;
hres = (RESHANDLE) handle;
GenKeyData(library, id, &key);
RES_LOCK
status = (*hres->hdb->get)(hres->hdb, &key, &data, 0);
RES_UNLOCK
if (retbuf)
{
memcpy(retbuf, (char *)data.data + sizeof(CHARSETTYPE), data.size - sizeof(CHARSETTYPE));
return retbuf;
}
else
{
static int WhichString = 0;
static int bFirstTime = 1;
char *szLoadedString;
int i;
RES_LOCK
if (bFirstTime) {
for (i = 0; i < MAXBUFNUM; i++)
hres->pbuf[i] = (char *) malloc(MAXSTRINGLEN * sizeof(char));
bFirstTime = 0;
}
szLoadedString = hres->pbuf[WhichString];
WhichString++;
/* reset to 0, if WhichString reaches to the end */
if (WhichString == MAXBUFNUM)
WhichString = 0;
if (status == 0)
memcpy(szLoadedString, (char *) data.data + sizeof(CHARSETTYPE),
data.size - sizeof(CHARSETTYPE));
else
szLoadedString[0] = 0;
RES_UNLOCK
return szLoadedString;
}
}
int32 NSResGetSize(NSRESHANDLE handle, const char *library, int32 id)
{
int status;
RESHANDLE hres;
DBT key, data;
if (handle == NULL)
return 0;
hres = (RESHANDLE) handle;
GenKeyData(library, id, &key);
RES_LOCK
status = (*hres->hdb->get)(hres->hdb, &key, &data, 0);
RES_UNLOCK
return data.size - sizeof(CHARSETTYPE);
}
int32 NSResLoadResource(NSRESHANDLE handle, const char *library, int32 id, char *retbuf)
{
int status;
RESHANDLE hres;
DBT key, data;
if (handle == NULL)
return 0;
hres = (RESHANDLE) handle;
GenKeyData(library, id, &key);
RES_LOCK
status = (*hres->hdb->get)(hres->hdb, &key, &data, 0);
RES_UNLOCK
if (retbuf)
{
memcpy(retbuf, (char *)data.data + sizeof(CHARSETTYPE), data.size - sizeof(CHARSETTYPE));
return data.size;
}
else
return 0;
}
int NSResAddString(NSRESHANDLE handle, const char *library, int32 id,
const char *string, unsigned int charset)
{
int status;
RESHANDLE hres;
DBT key, data;
char * recdata;
if (handle == NULL)
return 0;
hres = (RESHANDLE) handle;
GenKeyData(library, id, &key);
data.size = sizeof(CHARSETTYPE) + (strlen(string) + 1) ;
recdata = (char *) malloc(data.size) ;
/* set charset to the first field of record data */
*((CHARSETTYPE *)recdata) = (CHARSETTYPE)charset;
/* set data field */
memcpy(recdata+sizeof(CHARSETTYPE), string, strlen(string) + 1);
data.data = recdata;
RES_LOCK
status = (*hres->hdb->put)(hres->hdb, &key, &data, 0);
if (recdata)
free(recdata);
RES_UNLOCK
return status;
}

View File

@@ -1,75 +0,0 @@
#ifndef HAVE_SNPRINTF
#include "watcomfx.h"
#include <sys/types.h>
#include <stddef.h>
#include <stdio.h>
#ifdef HAVE_SYS_CDEFS_H
#include <sys/cdefs.h>
#else
#include "cdefs.h"
#endif
#include "prtypes.h"
#include <ncompat.h>
/* The OS/2 VAC compiler doesn't appear to define __STDC__ and won't let us define it either */
#if defined(__STDC__) || defined(XP_OS2_VACPP)
#include <stdarg.h>
#else
#include <varargs.h>
#endif
int
#if defined(__STDC__) || defined(XP_OS2_VACPP)
snprintf(char *str, size_t n, const char *fmt, ...)
#else
snprintf(str, n, fmt, va_alist)
char *str;
size_t n;
const char *fmt;
va_dcl
#endif
{
va_list ap;
#ifdef VSPRINTF_CHARSTAR
char *rp;
#else
int rval;
#endif
#if defined(__STDC__) || defined(XP_OS2_VACPP)
va_start(ap, fmt);
#else
va_start(ap);
#endif
#ifdef VSPRINTF_CHARSTAR
rp = vsprintf(str, fmt, ap);
va_end(ap);
return (strlen(rp));
#else
rval = vsprintf(str, fmt, ap);
va_end(ap);
return (rval);
#endif
}
int
vsnprintf(str, n, fmt, ap)
char *str;
size_t n;
const char *fmt;
va_list ap;
{
#ifdef VSPRINTF_CHARSTAR
return (strlen(vsprintf(str, fmt, ap)));
#else
return (vsprintf(str, fmt, ap));
#endif
}
#endif /* HAVE_SNPRINTF */
/* Some compilers don't like an empty source file. */
static int dummy = 0;

View File

@@ -1,78 +0,0 @@
/*
* Copyright (c) 1988, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#if defined(LIBC_SCCS) && !defined(lint)
static char sccsid[] = "@(#)strerror.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include "watcomfx.h"
#include <string.h>
#ifdef _DLL
#define sys_nerr (*_sys_nerr_dll)
#endif
#ifndef HAVE_STRERROR
#ifndef _AFXDLL
char *
strerror(num)
int num;
{
extern int sys_nerr;
extern char *sys_errlist[];
#define UPREFIX "Unknown error: "
static char ebuf[40] = UPREFIX; /* 64-bit number + slop */
register unsigned int errnum;
register char *p, *t;
char tmp[40];
errnum = num; /* convert to unsigned */
if (errnum < sys_nerr)
return(sys_errlist[errnum]);
/* Do this by hand, so we don't include stdio(3). */
t = tmp;
do {
*t++ = "0123456789"[errnum % 10];
} while (errnum /= 10);
for (p = ebuf + sizeof(UPREFIX) - 1;;) {
*p++ = *--t;
if (t <= tmp)
break;
}
return(ebuf);
}
#endif
#endif /* !HAVE_STRERROR */

View File

@@ -1,46 +0,0 @@
#
# The contents of this file are subject to the Netscape Public
# License Version 1.1 (the "License"); you may not use this file
# except in compliance with the License. You may obtain a copy of
# the License at http://www.mozilla.org/NPL/
#
# Software distributed under the License is distributed on an "AS
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
# implied. See the License for the specific language governing
# rights and limitations under the License.
#
# The Original Code is mozilla.org code.
#
# The Initial Developer of the Original Code is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s):
#
DEPTH = ../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
MODULE = dbm
PACKAGE_FILE = dbmtest.pkg
PROGRAM = lots$(BIN_SUFFIX)
CSRCS = lots.c
ifeq ($(OS_ARCH),WINNT)
EXTRA_DSO_LIBS = dbm$(MOZ_BITS)
else
EXTRA_DSO_LIBS = mozdbm_s
endif
LIBS = $(EXTRA_DSO_LIBS)
include $(topsrcdir)/config/rules.mk

View File

@@ -1,2 +0,0 @@
[gecko-tests]
dist/bin/lots@BINS@

View File

@@ -1,639 +0,0 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Netscape Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1998
* 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 NPL, 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 NPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
/* use sequental numbers printed to strings
* to store lots and lots of entries in the
* database.
*
* Start with 100 entries, put them and then
* read them out. Then delete the first
* half and verify that all of the first half
* is gone and then verify that the second
* half is still there.
* Then add the first half back and verify
* again. Then delete the middle third
* and verify again.
* Then increase the size by 1000 and do
* the whole add delete thing again.
*
* The data for each object is the number string translated
* to hex and replicated a random number of times. The
* number of times that the data is replicated is the first
* int32 in the data.
*/
#include <stdio.h>
#include <stdlib.h>
#ifdef STDC_HEADERS
#include <stdarg.h>
#else
#include <varargs.h>
#endif
#ifdef HAVE_MEMORY_H
#include <memory.h>
#endif
#include <string.h>
#include <assert.h>
#include "mcom_db.h"
DB *database=0;
int MsgPriority=5;
#if defined(_WINDOWS) && !defined(WIN32)
#define int32 long
#define uint32 unsigned long
#else
#define int32 int
#define uint32 unsigned int
#endif
typedef enum {
USE_LARGE_KEY,
USE_SMALL_KEY
} key_type_enum;
#define TraceMe(priority, msg) \
do { \
if(priority <= MsgPriority) \
{ \
ReportStatus msg; \
} \
} while(0)
int
ReportStatus(char *string, ...)
{
va_list args;
#ifdef STDC_HEADERS
va_start(args, string);
#else
va_start(args);
#endif
vfprintf(stderr, string, args);
va_end(args);
fprintf (stderr, "\n");
return(0);
}
int
ReportError(char *string, ...)
{
va_list args;
#ifdef STDC_HEADERS
va_start(args, string);
#else
va_start(args);
#endif
fprintf (stderr, "\n ");
vfprintf(stderr, string, args);
fprintf (stderr, "\n");
va_end(args);
return(0);
}
DBT * MakeLargeKey(int32 num)
{
int32 low_bits;
static DBT rv;
static char *string_rv=0;
int rep_char;
size_t size;
if(string_rv)
free(string_rv);
/* generate a really large text key derived from
* an int32
*/
low_bits = (num % 10000) + 1;
/* get the repeat char from the low 26 */
rep_char = (char) ((low_bits % 26) + 'a');
/* malloc a string low_bits wide */
size = low_bits*sizeof(char);
string_rv = (char *)malloc(size);
memset(string_rv, rep_char, size);
rv.data = string_rv;
rv.size = size;
return(&rv);
}
DBT * MakeSmallKey(int32 num)
{
static DBT rv;
static char data_string[64];
rv.data = data_string;
sprintf(data_string, "%ld", (long)num);
rv.size = strlen(data_string);
return(&rv);
}
DBT * GenKey(int32 num, key_type_enum key_type)
{
DBT *key;
switch(key_type)
{
case USE_LARGE_KEY:
key = MakeLargeKey(num);
break;
case USE_SMALL_KEY:
key = MakeSmallKey(num);
break;
default:
abort();
break;
}
return(key);
}
int
SeqDatabase()
{
int status;
DBT key, data;
ReportStatus("SEQuencing through database...");
/* seq throught the whole database */
if(!(status = (*database->seq)(database, &key, &data, R_FIRST)))
{
while(!(status = (database->seq) (database, &key, &data, R_NEXT)));
; /* null body */
}
if(status < 0)
ReportError("Error seq'ing database");
return(status);
}
int
VerifyData(DBT *data, int32 num, key_type_enum key_type)
{
int32 count, compare_num;
size_t size;
int32 *int32_array;
/* The first int32 is count
* The other n entries should
* all equal num
*/
if(data->size < sizeof(int32))
{
ReportError("Data size corrupted");
return -1;
}
memcpy(&count, data->data, sizeof(int32));
size = sizeof(int32)*(count+1);
if(size != data->size)
{
ReportError("Data size corrupted");
return -1;
}
int32_array = (int32*)data->data;
for(;count > 0; count--)
{
memcpy(&compare_num, &int32_array[count], sizeof(int32));
if(compare_num != num)
{
ReportError("Data corrupted");
return -1;
}
}
return(0);
}
/* verify that a range of number strings exist
* or don't exist. And that the data is valid
*/
#define SHOULD_EXIST 1
#define SHOULD_NOT_EXIST 0
int
VerifyRange(int32 low, int32 high, int32 should_exist, key_type_enum key_type)
{
DBT *key, data;
int32 num;
int status;
TraceMe(1, ("Verifying: %ld to %ld, using %s keys",
low, high, key_type == USE_SMALL_KEY ? "SMALL" : "LARGE"));
for(num = low; num <= high; num++)
{
key = GenKey(num, key_type);
status = (*database->get)(database, key, &data, 0);
if(status == 0)
{
/* got the item */
if(!should_exist)
{
ReportError("Item exists but shouldn't: %ld", num);
}
else
{
/* else verify the data */
VerifyData(&data, num, key_type);
}
}
else if(status > 0)
{
/* item not found */
if(should_exist)
{
ReportError("Item not found but should be: %ld", num);
}
}
else
{
/* database error */
ReportError("Database error");
return(-1);
}
}
TraceMe(1, ("Correctly verified: %ld to %ld", low, high));
return(0);
}
DBT *
GenData(int32 num)
{
int32 n;
static DBT *data=0;
int32 *int32_array;
size_t size;
if(!data)
{
data = (DBT*)malloc(sizeof(DBT));
data->size = 0;
data->data = 0;
}
else if(data->data)
{
free(data->data);
}
n = rand();
n = n % 512; /* bound to a 2K size */
size = sizeof(int32)*(n+1);
int32_array = (int32 *) malloc(size);
memcpy(&int32_array[0], &n, sizeof(int32));
for(; n > 0; n--)
{
memcpy(&int32_array[n], &num, sizeof(int32));
}
data->data = (void*)int32_array;
data->size = size;
return(data);
}
#define ADD_RANGE 1
#define DELETE_RANGE 2
int
AddOrDelRange(int32 low, int32 high, int action, key_type_enum key_type)
{
DBT *key, *data;
#if 0 /* only do this if your really analy checking the puts */
DBT tmp_data;
#endif
int32 num;
int status;
if(action != ADD_RANGE && action != DELETE_RANGE)
assert(0);
if(action == ADD_RANGE)
{
TraceMe(1, ("Adding: %ld to %ld: %s keys", low, high,
key_type == USE_SMALL_KEY ? "SMALL" : "LARGE"));
}
else
{
TraceMe(1, ("Deleting: %ld to %ld: %s keys", low, high,
key_type == USE_SMALL_KEY ? "SMALL" : "LARGE"));
}
for(num = low; num <= high; num++)
{
key = GenKey(num, key_type);
if(action == ADD_RANGE)
{
data = GenData(num);
status = (*database->put)(database, key, data, 0);
}
else
{
status = (*database->del)(database, key, 0);
}
if(status < 0)
{
ReportError("Database error %s item: %ld",
action == ADD_RANGE ? "ADDING" : "DELETING",
num);
}
else if(status > 0)
{
ReportError("Could not %s item: %ld",
action == ADD_RANGE ? "ADD" : "DELETE",
num);
}
else if(action == ADD_RANGE)
{
#define SYNC_EVERY_TIME
#ifdef SYNC_EVERY_TIME
status = (*database->sync)(database, 0);
if(status != 0)
ReportError("Database error syncing after add");
#endif
#if 0 /* only do this if your really analy checking the puts */
/* make sure we can still get it
*/
status = (*database->get)(database, key, &tmp_data, 0);
if(status != 0)
{
ReportError("Database error checking item just added: %d",
num);
}
else
{
/* now verify that none of the ones we already
* put in have disappeared
*/
VerifyRange(low, num, SHOULD_EXIST, key_type);
}
#endif
}
}
if(action == ADD_RANGE)
{
TraceMe(1, ("Successfully added: %ld to %ld", low, high));
}
else
{
TraceMe(1, ("Successfully deleted: %ld to %ld", low, high));
}
return(0);
}
int
TestRange(int32 low, int32 range, key_type_enum key_type)
{
int status; int32 low_of_range1, high_of_range1; int32 low_of_range2, high_of_range2;
int32 low_of_range3, high_of_range3;
status = AddOrDelRange(low, low+range, ADD_RANGE, key_type);
status = VerifyRange(low, low+range, SHOULD_EXIST, key_type);
TraceMe(1, ("Finished with sub test 1"));
SeqDatabase();
low_of_range1 = low;
high_of_range1 = low+(range/2);
low_of_range2 = high_of_range1+1;
high_of_range2 = low+range;
status = AddOrDelRange(low_of_range1, high_of_range1, DELETE_RANGE, key_type);
status = VerifyRange(low_of_range1, high_of_range1, SHOULD_NOT_EXIST, key_type);
status = VerifyRange(low_of_range2, low_of_range2, SHOULD_EXIST, key_type);
TraceMe(1, ("Finished with sub test 2"));
SeqDatabase();
status = AddOrDelRange(low_of_range1, high_of_range1, ADD_RANGE, key_type);
/* the whole thing should exist now */
status = VerifyRange(low, low+range, SHOULD_EXIST, key_type);
TraceMe(1, ("Finished with sub test 3"));
SeqDatabase();
status = AddOrDelRange(low_of_range2, high_of_range2, DELETE_RANGE, key_type);
status = VerifyRange(low_of_range1, high_of_range1, SHOULD_EXIST, key_type);
status = VerifyRange(low_of_range2, high_of_range2, SHOULD_NOT_EXIST, key_type);
TraceMe(1, ("Finished with sub test 4"));
SeqDatabase();
status = AddOrDelRange(low_of_range2, high_of_range2, ADD_RANGE, key_type);
/* the whole thing should exist now */
status = VerifyRange(low, low+range, SHOULD_EXIST, key_type);
TraceMe(1, ("Finished with sub test 5"));
SeqDatabase();
low_of_range1 = low;
high_of_range1 = low+(range/3);
low_of_range2 = high_of_range1+1;
high_of_range2 = high_of_range1+(range/3);
low_of_range3 = high_of_range2+1;
high_of_range3 = low+range;
/* delete range 2 */
status = AddOrDelRange(low_of_range2, high_of_range2, DELETE_RANGE, key_type);
status = VerifyRange(low_of_range1, high_of_range1, SHOULD_EXIST, key_type);
status = VerifyRange(low_of_range2, low_of_range2, SHOULD_NOT_EXIST, key_type);
status = VerifyRange(low_of_range3, low_of_range2, SHOULD_EXIST, key_type);
TraceMe(1, ("Finished with sub test 6"));
SeqDatabase();
status = AddOrDelRange(low_of_range2, high_of_range2, ADD_RANGE, key_type);
/* the whole thing should exist now */
status = VerifyRange(low, low+range, SHOULD_EXIST, key_type);
TraceMe(1, ("Finished with sub test 7"));
return(0);
}
#define START_RANGE 109876
int
main(int argc, char **argv)
{
int32 i, j=0;
int quick_exit = 0;
int large_keys = 0;
HASHINFO hash_info = {
16*1024,
0,
0,
0,
0,
0};
if(argc > 1)
{
while(argc > 1)
{
if(!strcmp(argv[argc-1], "-quick"))
quick_exit = 1;
else if(!strcmp(argv[argc-1], "-large"))
{
large_keys = 1;
}
argc--;
}
}
database = dbopen("test.db", O_RDWR | O_CREAT, 0644, DB_HASH, &hash_info);
if(!database)
{
ReportError("Could not open database");
#ifdef unix
perror("");
#endif
exit(1);
}
if(quick_exit)
{
if(large_keys)
TestRange(START_RANGE, 200, USE_LARGE_KEY);
else
TestRange(START_RANGE, 200, USE_SMALL_KEY);
(*database->sync)(database, 0);
(*database->close)(database);
exit(0);
}
for(i=100; i < 10000000; i+=200)
{
if(1 || j)
{
TestRange(START_RANGE, i, USE_LARGE_KEY);
j = 0;
}
else
{
TestRange(START_RANGE, i, USE_SMALL_KEY);
j = 1;
}
if(1 == rand() % 3)
{
(*database->sync)(database, 0);
}
if(1 == rand() % 3)
{
/* close and reopen */
(*database->close)(database);
database = dbopen("test.db", O_RDWR | O_CREAT, 0644, DB_HASH, 0);
if(!database)
{
ReportError("Could not reopen database");
#ifdef unix
perror("");
#endif
exit(1);
}
}
else
{
/* reopen database without closeing the other */
database = dbopen("test.db", O_RDWR | O_CREAT, 0644, DB_HASH, 0);
if(!database)
{
ReportError("Could not reopen database "
"after not closing the other");
#ifdef unix
perror("");
#endif
exit(1);
}
}
}
return(0);
}

44
mozilla/js/js2/Makefile Normal file
View File

@@ -0,0 +1,44 @@
STLPORT = /usr/local/include/stlport
CC = gcc
CFLAGS = -g -ggdb -DDEBUG -DXP_UNIX -Wall -W -Wpointer-arith \
-Wbad-function-cast -Wstrict-prototypes -Wmissing-prototypes \
-Wno-non-virtual-dtor -I$(STLPORT)
objs = hash.o \
icodegenerator.o \
interpreter.o \
js2.o \
jsmath.o \
jstypes.o \
numerics.o \
parser.o \
utilities.o \
world.o \
vmtypes.o \
debugger.o
gc_path = ../../gc/boehm/
libs = gc.a -lstdc++ -lm
%.o : %.cpp
$(CC) -c $(CFLAGS) $< -o $@
js2: $(objs) gc.a
$(CC) -o $@ -ggdb $(objs) $(libs)
gc.a:
(cd $(gc_path) ; ln -f -s Makefile.unix Makefile ; make gc.a)
ln -f -s $(gc_path)gc.a ./gc.a
gctest: gc_allocator.o
$(CC) -o $@ -ggdb $^ $(libs)
clean:
rm -f $(objs)
depend:
gcc -MM *.cpp > dependencies
include dependencies

View File

@@ -0,0 +1,111 @@
# Microsoft Developer Studio Project File - Name="CPlusPlusTests" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Console Application" 0x0103
CFG=CPlusPlusTests - Win32 Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
!MESSAGE
!MESSAGE NMAKE /f "CPlusPlusTests.mak".
!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
!MESSAGE
!MESSAGE NMAKE /f "CPlusPlusTests.mak" CFG="CPlusPlusTests - Win32 Debug"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "CPlusPlusTests - Win32 Release" (based on "Win32 (x86) Console Application")
!MESSAGE "CPlusPlusTests - Win32 Debug" (based on "Win32 (x86) Console Application")
!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
CPP=cl.exe
RSC=rc.exe
!IF "$(CFG)" == "CPlusPlusTests - Win32 Release"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "Release"
# PROP BASE Intermediate_Dir "Release"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "Release"
# PROP Intermediate_Dir "Release"
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
# ADD BASE RSC /l 0x409 /d "NDEBUG"
# ADD RSC /l 0x409 /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
!ELSEIF "$(CFG)" == "CPlusPlusTests - Win32 Debug"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "Debug"
# PROP BASE Intermediate_Dir "Debug"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "Debug"
# PROP Intermediate_Dir "Debug"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
# ADD CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
# ADD BASE RSC /l 0x409 /d "_DEBUG"
# ADD RSC /l 0x409 /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
!ENDIF
# Begin Target
# Name "CPlusPlusTests - Win32 Release"
# Name "CPlusPlusTests - Win32 Debug"
# Begin Group "Source Files"
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
# Begin Source File
SOURCE=.\cplusplustests.cpp
!IF "$(CFG)" == "CPlusPlusTests - Win32 Release"
!ELSEIF "$(CFG)" == "CPlusPlusTests - Win32 Debug"
# ADD CPP /Ob1 /FR
# SUBTRACT CPP /O<none> /YX
!ENDIF
# End Source File
# End Group
# Begin Group "Header Files"
# PROP Default_Filter "h;hpp;hxx;hm;inl"
# End Group
# Begin Group "Resource Files"
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
# End Group
# End Target
# End Project

View File

@@ -0,0 +1,29 @@
Microsoft Developer Studio Workspace File, Format Version 6.00
# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
###############################################################################
Project: "CPlusPlusTests"=.\CPlusPlusTests.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
}}}
###############################################################################
Global:
Package=<5>
{{{
}}}
Package=<3>
{{{
}}}
###############################################################################

Binary file not shown.

View File

@@ -0,0 +1,129 @@
#include <cstddef>
#include <cstdio>
#include <cstdlib>
#include <new>
using namespace std;
struct Arena {
const char *name;
Arena(const char *name): name(name) {}
};
void *operator new(size_t size, Arena &arena);
void operator delete(void *p);
void *operator new(size_t size, Arena &arena)
{
void *p = malloc(size);
printf("Allocating %d bytes at %p using arena \"%s\"\n", size, p, arena.name);
return p;
}
#ifndef __MWERKS__
void operator delete(void *p, Arena &arena)
{
printf("Deleting object at %p using arena \"%s\"\n", p, arena.name);
}
#endif
void operator delete(void *p)
{
printf("Deleting object at %p\n", p);
}
struct C {
int n;
C(int n, bool bad = false);
~C();
};
struct Exception {
int num;
explicit Exception(int n): num(n) {}
};
C::C(int n, bool bad): n(n)
{
printf("Constructing C #%d at %p\n", n, this);
if (bad) {
printf("Throwing %d; constructor aborted\n", n);
throw Exception(n);
}
}
C::~C()
{
printf("Destroying C #%d at %p\n", n, this);
}
static void constructorTest1(int n, bool bad)
{
try {
printf("Calling C(%d,%d)\n", n, (int)bad);
{
C c(n, bad);
printf("We have C #%d\n", c.n);
}
printf("C is out of scope\n");
} catch (Exception &e) {
printf("Caught exception %d\n", e.num);
}
printf("\n");
}
static void constructorTest2(int n, bool bad)
{
try {
printf("Calling new C(%d,%d)\n", n, (int)bad);
{
C *c = new C(n, bad);
printf("We have C #%d\n", c->n);
delete c;
}
printf("C is out of scope\n");
} catch (Exception &e) {
printf("Caught exception %d\n", e.num);
}
printf("\n");
}
static void constructorTest3(int n, bool bad)
{
try {
printf("Calling new(arena) C(%d,%d)\n", n, (int)bad);
{
Arena arena("My arena");
C *c = new(arena) C(n, bad);
printf("We have C #%d\n", c->n);
}
printf("C is out of scope\n");
} catch (Exception &e) {
printf("Caught exception %d\n", e.num);
}
printf("\n");
}
int main()
{
printf("Beginning constructor tests\n\n");
constructorTest1(1, false);
constructorTest1(2, true);
constructorTest2(3, false);
constructorTest2(4, true);
constructorTest3(5, false);
constructorTest3(6, true);
printf("Ending constructor tests\n");
return 0;
}

191
mozilla/js/js2/cpucfg.h Normal file
View File

@@ -0,0 +1,191 @@
/* -*- 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.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is Mozilla Communicator client code, released
* March 31, 1998.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU Public License (the "GPL"), in which case the
* provisions of the GPL are applicable instead of those above.
* If you wish to allow use of your version of this file only
* under the terms of the GPL and not to allow others to use your
* version of this file under the NPL, indicate your decision by
* deleting the provisions above and replace them with the notice
* and other provisions required by the GPL. If you do not delete
* the provisions above, a recipient may use your version of this
* file under either the NPL or the GPL.
*/
#ifndef cpucfg_h
#define cpucfg_h
#define JS_HAVE_LONG_LONG
#ifdef XP_MAC
#undef IS_LITTLE_ENDIAN
#define IS_BIG_ENDIAN 1
#define JS_BYTES_PER_BYTE 1L
#define JS_BYTES_PER_SHORT 2L
#define JS_BYTES_PER_INT 4L
#define JS_BYTES_PER_INT64 8L
#define JS_BYTES_PER_LONG 4L
#define JS_BYTES_PER_FLOAT 4L
#define JS_BYTES_PER_DOUBLE 8L
#define JS_BYTES_PER_WORD 4L
#define JS_BYTES_PER_DWORD 8L
#define JS_BITS_PER_BYTE 8L
#define JS_BITS_PER_SHORT 16L
#define JS_BITS_PER_INT 32L
#define JS_BITS_PER_INT64 64L
#define JS_BITS_PER_LONG 32L
#define JS_BITS_PER_FLOAT 32L
#define JS_BITS_PER_DOUBLE 64L
#define JS_BITS_PER_WORD 32L
#define JS_BITS_PER_BYTE_LOG2 3L
#define JS_BITS_PER_SHORT_LOG2 4L
#define JS_BITS_PER_INT_LOG2 5L
#define JS_BITS_PER_INT64_LOG2 6L
#define JS_BITS_PER_LONG_LOG2 5L
#define JS_BITS_PER_FLOAT_LOG2 5L
#define JS_BITS_PER_DOUBLE_LOG2 6L
#define JS_BITS_PER_WORD_LOG2 5L
#define JS_ALIGN_OF_SHORT 2L
#define JS_ALIGN_OF_INT 4L
#define JS_ALIGN_OF_LONG 4L
#define JS_ALIGN_OF_INT64 2L
#define JS_ALIGN_OF_FLOAT 4L
#define JS_ALIGN_OF_DOUBLE 4L
#define JS_ALIGN_OF_POINTER 4L
#define JS_ALIGN_OF_WORD 4L
#define JS_BYTES_PER_WORD_LOG2 2L
#define JS_BYTES_PER_DWORD_LOG2 3L
#define PR_WORDS_PER_DWORD_LOG2 1L
#elif defined(XP_PC)
#ifdef _WIN32
#define IS_LITTLE_ENDIAN 1
#undef IS_BIG_ENDIAN
#define JS_BYTES_PER_BYTE 1L
#define JS_BYTES_PER_SHORT 2L
#define JS_BYTES_PER_INT 4L
#define JS_BYTES_PER_INT64 8L
#define JS_BYTES_PER_LONG 4L
#define JS_BYTES_PER_FLOAT 4L
#define JS_BYTES_PER_DOUBLE 8L
#define JS_BYTES_PER_WORD 4L
#define JS_BYTES_PER_DWORD 8L
#define JS_BITS_PER_BYTE 8L
#define JS_BITS_PER_SHORT 16L
#define JS_BITS_PER_INT 32L
#define JS_BITS_PER_INT64 64L
#define JS_BITS_PER_LONG 32L
#define JS_BITS_PER_FLOAT 32L
#define JS_BITS_PER_DOUBLE 64L
#define JS_BITS_PER_WORD 32L
#define JS_BITS_PER_BYTE_LOG2 3L
#define JS_BITS_PER_SHORT_LOG2 4L
#define JS_BITS_PER_INT_LOG2 5L
#define JS_BITS_PER_INT64_LOG2 6L
#define JS_BITS_PER_LONG_LOG2 5L
#define JS_BITS_PER_FLOAT_LOG2 5L
#define JS_BITS_PER_DOUBLE_LOG2 6L
#define JS_BITS_PER_WORD_LOG2 5L
#define JS_ALIGN_OF_SHORT 2L
#define JS_ALIGN_OF_INT 4L
#define JS_ALIGN_OF_LONG 4L
#define JS_ALIGN_OF_INT64 8L
#define JS_ALIGN_OF_FLOAT 4L
#define JS_ALIGN_OF_DOUBLE 4L
#define JS_ALIGN_OF_POINTER 4L
#define JS_ALIGN_OF_WORD 4L
#define JS_BYTES_PER_WORD_LOG2 2L
#define JS_BYTES_PER_DWORD_LOG2 3L
#define PR_WORDS_PER_DWORD_LOG2 1L
#endif /* _WIN32 */
#if defined(_WINDOWS) && !defined(_WIN32) /* WIN16 */
#define IS_LITTLE_ENDIAN 1
#undef IS_BIG_ENDIAN
#define JS_BYTES_PER_BYTE 1L
#define JS_BYTES_PER_SHORT 2L
#define JS_BYTES_PER_INT 2L
#define JS_BYTES_PER_INT64 8L
#define JS_BYTES_PER_LONG 4L
#define JS_BYTES_PER_FLOAT 4L
#define JS_BYTES_PER_DOUBLE 8L
#define JS_BYTES_PER_WORD 4L
#define JS_BYTES_PER_DWORD 8L
#define JS_BITS_PER_BYTE 8L
#define JS_BITS_PER_SHORT 16L
#define JS_BITS_PER_INT 16L
#define JS_BITS_PER_INT64 64L
#define JS_BITS_PER_LONG 32L
#define JS_BITS_PER_FLOAT 32L
#define JS_BITS_PER_DOUBLE 64L
#define JS_BITS_PER_WORD 32L
#define JS_BITS_PER_BYTE_LOG2 3L
#define JS_BITS_PER_SHORT_LOG2 4L
#define JS_BITS_PER_INT_LOG2 4L
#define JS_BITS_PER_INT64_LOG2 6L
#define JS_BITS_PER_LONG_LOG2 5L
#define JS_BITS_PER_FLOAT_LOG2 5L
#define JS_BITS_PER_DOUBLE_LOG2 6L
#define JS_BITS_PER_WORD_LOG2 5L
#define JS_ALIGN_OF_SHORT 2L
#define JS_ALIGN_OF_INT 2L
#define JS_ALIGN_OF_LONG 2L
#define JS_ALIGN_OF_INT64 2L
#define JS_ALIGN_OF_FLOAT 2L
#define JS_ALIGN_OF_DOUBLE 2L
#define JS_ALIGN_OF_POINTER 2L
#define JS_ALIGN_OF_WORD 2L
#define JS_BYTES_PER_WORD_LOG2 2L
#define JS_BYTES_PER_DWORD_LOG2 3L
#define PR_WORDS_PER_DWORD_LOG2 1L
#endif /* defined(_WINDOWS) && !defined(_WIN32) */
#elif defined(XP_UNIX) || defined(XP_BEOS)
#error "This file is supposed to be auto-generated on UNIX platforms, but the"
#error "static version for Mac and Windows platforms is being used."
#error "Something's probably wrong with paths/headers/dependencies/Makefiles."
#else
#error "Must define one of XP_MAC, XP_PC, or XP_UNIX"
#endif
#endif

466
mozilla/js/js2/debugger.cpp Normal file
View File

@@ -0,0 +1,466 @@
/* -*- 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.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is the JavaScript 2 Prototype.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU Public License (the "GPL"), in which case the
* provisions of the GPL are applicable instead of those above.
* If you wish to allow use of your version of this file only
* under the terms of the GPL and not to allow others to use your
* version of this file under the NPL, indicate your decision by
* deleting the provisions above and replace them with the notice
* and other provisions required by the GPL. If you do not delete
* the provisions above, a recipient may use your version of this
* file under either the NPL or the GPL.
*/
#include "world.h"
#include "debugger.h"
#include <string>
#include <ctype.h>
#include <assert.h>
namespace JavaScript {
namespace Debugger {
using namespace Interpreter;
/* keep in sync with list in debugger.h */
static const char *shell_cmds[][3] = {
{"assemble", "", 0},
{"ambiguous", "", "Test command for ambiguous command detection"},
{"ambiguous2", "", "Test command for ambiguous command detection"},
{"continue", "", "Continue execution until complete."},
{"dissassemble", "[start_pc] [end_pc]", "Dissassemble entire module, or subset of module."},
{"exit", "", 0},
{"help", "", "Display this message."},
{"istep", "", "Execute the current opcode and stop."},
{"let", "", "Set a debugger environment variable."},
{"print", "", 0},
{"register", "", "(nyi) Show the value of a single register or all registers, or set the value of a single register."},
{"step", "", "Execute the current JS statement and stop."},
{0, 0} /* sentry */
};
enum ShellVariable {
TRACE_SOURCE,
TRACE_ICODE,
VARIABLE_COUNT
};
static const char *shell_vars[][3] = {
{"tracesource", "", "(bool) Show JS source while executing."},
{"traceicode", " ", "(bool) Show opcodes while executing."},
{0, 0} /* sentry */
};
/* return true if str2 starts with/is str1
* XXX ignore case */
static bool
startsWith (const String &str1, const String &str2)
{
uint n;
size_t m = str1.size();
if (m > str2.size())
return false;
for (n = 0; n < m; ++n)
if (str1[n] != str2[n])
return false;
return true;
}
/**
* locate the best match for |partial| in the command list |list|.
* if no matches are found, return |length|, if multiple matches are found,
* return |length| plus the number of ambiguous matches
*/
static uint32
matchElement (const String &partial, const char *list[][3], size_t length)
{
uint32 ambig_matches = 0;
uint32 match = length;
for (uint32 i = 0; i < length ; ++i)
{
String possibleMatch (widenCString(list[i][0]));
if (startsWith(partial, possibleMatch))
{
if (partial.size() == possibleMatch.size())
{
/* exact match */
ambig_matches = 0;
return i;
}
else if (match == COMMAND_COUNT) /* no match yet */
match = i;
else
++ambig_matches; /* something already matched,
* ambiguous command */
}
}
if (ambig_matches == 0)
return match;
else
return length + ambig_matches;
}
static void
showHelp(Formatter &out)
{
int i;
out << "JavaScript 2.0 Debugger Help...\n\n";
for (i = 0; shell_cmds[i][0] != 0; i++)
{
out << "Command : " << shell_cmds[i][0] << " " <<
shell_cmds[i][1] << "\n";
if (shell_cmds[i][2])
out << "Help : " << shell_cmds[i][2] << "\n";
else
out << "Help : (probably) Not Implemented.\n";
}
}
static uint32
getClosestSourcePosForPC (Context *cx, InstructionIterator pc)
{
ICodeModule *iCode = cx->getICode();
if (iCode->mInstructionMap->begin() == iCode->mInstructionMap->end())
return NotABanana;
/*NOT_REACHED ("Instruction map is empty, waah.");*/
InstructionMap::iterator pos_iter =
iCode->mInstructionMap->upper_bound (pc - iCode->its_iCode->begin());
if (pos_iter != iCode->mInstructionMap->begin())
--pos_iter;
return pos_iter->second;
}
void
Shell::showSourceAtPC (Context *cx, InstructionIterator pc)
{
if (!mResolveFileCallback)
{
mErr << "Source not available (Debugger was improperly initialized.)\n";
return;
}
ICodeModule *iCode = cx->getICode();
String fn = iCode->getFileName();
const Reader *reader = mResolveFileCallback(fn);
if (!reader)
{
mErr << "Source not available.\n";
return;
}
uint32 pos = getClosestSourcePosForPC(cx, pc);
if (pos == NotABanana)
{
mErr << "Map is empty, cannot display source.\n";
return;
}
uint32 lineNum = reader->posToLineNum (pos);
const char16 *lineBegin, *lineEnd;
uint32 lineStartPos = reader->getLine (lineNum, lineBegin, lineEnd);
String sourceLine (lineBegin, lineEnd);
mOut << fn << ":" << lineNum << " " << sourceLine << "\n";
uint padding = fn.length() + (uint32)(lineNum / 10) + 3;
uint i;
for (i = 0; i < padding; i++)
mOut << " ";
padding = (pos - lineStartPos);
for (i = 0; i < padding; i++)
mOut << ".";
mOut << "^\n";
}
void
Shell::showOpAtPC(Context* cx, InstructionIterator pc)
{
ICodeModule *iCode = cx->getICode();
if ((pc < iCode->its_iCode->begin()) ||
(pc >= iCode->its_iCode->end()))
{
mErr << "PC Out Of Range.";
return;
}
JSValues &registers = cx->getRegisters();
printFormat(mOut, "trace [%02u:%04u]: ",
iCode->mID, (pc - iCode->its_iCode->begin()));
Instruction* i = *pc;
stdOut << *i;
if (i->op() != BRANCH && i->count() > 0) {
mOut << " [";
i->printOperands(stdOut, registers);
mOut << "]\n";
} else {
mOut << '\n';
}
}
void
Shell::listen(Context* cx, Context::Event event)
{
InstructionIterator pc = cx->getPC();
if (mTraceSource)
showSourceAtPC (cx, pc);
if (mTraceICode)
showOpAtPC (cx, pc);
if (!(mStopMask & event))
return;
if ((mLastCommand == STEP) && (mLastICodeID == cx->getICode()->mID) &&
(mLastSourcePos == getClosestSourcePosForPC (cx, cx->getPC())))
/* we're in source-step mode, and the source position hasn't
* changed yet */
return;
if (!mTraceSource && !mTraceICode)
showSourceAtPC (cx, pc);
static String lastLine(widenCString("help\n"));
String line;
LineReader reader(mIn);
do {
stdOut << "jsd";
if (mLastCommand != COMMAND_COUNT)
stdOut << " (" << shell_cmds[mLastCommand][0] << ") ";
stdOut << "> ";
reader.readLine(line);
if (line[0] == uni::lf)
line = lastLine;
else
lastLine = line;
} while (doCommand(cx, line));
}
/**
* lex and execute the debugger command in |source|, return true if the
* command does not require the script being debugged to continue (eg, ask
* for more debugger input.)
*/
bool
Shell::doCommand (Interpreter::Context *cx, const String &source)
{
Lexer lex (mWorld, source, widenCString("debugger console"), 0);
const String *cmd;
uint32 match;
bool rv = true;
const Token &t = lex.get(true);
if (t.hasKind(Token::identifier))
cmd = &(t.getIdentifier());
else
{
mErr << "you idiot.\n";
return true;
}
match = matchElement (*cmd, shell_cmds, (size_t)COMMAND_COUNT);
if (match <= (uint32)COMMAND_COUNT)
{
switch ((ShellCommand)match)
{
case COMMAND_COUNT:
mErr << "Unknown command '" << *cmd << "'.\n";
break;
case AMBIGUOUS:
case AMBIGUOUS2:
mErr << "I pity the foogoo.\n";
break;
case CONTINUE:
mStopMask &= (Context::EV_ALL ^ Context::EV_STEP);
rv = false;
break;
case DISSASSEMBLE:
mOut << *cx->getICode();
break;
case HELP:
showHelp (mOut);
break;
case PRINT:
doPrint (cx, lex);
break;
case STEP:
mStopMask |= Context::EV_STEP;
rv = false;
break;
case LET:
doSetVariable (lex);
break;
default:
mErr << "Input '" << *cmd << "' matched unimplemented " <<
"command '" << shell_cmds[match][0] << "'.\n";
break;
}
mLastSourcePos = getClosestSourcePosForPC (cx, cx->getPC());
mLastICodeID = cx->getICode()->mID;
mLastCommand = (ShellCommand)match;
} else
mErr << "Ambiguous command '" << *cmd << "', " <<
(match - (uint32)COMMAND_COUNT + 1) << " similar commands.\n";
return rv;
}
void
Shell::doSetVariable (Lexer &lex)
{
uint32 match;
const String *varname;
const Token *t = &(lex.get(true));
if (t->hasKind(Token::identifier))
varname = &(t->getIdentifier());
else
{
mErr << "invalid variable name.\n";
return;
}
match = matchElement (*varname, shell_vars, (size_t)VARIABLE_COUNT);
if (match <= (uint32)VARIABLE_COUNT)
switch ((ShellVariable)match)
{
case VARIABLE_COUNT:
mErr << "Unknown variable '" << *varname << "'.\n";
break;
case TRACE_SOURCE:
t = &(lex.get(true));
if (t->hasKind(Token::assignment))
t = &(lex.get(true)); /* optional = */
if (t->hasKind(Token::True))
mTraceSource = true;
else if (t->hasKind(Token::False))
mTraceSource = false;
else
goto badval;
break;
case TRACE_ICODE:
t = &(lex.get(true));
if (t->hasKind(Token::assignment))
t = &(lex.get(true)); /* optional = */
if (t->hasKind(Token::True))
mTraceICode = true;
else if (t->hasKind(Token::False))
mTraceICode = false;
else
goto badval;
break;
default:
mErr << "Variable '" << *varname <<
"' matched unimplemented variable '" <<
shell_vars[match][0] << "'.\n";
}
else
mErr << "Ambiguous variable '" << *varname << "', " <<
(match - (uint32)COMMAND_COUNT + 1) << " similar variables.\n";
return;
badval:
mErr << "Invalid value for variable '" <<
shell_vars[(ShellVariable)match][0] << "'\n";
}
void
Shell::doPrint (Context *, Lexer &lex)
{
const Token *t = &(lex.get(true));
if (!(t->hasKind(Token::identifier)))
{
mErr << "Invalid register name.\n";
return;
}
/*
const StringAtom *name = &(t->getIdentifier());
VariableMap::iterator i = ((cx->getICode())->itsVariables)->find(*name);
// if (i)
mOut << (*i).first << " = " << (*i).second << "\n";
// else
// mOut << "No " << *name << " defined.\n";
*/
}
} /* namespace Debugger */
} /* namespace JavaScript */

163
mozilla/js/js2/debugger.h Normal file
View 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.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is the JavaScript 2 Prototype.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU Public License (the "GPL"), in which case the
* provisions of the GPL are applicable instead of those above.
* If you wish to allow use of your version of this file only
* under the terms of the GPL and not to allow others to use your
* version of this file under the NPL, indicate your decision by
* deleting the provisions above and replace them with the notice
* and other provisions required by the GPL. If you do not delete
* the provisions above, a recipient may use your version of this
* file under either the NPL or the GPL.
*/
/* this is all vapor, don't take it to serious yet */
#ifndef debugger_h
#define debugger_h
#include "utilities.h"
#include "interpreter.h"
#include <stdio.h>
namespace JavaScript {
namespace Debugger {
using namespace Interpreter;
class Shell;
typedef const Reader *ResolveFileCallback (const String &fileName);
typedef bool DebuggerCommandCallback (Shell &debugger, const Lexer &lex);
class Breakpoint {
public:
/* representation of a breakpoint */
void set();
void clear();
bool getState();
InstructionIterator getPC();
};
struct DebuggerCommand
{
DebuggerCommand(String aName, String aParamDesc, String aShortHelp,
String aLongHelp = widenCString("No more help available."),
DebuggerCommandCallback *aCommandFunction = 0)
: mName(aName), mParamDesc(aParamDesc), mShortHelp(aShortHelp),
mLongHelp(aLongHelp), mCommandFunction(aCommandFunction) {}
String mName;
String mParamDesc;
String mShortHelp;
String mLongHelp;
DebuggerCommandCallback *mCommandFunction;
};
/* keep in sync with list in debugger.cpp */
enum ShellCommand {
ASSEMBLE,
AMBIGUOUS,
AMBIGUOUS2,
CONTINUE,
DISSASSEMBLE,
EXIT,
HELP,
ISTEP,
LET,
PRINT,
REGISTER,
STEP,
COMMAND_COUNT
};
class Shell : public Context::Listener {
public:
Shell (World &aWorld, FILE *aIn, Formatter &aOut, Formatter &aErr,
ResolveFileCallback *aCallback = 0) :
mWorld(aWorld), mIn(aIn), mOut(aOut), mErr(aErr),
mResolveFileCallback(aCallback), mStopMask(Context::EV_DEBUG),
mTraceSource(false), mTraceICode(false), mLastSourcePos(0),
mLastICodeID(NotABanana), mLastCommand(COMMAND_COUNT)
{
}
~Shell ()
{
}
ResolveFileCallback
*setResolveFileCallback (ResolveFileCallback *aCallback)
{
ResolveFileCallback *rv = mResolveFileCallback;
mResolveFileCallback = aCallback;
return rv;
}
void listen(Context *context, Context::Event event);
/**
* install on a context
*/
bool attachToContext (Context *aContext)
{
aContext->addListener (this);
return true;
}
/**
* detach an icdebugger from a context
*/
bool detachFromContext (Context *aContext)
{
aContext->removeListener (this);
return true;
}
FILE *getIStream() { return mIn; }
Formatter &getOStream() { return mOut; }
Formatter &getEStream() { return mErr; }
private:
bool doCommand (Context *cx, const String &aSource);
void doSetVariable (Lexer &lex);
void doPrint (Context *cx, Lexer &lex);
void showOpAtPC(Context* cx, InstructionIterator pc);
void showSourceAtPC(Context* cx, InstructionIterator pc);
World &mWorld;
FILE *mIn;
Formatter &mOut, &mErr;
ResolveFileCallback *mResolveFileCallback;
uint32 mStopMask;
bool mTraceSource, mTraceICode;
uint32 mLastSourcePos, mLastICodeID;
ShellCommand mLastCommand;
};
} /* namespace Debugger */
} /* namespace JavaScript */
#endif /* debugger_h */

View File

@@ -0,0 +1,26 @@
debugger.o: debugger.cpp world.h utilities.h systemtypes.h hash.h \
parser.h debugger.h interpreter.h jstypes.h gc_allocator.h vmtypes.h \
numerics.h jsclasses.h icode.h icodegenerator.h
gc_allocator.o: gc_allocator.cpp gc_allocator.h gc_container.h
hash.o: hash.cpp hash.h utilities.h systemtypes.h
icodegenerator.o: icodegenerator.cpp numerics.h utilities.h \
systemtypes.h world.h hash.h parser.h vmtypes.h jstypes.h \
gc_allocator.h jsclasses.h icode.h icodegenerator.h interpreter.h
interpreter.o: interpreter.cpp interpreter.h utilities.h systemtypes.h \
jstypes.h gc_allocator.h vmtypes.h numerics.h jsclasses.h world.h \
hash.h parser.h icode.h icodegenerator.h jsmath.h
js2.o: js2.cpp world.h utilities.h systemtypes.h hash.h parser.h \
interpreter.h jstypes.h gc_allocator.h vmtypes.h numerics.h \
jsclasses.h icode.h icodegenerator.h debugger.h
jsmath.o: jsmath.cpp jsmath.h jstypes.h utilities.h systemtypes.h \
gc_allocator.h
jstypes.o: jstypes.cpp jstypes.h utilities.h systemtypes.h \
gc_allocator.h jsclasses.h numerics.h icodegenerator.h parser.h \
vmtypes.h world.h hash.h icode.h
numerics.o: numerics.cpp numerics.h utilities.h systemtypes.h
parser.o: parser.cpp numerics.h utilities.h systemtypes.h parser.h \
world.h hash.h
utilities.o: utilities.cpp utilities.h systemtypes.h
vmtypes.o: vmtypes.cpp utilities.h systemtypes.h vmtypes.h numerics.h \
jstypes.h gc_allocator.h jsclasses.h world.h hash.h parser.h icode.h
world.o: world.cpp world.h utilities.h systemtypes.h hash.h parser.h

View File

@@ -0,0 +1,150 @@
// -*- Mode: C++; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*-
//
// The contents of this file are subject to the Netscape Public
// License Version 1.1 (the "License"); you may not use this file
// except in compliance with the License. You may obtain a copy of
// the License at http://www.mozilla.org/NPL/
//
// Software distributed under the License is distributed on an "AS
// IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr
// implied. See the License for the specific language governing
// rights and limitations under the License.
//
// The Original Code is the JavaScript 2 Prototype.
//
// The Initial Developer of the Original Code is Netscape
// Communications Corporation. Portions created by Netscape are
// Copyright (C) 2000 Netscape Communications Corporation. All
// Rights Reserved.
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include "gc_allocator.h"
#include "gc_container.h"
/*
namespace JavaScript {
template <class T>
typename gc_allocator<T>::pointer
gc_allocator<T>::allocate(gc_allocator<T>::size_type n, const void*)
{
return static_cast<pointer>(GC_malloc(n*sizeof(T)));
}
template <class T>
void gc_allocator<T>::deallocate(gc_allocator<T>::pointer ptr, gc_allocator<T>::size_type)
{
// this can really be a NO-OP with the GC.
// ::GC_free(static_cast<void*>(ptr));
}
}
*/
// test driver for standalone GC development.
namespace JS = JavaScript;
template <class T>
void* operator new(std::size_t, const JS::gc_allocator<T>& alloc)
{
return alloc.allocate(1);
}
/**
* Define a C++ class that is garbage collectable, and wants to have its destructor
* called when it is finalized.
*/
class A {
public:
typedef JS::gc_traits_finalizable<A> traits;
typedef JS::gc_allocator<A, traits> allocator;
friend struct traits;
static int instances;
void* operator new(std::size_t)
{
return allocator::allocate(1);
}
A()
{
++instances;
std::cout << "A::A() here." << std::endl;
}
protected:
~A()
{
--instances;
std::cout << "A::~A() here." << std::endl;
}
private:
// void operator delete(void*) {}
};
int A::instances = 0;
int main(int /* argc */, char* /* argv[] */)
{
using namespace std;
using namespace JS;
cout << "testing the GC allocator." << endl;
#ifdef XP_MAC
// allocate a string, using the GC, and owned by an auto_ptr, that knows how to correctly destroy the string.
typedef gc_container<char>::string char_string;
typedef gc_allocator<char_string> char_string_alloc;
auto_ptr<char_string, char_string_alloc> ptr(new(char_string_alloc()) char_string("This is a garbage collectable string."));
const char_string& str = *ptr;
cout << str << endl;
#endif
// question, how can we partially evaluate a template?
// can we say, typedef template <class T> vector<typename T>.
// typedef vector<int, gc_allocator<int> > int_vector;
typedef gc_container<int>::vector int_vector;
// generate 1000 random values.
int_vector values;
for (int i = 0; i < 1000; ++i) {
int value = rand() % 32767;
values.push_back(value);
// allocate a random amount of garbage.
if (!GC_malloc(static_cast<size_t>(value)))
cerr << "GC_malloc failed." << endl;
// allocate an object that has a finalizer to call its destructor.
A* a = new A();
}
// run a collection.
// gc_allocator<void>::collect();
GC_gcollect();
// print out instance count.
cout << "A::instances = " << A::instances << endl;
// sort the values.
sort(values.begin(), values.end());
// print the values.
int_vector::iterator iter = values.begin(), last = values.end();
cout << *iter++;
while (iter < last)
cout << ' ' << *iter++;
cout << endl;
#ifdef XP_MAC
// finally, print the string again.
cout << str << endl;
#endif
return 0;
}

View File

@@ -0,0 +1,178 @@
// -*- Mode: C++; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*-
//
// The contents of this file are subject to the Netscape Public
// License Version 1.1 (the "License"); you may not use this file
// except in compliance with the License. You may obtain a copy of
// the License at http://www.mozilla.org/NPL/
//
// Software distributed under the License is distributed on an "AS
// IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr
// implied. See the License for the specific language governing
// rights and limitations under the License.
//
// The Original Code is the JavaScript 2 Prototype.
//
// The Initial Developer of the Original Code is Netscape
// Communications Corporation. Portions created by Netscape are
// Copyright (C) 2000 Netscape Communications Corporation. All
// Rights Reserved.
#ifndef gc_allocator_h
#define gc_allocator_h
#include <memory>
#ifndef _WIN32 // Microsoft VC6 bug: standard identifiers should be in std namespace
using std::size_t;
using std::ptrdiff_t;
#endif
namespace JavaScript {
extern "C" {
void* GC_malloc(size_t bytes);
void* GC_malloc_atomic(size_t bytes);
void GC_free(void* ptr);
void GC_gcollect(void);
typedef void (*GC_finalization_proc) (void* obj, void* client_data);
void GC_register_finalizer(void* obj, GC_finalization_proc proc, void* client_data,
GC_finalization_proc *old_proc, void* *old_client_data);
}
#if 0 && !defined(XP_MAC)
// for platforms where GC doesn't exist yet.
inline void* GC_malloc(size_t bytes) { return ::operator new(bytes); }
inline void* GC_malloc_atomic(size_t bytes) { return ::operator new(bytes); }
inline void GC_free(void* ptr) { operator delete(ptr); }
inline void GC_gcollect() {}
inline void GC_register_finalizer(void* obj, GC_finalization_proc proc, void* client_data,
GC_finalization_proc *old_proc, void* *old_client_data) {}
#endif
/**
* General case: memory for type must be allocated as a conservatively
* scanned block of memory.
*/
template <class T> struct gc_traits {
static T* allocate(size_t n) { return static_cast<T*>(GC_malloc(n * sizeof(T))); }
};
/**
* Specializations for blocks of atomic types: the macro define_atomic_type(_type)
* specializes gc_traits<T> for types that need not be scanned by the
* GC. Implementors are free to define other types as atomic, if they are
* guaranteed not to contain pointers.
*/
#define define_atomic_type(_type) \
template <> struct gc_traits<_type> { \
static _type* allocate(size_t n) \
{ \
return static_cast<_type*>(GC_malloc_atomic(n * sizeof(_type))); \
} \
};
define_atomic_type(char)
define_atomic_type(unsigned char)
define_atomic_type(short)
define_atomic_type(unsigned short)
define_atomic_type(int)
define_atomic_type(unsigned int)
define_atomic_type(long)
define_atomic_type(unsigned long)
define_atomic_type(float)
define_atomic_type(double)
#undef define_atomic_type
/**
* Traits for classes that need to have their destructor called
* when reclaimed by the garbage collector.
*/
template <class T> struct gc_traits_finalizable {
static void finalizer(void* obj, void* client_data)
{
T* t = static_cast<T*>(obj);
size_t n = reinterpret_cast<size_t>(client_data);
for (size_t i = 0; i < n; ++i)
t[i].~T();
}
static T* allocate(size_t n)
{
T* t = gc_traits<T>::allocate(n);
GC_finalization_proc old_proc; void* old_client_data;
GC_register_finalizer(t, &finalizer, reinterpret_cast<void*>(n), &old_proc, &old_client_data);
return t;
}
};
/**
* An allocator that can be used to allocate objects in the garbage collected heap.
*/
template <class T, class traits = gc_traits<T> > class gc_allocator {
public:
typedef T value_type;
typedef size_t size_type;
typedef ptrdiff_t difference_type;
typedef T *pointer;
typedef const T *const_pointer;
typedef T &reference;
typedef const T &const_reference;
gc_allocator() {}
template<typename U, typename UTraits> gc_allocator(const gc_allocator<U, UTraits>&) {}
// ~gc_allocator() {}
static pointer address(reference r) { return &r; }
static const_pointer address(const_reference r) { return &r; }
static pointer allocate(size_type n, const void* /* hint */ = 0) { return traits::allocate(n); }
static void deallocate(pointer, size_type) {}
static void construct(pointer p, const T &val) { new(p) T(val);}
static void destroy(pointer p) { p->~T(); }
#if defined(__GNUC__) || defined(_WIN32)
static size_type max_size() { return size_type(-1) / sizeof(T); }
#else
static size_type max_size() { return std::numeric_limits<size_type>::max() / sizeof(T); }
#endif
template<class U> struct rebind { typedef gc_allocator<U> other; };
#ifdef _WIN32
// raw byte allocator used on some platforms (grrr).
typedef char _Char[1];
static char* _Charalloc(size_type n) { return (char*) rebind<_Char>::other::allocate(n); }
// funky operator required for calling basic_string<T> constructor (grrr).
template<typename U, typename UTraits> int operator==(const gc_allocator<U, UTraits>&) { return 0; }
#endif
// void* deallocate used on some platforms (grrr).
static void deallocate(void*, size_type) {}
static void collect() { GC_gcollect(); }
};
/**
* Generic base class for objects allocated using a gc_allocator. How they are allocated
* can be controlled by specializing gc_traits for the specific class.
*/
template <typename T> class gc_object {
public:
void* operator new(size_t) { return gc_allocator<T>::allocate(1, 0); }
void operator delete(void* /* ptr */) {}
};
/**
* Simpler base class for classes that have no need to specialize allocation behavior.
*/
class gc_base {
public:
void* operator new(size_t n) { return GC_malloc(n); }
void operator delete(void*) {}
};
}
#endif /* gc_allocator_h */

View File

@@ -0,0 +1,71 @@
// -*- Mode: C++; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*-
//
// The contents of this file are subject to the Netscape Public
// License Version 1.1 (the "License"); you may not use this file
// except in compliance with the License. You may obtain a copy of
// the License at http://www.mozilla.org/NPL/
//
// Software distributed under the License is distributed on an "AS
// IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr
// implied. See the License for the specific language governing
// rights and limitations under the License.
//
// The Original Code is the JavaScript 2 Prototype.
//
// The Initial Developer of the Original Code is Netscape
// Communications Corporation. Portions created by Netscape are
// Copyright (C) 2000 Netscape Communications Corporation. All
// Rights Reserved.
#ifndef gc_container_h
#define gc_container_h
#include "gc_allocator.h"
#include <list>
#include <vector>
#include <string>
#define LIST std::list
#define VECTOR std::vector
#if defined(__GNUC__)
// grr, what kind of standard is this?
#define STRING basic_string
#define CHAR_TRAITS string_char_traits
#else
#define STRING std::basic_string
#define CHAR_TRAITS std::char_traits
#endif
namespace JavaScript {
/**
* Rebind some of the basic container types to use a GC_allocator.
* What I really want is something more general, something like:
* template <typename Container, typename T> class gc_rebind {
* typedef typename Container<T, gc_allocator<T> > other;
* };
* But I can't figure out how to do that with C++ templates.
*/
template <class T> struct gc_container {
typedef typename LIST<T, gc_allocator<T> > list;
typedef typename VECTOR<T, gc_allocator<T> > vector;
typedef typename STRING<T, CHAR_TRAITS<T>, gc_allocator<T> > string;
};
/**
* But, it's pretty easy to do with macros:
*/
#define GC_CONTAINER(container, type) container<T, gc_allocator<T> >
/*
// this gives an "unimplemented C++ feature" error using CWPro5.
// maybe someday.
template <template<class, class> typename Container, typename T>
struct gc_rebind {
typedef typename Container<T, gc_allocator<T> > container;
};
*/
}
#endif /* gc_container_h */

173
mozilla/js/js2/hash.cpp Normal file
View File

@@ -0,0 +1,173 @@
// -*- 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.1 (the "License"); you may not use this file
// except in compliance with the License. You may obtain a copy of
// the License at http://www.mozilla.org/NPL/
//
// Software distributed under the License is distributed on an "AS
// IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr
// implied. See the License for the specific language governing
// rights and limitations under the License.
//
// The Original Code is the JavaScript 2 Prototype.
//
// The Initial Developer of the Original Code is Netscape
// Communications Corporation. Portions created by Netscape are
// Copyright (C) 1998 Netscape Communications Corporation. All
// Rights Reserved.
#include "hash.h"
#include <new>
namespace JS = JavaScript;
//
// Hash Codes
//
// General-purpose null-terminated C string hash function
JS::HashNumber JS::hashString(const char *s)
{
HashNumber h = 0;
uchar ch;
while ((ch = (uchar)*s++) != 0)
h = (h >> 28) ^ (h << 4) ^ ch;
return h;
}
// General-purpose String hash function
JS::HashNumber JS::hashString(const String &s)
{
HashNumber h = 0;
String::const_iterator p = s.begin();
String::size_type n = s.size();
if (n < 16)
// Hash every character in a short string.
while (n--)
h = (h >> 28) ^ (h << 4) ^ *p++;
else
// Sample a la java.lang.String.hash().
for (String::size_type m = n / 8; n >= m; p += m, n -= m)
h = (h >> 28) ^ (h << 4) ^ *p;
return h;
}
//
// Hash Tables
//
const uint minLgNBuckets = 4;
JS::GenericHashTableIterator::GenericHashTableIterator(GenericHashTable &ht):
ht(ht), entry(0), nextBucket(ht.buckets)
{
DEBUG_ONLY(++ht.nReferences);
operator++();
}
JS::GenericHashTableIterator &
JS::GenericHashTableIterator::operator++()
{
GenericHashEntry *e = entry;
if (e) {
backpointer = &e->next;
e = e->next;
}
if (!e) {
GenericHashEntry **const bucketsEnd = ht.bucketsEnd;
GenericHashEntry **bucket = nextBucket;
while (bucket != bucketsEnd) {
e = *bucket++;
if (e) {
backpointer = bucket-1;
break;
}
}
nextBucket = bucket;
}
entry = e;
return *this;
}
JS::GenericHashTable::GenericHashTable(uint32 nEntriesDefault):
nEntries(0)
{
DEBUG_ONLY(nReferences = 0);
uint lgNBuckets = ceilingLog2(nEntriesDefault);
if (lgNBuckets < minLgNBuckets)
lgNBuckets = minLgNBuckets;
defaultLgNBuckets = lgNBuckets;
recomputeMinMaxNEntries(lgNBuckets);
uint32 nBuckets = JS_BIT(lgNBuckets);
buckets = new GenericHashEntry*[nBuckets];
// No exceptions after this point unless buckets is deleted.
bucketsEnd = buckets + nBuckets;
zero(buckets, bucketsEnd);
}
// Initialize shift, minNEntries, and maxNEntries based on the lg2 of the
// number of buckets.
void JS::GenericHashTable::recomputeMinMaxNEntries(uint lgNBuckets)
{
uint32 nBuckets = JS_BIT(lgNBuckets);
shift = 32 - lgNBuckets;
maxNEntries = nBuckets; // Maximum ratio is 100%
minNEntries = lgNBuckets <= defaultLgNBuckets ? 0 : 3*(nBuckets>>3); // Minimum ratio is 37.5%
}
// Rehash the table. This method cannot throw out-of-memory exceptions, so it is
// safe to call from a destructor.
void JS::GenericHashTable::rehash()
{
uint32 newLgNBuckets = ceilingLog2(nEntries);
if (newLgNBuckets < defaultLgNBuckets)
newLgNBuckets = defaultLgNBuckets;
uint32 newNBuckets = JS_BIT(newLgNBuckets);
try {
GenericHashEntry **newBuckets = new GenericHashEntry*[newNBuckets];
// No exceptions after this point.
GenericHashEntry **newBucketsEnd = newBuckets + newNBuckets;
zero(newBuckets, newBucketsEnd);
recomputeMinMaxNEntries(newLgNBuckets);
GenericHashEntry **be = bucketsEnd;
for (GenericHashEntry **b = buckets; b != be; b++) {
GenericHashEntry *e = *b;
while (e) {
GenericHashEntry *next = e->next;
// Place e in the new set of buckets.
GenericHashEntry **nb = newBuckets + (e->keyHash*goldenRatio >> shift);
e->next = *nb;
*nb = e;
e = next;
}
}
delete[] buckets;
buckets = newBuckets;
bucketsEnd = newBucketsEnd;
} catch (std::bad_alloc) {
// Out of memory. Ignore the error and just relax the resizing boundaries.
if (buckets + JS_BIT(newLgNBuckets) > bucketsEnd)
maxNEntries >>= 1;
else
minNEntries <<= 1;
}
}

373
mozilla/js/js2/hash.h Normal file
View File

@@ -0,0 +1,373 @@
// -*- 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.1 (the "License"); you may not use this file
// except in compliance with the License. You may obtain a copy of
// the License at http://www.mozilla.org/NPL/
//
// Software distributed under the License is distributed on an "AS
// IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr
// implied. See the License for the specific language governing
// rights and limitations under the License.
//
// The Original Code is the JavaScript 2 Prototype.
//
// The Initial Developer of the Original Code is Netscape
// Communications Corporation. Portions created by Netscape are
// Copyright (C) 1998 Netscape Communications Corporation. All
// Rights Reserved.
#ifndef hash_h
#define hash_h
#include "utilities.h"
namespace JavaScript {
//
// Hash Codes
//
typedef uint32 HashNumber;
HashNumber hashString(const char *s);
HashNumber hashString(const String &s);
template<class Key>
struct Hash {
HashNumber operator()(Key key) const;
};
template<class Key>
inline HashNumber Hash<Key>::operator()(Key key) const
{
return hashString(key);
}
const HashNumber goldenRatio = 0x9E3779B9U;
//
// Private
//
// Base class for user-defined hash entries.
// private
class GenericHashEntry {
public:
GenericHashEntry *next; // Link to next entry in the same bucket
const HashNumber keyHash; // This entry's hash value
protected:
explicit GenericHashEntry(HashNumber keyHash): next(0), keyHash(keyHash) {}
friend class GenericHashTable;
};
// private
class GenericHashTableIterator;
class GenericHashTable {
protected:
GenericHashEntry **buckets; // Vector of hash buckets
GenericHashEntry **bucketsEnd; // Pointer past end of vector of hash buckets
uint defaultLgNBuckets; // lg2 of minimum number of buckets for which to size the table
uint32 nEntries; // Number of entries in table
uint32 minNEntries; // Minimum number of entries without rehashing
uint32 maxNEntries; // Maximum number of entries without rehashing
uint32 shift; // 32 - lg2(number of buckets)
#ifdef DEBUG
public:
uint32 nReferences; // Number of iterators and references currently pointing to this hash table
#endif
public:
explicit GenericHashTable(uint32 nEntriesDefault);
~GenericHashTable() {
#ifndef _WIN32
ASSERT(nReferences == 0);
#endif
delete[] buckets;
}
void recomputeMinMaxNEntries(uint lgNBuckets);
void rehash();
void maybeGrow() {if (nEntries > maxNEntries) rehash();}
void maybeShrink() {if (nEntries < minNEntries) rehash();}
friend class GenericHashTableIterator;
typedef GenericHashTableIterator Iterator;
};
// This ought to be GenericHashTable::Iterator, but this doesn't work due to a
// Microsoft VC6 bug.
class GenericHashTableIterator {
protected:
GenericHashTable &ht; // Hash table being iterated
GenericHashEntry *entry; // Current entry; nil if done
GenericHashEntry **backpointer; // Pointer to pointer to current entry
GenericHashEntry **nextBucket; // Next bucket; pointer past end of vector of hash buckets if done
public:
explicit GenericHashTableIterator(GenericHashTable &ht);
~GenericHashTableIterator() {ht.maybeShrink(); DEBUG_ONLY(--ht.nReferences);}
operator bool() const {return entry != 0;} // Return true if there are entries left.
GenericHashTableIterator &operator++();
};
//
// Hash Tables
//
template<class Data, class Key, class H = Hash<Key> >
class HashTable: private GenericHashTable {
H hasher; // Hash function
struct Entry: public GenericHashEntry {
Data data;
Entry(HashNumber keyHash, Key key): GenericHashEntry(keyHash), data(key) {}
template<class Value>
Entry(HashNumber keyHash, Key key, Value value): GenericHashEntry(keyHash), data(key, value) {}
};
public:
class Reference {
#ifdef _WIN32 // Microsoft VC6 bug: friend declarations to inner classes don't work
public:
#endif
Entry *entry; // Current entry; nil if done
GenericHashEntry **backpointer; // Pointer to pointer to current entry
const HashNumber keyHash; // This entry's key's hash value
#ifdef DEBUG
GenericHashTable *ht; // Hash table to which this Reference points
#endif
public:
#ifndef _WIN32
Reference(HashTable &ht, Key key); // Search for an entry with the given key.
#else // Microsoft VC6 bug: VC6 doesn't allow this to be defined outside the class
Reference(HashTable &ht, Key key): keyHash(ht.hasher(key)) {
#ifdef DEBUG
Reference::ht = &ht;
++ht.nReferences;
#endif
HashNumber kh = keyHash;
HashNumber h = kh*goldenRatio >> ht.shift;
GenericHashEntry **bp = ht.buckets + h;
Entry *e;
while ((e = static_cast<Entry *>(*bp)) != 0 && !(e->keyHash == kh && e->data == key))
bp = &e->next;
entry = e;
backpointer = bp;
}
#endif
private:
Reference(const Reference&); // No copy constructor
void operator=(const Reference&); // No assignment operator
public:
#if defined(DEBUG) && !defined(_WIN32)
~Reference() {if (ht) --ht->nReferences;}
#endif
operator bool() const {return entry != 0;} // Return true if an entry was found.
Data &operator*() const {ASSERT(entry); return entry->data;} // Return the data of the entry that was found.
friend class HashTable;
};
class Iterator: public GenericHashTableIterator {
public:
explicit Iterator(HashTable &ht): GenericHashTableIterator(ht) {}
private:
Iterator(const Iterator&); // No copy constructor
void operator=(const Iterator&); // No assignment operator
public:
// Go to next entry.
Iterator &operator++() {return *static_cast<Iterator*>(&GenericHashTableIterator::operator++());}
Data &operator*() const {ASSERT(entry); return static_cast<Entry *>(entry)->data;} // Return current entry's data.
void erase();
};
HashTable(uint32 nEntriesDefault = 0, const H &hasher = H()): GenericHashTable(nEntriesDefault), hasher(hasher) {}
~HashTable();
template<class Value> Data &insert(Reference &r, Key key, Value value);
Data &insert(Reference &r, Key key);
Data &insert(Key key);
void erase(Reference &r);
void erase(Key key);
Data *operator[](Key key);
friend class Reference;
friend class Iterator;
#ifndef _WIN32
template<class Value> Data &insert(Key key, Value value);
#else // Microsoft VC6 bug: VC6 doesn't allow this to be defined outside the class
template<class Value> Data &insert(Key key, Value value) {
Reference r(*this, key);
if (r)
return *r = value;
else
return insert(r, key, value);
}
#endif
};
//
// Implementation
//
template<class Data, class Key, class H>
HashTable<Data, Key, H>::~HashTable()
{
GenericHashEntry **be = bucketsEnd;
for (GenericHashEntry **b = buckets; b != be; b++) {
Entry *e = static_cast<Entry *>(*b);
while (e) {
Entry *next = static_cast<Entry *>(e->next);
delete e;
e = next;
}
}
}
#ifndef _WIN32
template<class Data, class Key, class H>
HashTable<Data, Key, H>::Reference::Reference(HashTable &ht, Key key):
keyHash(ht.hasher(key))
{
#ifdef DEBUG
Reference::ht = &ht;
++ht.nReferences;
#endif
HashNumber kh = keyHash;
HashNumber h = kh*goldenRatio >> ht.shift;
GenericHashEntry **bp = ht.buckets + h;
Entry *e;
while ((e = static_cast<Entry *>(*bp)) != 0 && !(e->keyHash == kh && e->data == key))
bp = &e->next;
entry = e;
backpointer = bp;
}
// Insert the given key/value pair into the hash table. Reference must
// be the result of an unsuccessful search for that key in the table.
// The reference is not valid after this method is called.
// Return a reference to the new entry's value.
template<class Data, class Key, class H> template<class Value>
inline Data &HashTable<Data, Key, H>::insert(Reference &r, Key key, Value value)
{
ASSERT(r.ht == this && !r.entry);
Entry *e = new Entry(r.keyHash, key, value);
*r.backpointer = e;
++nEntries;
maybeGrow();
#ifdef DEBUG
--r.ht->nReferences;
r.ht = 0;
#endif
return e->data;
}
#endif
// Same as above but without a Value argument.
template<class Data, class Key, class H>
inline Data &HashTable<Data, Key, H>::insert(Reference &r, Key key)
{
ASSERT(r.ht == this && !r.entry);
Entry *e = new Entry(r.keyHash, key);
*r.backpointer = e;
++nEntries;
maybeGrow();
#ifdef DEBUG
--r.ht->nReferences;
r.ht = 0;
#endif
return e->data;
}
// Insert the given key/value pair into the hash table. If an entry with a
// matching key already exists, replace that entry's value.
// Return a reference to the new entry's value.
#ifndef _WIN32 // Microsoft VC6 bug: VC6 doesn't allow this to be defined outside the class
template<class Data, class Key, class H> template<class Value>
Data &HashTable<Data, Key, H>::insert(Key key, Value value)
{
Reference r(*this, key);
if (r)
return *r = value;
else
return insert(r, key, value);
}
#endif
// Same as above but without a Value argument.
template<class Data, class Key, class H>
Data &HashTable<Data, Key, H>::insert(Key key)
{
Reference r(*this, key);
if (r)
return *r;
else
return insert(r, key);
}
// Reference r must point to an existing entry. Delete that entry.
// The reference is not valid after this method is called.
template<class Data, class Key, class H>
inline void HashTable<Data, Key, H>::erase(Reference &r)
{
Entry *e = r.entry;
ASSERT(r.ht == this && e);
*r.backpointer = e->next;
--nEntries;
delete e;
#ifdef DEBUG
--r.ht->nReferences;
r.ht = 0;
#endif
maybeShrink();
}
// Remove the hash table entry, if any, matching the given key.
template<class Data, class Key, class H>
void HashTable<Data, Key, H>::erase(Key key)
{
Reference r(*this, key);
if (r)
erase(r);
}
// Return a pointer to the value of the hash table entry matching the given key.
// Return nil if no entry matches.
template<class Data, class Key, class H>
Data *HashTable<Data, Key, H>::operator[](Key key)
{
Reference r(*this, key);
if (r)
return &*r;
else
return 0;
}
}
#endif

1104
mozilla/js/js2/icode.h Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,306 @@
/* -*- 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.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is the JavaScript 2 Prototype.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU Public License (the "GPL"), in which case the
* provisions of the GPL are applicable instead of those above.
* If you wish to allow use of your version of this file only
* under the terms of the GPL and not to allow others to use your
* version of this file under the NPL, indicate your decision by
* deleting the provisions above and replace them with the notice
* and other provisions required by the GPL. If you do not delete
* the provisions above, a recipient may use your version of this
* file under either the NPL or the GPL.
*/
#ifndef icodegenerator_h
#define icodegenerator_h
#include <vector>
#include <stack>
#include "utilities.h"
#include "parser.h"
#include "vmtypes.h"
#include "jsclasses.h"
namespace JavaScript {
namespace ICG {
using namespace VM;
using namespace JSTypes;
using namespace JSClasses;
typedef std::map<String, TypedRegister, std::less<String> > VariableList;
typedef std::map<uint32, uint32, std::less<uint32> > InstructionMap;
class ICodeModule {
public:
ICodeModule(InstructionStream *iCode, VariableList *variables,
uint32 maxRegister, uint32 maxParameter,
InstructionMap *instructionMap) :
its_iCode(iCode), itsVariables(variables),
itsParameterCount(maxParameter), itsMaxRegister(maxRegister),
mID(++sMaxID), mInstructionMap(instructionMap) { }
~ICodeModule()
{
delete its_iCode;
delete itsVariables;
delete mInstructionMap;
}
Formatter& print(Formatter& f);
void setFileName (String aFileName) { mFileName = aFileName; }
String getFileName () { return mFileName; }
InstructionStream *its_iCode;
VariableList *itsVariables;
uint32 itsParameterCount;
uint32 itsMaxRegister;
uint32 mID;
InstructionMap *mInstructionMap;
String mFileName;
static uint32 sMaxID;
};
typedef std::vector<const StringAtom *> LabelSet;
class LabelEntry {
public:
LabelEntry(LabelSet *labelSet, Label *breakLabel)
: labelSet(labelSet), breakLabel(breakLabel), continueLabel(NULL) { }
LabelEntry(LabelSet *labelSet, Label *breakLabel, Label *continueLabel)
: labelSet(labelSet), breakLabel(breakLabel), continueLabel(continueLabel) { }
bool containsLabel(const StringAtom *label);
LabelSet *labelSet;
Label *breakLabel;
Label *continueLabel;
};
typedef std::vector<LabelEntry *> LabelStack;
Formatter& operator<<(Formatter &f, ICodeModule &i);
/****************************************************************/
// An ICodeGenerator provides the interface between the parser and the
// interpreter. The parser constructs one of these for each
// function/script, adds statements and expressions to it and then
// converts it into an ICodeModule, ready for execution.
class ICodeGenerator {
public:
typedef enum { kNoFlags = 0, kIsTopLevel = 0x01, kIsStaticMethod = 0x02, kIsWithinWith = 0x04 } ICodeGeneratorFlags;
private:
InstructionStream *iCode;
bool iCodeOwner;
LabelList labels;
Register mTopRegister; // highest (currently) alloacated register
uint32 mParameterCount; // number of parameters declared for the function
// these must come before any variables declared.
TypedRegister mExceptionRegister; // reserved to carry the exception object.
VariableList *variableList; // name|register pair for each variable
World *mWorld; // used to register strings
JSScope *mGlobal; // the scope for compiling within
LabelStack mLabelStack; // stack of LabelEntry objects, one per nested looping construct
// maps source position to instruction index
InstructionMap *mInstructionMap;
JSClass *mClass; // enclosing class when generating code for methods
ICodeGeneratorFlags mFlags; // assorted flags
std::vector<bool> mPermanentRegister;
Register getTempRegister()
{
while (mTopRegister < mPermanentRegister.size())
if (!mPermanentRegister[mTopRegister])
return mTopRegister++;
else
++mTopRegister;
mPermanentRegister.resize(mTopRegister + 1);
mPermanentRegister[mTopRegister] = false;
return mTopRegister++;
}
void resetTopRegister() { mTopRegister = mParameterCount; }
void resetStatement() { resetTopRegister(); }
TypedRegister allocateRegister(const StringAtom& name, JSType *type);
void setRegisterForVariable(const StringAtom& name, TypedRegister r) { (*variableList)[name] = r; }
JSType *findType(const StringAtom& typeName);
void setLabel(Label *label);
void jsr(Label *label) { iCode->push_back(new Jsr(label)); }
void rts() { iCode->push_back(new Rts()); }
void branch(Label *label);
GenericBranch *branchTrue(Label *label, TypedRegister condition);
GenericBranch *branchFalse(Label *label, TypedRegister condition);
void beginTry(Label *catchLabel, Label *finallyLabel)
{ iCode->push_back(new Tryin(catchLabel, finallyLabel)); }
void endTry() { iCode->push_back(new Tryout()); }
void beginWith(TypedRegister obj) { iCode->push_back(new Within(obj)); }
void endWith() { iCode->push_back(new Without()); }
void startStatement(uint32 pos) { (*mInstructionMap)[iCode->size()] = pos; }
ICodeOp mapExprNodeToICodeOp(ExprNode::Kind kind);
bool isTopLevel() { return (mFlags & kIsTopLevel) != 0; }
bool isWithinWith() { return (mFlags & kIsWithinWith) != 0; }
bool isStaticMethod() { return (mFlags & kIsStaticMethod) != 0; }
void setFlag(uint32 flag, bool v) { mFlags = (ICodeGeneratorFlags)((v) ? mFlags | flag : mFlags & ~flag); }
typedef enum {Var, Property, Slot, Static, Constructor, Name, Method} LValueKind;
LValueKind resolveIdentifier(const StringAtom &name, TypedRegister &v, uint32 &slotIndex);
TypedRegister handleIdentifier(IdentifierExprNode *p, ExprNode::Kind use, ICodeOp xcrementOp, TypedRegister ret, RegisterList *args);
TypedRegister handleDot(BinaryExprNode *b, ExprNode::Kind use, ICodeOp xcrementOp, TypedRegister ret, RegisterList *args);
ICodeModule *genFunction(FunctionStmtNode *f, bool isConstructor, JSClass *superClass);
public:
ICodeGenerator(World *world, JSScope *global, JSClass *aClass = NULL, ICodeGeneratorFlags flags = kIsTopLevel);
~ICodeGenerator()
{
if (iCodeOwner) {
delete iCode;
delete mInstructionMap;
}
}
ICodeModule *complete();
TypedRegister genExpr(ExprNode *p,
bool needBoolValueInBranch = false,
Label *trueBranch = NULL,
Label *falseBranch = NULL);
TypedRegister genStmt(StmtNode *p, LabelSet *currentLabelSet = NULL);
void returnStmt(TypedRegister r);
void returnStmt();
void throwStmt(TypedRegister r) { iCode->push_back(new Throw(r)); }
void debuggerStmt() { iCode->push_back(new Debugger()); }
TypedRegister allocateVariable(const StringAtom& name);
TypedRegister allocateVariable(const StringAtom& name, const StringAtom& typeName);
TypedRegister findVariable(const StringAtom& name)
{
VariableList::iterator i = variableList->find(name);
return (i == variableList->end()) ? TypedRegister(NotARegister, &None_Type) : (*i).second;
}
TypedRegister allocateParameter(const StringAtom& name) { mParameterCount++; return allocateRegister(name, &Any_Type); }
TypedRegister allocateParameter(const StringAtom& name, const StringAtom& typeName)
{ mParameterCount++; return allocateRegister(name, findType(typeName)); }
TypedRegister allocateParameter(const StringAtom& name, JSType *type)
{ mParameterCount++; return allocateRegister(name, type); }
Formatter& print(Formatter& f);
TypedRegister op(ICodeOp op, TypedRegister source);
TypedRegister op(ICodeOp op, TypedRegister source1, TypedRegister source2);
TypedRegister binaryOp(ICodeOp op, TypedRegister source1, TypedRegister source2);
TypedRegister call(TypedRegister base, TypedRegister target, RegisterList *args);
TypedRegister getMethod(TypedRegister thisArg, uint32 slotIndex);
void move(TypedRegister destination, TypedRegister source);
TypedRegister logicalNot(TypedRegister source);
TypedRegister test(TypedRegister source);
TypedRegister loadBoolean(bool value);
TypedRegister loadImmediate(double value);
TypedRegister loadString(const String &value);
TypedRegister loadString(const StringAtom &name);
TypedRegister newObject(TypedRegister constructor);
TypedRegister newArray();
TypedRegister newFunction(ICodeModule *icm);
TypedRegister newClass(JSClass *clazz);
TypedRegister cast(TypedRegister arg, JSType *toType);
TypedRegister super();
TypedRegister loadName(const StringAtom &name, JSType *t = &Any_Type);
void saveName(const StringAtom &name, TypedRegister value);
TypedRegister nameXcr(const StringAtom &name, ICodeOp op);
TypedRegister deleteProperty(TypedRegister base, const StringAtom &name);
TypedRegister getProperty(TypedRegister base, const StringAtom &name);
void setProperty(TypedRegister base, const StringAtom &name, TypedRegister value);
TypedRegister propertyXcr(TypedRegister base, const StringAtom &name, ICodeOp op);
TypedRegister getStatic(JSClass *base, const String &name);
void setStatic(JSClass *base, const StringAtom &name, TypedRegister value);
TypedRegister staticXcr(JSClass *base, const StringAtom &name, ICodeOp op);
TypedRegister getElement(TypedRegister base, TypedRegister index);
void setElement(TypedRegister base, TypedRegister index, TypedRegister value);
TypedRegister elementXcr(TypedRegister base, TypedRegister index, ICodeOp op);
TypedRegister getSlot(TypedRegister base, uint32 slot);
void setSlot(TypedRegister base, uint32 slot, TypedRegister value);
TypedRegister slotXcr(TypedRegister base, uint32 slot, ICodeOp op);
TypedRegister varXcr(TypedRegister var, ICodeOp op);
InstructionStream *getICode() { return iCode; }
Label *getLabel();
};
Formatter& operator<<(Formatter &f, ICodeGenerator &i);
Formatter& operator<<(Formatter &f, ICodeModule &i);
/*
std::ostream &operator<<(std::ostream &s, ICodeGenerator &i);
std::ostream &operator<<(std::ostream &s, StringAtom &str);
*/
} /* namespace IGC */
} /* namespace JavaScript */
#endif /* icodegenerator_h */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,113 @@
// -*- 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.1 (the "License"); you may not use this file
// except in compliance with the License. You may obtain a copy of
// the License at http://www.mozilla.org/NPL/
//
// Software distributed under the License is distributed on an "AS
// IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr
// implied. See the License for the specific language governing
// rights and limitations under the License.
//
// The Original Code is the JavaScript 2 Prototype.
//
// The Initial Developer of the Original Code is Netscape
// Communications Corporation. Portions created by Netscape are
// Copyright (C) 2000 Netscape Communications Corporation. All
// Rights Reserved.
#ifndef interpreter_h
#define interpreter_h
#include "utilities.h"
#include "jstypes.h"
#include "vmtypes.h"
#include "icodegenerator.h"
#include "gc_allocator.h"
namespace JavaScript {
namespace Interpreter {
using namespace ICG;
using namespace JSTypes;
struct Activation;
struct Linkage;
class Context : public gc_base {
void initContext();
public:
explicit Context(World& world, JSScope* aGlobal)
: mWorld(world), mGlobal(aGlobal), mLinkage(0), mActivation(0), mHasOperatorsPackageLoaded(false) { initContext(); }
World& getWorld() { return mWorld; }
JSScope* getGlobalObject() { return mGlobal; }
InstructionIterator getPC() { return mPC; }
JSValues& getRegisters();
ICodeModule* getICode();
enum Event {
EV_NONE = 0x0000,
EV_STEP = 0x0001,
EV_THROW = 0x0002,
EV_DEBUG = 0x0004,
EV_ALL = 0xffff
};
class Listener {
public:
virtual void listen(Context *context, Event event) = 0;
};
void addListener(Listener* listener);
void removeListener(Listener* listener);
class Frame {
public:
virtual Frame* getNext() = 0;
virtual void getState(InstructionIterator& pc, JSValues*& registers,
ICodeModule*& iCode) = 0;
};
Frame* getFrames();
JSValue interpret(ICodeModule* iCode, const JSValues& args);
void doCall(JSFunction *target, Instruction *pc);
ICodeModule* compile(const String &source);
ICodeModule* genCode(StmtNode *p, const String &fileName);
JSValue readEvalFile(FILE* in, const String& fileName);
void addBinaryOperator(BinaryOperator::BinaryOp op, BinaryOperator *fn) { mBinaryOperators[op].push_back(fn); }
const JSValue findBinaryOverride(JSValue &operand1, JSValue &operand2, BinaryOperator::BinaryOp op);
bool hasOperatorsPackageLoaded() { return mHasOperatorsPackageLoaded; }
private:
void broadcast(Event event);
void initOperatorsPackage();
private:
World& mWorld;
JSScope* mGlobal;
Linkage* mLinkage;
typedef std::vector<Listener*, gc_allocator<Listener*> > ListenerList;
typedef ListenerList::iterator ListenerIterator;
ListenerList mListeners;
Activation* mActivation;
bool mHasOperatorsPackageLoaded;
InstructionIterator mPC;
BinaryOperatorList mBinaryOperators[BinaryOperator::BinaryOperatorCount];
}; /* class Context */
} /* namespace Interpreter */
} /* namespace JavaScript */
#endif /* interpreter_h */

View File

@@ -0,0 +1,33 @@
class ArithmeticNode extends BinaryNode {
ArithmeticNode(String aOp, ExpressionNode aLeft, ExpressionNode aRight)
{
super(aOp, aLeft, aRight);
}
JSValue eval(Environment theEnv)
{
JSValue lV = left.eval(theEnv);
JSValue rV = right.eval(theEnv);
if (op == "+")
return lV.add(theEnv, rV);
else
if (op == "-")
return lV.subtract(theEnv, rV);
else
if (op == "*")
return lV.multiply(theEnv, rV);
else
if (op == "/")
return lV.divide(theEnv, rV);
else
if (op == "%")
return lV.remainder(theEnv, rV);
else {
System.out.println("missing arithmetic op " + op);
return null;
}
}
}

View File

@@ -0,0 +1,16 @@
class AssignmentNode extends BinaryNode {
AssignmentNode(String aOp, ExpressionNode aLeft, ExpressionNode aRight)
{
super(aOp, aLeft, aRight);
}
JSValue eval(Environment theEnv)
{
JSReference lV = left.evalLHS(theEnv);
JSValue rV = right.eval(theEnv);
return lV.base.putProp(theEnv, lV.id, rV);
}
}

View File

@@ -0,0 +1,72 @@
class BinaryNode extends ExpressionNode {
BinaryNode(String aOp, ExpressionNode aLeft, ExpressionNode aRight)
{
left = aLeft;
right = aRight;
op = aOp;
}
JSReference evalLHS(Environment theEnv)
{
if (op == ".") {
JSValue lV = left.eval(theEnv);
JSString id;
if (right instanceof JSIdentifier)
id = (JSString)right;
else
id = right.eval(theEnv).toJSString(theEnv);
return new JSReference(lV, id);
}
else
throw new RuntimeException("bad lValue operator " + op);
}
JSValue eval(Environment theEnv)
{
JSValue lV = left.eval(theEnv);
JSValue rV = right.eval(theEnv);
if (op == ".")
return lV.getProp(theEnv, rV.toJSString(theEnv));
else
if (op == "()")
return lV.call(theEnv, rV);
else
if (op == ",")
return JSValueList.buildList(lV, rV);
else {
System.out.println("missing binary op " + op);
return null;
}
}
String print(String indent)
{
StringBuffer result = new StringBuffer(indent);
result.append(getClass().toString());
result.append(" ");
result.append(op);
result.append("\n");
indent += " ";
if (left == null) {
result.append(indent);
result.append("null\n");
}
else
result.append(left.print(indent));
if (right == null) {
result.append(indent);
result.append("null\n");
}
else
result.append(right.print(indent));
return result.toString();
}
protected ExpressionNode left;
protected ExpressionNode right;
protected String op;
}

View File

@@ -0,0 +1,36 @@
class BitwiseNode extends BinaryNode {
BitwiseNode(String aOp, ExpressionNode aLeft, ExpressionNode aRight)
{
super(aOp, aLeft, aRight);
}
JSValue eval(Environment theEnv)
{
JSInteger lV = left.eval(theEnv).toJSInteger(theEnv);
JSValue rV = right.eval(theEnv);
if (op == "&")
return lV.and(theEnv, rV);
else
if (op == "|")
return lV.or(theEnv, rV);
else
if (op == "^")
return lV.xor(theEnv, rV);
else
if (op == "<<")
return lV.shr(theEnv, rV);
else
if (op == ">>")
return lV.shl(theEnv, rV);
else
if (op == ">>>")
return lV.ushl(theEnv, rV);
else {
System.out.println("missing bitwise op " + op);
return null;
}
}
}

View File

@@ -0,0 +1,24 @@
import java.io.*;
class Brenda {
public static void main(String[] args) {
try {
JSLexer lexer = new JSLexer((args != null) ? new DataInputStream(new FileInputStream(args[0])) : new DataInputStream(System.in));
JSParser parser = new JSParser(lexer);
ControlNodeGroup tree = new ControlNodeGroup();
parser.statements(0, tree);
System.out.println(ControlNode.printAll());
Environment theEnv = new Environment();
ControlNode c = tree.getHead();
while (c != null) c = c.eval(theEnv);
System.out.println("After eval :\n" + theEnv.print());
} catch(Exception e) {
System.err.println("exception: "+e);
}
}
}

View File

@@ -0,0 +1,59 @@
class ConditionalNode extends ControlNode {
ConditionalNode(ExpressionNode aCondition)
{
super(aCondition);
}
ConditionalNode(ExpressionNode aCondition, ControlNode aTrueCode)
{
super(aCondition);
trueCode = aTrueCode;
}
ConditionalNode(ExpressionNode aCondition, ControlNode aTrueCode, ControlNode aFalseCode)
{
super(aCondition);
trueCode = aTrueCode;
setNext(aFalseCode);
}
void moveNextToTrue()
{
trueCode = next;
setNext(null);
}
ControlNode eval(Environment theEnv)
{
JSBoolean b = expr.eval(theEnv).toJSBoolean(theEnv);
if (b.isTrue())
return trueCode;
else
return next;
}
String print()
{
StringBuffer result = new StringBuffer("ConditionalNode ");
result.append(index);
result.append("\nexpr:\n");
if (expr == null)
result.append("expr = null\n");
else
result.append(expr.print(""));
result.append("true branch:\n");
if (trueCode == null)
result.append("true branch = null\n");
else
result.append("true branch->" + trueCode.index + "\n");
result.append("false branch:\n");
if (next == null)
result.append("false branch = null\n");
else
result.append("false branch->" + next.index + "\n");
return result.toString();
}
protected ControlNode trueCode;
}

View File

@@ -0,0 +1,67 @@
import java.util.Vector;
class ControlNode {
private static Vector gList = new Vector();
static String printAll()
{
StringBuffer result = new StringBuffer();
for (int i = 0; i < gList.size(); i++) {
result.append(((ControlNode)(gList.elementAt(i))).print());
}
return result.toString();
}
ControlNode(ExpressionNode anExpr)
{
expr = anExpr;
index = gList.size();
gList.addElement(this);
}
ExpressionNode getExpression()
{
return expr;
}
void setNext(ControlNode aNext)
{
next = aNext;
}
ControlNode eval(Environment theEnv)
{
if (expr != null) theEnv.resultValue = expr.eval(theEnv);
return next;
}
String print()
{
StringBuffer result = new StringBuffer(getClass().toString().substring(6));
result.append(" #");
result.append(index);
result.append("\nexpr: \n");
if (expr == null)
result.append("expr = null\n");
else
result.append(expr.print(""));
result.append("next: ");
if (next == null)
result.append("next = null\n");
else
result.append("next->" + next.index + "\n");
return result.toString();
}
protected ExpressionNode expr;
protected ControlNode next;
protected int index;
}

View File

@@ -0,0 +1,153 @@
import java.util.Vector;
class ControlNodeGroup {
ControlNodeGroup()
{
}
ControlNodeGroup(ControlNode aHead)
{
head = aHead;
}
void add(ControlNodeGroup aGroup)
{
if (head == null) {
head = aGroup.head;
}
else {
fixTails(aGroup.getHead());
}
addTails(aGroup);
}
void add(ControlNode aNode)
{
fixTails(aNode);
addTail(aNode);
if (head == null) head = aNode;
}
void addBreak(ControlNode aNode)
{
fixTails(aNode);
addBreakTail(aNode);
if (head == null) head = aNode;
}
void addContinue(ControlNode aNode)
{
fixTails(aNode);
addContinueTail(aNode);
if (head == null) head = aNode;
}
void fixTails(ControlNode butt)
{
int count = tails.size();
for (int i = 0; i < count; i++)
{
ControlNode aNode = (ControlNode)(tails.elementAt(i));
aNode.setNext(butt);
}
tails.removeAllElements();
}
void fixContinues(ControlNode butt, String label)
{
int count = continueTails.size();
int i = 0;
while (i < count) {
ControlNode c = (ControlNode)(continueTails.elementAt(i));
ExpressionNode e = c.getExpression();
String tgt = (e == null) ? null : ((JSIdentifier)e).s;
if ((tgt == null) || tgt.equals(label)) {
c.setNext(butt);
continueTails.removeElementAt(i);
count--;
}
else
i++;
}
}
void setHead(ControlNode aHead)
{
head = aHead;
}
ControlNode getHead()
{
return head;
}
void addTail(ControlNode aTail)
{
tails.addElement(aTail);
}
void addBreakTail(ControlNode aTail)
{
breakTails.addElement(aTail);
}
void addContinueTail(ControlNode aTail)
{
continueTails.addElement(aTail);
}
void removeTail(ControlNode aTail)
{
tails.removeElement(aTail);
}
void addTails(ControlNodeGroup aGroup)
{
int count = aGroup.tails.size();
for (int i = 0; i < count; i++)
{
tails.addElement(aGroup.tails.elementAt(i));
}
aGroup.tails.removeAllElements();
count = aGroup.breakTails.size();
for (int i = 0; i < count; i++)
{
breakTails.addElement(aGroup.breakTails.elementAt(i));
}
aGroup.breakTails.removeAllElements();
count = aGroup.continueTails.size();
for (int i = 0; i < count; i++)
{
continueTails.addElement(aGroup.continueTails.elementAt(i));
}
aGroup.continueTails.removeAllElements();
}
void shiftBreakTails(String label)
{
int count = breakTails.size();
int i = 0;
while (i < count) {
ControlNode c = (ControlNode)(breakTails.elementAt(i));
ExpressionNode e = c.getExpression();
String tgt = (e == null) ? null : ((JSIdentifier)e).s;
if ((tgt == null) || tgt.equals(label)) {
tails.addElement(c);
breakTails.removeElementAt(i);
count--;
}
else
i++;
}
}
ControlNode head;
Vector tails = new Vector();
Vector breakTails = new Vector();
Vector continueTails = new Vector();
}

View File

@@ -0,0 +1,30 @@
import java.util.Hashtable;
class Environment {
JSScope scope = new JSScope("globals");
JSScope globalScope = scope;
void enterNewScope(JSScope newScope)
{
newScope.parent = scope;
scope = newScope;
}
void leaveScope()
{
scope = scope.parent;
}
String print()
{
StringBuffer result = new StringBuffer("Globals contents :\n");
result.append(scope.toString());
return result.toString();
}
JSValue resultValue;
}

View File

@@ -0,0 +1,24 @@
class ExpressionNode {
ExpressionNode()
{
}
String print(String indent)
{
return indent + "ExpressionNode(" + getClass().toString() + ")\n";
}
JSReference evalLHS(Environment theEnv)
{
System.out.println("Unimplemented evalLHS for " + print(""));
return null;
}
JSValue eval(Environment theEnv)
{
System.out.println("Unimplemented eval for " + print(""));
return null;
}
}

View File

@@ -0,0 +1,36 @@
class FunctionNode extends ExpressionNode {
FunctionNode(JSIdentifier aName, ControlNodeGroup aBody, ExpressionNode parameterList)
{
fn = new NativeFunction(aBody.getHead());
name = aName;
if (parameterList != null) {
if (parameterList instanceof BinaryNode)
buildParameterVector((BinaryNode)parameterList);
else
fn.parameters.addElement(parameterList);
}
}
void buildParameterVector(BinaryNode x)
{
if (x.left instanceof BinaryNode) {
buildParameterVector((BinaryNode)(x.left));
fn.parameters.addElement(x.right);
}
else {
fn.parameters.addElement(x.left);
fn.parameters.addElement(x.right);
}
}
JSValue eval(Environment theEnv)
{
theEnv.scope.putProp(theEnv, name, fn);
return fn;
}
JSString name;
NativeFunction fn;
}

View File

@@ -0,0 +1,52 @@
class JSBoolean extends JSValue {
static JSBoolean JSTrue = new JSBoolean(true);
static JSBoolean JSFalse = new JSBoolean(false);
private JSBoolean(boolean p)
{
b = p;
}
JSValue eval(Environment theEnv)
{
return this;
}
boolean isTrue()
{
return b;
}
boolean isFalse()
{
return !b;
}
JSValue bang(Environment theEnv) {
return (b) ? JSFalse : JSTrue;
}
JSValue typeof(Environment theEnv) {
return new JSString("boolean");
}
JSBoolean toJSBoolean(Environment theEnv) {
return this;
}
JSValue toPrimitive(Environment theEnv, String hint) {
return this;
}
JSString toJSString(Environment theEnv) {
return (b) ? new JSString("true") : new JSString("false");
}
JSDouble toJSDouble(Environment theEnv) {
return (b) ? new JSDouble(1) : new JSDouble(0);
}
boolean b;
}

View File

@@ -0,0 +1,111 @@
class JSDouble extends JSNumber {
JSDouble(double p)
{
d = p;
}
JSDouble(String s)
{
d = new Double(s).doubleValue();
}
String print(String indent)
{
return indent + "JSDouble " + d + "\n";
}
public String toString()
{
return Double.toString(d);
}
JSValue eval(Environment theEnv)
{
return this;
}
JSValue plus(Environment theEnv) {
return this;
}
JSValue minus(Environment theEnv) {
return new JSDouble(-d);
}
JSValue add(Environment theEnv, JSValue rV) {
if (rV instanceof JSString)
return toJSString(theEnv).add(theEnv, rV);
else
return new JSDouble(d + rV.toJSDouble(theEnv).d);
}
JSValue subtract(Environment theEnv, JSValue rV) {
return new JSDouble(d - rV.toJSDouble(theEnv).d);
}
JSValue multiply(Environment theEnv, JSValue rV) {
return new JSDouble(d * rV.toJSDouble(theEnv).d);
}
JSValue divide(Environment theEnv, JSValue rV) {
return new JSDouble(d / rV.toJSDouble(theEnv).d);
}
JSValue remainder(Environment theEnv, JSValue rV) {
return new JSDouble(d % rV.toJSDouble(theEnv).d);
}
JSValue gt(Environment theEnv, JSValue rV) {
return (d > rV.toJSDouble(theEnv).d) ? JSBoolean.JSTrue : JSBoolean.JSFalse;
}
JSValue ge(Environment theEnv, JSValue rV) {
return (d >= rV.toJSDouble(theEnv).d) ? JSBoolean.JSTrue : JSBoolean.JSFalse;
}
JSValue lt(Environment theEnv, JSValue rV) {
return (d < rV.toJSDouble(theEnv).d) ? JSBoolean.JSTrue : JSBoolean.JSFalse;
}
JSValue le(Environment theEnv, JSValue rV) {
return (d <= rV.toJSDouble(theEnv).d) ? JSBoolean.JSTrue : JSBoolean.JSFalse;
}
JSValue eq(Environment theEnv, JSValue rV) {
return (d == rV.toJSDouble(theEnv).d) ? JSBoolean.JSTrue : JSBoolean.JSFalse;
}
JSValue ne(Environment theEnv, JSValue rV) {
return (d != rV.toJSDouble(theEnv).d) ? JSBoolean.JSTrue : JSBoolean.JSFalse;
}
JSDouble toJSDouble(Environment theEnv) {
return this;
}
JSValue toPrimitive(Environment theEnv, String hint) {
return this;
}
JSInteger toJSInteger(Environment theEnv) {
return new JSInteger((int)d);
}
JSBoolean toJSBoolean(Environment theEnv) {
return ((d == d) && (d != 0.0)) ? JSBoolean.JSTrue : JSBoolean.JSFalse;
}
JSString toJSString(Environment theEnv) {
return new JSString(Double.toString(d));
}
JSObject toJSObject(Environment theEnv) {
return new NativeNumber(d);
}
double d;
}

View File

@@ -0,0 +1,22 @@
class JSException extends RuntimeException {
JSException(JSValue x)
{
value = x;
}
JSValue getValue()
{
return value;
}
public String toString()
{
return value.toJSString(null).s;
}
JSValue value;
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,23 @@
class JSIdentifier extends JSString {
JSIdentifier(String s)
{
super(s);
}
String print(String indent)
{
return indent + "JSIdentifier : " + s + "\n";
}
JSValue eval(Environment theEnv)
{
return theEnv.scope.getProp(theEnv, this);
}
JSReference evalLHS(Environment theEnv)
{
return new JSReference(theEnv.scope, this);
}
}

View File

@@ -0,0 +1,68 @@
class JSInteger extends JSNumber {
JSInteger(String s)
{
i = new Integer(s).intValue();
}
JSInteger(int p)
{
i = p;
}
JSValue eval(Environment theEnv)
{
return this;
}
JSBoolean toJSBoolean(Environment theEnv) {
return (i != 0) ? JSBoolean.JSTrue : JSBoolean.JSFalse;
}
JSDouble toJSDouble(Environment theEnv) {
return new JSDouble(i);
}
JSInteger toJSInteger(Environment theEnv) {
return this;
}
JSValue toPrimitive(Environment theEnv, String hint) {
return this;
}
JSString toJSString(Environment theEnv) {
return new JSString(Integer.toString(i));
}
JSValue twiddle(Environment theEnv) {
return new JSInteger(~i);
}
JSValue and(Environment theEnv, JSValue rV) {
return new JSInteger(i & rV.toJSInteger(theEnv).i);
}
JSValue or(Environment theEnv, JSValue rV) {
return new JSInteger(i | rV.toJSInteger(theEnv).i);
}
JSValue xor(Environment theEnv, JSValue rV) {
return new JSInteger(i ^ rV.toJSInteger(theEnv).i);
}
JSValue shl(Environment theEnv, JSValue rV) {
return new JSInteger(i >> rV.toJSInteger(theEnv).i);
}
JSValue shr(Environment theEnv, JSValue rV) {
return new JSInteger(i << rV.toJSInteger(theEnv).i);
}
JSValue ushl(Environment theEnv, JSValue rV) {
return new JSInteger(i >>> rV.toJSInteger(theEnv).i);
}
int i;
}

View File

@@ -0,0 +1,41 @@
class JSName extends ExpressionNode {
JSName(JSIdentifier anID, int aScope)
{
id = anID;
scope = aScope; // this is the scope that the name was used in
}
String print(String indent)
{
return indent + "JSName : " + id.s + ", scope : " + scope + "\n";
}
JSReference evalLHS(Environment theEnv)
{
JSScope scope = theEnv.scope;
while (scope != null) {
if (scope.hasProp(theEnv, id))
return new JSReference(scope, id);
else
scope = scope.parent;
}
return new JSReference(theEnv.globalScope, id);
}
JSValue eval(Environment theEnv)
{
JSScope scope = theEnv.scope;
while (scope != null) {
if (scope.hasProp(theEnv, id))
return scope.getProp(theEnv, id);
else
scope = scope.parent;
}
throw new JSException(new JSString(id.s + " undefined"));
}
JSIdentifier id;
int scope;
}

View File

@@ -0,0 +1,8 @@
abstract class JSNumber extends JSValue {
JSValue typeof(Environment theEnv) {
return new JSString("number");
}
}

View File

@@ -0,0 +1,84 @@
import java.util.Hashtable;
class JSObject extends JSValue {
static JSObject objectPrototype = new JSObject("Object");
static JSObject JSUndefined = new JSObject("undefined");
JSObject(String aClass)
{
oClass = aClass;
prototype = objectPrototype;
}
void setPrototype(JSObject aPrototype)
{
prototype = aPrototype;
}
String print(String indent)
{
return indent + "JSObject : " + oClass + "\n";
}
public String toString() {
return oClass + contents.toString();
}
JSValue eval(Environment theEnv)
{
return this;
}
JSValue typeof(Environment theEnv) {
if (this == JSUndefined)
return new JSString("undefined");
else
return new JSString("object");
}
JSBoolean toJSBoolean(Environment theEnv) {
return JSBoolean.JSTrue;
}
JSDouble toJSDouble(Environment theEnv) {
return toPrimitive(theEnv, "Number").toJSDouble(theEnv);
}
JSValue getProp(Environment theEnv, JSString id)
{
Object v = contents.get(id.s);
if (v == null)
if (prototype == null)
return JSUndefined;
else
return prototype.getProp(theEnv, id);
else
return (JSValue)v;
}
boolean hasProp(Environment theEnv, JSString id)
{
Object v = contents.get(id.s);
if (v == null)
if (prototype == null)
return false;
else
return prototype.hasProp(theEnv, id);
else
return true;
}
JSValue putProp(Environment theEnv, JSString id, JSValue rV) {
contents.put(id.s, rV);
return rV;
}
Hashtable contents = new Hashtable();
String oClass;
JSObject prototype;
}

View File

@@ -0,0 +1,12 @@
class JSReference {
JSReference(JSValue aBase, JSString aID)
{
base = aBase;
id = aID;
}
JSValue base;
JSString id;
}

View File

@@ -0,0 +1,10 @@
class JSScope extends JSObject {
JSScope(String s)
{
super(s);
}
JSScope parent;
}

View File

@@ -0,0 +1,83 @@
class JSString extends JSValue {
JSString(String p)
{
s = p;
}
JSValue eval(Environment theEnv)
{
return this;
}
JSValue typeof(Environment theEnv) {
return new JSString("string");
}
JSValue add(Environment theEnv, JSValue rV)
{
return new JSString(s + rV.toJSString(theEnv).s);
}
JSValue gt(Environment theEnv, JSValue rV) {
if (rV instanceof JSString)
return (s.compareTo(rV.toJSString(theEnv).s) == 1) ? JSBoolean.JSTrue : JSBoolean.JSFalse;
else
return toJSDouble(theEnv).gt(theEnv, rV);
}
JSValue ge(Environment theEnv, JSValue rV) {
if (rV instanceof JSString)
return (s.compareTo(rV.toJSString(theEnv).s) != -1) ? JSBoolean.JSTrue : JSBoolean.JSFalse;
else
return toJSDouble(theEnv).ge(theEnv, rV);
}
JSValue lt(Environment theEnv, JSValue rV) {
if (rV instanceof JSString)
return (s.compareTo(rV.toJSString(theEnv).s) == -1) ? JSBoolean.JSTrue : JSBoolean.JSFalse;
else
return toJSDouble(theEnv).lt(theEnv, rV);
}
JSValue le(Environment theEnv, JSValue rV) {
if (rV instanceof JSString)
return (s.compareTo(rV.toJSString(theEnv).s) != 1) ? JSBoolean.JSTrue : JSBoolean.JSFalse;
else
return toJSDouble(theEnv).le(theEnv, rV);
}
JSValue eq(Environment theEnv, JSValue rV) {
if (rV instanceof JSString)
return (s.compareTo(rV.toJSString(theEnv).s) == 0) ? JSBoolean.JSTrue : JSBoolean.JSFalse;
else
return toJSDouble(theEnv).eq(theEnv, rV);
}
JSValue ne(Environment theEnv, JSValue rV) {
if (rV instanceof JSString)
return (s.compareTo(rV.toJSString(theEnv).s) != 0) ? JSBoolean.JSTrue : JSBoolean.JSFalse;
else
return toJSDouble(theEnv).ne(theEnv, rV);
}
JSDouble toJSDouble(Environment theEnv) {
return new JSDouble(s); // XXX Way More To Do, see Rhino ScriptRuntime.java
}
JSString toJSString(Environment theEnv) {
return this;
}
JSValue toPrimitive(Environment theEnv, String hint) {
return this;
}
String print(String indent)
{
return indent + "JSString : " + s + "\n";
}
protected String s;
}

View File

@@ -0,0 +1,222 @@
class JSValue extends ExpressionNode {
String print(String indent)
{
return indent + "JSValue\n";
}
JSReference evalLHS(Environment theEnv)
{
throw new RuntimeException("EvalLHS on non-lvalue");
}
JSValue eval(Environment theEnv)
{
throw new RuntimeException("Eval on JSValue");
}
JSValue unimplemented(String op)
{
throw new RuntimeException("unimplemented " + op + " called");
}
JSValue gt(Environment theEnv, JSValue rV) {
JSValue lV = toPrimitive(theEnv, "Number");
rV = rV.toPrimitive(theEnv, "Number");
if ((lV instanceof JSString) && (rV instanceof JSString))
return lV.gt(theEnv, rV);
else
return lV.toJSDouble(theEnv).gt(theEnv, rV.toJSDouble(theEnv));
}
JSValue ge(Environment theEnv, JSValue rV) {
JSValue lV = toPrimitive(theEnv, "Number");
rV = rV.toPrimitive(theEnv, "Number");
if ((lV instanceof JSString) && (rV instanceof JSString))
return lV.ge(theEnv, rV);
else
return lV.toJSDouble(theEnv).ge(theEnv, rV.toJSDouble(theEnv));
}
JSValue lt(Environment theEnv, JSValue rV) {
JSValue lV = toPrimitive(theEnv, "Number");
rV = rV.toPrimitive(theEnv, "Number");
if ((lV instanceof JSString) && (rV instanceof JSString))
return lV.lt(theEnv, rV);
else
return lV.toJSDouble(theEnv).lt(theEnv, rV.toJSDouble(theEnv));
}
JSValue le(Environment theEnv, JSValue rV) {
JSValue lV = toPrimitive(theEnv, "Number");
rV = rV.toPrimitive(theEnv, "Number");
if ((lV instanceof JSString) && (rV instanceof JSString))
return lV.le(theEnv, rV);
else
return lV.toJSDouble(theEnv).le(theEnv, rV.toJSDouble(theEnv));
}
JSValue eq(Environment theEnv, JSValue rV) {
JSValue lV = toPrimitive(theEnv, "Number");
rV = rV.toPrimitive(theEnv, "Number");
if ((lV instanceof JSString) && (rV instanceof JSString))
return lV.eq(theEnv, rV);
else
return lV.toJSDouble(theEnv).eq(theEnv, rV.toJSDouble(theEnv));
}
JSValue ne(Environment theEnv, JSValue rV) {
JSValue lV = toPrimitive(theEnv, "Number");
rV = rV.toPrimitive(theEnv, "Number");
if ((lV instanceof JSString) && (rV instanceof JSString))
return lV.ne(theEnv, rV);
else
return lV.toJSDouble(theEnv).ne(theEnv, rV.toJSDouble(theEnv));
}
JSValue plus(Environment theEnv) {
return toJSDouble(theEnv).plus(theEnv);
}
JSValue minus(Environment theEnv) {
return toJSDouble(theEnv).minus(theEnv);
}
JSValue twiddle(Environment theEnv) {
return toJSInteger(theEnv).twiddle(theEnv);
}
JSValue bang(Environment theEnv) {
return toJSBoolean(theEnv).bang(theEnv);
}
JSValue typeof(Environment theEnv) {
return unimplemented("typeof");
}
JSValue add(Environment theEnv, JSValue rV) {
JSValue lV = toPrimitive(theEnv, "");
rV = rV.toPrimitive(theEnv, "");
if ((lV instanceof JSString) || (rV instanceof JSString))
return lV.add(theEnv, rV);
else
return lV.toJSDouble(theEnv).add(theEnv, rV);
}
JSValue subtract(Environment theEnv, JSValue rV) {
return toJSDouble(theEnv).subtract(theEnv, rV.toJSDouble(theEnv));
}
JSValue multiply(Environment theEnv, JSValue rV) {
return toJSDouble(theEnv).multiply(theEnv, rV.toJSDouble(theEnv));
}
JSValue divide(Environment theEnv, JSValue rV) {
return toJSDouble(theEnv).divide(theEnv, rV.toJSDouble(theEnv));
}
JSValue remainder(Environment theEnv, JSValue rV) {
return toJSDouble(theEnv).remainder(theEnv, rV.toJSDouble(theEnv));
}
JSValue and(Environment theEnv, JSValue rV) {
return toJSInteger(theEnv).and(theEnv, rV.toJSInteger(theEnv));
}
JSValue or(Environment theEnv, JSValue rV) {
return toJSInteger(theEnv).or(theEnv, rV.toJSInteger(theEnv));
}
JSValue xor(Environment theEnv, JSValue rV) {
return toJSInteger(theEnv).xor(theEnv, rV.toJSInteger(theEnv));
}
JSValue shl(Environment theEnv, JSValue rV) {
return toJSInteger(theEnv).shl(theEnv, rV.toJSInteger(theEnv));
}
JSValue shr(Environment theEnv, JSValue rV) {
return toJSInteger(theEnv).shr(theEnv, rV.toJSInteger(theEnv));
}
JSValue ushl(Environment theEnv, JSValue rV) {
return toJSInteger(theEnv).ushl(theEnv, rV.toJSInteger(theEnv));
}
JSValue getProp(Environment theEnv, JSString id) {
return toJSObject(theEnv).getProp(theEnv, id);
}
boolean hasProp(Environment theEnv, JSString id) {
return toJSObject(theEnv).hasProp(theEnv, id);
}
JSValue putProp(Environment theEnv, JSString id, JSValue rV) {
return toJSObject(theEnv).putProp(theEnv, id, rV);
}
JSValue call(Environment theEnv, JSValue rV) {
throw new JSException(new JSString("[[call]] not implemented"));
}
JSValue defaultValue(Environment theEnv, String hint) {
/*
When the [[DefaultValue]] method of O is called with hint String, the following steps are taken:
1. Call the [[Get]] method of object O with argument "toString".
2. If Result(1) is not an object, go to step 5.
3. Call the [[Call]] method of Result(1), with O as the this value and an empty argument list.
4. If Result(3) is a primitive value, return Result(3).
5. Call the [[Get]] method of object O with argument "valueOf".
6. If Result(5) is not an object, go to step 9.
7. Call the [[Call]] method of Result(5), with O as the this value and an empty argument list.
8. If Result(7) is a primitive value, return Result(7).
9. Generate a runtime error.
*/
JSValue v = null;
if (hint.equals("String")) {
v = getProp(theEnv, new JSString("toString"));
if (v instanceof JSObject) {
// invoke 'v.Call' with 'this' as the JS this
}
else {
v = getProp(theEnv, new JSString("valueOf"));
if (v instanceof JSObject) {
}
else
throw new JSException(new JSString("No default value"));
}
}
else { // hint.equals("Number")
/*
When the [[DefaultValue]] method of O is called with hint Number, the following steps are taken:
1. Call the [[Get]] method of object O with argument "valueOf".
2. If Result(1) is not an object, go to step 5.
3. Call the [[Call]] method of Result(1), with O as the this value and an empty argument list.
4. If Result(3) is a primitive value, return Result(3).
5. Call the [[Get]] method of object O with argument "toString".
6. If Result(5) is not an object, go to step 9.
7. Call the [[Call]] method of Result(5), with O as the this value and an empty argument list.
8. If Result(7) is a primitive value, return Result(7).
9. Generate a runtime error.
*/
}
return null;
}
JSValue toPrimitive(Environment theEnv, String hint) {
JSValue result = defaultValue(theEnv, hint);
if (result instanceof JSObject)
throw new JSException(new JSString("default value returned object"));
else
return result;
}
JSObject toJSObject(Environment theEnv) { unimplemented("toJSObjet"); return null; }
JSDouble toJSDouble(Environment theEnv) { unimplemented("toJSDouble"); return null; }
JSInteger toJSInteger(Environment theEnv) { unimplemented("toJSInteger"); return null; }
JSString toJSString(Environment theEnv) { unimplemented("toJSString"); return null; }
JSBoolean toJSBoolean(Environment theEnv) { unimplemented("toJSBoolean"); return null; }
}

View File

@@ -0,0 +1,40 @@
import java.util.Vector;
class JSValueList extends JSValue {
static JSValueList buildList(JSValue left, JSValue right)
{
JSValueList theList;
if (left instanceof JSValueList) {
theList = (JSValueList)left;
theList.add(right);
}
else
if (right instanceof JSValueList) {
theList = (JSValueList)right;
theList.add(left);
}
else {
theList = new JSValueList();
theList.add(left);
theList.add(right);
}
return theList;
}
void add(JSValue v)
{
if (v instanceof JSValueList) {
JSValueList vl = (JSValueList)v;
for (int i = 0; i < vl.contents.size(); i++)
contents.addElement((JSValue)(vl.contents.elementAt(i)));
}
else
contents.addElement(v);
}
Vector contents = new Vector();
}

View File

@@ -0,0 +1,39 @@
class LogicalNode extends BinaryNode {
LogicalNode(String aOp, ExpressionNode aLeft, ExpressionNode aRight)
{
super(aOp, aLeft, aRight);
}
JSValue eval(Environment theEnv)
{
JSBoolean b = left.eval(theEnv).toJSBoolean(theEnv);
if (op == "&&") {
if (b.isFalse())
return b;
else {
b = right.eval(theEnv).toJSBoolean(theEnv);
if (b.isFalse())
return b;
else
return JSBoolean.JSTrue;
}
}
if (op == "||") {
if (b.isTrue())
return b;
else {
b = right.eval(theEnv).toJSBoolean(theEnv);
if (b.isTrue())
return b;
else
return JSBoolean.JSFalse;
}
}
else {
System.out.println("missing logical op " + op);
return null;
}
}
}

View File

@@ -0,0 +1,35 @@
import java.util.Vector;
class NativeFunction extends JSObject {
NativeFunction(ControlNode aBody)
{
super("Function");
body = aBody;
}
JSValue call(Environment theEnv, JSValue rV)
{
JSScope args = new JSScope("Arguments");
theEnv.enterNewScope(args);
for (int i = 0; i < parameters.size(); i++) {
if (rV instanceof JSValueList)
args.putProp(theEnv, (JSString)(parameters.elementAt(i)), (JSValue) ( ((JSValueList)rV).contents.elementAt(i)) );
else
args.putProp(theEnv, (JSString)(parameters.elementAt(i)), rV );
}
ControlNode c = body;
while (c != null) c = c.eval(theEnv);
theEnv.leaveScope();
return theEnv.resultValue;
}
ControlNode body;
Vector parameters = new Vector();
}

View File

@@ -0,0 +1,18 @@
class NativeNumber extends JSObject {
NativeNumber(double p) {
super("Number");
d = p;
}
JSValue defaultValue(Environment theEnv, String hint) {
if (hint.equals("String"))
return new JSString(Double.toString(d));
else
return new JSDouble(d);
}
double d;
}

View File

@@ -0,0 +1,35 @@
class RelationalNode extends BinaryNode {
RelationalNode(String aOp, ExpressionNode aLeft, ExpressionNode aRight)
{
super(aOp, aLeft, aRight);
}
JSValue eval(Environment theEnv)
{
JSValue lV = left.eval(theEnv);
JSValue rV = right.eval(theEnv);
if (op == ">")
return lV.gt(theEnv, rV);
else
if (op == ">=")
return lV.ge(theEnv, rV);
else
if (op == "<")
return lV.lt(theEnv, rV);
else
if (op == "<=")
return lV.le(theEnv, rV);
else
if (op == "==")
return lV.eq(theEnv, rV);
else
if (op == "!=")
return lV.ne(theEnv, rV);
else {
System.out.println("missing relational op");
return null;
}
}
}

View File

@@ -0,0 +1,43 @@
import java.util.Vector;
class SwitchNode extends ControlNode {
SwitchNode(ExpressionNode e)
{
super(e);
}
void addCase(ExpressionNode e, ControlNode c)
{
if (e == null)
defaultCode = c;
else {
caseExpr.addElement(e);
caseCode.addElement(c);
}
}
ControlNode eval(Environment theEnv)
{
JSValue v = expr.eval(theEnv);
int count = caseExpr.size();
for (int i = 0; i < count; i++) {
ExpressionNode e = (ExpressionNode)(caseExpr.elementAt(i));
JSBoolean b = v.eq(theEnv, e.eval(theEnv)).toJSBoolean(theEnv);
if (b.isTrue())
return (ControlNode)(caseCode.elementAt(i));
}
if (defaultCode != null)
return defaultCode;
else
return next;
}
Vector caseExpr = new Vector();
Vector caseCode = new Vector();
ControlNode defaultCode;
}

View File

@@ -0,0 +1,13 @@
class ThrowNode extends ControlNode {
ThrowNode(ExpressionNode e)
{
super(e);
}
ControlNode eval(Environment theEnv)
{
throw new JSException(expr.eval(theEnv));
}
}

View File

@@ -0,0 +1,47 @@
import java.util.Vector;
class TryNode extends ControlNode {
TryNode(ControlNode tryCode)
{
super(null);
tryBody = tryCode;
}
void addFinally(ControlNode finallyCode)
{
finallyBody = finallyCode;
}
void addCatchClause(ExpressionNode e, ControlNode c)
{
catchExpr.addElement(e);
catchCode.addElement(c);
}
ControlNode eval(Environment theEnv)
{
try {
ControlNode c = tryBody;
while (c != null) c = c.eval(theEnv);
}
catch (JSException x) {
int count = catchExpr.size();
for (int i = 0; i < count; i++) {
ExpressionNode e = (ExpressionNode)(catchExpr.elementAt(i));
String id = ((JSObject)e).oClass;
theEnv.scope.contents.put(id, x.getValue()); // XXX YAARGH !!!
return (ControlNode)(catchCode.elementAt(i));
}
}
return next;
}
Vector catchExpr = new Vector();
Vector catchCode = new Vector();
ControlNode tryBody;
ControlNode finallyBody;
}

View File

@@ -0,0 +1,62 @@
class UnaryNode extends ExpressionNode {
UnaryNode(String aOp, ExpressionNode aChild)
{
child = aChild;
op = aOp;
}
String print(String indent)
{
StringBuffer result = new StringBuffer(indent);
result.append("UnaryNode ");
result.append(op);
result.append("\n");
indent += " ";
if (child == null) {
result.append(indent);
result.append("null\n");
}
else
result.append(child.print(indent));
return result.toString();
}
JSValue eval(Environment theEnv)
{
JSValue cV = child.eval(theEnv);
if (op == "+")
return cV.plus(theEnv);
else
if (op == "-")
return cV.minus(theEnv);
else
if (op == "~")
return cV.twiddle(theEnv);
else
if (op == "!")
return cV.bang(theEnv);
else
if (op == "typeof")
return cV.typeof(theEnv);
else {
System.out.println("missing unary op " + op);
return null;
}
}
String getOperator()
{
return op;
}
ExpressionNode getChild()
{
return child;
}
protected ExpressionNode child;
protected String op;
}

343
mozilla/js/js2/js2.cpp Normal file
View File

@@ -0,0 +1,343 @@
// -*- 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.1 (the "License"); you may not use this file
// except in compliance with the License. You may obtain a copy of
// the License at http://www.mozilla.org/NPL/
//
// Software distributed under the License is distributed on an "AS
// IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr
// implied. See the License for the specific language governing
// rights and limitations under the License.
//
// The Original Code is the JavaScript 2 Prototype.
//
// The Initial Developer of the Original Code is Netscape
// Communications Corporation. Portions created by Netscape are
// Copyright (C) 1998 Netscape Communications Corporation. All
// Rights Reserved.
//
// JS2 shell.
//
#if 1
#define DEBUGGER_FOO
#define INTERPRET_INPUT
#else
#undef DEBUGGER_FOO
#undef INTERPRET_INPUT
#endif
#include <assert.h>
#include "world.h"
#include "interpreter.h"
#include "icodegenerator.h"
#ifdef DEBUGGER_FOO
#include "debugger.h"
#endif
#if defined(XP_MAC) && !defined(XP_MAC_MPW)
#include <SIOUX.h>
#include <MacTypes.h>
static char *mac_argv[] = {"js2", 0};
static void initConsole(StringPtr consoleName,
const char* startupMessage,
int &argc, char **&argv)
{
SIOUXSettings.autocloseonquit = false;
SIOUXSettings.asktosaveonclose = false;
SIOUXSetTitle(consoleName);
// Set up a buffer for stderr (otherwise it's a pig).
static char buffer[BUFSIZ];
setvbuf(stderr, buffer, _IOLBF, BUFSIZ);
JavaScript::stdOut << startupMessage;
argc = 1;
argv = mac_argv;
}
#endif
namespace JavaScript {
namespace Shell {
using namespace ICG;
using namespace JSTypes;
using namespace Interpreter;
// Interactively read a line from the input stream in and put it into
// s. Return false if reached the end of input before reading anything.
static bool promptLine(LineReader &inReader, string &s, const char *prompt)
{
if (prompt) {
stdOut << prompt;
#ifdef XP_MAC_MPW
// Print a CR after the prompt because MPW grabs the entire
// line when entering an interactive command.
stdOut << '\n';
#endif
}
return inReader.readLine(s) != 0;
}
World world;
/* "filename" of the console */
const String ConsoleName = widenCString("<console>");
const bool showTokens = false;
#ifdef DEBUGGER_FOO
Reader *sourceReader; /* Reader for console file */
static
const Reader *ResolveFile (const String& fileName)
{
if (fileName == ConsoleName)
return sourceReader;
else
{
stdErr << "Could not locate source for file '" << fileName << "'\n";
return 0;
}
}
JavaScript::Debugger::Shell jsd(world, stdin, JavaScript::stdOut,
JavaScript::stdOut, &ResolveFile);
#endif
static JSValue print(Context *cx, const JSValues &argv)
{
size_t n = argv.size();
if (n > 1) { // the 'this' parameter is un-interesting
stdOut << argv[1];
for (size_t i = 2; i < n; ++i)
stdOut << ' ' << argv[i];
}
stdOut << "\n";
return kUndefinedValue;
}
static JSValue dump(Context *cx, const JSValues &argv)
{
size_t n = argv.size();
if (n > 1) { // the 'this' parameter is un-interesting
if (argv[1].isFunction()) {
JSFunction *f = static_cast<JSFunction *>(argv[1].function);
if (f->isNative())
stdOut << "Native function";
else
stdOut << *f->getICode();
}
else
stdOut << "Not a function";
}
stdOut << "\n";
return kUndefinedValue;
}
inline char narrow(char16 ch) { return char(ch); }
static JSValue load(Context *cx, const JSValues &argv)
{
JSValue result;
size_t n = argv.size();
if (n > 1) {
for (size_t i = 1; i < n; ++i) {
JSValue val = argv[i].toString();
if (val.isString()) {
String fileName(*val.string);
std::string str(fileName.length(), char());
std::transform(fileName.begin(), fileName.end(), str.begin(), narrow);
FILE* f = fopen(str.c_str(), "r");
if (f) {
result = cx->readEvalFile(f, fileName);
fclose(f);
}
}
}
}
return result;
}
#if 0 // need a XP version of this, rip off from Monkey?
#include <sys/timeb.h>
static JSValue time(Context *cx, const JSValues &argv)
{
struct _timeb timebuffer;
_ftime(&timebuffer);
return JSValue((double)timebuffer.time * 1000 + timebuffer.millitm);
}
#endif
static void readEvalPrint(FILE *in, World &world)
{
JSScope global;
Context cx(world, &global);
#ifdef DEBUGGER_FOO
jsd.attachToContext (&cx);
#endif
global.defineNativeFunction(world.identifiers["print"], print);
global.defineNativeFunction(world.identifiers["dump"], dump);
global.defineNativeFunction(world.identifiers["load"], load);
// global.defineNativeFunction(world.identifiers["time"], time);
String buffer;
string line;
LineReader inReader(in);
while (promptLine(inReader, line, buffer.empty() ? "js> " : "> ")) {
appendChars(buffer, line.data(), line.size());
try {
Arena a;
Parser p(world, a, buffer, ConsoleName);
if (showTokens) {
Lexer &l = p.lexer;
while (true) {
const Token &t = l.get(true);
if (t.hasKind(Token::end))
break;
stdOut << ' ';
t.print(stdOut, true);
}
stdOut << '\n';
} else {
StmtNode *parsedStatements = p.parseProgram();
ASSERT(p.lexer.peek(true).hasKind(Token::end));
{
PrettyPrinter f(stdOut, 30);
{
PrettyPrinter::Block b(f, 2);
f << "Program =";
f.linearBreak(1);
StmtNode::printStatements(f, parsedStatements);
}
f.end();
}
stdOut << '\n';
#ifdef INTERPRET_INPUT
#ifdef DEBUGGER_FOO
sourceReader = &(p.lexer.reader);
#endif
// Generate code for parsedStatements, which is a linked
// list of zero or more statements
ICodeModule* icm = cx.genCode(parsedStatements, ConsoleName);
if (icm) {
stdOut << *icm;
JSValue result = cx.interpret(icm, JSValues());
stdOut << "result = " << result << "\n";
delete icm;
}
#endif
}
clear(buffer);
} catch (Exception &e) {
/* If we got a syntax error on the end of input,
* then wait for a continuation
* of input rather than printing the error message. */
if (!(e.hasKind(Exception::syntaxError) &&
e.lineNum && e.pos == buffer.size() &&
e.sourceFile == ConsoleName)) {
stdOut << '\n' << e.fullMessage();
clear(buffer);
}
}
}
stdOut << '\n';
}
/**
* Poor man's instruction tracing facility.
*/
class Tracer : public Context::Listener {
typedef InstructionStream::difference_type InstructionOffset;
void listen(Context* context, Context::Event event)
{
if (event & Context::EV_STEP) {
ICodeModule *iCode = context->getICode();
JSValues &registers = context->getRegisters();
InstructionIterator pc = context->getPC();
InstructionOffset offset = (pc - iCode->its_iCode->begin());
printFormat(stdOut, "trace [%02u:%04u]: ",
iCode->mID, offset);
Instruction* i = *pc;
stdOut << *i;
if (i->op() != BRANCH && i->count() > 0) {
stdOut << " [";
i->printOperands(stdOut, registers);
stdOut << "]\n";
} else {
stdOut << '\n';
}
}
}
};
char * tests[] = {
"function fact(n) { if (n > 1) return n * fact(n-1); else return 1; } print(fact(6), \" should be 720\"); return;" ,
"a = { f1: 1, f2: 2}; print(a.f2++, \" should be 2\"); print(a.f2 <<= 1, \" should be 6\"); return;" ,
"class A { static var b = 3; static function s() { return b++; }function x() { return \"Ax\"; } function y() { return \"Ay\"; } } var a:A = new A; print(a.s(), \" should be 3\"); print(A.b, \" should be 4\"); return;",
"class B extends A { function x() { return \"Bx\"; } } var b:B = new B; print(b.x(), \" should be Bx\"); print(b.y(), \" should be Ay\"); return;"
};
static void testCompile()
{
JSScope glob;
Context cx(world, &glob);
glob.defineNativeFunction(world.identifiers["print"], print);
for (uint i = 0; i < sizeof(tests) / sizeof(char *); i++) {
String testScript = widenCString(tests[i]);
Arena a;
Parser p(world, a, testScript, widenCString("testCompile"));
StmtNode *parsedStatements = p.parseProgram();
ICodeGenerator icg(&world, &glob);
StmtNode *s = parsedStatements;
while (s) {
icg.genStmt(s);
s = s->next;
}
cx.interpret(icg.complete(), JSValues());
}
}
} /* namespace Shell */
} /* namespace JavaScript */
#if defined(XP_MAC) && !defined(XP_MAC_MPW)
int main(int argc, char **argv)
{
initConsole("\pJavaScript Shell", "Welcome to the js2 shell.\n", argc, argv);
#else
int main(int , char **)
{
#endif
using namespace JavaScript;
using namespace Shell;
#if 1
testCompile();
#endif
readEvalPrint(stdin, world);
return 0;
// return ProcessArgs(argv + 1, argc - 1);
}

316
mozilla/js/js2/jsclasses.h Normal file
View File

@@ -0,0 +1,316 @@
/* -*- 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.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is the JavaScript 2 Prototype.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU Public License (the "GPL"), in which case the
* provisions of the GPL are applicable instead of those above.
* If you wish to allow use of your version of this file only
* under the terms of the GPL and not to allow others to use your
* version of this file under the NPL, indicate your decision by
* deleting the provisions above and replace them with the notice
* and other provisions required by the GPL. If you do not delete
* the provisions above, a recipient may use your version of this
* file under either the NPL or the GPL.
*/
#ifndef jsclasses_h
#define jsclasses_h
#include "jstypes.h"
namespace JavaScript {
namespace JSClasses {
using JSTypes::JSValue;
using JSTypes::JSObject;
using JSTypes::JSType;
using JSTypes::JSScope;
using JSTypes::JSFunction;
using ICG::ICodeModule;
struct JSSlot {
typedef enum { kNoFlag = 0, kIsConstructor = 0x01 } SlotFlags; // <-- readonly, enumerable etc
JSType* mType;
uint32 mIndex;
SlotFlags mFlags;
JSSlot() : mType(0), mFlags(kNoFlag)
{
}
bool isConstructor() const { return (mFlags & kIsConstructor) != 0; }
};
#if defined(XP_MAC)
// copied from default template parameters in map.
typedef gc_allocator<std::pair<const String, JSSlot> > gc_slot_allocator;
#elif defined(XP_UNIX)
typedef JSTypes::gc_map_allocator gc_slot_allocator;
#elif defined(_WIN32)
typedef gc_allocator<JSSlot> gc_slot_allocator;
#endif
typedef std::map<String, JSSlot, std::less<const String>, gc_slot_allocator> JSSlots;
typedef std::pair<String, JSFunction*> MethodEntry;
typedef std::vector<MethodEntry> JSMethods;
/**
* Represents a class in the JavaScript 2 (ECMA 4) language.
* Since a class defines a scope, and is defined in a scope,
* a new scope is created whose parent scope is the scope of
* class definition.
*/
class JSClass : public JSType {
protected:
JSScope* mScope;
uint32 mSlotCount;
JSSlots mSlots;
uint32 mStaticCount;
JSSlots mStaticSlots;
JSValue* mStaticData;
JSMethods mMethods;
public:
JSClass(JSScope* scope, const String& name, JSClass* superClass = 0)
: JSType(name, superClass),
mScope(new JSScope(scope)),
mSlotCount(superClass ? superClass->mSlotCount : 0),
mStaticCount(0),
mStaticData(0)
{
if (superClass) {
// inherit superclass methods
JSMethods::iterator end = superClass->mMethods.end();
for (JSMethods::iterator i = superClass->mMethods.begin(); i != end; i++)
mMethods.push_back(*i);
}
}
JSClass* getSuperClass()
{
return static_cast<JSClass*>(mBaseType);
}
JSScope* getScope()
{
return mScope;
}
const JSSlot& defineSlot(const String& name, JSType* type)
{
JSSlot& slot = mSlots[name];
ASSERT(slot.mType == 0);
slot.mType = type;
slot.mIndex = mSlotCount++; // starts at 0.
return slot;
}
const JSSlot& getSlot(const String& name)
{
return mSlots[name];
}
bool hasSlot(const String& name)
{
return (mSlots.find(name) != mSlots.end());
}
JSSlots& getSlots()
{
return mSlots;
}
uint32 getSlotCount()
{
return mSlotCount;
}
/**
* Define a static/class variable.
*/
const JSSlot& defineStatic(const String& name, JSType* type)
{
JSSlot& slot = mStaticSlots[name];
ASSERT(slot.mType == 0);
slot.mType = type;
slot.mIndex = mStaticCount++;
return slot;
}
const JSSlot& defineConstructor(const String& name)
{
JSSlot& slot = mStaticSlots[name];
ASSERT(slot.mType == 0);
slot.mType = &JSTypes::Function_Type;
slot.mIndex = mStaticCount++;
slot.mFlags = JSSlot::kIsConstructor;
return slot;
}
const JSSlot& getStatic(const String& name)
{
return mStaticSlots[name];
}
bool hasStatic(const String& name, JSType*& type, bool &isConstructor)
{
JSSlots::const_iterator i = mStaticSlots.find(name);
if (i != mStaticSlots.end()) {
type = i->second.mType;
isConstructor = i->second.isConstructor();
return true;
}
return false;
}
bool hasStatic(const String& name)
{
return (mStaticSlots.find(name) != mStaticSlots.end());
}
bool complete()
{
mStaticData = new JSValue[mStaticCount];
return (mStaticData != 0);
}
JSValue& operator[] (uint32 index)
{
return mStaticData[index];
}
virtual void printProperties(Formatter& f)
{
f << "Properties:\n";
JSObject::printProperties(f);
f << "Statics:\n";
printStatics(f);
}
void printStatics(Formatter& f)
{
JSClass* superClass = getSuperClass();
if (superClass) superClass->printStatics(f);
for (JSSlots::iterator i = mStaticSlots.begin(), end = mStaticSlots.end(); i != end; ++i) {
f << i->first << " : " << mStaticData[i->second.mIndex] << "\n";
}
}
void defineMethod(const String& name, JSFunction *f)
{
uint32 slot;
if (hasMethod(name, slot))
mMethods[slot] = MethodEntry(name, f);
else
mMethods.push_back(MethodEntry(name, f));
}
bool hasMethod(const String& name, uint32& index)
{
JSMethods::iterator end = mMethods.end();
for (JSMethods::iterator i = mMethods.begin(); i != end; i++) {
if (i->first == name) {
index = i - mMethods.begin();
return true;
}
}
return false;
}
JSFunction* getMethod(uint32 index)
{
return mMethods[index].second;
}
};
/**
* Represents an instance of a JSClass.
*/
class JSInstance : public JSObject {
protected:
JSValue mSlots[1];
public:
void* operator new(size_t n, JSClass* thisClass)
{
uint32 slotCount = thisClass->getSlotCount();
if (slotCount > 0) n += sizeof(JSValue) * (slotCount - 1);
return gc_base::operator new(n);
}
#if !defined(XP_MAC)
void operator delete(void* /*ptr*/, JSClass* /*thisClass*/) {}
#endif
JSInstance(JSClass* thisClass)
{
mType = thisClass;
// initialize extra slots with undefined.
uint32 slotCount = thisClass->getSlotCount();
if (slotCount > 0) {
std::uninitialized_fill(&mSlots[1], &mSlots[1] + (slotCount - 1),
JSTypes::kUndefinedValue);
}
// for grins, use the prototype link to access methods.
setPrototype(thisClass->getScope());
}
JSFunction* getMethod(uint32 index)
{
return getClass()->getMethod(index);
}
JSClass* getClass()
{
return static_cast<JSClass*>(mType);
}
JSValue& operator[] (uint32 index)
{
return mSlots[index];
}
virtual void printProperties(Formatter& f)
{
f << "Properties:\n";
JSObject::printProperties(f);
f << "Slots:\n";
printSlots(f, getClass());
}
private:
void printSlots(Formatter& f, JSClass* thisClass)
{
JSClass* superClass = thisClass->getSuperClass();
if (superClass) printSlots(f, superClass);
JSSlots& slots = thisClass->getSlots();
for (JSSlots::iterator i = slots.begin(), end = slots.end(); i != end; ++i) {
f << i->first << " : " << mSlots[i->second.mIndex] << "\n";
}
}
};
} /* namespace JSClasses */
} /* namespace JavaScript */
#endif /* jsclasses_h */

208
mozilla/js/js2/jsmath.cpp Normal file
View File

@@ -0,0 +1,208 @@
/* -*- 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.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is the JavaScript 2 Prototype.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU Public License (the "GPL"), in which case the
* provisions of the GPL are applicable instead of those above.
* If you wish to allow use of your version of this file only
* under the terms of the GPL and not to allow others to use your
* version of this file under the NPL, indicate your decision by
* deleting the provisions above and replace them with the notice
* and other provisions required by the GPL. If you do not delete
* the provisions above, a recipient may use your version of this
* file under either the NPL or the GPL.
*/
#include <math.h>
#include "jsmath.h"
namespace JavaScript {
namespace JSMathClass {
using namespace JSTypes;
#ifndef M_E
#define M_E 2.7182818284590452354
#endif
#ifndef M_LOG2E
#define M_LOG2E 1.4426950408889634074
#endif
#ifndef M_LOG10E
#define M_LOG10E 0.43429448190325182765
#endif
#ifndef M_LN2
#define M_LN2 0.69314718055994530942
#endif
#ifndef M_LN10
#define M_LN10 2.30258509299404568402
#endif
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif
#ifndef M_SQRT2
#define M_SQRT2 1.41421356237309504880
#endif
#ifndef M_SQRT1_2
#define M_SQRT1_2 0.70710678118654752440
#endif
/*
Concept copied from SpiderMonkey -
fd_XXX needs to be defined either as a call to the fdlibm routine
or the native C library routine depending on the platform
*/
#define JS_USE_FDLIBM_MATH 0
#if !JS_USE_FDLIBM_MATH
/*
* Use system provided math routines.
*/
#define fd_acos acos
#define fd_asin asin
#define fd_atan atan
#define fd_atan2 atan2
#define fd_ceil ceil
#define fd_copysign copysign
#define fd_cos cos
#define fd_exp exp
#define fd_fabs fabs
#define fd_floor floor
#define fd_fmod fmod
#define fd_log log
#define fd_pow pow
#define fd_sin sin
#define fd_sqrt sqrt
#define fd_tan tan
#endif
JSValue math_abs(Context *cx, const JSValues& argv)
{
if (argv.size() > 0) {
JSValue num = argv[1].toNumber();
if (num.isNaN()) return num;
if (num.isNegativeZero()) return kPositiveZero;
if (num.isNegativeInfinity()) return kPositiveInfinity;
if (num.f64 < 0) return JSValue(-num.f64);
return num;
}
return kUndefinedValue;
}
JSValue math_acos(Context *cx, const JSValues& argv)
{
if (argv.size() > 0) {
JSValue num = argv[1].toNumber();
return JSValue(fd_acos(num.f64));
}
return kUndefinedValue;
}
JSValue math_asin(Context *cx, const JSValues& argv)
{
if (argv.size() > 0) {
JSValue num = argv[1].toNumber();
return JSValue(fd_asin(num.f64));
}
return kUndefinedValue;
}
JSValue math_atan(Context *cx, const JSValues& argv)
{
if (argv.size() > 0) {
JSValue num = argv[1].toNumber();
return JSValue(fd_atan(num.f64));
}
return kUndefinedValue;
}
JSValue math_atan2(Context *cx, const JSValues& argv)
{
if (argv.size() > 1) {
JSValue num1 = argv[1].toNumber();
JSValue num2 = argv[1].toNumber();
return JSValue(fd_atan2(num1.f64, num2.f64));
}
return kUndefinedValue;
}
JSValue math_ceil(Context *cx, const JSValues& argv)
{
if (argv.size() > 0) {
JSValue num = argv[1].toNumber();
return JSValue(fd_ceil(num.f64));
}
return kUndefinedValue;
}
struct MathFunctionEntry {
char *name;
JSNativeFunction::JSCode fn;
} MathFunctions[] = {
{ "abs", math_abs },
{ "acos", math_acos },
{ "asin", math_asin },
{ "atan", math_atan },
{ "atan2", math_atan2 },
{ "ceil", math_acos },
{ "acos", math_acos },
{ "acos", math_acos }
};
struct MathConstantEntry {
char *name;
double value;
} MathConstants[] = {
{ "E", M_E },
{ "LOG2E", M_LOG2E },
{ "LOG10E", M_LOG10E },
{ "LN2", M_LN2 },
{ "LN10", M_LN10 },
{ "PI", M_PI },
{ "SQRT2", M_SQRT2 },
{ "SQRT1_2", M_SQRT1_2 }
};
// There is no constructor for Math, we simply initialize
// the properties of the Math object
void JSMath::initMathObject(JSScope *g)
{
int i;
JSMath *m = new JSMath();
m->setClass(new JSString("Math"));
for (i = 0; i < sizeof(MathFunctions) / sizeof(MathFunctionEntry); i++)
m->setProperty(widenCString(MathFunctions[i].name), JSValue(new JSNativeFunction(MathFunctions[i].fn) ) );
for (i = 0; i < sizeof(MathConstants) / sizeof(MathConstantEntry); i++)
m->setProperty(widenCString(MathConstants[i].name), JSValue(MathConstants[i].value) );
g->setProperty(widenCString("Math"), JSValue(m));
}
} /* JSMathClass */
} /* JavaScript */

58
mozilla/js/js2/jsmath.h Normal file
View File

@@ -0,0 +1,58 @@
/* -*- 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.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is the JavaScript 2 Prototype.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU Public License (the "GPL"), in which case the
* provisions of the GPL are applicable instead of those above.
* If you wish to allow use of your version of this file only
* under the terms of the GPL and not to allow others to use your
* version of this file under the NPL, indicate your decision by
* deleting the provisions above and replace them with the notice
* and other provisions required by the GPL. If you do not delete
* the provisions above, a recipient may use your version of this
* file under either the NPL or the GPL.
*/
#ifndef jsmath_h
#define jsmath_h
#include "jstypes.h"
namespace JavaScript {
namespace JSMathClass {
using JSTypes::JSObject;
using JSTypes::JSString;
using JSTypes::JSScope;
class JSMath : public JSObject {
private:
JSMath() { }
public:
static void initMathObject(JSScope *g);
};
} /* JSMathClass */
} /* JavaScript */
#endif jsmath_h

775
mozilla/js/js2/jstypes.cpp Normal file
View File

@@ -0,0 +1,775 @@
/* -*- 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.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is the JavaScript 2 Prototype.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU Public License (the "GPL"), in which case the
* provisions of the GPL are applicable instead of those above.
* If you wish to allow use of your version of this file only
* under the terms of the GPL and not to allow others to use your
* version of this file under the NPL, indicate your decision by
* deleting the provisions above and replace them with the notice
* and other provisions required by the GPL. If you do not delete
* the provisions above, a recipient may use your version of this
* file under either the NPL or the GPL.
*/
#include "jstypes.h"
#include "jsclasses.h"
#include "numerics.h"
#include "icodegenerator.h"
#include "interpreter.h"
namespace JavaScript {
namespace JSTypes {
using namespace JSClasses;
using namespace Interpreter;
/********** Object Object Stuff **************************/
JSValue object_toString(Context *cx, const JSValues& argv)
{
if (argv.size() > 0) {
JSString *s = new JSString("[object ");
JSValue theThis = argv[0];
ASSERT(theThis.isObject());
s->append(theThis.object->getClass());
s->append("]");
return JSValue(s);
}
return kUndefinedValue;
}
JSValue objectConstructor(Context *cx, const JSValues& argv)
{
ASSERT(argv.size() > 0);
JSValue theThis = argv[0];
// the prototype and class have been established already
return theThis;
}
struct ObjectFunctionEntry {
char *name;
JSNativeFunction::JSCode fn;
} ObjectFunctions[] = {
{ "toString", object_toString },
};
JSObject *JSObject::objectPrototypeObject = JSObject::initJSObject();
String JSObject::ObjectString = widenCString("Object");
// This establishes the ur-prototype, there's a timing issue
// here - the JSObject static initializers have to run before
// any other JSObject objects are constructed.
JSObject *JSObject::initJSObject()
{
JSObject *result = new JSObject();
for (int i = 0; i < sizeof(ObjectFunctions) / sizeof(ObjectFunctionEntry); i++)
result->setProperty(widenCString(ObjectFunctions[i].name), JSValue(new JSNativeFunction(ObjectFunctions[i].fn) ) );
return result;
}
// Install the 'Object' constructor into the scope, mostly irrelevant since making
// a new JSObject does all the work of setting the prototype and [[class]] values.
void JSObject::initObjectObject(JSScope *g)
{
JSNativeFunction *objCon = new JSNativeFunction(objectConstructor);
objCon->setProperty(widenCString("prototype"), JSValue(objectPrototypeObject));
g->setProperty(ObjectString, JSValue(objCon));
}
/********** Function Object Stuff **************************/
// An empty function that returns undefined
JSValue functionPrototypeFunction(Context *cx, const JSValues& argv)
{
return kUndefinedValue;
}
JSValue function_constructor(Context *cx, const JSValues& argv)
{
// build a function from the arguments into the this.
ASSERT(argv.size() > 0);
JSValue theThis = argv[0];
ASSERT(theThis.isObject());
if (argv.size() == 2) {
JSValue s = JSValue::valueToString(argv[1]);
theThis = new JSFunction(cx->compile((String)(*s.string)));
}
return theThis;
}
JSValue function_toString(Context *cx, const JSValues& argv)
{
return JSValue(new JSString("function XXX() { }" ));
}
JSValue function_apply(Context *cx, const JSValues& argv)
{
// XXX
return kUndefinedValue;
}
JSValue function_call(Context *cx, const JSValues& argv)
{
// XXX
return kUndefinedValue;
}
String JSFunction::FunctionString = widenCString("Function");
JSObject *JSFunction::functionPrototypeObject = NULL; // the 'original Function prototype object'
struct FunctionFunctionEntry {
char *name;
JSNativeFunction::JSCode fn;
} FunctionFunctions[] = {
{ "constructor", function_constructor },
{ "toString", function_toString },
{ "apply", function_apply },
{ "call", function_call },
};
void JSFunction::initFunctionObject(JSScope *g)
{
// first build the Function Prototype Object
functionPrototypeObject = new JSNativeFunction(functionPrototypeFunction);
for (int i = 0; i < sizeof(FunctionFunctions) / sizeof(FunctionFunctionEntry); i++)
functionPrototypeObject->setProperty(widenCString(FunctionFunctions[i].name), JSValue(new JSNativeFunction(FunctionFunctions[i].fn) ) );
// now the Function Constructor Object
JSNativeFunction *functionConstructorObject = new JSNativeFunction(function_constructor);
functionConstructorObject->setPrototype(functionPrototypeObject);
functionConstructorObject->setProperty(widenCString("length"), JSValue((int32)1));
functionConstructorObject->setProperty(widenCString("prototype"), JSValue(functionPrototypeObject));
// This is interesting - had to use defineVariable here to specify a type because
// when left as Any_Type (via setProperty), the Function predefined type interacted
// badly with this value. (I think setProperty perhaps should have reset the entry
// in mTypes) (?)
g->defineVariable(FunctionString, &Function_Type, JSValue(functionConstructorObject));
}
/**************************************************************************************/
JSType Any_Type = JSType(widenCString("any"), NULL);
JSType Integer_Type = JSType(widenCString("Integer"), &Any_Type);
JSType Number_Type = JSType(widenCString("Number"), &Integer_Type);
JSType Character_Type = JSType(widenCString("Character"), &Any_Type);
JSType String_Type = JSType(widenCString("String"), &Character_Type);
JSType Function_Type = JSType(widenCString("Function"), &Any_Type);
JSType Array_Type = JSType(widenCString("Array"), &Any_Type);
JSType Type_Type = JSType(widenCString("Type"), &Any_Type);
JSType Boolean_Type = JSType(widenCString("Boolean"), &Any_Type);
JSType Null_Type = JSType(widenCString("Null"), &Any_Type);
JSType Void_Type = JSType(widenCString("void"), &Any_Type);
JSType None_Type = JSType(widenCString("none"), &Any_Type);
#ifdef IS_LITTLE_ENDIAN
#define JSDOUBLE_HI32(x) (((uint32 *)&(x))[1])
#define JSDOUBLE_LO32(x) (((uint32 *)&(x))[0])
#else
#define JSDOUBLE_HI32(x) (((uint32 *)&(x))[0])
#define JSDOUBLE_LO32(x) (((uint32 *)&(x))[1])
#endif
#define JSDOUBLE_HI32_SIGNBIT 0x80000000
#define JSDOUBLE_HI32_EXPMASK 0x7ff00000
#define JSDOUBLE_HI32_MANTMASK 0x000fffff
#define JSDOUBLE_IS_NaN(x) \
((JSDOUBLE_HI32(x) & JSDOUBLE_HI32_EXPMASK) == JSDOUBLE_HI32_EXPMASK && \
(JSDOUBLE_LO32(x) || (JSDOUBLE_HI32(x) & JSDOUBLE_HI32_MANTMASK)))
#define JSDOUBLE_IS_INFINITE(x) \
((JSDOUBLE_HI32(x) & ~JSDOUBLE_HI32_SIGNBIT) == JSDOUBLE_HI32_EXPMASK && \
!JSDOUBLE_LO32(x))
#define JSDOUBLE_IS_FINITE(x) \
((JSDOUBLE_HI32(x) & JSDOUBLE_HI32_EXPMASK) != JSDOUBLE_HI32_EXPMASK)
#define JSDOUBLE_IS_NEGZERO(d) (JSDOUBLE_HI32(d) == JSDOUBLE_HI32_SIGNBIT && \
JSDOUBLE_LO32(d) == 0)
// the canonical undefined value, etc.
const JSValue kUndefinedValue;
const JSValue kNaNValue = JSValue(nan);
const JSValue kTrueValue = JSValue(true);
const JSValue kFalseValue = JSValue(false);
const JSValue kNullValue = JSValue((JSObject*)NULL);
const JSValue kNegativeZero = JSValue(-0.0);
const JSValue kPositiveZero = JSValue(0.0);
const JSValue kNegativeInfinity = JSValue(negativeInfinity);
const JSValue kPositiveInfinity = JSValue(positiveInfinity);
const JSType *JSValue::getType() const
{
switch (tag) {
case JSValue::i32_tag:
return &Integer_Type;
case JSValue::u32_tag:
return &Integer_Type;
case JSValue::integer_tag:
return &Integer_Type;
case JSValue::f64_tag:
return &Number_Type;
case JSValue::object_tag:
{
//
// XXX why isn't there a class for Object? XXX
//
JSClass *clazz = dynamic_cast<JSClass *>(object->getType());
if (clazz)
return clazz;
else
return &Any_Type;
}
case JSValue::array_tag:
return &Array_Type;
case JSValue::function_tag:
return &Function_Type;
case JSValue::string_tag:
return &String_Type;
case JSValue::boolean_tag:
return &Boolean_Type;
case JSValue::undefined_tag:
return &Void_Type;
case JSValue::type_tag:
return &Type_Type;
default:
NOT_REACHED("Bad tag");
return &None_Type;
}
}
bool JSValue::isNaN() const
{
ASSERT(isNumber());
switch (tag) {
case i32_tag:
case u32_tag:
return false;
case integer_tag:
case f64_tag:
return JSDOUBLE_IS_NaN(f64);
default:
NOT_REACHED("Broken compiler?");
return true;
}
}
bool JSValue::isNegativeInfinity() const
{
ASSERT(isNumber());
switch (tag) {
case i32_tag:
case u32_tag:
return false;
case integer_tag:
case f64_tag:
return (f64 < 0) && JSDOUBLE_IS_INFINITE(f64);
default:
NOT_REACHED("Broken compiler?");
return true;
}
}
bool JSValue::isPositiveInfinity() const
{
ASSERT(isNumber());
switch (tag) {
case i32_tag:
case u32_tag:
return false;
case integer_tag:
case f64_tag:
return (f64 > 0) && JSDOUBLE_IS_INFINITE(f64);
default:
NOT_REACHED("Broken compiler?");
return true;
}
}
bool JSValue::isNegativeZero() const
{
ASSERT(isNumber());
switch (tag) {
case i32_tag:
case u32_tag:
return false;
case integer_tag:
case f64_tag:
return JSDOUBLE_IS_NEGZERO(f64);
default:
NOT_REACHED("Broken compiler?");
return true;
}
}
bool JSValue::isPositiveZero() const
{
ASSERT(isNumber());
switch (tag) {
case i32_tag:
return (i32 == 0);
case u32_tag:
return (u32 == 0);
case integer_tag:
case f64_tag:
return (f64 == 0.0) && !JSDOUBLE_IS_NEGZERO(f64);
default:
NOT_REACHED("Broken compiler?");
return true;
}
}
int JSValue::operator==(const JSValue& value) const
{
if (this->tag == value.tag) {
#define CASE(T) case T##_tag: return (this->T == value.T)
switch (tag) {
CASE(i8); CASE(u8);
CASE(i16); CASE(u16);
CASE(i32); CASE(u32); CASE(f32);
CASE(i64); CASE(u64); CASE(f64);
CASE(object); CASE(array); CASE(function); CASE(string);
CASE(type); CASE(boolean);
#undef CASE
case integer_tag : return (this->f64 == value.f64);
// question: are all undefined values equal to one another?
case undefined_tag: return 1;
}
}
return 0;
}
Formatter& operator<<(Formatter& f, JSObject& obj)
{
obj.printProperties(f);
return f;
}
void JSObject::printProperties(Formatter& f)
{
for (JSProperties::const_iterator i = mProperties.begin(); i != mProperties.end(); i++) {
f << (*i).first << " : " << (*i).second;
f << "\n";
}
}
Formatter& operator<<(Formatter& f, const JSValue& value)
{
switch (value.tag) {
case JSValue::i32_tag:
f << float64(value.i32);
break;
case JSValue::u32_tag:
f << float64(value.u32);
break;
case JSValue::integer_tag:
case JSValue::f64_tag:
f << value.f64;
break;
case JSValue::object_tag:
printFormat(f, "Object @ 0x%08X\n", value.object);
f << *value.object;
break;
case JSValue::array_tag:
printFormat(f, "Array @ 0x%08X", value.object);
break;
case JSValue::function_tag:
printFormat(f, "Function @ 0x%08X", value.object);
break;
case JSValue::string_tag:
f << *value.string;
break;
case JSValue::boolean_tag:
f << ((value.boolean) ? "true" : "false");
break;
case JSValue::undefined_tag:
f << "undefined";
break;
case JSValue::type_tag:
printFormat(f, "Type @ 0x%08X\n", value.type);
f << *value.type;
break;
default:
NOT_REACHED("Bad tag");
}
return f;
}
JSValue JSValue::toPrimitive(ECMA_type /*hint*/) const
{
JSObject *obj;
switch (tag) {
case i32_tag:
case u32_tag:
case integer_tag:
case f64_tag:
case string_tag:
case boolean_tag:
case undefined_tag:
return *this;
case object_tag:
obj = object;
break;
case array_tag:
obj = array;
break;
case function_tag:
obj = function;
break;
default:
NOT_REACHED("Bad tag");
return kUndefinedValue;
}
const JSValue &toString = obj->getProperty(widenCString("toString"));
if (toString.isObject()) {
if (toString.isFunction()) {
}
else // right? The spec doesn't say
throw new JSException("Runtime error from toPrimitive"); // XXX
}
const JSValue &valueOf = obj->getProperty(widenCString("valueOf"));
if (!valueOf.isObject())
throw new JSException("Runtime error from toPrimitive"); // XXX
return kUndefinedValue;
}
JSValue JSValue::valueToString(const JSValue& value) // can assume value is not a string
{
const char* chrp;
char buf[dtosStandardBufferSize];
switch (value.tag) {
case i32_tag:
chrp = doubleToStr(buf, dtosStandardBufferSize, value.i32, dtosStandard, 0);
break;
case u32_tag:
chrp = doubleToStr(buf, dtosStandardBufferSize, value.u32, dtosStandard, 0);
break;
case integer_tag:
case f64_tag:
chrp = doubleToStr(buf, dtosStandardBufferSize, value.f64, dtosStandard, 0);
break;
case object_tag:
chrp = "object";
break;
case array_tag:
chrp = "array";
break;
case function_tag:
chrp = "function";
break;
case string_tag:
return value;
case boolean_tag:
chrp = (value.boolean) ? "true" : "false";
break;
case undefined_tag:
chrp = "undefined";
break;
default:
NOT_REACHED("Bad tag");
}
return JSValue(new JSString(chrp));
}
JSValue JSValue::valueToNumber(const JSValue& value) // can assume value is not a number
{
switch (value.tag) {
case i32_tag:
return JSValue((float64)value.i32);
case u32_tag:
return JSValue((float64)value.u32);
case integer_tag:
case f64_tag:
return value;
case string_tag:
{
JSString* str = value.string;
const char16 *numEnd;
double d = stringToDouble(str->begin(), str->end(), numEnd);
return JSValue(d);
}
case object_tag:
case array_tag:
case function_tag:
// XXX more needed :
// toNumber(toPrimitive(hint Number))
return kUndefinedValue;
case boolean_tag:
return JSValue((value.boolean) ? 1.0 : 0.0);
case undefined_tag:
return kNaNValue;
default:
NOT_REACHED("Bad tag");
return kUndefinedValue;
}
}
JSValue JSValue::valueToInteger(const JSValue& value)
{
JSValue result = valueToNumber(value);
ASSERT(result.tag == f64_tag);
result.tag = i64_tag;
bool neg = (result.f64 < 0);
result.f64 = floor((neg) ? -result.f64 : result.f64);
result.f64 = (neg) ? -result.f64 : result.f64;
return result;
}
JSValue JSValue::valueToBoolean(const JSValue& value)
{
switch (value.tag) {
case i32_tag:
return JSValue(value.i32 != 0);
case u32_tag:
return JSValue(value.u32 != 0);
case integer_tag:
case f64_tag:
return JSValue(!(value.f64 == 0.0) || JSDOUBLE_IS_NaN(value.f64));
case string_tag:
return JSValue(value.string->length() != 0);
case boolean_tag:
return value;
case object_tag:
case array_tag:
case function_tag:
return kTrueValue;
case undefined_tag:
return kFalseValue;
default:
NOT_REACHED("Bad tag");
return kUndefinedValue;
}
}
static const double two32 = 4294967296.0;
static const double two31 = 2147483648.0;
JSValue JSValue::valueToInt32(const JSValue& value)
{
double d;
switch (value.tag) {
case i32_tag:
return value;
case u32_tag:
d = value.u32;
break;
case integer_tag:
case f64_tag:
d = value.f64;
break;
case string_tag:
{
JSString* str = value.string;
const char16 *numEnd;
d = stringToDouble(str->begin(), str->end(), numEnd);
}
break;
case boolean_tag:
return JSValue((int32)((value.boolean) ? 1 : 0));
case object_tag:
case array_tag:
case undefined_tag:
// toNumber(toPrimitive(hint Number))
return kUndefinedValue;
default:
NOT_REACHED("Bad tag");
return kUndefinedValue;
}
if ((d == 0.0) || !JSDOUBLE_IS_FINITE(d) )
return JSValue((int32)0);
d = fmod(d, two32);
d = (d >= 0) ? d : d + two32;
if (d >= two31)
return JSValue((int32)(d - two32));
else
return JSValue((int32)d);
}
JSValue JSValue::valueToUInt32(const JSValue& value)
{
double d;
switch (value.tag) {
case i32_tag:
return JSValue((uint32)value.i32);
case u32_tag:
return value;
case f64_tag:
d = value.f64;
break;
case string_tag:
{
JSString* str = value.string;
const char16 *numEnd;
d = stringToDouble(str->begin(), str->end(), numEnd);
}
break;
case boolean_tag:
return JSValue((uint32)((value.boolean) ? 1 : 0));
case object_tag:
case array_tag:
case undefined_tag:
// toNumber(toPrimitive(hint Number))
return kUndefinedValue;
default:
NOT_REACHED("Bad tag");
return kUndefinedValue;
}
if ((d == 0.0) || !JSDOUBLE_IS_FINITE(d))
return JSValue((uint32)0);
bool neg = (d < 0);
d = floor(neg ? -d : d);
d = neg ? -d : d;
d = fmod(d, two32);
d = (d >= 0) ? d : d + two32;
return JSValue((uint32)d);
}
JSValue JSValue::convert(JSType *toType)
{
if (toType == &Any_Type) // yuck, something wrong with this
// maybe the base types should be
// a family of classes, not just instances
// of JSType ???
return *this;
else if (toType == &Integer_Type)
return valueToInteger(*this);
else {
JSClass *toClass = dynamic_cast<JSClass *>(toType);
if (toClass) {
if (tag == object_tag) {
JSClass *fromClass = dynamic_cast<JSClass *>(object->getType());
if (fromClass) {
while (fromClass != toClass) {
fromClass = fromClass->getSuperClass();
if (fromClass == NULL)
throw new JSException("Can't cast to unrelated class");
}
return *this;
}
else
throw new JSException("Can't cast a generic object to a class");
}
else
throw new JSException("Can't cast a non-object to a class");
}
}
return kUndefinedValue;
}
JSFunction::~JSFunction()
{
delete mICode;
}
JSString::JSString(const String& str)
{
size_t n = str.size();
resize(n);
traits_type::copy(begin(), str.begin(), n);
}
JSString::JSString(const String* str)
{
size_t n = str->size();
resize(n);
traits_type::copy(begin(), str->begin(), n);
}
JSString::JSString(const char* str)
{
size_t n = ::strlen(str);
resize(n);
std::transform(str, str + n, begin(), JavaScript::widen);
}
void JSString::append(const char* str)
{
size_t n = ::strlen(str);
size_t oldSize = size();
resize(oldSize + n);
std::transform(str, str + n, begin() + oldSize, JavaScript::widen);
}
void JSString::append(const JSStringBase* str)
{
size_t n = str->size();
size_t oldSize = size();
resize(oldSize + n);
traits_type::copy(begin() + oldSize, str->begin(), n);
}
JSString::operator String()
{
return String(begin(), size());
}
// # of sub-type relationship between this type and the other type
// (== MAX_INT if other is not a base type)
int32 JSType::distance(const JSType *other) const
{
if (other == this)
return 0;
if (mBaseType == NULL)
return NoRelation;
int32 baseDistance = mBaseType->distance(other);
if (baseDistance != NoRelation)
++baseDistance;
return baseDistance;
}
} /* namespace JSTypes */
} /* namespace JavaScript */

579
mozilla/js/js2/jstypes.h Normal file
View File

@@ -0,0 +1,579 @@
/* -*- 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.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is the JavaScript 2 Prototype.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU Public License (the "GPL"), in which case the
* provisions of the GPL are applicable instead of those above.
* If you wish to allow use of your version of this file only
* under the terms of the GPL and not to allow others to use your
* version of this file under the NPL, indicate your decision by
* deleting the provisions above and replace them with the notice
* and other provisions required by the GPL. If you do not delete
* the provisions above, a recipient may use your version of this
* file under either the NPL or the GPL.
*/
#ifndef jstypes_h
#define jstypes_h
#include "utilities.h"
#include "gc_allocator.h"
#include <vector>
#include <map>
#include <stack>
/* forward declare classes from JavaScript::ICG */
namespace JavaScript {
namespace ICG {
class ICodeModule;
} /* namespace ICG */
namespace Interpreter {
class Context;
} /* namespace Interpreter */
} /* namespace JavaScript */
namespace JavaScript {
namespace JSTypes {
using ICG::ICodeModule;
using Interpreter::Context;
class JSObject;
class JSArray;
class JSFunction;
class JSScope;
class JSString;
class JSType;
class Context;
/**
* All JavaScript data types.
*/
struct JSValue {
union {
int8 i8;
uint8 u8;
int16 i16;
uint16 u16;
int32 i32;
uint32 u32;
int64 i64;
uint64 u64;
float32 f32;
float64 f64;
JSObject* object;
JSArray* array;
JSFunction *function;
JSString *string;
JSType *type;
bool boolean;
};
/* These are the ECMA types, for use in 'toPrimitive' calls */
enum ECMA_type {
Undefined, Null, Boolean, Number, Object, String,
NoHint
};
enum {
i8_tag, u8_tag,
i16_tag, u16_tag,
i32_tag, u32_tag,
i64_tag, u64_tag,
f32_tag, f64_tag,
integer_tag,
object_tag, array_tag, function_tag, string_tag, boolean_tag, type_tag,
undefined_tag
} tag;
JSValue() : f64(0.0), tag(undefined_tag) {}
explicit JSValue(int32 i32) : i32(i32), tag(i32_tag) {}
explicit JSValue(uint32 u32) : u32(u32), tag(u32_tag) {}
explicit JSValue(float64 f64) : f64(f64), tag(f64_tag) {}
explicit JSValue(JSObject* object) : object(object), tag(object_tag) {}
explicit JSValue(JSArray* array) : array(array), tag(array_tag) {}
explicit JSValue(JSFunction* function) : function(function), tag(function_tag) {}
explicit JSValue(JSString* string) : string(string), tag(string_tag) {}
explicit JSValue(bool boolean) : boolean(boolean), tag(boolean_tag) {}
explicit JSValue(JSType* type) : type(type), tag(type_tag) {}
int32& operator=(int32 i32) { return (tag = i32_tag, this->i32 = i32); }
uint32& operator=(uint32 u32) { return (tag = u32_tag, this->u32 = u32); }
float64& operator=(float64 f64) { return (tag = f64_tag, this->f64 = f64); }
JSObject*& operator=(JSObject* object) { return (tag = object_tag, this->object = object); }
JSArray*& operator=(JSArray* array) { return (tag = array_tag, this->array = array); }
JSFunction*& operator=(JSFunction* function) { return (tag = function_tag, this->function = function); }
JSString*& operator=(JSString* string) { return (tag = string_tag, this->string = string); }
bool& operator=(bool boolean) { return (tag = boolean_tag, this->boolean = boolean); }
JSType*& operator=(JSType* type) { return (tag = type_tag, this->type = type); }
bool isFunction() const { return (tag == function_tag); }
bool isObject() const { return ((tag == object_tag) || (tag == function_tag) || (tag == array_tag) || (tag == type_tag)); }
bool isString() const { return (tag == string_tag); }
bool isBoolean() const { return (tag == boolean_tag); }
bool isNumber() const { return (tag == f64_tag) || (tag == integer_tag); }
/* this is correct wrt ECMA, The i32 & u32 kinds
will have to be converted (to doubles?) anyway because
we can't have overflow happening in generic arithmetic */
bool isUndefined() const { return (tag == undefined_tag); }
bool isNull() const { return ((tag == object_tag) && (this->object == NULL)); }
bool isNaN() const;
bool isNegativeInfinity() const;
bool isPositiveInfinity() const;
bool isNegativeZero() const;
bool isPositiveZero() const;
bool isType() const { return (tag == type_tag); }
JSValue toString() const { return (isString() ? *this : valueToString(*this)); }
JSValue toNumber() const { return (isNumber() ? *this : valueToNumber(*this)); }
JSValue toInt32() const { return ((tag == i32_tag) ? *this : valueToInt32(*this)); }
JSValue toUInt32() const { return ((tag == u32_tag) ? *this : valueToUInt32(*this)); }
JSValue toBoolean() const { return ((tag == boolean_tag) ? *this : valueToBoolean(*this)); }
JSValue toPrimitive(ECMA_type hint = NoHint) const;
JSValue convert(JSType *toType);
static JSValue valueToString(const JSValue& value);
static JSValue valueToNumber(const JSValue& value);
static JSValue valueToInteger(const JSValue& value);
static JSValue valueToInt32(const JSValue& value);
static JSValue valueToUInt32(const JSValue& value);
static JSValue valueToBoolean(const JSValue& value);
const JSType *getType() const; // map from tag type to JS2 type
int operator==(const JSValue& value) const;
};
Formatter& operator<<(Formatter& f, const JSValue& value);
#if defined(XP_MAC)
// copied from default template parameters in map.
typedef gc_allocator<std::pair<const String, JSValue> > gc_map_allocator;
#elif defined(XP_UNIX)
// FIXME: in libg++, they assume the map's allocator is a byte allocator,
// which is wrapped in a simple_allocator. this is crap.
typedef char _Char[1];
typedef gc_allocator<_Char> gc_map_allocator;
#elif defined(_WIN32)
// FIXME: MSVC++'s notion. this is why we had to add _Charalloc().
typedef gc_allocator<JSValue> gc_map_allocator;
#endif
/**
* GC-scannable array of values.
*/
typedef std::vector<JSValue, gc_allocator<JSValue> > JSValues;
extern const JSValue kUndefinedValue;
extern const JSValue kNaNValue;
extern const JSValue kTrueValue;
extern const JSValue kFalseValue;
extern const JSValue kNullValue;
extern const JSValue kNegativeZero;
extern const JSValue kPositiveZero;
extern const JSValue kNegativeInfinity;
extern const JSValue kPositiveInfinity;
extern JSType Any_Type;
extern JSType Integer_Type;
extern JSType Number_Type;
extern JSType Character_Type;
extern JSType String_Type;
extern JSType Function_Type;
extern JSType Array_Type;
extern JSType Type_Type;
extern JSType Boolean_Type;
extern JSType Null_Type;
extern JSType Void_Type;
extern JSType None_Type;
typedef std::map<String, JSValue, std::less<String>, gc_map_allocator> JSProperties;
/**
* Basic behavior of all JS objects, mapping a name to a value,
* with prototype-based inheritance.
*/
class JSObject : public gc_base {
protected:
JSProperties mProperties;
JSObject* mPrototype;
JSType* mType;
JSString* mClass; // this is the internal [[Class]] property
static JSObject *initJSObject();
static String ObjectString;
static JSObject *objectPrototypeObject;
void init(JSObject* prototype);
public:
JSObject() { init(objectPrototypeObject); }
JSObject(JSValue &constructor) { init(constructor.object->getProperty(widenCString("prototype")).object); }
JSObject(JSObject *prototype) { init(prototype); }
static void initObjectObject(JSScope *g);
bool hasProperty(const String& name)
{
return (mProperties.count(name) != 0);
}
const JSValue& getProperty(const String& name)
{
JSProperties::const_iterator i = mProperties.find(name);
if (i != mProperties.end())
return i->second;
if (mPrototype)
return mPrototype->getProperty(name);
return kUndefinedValue;
}
// return the property AND the object it's found in
// (would rather return references, but couldn't get that to work)
const JSValue getReference(JSValue &prop, const String& name)
{
JSProperties::const_iterator i = mProperties.find(name);
if (i != mProperties.end()) {
prop = i->second;
return JSValue(this);
}
if (mPrototype)
return mPrototype->getReference(prop, name);
return kUndefinedValue;
}
JSValue& setProperty(const String& name, const JSValue& value)
{
return (mProperties[name] = value);
}
const JSValue& deleteProperty(const String& name)
{
JSProperties::iterator i = mProperties.find(name);
if (i != mProperties.end()) {
mProperties.erase(i);
return kTrueValue;
}
if (mPrototype)
return mPrototype->deleteProperty(name);
return kFalseValue;
}
void setPrototype(JSObject* prototype)
{
mPrototype = prototype;
}
JSObject* getPrototype()
{
return mPrototype;
}
JSType* getType()
{
return mType;
}
JSString* getClass()
{
return mClass;
}
void setClass(JSString* s)
{
mClass = s;
}
virtual void printProperties(Formatter& f);
};
Formatter& operator<<(Formatter& f, JSObject& obj);
/**
* Private representation of a JavaScript array.
*/
class JSArray : public JSObject {
JSValues elements;
public:
JSArray() : elements(1) {}
JSArray(uint32 size) : elements(size) {}
JSArray(const JSValues &v) : elements(v) {}
uint32 length()
{
return elements.size();
}
JSValue& operator[](const JSValue& index)
{
// for now, we can only handle f64 index values.
uint32 n = (uint32)index.f64;
// obviously, a sparse representation might be better.
uint32 size = elements.size();
if (n >= size) expand(n, size);
return elements[n];
}
JSValue& operator[](uint32 n)
{
// obviously, a sparse representation might be better.
uint32 size = elements.size();
if (n >= size) expand(n, size);
return elements[n];
}
void resize(uint32 size)
{
elements.resize(size);
}
private:
void expand(uint32 n, uint32 size)
{
do {
size *= 2;
} while (n >= size);
elements.resize(size);
}
};
/**
* Private representation of a JS function. This simply
* holds a reference to the iCode module that is the
* compiled code of the function.
*/
class JSFunction : public JSObject {
static String FunctionString;
static JSObject *functionPrototypeObject;
ICodeModule* mICode;
protected:
JSFunction() : mICode(0) {}
typedef JavaScript::gc_traits_finalizable<JSFunction> traits;
typedef gc_allocator<JSFunction, traits> allocator;
public:
static void JSFunction::initFunctionObject(JSScope *g);
JSFunction(ICodeModule* iCode);
~JSFunction();
void* operator new(size_t) { return allocator::allocate(1); }
ICodeModule* getICode() { return mICode; }
virtual bool isNative() { return false; }
};
class JSNativeFunction : public JSFunction {
public:
typedef JSValue (*JSCode)(Context *cx, const JSValues& argv);
JSCode mCode;
JSNativeFunction(JSCode code) : mCode(code) {}
virtual bool isNative() { return true; }
};
class JSBinaryOperator : public JSFunction {
public:
typedef JSValue (*JSBinaryCode)(const JSValue& arg1, const JSValue& arg2);
JSBinaryCode mCode;
JSBinaryOperator(JSBinaryCode code) : mCode(code) {}
virtual bool isNative() { return true; }
};
#ifndef STLPORT
# if defined(XP_UNIX)
// bastring.cc defines a funky operator new that assumes a byte-allocator.
typedef string_char_traits<char16> JSCharTraits;
typedef gc_allocator<_Char> JSStringAllocator;
# else
typedef std::char_traits<char16> JSCharTraits;
typedef gc_allocator<char16> JSStringAllocator;
# endif
#else
typedef std::char_traits<char16> JSCharTraits;
typedef gc_allocator<char16> JSStringAllocator;
#endif
typedef std::basic_string<char16, JSCharTraits, JSStringAllocator> JSStringBase;
/**
* Garbage collectable UNICODE string.
*/
class JSString : public JSStringBase, public gc_base {
public:
JSString() {}
explicit JSString(const JSStringBase& str) : JSStringBase(str) {}
explicit JSString(const JSStringBase* str) : JSStringBase(*str) {}
explicit JSString(const String& str);
explicit JSString(const String* str);
explicit JSString(const char* str);
operator String();
void append(const char* str);
void append(const JSStringBase* str);
};
class JSException : public gc_base {
public:
JSException(char *mess) : value(JSValue(new JSString(mess))) { }
JSException(JSValue v) : value(v) { }
JSValue value;
};
inline Formatter& operator<<(Formatter& f, const JSString& str)
{
printString(f, str.begin(), str.end());
return f;
}
/**
* Provides a set of nested scopes.
*/
class JSScope : public JSObject {
protected:
JSScope* mParent;
JSProperties mTypes;
public:
JSScope(JSScope* parent = 0, JSObject* prototype = 0)
: mParent(parent)
{
if (prototype)
setPrototype(prototype);
}
JSScope* getParent()
{
return mParent;
}
bool isDefined(const String& name)
{
if (hasProperty(name))
return true;
if (mParent)
return mParent->isDefined(name);
return false;
}
const JSValue& getVariable(const String& name)
{
const JSValue& ret = getProperty(name);
if (ret.isUndefined() && mParent)
return mParent->getVariable(name);
return ret;
}
JSValue& setVariable(const String& name, const JSValue& value)
{
return (mProperties[name] = value);
}
JSValue& defineVariable(const String& name, JSType* type, const JSValue& value)
{
if (type != &Any_Type)
mTypes[name] = type;
return (mProperties[name] = value);
}
JSValue& defineVariable(const String& name, JSType* type)
{
if (type != &Any_Type)
mTypes[name] = type;
return (mProperties[name] = kUndefinedValue);
}
void setType(const String& name, JSType* type)
{
// only type variables that are defined in this scope.
JSProperties::iterator i = mProperties.find(name);
if (i != mProperties.end())
mTypes[name] = type;
else
if (mParent)
mParent->setType(name, type);
}
JSType* getType(const String& name)
{
JSType* result = &Any_Type;
// only consider types for variables defined in this scope.
JSProperties::const_iterator i = mProperties.find(name);
if (i != mProperties.end()) {
i = mTypes.find(name);
if (i != mTypes.end())
result = i->second.type;
} else {
// see if variable is defined in parent scope.
if (mParent)
result = mParent->getType(name);
}
return result;
}
JSValue& defineFunction(const String& name, ICodeModule* iCode)
{
JSValue value(new JSFunction(iCode));
return defineVariable(name, &Function_Type, value);
}
JSValue& defineNativeFunction(const String& name, JSNativeFunction::JSCode code)
{
JSValue value(new JSNativeFunction(code));
return defineVariable(name, &Function_Type, value);
}
};
class JSType : public JSObject {
protected:
String mName;
JSType *mBaseType;
public:
JSType(const String &name, JSType *baseType) : mName(name), mBaseType(baseType)
{
mType = &Type_Type;
}
enum { NoRelation = 0x7FFFFFFF };
const String& getName() const { return mName; }
int32 distance(const JSType *other) const;
};
inline void JSObject::init(JSObject* prototype) { mPrototype = prototype; mType = &Any_Type; mClass = new JSString(ObjectString); }
inline JSFunction::JSFunction(ICodeModule* iCode) : mICode(iCode), JSObject(functionPrototypeObject) { setClass(new JSString(FunctionString)); }
} /* namespace JSTypes */
} /* namespace JavaScript */
#endif /* jstypes_h */

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1 @@
#define XP_MAC 1

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,2 @@
#define XP_MAC 1
#define DEBUG 1

View File

@@ -0,0 +1,2 @@
#define XP_MAC 1
#define XP_MAC_MPW 1

Some files were not shown because too many files have changed in this diff Show More