home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 8 Other
/
08-Other.zip
/
uconv123.zip
/
uconvexp.c
< prev
next >
Wrap
Text File
|
2000-03-03
|
31KB
|
1,172 lines
/*
* uconvexp: Expand a uconv table
*
* Function:
* Expand a uconv table from the binary to a source file.
* This has the secondary effect of being a good test case.
*
* Author:
* Ken Borgendale kwb@us.ibm.com
*
* Copyright:
* Copyright (C) IBM Copr. 1995, 2000
*
* Notes:
* In order to always get the primary mapping last, the file
* is processed in two passes. The first pass puts out all
* alternate mappings, and the second pass puts out the
* primary mappings.
*/
#include <stdlib.h>
#include <string.h>
#include <wcstr.h>
#include <ctype.h>
#include <stdio.h>
#include <direct.h>
#include <io.h>
#define INCL_DOS
#include <os2.h>
/*
* Basic defines
*/
typedef unsigned long int uint32;
typedef unsigned short int uint16;
/*
* Do ULS specific defines
*/
#include <uconv.h>
#define SHIFT_TO 1
#define SHIFT_FROM 2
/*
* File structure of ucmap files. This is just a subset but allows
* us to get at a couple of fields for which there are no queries.
*/
typedef struct {
uint32 size; /* size of header */
uint16 bom; /* = 0xfeff (our endian) */
char version; /* = UC_VERSION */
char release; /* = UC_RELEASE */
char eyecatcher[4]; /* "ucv" */
uint16 codepage; /* IBM registered codepage */
uint16 flags;
char name[12]; /* Name of codepage */
uint32 resv2;
uint16 hdrlen; /* Length of base header */
uint16 copyright; /* Offset to copyright */
uint16 desc; /* Offset to description */
uint16 uconv_more; /* Additional codepoints */
} ucm_hdr_t;
/*
* Name table for names read from file
*/
typedef struct {
char * name;
uint16 uni;
uint16 len;
} NAMETAB;
#define NOTHEXVAL 999999
/*
* Function prototypes
*/
void help (void);
int doargs (int argc, char * * argv);
void putmap (int uchr, int match);
void outheader(FILE * f);
char * encname(uint16 encoding, int flag);
int getglyph(UniChar uni);
char * getline(char * buf, FILE * f);
int getnames(NAMETAB * * tab, char * name, char * * text, NAMETAB * * utab);
long gethexval(char * cp);
long parse (char * line, char * * value);
char * nexttoken(char * value);
void nullword(char * cptr);
FILE * findopen (char * fname, char * mode, char * path, int msg);
void searchenv (const char *fname, const char *env_var, char *path);
char * getpath (char *src, char *dst);
void replaceext(char * in, char * ext, char * out);
void touni(UniChar * ustr, char * str);
/*
* Encoding names
*/
struct {
char * name; /* Encoding name */
uint16 encoding; /* Encoding value */
uint16 class; /* UCONV class */
char min; /* Default min */
char max; /* Default max */
} EncNames[] = {
{ "sbcs-ebcdic", 0x1100, 1, 1, 1 },
{ "sbcs-ebcdic-v", 0x1100, 2, 1, 2 },
{ "dbcs-ebcdic", 0x1200, 2, 1, 2 },
{ "mbcs-ebcdic", 0x1301, 4, 1, 2 },
{ "sbcs-data", 0x2100, 1, 1, 1 },
{ "sbcs", 0x2100, 1, 1, 1 },
{ "dbcs-data", 0x2200, 2, 1, 2 },
{ "dbcs", 0x2200, 2, 1, 2 },
{ "mbcs-data", 0x2300, 3, 1, 2 },
{ "mbcs", 0x2300, 3, 1, 2 },
{ "sbcs-pc", 0x3100, 1, 1, 1 },
{ "dbcs-pc", 0x3200, 2, 1, 2 },
{ "mbcs-pc", 0x3300, 3, 1, 2 },
{ "sbcs-iso", 0x4100, 1, 1, 1 },
{ "sbcs-iso-v", 0x4100, 2, 1, 2 },
{ "sbcs-windows", 0x4105, 1, 1, 1 },
{ "sbcs-windows-v", 0x4105, 2, 1, 2 },
{ "sbcs-alt", 0xF100, 1, 1, 1 },
{ "ucs-2", 0x7200, 5, 2, 2 },
{ "utf-8", 0x7807, 6, 1, 3 },
{ "upf-8", 0x78FF, 0, 1, 3 },
{ NULL, 0, 0, 0, 0 }
};
char EncHex[32];
/*
* Class names. These are used for the standard output
*/
char * ClassName[] = {
"INVALID",
"SBCS",
"DBCS",
"MBCS",
"EBCDIC_STATEFUL",
"UCS-2",
"UTF-8",
"UPF-8",
};
/*
* Global variables
*/
char Debugflag; /* -d option */
char Quietflag; /* -q option */
char Stdflag; /* -s option */
char Upflag; /* -u option */
char Displayflag; /* -z option */
char Javaflag; /* -j option */
char CDRAflag; /* -c option */
char GlyphAdobe[64];
char GlyphIBM[12];
char Fn[260]; /* Expanded file name */
char InLine[256]; /* Input line from names file */
char InName[260]; /* Input file name */
char OutName[260]; /* Output file name */
int MaxLen;
int MinLen;
int CClass;
UconvObject Hand; /* Uconv object handle */
FILE * Outf;
NAMETAB * Unicode; /* Unicode name table */
char * Unitext; /* Unicode name data */
NAMETAB * Utab[256];
char * Value;
int CharCnt;
char DbcsStarter[256];
udcrange_t UdcRange[32];
char TableHdr[2048];
uconv_attribute_t Attr;
uint16 * JToChar;
uint16 * JToByte;
/*
* main: Expand uconv object
*/
main(int argc, char * * argv) {
int rc;
UniChar ucbuf[256];
int i, j;
FILE * ufile;
uint32 bootdrive;
char xfile[268];
/*
* Process the input arguments
*/
doargs(argc, argv);
if (!*InName) /* Input name not specified */
help(); /* Does not return */
if (!Quietflag) {
printf("uconvexp - (C) Copyright IBM Corp. 1995, 2000\n");
}
/*
* Open the input file (using uconv services)
*/
touni(ucbuf, InName);
rc = UniCreateUconvObject(ucbuf, &Hand);
if (rc) {
printf("Unable to open input uconv object: %s (%d)\n", InName, rc);
exit (4);
}
rc = UniQueryUconvObject(Hand, &Attr, sizeof(Attr), DbcsStarter, NULL, UdcRange);
if (rc) {
printf("Unable to query uconv object: %s (%d)\n", InName, rc);
exit (5);
}
Attr.options = 0;
if (Displayflag) {
Attr.displaymask = DSPMASK_DISPLAY;
}
if (CDRAflag) {
Attr.converttype = CVTTYPE_CDRA;
}
rc = UniSetUconvObject(Hand, &Attr);
if (rc) {
printf("Unable to set uconv object: %s (%d)\n", InName, rc);
exit (6);
}
/*
* Open the output file
*/
if (!OutName[0])
replaceext(InName, ".ucx", OutName);
Outf = fopen(OutName, "w");
if (!Outf) {
printf("Unable to open output file - %s\n", OutName);
exit(5);
}
/*
* Get the names of the unicode characters
*/
getnames(&Unicode, "unicode.nam", &Unitext, Utab);
/*
* Open the file to get extra header information. This is
* not needed for standard output.
*/
strcpy(xfile, "CODEPAGE\\");
strcat(xfile, InName);
ufile = findopen(xfile, "rb", "ULSPATH", 0);
if (!ufile) {
ufile = findopen(InName, "rb", "ULSPATH", 0);
}
if (!ufile) {
strcpy(xfile, "C:\\LANGUAGE\\CODEPAGE\\");
strcat(xfile, InName);
bootdrive = 3;
DosQuerySysInfo ( QSV_BOOT_DRIVE, QSV_BOOT_DRIVE, &bootdrive, 4);
xfile[0] = 'A' + bootdrive - 1;
ufile = findopen(xfile, "rb", "ULSPATH", 0);
}
if (ufile) {
fread(TableHdr, 2048, 1, ufile);
fclose(ufile);
} else {
printf("Extended header information not available\n");
}
/*
* Output the header of the uconvobj
*/
outheader(Outf);
/*
* Create the charmap section
*/
CharCnt = 0;
fprintf(Outf, Upflag?"#\nCHARMAP\n":"#\ncharmap\n");
/*
* First put out all entries which do not reverse map
*/
fprintf(Outf, "# Alternate mappings\n");
for (i=0; i<0xfffe; i++) {
putmap(i, 1);
}
/*
* Then put out all entries with do reverse map
*/
fprintf(Outf, "#\n# Primary mappings\n#\n");
for (i=0; i<0xfffe; i++) {
putmap(i, 0);
}
fprintf(Outf, Upflag?"END CHARMAP\n":"end charmap\n");
if (Javaflag) {
uint16 * index = calloc(2, 256);
uint16 maxpos = 0;
for (i=0; i<256; i++) {
uint16 ch;
if (i%8 == 0) {
printf(" \"");
}
ch = JToChar[i];
printf("\\u%04x", ch);
if (i%8 == 7) {
printf("\" + /* %02x - %02x */\n", i-7, i);
}
}
for (i=0; i<256; i++) {
for (j=0; j<maxpos; j++) {
if (!memcmp(JToByte+j, JToByte+(i*256), 512)) {
break;
}
}
index[i] = j;
if (j==maxpos) {
memmove(JToByte+j, JToByte+(i*256), 512);
maxpos += 256;
} else {
if (j+256 > maxpos)
maxpos = j+256;
}
}
printf("\n");
for (i=0; i<maxpos; i++) {
uint16 ch;
if (i%10 == 0) {
printf(" \"");
}
ch = JToByte[i];
printf("\\u%04x", ch);
if (i%10 == 9) {
printf("\" + /* %3d - %3d */\n", i-9, i);
}
}
printf("\n");
for (i=0; i<256; i++) {
printf("%4d,", index[i]);
if (i%16 == 15) {
printf("\n");
}
}
free(index);
}
/*
* Completion
*/
rc = UniFreeUconvObject(Hand);
if (!Quietflag)
printf("Codepage source '%s' created - %ld characters\n", OutName, CharCnt);
return 0;
}
/*
* help: Simple help
*/
void help(void) {
printf("uconvexp - Expand Unicode Conversion Object - V1.2 3 March 2000\n");
printf(" (C) Copyright IBM Corp. 1995, 2000\n\n");
printf("uconvexp uconvname outname -options\n");
printf("uconvname = Name of a uconv to expand (must be simple name)\n");
printf("outname = Name of output (defaults from uconv name)\n\n");
printf("-s = Standard - Produce output suitable for Unix\n");
printf("-u = Upper - Show hex constants and names in upper case\n");
printf("-q = Quiet - Do not put out informational messages\n\n");
printf("-f = Full - Use mapping to allow recreation of table\n");
printf("-c = CDRA - Use CDRA mappings (default is no CDRA)\n");
printf("-z = Display - Use display mappings (default is data mapping)\n");
printf("\nThe name of the uconv object must be the name known to the system.\n");
printf("It does not contain the path name. \n");
printf("\nexamples:\n");
printf(" uconvexp -f IBM850\n");
printf(" uconvexp -s -z IBM932 ibm-932.ucm\n");
exit (1);
}
/*
* putmap: Put out a map entry
* match = 0 : Put out only matching entries
* match = 1 : Put out only non-matching entries
* match = 2 : Put out all entries
*/
void putmap (int uchr, int match) {
UniChar ucbuf[256], * up;
char chbuf[256], * cp;
size_t insize, outsize, outlen;
size_t subs;
int skip;
int rc;
int j;
/*
* Convert the character from unicode to multibyte
*/
ucbuf[0] = uchr;
up = ucbuf;
cp = chbuf;
insize = 1;
outsize = 4;
subs = 0;
skip = 0;
rc = UniUconvFromUcs ( Hand, &up, &insize, (void * *)&cp, &outsize, &subs);
if (!rc) {
outsize = 4-outsize;
/*
* Check if this is a reverse translate
*/
if (match<2) {
up = ucbuf;
cp = chbuf;
insize = outsize;
outlen = 2;
rc = UniUconvToUcs ( Hand, (void * *)&cp, &insize, &up, &outlen, &subs);
outlen = 2-outlen;
if (rc || outlen != 1) { /* Reverse map failed */
printf("Bad glyph: %04x (%d, %d)\n", uchr, rc, outlen);
if (!match) /* Mismatch */
return;
} else {
if (*ucbuf == uchr) {
if (JToChar) {
JToChar[chbuf[0]] = uchr;
}
if (match) /* Fail on match */
return;
} else {
if (!match) /* Fail on mismatch */
return;
}
}
}
if (Attr.esid==ESID_mbcs_ebcdic) {
if (outsize>1 && (*chbuf==0x0e || *chbuf==0x0f)) {
skip = 1;
outsize--;
}
}
CharCnt++;
fprintf(Outf, Upflag?"<U%04X> ":"<u%04x> ", uchr);
for (j=0; j<4; j++) {
if (j<outsize)
fprintf(Outf, Upflag?"\\x%02X":"\\x%02x", chbuf[j+skip]);
else
fprintf(Outf, " ");
}
if (getglyph(uchr)) {
fprintf(Outf, " # %8s %s", GlyphIBM, GlyphAdobe);
}
fprintf(Outf, "\n");
if (JToByte) {
JToByte[uchr] = chbuf[0];
}
}
}
/*
* doargs: Process arguments
*/
int doargs(int argc, char * * argv) {
int argcnt, filecnt;
char * argp;
char swchar;
argcnt = 1;
filecnt = 0;
/*
* Read the arguments and decide what we are doing
*/
while (argcnt<argc) {
argp = argv[argcnt];
/*
* Check for switches.
*/
if (*argp == '-' && argp[1]) {
/* Process switches */
swchar = (char)tolower(argp[1]);
argp += 2;
switch (swchar) {
case '?':
help(); /* Does not return */
break;
/*
* -c -- CDRA mappings
*/
case 'c':
CDRAflag = 1;
break;
/*
* -f -- Full roundtrip mappings
*/
case 'f':
CDRAflag = 1;
Displayflag = 1;
break;
/*
* -d -- Debug option.
*/
case 'd':
Debugflag = 1;
if (argp[-1]=='D') Debugflag=2;
break;
/*
* -q -- Quiet option. This is normally used in cmd files
*/
case 'q':
Quietflag = 1;
break;
/*
* -s -- Standard flag
*/
case 's':
Stdflag = 1;
Upflag = 1;
break;
/*
* -u -- Uppercas flag
*/
case 'u':
Upflag = 1;
break;
/*
* -j -- Java flag (put to stdout)
*/
case 'j':
Javaflag = 1;
JToChar = calloc(2, 256);
JToByte = calloc(2, 64*1024);
break;
/*
* -z -- Data mappings
*/
case 'z':
Displayflag = 1;
break;
/*
* Any other switch is an error
*/
default:
printf("Unknown switch ignored - %s\n", (argp-2));
}
} else {
/*
* Check for help specified as just a ?. This does now work
* in unix, since the shell will try to interpret these.
*/
if (*argp=='?') {
if (argp[1]==0) help(); /* Does not return */
}
filecnt++;
switch(filecnt) {
/*
* The first file name is the source file name.
*/
case 1:
strncpy(InName, argp, 259);
break;
/*
* The second name is the output file name
*/
case 2:
strncpy(OutName, argp, 259);
break;
/*
* The third name is an error
*/
default:
printf("Extra parameter ignored - %s\n", argp);
}
}
argcnt++;
}
return filecnt;
}
/*
* encname: Get encoding name
*/
char * encname(uint16 encoding, int flag) {
int i;
i=0;
while (EncNames[i].encoding) {
if (encoding == EncNames[i].encoding) {
if ((flag&1) && EncNames[i+1].encoding==encoding)
i++;
MinLen = EncNames[i].min;
MaxLen = EncNames[i].max;
CClass = EncNames[i].class;
return EncNames[i].name;
}
i++;
}
sprintf(EncHex, "%04X", encoding);
return EncHex;
}
/*
* outheader: Output the ucmap header
*/
void outheader(FILE * f) {
char * ucx;
ucm_hdr_t * ucmap;
char * encn;
char * starter;
char * udc;
int first, last, i;
ucx = (char *) TableHdr;
ucmap = (ucm_hdr_t *) TableHdr;
/*
* Comment
*/
if (Upflag)
strupr(InName);
fprintf(f, "#\n# uconvexp - %s", InName);
if (ucmap->codepage)
fprintf(f, " (%d) %s", ucmap->codepage, ucx+84);
fprintf(f, "\n#\n");
/*
* Codepage name
*/
if (!*ucmap->name)
strncpy(ucmap->name, InName, 10);
if (Stdflag) {
fprintf(f, "<code_set_name> \"%s\"\n", ucmap->name);
} else {
fprintf(f, "<codepage> \"%s\"\n", ucmap->name);
}
/*
* Description
*/
if (ucmap->desc) {
if (Stdflag)
fprintf(f, "# ");
fprintf(f, "<description> \"%s\"\n", ucx+ucmap->desc);
}
/*
* Encoding
*/
encn = encname(Attr.esid, ucmap->flags);
if (Upflag) {
encn = strdup(encn);
strupr(encn);
}
if (Stdflag)
fprintf(f, "# ");
fprintf(f, "<encoding> \"%s\"\n", encn);
if (Stdflag) {
fprintf(f, "<uls_class> \"%s\"\n", ClassName[CClass]);
fprintf(f, "<mb_min_len> %d\n", Attr.mb_min_len);
fprintf(f, "<mb_max_len> %d\n", Attr.mb_max_len);
fprintf(f, "<char_name_mask> \"AXXXX\"\n");
}
/*
* Min and max lengths
*/
if (!Stdflag) {
if (MinLen != Attr.mb_min_len ||
MaxLen != Attr.mb_max_len) {
fprintf(f, "<mb_min_len> %d\n", Attr.mb_min_len);
fprintf(f, "<mb_max_len> %d\n", Attr.mb_max_len);
}
}
/*
* Copyright
*/
if (ucmap->copyright) {
if (Stdflag)
fprintf(f, "# ");
fprintf(f, "<copyright> \"%s\"\n", ucx+ucmap->copyright);
}
/*
* Substitution character
*/
if (Attr.subchar_len) {
fprintf(f, "<subchar> ");
for (i=0; i<Attr.subchar_len; i++) {
fprintf(f, Upflag?"\\x%02X":"\\x%02x", Attr.subchar[i]);
}
fprintf(f, "\n");
}
/*
* Substitution character
*/
if (!Stdflag) {
fprintf(f, "<subcharuni> ");
fprintf(f, Upflag?"\\x%02X\\x%02X\n":"\\x%02x\\x%02x\n",
(Attr.subuni[0]>>8), (Attr.subuni[0]&0xff));
}
/*
* Uconv more
*/
if (ucmap->uconv_more) {
if (Stdflag)
fprintf(f, "# ");
fprintf(f, "<uconv_more> \"%s\"\n", ucx+ucmap->uconv_more);
}
/*
* User defined range
*/
udc = (char *) UdcRange;
while (*udc) {
if (Stdflag)
fprintf(f, "# ");
fprintf(f, "<user_defined> ");
if (Upflag) {
fprintf(f, "\\x%02X\\x%02X...\\x%02X\\x%02X\n",
udc[1], udc[0], udc[3], udc[2]);
} else {
fprintf(f, "\\x%02x\\x%02x...\\x%02x\\x%02x\n",
udc[1], udc[0], udc[3], udc[2]);
}
udc += 4;
}
/*
* DBCS starter
*/
if (Attr.esid==0x3200 || Attr.esid==0x2200) {
starter = DbcsStarter;
first = 0;
for (i=0; i<=256; i++) {
if (starter[i]==2) {
if (!first)
first=i;
} else {
if (first) {
last = i-1;
if (Stdflag)
fprintf(f, "# ");
fprintf(f, "<dbcs_starter> ");
fprintf(f, Upflag?"\\x%02X":"\\x%02x", first);
if (first != last)
fprintf(f, Upflag?"...\\x%02X":"...\\x%02x", last);
fprintf(f, "\n");
first = 0;
}
}
}
}
}
/*
* getglyph: Get the glyph name in IBM and Adobe styles
*/
int getglyph(UniChar uni) {
NAMETAB * np;
GlyphIBM[0] = 0;
GlyphAdobe[0] = 0;
np = Utab[uni>>8];
if (!np)
return 0;
while (np->name) {
if (np->uni==uni) {
if (np->len==8 && np->name[2]>='0' && np->name[2]<='9') {
strcpy(GlyphIBM, np->name);
if (Upflag)
strupr(GlyphIBM);
np++;
if (np->uni != uni)
return 1;
}
strcpy(GlyphAdobe, np->name);
return 1;
}
np++;
}
return 0;
}
/*
* getline: Get the line a remember it for an error message
*/
char * getline(char * buf, FILE * f) {
char * ret;
char * cp;
*buf = 0;
ret = fgets(buf, 255, f);
/* Strip CR and LF from the end of the line */
cp = buf+strlen(buf)-1;
while (*cp=='\n' || *cp=='\r') {
cp--;
}
cp[1]=0;
cp[2]=0;
strncpy(InLine, buf, 255);
return ret;
}
/*
* getnames: Read in a name table.
* The file is read twice, once to get the sizes, and
* a second time to make the actual tables.
*
* Notes:
* The code in this section is taken from the original code within
* makekb. Several of the support routines came with it even though
* they are minimally used.
*/
int getnames(NAMETAB * * tab, char * name, char * * text, NAMETAB * * utab) {
FILE * f;
int len;
NAMETAB * np;
char * tp;
char line[256];
long val;
long entrycount;
long stringlen;
f = findopen(name, "r", "PATH", 1);
if (!f) return 1;
entrycount = 0;
stringlen = 0;
/*
* Process one pass to find the sizes of stuff
*/
line[255]=0;
getline(line, f);
while (!feof(f) && !ferror(f)) {
if (*line!='*' && *line!=';' && *line!='#') {
val = parse(line, &Value);
nullword(Value);
if (val && val<=0xffff) {
while (*Value && *Value!=';') {
entrycount++;
stringlen += (strlen(Value)+1);
Value = nexttoken(Value);
}
} else {
if (val)
printf("Bad name entry - %s\n", InLine);
}
}
getline(line, f);
}
if (ferror(f)) {
printf("Error reading file - %s\n", name);
return 2;
}
/*
* Allocate the tables
*/
entrycount++;
stringlen += 8;
*tab = malloc(entrycount*sizeof(NAMETAB));
*text = malloc(stringlen);
np = *tab;
tp = *text;
/*
* Process second pass to create the tables
*/
rewind(f);
getline(line, f);
while (!feof(f) && !ferror(f)) {
val = parse(line, &Value);
nullword(Value);
if (val && val<=0xffff) {
while (*Value && *Value!=';') {
np->name = tp;
strcpy(tp, Value);
len = strlen(Value);
tp += (len+1);
np->len = len;
np->uni = val;
Value = nexttoken(Value);
if (!utab[val>>8]) {
utab[val>>8] = np;
}
np++;
}
}
getline(line, f);
}
np->name = 0;
np->uni = 0;
np->len = 0;
fclose(f);
return 0;
}
/*
* parse: Parse the input line
*/
long parse (char * line, char * * value) {
char * cp, * kp;
/* Strip CR and LF from the end of the line */
cp = line+strlen(line)-1;
while (*cp=='\n' || *cp=='\r') {
cp--;
}
cp[1]=0;
cp[2]=0;
*value = line;
cp = line;
/*
* Skip leading spaces and detect comments
*/
while (*cp==' ' || *cp=='\t')
cp++;
if (*cp=='*' || *cp==';' || *cp=='#' || *cp=='/' || *cp==0 || *cp==0x1a) {
return 0;
}
/* Find the keyword */
kp = cp;
while (*cp && *cp!=' ' && *cp!='\t' && *cp!='=') {
*cp = (char) tolower(*cp);
cp++;
}
*cp++=0; /* Make keyword into string */
/* Skip blanks and = after keyword */
while (*cp==' ' || *cp=='\t') cp++; /* Skip blanks after keyword */
if (*cp=='=') { /* If = found, skip it and trailing blank */
cp++;
if(*cp==' ' || *cp=='\t') cp++;
}
*value = cp;
return gethexval(kp);
}
/*
* gethexval: Get a hex number. Convert a hex value with an optional
* leading 0x.
*/
long gethexval(char * cp) {
long val;
char gotone;
char ch;
val = 0;
gotone = 0;
if (*cp=='0') {
cp++;
if (!*cp) return 0;
if (*cp=='x') cp++;
}
while (*cp) {
if (*cp>='0' && *cp<='9') {
ch = *cp-'0';
} else {
if (*cp>='a' && *cp<='f') {
ch = *cp-'a'+10;
} else {
return NOTHEXVAL;
}
}
val *= 16;
val += ch;
gotone = 1;
cp++;
}
if (!gotone)
return NOTHEXVAL;
return val;
}
/*
* nexttoken: Set value to the next token
*/
char * nexttoken(char * value) {
if (!*value) return value;
value += strlen(value);
value++;
while (*value==' ' || *value=='\t') value++;
nullword(value);
return value;
}
/*
* nullword: Put a null at the end of the word
*/
void nullword(char * cptr) {
char * cp;
cp = cptr;
while (*cp>' ') cp++;
*cp = 0;
}
/*
* replaceext: Replace extension
*/
void replaceext(char * in, char * ext, char * out) {
char * cp;
if (in != out)
strcpy(out, in);
cp = out + strlen(out) - 1;
while (*cp!='.' && *cp!='\\' && *cp!='/' && *cp!=':') {
if (cp==out) break;
cp--;
}
if (*cp=='.') *cp=0;
strcat(out, ext); /* Replace extension */
}
/*
* findopen: Common file open routine
*/
FILE * findopen(char * fname, char * mode, char * path, int msg) {
FILE * f;
searchenv(fname, path, Fn);
if (*Fn==0 && msg) {
printf("File not found - %s\n", fname);
return NULL;
}
f = fopen(Fn, mode);
if (!f && msg) {
printf("Unable to open file - %s\n", fname);
return NULL;
}
return f;
}
#define PATHSEP '/'
/*
* searchenv: Search for file along paths from environment variable
*/
void searchenv(const char *fname, const char *env_var, register char *path) {
register char *p;
register int c;
char *env_p;
/* Check for fully specified file name */
if (*fname=='/' || *fname=='\\' || fname[1]==':') {
if (access(fname, 0)==0) {
strcpy(path, fname);
} else {
*path = 0;
}
return;
}
/* Check exists in current directory */
if (access(fname, 0) == 0) {
getcwd(path, 256);
p = path + strlen(path);
if (((c = *(p - 1)) != '/') && (c != '\\') && (c != ':')) {
*p++ = PATHSEP;
*p = 0;
}
strcat(path, fname);
return;
}
/* Get environment variable. Return if it does not exist */
env_p = getenv(env_var);
if (!env_p || !*env_p) {
*path = 0;
return;
}
/* Loop thru all paths in the environment variable */
env_p = getpath(env_p, path);
while (env_p && *path) {
p = path + strlen(path);
if (((c = *(p - 1)) != '/') && (c != '\\') && (c != ':')) {
*p++ = PATHSEP;
}
strcpy(p, fname);
if (access(path, 0) == 0)
return;
strcpy(p, "codepage/");
strcpy(p+9, fname);
if (access(path, 0) == 0)
return;
env_p = getpath(env_p, path);
}
/* File not found, return an empty string */
*path = 0;
}
/*
* getpath: Extract a pathname from a semicolon-delimited list of pathnames
*/
char * getpath(register char *src, register char *dst) {
const char *keepsrc;
keepsrc = src;
while (*src && *src != ';') {
if (*src != '"') { /* Process quoted path */
*dst++ = *src++;
} else {
src++; /* skip over opening quote */
while (*src && (*src != '"')) {
*dst++ = *src++;
}
if (*src) src++; /* skip over closing quote */
}
}
while ( *src == ';' ) src++;
*dst = 0;
return((keepsrc != src) ? src : NULL);
}
/*
* touni: Make unicode string the simple way.
* We know the name string is limited to ASCII-7 characters.
*/
void touni(UniChar * ustr, char * str) {
while (*str) {
*ustr++ = *str++;
}
*ustr = 0;
}