#pragma title l$cldbex -- SAS/C double byte locale example
/*--------------------------------------------------------------------+
| |
| Copyright 1996 (c), SAS Institute Inc. |
| Unpublished - All Rights Reserved |
| |
| S A S / C S A M P L E |
| |
| Name: L$CLDEBX |
| |
| Language: C |
| |
| EntryPoint: @DYNAMN |
| |
| EntryType : C Linkage, reentrant |
| |
| Files Note: 'prefix' is the installation defined high level |
| qualifier for the SAS/C product. |
| |
| Purpose: Provide sample SAS/C DBCS user-added locale module. |
| |
| MVS - |
| |
| Source: prefix.SAMPLE.C(L$CLDBEX) |
| |
| Comp/Link: Use proc LC370CL, with parameter RENT and ENTRY=DYN. |
| Output module should placed in a library that can be |
| located by loadm() at execution time. |
| |
| Execute: via setlocale() function |
| |
| CMS - |
| |
| Source: SAMPLC MACLIB (L$CLSAMP) |
| |
| Note: The following compile/link are used for executing the |
| module as a nucelus extension. |
| |
| Compile: |
| global maclig lc370 |
| lc370 l$cldbex ( rent sname l$cldbe |
| |
| Link: |
| clink l$cldbex |
| load clink370 ( rldsave |
| genmode l$cldbex |
| |
| Execute: via setlocale() function |
| Notes: |
| |
| This is an example DBCS locale value module table to support |
| DBCS environment. It can be used via setlocale(LC_CTYPE,"DBEX"), |
| (or setlocale(LC_ALL,"DBEX") to allow recognition and processing |
| of double byte strings by other library routines and provides |
| sample DBCS strxfrm() and strcoll() functions for DBCS support |
| which are loaded via setlocale(LC_COLLATE,"DBEX") or |
| setlocale(LC_ALL,"DBEX") and are invoked when the strcoll/strxfrm |
| functions are called thereafter. |
| |
| This sample is provided for locales that need to either modify |
| the DBCS collation sequence, or supply their own strxfrm and |
| strcoll functions. See dbexxfrm and dbexcoll documentation below.|
| |
| The library functions strcoll and strxfrm provide limited builtin |
| DBCS support: shift_out, shift_in sequence, and end-of-string |
| recognition, and limited DBCS character range and string |
| validation. The library versions can be invoked through |
| setlocale(LC_COLLATE,"DBCS"); |
| |
| |
+--------------------------------------------------------------------*/
#include <stddef.h<
#include <locale.h<
#include <localeu.h<
#include <dynam.h<
#include <stdlib.h<
#include <errno.h<
#include <stdio.h<
#include <string.h<
#define SHIFT_OUT '\x0E' /* SHIFT_OUT to DBCS mode */
#define SHIFT_IN '\x0F' /* SHIFT_IN from DBCS mode */
#define DBCS_BLANK " " /* Double byte blank */
#define DBCS_COLLATE_LOW "\x42\x41" /* Lowest dbc in table */
#define DBCS_COLLATE_HIGH "\x42\xfe" /* Highest dbc in table */
#eject
static const struct dbex_collate_table_entry {
unsigned short int dbex_hex_value; /* hex value of the dbcs char*/
unsigned short int dbex_collate_pos; /* Relative position of the
char in collating sequence.
Can be, but not necessarily
the same as the hex value
*/
} dbex_collate_table [] = {
/* */
/* dbex_hex entries 0x0000-0x00ff represent the equivalent */
/* single byte ebcidic characters with values 00-ff */
/* */
{0x0000, 0x0000}, {0x0001, 0x4001}, /* 0000-000f <=> 00-0f */
{0x0002, 0x4002}, {0x0003, 0x4003},
{0x0004, 0x4004}, {0x0005, 0x4005},
{0x0006, 0x4006}, {0x0007, 0x4007},
{0x0008, 0x4008}, {0x0009, 0x4009},
{0x000a, 0x400a}, {0x000b, 0x400b},
{0x000c, 0x400c}, {0x000d, 0x400d},
{0x000e, 0x400e}, {0x000f, 0x400f},
{0x0010, 0x4010}, {0x0011, 0x4011}, /* 0010-001f <=> 10-1f */
{0x0012, 0x4012}, {0x0013, 0x4013},
{0x0014, 0x4014}, {0x0015, 0x4015},
{0x0016, 0x4016}, {0x0017, 0x4017},
{0x0018, 0x4018}, {0x0019, 0x4019},
{0x001a, 0x401a}, {0x001b, 0x401b},
{0x001c, 0x401c}, {0x001d, 0x401d},
{0x001e, 0x401e}, {0x001f, 0x401f},
{0x0020, 0x4020}, {0x0021, 0x4021}, /* 0020-002f <=> 20-2f */
{0x0022, 0x4022}, {0x0023, 0x4023},
{0x0024, 0x4024}, {0x0025, 0x4025},
{0x0026, 0x4026}, {0x0027, 0x4027},
{0x0028, 0x4028}, {0x0029, 0x4029},
{0x002a, 0x402a}, {0x002b, 0x402b},
{0x002c, 0x402c}, {0x002d, 0x402d},
{0x002e, 0x402e}, {0x002f, 0x402f},
{0x0030, 0x4030}, {0x0031, 0x4031}, /* 0030-003f <=> 30-3f */
{0x0032, 0x4032}, {0x0033, 0x4033},
{0x0034, 0x4034}, {0x0035, 0x4035},
{0x0036, 0x4036}, {0x0037, 0x4037},
{0x0038, 0x4038}, {0x0039, 0x4039},
{0x003a, 0x403a}, {0x003b, 0x403b},
{0x003c, 0x403c}, {0x003d, 0x403d},
{0x003e, 0x403e}, {0x003f, 0x403f},
{0x0040, 0x4040}, {0x0041, 0x4041}, /* 0040-004f <=> 40-4f */
{0x0042, 0x4042}, {0x0043, 0x4043},
{0x0044, 0x4044}, {0x0045, 0x4045},
{0x0046, 0x4046}, {0x0047, 0x4047},
{0x0048, 0x4048}, {0x0049, 0x4049},
{0x004a, 0x404a}, {0x004b, 0x404b},
{0x004c, 0x404c}, {0x004d, 0x404d},
{0x004e, 0x404e}, {0x004f, 0x404f},
{0x0050, 0x4050}, {0x0051, 0x4051}, /* 0050-005f <=>> 50-5f */
{0x0052, 0x4052}, {0x0053, 0x4053},
{0x0054, 0x4054}, {0x0055, 0x4055},
{0x0056, 0x4056}, {0x0057, 0x4057},
{0x0058, 0x4058}, {0x0059, 0x4059},
{0x005a, 0x405a}, {0x005b, 0x405b},
{0x005c, 0x405c}, {0x005d, 0x405d},
{0x005e, 0x405e}, {0x005f, 0x405f},
{0x0060, 0x4060}, {0x0061, 0x4061}, /* 0060-006f <=> 60-6f */
{0x0062, 0x4062}, {0x0063, 0x4063},
{0x0064, 0x4064}, {0x0065, 0x4065},
{0x0066, 0x4066}, {0x0067, 0x4067},
{0x0068, 0x4068}, {0x0069, 0x4069},
{0x006a, 0x406a}, {0x006b, 0x406b},
{0x006c, 0x406c}, {0x006d, 0x406d},
{0x006e, 0x406e}, {0x006f, 0x406f},
{0x0070, 0x4070}, {0x0071, 0x4071}, /* 0070-007f <=> 70-7f */
{0x0072, 0x4072}, {0x0073, 0x4073},
{0x0074, 0x4074}, {0x0075, 0x4075},
{0x0076, 0x4076}, {0x0077, 0x4077},
{0x0078, 0x4078}, {0x0079, 0x4079},
{0x007a, 0x407a}, {0x007b, 0x407b},
{0x007c, 0x407c}, {0x007d, 0x407d},
{0x007e, 0x407e}, {0x007f, 0x407f},
{0x0080, 0x4080}, {0x0081, 0x4081}, /* 0080-008f <=> 80-8f */
{0x0082, 0x4082}, {0x0083, 0x4083},
{0x0084, 0x4084}, {0x0085, 0x4085},
{0x0086, 0x4086}, {0x0087, 0x4087},
{0x0088, 0x4088}, {0x0089, 0x4089},
{0x008a, 0x408a}, {0x008b, 0x408b},
{0x008c, 0x408c}, {0x008d, 0x408d},
{0x008e, 0x408e}, {0x008f, 0x408f},
{0x0090, 0x4090}, {0x0091, 0x4091}, /* 0090-009f <=> 90-9f */
{0x0092, 0x4092}, {0x0093, 0x4093},
{0x0094, 0x4094}, {0x0095, 0x4095},
{0x0096, 0x4096}, {0x0097, 0x4097},
{0x0098, 0x4098}, {0x0099, 0x4099},
{0x009a, 0x409a}, {0x009b, 0x409b},
{0x009c, 0x409c}, {0x009d, 0x409d},
{0x009e, 0x409e}, {0x009f, 0x409f},
{0x00a0, 0x40a0}, {0x00a1, 0x40a1}, /* 00a0-00af <=> a0-af */
{0x00a2, 0x40a2}, {0x00a3, 0x40a3},
{0x00a4, 0x40a4}, {0x00a5, 0x40a5},
{0x00a6, 0x40a6}, {0x00a7, 0x40a7},
{0x00a8, 0x40a8}, {0x00a9, 0x40a9},
{0x00aa, 0x40aa}, {0x00ab, 0x40ab},
{0x00ac, 0x40ac}, {0x00ad, 0x40ad},
{0x00ae, 0x40ae}, {0x00af, 0x40af},
{0x00b0, 0x40b0}, {0x00b1, 0x40b1}, /* 00b0-00bf <=> b0-bf */
{0x00b2, 0x40b2}, {0x00b3, 0x40b3},
{0x00b4, 0x40b4}, {0x00b5, 0x40b5},
{0x00b6, 0x40b6}, {0x00b7, 0x40b7},
{0x00b8, 0x40b8}, {0x00b9, 0x40b9},
{0x00ba, 0x40ba}, {0x00bb, 0x40bb},
{0x00bc, 0x40bc}, {0x00bd, 0x40bd},
{0x00be, 0x40be}, {0x00bf, 0x40bf},
{0x00c0, 0x40c0}, {0x00c1, 0x40c1}, /* 00c0-00cf <=> c0-cf */
{0x00c2, 0x40c2}, {0x00c3, 0x40c3},
{0x00c4, 0x40c4}, {0x00c5, 0x40c5},
{0x00c6, 0x40c6}, {0x00c7, 0x40c7},
{0x00c8, 0x40c8}, {0x00c9, 0x40c9},
{0x00ca, 0x40ca}, {0x00cb, 0x40cb},
{0x00cc, 0x40cc}, {0x00cd, 0x40cd},
{0x00ce, 0x40ce}, {0x00cf, 0x40cf},
{0x00d0, 0x40d0}, {0x00d1, 0x40d1}, /* 00d0-00df <=> d0-df */
{0x00d2, 0x40d2}, {0x00d3, 0x40d3},
{0x00d4, 0x40d4}, {0x00d5, 0x40d5},
{0x00d6, 0x40d6}, {0x00d7, 0x40d7},
{0x00d8, 0x40d8}, {0x00d9, 0x40d9},
{0x00da, 0x40da}, {0x00db, 0x40db},
{0x00dc, 0x40dc}, {0x00dd, 0x40dd},
{0x00de, 0x40de}, {0x00df, 0x40df},
{0x00e0, 0x40e0}, {0x00e1, 0x40e1}, /* 00e0-00ef <=> e0-ef */
{0x00e2, 0x40e2}, {0x00e3, 0x40e3},
{0x00e4, 0x40e4}, {0x00e5, 0x40e5},
{0x00e6, 0x40e6}, {0x00e7, 0x40e7},
{0x00e8, 0x40e8}, {0x00e9, 0x40e9},
{0x00ea, 0x40ea}, {0x00eb, 0x40eb},
{0x00ec, 0x40ec}, {0x00ed, 0x40ed},
{0x00ee, 0x40ee}, {0x00ef, 0x40ef},
{0x00f0, 0x40f0}, {0x00f1, 0x40f1}, /* 00f0-00ff <=> f0-ff */
{0x00f2, 0x40f2}, {0x00f3, 0x40f3},
{0x00f4, 0x40f4}, {0x00f5, 0x40f5},
{0x00f6, 0x40f6}, {0x00f7, 0x40f7},
{0x00f8, 0x40f8}, {0x00f9, 0x40f9},
{0x00fa, 0x40fa}, {0x00fb, 0x40fb},
{0x00fc, 0x40fc}, {0x00fd, 0x40fd},
{0x00fe, 0x40fe}, {0x00ff, 0x40ff},
/* dbex_hex entries 0x4241-0x42fe are the double byte */
/* representation of the alpahnumeric and special symbols */
/* corresponding to their single byte representations */
/* */
{0x4040, 0x4040}, /* element (256) double byte blank */
{0x4241, 0x4241}, /* 4241-424f <=> 41-4f */
{0x4242, 0x4242}, {0x4243, 0x4243},
{0x4244, 0x4244}, {0x4245, 0x4245},
{0x4246, 0x4246}, {0x4247, 0x4247},
{0x4248, 0x4248}, {0x4249, 0x4249},
{0x424a, 0x424a}, {0x424b, 0x424b},
{0x424c, 0x424c}, {0x424d, 0x424d},
{0x424e, 0x424e}, {0x424f, 0x424f},
{0x4250, 0x4250}, {0x4251, 0x4251}, /* 4250-425f <=> 50-5f */
{0x4252, 0x4252}, {0x4253, 0x4253},
{0x4254, 0x4254}, {0x4255, 0x4255},
{0x4256, 0x4256}, {0x4257, 0x4257},
{0x4258, 0x4258}, {0x4259, 0x4259},
{0x425a, 0x425a}, {0x425b, 0x425b},
{0x425c, 0x425c}, {0x425d, 0x425d},
{0x425e, 0x425e}, {0x425f, 0x425f},
{0x4260, 0x4260}, {0x4261, 0x4261}, /* 4260-426f <=> 60-6f */
{0x4262, 0x4262}, {0x4263, 0x4263},
{0x4264, 0x4264}, {0x4265, 0x4265},
{0x4266, 0x4266}, {0x4267, 0x4267},
{0x4268, 0x4268}, {0x4269, 0x4269},
{0x426a, 0x426a}, {0x426b, 0x426b},
{0x426c, 0x426c}, {0x426d, 0x426d},
{0x426e, 0x426e}, {0x426f, 0x426f},
{0x4270, 0x4270}, {0x4271, 0x4271}, /* 4260-427f <=> 70-7f */
{0x4272, 0x4272}, {0x4273, 0x4273},
{0x4274, 0x4274}, {0x4275, 0x4275},
{0x4276, 0x4276}, {0x4277, 0x4277},
{0x4278, 0x4278}, {0x4279, 0x4279},
{0x427a, 0x427a}, {0x427b, 0x427b},
{0x427c, 0x427c}, {0x427d, 0x427d},
{0x427e, 0x427e}, {0x427f, 0x427f},
{0x4280, 0x4280}, {0x4281, 0x4281}, /* 4280-428f <=> 80-8f */
{0x4282, 0x4282}, {0x4283, 0x4283},
{0x4284, 0x4284}, {0x4285, 0x4285},
{0x4286, 0x4286}, {0x4287, 0x4287},
{0x4288, 0x4288}, {0x4289, 0x4289},
{0x428a, 0x428a}, {0x428b, 0x428b},
{0x428c, 0x428c}, {0x428d, 0x428d},
{0x428e, 0x428e}, {0x428f, 0x428f},
{0x4290, 0x4290}, {0x4291, 0x4291}, /* 4290-429f <=> 90-9f */
{0x4292, 0x4292}, {0x4293, 0x4293},
{0x4294, 0x4294}, {0x4295, 0x4295},
{0x4296, 0x4296}, {0x4297, 0x4297},
{0x4298, 0x4298}, {0x4299, 0x4299},
{0x429a, 0x429a}, {0x429b, 0x429b},
{0x429c, 0x429c}, {0x429d, 0x429d},
{0x429e, 0x429e}, {0x429f, 0x429f},
{0x42a0, 0x42a0}, {0x42a1, 0x42a1}, /* 42a0-42af <=> a0-af */
{0x42a2, 0x42a2}, {0x42a3, 0x42a3},
{0x42a4, 0x42a4}, {0x42a5, 0x42a5},
{0x42a6, 0x42a6}, {0x42a7, 0x42a7},
{0x42a8, 0x42a8}, {0x42a9, 0x42a9},
{0x42aa, 0x42aa}, {0x42ab, 0x42ab},
{0x42ac, 0x42ac}, {0x42ad, 0x42ad},
{0x42ae, 0x42ae}, {0x42af, 0x42af},
{0x42b0, 0x42b0}, {0x42b1, 0x42b1}, /* 42b0-42bf <=> b0-bf */
{0x42b2, 0x42b2}, {0x42b3, 0x42b3},
{0x42b4, 0x42b4}, {0x42b5, 0x42b5},
{0x42b6, 0x42b6}, {0x42b7, 0x42b7},
{0x42b8, 0x42b8}, {0x42b9, 0x42b9},
{0x42ba, 0x42ba}, {0x42bb, 0x42bb},
{0x42bc, 0x42bc}, {0x42bd, 0x42bd},
{0x42be, 0x42be}, {0x42bf, 0x42bf},
{0x42c0, 0x42c0}, {0x42c1, 0x42c1}, /* 42c0-42cf <=> c0-cf */
{0x42c2, 0x42c2}, {0x42c3, 0x42c3},
{0x42c4, 0x42c4}, {0x42c5, 0x42c5},
{0x42c6, 0x42c6}, {0x42c7, 0x42c7},
{0x42c8, 0x42c8}, {0x42c9, 0x42c9},
{0x42ca, 0x42ca}, {0x42cb, 0x42cb},
{0x42cc, 0x42cc}, {0x42cd, 0x42cd},
{0x42ce, 0x42ce}, {0x42cf, 0x42cf},
{0x42d0, 0x42d0}, {0x42d1, 0x42d1}, /* 42d0-42df <=> d0-df */
{0x42d2, 0x42d2}, {0x42d3, 0x42d3},
{0x42d4, 0x42d4}, {0x42d5, 0x42d5},
{0x42d6, 0x42d6}, {0x42d7, 0x42d7},
{0x42d8, 0x42d8}, {0x42d9, 0x42d9},
{0x42da, 0x42da}, {0x42db, 0x42db},
{0x42dc, 0x42dc}, {0x42dd, 0x42dd},
{0x42de, 0x42de}, {0x42df, 0x42df},
{0x42e0, 0x42e0}, {0x42e1, 0x42e1}, /* 42e0-42ef <=> e0-ef */
{0x42e2, 0x42e2}, {0x42e3, 0x42e3},
{0x42e4, 0x42e4}, {0x42e5, 0x42e5},
{0x42e6, 0x42e6}, {0x42e7, 0x42e7},
{0x42e8, 0x42e8}, {0x42e9, 0x42e9},
{0x42ea, 0x42ea}, {0x42eb, 0x42eb},
{0x42ec, 0x42ec}, {0x42ed, 0x42ed},
{0x42ee, 0x42ee}, {0x42ef, 0x42ef},
{0x42f0, 0x42f0}, {0x42f1, 0x42f1}, /* 42f0-42ff <=> f0-ff */
{0x42f2, 0x42f2}, {0x42f3, 0x42f3},
{0x42f4, 0x42f4}, {0x42f5, 0x42f5},
{0x42f6, 0x42f6}, {0x42f7, 0x42f7},
{0x42f8, 0x42f8}, {0x42f9, 0x42f9},
{0x42fa, 0x42fa}, {0x42fb, 0x42fb},
{0x42fc, 0x42fc}, {0x42fd, 0x42fd},
{0x42fe, 0x42fe}
};
#eject
#title l$cldbex -- dbexfrm - sample DBCS locale transform function
size_t dbexfrm(char *s1, const char *s2, size_t n, size_t *used)
{
/*-------------------------------------------------------------------
* ENTRY: <=== dbcexfrm
*
* USAGE: <=== Prototype call:
*
* size_t dbexfrm(char *s1, const char *s2, size_t n, size_t *used);
*
* nchar_xfrm = dbcexfrm(s1,s2,n,&used)
*
*
* ARGUMENTS: <===
*
* -ARG- -DCL--------- -DESCRIPTION-
*
* s1 char * pointer to the transformed string
* output array.
*
* s2 const char * pointer to input string array
*
* n size_t max number of bytes (chars) to written
* to s1 including terminating null. If n or
* more chars are required for the
* transformed string, only the first n
* are written and the string is not null
* terminated.
*
* used size_t * pointer to size_t (unsigned int) value
* where the number of input characters
* consumed from the input string s2 is
* returned.
*
*
* RETURNS: <=== The number of characters placed in the output
* transformation arrary is returned.
*
* Also the number of characters consumed(scanned)
* from the input string s2 is returned in size_t
* int pointed to by *used.
*
* ******This return is different from the*********
* ******ANSI strxfrm function. *********
*
* The total number of characters required for the
* dbcs transformation is obtained by a special call:
*
* total_dbcsxfrm_len = dbexfrm(0,s2,0,&used)
*
*
*
* NOTES: <=== The arguments to dbexfrm and return values have
* similiarities with the ANSI function strxfrm,
* but note the difference that the number of chars
* returned is the number xfrmed and placed in the
* buffer not the total length of the xfrmed string.
* Also the additional 4th paramter is required to
* pass back the number of chars consumed from the
* input string. This different functionality
* required for a locale that requires its own
* strxfrm function to be loaded via setlocale and
* invoked by the strxfrm function.
*
* The purpose of this function is to transform a
* valid mixed DBCS character string. into a string
* such that strcmp can be used correctly to compare
* two such transformed strings byte for byte so that
* the strings can be collated correctly according
* to the rules for mixed mode DBCS strings. Minimal
* validation is done to to check that the DBCS chars
* are in the proper range (x'4040', x'4241-x'42fe')
* and that shift-in shift-out sequences are proper.
* However, dbexfrm merely copies the invalid
* chars to the output string or null terminates it
* for shift_in errors. Also, this example uses
* a DBCS collation table so that if the values
* for the output side of the collation table were
* edited, the collation order would change.
*
*
* END
*-------------------------------------------------------------------*/
size_t s2len, /* input string length */
cmode, /* DBCS or SBCS mode */
nchar, /* # char in output buff */
tix; /* collation table index */
char *s2ptr, /* input string pointer */
errbuf [16] ; /* error message buffer */
*used = nchar = cmode = 0;
s2ptr = (char *) s2; /* set input string ptr */
s2len = strlen(s2ptr); /* and length */
while ((*used = s2ptr - s2) < s2len) { /* do until end of string*/
if (cmode) {
if (*(s2ptr) == SHIFT_IN) { /* check for SHIFT_IN */
cmode = 0; /* reset dbcs mode if so */
s2ptr++;
continue; /* and continue */
}
if (!(memcmp(s2ptr,DBCS_BLANK,2))){ /* check for a db blank */
if (nchar+2 <= n) /* if enough room */
memcpy(s1+nchar, /* copy table entry */
&(dbex_collate_table [256] .dbex_collate_pos),
2);
else if (n) return nchar; /* return #xfrmed so far */
nchar += 2;
s2ptr += 2;
continue;
}
/* validate char */
if ((memcmp(s2ptr,DBCS_COLLATE_LOW,2) >= 0)
&& (memcmp(s2ptr,DBCS_COLLATE_HIGH,2) <= 0)) {
/*-------------------------------------------------------------------+
* *
* If the table values were not semi-contigous it is possible to do *
* a search with the input dbcs char as the key against the *
* hex values in the collate table, however this is less efficient *
* than indexing directly into the collate table with some value *
* range checking and index maninipulation if possible. *
* *
+-------------------------------------------------------------------*/
/* copy correct collating position for db char to *s1 string from */
/* the collate table entry */
if (nchar+2 <= n) { /* make sure enough room */
tix = 256 + ((size_t) *(s2ptr+1) - 64); /* collate tbl indx*/
memcpy(s1+nchar,
&(dbex_collate_table [ tix ] .dbex_collate_pos),
2);
}
else if (n) return nchar; /* return # xfrmed so far */
nchar += 2;
s2ptr += 2;
continue;
}
else { /* char not in collate table, issue msg but copy it */
sprintf(errbuf,"...0x%02X%02X",*s2ptr,*(s2ptr+1));
fprintf(stderr,"Invalid DBCS string, =<%s>=",errbuf);
if (nchar+2 <= n) /* make sure enough room */
memcpy(s1+nchar,s2ptr,2);
else if (n) return nchar; /* return # xfrmed so far */
nchar += 2;
s2ptr += 2;
continue;
}
} /* end if (cmode) ... = dbcs mode */
else { /* single byte character mode */
if (*(s2ptr) == SHIFT_OUT) { /* check for SHIFT_OUT */
cmode = DBCS; /* set DBCS mode on if so*/
s2ptr++; /* dont include char */
continue; /* and continue */
}
/*----------------------------------------------------------+
* expand a single byte char to pseudo db char for collation*
* purposes so that the sb char collates ahead of the *
* equivalent db char e.g. 'A' < double byte A *
* transform 0XC1 -> 0x40C1 < 0x42C1 *
+----------------------------------------------------------*/
if (nchar+2 <= n) { /* make sure enough room */
*(s1+nchar) = ' '; /* insert blank */
*(s1+nchar+1) = *(s2ptr); /* copy char */
}
else if (n) return nchar; /* return number xfrm so far */
s2ptr++;
nchar += 2;
} /* end if (cmode) ... else */
} /* end while (*used = (2ptr < s2+strlen(s2))) */
if (cmode) /* should not be in dbcs mode */
fprintf(stderr,"Missing SHIFT_IN (0x0f) from DBCS mode");
if (nchar+1 <= n) /* null terminate if room */
*(s1+nchar) = '\0';
return nchar; /* return #chars in xfrm string*/
}
#eject
#title l$cldbex -- dbexcoll - sample DBCS locale collation function
int dbexcoll(const char *s1, const char *s2)
{
/*-------------------------------------------------------------------
* ENTRY: <=== dbexcoll name (externally visible)
*
* USAGE: <=== Prototype call:
*
* int dbexcoll(const char *s1, const char *s2);
*
* compare_result = dbexcoll(s1,s2);
*
*
* ARGUMENTS: <===
*
* -ARG- -DCL--------- -DESCRIPTION-
*
* s1 const *s1 pointer to the first string to be
* compared.
* s2 const *s2 pointer to the 2nd string to be
* compared.
*
*
* RETURNS: <=== 0 if the locale dependent transformation
* of strings s1 and s2 are equal.
* + a positive value (+)
* if transformed(s1) > transformed(s2)
* - a negative value (-)
* if transformed(s1) > transformed(s2)
*
*
* NOTES: <=== The 2 strings are first tranformed by invoking:
*
* After the two strings are transformed or
* partially transformed, the equivalent of a
* strcmp is done to compare transformed s1 and
* s2.
*
*
* END
*-------------------------------------------------------------------*/
int compare_result; /* compare result return */
int rem1, rem2; /* uncompared xfrmed chars */
/* remaining in xfrm buffers */
size_t s1len, s2len, s1xlen, s2xlen; /* input and xfrmed lengths */
size_t used1, used2; /* number of chars used */
/* from input strings */
#define BF_LIM 256 /* length of xfrm buffers */
char tx1wk [BF_LIM] , /* xfrm output buffers */
tx2wk [BF_LIM] ;
char *txfm1, *txfm2; /* xfrm buffer pointers */
/*-------------------------------------------------------------------*/
s1len = strlen((char *) s1); /* obtain lengths */
s2len = strlen((char *) s2);
txfm1 = tx1wk; /* point to transform */
txfm2 = tx2wk; /* work areas */
rem1 = rem2 = 0; /* zero xfrm uncompared rem. */
while (s1len && s2len ) { /* loop while chars remain */
/* un xfrmed in both strings */
used1 = used2 = 0;
if (!rem1)
s1xlen = dbexfrm(txfm1+rem1,s1,BF_LIM-rem1,&used1);
if (!rem2)
s2xlen = dbexfrm(txfm2+rem2,s2,BF_LIM-rem2,&used2);
if ((rem1 = s1xlen - s2xlen) > 0 ) {
compare_result = memcmp(txfm1,txfm2,s2xlen);
memmove(txfm1,txfm1+(BF_LIM-rem1),rem1);
}
else {
compare_result=memcmp(txfm1,txfm2,s1xlen);
rem2 = -rem1;
rem1 = 0;
if (rem2) memmove(txfm2,txfm2+(BF_LIM-rem2),rem2);
}
if (compare_result>0) return +1;
if (compare_result<0) return -1;
s1 += used1;
s2 += used2;
s1len -= used1;
s2len -= used2;
} /* end while */
if (!s1len && !s2len) return 0;
if (s1len) return +1;
else return -1;
}
#eject
#title l$cldbex -- "C" double byte locale example
static const struct _lc_collate dbex_collate = {
DBCS, /* double byte collation */
&dbex_collate_table, /* pointer to collate table */
&dbexcoll, /* ptr to strcoll fnc equiv */
&dbexfrm}; /* ptr to strxfrm fnc equiv */
static const struct _lc_ctype dbex_ctype = {
DBCS, /* double byte strings honored*/
0}; /* ptr to CTYPE table (NULL) */
static const void *dbex_all [5] = {
&dbex_collate, /* collate pointer */
&dbex_ctype, /* ctype pointer */
0, /* monetary pointer (NULL) */
0, /* numeric pointer (NULL) */
0 /* time format pointer (NULL) */
};
void *_dynamn() /* l$cldbex */
{
return (void *) &dbex_all;
}
|