diff options
-rw-r--r-- | ChangeLog | 8 | ||||
-rw-r--r-- | catgets/Makefile | 15 | ||||
-rwxr-xr-x | catgets/xopen-msg.sed | 104 | ||||
-rw-r--r-- | stdlib/random_r.c | 331 |
4 files changed, 341 insertions, 117 deletions
@@ -1,3 +1,11 @@ +1998-05-22 10:56 Ulrich Drepper <drepper@cygnus.com> + + * catgets/Makefile (distribute): Add xopen-msg.h. + (generated): Add de.msg and de.cat. + (tests): Add do-gencat-test. + (do-gencat-test): New goal. Run gencat on a generated msg file. + * catgets/xopen-msg.h: New file. + 1998-05-22 Ulrich Drepper <drepper@cygnus.com> * catgets/open_catalog.c (__open_catalog): Use byteswap.h diff --git a/catgets/Makefile b/catgets/Makefile index ee464c1adc..7ce634ff5b 100644 --- a/catgets/Makefile +++ b/catgets/Makefile @@ -22,7 +22,7 @@ subdir := catgets headers = nl_types.h -distribute = catgetsinfo.h config.h +distribute = catgetsinfo.h config.h xopen-msg.sed routines = catgets open_catalog others = gencat install-bin = gencat @@ -40,3 +40,16 @@ $(objpfx)gencat: $(gencat-modules:%=$(objpfx)%.o) CPPFLAGS := -DNLSPATH='"$(localedir)/%L/%N:$(localedir)/%L/LC_MESSAGES/%N:$(localedir)/%l/%N:$(localedir)/%l/LC_MESSAGES/%N:"' \ -DHAVE_CONFIG_H $(CPPFLAGS) + +generated = de.msg de.cat + +.PHONY: do-gencat-test +tests: do-gencat-test +# This test just checks whether the program produces any error or not. +# The result is not tested. +do-gencat-test: $(objpfx)de.msg $(objpfx)gencat + $(built-program-cmd) $(objpfx)de.cat $(objpfx)de.msg + +# Generate a non-simple input file. +$(objpfx)de.msg: $(..)/po/de.po + sed -f xopen-msg.sed $< > $@ diff --git a/catgets/xopen-msg.sed b/catgets/xopen-msg.sed new file mode 100755 index 0000000000..b19c0bbd0e --- /dev/null +++ b/catgets/xopen-msg.sed @@ -0,0 +1,104 @@ +# po2msg.sed - Convert Uniforum style .po file to X/Open style .msg file +# Copyright (C) 1995 Free Software Foundation, Inc. +# Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1995. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# +# The first directive in the .msg should be the definition of the +# message set number. We use always set number 1. +# +1 { + i\ +$set 1 # Automatically created by po2msg.sed + h + s/.*/0/ + x +} +# +# We copy all comments into the .msg file. Perhaps they can help. +# +/^#/ s/^#[ ]*/$ /p +# +# We copy the original message as a comment into the .msg file. +# +/^msgid/ { +# Does not work now +# /"$/! { +# s/\\$// +# s/$/ ... (more lines following)"/ +# } + s/^msgid[ ]*"\(.*\)"$/$ Original Message: \1/ + p +} +# +# The .msg file contains, other then the .po file, only the translations +# but each given a unique ID. Starting from 1 and incrementing by 1 for +# each message we assign them to the messages. +# It is important that the .po file used to generate the cat-id-tbl.c file +# (with po-to-tbl) is the same as the one used here. (At least the order +# of declarations must not be changed.) +# +/^msgstr/ { + s/msgstr[ ]*"\(.*\)"/\1/ + x +# The following nice solution is by +# Bruno <Haible@ma2s2.mathematik.uni-karlsruhe.de> + td +# Increment a decimal number in pattern space. +# First hide trailing `9' digits. + :d + s/9\(_*\)$/_\1/ + td +# Assure at least one digit is available. + s/^\(_*\)$/0\1/ +# Increment the last digit. + s/8\(_*\)$/9\1/ + s/7\(_*\)$/8\1/ + s/6\(_*\)$/7\1/ + s/5\(_*\)$/6\1/ + s/4\(_*\)$/5\1/ + s/3\(_*\)$/4\1/ + s/2\(_*\)$/3\1/ + s/1\(_*\)$/2\1/ + s/0\(_*\)$/1\1/ +# Convert the hidden `9' digits to `0's. + s/_/0/g + x +# Bring the line in the format `<number> <message>' + G + s/^[^\n]*$/& / + s/\(.*\)\n\([0-9]*\)/\2 \1/ +# Clear flag from last substitution. + tb +# Append the next line. + :b + N +# Look whether second part is a continuation line. + s/\(.*\n\)"\(.*\)"/\1\2/ +# Yes, then branch. + ta + P + D +# Note that `D' includes a jump to the start!! +# We found a continuation line. But before printing insert '\'. + :a + s/\(.*\)\(\n.*\)/\1\\\2/ + P +# We cannot use the sed command `D' here + s/.*\n\(.*\)/\1/ + tb +} +d diff --git a/stdlib/random_r.c b/stdlib/random_r.c index 6355097a93..85a991a5c5 100644 --- a/stdlib/random_r.c +++ b/stdlib/random_r.c @@ -105,9 +105,17 @@ #define MAX_TYPES 5 /* Max number of types above. */ -static const int degrees[MAX_TYPES] = { DEG_0, DEG_1, DEG_2, DEG_3, DEG_4 }; -static const int seps[MAX_TYPES] = { SEP_0, SEP_1, SEP_2, SEP_3, SEP_4 }; +struct random_poly_info +{ + char seps[MAX_TYPES - 1]; + char degrees[MAX_TYPES - 1]; +}; +static const struct random_poly_info random_poly_info = +{ + { SEP_1, SEP_2, SEP_3, SEP_4 }, + { DEG_1, DEG_2, DEG_3, DEG_4 }, +}; @@ -120,37 +128,73 @@ static const int seps[MAX_TYPES] = { SEP_0, SEP_1, SEP_2, SEP_3, SEP_4 }; introduced by the L.C.R.N.G. Note that the initialization of randtbl[] for default usage relies on values produced by this routine. */ int -__srandom_r (x, buf) - unsigned int x; +__srandom_r (seed, buf) + unsigned int seed; struct random_data *buf; { - if (buf == NULL || buf->rand_type < TYPE_0 || buf->rand_type > TYPE_4) - return -1; + int type; + int32_t *state; + + if (buf == NULL) + goto fail; + type = buf->rand_type; + if ((unsigned)type >= MAX_TYPES) + goto fail; /* We must make sure the seed is not 0. Take arbitrarily 1 in this case. */ - buf->state[0] = x ? x : 1; - if (buf->rand_type != TYPE_0) + state = buf->state; + if (seed == 0) + seed = 1; + state[0] = seed; + if (type == TYPE_0) + goto done; + { - long int i; - for (i = 1; i < buf->rand_deg; ++i) + int degree; + long int word; + int jc; + int32_t *dst; + int kc; + int separation; + + degree = buf->rand_deg; + jc = degree - 1; + dst = state; + word = seed; + while (--jc >= 0) { + long int hi; + long int lo; + /* This does: state[i] = (16807 * state[i - 1]) % 2147483647; but avoids overflowing 31 bits. */ - long int hi = buf->state[i - 1] / 127773; - long int lo = buf->state[i - 1] % 127773; - long int test = 16807 * lo - 2836 * hi; - buf->state[i] = test + (test < 0 ? 2147483647 : 0); + ++dst; + hi = word / 127773; + lo = word % 127773; + word = 16807 * lo - 2836 * hi; + if (word < 0) + word += 2147483647; + *dst = word; } - buf->fptr = &buf->state[buf->rand_sep]; - buf->rptr = &buf->state[0]; - for (i = 0; i < 10 * buf->rand_deg; ++i) + state = buf->state; + degree = buf->rand_deg; + separation = buf->rand_sep; + buf->fptr = &state[separation]; + buf->rptr = &state[0]; + kc = 10 * degree; + while (--kc >= 0) { int32_t discard; (void) __random_r (buf, &discard); } } + goto done; + + fail: + return -1; + done: return 0; } @@ -174,57 +218,54 @@ __initstate_r (seed, arg_state, n, buf) size_t n; struct random_data *buf; { + int type; + int degree; + int separation; + int32_t *state; + int mess; + const struct random_poly_info *rpi; + if (buf == NULL) - return -1; + goto fail; - if (n < BREAK_1) + if (n >= BREAK_3) + type = n < BREAK_4 ? TYPE_3 : TYPE_4; + else if (n < BREAK_1) { if (n < BREAK_0) - { - __set_errno (EINVAL); - return -1; - } - buf->rand_type = TYPE_0; - buf->rand_deg = DEG_0; - buf->rand_sep = SEP_0; - } - else if (n < BREAK_2) - { - buf->rand_type = TYPE_1; - buf->rand_deg = DEG_1; - buf->rand_sep = SEP_1; - } - else if (n < BREAK_3) - { - buf->rand_type = TYPE_2; - buf->rand_deg = DEG_2; - buf->rand_sep = SEP_2; - } - else if (n < BREAK_4) - { - buf->rand_type = TYPE_3; - buf->rand_deg = DEG_3; - buf->rand_sep = SEP_3; + goto fail; + type = TYPE_0; } else - { - buf->rand_type = TYPE_4; - buf->rand_deg = DEG_4; - buf->rand_sep = SEP_4; - } + type = n < BREAK_2 ? TYPE_1 : TYPE_2; + + state = &((int32_t *) arg_state)[1]; /* First location. */ + buf->state = state; + mess = TYPE_0; + if (type == TYPE_0) + goto skip_to_here; + + rpi = &random_poly_info; + degree = rpi->degrees[type - 1]; + separation = rpi->seps[type - 1]; - buf->state = &((int32_t *) arg_state)[1]; /* First location. */ /* Must set END_PTR before srandom. */ - buf->end_ptr = &buf->state[buf->rand_deg]; + buf->end_ptr = &state[degree]; - __srandom_r (seed, buf); + buf->rand_deg = degree; + buf->rand_sep = separation; - if (buf->rand_type == TYPE_0) - buf->state[-1] = buf->rand_type; - else - buf->state[-1] = (MAX_TYPES * (buf->rptr - buf->state)) + buf->rand_type; + mess = (buf->rptr - state) * MAX_TYPES + type; + + skip_to_here: + state[-1] = mess; + + __srandom_r (seed, buf); return 0; + + fail: + return -1; } weak_alias (__initstate_r, initstate_r) @@ -242,45 +283,60 @@ __setstate_r (arg_state, buf) void *arg_state; struct random_data *buf; { - int32_t *new_state = (int32_t *) arg_state; - int type = new_state[0] % MAX_TYPES; - int rear = new_state[0] / MAX_TYPES; + int32_t *new_state; + int type; + int rear; + int32_t *old_state; + int32_t *ns1; + int degree; + int separation; + int mess; + int old_type; + int new_mess; + int *old_rptr; + const struct random_poly_info *rpi; if (buf == NULL) return -1; - if (buf->rand_type == TYPE_0) - buf->state[-1] = buf->rand_type; - else - buf->state[-1] = (MAX_TYPES * (buf->rptr - buf->state)) + buf->rand_type; - - switch (type) - { - case TYPE_0: - case TYPE_1: - case TYPE_2: - case TYPE_3: - case TYPE_4: - buf->rand_type = type; - buf->rand_deg = degrees[type]; - buf->rand_sep = seps[type]; - break; - default: - /* State info munged. */ - __set_errno (EINVAL); - return -1; - } - - buf->state = &new_state[1]; - if (buf->rand_type != TYPE_0) + old_type = buf->rand_type; + old_state = buf->state; + old_rptr = buf->rptr; + mess = old_type; + if (old_type != TYPE_0) + mess += (old_rptr - old_state) * MAX_TYPES; + old_state[-1] = mess; + + new_state = (int32_t *) arg_state; + new_mess = new_state[0]; + type = new_mess % MAX_TYPES; + rear = new_mess / MAX_TYPES; + + rpi = &random_poly_info; + degree = rpi->degrees[type - 1]; + separation = rpi->seps[type - 1]; + if (rear >= degree) + goto fail; + + ns1 = &new_state[1]; + if (type != TYPE_0) { - buf->rptr = &buf->state[rear]; - buf->fptr = &buf->state[(rear + buf->rand_sep) % buf->rand_deg]; + int t; + + t = rear + separation; + if (t >= degree) + t -= degree; + buf->rptr = &ns1[rear]; + buf->fptr = &ns1[t]; + buf->rand_deg = degree; + buf->rand_sep = separation; + buf->end_ptr = &ns1[degree]; } - /* Set end_ptr too. */ - buf->end_ptr = &buf->state[buf->rand_deg]; return 0; + + fail: + return -1; } weak_alias (__setstate_r, setstate_r) @@ -292,41 +348,84 @@ weak_alias (__setstate_r, setstate_r) the one at the front pointer. Then both pointers are advanced to the next location cyclically in the table. The value returned is the sum generated, reduced to 31 bits by throwing away the "least random" low bit. - Note: The code takes advantage of the fact that both the front and - rear pointers can't wrap on the same call by not testing the rear - pointer if the front one has wrapped. Returns a 31-bit random number. */ + Returns a 31-bit random number. */ int __random_r (buf, result) struct random_data *buf; int32_t *result; { - if (buf == NULL || result == NULL) - return -1; - - if (buf->rand_type == TYPE_0) - { - buf->state[0] = ((buf->state[0] * 1103515245) + 12345) & 0x7fffffff; - *result = buf->state[0]; - } - else - { - *buf->fptr += *buf->rptr; - /* Chucking least random bit. */ - *result = (*buf->fptr >> 1) & 0x7fffffff; - ++buf->fptr; - if (buf->fptr >= buf->end_ptr) - { - buf->fptr = buf->state; - ++buf->rptr; - } - else - { - ++buf->rptr; - if (buf->rptr >= buf->end_ptr) - buf->rptr = buf->state; - } - } + int32_t *res_ptr; + int rand_type; + + res_ptr = result; + rand_type = buf->rand_type; + if (buf == NULL || res_ptr == NULL) + goto fail; + + if (rand_type == TYPE_0) + goto old_style; + + { + int32_t *fp0; + int32_t *rp0; + int32_t sum; + int32_t fval; + int32_t rval; + int32_t rez; + int32_t *fp1; + int32_t *rp1; + int32_t *end; + int32_t *begin; + + /* 0 */ + fp0 = buf->fptr; + rp0 = buf->rptr; + + /* 1 */ + fval = *fp0; + rval = *rp0; + fp1 = fp0 + 1; + + /* 2 */ + sum = fval + rval; + rp1 = rp0 + 1; + + /* 3 */ + rez = (sum >> 1) & 0x7FFFFFFF; + *fp0 = sum; + end = buf->end_ptr; + + /* 4 */ + *res_ptr = rez; + begin = buf->state; + if (fp1 == end) + fp1 = begin; + if (rp1 == end) + rp1 = begin; + + /* 5 */ + buf->fptr = fp1; + buf->rptr = rp1; + } + goto done; + + old_style: + { + int32_t *state; + int32_t rez; + + state = buf->state; + rez = ((*state * 1103515245) + 12345) & 0x7FFFFFFF; + *res_ptr = rez; + *state = rez; + } + goto done; + + fail: + return -1; + + done: return 0; } |