Home | History | Annotate | Line # | Download | only in lint1
mem1.c revision 1.17.6.1
      1  1.17.6.1  pgoyette /*	$NetBSD: mem1.c,v 1.17.6.1 2017/01/07 08:56:59 pgoyette 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.17.6.1  pgoyette __RCSID("$NetBSD: mem1.c,v 1.17.6.1 2017/01/07 08:56:59 pgoyette 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.17.6.1  pgoyette struct repl {
     91  1.17.6.1  pgoyette 	char *orig;
     92  1.17.6.1  pgoyette 	char *repl;
     93  1.17.6.1  pgoyette 	size_t len;
     94  1.17.6.1  pgoyette 	struct repl *next;
     95  1.17.6.1  pgoyette };
     96  1.17.6.1  pgoyette 
     97  1.17.6.1  pgoyette struct repl *replist;
     98  1.17.6.1  pgoyette 
     99  1.17.6.1  pgoyette void
    100  1.17.6.1  pgoyette fnaddreplsrcdir(char *arg)
    101  1.17.6.1  pgoyette {
    102  1.17.6.1  pgoyette 	struct repl *r = xmalloc(sizeof(*r));
    103  1.17.6.1  pgoyette 
    104  1.17.6.1  pgoyette 	r->orig = arg;
    105  1.17.6.1  pgoyette 	if ((r->repl = strchr(arg, '=')) == NULL)
    106  1.17.6.1  pgoyette 		err(1, "Bad replacement directory spec `%s'", arg);
    107  1.17.6.1  pgoyette 	r->len = r->repl - r->orig;
    108  1.17.6.1  pgoyette 	*(r->repl)++ = '\0';
    109  1.17.6.1  pgoyette 	if (replist == NULL) {
    110  1.17.6.1  pgoyette 		r->next = NULL;
    111  1.17.6.1  pgoyette 	} else
    112  1.17.6.1  pgoyette 		r->next = replist;
    113  1.17.6.1  pgoyette 	replist = r;
    114  1.17.6.1  pgoyette }
    115  1.17.6.1  pgoyette 
    116  1.17.6.1  pgoyette const char *
    117  1.17.6.1  pgoyette fnxform(const char *name, size_t len)
    118  1.17.6.1  pgoyette {
    119  1.17.6.1  pgoyette 	static char buf[MAXPATHLEN];
    120  1.17.6.1  pgoyette 	struct repl *r;
    121  1.17.6.1  pgoyette 
    122  1.17.6.1  pgoyette 	for (r = replist; r; r = r->next)
    123  1.17.6.1  pgoyette 		if (r->len < len && memcmp(name, r->orig, r->len) == 0)
    124  1.17.6.1  pgoyette 			break;
    125  1.17.6.1  pgoyette 	if (r == NULL)
    126  1.17.6.1  pgoyette 		return name;
    127  1.17.6.1  pgoyette 	snprintf(buf, sizeof(buf), "%s%s", r->repl, name + r->len);
    128  1.17.6.1  pgoyette 	return buf;
    129  1.17.6.1  pgoyette }
    130  1.17.6.1  pgoyette 
    131       1.1       cgd const char *
    132       1.5     lukem fnnalloc(const char *s, size_t len)
    133       1.1       cgd {
    134       1.1       cgd 	fn_t	*fn;
    135       1.1       cgd 
    136       1.1       cgd 	static	int	nxt_id = 0;
    137       1.1       cgd 
    138       1.1       cgd 	if (s == NULL)
    139       1.1       cgd 		return (NULL);
    140       1.1       cgd 
    141       1.1       cgd 	if ((fn = srchfn(s, len)) == NULL) {
    142       1.1       cgd 		fn = xmalloc(sizeof (fn_t));
    143       1.1       cgd 		/* Do not used strdup() because string is not NUL-terminated.*/
    144       1.1       cgd 		fn->fn_name = xmalloc(len + 1);
    145       1.1       cgd 		(void)memcpy(fn->fn_name, s, len);
    146       1.1       cgd 		fn->fn_name[len] = '\0';
    147       1.1       cgd 		fn->fn_len = len;
    148       1.1       cgd 		fn->fn_id = nxt_id++;
    149       1.1       cgd 		fn->fn_nxt = fnames;
    150       1.1       cgd 		fnames = fn;
    151       1.1       cgd 		/* Write id of this filename to the output file. */
    152       1.1       cgd 		outclr();
    153       1.1       cgd 		outint(fn->fn_id);
    154       1.1       cgd 		outchar('s');
    155  1.17.6.1  pgoyette 		outstrg(fnxform(fn->fn_name, fn->fn_len));
    156       1.1       cgd 	}
    157       1.1       cgd 	return (fn->fn_name);
    158       1.1       cgd }
    159       1.1       cgd 
    160       1.1       cgd /*
    161       1.1       cgd  * Get id of a filename.
    162       1.1       cgd  */
    163       1.1       cgd int
    164       1.5     lukem getfnid(const char *s)
    165       1.1       cgd {
    166       1.1       cgd 	fn_t	*fn;
    167       1.1       cgd 
    168       1.1       cgd 	if (s == NULL || (fn = srchfn(s, strlen(s))) == NULL)
    169       1.1       cgd 		return (-1);
    170       1.1       cgd 	return (fn->fn_id);
    171       1.1       cgd }
    172       1.1       cgd 
    173       1.1       cgd /*
    174       1.1       cgd  * Memory for declarations and other things which must be available
    175       1.1       cgd  * until the end of a block (or the end of the translation unit)
    176      1.13       wiz  * are associated with the level (mblklev) of the block (or with 0).
    177      1.13       wiz  * Because this memory is allocated in large blocks associated with
    178       1.1       cgd  * a given level it can be freed easily at the end of a block.
    179       1.1       cgd  */
    180       1.1       cgd #define	ML_INC	((size_t)32)		/* Increment for length of *mblks */
    181       1.1       cgd 
    182       1.1       cgd typedef struct mbl {
    183       1.1       cgd 	void	*blk;			/* beginning of memory block */
    184       1.1       cgd 	void	*ffree;			/* first free byte */
    185       1.1       cgd 	size_t	nfree;			/* # of free bytes */
    186       1.1       cgd 	size_t	size;			/* total size of memory block */
    187       1.1       cgd 	struct	mbl *nxt;		/* next block */
    188       1.1       cgd } mbl_t;
    189       1.1       cgd 
    190       1.1       cgd /*
    191       1.1       cgd  * Array of pointers to lists of memory blocks. mblklev is used as
    192       1.1       cgd  * index into this array.
    193       1.1       cgd  */
    194       1.1       cgd static	mbl_t	**mblks;
    195       1.1       cgd 
    196       1.1       cgd /* number of elements in *mblks */
    197       1.1       cgd static	size_t	nmblks;
    198       1.1       cgd 
    199       1.1       cgd /* free list for memory blocks */
    200       1.1       cgd static	mbl_t	*frmblks;
    201       1.1       cgd 
    202       1.1       cgd /* length of new allocated memory blocks */
    203       1.1       cgd static	size_t	mblklen;
    204       1.1       cgd 
    205       1.5     lukem static	void	*xgetblk(mbl_t **, size_t);
    206       1.5     lukem static	void	xfreeblk(mbl_t **);
    207       1.5     lukem static	mbl_t	*xnewblk(void);
    208       1.1       cgd 
    209       1.1       cgd static mbl_t *
    210       1.5     lukem xnewblk(void)
    211       1.1       cgd {
    212      1.10  christos 	mbl_t	*mb = xmalloc(sizeof (mbl_t));
    213       1.1       cgd 
    214       1.1       cgd 	/* use mmap instead of malloc to avoid malloc's size overhead */
    215      1.10  christos 	mb->blk = xmapalloc(mblklen);
    216       1.1       cgd 	mb->size = mblklen;
    217       1.1       cgd 
    218       1.1       cgd 	return (mb);
    219       1.1       cgd }
    220       1.1       cgd 
    221       1.1       cgd /*
    222       1.1       cgd  * Allocate new memory. If the first block of the list has not enough
    223       1.1       cgd  * free space, or there is no first block, get a new block. The new
    224       1.1       cgd  * block is taken from the free list or, if there is no block on the
    225       1.1       cgd  * free list, is allocated using xnewblk(). If a new block is allocated
    226       1.1       cgd  * it is initialized with zero. Blocks taken from the free list are
    227       1.1       cgd  * zero'd in xfreeblk().
    228       1.1       cgd  */
    229       1.1       cgd static void *
    230       1.5     lukem xgetblk(mbl_t **mbp, size_t s)
    231       1.1       cgd {
    232       1.1       cgd 	mbl_t	*mb;
    233       1.1       cgd 	void	*p;
    234       1.8       jmc 	size_t	t = 0;
    235       1.1       cgd 
    236      1.15  christos 	s = WORST_ALIGN(s);
    237       1.1       cgd 	if ((mb = *mbp) == NULL || mb->nfree < s) {
    238      1.14  christos 		if ((mb = frmblks) == NULL || mb->size < s) {
    239       1.8       jmc 			if (s > mblklen) {
    240       1.8       jmc 				t = mblklen;
    241       1.8       jmc 				mblklen = s;
    242       1.8       jmc 			}
    243       1.1       cgd 			mb = xnewblk();
    244      1.17  christos #ifndef BLKDEBUG
    245      1.17  christos 			(void)memset(mb->blk, 0, mb->size);
    246      1.17  christos #endif
    247       1.8       jmc 			if (t)
    248       1.8       jmc 				mblklen = t;
    249       1.1       cgd 		} else {
    250       1.1       cgd 			frmblks = mb->nxt;
    251       1.1       cgd 		}
    252       1.1       cgd 		mb->ffree = mb->blk;
    253       1.9    simonb 		mb->nfree = mb->size;
    254       1.1       cgd 		mb->nxt = *mbp;
    255       1.1       cgd 		*mbp = mb;
    256       1.1       cgd 	}
    257       1.1       cgd 	p = mb->ffree;
    258       1.1       cgd 	mb->ffree = (char *)mb->ffree + s;
    259       1.1       cgd 	mb->nfree -= s;
    260      1.17  christos #ifdef BLKDEBUG
    261      1.17  christos 	(void)memset(p, 0, s);
    262      1.17  christos #endif
    263       1.1       cgd 	return (p);
    264       1.1       cgd }
    265       1.1       cgd 
    266       1.1       cgd /*
    267       1.1       cgd  * Move all blocks from list *fmbp to free list. For each block, set all
    268       1.1       cgd  * used memory to zero.
    269       1.1       cgd  */
    270       1.1       cgd static void
    271       1.5     lukem xfreeblk(mbl_t **fmbp)
    272       1.1       cgd {
    273       1.1       cgd 	mbl_t	*mb;
    274       1.1       cgd 
    275       1.1       cgd 	while ((mb = *fmbp) != NULL) {
    276       1.1       cgd 		*fmbp = mb->nxt;
    277       1.1       cgd 		mb->nxt = frmblks;
    278       1.1       cgd 		frmblks = mb;
    279      1.17  christos 		(void)memset(mb->blk, ZERO, mb->size - mb->nfree);
    280       1.1       cgd 	}
    281       1.1       cgd }
    282       1.1       cgd 
    283       1.1       cgd void
    284       1.5     lukem initmem(void)
    285       1.1       cgd {
    286       1.1       cgd 	int	pgsz;
    287       1.1       cgd 
    288       1.1       cgd 	pgsz = getpagesize();
    289       1.1       cgd 	mblklen = ((MBLKSIZ + pgsz - 1) / pgsz) * pgsz;
    290       1.1       cgd 
    291       1.1       cgd 	mblks = xcalloc(nmblks = ML_INC, sizeof (mbl_t *));
    292       1.1       cgd }
    293       1.1       cgd 
    294       1.5     lukem 
    295       1.1       cgd /*
    296       1.1       cgd  * Allocate memory associated with level l.
    297       1.1       cgd  */
    298       1.1       cgd void *
    299      1.12  christos getlblk(size_t l, size_t s)
    300       1.1       cgd {
    301       1.5     lukem 
    302       1.1       cgd 	while (l >= nmblks) {
    303       1.1       cgd 		mblks = xrealloc(mblks, (nmblks + ML_INC) * sizeof (mbl_t *));
    304       1.1       cgd 		(void)memset(&mblks[nmblks], 0, ML_INC * sizeof (mbl_t *));
    305       1.1       cgd 		nmblks += ML_INC;
    306       1.1       cgd 	}
    307       1.1       cgd 	return (xgetblk(&mblks[l], s));
    308       1.1       cgd }
    309       1.1       cgd 
    310       1.1       cgd void *
    311       1.5     lukem getblk(size_t s)
    312       1.1       cgd {
    313       1.5     lukem 
    314       1.1       cgd 	return (getlblk(mblklev, s));
    315       1.1       cgd }
    316       1.1       cgd 
    317       1.1       cgd /*
    318       1.1       cgd  * Free all memory associated with level l.
    319       1.1       cgd  */
    320       1.1       cgd void
    321       1.5     lukem freelblk(int l)
    322       1.1       cgd {
    323       1.5     lukem 
    324       1.1       cgd 	xfreeblk(&mblks[l]);
    325       1.1       cgd }
    326       1.1       cgd 
    327       1.1       cgd void
    328       1.5     lukem freeblk(void)
    329       1.1       cgd {
    330       1.5     lukem 
    331       1.1       cgd 	freelblk(mblklev);
    332       1.1       cgd }
    333       1.1       cgd 
    334       1.1       cgd /*
    335       1.1       cgd  * tgetblk() returns memory which is associated with the current
    336       1.1       cgd  * expression.
    337       1.1       cgd  */
    338       1.1       cgd static	mbl_t	*tmblk;
    339       1.1       cgd 
    340       1.1       cgd void *
    341       1.5     lukem tgetblk(size_t s)
    342       1.1       cgd {
    343       1.5     lukem 
    344       1.1       cgd 	return (xgetblk(&tmblk, s));
    345       1.1       cgd }
    346       1.1       cgd 
    347       1.1       cgd /*
    348       1.1       cgd  * Get memory for a new tree node.
    349       1.1       cgd  */
    350       1.1       cgd tnode_t *
    351       1.5     lukem getnode(void)
    352       1.1       cgd {
    353       1.5     lukem 
    354       1.1       cgd 	return (tgetblk(sizeof (tnode_t)));
    355       1.1       cgd }
    356       1.1       cgd 
    357       1.1       cgd /*
    358       1.4     soren  * Free all memory which is allocated by the current expression.
    359       1.1       cgd  */
    360       1.1       cgd void
    361       1.5     lukem tfreeblk(void)
    362       1.1       cgd {
    363       1.5     lukem 
    364       1.1       cgd 	xfreeblk(&tmblk);
    365       1.1       cgd }
    366       1.1       cgd 
    367       1.1       cgd /*
    368       1.1       cgd  * Save the memory which is used by the current expression. This memory
    369       1.1       cgd  * is not freed by the next tfreeblk() call. The pointer returned can be
    370       1.1       cgd  * used to restore the memory.
    371       1.1       cgd  */
    372       1.1       cgd mbl_t *
    373       1.5     lukem tsave(void)
    374       1.1       cgd {
    375       1.1       cgd 	mbl_t	*tmem;
    376       1.1       cgd 
    377       1.1       cgd 	tmem = tmblk;
    378       1.1       cgd 	tmblk = NULL;
    379       1.1       cgd 	return (tmem);
    380       1.1       cgd }
    381       1.1       cgd 
    382       1.1       cgd /*
    383       1.1       cgd  * Free all memory used for the current expression and the memory used
    384       1.1       cgd  * be a previous expression and saved by tsave(). The next call to
    385       1.1       cgd  * tfreeblk() frees the restored memory.
    386       1.1       cgd  */
    387       1.1       cgd void
    388       1.5     lukem trestor(mbl_t *tmem)
    389       1.1       cgd {
    390       1.5     lukem 
    391       1.1       cgd 	tfreeblk();
    392       1.1       cgd 	if (tmblk != NULL) {
    393       1.1       cgd 		free(tmblk->blk);
    394       1.1       cgd 		free(tmblk);
    395       1.1       cgd 	}
    396       1.1       cgd 	tmblk = tmem;
    397       1.1       cgd }
    398