Home | History | Annotate | Line # | Download | only in modules
citrus_mapper_zone.c revision 1.1
      1 /*	$NetBSD: citrus_mapper_zone.c,v 1.1 2003/06/25 09:51:48 tshiozak Exp $	*/
      2 
      3 /*-
      4  * Copyright (c)2003 Citrus Project,
      5  * All rights reserved.
      6  *
      7  * Redistribution and use in source and binary forms, with or without
      8  * modification, are permitted provided that the following conditions
      9  * are met:
     10  * 1. Redistributions of source code must retain the above copyright
     11  *    notice, this list of conditions and the following disclaimer.
     12  * 2. Redistributions in binary form must reproduce the above copyright
     13  *    notice, this list of conditions and the following disclaimer in the
     14  *    documentation and/or other materials provided with the distribution.
     15  *
     16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
     17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
     20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     26  * SUCH DAMAGE.
     27  */
     28 
     29 #include <sys/cdefs.h>
     30 #if defined(LIBC_SCCS) && !defined(lint)
     31 __RCSID("$NetBSD: citrus_mapper_zone.c,v 1.1 2003/06/25 09:51:48 tshiozak Exp $");
     32 #endif /* LIBC_SCCS and not lint */
     33 
     34 #include <assert.h>
     35 #include <errno.h>
     36 #include <stdio.h>
     37 #include <stdlib.h>
     38 #include <string.h>
     39 
     40 #include "citrus_namespace.h"
     41 #include "citrus_types.h"
     42 #include "citrus_bcs.h"
     43 #include "citrus_module.h"
     44 #include "citrus_region.h"
     45 #include "citrus_memstream.h"
     46 #include "citrus_mmap.h"
     47 #include "citrus_hash.h"
     48 #include "citrus_mapper.h"
     49 #include "citrus_mapper_zone.h"
     50 
     51 /* ---------------------------------------------------------------------- */
     52 
     53 _CITRUS_MAPPER_DECLS(mapper_zone);
     54 _CITRUS_MAPPER_DEF_OPS(mapper_zone);
     55 
     56 
     57 /* ---------------------------------------------------------------------- */
     58 
     59 struct _zone {
     60 	u_int32_t z_begin;
     61 	u_int32_t z_end;
     62 };
     63 
     64 struct _citrus_mapper_zone {
     65 	struct _zone	mz_row;
     66 	struct _zone	mz_col;
     67 	int		mz_col_bits;
     68 	int32_t		mz_row_offset;
     69 	int32_t		mz_col_offset;
     70 };
     71 
     72 struct _parse_state {
     73 	enum { S_BEGIN, S_OFFSET }	ps_state;
     74 	union {
     75 		u_int32_t	u_imm;
     76 		int32_t		s_imm;
     77 		struct _zone	zone;
     78 	} u;
     79 #define ps_u_imm	u.u_imm
     80 #define ps_s_imm	u.s_imm
     81 #define ps_zone		u.zone
     82 	int ps_top;
     83 };
     84 
     85 int
     86 _citrus_mapper_zone_mapper_getops(struct _citrus_mapper_ops *ops,
     87 				  size_t lenops, uint32_t expected_version)
     88 {
     89 	if (expected_version<_CITRUS_MAPPER_ABI_VERSION || lenops<sizeof(*ops))
     90 		return EINVAL;
     91 
     92 	memcpy(ops, &_citrus_mapper_zone_mapper_ops,
     93 	       sizeof(_citrus_mapper_zone_mapper_ops));
     94 
     95 	return 0;
     96 }
     97 
     98 #define BUFSIZE 20
     99 #define T_ERR	0x100
    100 #define T_IMM	0x101
    101 
    102 static int
    103 get_imm(struct _memstream *ms, struct _parse_state *ps)
    104 {
    105 	int sign = 0;
    106 	int c, i;
    107 	char buf[BUFSIZE+1], *p;
    108 
    109 	for (i=0; i<BUFSIZE; i++) {
    110 retry:
    111 		c = _memstream_peek(ms);
    112 		if (i==0) {
    113 			if (sign == 0 && (c == '+' || c == '-')) {
    114 				sign = c;
    115 				_memstream_getc(ms);
    116 				goto retry;
    117 			} else if (!_bcs_isdigit(c))
    118 				break;
    119 		} else if (!_bcs_isxdigit(c))
    120 			if (!(i==1 && c == 'x'))
    121 				break;
    122 		buf[i] = _memstream_getc(ms);
    123 	}
    124 	buf[i] = '\0';
    125 	ps->ps_u_imm = strtoul(buf, &p, 0);
    126 	if ((p-buf) != i)
    127 		return T_ERR;
    128 	if (sign == '-')
    129 		ps->ps_u_imm = (unsigned long)-(long)ps->ps_u_imm;
    130 	return T_IMM;
    131 }
    132 
    133 static int
    134 get_tok(struct _memstream *ms, struct _parse_state *ps)
    135 {
    136 	int c;
    137 
    138 loop:
    139 	c = _memstream_peek(ms);
    140 	if (c==0x00)
    141 		return EOF;
    142 	if (_bcs_isspace(c)) {
    143 		_memstream_getc(ms);
    144 		goto loop;
    145 	}
    146 
    147 	switch (ps->ps_state) {
    148 	case S_BEGIN:
    149 		switch (c) {
    150 		case ':':
    151 		case '-':
    152 		case '/':
    153 			_memstream_getc(ms);
    154 			return c;
    155 		case '0':
    156 		case '1':
    157 		case '2':
    158 		case '3':
    159 		case '4':
    160 		case '5':
    161 		case '6':
    162 		case '7':
    163 		case '8':
    164 		case '9':
    165 			return get_imm(ms, ps);
    166 		}
    167 		break;
    168 	case S_OFFSET:
    169 		switch (c) {
    170 		case '/':
    171 			_memstream_getc(ms);
    172 			return c;
    173 		case '+':
    174 		case '-':
    175 		case '0':
    176 		case '1':
    177 		case '2':
    178 		case '3':
    179 		case '4':
    180 		case '5':
    181 		case '6':
    182 		case '7':
    183 		case '8':
    184 		case '9':
    185 			return get_imm(ms, ps);
    186 		}
    187 		break;
    188 	}
    189 	return T_ERR;
    190 }
    191 
    192 static int
    193 parse_zone(struct _memstream *ms, struct _parse_state *ps, struct _zone *z)
    194 {
    195 	if (get_tok(ms, ps) != T_IMM)
    196 		return -1;
    197 	z->z_begin = ps->ps_u_imm;
    198 	if (get_tok(ms, ps) != '-')
    199 		return -1;
    200 	if (get_tok(ms, ps) != T_IMM)
    201 		return -1;
    202 	z->z_end = ps->ps_u_imm;
    203 
    204 	if (z->z_begin > z->z_end)
    205 		return -1;
    206 
    207 	return 0;
    208 }
    209 
    210 static int
    211 check_rowcol(struct _zone *z, int32_t ofs, uint32_t maxval)
    212 {
    213 	u_int32_t remain;
    214 
    215 	if (maxval != 0 && z->z_end >= maxval)
    216 		return -1;
    217 
    218 	if (ofs > 0) {
    219 		if (maxval == 0) {
    220 			/* this should 0x100000000 - z->z_end */
    221 			if (z->z_end == 0) {
    222 				remain = 0xFFFFFFFF;
    223 			} else {
    224 				remain = 0xFFFFFFFF - z->z_end + 1;
    225 			}
    226 		} else
    227 			remain = maxval - z->z_end;
    228 		if ((u_int32_t)ofs > remain)
    229 			return -1;
    230 	} else if (ofs < 0) {
    231 		if (z->z_begin < (u_int32_t)-ofs)
    232 			return -1;
    233 	}
    234 
    235 	return 0;
    236 }
    237 
    238 static int
    239 parse_var(struct _citrus_mapper_zone *mz, struct _memstream *ms)
    240 {
    241 	struct _parse_state ps;
    242 	int ret, isrc;
    243 	uint32_t rowmax, colmax;
    244 
    245 	ps.ps_state = S_BEGIN;
    246 
    247 	if (parse_zone(ms, &ps, &mz->mz_col))
    248 		return -1;
    249 
    250 	ret = get_tok(ms, &ps);
    251 	if (ret == '/') {
    252 		/* rowzone / colzone / bits */
    253 		isrc = 1;
    254 		mz->mz_row = mz->mz_col;
    255 
    256 		if (parse_zone(ms, &ps, &mz->mz_col))
    257 			return -1;
    258 		if (get_tok(ms, &ps) != '/')
    259 			return -1;
    260 		if (get_tok(ms, &ps) != T_IMM)
    261 			return -1;
    262 		mz->mz_col_bits = ps.ps_u_imm;
    263 		if (mz->mz_col_bits<0 || mz->mz_col_bits>32)
    264 			return -1;
    265 		ret = get_tok(ms, &ps);
    266 	} else {
    267 		/* colzone */
    268 		isrc = 0;
    269 		mz->mz_col_bits = 32;
    270 		mz->mz_row.z_begin = mz->mz_row.z_end = 0;
    271 	}
    272 	if (ret == ':') {
    273 		/* offset */
    274 		ps.ps_state = S_OFFSET;
    275 		if (get_tok(ms, &ps) != T_IMM)
    276 			return -1;
    277 		mz->mz_col_offset = ps.ps_s_imm;
    278 		if (isrc) {
    279 			/* row/col */
    280 			mz->mz_row_offset = mz->mz_col_offset;
    281 			if (get_tok(ms, &ps) != '/')
    282 				return -1;
    283 			if (get_tok(ms, &ps) != T_IMM)
    284 				return -1;
    285 			mz->mz_col_offset = ps.ps_s_imm;
    286 		} else
    287 			mz->mz_row_offset = 0;
    288 		ret = get_tok(ms, &ps);
    289 	}
    290 	if (ret != EOF)
    291 		return -1;
    292 
    293 	/* sanity check */
    294 	if (mz->mz_col_bits==32)
    295 		colmax = 0;
    296 	else
    297 		colmax = 1 << mz->mz_col_bits;
    298 	if (mz->mz_col_bits==0)
    299 		rowmax = 0;
    300 	else
    301 		rowmax = 1 << (32-mz->mz_col_bits);
    302 	if (check_rowcol(&mz->mz_col, mz->mz_col_offset, colmax))
    303 		return -1;
    304 	if (check_rowcol(&mz->mz_row, mz->mz_row_offset, rowmax))
    305 		return -1;
    306 
    307 	return 0;
    308 }
    309 
    310 static int
    311 /*ARGSUSED*/
    312 _citrus_mapper_zone_mapper_init(struct _citrus_mapper_area *__restrict ma,
    313 				struct _citrus_mapper * __restrict cm,
    314 				const char * __restrict dir,
    315 				const void * __restrict var, size_t lenvar,
    316 				struct _citrus_mapper_traits * __restrict mt,
    317 				size_t lenmt)
    318 {
    319 	struct _citrus_mapper_zone *mz;
    320 	struct _memstream ms;
    321 	struct _region r;
    322 
    323 	_DIAGASSERT(cm && dir && mt);
    324 
    325 	if (lenmt<sizeof(*mt))
    326 		return EINVAL;
    327 
    328 	mz = malloc(sizeof(*mz));
    329 	if (mz == NULL)
    330 		return errno;
    331 
    332 	_region_init(&r, (void *)var, lenvar);
    333 	_memstream_bind(&ms, &r);
    334 	if (parse_var(mz, &ms)) {
    335 		free(mz);
    336 		return EINVAL;
    337 	}
    338 	cm->cm_closure = mz;
    339 	mt->mt_src_max = mt->mt_dst_max = 1;	/* 1:1 converter */
    340 	mt->mt_state_size = 0;			/* stateless */
    341 
    342 	return 0;
    343 }
    344 
    345 static void
    346 /*ARGSUSED*/
    347 _citrus_mapper_zone_mapper_uninit(struct _citrus_mapper *cm)
    348 {
    349 }
    350 
    351 static int
    352 /*ARGSUSED*/
    353 _citrus_mapper_zone_mapper_convert(struct _citrus_mapper * __restrict cm,
    354 				   _citrus_index_t * __restrict dst,
    355 				   _citrus_index_t src, void * __restrict ps)
    356 {
    357 	u_int32_t row, col;
    358 	struct _citrus_mapper_zone *mz = cm->cm_closure;
    359 
    360 	if (mz->mz_col_bits == 32) {
    361 		col = src;
    362 		row = 0;
    363 		if (col < mz->mz_col.z_begin || col > mz->mz_col.z_end)
    364 			return _CITRUS_MAPPER_CONVERT_INVAL;
    365 		if (mz->mz_col_offset>0)
    366 			col += (u_int32_t)mz->mz_col_offset;
    367 		else
    368 			col -= (u_int32_t)-mz->mz_col_offset;
    369 		*dst = col;
    370 	} else {
    371 		col = src & (((u_int32_t)1<<mz->mz_col_bits)-1);
    372 		row = src >> mz->mz_col_bits;
    373 		if (row < mz->mz_row.z_begin || row > mz->mz_row.z_end ||
    374 		    col < mz->mz_col.z_begin || col > mz->mz_col.z_end)
    375 			return _CITRUS_MAPPER_CONVERT_INVAL;
    376 		if (mz->mz_col_offset>0)
    377 			col += (u_int32_t)mz->mz_col_offset;
    378 		else
    379 			col -= (u_int32_t)-mz->mz_col_offset;
    380 		if (mz->mz_row_offset>0)
    381 			row += (u_int32_t)mz->mz_row_offset;
    382 		else
    383 			row -= (u_int32_t)-mz->mz_row_offset;
    384 		*dst = col | (row << mz->mz_col_bits);
    385 	}
    386 	return _CITRUS_MAPPER_CONVERT_SUCCESS;
    387 }
    388 
    389 static void
    390 /*ARGSUSED*/
    391 _citrus_mapper_zone_mapper_init_state(struct _citrus_mapper * __restrict cm,
    392 				      void * __restrict ps)
    393 {
    394 }
    395