Home | History | Annotate | Line # | Download | only in lint1
mem1.c revision 1.11.36.1
      1  1.11.36.1       jym /*	$NetBSD: mem1.c,v 1.11.36.1 2009/05/13 19:20:13 jym Exp $	*/
      2        1.2       cgd 
      3        1.1       cgd /*
      4        1.1       cgd  * Copyright (c) 1994, 1995 Jochen Pohl
      5        1.1       cgd  * All Rights Reserved.
      6        1.1       cgd  *
      7        1.1       cgd  * Redistribution and use in source and binary forms, with or without
      8        1.1       cgd  * modification, are permitted provided that the following conditions
      9        1.1       cgd  * are met:
     10        1.1       cgd  * 1. Redistributions of source code must retain the above copyright
     11        1.1       cgd  *    notice, this list of conditions and the following disclaimer.
     12        1.1       cgd  * 2. Redistributions in binary form must reproduce the above copyright
     13        1.1       cgd  *    notice, this list of conditions and the following disclaimer in the
     14        1.1       cgd  *    documentation and/or other materials provided with the distribution.
     15        1.1       cgd  * 3. All advertising materials mentioning features or use of this software
     16        1.1       cgd  *    must display the following acknowledgement:
     17        1.1       cgd  *      This product includes software developed by Jochen Pohl for
     18        1.1       cgd  *	The NetBSD Project.
     19        1.1       cgd  * 4. The name of the author may not be used to endorse or promote products
     20        1.1       cgd  *    derived from this software without specific prior written permission.
     21        1.1       cgd  *
     22        1.1       cgd  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     23        1.1       cgd  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     24        1.1       cgd  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     25        1.1       cgd  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     26        1.1       cgd  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     27        1.1       cgd  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     28        1.1       cgd  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     29        1.1       cgd  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     30        1.1       cgd  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     31        1.1       cgd  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     32        1.1       cgd  */
     33        1.1       cgd 
     34       1.11       jmc #if HAVE_NBTOOL_CONFIG_H
     35       1.11       jmc #include "nbtool_config.h"
     36       1.11       jmc #endif
     37       1.11       jmc 
     38        1.3  christos #include <sys/cdefs.h>
     39        1.7        tv #if defined(__RCSID) && !defined(lint)
     40  1.11.36.1       jym __RCSID("$NetBSD: mem1.c,v 1.11.36.1 2009/05/13 19:20:13 jym Exp $");
     41        1.1       cgd #endif
     42        1.1       cgd 
     43        1.1       cgd #include <sys/types.h>
     44        1.1       cgd #include <sys/param.h>
     45        1.1       cgd #include <stdlib.h>
     46        1.1       cgd #include <string.h>
     47        1.1       cgd #include <unistd.h>
     48        1.1       cgd 
     49        1.1       cgd #include "lint1.h"
     50        1.1       cgd 
     51        1.1       cgd /*
     52        1.1       cgd  * Filenames allocated by fnalloc() and fnnalloc() are shared.
     53        1.1       cgd  */
     54        1.1       cgd typedef struct fn {
     55        1.1       cgd 	char	*fn_name;
     56        1.1       cgd 	size_t	fn_len;
     57        1.1       cgd 	int	fn_id;
     58        1.1       cgd 	struct	fn *fn_nxt;
     59        1.1       cgd } fn_t;
     60        1.1       cgd 
     61        1.1       cgd static	fn_t	*fnames;
     62        1.1       cgd 
     63        1.5     lukem static	fn_t	*srchfn(const char *, size_t);
     64        1.1       cgd 
     65        1.1       cgd /*
     66        1.1       cgd  * Look for a Filename of length l.
     67        1.1       cgd  */
     68        1.1       cgd static fn_t *
     69        1.5     lukem srchfn(const char *s, size_t len)
     70        1.1       cgd {
     71        1.1       cgd 	fn_t	*fn;
     72        1.1       cgd 
     73        1.1       cgd 	for (fn = fnames; fn != NULL; fn = fn->fn_nxt) {
     74        1.1       cgd 		if (fn->fn_len == len && memcmp(fn->fn_name, s, len) == 0)
     75        1.1       cgd 			break;
     76        1.1       cgd 	}
     77        1.1       cgd 	return (fn);
     78        1.1       cgd }
     79        1.1       cgd 
     80        1.1       cgd /*
     81        1.1       cgd  * Return a shared string for filename s.
     82        1.1       cgd  */
     83        1.1       cgd const char *
     84        1.5     lukem fnalloc(const char *s)
     85        1.1       cgd {
     86        1.5     lukem 
     87        1.1       cgd 	return (s != NULL ? fnnalloc(s, strlen(s)) : NULL);
     88        1.1       cgd }
     89        1.1       cgd 
     90        1.1       cgd const char *
     91        1.5     lukem fnnalloc(const char *s, size_t len)
     92        1.1       cgd {
     93        1.1       cgd 	fn_t	*fn;
     94        1.1       cgd 
     95        1.1       cgd 	static	int	nxt_id = 0;
     96        1.1       cgd 
     97        1.1       cgd 	if (s == NULL)
     98        1.1       cgd 		return (NULL);
     99        1.1       cgd 
    100        1.1       cgd 	if ((fn = srchfn(s, len)) == NULL) {
    101        1.1       cgd 		fn = xmalloc(sizeof (fn_t));
    102        1.1       cgd 		/* Do not used strdup() because string is not NUL-terminated.*/
    103        1.1       cgd 		fn->fn_name = xmalloc(len + 1);
    104        1.1       cgd 		(void)memcpy(fn->fn_name, s, len);
    105        1.1       cgd 		fn->fn_name[len] = '\0';
    106        1.1       cgd 		fn->fn_len = len;
    107        1.1       cgd 		fn->fn_id = nxt_id++;
    108        1.1       cgd 		fn->fn_nxt = fnames;
    109        1.1       cgd 		fnames = fn;
    110        1.1       cgd 		/* Write id of this filename to the output file. */
    111        1.1       cgd 		outclr();
    112        1.1       cgd 		outint(fn->fn_id);
    113        1.1       cgd 		outchar('s');
    114        1.1       cgd 		outstrg(fn->fn_name);
    115        1.1       cgd 	}
    116        1.1       cgd 	return (fn->fn_name);
    117        1.1       cgd }
    118        1.1       cgd 
    119        1.1       cgd /*
    120        1.1       cgd  * Get id of a filename.
    121        1.1       cgd  */
    122        1.1       cgd int
    123        1.5     lukem getfnid(const char *s)
    124        1.1       cgd {
    125        1.1       cgd 	fn_t	*fn;
    126        1.1       cgd 
    127        1.1       cgd 	if (s == NULL || (fn = srchfn(s, strlen(s))) == NULL)
    128        1.1       cgd 		return (-1);
    129        1.1       cgd 	return (fn->fn_id);
    130        1.1       cgd }
    131        1.1       cgd 
    132        1.1       cgd /*
    133        1.1       cgd  * Memory for declarations and other things which must be available
    134        1.1       cgd  * until the end of a block (or the end of the translation unit)
    135        1.1       cgd  * are assoziated with the level (mblklev) of the block (or wiht 0).
    136        1.1       cgd  * Because these memory is allocated in large blocks associated with
    137        1.1       cgd  * a given level it can be freed easily at the end of a block.
    138        1.1       cgd  */
    139        1.1       cgd #define	ML_INC	((size_t)32)		/* Increment for length of *mblks */
    140        1.1       cgd 
    141        1.1       cgd typedef struct mbl {
    142        1.1       cgd 	void	*blk;			/* beginning of memory block */
    143        1.1       cgd 	void	*ffree;			/* first free byte */
    144        1.1       cgd 	size_t	nfree;			/* # of free bytes */
    145        1.1       cgd 	size_t	size;			/* total size of memory block */
    146        1.1       cgd 	struct	mbl *nxt;		/* next block */
    147        1.1       cgd } mbl_t;
    148        1.1       cgd 
    149        1.1       cgd /*
    150        1.1       cgd  * Array of pointers to lists of memory blocks. mblklev is used as
    151        1.1       cgd  * index into this array.
    152        1.1       cgd  */
    153        1.1       cgd static	mbl_t	**mblks;
    154        1.1       cgd 
    155        1.1       cgd /* number of elements in *mblks */
    156        1.1       cgd static	size_t	nmblks;
    157        1.1       cgd 
    158        1.1       cgd /* free list for memory blocks */
    159        1.1       cgd static	mbl_t	*frmblks;
    160        1.1       cgd 
    161        1.1       cgd /* length of new allocated memory blocks */
    162        1.1       cgd static	size_t	mblklen;
    163        1.1       cgd 
    164        1.5     lukem static	void	*xgetblk(mbl_t **, size_t);
    165        1.5     lukem static	void	xfreeblk(mbl_t **);
    166        1.5     lukem static	mbl_t	*xnewblk(void);
    167        1.1       cgd 
    168        1.1       cgd static mbl_t *
    169        1.5     lukem xnewblk(void)
    170        1.1       cgd {
    171       1.10  christos 	mbl_t	*mb = xmalloc(sizeof (mbl_t));
    172        1.1       cgd 
    173        1.1       cgd 	/* use mmap instead of malloc to avoid malloc's size overhead */
    174       1.10  christos 	mb->blk = xmapalloc(mblklen);
    175        1.1       cgd 	mb->size = mblklen;
    176        1.1       cgd 
    177        1.1       cgd 	return (mb);
    178        1.1       cgd }
    179        1.1       cgd 
    180        1.1       cgd /*
    181        1.1       cgd  * Allocate new memory. If the first block of the list has not enough
    182        1.1       cgd  * free space, or there is no first block, get a new block. The new
    183        1.1       cgd  * block is taken from the free list or, if there is no block on the
    184        1.1       cgd  * free list, is allocated using xnewblk(). If a new block is allocated
    185        1.1       cgd  * it is initialized with zero. Blocks taken from the free list are
    186        1.1       cgd  * zero'd in xfreeblk().
    187        1.1       cgd  */
    188        1.1       cgd static void *
    189        1.5     lukem xgetblk(mbl_t **mbp, size_t s)
    190        1.1       cgd {
    191        1.1       cgd 	mbl_t	*mb;
    192        1.1       cgd 	void	*p;
    193        1.8       jmc 	size_t	t = 0;
    194        1.1       cgd 
    195        1.1       cgd 	s = ALIGN(s);
    196        1.1       cgd 	if ((mb = *mbp) == NULL || mb->nfree < s) {
    197        1.1       cgd 		if ((mb = frmblks) == NULL) {
    198        1.8       jmc 			if (s > mblklen) {
    199        1.8       jmc 				t = mblklen;
    200        1.8       jmc 				mblklen = s;
    201        1.8       jmc 			}
    202        1.1       cgd 			mb = xnewblk();
    203        1.8       jmc 			if (t)
    204        1.8       jmc 				mblklen = t;
    205        1.1       cgd 			(void)memset(mb->blk, 0, mb->size);
    206        1.1       cgd 		} else {
    207        1.1       cgd 			frmblks = mb->nxt;
    208        1.1       cgd 		}
    209        1.1       cgd 		mb->ffree = mb->blk;
    210        1.9    simonb 		mb->nfree = mb->size;
    211        1.1       cgd 		mb->nxt = *mbp;
    212        1.1       cgd 		*mbp = mb;
    213        1.1       cgd 	}
    214        1.1       cgd 	p = mb->ffree;
    215        1.1       cgd 	mb->ffree = (char *)mb->ffree + s;
    216        1.1       cgd 	mb->nfree -= s;
    217        1.1       cgd 	return (p);
    218        1.1       cgd }
    219        1.1       cgd 
    220        1.1       cgd /*
    221        1.1       cgd  * Move all blocks from list *fmbp to free list. For each block, set all
    222        1.1       cgd  * used memory to zero.
    223        1.1       cgd  */
    224        1.1       cgd static void
    225        1.5     lukem xfreeblk(mbl_t **fmbp)
    226        1.1       cgd {
    227        1.1       cgd 	mbl_t	*mb;
    228        1.1       cgd 
    229        1.1       cgd 	while ((mb = *fmbp) != NULL) {
    230        1.1       cgd 		*fmbp = mb->nxt;
    231        1.1       cgd 		mb->nxt = frmblks;
    232        1.1       cgd 		frmblks = mb;
    233        1.1       cgd 		(void)memset(mb->blk, 0, mb->size - mb->nfree);
    234        1.1       cgd 	}
    235        1.1       cgd }
    236        1.1       cgd 
    237        1.1       cgd void
    238        1.5     lukem initmem(void)
    239        1.1       cgd {
    240        1.1       cgd 	int	pgsz;
    241        1.1       cgd 
    242        1.1       cgd 	pgsz = getpagesize();
    243        1.1       cgd 	mblklen = ((MBLKSIZ + pgsz - 1) / pgsz) * pgsz;
    244        1.1       cgd 
    245        1.1       cgd 	mblks = xcalloc(nmblks = ML_INC, sizeof (mbl_t *));
    246        1.1       cgd }
    247        1.1       cgd 
    248        1.5     lukem 
    249        1.1       cgd /*
    250        1.1       cgd  * Allocate memory associated with level l.
    251        1.1       cgd  */
    252        1.1       cgd void *
    253  1.11.36.1       jym getlblk(size_t l, size_t s)
    254        1.1       cgd {
    255        1.5     lukem 
    256        1.1       cgd 	while (l >= nmblks) {
    257        1.1       cgd 		mblks = xrealloc(mblks, (nmblks + ML_INC) * sizeof (mbl_t *));
    258        1.1       cgd 		(void)memset(&mblks[nmblks], 0, ML_INC * sizeof (mbl_t *));
    259        1.1       cgd 		nmblks += ML_INC;
    260        1.1       cgd 	}
    261        1.1       cgd 	return (xgetblk(&mblks[l], s));
    262        1.1       cgd }
    263        1.1       cgd 
    264        1.1       cgd void *
    265        1.5     lukem getblk(size_t s)
    266        1.1       cgd {
    267        1.5     lukem 
    268        1.1       cgd 	return (getlblk(mblklev, s));
    269        1.1       cgd }
    270        1.1       cgd 
    271        1.1       cgd /*
    272        1.1       cgd  * Free all memory associated with level l.
    273        1.1       cgd  */
    274        1.1       cgd void
    275        1.5     lukem freelblk(int l)
    276        1.1       cgd {
    277        1.5     lukem 
    278        1.1       cgd 	xfreeblk(&mblks[l]);
    279        1.1       cgd }
    280        1.1       cgd 
    281        1.1       cgd void
    282        1.5     lukem freeblk(void)
    283        1.1       cgd {
    284        1.5     lukem 
    285        1.1       cgd 	freelblk(mblklev);
    286        1.1       cgd }
    287        1.1       cgd 
    288        1.1       cgd /*
    289        1.1       cgd  * tgetblk() returns memory which is associated with the current
    290        1.1       cgd  * expression.
    291        1.1       cgd  */
    292        1.1       cgd static	mbl_t	*tmblk;
    293        1.1       cgd 
    294        1.1       cgd void *
    295        1.5     lukem tgetblk(size_t s)
    296        1.1       cgd {
    297        1.5     lukem 
    298        1.1       cgd 	return (xgetblk(&tmblk, s));
    299        1.1       cgd }
    300        1.1       cgd 
    301        1.1       cgd /*
    302        1.1       cgd  * Get memory for a new tree node.
    303        1.1       cgd  */
    304        1.1       cgd tnode_t *
    305        1.5     lukem getnode(void)
    306        1.1       cgd {
    307        1.5     lukem 
    308        1.1       cgd 	return (tgetblk(sizeof (tnode_t)));
    309        1.1       cgd }
    310        1.1       cgd 
    311        1.1       cgd /*
    312        1.4     soren  * Free all memory which is allocated by the current expression.
    313        1.1       cgd  */
    314        1.1       cgd void
    315        1.5     lukem tfreeblk(void)
    316        1.1       cgd {
    317        1.5     lukem 
    318        1.1       cgd 	xfreeblk(&tmblk);
    319        1.1       cgd }
    320        1.1       cgd 
    321        1.1       cgd /*
    322        1.1       cgd  * Save the memory which is used by the current expression. This memory
    323        1.1       cgd  * is not freed by the next tfreeblk() call. The pointer returned can be
    324        1.1       cgd  * used to restore the memory.
    325        1.1       cgd  */
    326        1.1       cgd mbl_t *
    327        1.5     lukem tsave(void)
    328        1.1       cgd {
    329        1.1       cgd 	mbl_t	*tmem;
    330        1.1       cgd 
    331        1.1       cgd 	tmem = tmblk;
    332        1.1       cgd 	tmblk = NULL;
    333        1.1       cgd 	return (tmem);
    334        1.1       cgd }
    335        1.1       cgd 
    336        1.1       cgd /*
    337        1.1       cgd  * Free all memory used for the current expression and the memory used
    338        1.1       cgd  * be a previous expression and saved by tsave(). The next call to
    339        1.1       cgd  * tfreeblk() frees the restored memory.
    340        1.1       cgd  */
    341        1.1       cgd void
    342        1.5     lukem trestor(mbl_t *tmem)
    343        1.1       cgd {
    344        1.5     lukem 
    345        1.1       cgd 	tfreeblk();
    346        1.1       cgd 	if (tmblk != NULL) {
    347        1.1       cgd 		free(tmblk->blk);
    348        1.1       cgd 		free(tmblk);
    349        1.1       cgd 	}
    350        1.1       cgd 	tmblk = tmem;
    351        1.1       cgd }
    352