Remove building with NOCRYPTO option
[minix3.git] / lib / libc / citrus / modules / citrus_hz.c
blob54dca51282de59996110b5df686b7b483880ed8e
1 /* $NetBSD: citrus_hz.c,v 1.4 2014/06/24 22:24:18 spz Exp $ */
3 /*-
4 * Copyright (c)2004, 2006 Citrus Project,
5 * All rights reserved.
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.
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.
30 #include <sys/cdefs.h>
31 #if defined(LIBC_SCCS) && !defined(lint)
32 __RCSID("$NetBSD: citrus_hz.c,v 1.4 2014/06/24 22:24:18 spz Exp $");
33 #endif /* LIBC_SCCS and not lint */
35 #include <sys/queue.h>
36 #include <sys/types.h>
37 #include <assert.h>
38 #include <errno.h>
39 #include <string.h>
40 #include <stdint.h>
41 #include <stdlib.h>
42 #include <stddef.h>
43 #include <limits.h>
44 #include <wchar.h>
46 #include "citrus_namespace.h"
47 #include "citrus_types.h"
48 #include "citrus_bcs.h"
49 #include "citrus_module.h"
50 #include "citrus_ctype.h"
51 #include "citrus_stdenc.h"
53 #include "citrus_hz.h"
54 #include "citrus_prop.h"
57 * wchar_t mapping:
59 * CTRL/ASCII 00000000 00000000 00000000 gxxxxxxx
60 * GB2312 00000000 00000000 0xxxxxxx gxxxxxxx
61 * 94/96*n (~M) 0mmmmmmm 0xxxxxxx 0xxxxxxx gxxxxxxx
64 #define ESCAPE_CHAR '~'
66 typedef enum {
67 CTRL = 0, ASCII = 1, GB2312 = 2, CS94 = 3, CS96 = 4
68 } charset_t;
70 typedef struct {
71 int start, end, width;
72 } range_t;
74 static const range_t ranges[] = {
75 #define RANGE(start, end) { start, end, (end - start) + 1 }
76 /* CTRL */ RANGE(0x00, 0x1F),
77 /* ASCII */ RANGE(0x20, 0x7F),
78 /* GB2312 */ RANGE(0x21, 0x7E),
79 /* CS94 */ RANGE(0x21, 0x7E),
80 /* CS96 */ RANGE(0x20, 0x7F),
81 #undef RANGE
84 typedef struct escape_t escape_t;
85 typedef struct {
86 charset_t charset;
87 size_t length;
88 #define ROWCOL_MAX 3
89 escape_t *escape;
90 } graphic_t;
92 typedef TAILQ_HEAD(escape_list, escape_t) escape_list;
93 struct escape_t {
94 TAILQ_ENTRY(escape_t) entry;
95 int ch;
96 graphic_t *left, *right;
97 escape_list *set;
100 #define GL(escape) ((escape)->left)
101 #define GR(escape) ((escape)->right)
102 #define SET(escape) ((escape)->set)
103 #define ESC(escape) ((escape)->ch)
104 #define INIT(escape) (TAILQ_FIRST(SET(escape)))
106 static __inline escape_t *
107 find_escape(escape_list *set, int ch)
109 escape_t *escape;
111 _DIAGASSERT(set != NULL);
113 TAILQ_FOREACH(escape, set, entry) {
114 if (ESC(escape) == ch)
115 break;
118 return escape;
121 typedef struct {
122 escape_list e0, e1;
123 graphic_t *ascii, *gb2312;
124 } _HZEncodingInfo;
126 #define E0SET(ei) (&(ei)->e0)
127 #define E1SET(ei) (&(ei)->e1)
128 #define INIT0(ei) (TAILQ_FIRST(E0SET(ei)))
129 #define INIT1(ei) (TAILQ_FIRST(E1SET(ei)))
131 typedef struct {
132 int chlen;
133 char ch[ROWCOL_MAX];
134 escape_t *inuse;
135 } _HZState;
137 typedef struct {
138 _HZEncodingInfo ei;
139 struct {
140 /* for future multi-locale facility */
141 _HZState s_mblen;
142 _HZState s_mbrlen;
143 _HZState s_mbrtowc;
144 _HZState s_mbtowc;
145 _HZState s_mbsrtowcs;
146 _HZState s_mbsnrtowcs;
147 _HZState s_wcrtomb;
148 _HZState s_wcsrtombs;
149 _HZState s_wcsnrtombs;
150 _HZState s_wctomb;
151 } states;
152 } _HZCTypeInfo;
154 #define _CEI_TO_EI(_cei_) (&(_cei_)->ei)
155 #define _CEI_TO_STATE(_cei_, _func_) (_cei_)->states.s_##_func_
157 #define _FUNCNAME(m) _citrus_HZ_##m
158 #define _ENCODING_INFO _HZEncodingInfo
159 #define _CTYPE_INFO _HZCTypeInfo
160 #define _ENCODING_STATE _HZState
161 #define _ENCODING_MB_CUR_MAX(_ei_) MB_LEN_MAX
162 #define _ENCODING_IS_STATE_DEPENDENT 1
163 #define _STATE_NEEDS_EXPLICIT_INIT(_ps_) ((_ps_)->inuse == NULL)
165 static __inline void
166 _citrus_HZ_init_state(_HZEncodingInfo * __restrict ei,
167 _HZState * __restrict psenc)
169 _DIAGASSERT(ei != NULL);
170 _DIAGASSERT(psenc != NULL);
172 psenc->chlen = 0;
173 psenc->inuse = INIT0(ei);
176 static __inline void
177 /*ARGSUSED*/
178 _citrus_HZ_pack_state(_HZEncodingInfo * __restrict ei,
179 void *__restrict pspriv, const _HZState * __restrict psenc)
181 /* ei may be unused */
182 _DIAGASSERT(pspriv != NULL);
183 _DIAGASSERT(psenc != NULL);
185 memcpy(pspriv, (const void *)psenc, sizeof(*psenc));
188 static __inline void
189 /*ARGSUSED*/
190 _citrus_HZ_unpack_state(_HZEncodingInfo * __restrict ei,
191 _HZState * __restrict psenc, const void * __restrict pspriv)
193 /* ei may be unused */
194 _DIAGASSERT(psenc != NULL);
195 _DIAGASSERT(pspriv != NULL);
197 memcpy((void *)psenc, pspriv, sizeof(*psenc));
200 static int
201 _citrus_HZ_mbrtowc_priv(_HZEncodingInfo * __restrict ei,
202 wchar_t * __restrict pwc, const char ** __restrict s, size_t n,
203 _HZState * __restrict psenc, size_t * __restrict nresult)
205 const char *s0;
206 wchar_t wc;
207 int bit, head, tail, len, ch;
208 graphic_t *graphic;
209 escape_t *candidate, *init;
210 const range_t *range;
212 _DIAGASSERT(ei != NULL);
213 /* pwc may be null */
214 _DIAGASSERT(s != NULL);
215 _DIAGASSERT(psenc != NULL);
216 _DIAGASSERT(nresult != NULL);
218 if (*s == NULL) {
219 _citrus_HZ_init_state(ei, psenc);
220 *nresult = 1;
221 return 0;
223 s0 = *s;
224 if (psenc->chlen < 0 || psenc->inuse == NULL)
225 return EINVAL;
227 wc = (wchar_t)0;
228 bit = head = tail = 0;
229 graphic = NULL;
230 for (len = 0; len <= MB_LEN_MAX; /**/) {
231 if (psenc->chlen == tail) {
232 if (n-- < 1) {
233 *s = s0;
234 *nresult = (size_t)-2;
235 return 0;
237 psenc->ch[psenc->chlen++] = *s0++;
238 ++len;
240 ch = (unsigned char)psenc->ch[tail++];
241 if (tail == 1) {
242 if ((ch & ~0x80) <= 0x1F) {
243 if (psenc->inuse != INIT0(ei))
244 break;
245 wc = (wchar_t)ch;
246 goto done;
248 if (ch & 0x80) {
249 graphic = GR(psenc->inuse);
250 bit = 0x80;
251 ch &= ~0x80;
252 } else {
253 graphic = GL(psenc->inuse);
254 if (ch == ESCAPE_CHAR)
255 continue;
256 bit = 0x0;
258 if (graphic == NULL)
259 break;
260 } else if (tail == 2 && psenc->ch[0] == ESCAPE_CHAR) {
261 if (tail < psenc->chlen)
262 return EINVAL;
263 if (ch == ESCAPE_CHAR) {
264 ++head;
265 } else if (ch == '\n') {
266 if (psenc->inuse != INIT0(ei))
267 break;
268 tail = psenc->chlen = 0;
269 continue;
270 } else {
271 candidate = NULL;
272 init = INIT0(ei);
273 _DIAGASSERT(init != NULL);
274 if (psenc->inuse == init) {
275 init = INIT1(ei);
276 } else if (INIT(psenc->inuse) == init) {
277 if (ESC(init) != ch)
278 break;
279 candidate = init;
281 if (candidate == NULL) {
282 candidate = find_escape(
283 SET(psenc->inuse), ch);
284 if (candidate == NULL) {
285 if (init == NULL ||
286 ESC(init) != ch)
287 break;
288 candidate = init;
291 psenc->inuse = candidate;
292 tail = psenc->chlen = 0;
293 continue;
295 } else if (ch & 0x80) {
296 if (graphic != GR(psenc->inuse))
297 break;
298 ch &= ~0x80;
299 } else {
300 if (graphic != GL(psenc->inuse))
301 break;
303 _DIAGASSERT(graphic != NULL);
304 range = &ranges[(size_t)graphic->charset];
305 if (range->start > ch || range->end < ch)
306 break;
307 wc <<= 8;
308 wc |= ch;
309 if (graphic->length == (tail - head)) {
310 if (graphic->charset > GB2312)
311 bit |= ESC(psenc->inuse) << 24;
312 wc |= bit;
313 goto done;
316 *nresult = (size_t)-1;
317 return EILSEQ;
318 done:
319 if (tail < psenc->chlen)
320 return EINVAL;
321 *s = s0;
322 if (pwc != NULL)
323 *pwc = wc;
324 psenc->chlen = 0;
325 *nresult = (wc == 0) ? 0 : len;
327 return 0;
330 static int
331 _citrus_HZ_wcrtomb_priv(_HZEncodingInfo * __restrict ei,
332 char * __restrict s, size_t n, wchar_t wc,
333 _HZState * __restrict psenc, size_t * __restrict nresult)
335 int bit, ch;
336 escape_t *candidate, *init;
337 graphic_t *graphic;
338 size_t len;
339 const range_t *range;
341 _DIAGASSERT(ei != NULL);
342 _DIAGASSERT(s != NULL);
343 _DIAGASSERT(psenc != NULL);
344 _DIAGASSERT(nresult != NULL);
346 if (psenc->chlen != 0 || psenc->inuse == NULL)
347 return EINVAL;
348 if (wc & 0x80) {
349 bit = 0x80;
350 wc &= ~0x80;
351 } else {
352 bit = 0x0;
354 if ((uint32_t)wc <= 0x1F) {
355 candidate = INIT0(ei);
356 graphic = (bit == 0)
357 ? candidate->left : candidate->right;
358 if (graphic == NULL)
359 goto ilseq;
360 range = &ranges[(size_t)CTRL];
361 len = 1;
362 } else if ((uint32_t)wc <= 0x7F) {
363 graphic = ei->ascii;
364 if (graphic == NULL)
365 goto ilseq;
366 candidate = graphic->escape;
367 range = &ranges[(size_t)graphic->charset];
368 len = graphic->length;
369 } else if ((uint32_t)wc <= 0x7F7F) {
370 graphic = ei->gb2312;
371 if (graphic == NULL)
372 goto ilseq;
373 candidate = graphic->escape;
374 range = &ranges[(size_t)graphic->charset];
375 len = graphic->length;
376 } else {
377 ch = (wc >> 24) & 0xFF;
378 candidate = find_escape(E0SET(ei), ch);
379 if (candidate == NULL) {
380 candidate = find_escape(E1SET(ei), ch);
381 if (candidate == NULL)
382 goto ilseq;
384 wc &= ~0xFF000000;
385 graphic = (bit == 0)
386 ? candidate->left : candidate->right;
387 if (graphic == NULL)
388 goto ilseq;
389 range = &ranges[(size_t)graphic->charset];
390 len = graphic->length;
392 if (psenc->inuse != candidate) {
393 init = INIT0(ei);
394 if (SET(psenc->inuse) == SET(candidate)) {
395 if (INIT(psenc->inuse) != init ||
396 psenc->inuse == init || candidate == init)
397 init = NULL;
398 } else if (candidate == (init = INIT(candidate))) {
399 init = NULL;
401 if (init != NULL) {
402 if (n < 2)
403 return E2BIG;
404 n -= 2;
405 psenc->ch[psenc->chlen++] = ESCAPE_CHAR;
406 psenc->ch[psenc->chlen++] = ESC(init);
408 if (n < 2)
409 return E2BIG;
410 n -= 2;
411 psenc->ch[psenc->chlen++] = ESCAPE_CHAR;
412 psenc->ch[psenc->chlen++] = ESC(candidate);
413 psenc->inuse = candidate;
415 if (n < len)
416 return E2BIG;
417 while (len-- > 0) {
418 ch = (wc >> (len * 8)) & 0xFF;
419 if (range->start > ch || range->end < ch)
420 goto ilseq;
421 psenc->ch[psenc->chlen++] = ch | bit;
423 memcpy(s, psenc->ch, psenc->chlen);
424 *nresult = psenc->chlen;
425 psenc->chlen = 0;
427 return 0;
429 ilseq:
430 *nresult = (size_t)-1;
431 return EILSEQ;
434 static __inline int
435 _citrus_HZ_put_state_reset(_HZEncodingInfo * __restrict ei,
436 char * __restrict s, size_t n, _HZState * __restrict psenc,
437 size_t * __restrict nresult)
439 escape_t *candidate;
441 _DIAGASSERT(ei != NULL);
442 _DIAGASSERT(s != NULL);
443 _DIAGASSERT(psenc != NULL);
444 _DIAGASSERT(nresult != NULL);
446 if (psenc->chlen != 0 || psenc->inuse == NULL)
447 return EINVAL;
448 candidate = INIT0(ei);
449 if (psenc->inuse != candidate) {
450 if (n < 2)
451 return E2BIG;
452 n -= 2;
453 psenc->ch[psenc->chlen++] = ESCAPE_CHAR;
454 psenc->ch[psenc->chlen++] = ESC(candidate);
456 if (n < 1)
457 return E2BIG;
458 if (psenc->chlen > 0)
459 memcpy(s, psenc->ch, psenc->chlen);
460 *nresult = psenc->chlen;
461 _citrus_HZ_init_state(ei, psenc);
463 return 0;
466 static __inline int
467 _citrus_HZ_stdenc_get_state_desc_generic(_HZEncodingInfo * __restrict ei,
468 _HZState * __restrict psenc, int * __restrict rstate)
470 _DIAGASSERT(ei != NULL);
471 _DIAGASSERT(psenc != NULL);
472 _DIAGASSERT(rstate != NULL);
474 if (psenc->chlen < 0 || psenc->inuse == NULL)
475 return EINVAL;
476 *rstate = (psenc->chlen == 0)
477 ? ((psenc->inuse == INIT0(ei))
478 ? _STDENC_SDGEN_INITIAL
479 : _STDENC_SDGEN_STABLE)
480 : ((psenc->ch[0] == ESCAPE_CHAR)
481 ? _STDENC_SDGEN_INCOMPLETE_SHIFT
482 : _STDENC_SDGEN_INCOMPLETE_CHAR);
484 return 0;
487 static __inline int
488 /*ARGSUSED*/
489 _citrus_HZ_stdenc_wctocs(_HZEncodingInfo * __restrict ei,
490 _csid_t * __restrict csid, _index_t * __restrict idx, wchar_t wc)
492 int bit;
494 _DIAGASSERT(csid != NULL);
495 _DIAGASSERT(idx != NULL);
497 if (wc & 0x80) {
498 bit = 0x80;
499 wc &= ~0x80;
500 } else {
501 bit = 0x0;
503 if ((uint32_t)wc <= 0x7F) {
504 *csid = (_csid_t)bit;
505 *idx = (_index_t)wc;
506 } else if ((uint32_t)wc <= 0x7F7F) {
507 *csid = (_csid_t)(bit | 0x8000);
508 *idx = (_index_t)wc;
509 } else {
510 *csid = (_index_t)(wc & ~0x00FFFF7F);
511 *idx = (_csid_t)(wc & 0x00FFFF7F);
514 return 0;
517 static __inline int
518 /*ARGSUSED*/
519 _citrus_HZ_stdenc_cstowc(_HZEncodingInfo * __restrict ei,
520 wchar_t * __restrict wc, _csid_t csid, _index_t idx)
522 _DIAGASSERT(ei != NULL);
523 _DIAGASSERT(wc != NULL);
525 *wc = (wchar_t)idx;
526 switch (csid) {
527 case 0x80:
528 case 0x8080:
529 *wc |= (wchar_t)0x80;
530 /*FALLTHROUGH*/
531 case 0x0:
532 case 0x8000:
533 break;
534 default:
535 *wc |= (wchar_t)csid;
538 return 0;
541 static void
542 _citrus_HZ_encoding_module_uninit(_HZEncodingInfo *ei)
544 escape_t *escape;
546 _DIAGASSERT(ei != NULL);
547 while ((escape = TAILQ_FIRST(E0SET(ei))) != NULL) {
548 TAILQ_REMOVE(E0SET(ei), escape, entry);
549 free(GL(escape));
550 free(GR(escape));
551 free(escape);
553 while ((escape = TAILQ_FIRST(E1SET(ei))) != NULL) {
554 TAILQ_REMOVE(E1SET(ei), escape, entry);
555 free(GL(escape));
556 free(GR(escape));
557 free(escape);
561 static int
562 _citrus_HZ_parse_char(void *context, const char *name, const char *s)
564 void **p;
565 escape_t *escape;
567 _DIAGASSERT(context != NULL && *context != NULL);
568 _DIAGASSERT(name != NULL);
569 _DIAGASSERT(s != NULL);
571 p = (void **)context;
572 escape = (escape_t *)p[0];
573 if (escape->ch != '\0')
574 return EINVAL;
575 escape->ch = *s++;
576 if (escape->ch == ESCAPE_CHAR || *s != '\0')
577 return EINVAL;
579 return 0;
582 static int
583 _citrus_HZ_parse_graphic(void *context, const char *name, const char *s)
585 void **p;
586 _HZEncodingInfo *ei;
587 escape_t *escape;
588 graphic_t *graphic;
590 _DIAGASSERT(context != NULL && *context != NULL);
591 _DIAGASSERT(name != NULL);
592 _DIAGASSERT(s != NULL);
594 p = (void **)context;
595 escape = (escape_t *)p[0];
596 ei = (_HZEncodingInfo *)p[1];
597 graphic = malloc(sizeof(*graphic));
598 if (graphic == NULL)
599 return ENOMEM;
600 memset(graphic, 0, sizeof(*graphic));
601 if (strcmp("GL", name) == 0) {
602 if (GL(escape) != NULL)
603 goto release;
604 GL(escape) = graphic;
605 } else if (strcmp("GR", name) == 0) {
606 if (GR(escape) != NULL)
607 goto release;
608 GR(escape) = graphic;
609 } else {
610 release:
611 free(graphic);
612 return EINVAL;
614 graphic->escape = escape;
615 if (_bcs_strncasecmp("ASCII", s, 5) == 0) {
616 if (s[5] != '\0')
617 return EINVAL;
618 graphic->charset = ASCII;
619 graphic->length = 1;
620 ei->ascii = graphic;
621 return 0;
622 } else if (_bcs_strncasecmp("GB2312", s, 6) == 0) {
623 if (s[6] != '\0')
624 return EINVAL;
625 graphic->charset = GB2312;
626 graphic->length = 2;
627 ei->gb2312 = graphic;
628 return 0;
629 } else if (strncmp("94*", s, 3) == 0) {
630 graphic->charset = CS94;
631 } else if (strncmp("96*", s, 3) == 0) {
632 graphic->charset = CS96;
633 } else {
634 return EINVAL;
636 s += 3;
637 switch(*s) {
638 case '1': case '2': case '3':
639 graphic->length = (size_t)(*s - '0');
640 if (*++s == '\0')
641 break;
642 /*FALLTHROUGH*/
643 default:
644 return EINVAL;
646 return 0;
649 static const _citrus_prop_hint_t escape_hints[] = {
650 _CITRUS_PROP_HINT_STR("CH", &_citrus_HZ_parse_char),
651 _CITRUS_PROP_HINT_STR("GL", &_citrus_HZ_parse_graphic),
652 _CITRUS_PROP_HINT_STR("GR", &_citrus_HZ_parse_graphic),
653 _CITRUS_PROP_HINT_END
656 static int
657 _citrus_HZ_parse_escape(void *context, const char *name, const char *s)
659 _HZEncodingInfo *ei;
660 escape_t *escape;
661 void *p[2];
663 _DIAGASSERT(context != NULL);
664 _DIAGASSERT(name != NULL);
665 _DIAGASSERT(s != NULL);
667 ei = (_HZEncodingInfo *)context;
668 escape = malloc(sizeof(*escape));
669 if (escape == NULL)
670 return EINVAL;
671 memset(escape, 0, sizeof(*escape));
672 if (strcmp("0", name) == 0) {
673 escape->set = E0SET(ei);
674 TAILQ_INSERT_TAIL(E0SET(ei), escape, entry);
675 } else if (strcmp("1", name) == 0) {
676 escape->set = E1SET(ei);
677 TAILQ_INSERT_TAIL(E1SET(ei), escape, entry);
678 } else {
679 free(escape);
680 return EINVAL;
682 p[0] = (void *)escape;
683 p[1] = (void *)ei;
684 return _citrus_prop_parse_variable(
685 escape_hints, (void *)&p[0], s, strlen(s));
688 static const _citrus_prop_hint_t root_hints[] = {
689 _CITRUS_PROP_HINT_STR("0", &_citrus_HZ_parse_escape),
690 _CITRUS_PROP_HINT_STR("1", &_citrus_HZ_parse_escape),
691 _CITRUS_PROP_HINT_END
694 static int
695 _citrus_HZ_encoding_module_init(_HZEncodingInfo * __restrict ei,
696 const void * __restrict var, size_t lenvar)
698 int errnum;
700 _DIAGASSERT(ei != NULL);
702 memset(ei, 0, sizeof(*ei));
703 TAILQ_INIT(E0SET(ei));
704 TAILQ_INIT(E1SET(ei));
705 errnum = _citrus_prop_parse_variable(
706 root_hints, (void *)ei, var, lenvar);
707 if (errnum != 0)
708 _citrus_HZ_encoding_module_uninit(ei);
709 return errnum;
712 /* ----------------------------------------------------------------------
713 * public interface for ctype
716 _CITRUS_CTYPE_DECLS(HZ);
717 _CITRUS_CTYPE_DEF_OPS(HZ);
719 #include "citrus_ctype_template.h"
721 /* ----------------------------------------------------------------------
722 * public interface for stdenc
725 _CITRUS_STDENC_DECLS(HZ);
726 _CITRUS_STDENC_DEF_OPS(HZ);
728 #include "citrus_stdenc_template.h"