123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598 |
- /*
- * CDE - Common Desktop Environment
- *
- * Copyright (c) 1993-2012, The Open Group. All rights reserved.
- *
- * These libraries and programs are free software; you can
- * redistribute them and/or modify them under the terms of the GNU
- * Lesser General Public License as published by the Free Software
- * Foundation; either version 2 of the License, or (at your option)
- * any later version.
- *
- * These libraries and programs are distributed in the hope that
- * they will be useful, but WITHOUT ANY WARRANTY; without even the
- * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
- * PURPOSE. See the GNU Lesser General Public License for more
- * details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with these libraries and programs; if not, write
- * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
- * Floor, Boston, MA 02110-1301 USA
- */
- /* $TOG: XlationSvc.c /main/13 1999/10/14 15:59:35 mgreess $ */
- /****************************************************************************
- $FILEBEG$: XlationSvc.c
- $PROJECT$: Cde 1.0
- $COMPONENT$: DtXlate service
- $1LINER$: Implements a translation service using tables and regex search
- $COPYRIGHT$:
- (c) Copyright 1993, 1994 Hewlett-Packard Company
- (c) Copyright 1993, 1994 International Business Machines Corp.
- (c) Copyright 1993, 1994 Sun Microsystems, Inc.
- (c) Copyright 1993, 1994 Unix System Labs, Inc., a subsidiary of Novell, Inc.
- $END$
- ****************************************************************************
- ************************************<+>*************************************/
- #include <ctype.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <unistd.h>
- #if defined(sun)
- #include <sys/utsname.h>
- #endif
- #include <limits.h> /* INT_MAX */
- #include <pwd.h> /* for getpw... */
- #include <sys/utsname.h> /* for uname */
- #include <sys/param.h> /* MAXPATHLEN */
- /* for RADIXCHAR and nl_langinfo */
- #if defined(__linux__)
- # define RADIXCHAR MON_DECIMAL_POINT
- #endif
- #include <langinfo.h>
- #if defined(sun)
- #include <regexpr.h> /* for compile,advance */
- #else
- #include <regex.h> /* for regcomp,regexec */
- #endif
- /* for Xrm */
- #include <X11/Intrinsic.h>
- #include <X11/Xresource.h>
- /*=================================================================
- $SHAREDBEG$: This header appears in all appropriate DtXlate topics
- =======================================================$SKIP$======*/
- /*$INCLUDE$*/
- #include "XlationSvc.h"
- #include "LocaleXlate.h"
- /*$END$*/
- /**** For extensive Introductory info, go to the end of this file ****/
- /*========================================================*/
- /*====================== Constants =======================*/
- /*========================================================*/
- /*=============== private =================*/
- /*#define DBG_MATCHING ** if defined, debugging matching stages are compiled */
- #define DEBUG_XLATE_NAME "dtXlate.debugDtXlate"
- #define DEBUG_XLATE_CLASS "DtXlate.DebugDtXlate"
- #define EOS '\0'
- /* A "random" number used to ensure that the Db has been initalized */
- #define INIT_OCCURRED 2329479
- #define PATH_SEPARATOR ':'
- #define DIR_SLASH '/'
- #define LESSTHAN_STR "<"
- #define EQUALS_STR "="
- #define CONTAINS_STR "~"
- #define MORETHAN_STR ">"
- #define INHIBIT_STR "0"
- #define MATCHALL_CHAR '?'
- #define ESCAPE_CHAR '\\'
- #define COMMENT_CHAR '!'
- #define QUOTE_CHAR '\"'
- #define OPER_SEPARATOR ','
- #define STDVALUE_SEPARATOR '.'
- #define MATCHALL_VER 0
- #define PLATFORM_QUARK 0 /* index offsets into quarklist */
- #define VERSION_QUARK 1
- #define OPERS_QUARK 2
- #define DIRECTION_QUARK 3
- #define FIRSTSTD_QUARK 4
- #define MAXSPECQUARKS 43 /* std + platform + version + operation */
- #define MAXSTDQUARKS 40
- #define MAXRHSSIZE 100 /* max supported RHS size */
- #define MAXLHSSIZE 200 /* max supported LHS size */
- #define MAXINTSTRSIZE 15 /* handle any long int -> string */
- typedef enum {
- __DtXLATE_TYPE_NONE = 0,
- __DtXLATE_TYPE_INHIBIT = 1,
- __DtXLATE_TYPE_REGEX = 2,
- __DtXLATE_TYPE_PURE = 3,
- __DtXLATE_TYPE_CONTAINS = 4
- } __DtXlateType;
- #if defined(sun)
- /* Sun doesn't support regcomp() and regexec() yet, so
- define this here and fill it will the results of advance() */
- typedef struct regmatch_t {
- int rm_so; /* start offset */
- int rm_eo; /* end offset */
- } regmatch_t;
- #endif
- /*========================================================*/
- /*====================== Typedefs ========================*/
- /*========================================================*/
- #if DOC
- /*========================================================*/
- $PTYPEBEG$: __DtXlateDbRec
- $1LINER$: A private object used to represent translation dbs
- $SUMMARY$:
- __DtXlateDbRec is the type of the contents of a translation database
- object. The database object must be opened before use and closed
- after use. The definition of the object is opaque to users.
- $ARGS$:
- xrmDb: Xrm database used to hold specs
- initGuard: used to test whether Db initialized
- /*================================================$SKIP$==*/
- #endif
- /*$DEF$*/
- typedef struct __DtXlateDbRec
- {
- XrmDatabase xrmDb;
- int initGuard;
- Boolean debugMode;
- } __DtXlateDbRec;
- /*$END$*/
- #if DOC
- /*========================================================*/
- $PTYPEBEG$: __DtXlateSrchData
- $1LINER$: A private object used to collect search-related data
- $SUMMARY$:
- __DtXlateSrchData stores all the data pertaining to a search
- and the search results. The search routines utilize this
- to maintain status info over multiple calls by the
- enumeration routines and to return info to the routine
- that initiated the search.
- $ARGS$:
- filterQuarks: quark list for the platform, version, and op filter
- stdValueQuarks: quark list for the std value
- opValue: ptr to operation-specific value string
- SpecRef: indices 1 to MAXSPECQUARKS point to matching Xrm strings
- SubEx: indices 1 to MAXSPECQUARKS index sub exprs in opValue
- /*================================================$SKIP$==*/
- #endif
- /*$DEF$*/
- typedef struct __DtXlateSrchData
- {
- /* db info */
- _DtXlateDb db;
- /* query info */
- const char * platformStr;
- XrmQuark platformQuark;
- int version;
- char verStr[MAXINTSTRSIZE]; /* handle any long int */
- const char * operStr;
- int operStrLen;
- XrmQuark operQuark;
- XrmQuark lessThanQuark;
- XrmQuark equalsToQuark;
- XrmQuark containsQuark;
- XrmQuark moreThanQuark;
- XrmQuark inhibitQuark;
- /* query or search info */
- XrmQuark stdValueQuarks[MAXSTDQUARKS];
- const char * opValue;
- /* search info */
- __DtXlateType curTransType;
- __DtXlateType bestTransType;
- int curScore;
- int bestScore;
- /* MAXSPECQUARKS is depended upon elsewhere to be the size of these */
- const char * curSpecRefs[MAXSPECQUARKS];
- const char * bestSpecRefs[MAXSPECQUARKS];
- regmatch_t curSubEx[MAXSPECQUARKS]; /* pattern match data */
- regmatch_t bestSubEx[MAXSPECQUARKS]; /* pattern match data */
- } __DtXlateSrchData;
- /*$END$*/
- /*========================================================*/
- /*================== Private routines ====================*/
- /*========================================================*/
- #if DOC
- /*========================================================*/
- $PFUNBEG$: ExpandPath()
- $1LINER$: adds current working directory to front of path if its relative
- $SUMMARY$:
- If path is absolute, returns a malloced copy.
- If path is relative, inserts the CWD in front of the relative path
- and returns a mallocedd memory.
- The caller must free the memory when no longer needed.
- $ARGS$:
- filespec: the pathname
- $RETURNS$:
- ptr to mallocedd memory or NULL
- /*================================================$SKIP$==*/
- #endif
- char * ExpandPath (
- const char * filespec)
- { /* $CODE$ */
- char tmpPath[MAXPATHLEN + 2];
- char * pathName;
- char * eos = NULL;
- const char * slash = NULL;
- /* test args */
- if (NULL == filespec) return NULL;
- /*** is the file absolute ***/
- /* if filespec begins with / then it is absolute */
- if ( ( MB_CUR_MAX == 1
- || mblen(filespec, MB_CUR_MAX) == 1)/* 1st char is 1 byte */
- && *filespec == DIR_SLASH) /* and its a / */
- {
- return strdup(filespec); /* RETURN */
- }
- /*** otherwise, make it relative to the current directory ***/
- /* get user's current working directory */
- if (getcwd(tmpPath, MAXPATHLEN) == 0) return NULL; /* RETURN: error */
- /*** add a slash to end of path component, if needed ***/
- /* get end of the string */
- eos = tmpPath + strlen(tmpPath);
- /* get last slash */
- _DtMBStrrchr(tmpPath,DIR_SLASH,-1,&slash);
- if (slash != (eos-1)) /* is slash last char of path? */
- {
- *eos++ = DIR_SLASH;
- *eos = EOS;
- }
- /* make a malloc'd copy of the path with room to grow */
- pathName = malloc(sizeof(char) *
- (strlen(filespec) + (eos-tmpPath) + 5) ); /* 5: arbitrary */
- if (NULL == pathName) return NULL; /* RETURN: error */
- /* build the absolute path */
- strcpy(pathName,tmpPath);
- strcat(pathName,filespec);
- return pathName; /* RETURN: found */
- } /* $END$ */
- #if DOC
- /*========================================================*/
- $PFUNBEG$: DeleteDbMem()
- $1LINER$: Zeros out the db mem & frees it
- $SUMMARY$:
- Zeros out the db mem & frees it
- The xrmDb should have already been destroyed before calling
- this function.
- $ARGS$:
- io_db: db to delete
- $RETURNS$:
- /*================================================$SKIP$==*/
- #endif
- static
- void DeleteDbMem(
- _DtXlateDb * io_db)
- { /*$CODE$*/
- /* zero out object mem and free it */
- (*io_db)->xrmDb = NULL;
- (*io_db)->initGuard = 0;
- free(*io_db);
- *io_db= NULL;
- } /*$END$*/
- #if DOC
- /*========================================================*/
- $IFUNBEG$: _DtMBStrchr()
- $1LINER$: Searches for a character in a multibyte string
- $SUMMARY$:
- Returns in 'ret_ptr' the address of the first occurence of 'value'
- in string s1. Value may also be the end of string marker '\0'.
- $ARGS$:
- $RETURNS$:
- -1 If found an invalid character.
- 0 If found value in string s2
- 1 If found the null byte character without finding 'value'.
- 'ret_ptr' will also be null in this case.
- /*================================================$SKIP$==*/
- #endif
- int _DtMBStrchr (
- const char * s1,
- int value,
- int max_len,
- const char * * ret_ptr )
- { /*$CODE$*/
- int len;
- const char * p1;
- wchar_t wcs;
- *ret_ptr = NULL;
- if (!s1 || *s1 == '\0')
- return 1;
- if (max_len == 1)
- {
- *ret_ptr = strchr (s1, value);
- if (*ret_ptr)
- return 0;
- return 1;
- }
- p1 = s1;
- while (*p1 != '\0')
- {
- len = mblen (p1, max_len);
- if (len == -1)
- return -1;
- if (len == 1)
- {
- if (*p1 == value)
- {
- *ret_ptr = p1;
- return 0;
- }
- p1++;
- }
- else
- {
- if (mbstowcs (&wcs, p1, 1) == value)
- {
- *ret_ptr = p1;
- return 0;
- }
- p1 += len;
- }
- }
- /* check for match on EOS */
- if (*p1 == value) *ret_ptr = p1;
- return ((*ret_ptr) ? 0 : 1);
- } /*$CODE$*/
- #if DOC
- /*========================================================*/
- $IFUNBEG$: _DtMBStrrchr()
- $1LINER$: Searches for a character in a multibyte string
- $SUMMARY$:
- Returns in 'ret_ptr' the address of the last occurence of 'value'
- in string s1. Value may also be the end of string marker '\0'.
- $ARGS$:
- $RETURNS$:
- -1 If found an invalid character.
- 0 If found value in string s2
- 1 If found the null byte character without finding 'value'.
- 'ret_ptr' will also be null in this case.
- /*================================================$SKIP$==*/
- #endif
- int _DtMBStrrchr (
- const char * s1,
- int value,
- int max_len,
- const char * * ret_ptr )
- { /*$CODE$*/
- int len;
- const char * p1;
- wchar_t wcs;
- *ret_ptr = NULL;
- if (!s1 || *s1 == '\0')
- return 1;
- if (max_len == 1)
- {
- *ret_ptr = strrchr (s1, value);
- if (*ret_ptr)
- return 0;
- return 1;
- }
- p1 = s1;
- while (*p1 != '\0')
- {
- len = mblen (p1, max_len);
- if (len == -1)
- return -1;
- if (len == 1)
- {
- if (*p1 == value) *ret_ptr = p1;
- p1++;
- }
- else
- {
- if (mbstowcs (&wcs, p1, 1) == value) *ret_ptr = p1;
- p1 += len;
- }
- }
- /* check for match on EOS */
- if (*p1 == value) *ret_ptr = p1;
- return ((*ret_ptr) ? 0 : 1);
- }
- #if DOC
- /*========================================================*/
- $PFUNBEG$: SetDebugModeState()
- $1LINER$: Checks db for debug mode and sets flag
- $SUMMARY$:
- $WARNING$:
- $ARGS$:
- $RETURNS$:
- /*================================================$SKIP$==*/
- #endif
- static
- void SetDebugModeState(
- _DtXlateDb dbRec)
- { /*$CODE$*/
- XrmValue value;
- char * str_type;
- if (XrmGetResource(dbRec->xrmDb,
- DEBUG_XLATE_NAME,DEBUG_XLATE_CLASS,&str_type,&value) == True)
- dbRec->debugMode = True;
- }
- #if DOC
- /*========================================================*/
- $PFUNBEG$: ReplaceMatchallSubex()
- $1LINER$: Replace matchall subexpression refs (e.g. ?1) with values
- $SUMMARY$:
- If subexpressions are specified and referenced, the
- routine assumes that the string pointed to by pStr was
- allocated using malloc() and can be resized using realloc().
- The value and size of pStr may be different after the call.
- $WARNING$:
- This routine assumes it is working on a stdvalue expression
- (e.g. from the LHS of a spec), that uses only stdvalue strings
- or matchall-style subexpression replacement specs, e.g. ?1.
- $ARGS$:
- $RETURNS$:
- /*================================================$SKIP$==*/
- #endif
- static
- void ReplaceMatchallSubex(
- char * * pStr,
- regmatch_t * subex,
- const char * matchedStr)
- { /*$CODE$*/
- char * nxt = *pStr;
- char * old = *pStr;
- /* strip escapes out */
- for ( *nxt = *old; /* xfer but don't advance */
- *old != EOS;
- *nxt = *old ) /* xfer but don't advance */
- {
- if ( *old == MATCHALL_CHAR ) /* if an escaped char follows */
- {
- /* if MATCHALL_CHAR is not followed by a digit, e.g. \1
- or no replacement values exist, ignore it */
- if ( NULL == subex
- || isdigit(*(old+1)) == 0 )
- {
- old++; /* go past the escape char */
- *nxt++ = *old++; /* keep just the char that was escaped
- and assign here to avoid tranlating
- that character, then move on to the
- next one */
- continue; /* CONTINUE */
- }
- else /* a value reference is being made */
- { /* get the refNum and advance the ptr */
- int refNum, numLen;
- int newOff, oldOff;
- sscanf(++old,"%d%n", &refNum, &numLen);
- old += numLen; /* move old ptr past the ref number */
- /* printf("%d=%s\n", refNum, &matchedStr[subex[refNum].rm_so]); ** DBG */
- /* test for valid replacement */
- if ( refNum >= 0
- && refNum < MAXSPECQUARKS
- && subex[refNum].rm_so != -1)
- {
- int repLen;
- int strLen;
- char * oldTmp;
- char * newTmp;
- newOff = nxt - *pStr;
- oldOff = old - *pStr;
- repLen = subex[refNum].rm_eo - subex[refNum].rm_so;
- strLen = strlen(*pStr);
- /* expand memory and reset pointers */
- *pStr = realloc(*pStr,strLen+repLen+1);
- if (NULL == *pStr) return; /* RETURN */
- nxt = *pStr + newOff;
- old = *pStr + oldOff;
- /* move rest back to leave room for the replacement value */
- oldTmp = *pStr+strLen; /* pts to old EOS */
- newTmp = *pStr+strLen-(oldOff-newOff)+repLen;/*pts to new EOS*/
- while (oldTmp >= old) *newTmp-- = *oldTmp--;
- /* replace the ref with a value but don't append EOS */
- strncpy(nxt,&matchedStr[subex[refNum].rm_so],repLen);
- nxt += repLen; /* move new to end of replace string */
- old += repLen - (oldOff-newOff);
- /* move old to end of expanded old string */
- } /* if valid replacement */
- } /* if a replacement requested */
- continue; /* CONTINUE */
- } /* if an escaped character */
- /* if survived all the checks, can advance to next char */
- nxt++;
- old++;
- }
- } /*$END$*/
- #if DOC
- /*========================================================*/
- $PFUNBEG$: StripMetaAndReplaceEscSubex()
- $1LINER$: Strips off meta chars and replaces escaped subex (e.g. \1) values
- $SUMMARY$:
- Strip is performed in place if replaceValues is NULL.
- If replaceValues are specified and referenced, the
- routine assumes that the string pointed to by pStr was
- allocated using malloc() and can be resized using realloc().
- The value and size of pStr may be different after the call.
- $WARNING$:
- This routine assumes it is working on a value expression
- (e.g. from the RHS of a spec), that uses meta chars and
- regex(5)-style subexpression replacement specs.
- $ARGS$:
- $RETURNS$:
- /*================================================$SKIP$==*/
- #endif
- static
- void StripMetaAndReplaceEscSubex(
- char * * pStr,
- const Boolean keepEscChar,
- const char * * replaceValues)
- { /*$CODE$*/
- char * nxt = *pStr;
- char * old = *pStr;
- Boolean inQuote = False;
- /* strip escapes out */
- for ( *nxt = *old; /* xfer but don't advance */
- *old != EOS;
- *nxt = *old ) /* xfer but don't advance */
- {
- if ( *old == ESCAPE_CHAR ) /* if an escaped char follows */
- {
- /* if ESCAPE_CHAR is not followed by a digit, e.g. \1
- or no replacement values exist, ignore it */
- if ( NULL == replaceValues
- || keepEscChar
- || isdigit(*(old+1)) == 0 )
- {
- if (!keepEscChar) old++; /* go past the escape char */
- else *nxt++ = *old++; /* copy esc char over */
- *nxt++ = *old++; /* keep just the char that was escaped
- and assign here to avoid tranlating
- that character, then move on to the
- next one */
- continue; /* CONTINUE */
- }
- else /* a value reference is being made */
- { /* get the refNum and advance the ptr */
- int refNum, numLen;
- int newOff, oldOff;
- sscanf(++old,"%d%n", &refNum, &numLen);
- old += numLen; /* move old ptr past the ref number */
- /* printf("%x=%s\n", replaceValues[refNum], replaceValues[refNum]); ** DBG */
- /* test for valid replacement */
- if ( refNum >= 0
- && refNum < MAXSPECQUARKS
- && replaceValues[refNum] != NULL)
- {
- int repLen;
- int strLen;
- char * oldTmp;
- char * newTmp;
- newOff = nxt - *pStr;
- oldOff = old - *pStr;
- repLen = strlen(replaceValues[refNum]);
- strLen = strlen(*pStr);
- /* expand memory and reset pointers */
- *pStr = realloc(*pStr,strlen(*pStr)+repLen+1);
- if (NULL == *pStr) return; /* RETURN */
- nxt = *pStr + newOff;
- old = *pStr + oldOff;
- /* move rest back to leave room for the replacement value */
- oldTmp = *pStr+strLen; /* pts to old EOS */
- newTmp = *pStr+strLen-(oldOff-newOff)+repLen;/*pts to new EOS*/
- while (oldTmp >= old) *newTmp-- = *oldTmp--;
- /* replace the ref with a value but don't append EOS */
- strncpy(nxt,replaceValues[refNum],repLen);
- nxt += repLen; /* move new to end of replace string */
- old += repLen - (oldOff-newOff);
- /* move old to end of expanded old string */
- } /* if valid replacement */
- } /* if a replacement requested */
- continue; /* CONTINUE */
- } /* if an escaped character */
- else
- { /* a non-escaped char; make further checks */
- if ( *old == COMMENT_CHAR )
- {
- *old = EOS; /* end the string */
- continue; /* CONTINUE */
- }
- else if ( *old == QUOTE_CHAR )
- {
- if ( !inQuote) inQuote = True; /* start quote */
- else inQuote = False; /* end quote */
- old++; /* go to next char */
- continue; /* CONTINUE */
- }
- else if ( !inQuote && isspace(*old) )
- {
- old++; /* skip the space */
- continue; /* CONTINUE */
- }
- } /* else non-escaped char */
- /* if survived all the checks, can advance to next char */
- nxt++;
- old++;
- }
- } /*$END$*/
- /*========================================================*/
- /*============== Private Xlate routines ==================*/
- /*========================================================*/
- #if DOC
- /*========================================================*/
- $PFUNBEG$: PrintDbEntry()
- $1LINER$: Prints a db entry to stdout
- $SUMMARY$:
- $ARGS$:
- quarks: NULLQUARK-terminated list of quarks for the LHS of the entry
- value: value of the RHS of the entry
- $RETURNS$:
- /*================================================$SKIP$==*/
- #endif
- static
- void PrintDbEntry(
- XrmQuarkList quarks,
- XrmValue * value)
- { /*$CODE$*/
- char * str;
- XrmQuark quark;
- /* print the entry */
- quark=*quarks;
- while ( quark != NULLQUARK )
- {
- str = XrmQuarkToString(quark);
- fprintf(stderr,"%s", str);
- quark = *(++quarks);
- if (quark != NULLQUARK) fprintf(stderr,".");
- }
- fprintf(stderr,":%s\n",value->addr);
- } /*$END$*/
- #if DOC
- /*========================================================*/
- $PFUNBEG$: strCaseiCmp
- $1LINER$: case insensitive string comparison
- $SUMMARY$:
- Rolled my own because strcasecmp() not available on
- all platforms.
- $ARGS$:
- $RETURNS$:
- True: strings match
- False: they do not
- /*================================================$SKIP$==*/
- #endif
- static
- Boolean strCaseiCmp(
- const char * str1,
- const char * str2)
- { /*$CODE$*/
- /* if ( !str1 || !str2 ) return False; *//* unneeded performance hit */
- while ( *str1 && *str2 )
- if ( tolower(*str1++) != tolower(*str2++) ) return False;
- return (*str1 == *str2);
- } /*$END$*/
- #if DOC
- /*========================================================*/
- $PFUNBEG$: CheckForMatchall()
- $1LINER$: Matches search pattern to spec data
- $SUMMARY$:
- $ARGS$:
- $RETURNS$:
- /*================================================$SKIP$==*/
- #endif
- static
- Boolean CheckForMatchall(
- __DtXlateSrchData * srchData,
- const char * matchallString,
- const char * matchingString)
- { /*$CODE$*/
- int refNum = -1;
- int score = 0;
- /* test for a match all */
- if (! ( matchallString[0] == MATCHALL_CHAR
- && ( matchallString[1] == EOS
- || sscanf(matchallString+1,"%d", &refNum) == 1) ) )
- return False; /* RETURN: syntax error or non-matchall */
- /* matchall occurred; save the matching string if valid ref num */
- if ( refNum != -1
- && refNum >= 0
- && refNum < XtNumber(srchData->curSpecRefs) )
- {
- /* Don't store the string if it is just a matchall */
- /* This allows a replacement ref to be deleted on a match
- for which there is no replacement value. */
- if ( matchingString[0] == MATCHALL_CHAR
- && matchingString[1] == EOS )
- {
- srchData->curSpecRefs[refNum] = NULL;
- /* don't add to score for a matchall with no replacement value */
- }
- else
- {
- /* recall: string not owned by curSpecRefs */
- srchData->curSpecRefs[refNum] = matchingString;
- score = 1;
- }
- }
- else /* not a value reference; just determine if a plain match */
- {
- if ( matchingString[0] == MATCHALL_CHAR
- && matchingString[1] == EOS )
- score = 1; /* a plain matchall matches a plain matchall */
- }
- /* if a perfect matchall match, bump the score */
- srchData->curScore += score;
- return True; /* RETURN: matchall */
- } /*$END$*/
- #if DOC
- /*========================================================*/
- $PFUNBEG$: CheckSearchPlatformMatchesSpec()
- $1LINER$: Matches search pattern to spec data
- $SUMMARY$:
- $ARGS$:
- $RETURNS$:
- /*================================================$SKIP$==*/
- #endif
- static
- Boolean CheckSearchPlatformMatchesSpec(
- __DtXlateSrchData * srchData,
- XrmQuark specPlatformQuark)
- { /*$CODE$*/
- /* CheckForMatchall stores away the matching string if of form ?n */
- if (srchData->platformQuark != NULLQUARK)
- {
- char * specStr = XrmQuarkToString(specPlatformQuark);
- /* CheckForMatchall incs score if appropriate */
- if (CheckForMatchall(srchData,specStr,srchData->platformStr) == True)
- return True; /* RETURN: platform matches */
- }
- if (srchData->platformQuark == specPlatformQuark)
- {
- srchData->curScore += 2; /* perfect match better than matchall match */
- return True; /* RETURN: platform matches */
- }
- return False; /* RETURN: platform doesnt match */
- } /*$END$*/
- #if DOC
- /*========================================================*/
- $PFUNBEG$: CheckSearchVerMatchesSpec()
- $1LINER$: Matches search pattern to spec data
- $SUMMARY$:
- $ARGS$:
- $RETURNS$:
- /*================================================$SKIP$==*/
- #endif
- static
- Boolean CheckSearchVerMatchesSpec(
- __DtXlateSrchData * srchData,
- XrmQuark specVersionQuark)
- { /*$CODE$*/
- const char * numStr = XrmQuarkToString(specVersionQuark);
- int lowerBnd = 0;
- int upperBnd = INT_MAX;
- int score = 0;
- if ( srchData->version == MATCHALL_VER
- || CheckForMatchall(srchData,numStr,srchData->verStr) == True )
- return True; /* RETURN; matchall specified */
- /*** sscanf()-based parsing ***/
- /* note that the (score=x) is an assignment, not a compare */
- if ( (score=1) && sscanf(numStr,"%d-%d", &lowerBnd, &upperBnd) != 2
- && (score=1) && sscanf(numStr,"%d+", &lowerBnd) != 1
- && (score=2) && sscanf(numStr,"%d", &lowerBnd) != 1 )
- return False; /* RETURN: syntax error */
- if ( lowerBnd > srchData->version || upperBnd < srchData->version )
- return False; /* RETURN: version doesnt match */
- srchData->curScore += score;
- return True; /* RETURN: version matches */
- } /*$END$*/
- #if DOC
- /*========================================================*/
- $PFUNBEG$: CheckSearchOperMatchesSpec()
- $1LINER$: Matches search pattern to spec data
- $SUMMARY$:
- $ARGS$:
- srchData: state of the search
- specOperationQuark: quark for the operation specification string
- $RETURNS$:
- True: if srchData->operation is found in specOperation string
- or the specOperation string is a match all
- False: if not
- /*================================================$SKIP$==*/
- #endif
- static
- Boolean CheckSearchOperMatchesSpec(
- __DtXlateSrchData * srchData,
- XrmQuark specOperationQuark)
- { /*$CODE$*/
- const char * opStr = XrmQuarkToString(specOperationQuark);
- int hitLen;
- const char * hit;
- const char * remainingOps;
- if ( srchData->operStr == NULL
- || CheckForMatchall(srchData,opStr,srchData->operStr) == True
- || CheckForMatchall(srchData,srchData->operStr,opStr) == True )
- return True; /* RETURN; matchall specified */
- /* quark compare search */
- if ( specOperationQuark == srchData->operQuark )
- goto matched;
- /*** strstr-based search ***/
- hitLen = srchData->operStrLen;
- remainingOps = opStr;
- do
- {
- /* look for operation in remainingOps */
- hit = strstr(remainingOps,srchData->operStr);
- /* see if the hit is on a complete token */
- if ( NULL != hit
- && (hit == remainingOps || *(hit-1) == OPER_SEPARATOR)
- && (hit[hitLen] == EOS || hit[hitLen] == OPER_SEPARATOR) )
- {
- matched:
- srchData->curScore += 2; /*perfect match better than a matchall match*/
- return True; /* RETURN: operation matches */
- }
- } while(hit != NULL && *(remainingOps = hit+1) != EOS);
- return False; /* RETURN: no match on operation */
- } /*$END$*/
- #if DOC
- /*========================================================*/
- $PFUNBEG$: CheckSearchDirOpToStdMatchesSpec()
- $1LINER$: Matches search pattern to spec data
- $SUMMARY$:
- $ARGS$:
- $RETURNS$:
- /*================================================$SKIP$==*/
- #endif
- static
- Boolean CheckSearchDirOpToStdMatchesSpec(
- __DtXlateSrchData * srchData,
- XrmQuark specDirectionQuark)
- { /*$CODE$*/
- int score = 0;
- __DtXlateType type = __DtXLATE_TYPE_NONE;
- if (specDirectionQuark == srchData->inhibitQuark)
- return False; /* RETURN: no match */
- /* Note that the type and score expressions are assignments */
- if (! ( ( (type=__DtXLATE_TYPE_REGEX)
- && (specDirectionQuark == srchData->lessThanQuark))
- || ( (type=__DtXLATE_TYPE_PURE)
- && (score=1)
- && (specDirectionQuark == srchData->equalsToQuark))
- || ( (type=__DtXLATE_TYPE_CONTAINS)
- && (score=1)
- && (specDirectionQuark == srchData->containsQuark)) ) )
- return False; /* RETURN: no match */
- srchData->curScore += score;
- srchData->curTransType = type;
- return True; /* RETURN: direction matches */
- } /*$END$*/
- #if DOC
- /*========================================================*/
- $PFUNBEG$: CheckSearchDirStdToOpMatchesSpec()
- $1LINER$: Matches search pattern to spec data
- $SUMMARY$:
- $ARGS$:
- $RETURNS$:
- /*================================================$SKIP$==*/
- #endif
- static
- Boolean CheckSearchDirStdToOpMatchesSpec(
- __DtXlateSrchData * srchData,
- XrmQuark specDirectionQuark)
- { /*$CODE$*/
- int score = 0;
- __DtXlateType type = __DtXLATE_TYPE_NONE;
- if (specDirectionQuark == srchData->inhibitQuark)
- return False; /* RETURN: no match */
- /* Note that the type and score expressions are assignments */
- if (! ( ( (type=__DtXLATE_TYPE_REGEX)
- && (specDirectionQuark == srchData->moreThanQuark))
- || ( (type=__DtXLATE_TYPE_PURE)
- && (score=1)
- && (specDirectionQuark == srchData->equalsToQuark))
- || ( (type=__DtXLATE_TYPE_CONTAINS)
- && (score=1)
- && (specDirectionQuark == srchData->containsQuark)) ) )
- return False; /* RETURN: no match */
- srchData->curScore += score;
- srchData->curTransType = type;
- return True; /* RETURN: direction matches */
- } /*$END$*/
- #if DOC
- /*========================================================*/
- $PFUNBEG$: CheckSearchStdValueMatchesSpec()
- $1LINER$: Matches search pattern to spec data
- $SUMMARY$:
- $ARGS$:
- $RETURNS$:
- /*================================================$SKIP$==*/
- #endif
- static
- Boolean CheckSearchStdValueMatchesSpec(
- __DtXlateSrchData * srchData,
- XrmQuark * specStdValueQuarks)
- { /*$CODE$*/
- int score = 0;
- int unmatched = 0;
- XrmQuark * patQuarks;
- /* walk through all available quarks */
- for ( patQuarks = srchData->stdValueQuarks;
- *specStdValueQuarks != NULLQUARK && *patQuarks != NULLQUARK;
- specStdValueQuarks++, patQuarks++ )
- {
- char * specStr = XrmQuarkToString(*specStdValueQuarks);
- char * patStr = XrmQuarkToString(*patQuarks);
- if ( CheckForMatchall(srchData,specStr,patStr) == True
- || CheckForMatchall(srchData,patStr,specStr) == True )
- continue; /* no score for a matchall */
- /* is not exact match, match fails */
- /* be case insensitive when comparing standard values */
- if ( *patQuarks != *specStdValueQuarks
- && strCaseiCmp(specStr,patStr) == False )
- return False; /* RETURN: no match */
- /* one more match--increase score, go to next */
- score++;
- }
- /* find out how many stdValue fields were left unmatched */
- for ( unmatched = 0;
- *specStdValueQuarks != NULLQUARK;
- specStdValueQuarks++ )
- { unmatched++; }
- /* Score is combo of the number matched - the number unmatched
- and not counting the number matchalls that coincided with
- the search pattern. This technique allows the spec for
- val1 to be at "better" match than the one for val2, and
- val2 to be a better match than val3, and val3 to be a better
- match than val4.
- .a.std : val1 querypattern = a.std
- .?.std : val2 querypattern = a.std
- .?1.std : \\1val3 querypattern = a.std
- .a.std : val4 querypattern = ?.std
- .?.std : val5 querypattern = ?.std
- .?1.std : \\1val6 querypattern = ?.std
- .a.std.? : val4 querypattern = a.std
- .?.std.? : val5 querypattern = a.std
- .?.std.?1 : \\1val5 querypattern = a.std
- .?1.std.? : \\1val5 querypattern = a.std
- .?1.std.?2 : \\1\\2val5 querypattern = a.std
- .a.std.? : val4 querypattern = a.std.b
- .?.std.? : val5 querypattern = a.std.b
- .?.std.?1 : \\1val5 querypattern = a.std.b
- .?1.std.? : \\1val5 querypattern = a.std.b
- .?1.std.?2 : \\1\\2val5 querypattern = a.std.b
- */
- srchData->curScore += score + MAXSTDQUARKS - unmatched;
- return True; /* RETURN: direction matches */
- } /*$END$*/
- #if DOC
- /*========================================================*/
- $PFUNBEG$: CheckSearchOpValueMatchesSpec()
- $1LINER$: Matches search pattern to spec data
- $SUMMARY$:
- $ARGS$:
- $RETURNS$:
- /*================================================$SKIP$==*/
- #endif
- static
- Boolean CheckSearchOpValueMatchesSpec(
- __DtXlateSrchData * srchData,
- const char * specOpValue)
- { /*$CODE$*/
- char opValBuf[MAXRHSSIZE]; /* max supported RHS size */
- char * pOpValBuf = opValBuf; /* need this for StripMeta... call */
- size_t opValLen;
- Boolean matches = False;
- /* copy value to mutable memory */
- strncpy(opValBuf,specOpValue,sizeof(opValBuf));
- opValBuf[sizeof(opValBuf)-1] = EOS;
- opValLen = strlen(opValBuf);
- /* depending on the translation type of the spec, do a
- regexex match of the spec value pattern to the search
- value or do a pure match */
- if (srchData->curTransType == __DtXLATE_TYPE_REGEX)
- {
- #if defined(sun)
- char * ex = NULL;
- /* True: leave escape char in place */
- StripMetaAndReplaceEscSubex(&pOpValBuf,True,NULL);
- /* we need to use regexex to pattern match */
- /* and we need to save of the reference value matches */
- if ( (ex = compile(opValBuf,NULL,NULL)) != NULL
- && advance(srchData->opValue,ex) != 0)
- {
- int matchSize;
- int subExCnt = nbra; /* Sun global for advance() */
- matches = True; /* if got this far */
- /* need due to bug in advance()--operation doesn't meet documentation */
- if (NULL == loc1) loc1=(char *)srchData->opValue;
- /* inc score by the size of the match after
- scaling for the maximum possible match size */
- matchSize = loc2 - loc1; /*loc[12] are Sun globals for advance()*/
- if (matchSize < 0 || matchSize >= sizeof(opValBuf)) matchSize = 0;
- /* NOTE: this scoring code should be identical in the
- Sun-specific and non-Sun code blocks */
- if (matchSize == strlen(srchData->opValue))
- {
- /* if the matchSize is the length of srchData->opValue,
- then we have a complete match. In this case, use the
- specificity of the pattern to pick the best match */
- /* NOTE: opValLen is a crude measure of specificity.
- A better measure would be to count the number of
- literals/ranges that matched exactly. When doing this,
- a perfect match without regex syntax should rank higher
- than a perfect match with regex syntax. This is one
- area where the current algorithm breaks. For example:
- opValue=23, pat1=23, pat2=[0-9]3.
- Both patterns match and pat1 is a better match,
- but not with the current length-based algorithm. */
- /* NOTE: this formula does not advance the score
- to sizeof(opValBuf) for a perfect match. Other match
- formulas use sizeof(opValBuf) as the max value
- to indicate a perfect match. */
- srchData->curScore += matchSize + opValLen;
- }
- else
- {
- /* if its not a complete match, inc score by match size */
- srchData->curScore += matchSize;
- }
- /* put sub expression matching stuff in srchData->curSubEx */
- for( ; nbra > 0; nbra-- )
- {
- srchData->curSubEx[nbra].rm_so = braslist[nbra-1] - loc1;
- srchData->curSubEx[nbra].rm_eo = braelist[nbra-1] - loc1;
- }
- }
- if (ex) free(ex);
- #else
- regex_t re;
- /* True: leave escape char in place */
- StripMetaAndReplaceEscSubex(&pOpValBuf,True,NULL);
- /* we need to use regexex to pattern match */
- /* and we need to save of the reference value matches */
- if ( regcomp(&re,opValBuf,0) == 0
- && regexec(&re,srchData->opValue,
- XtNumber(srchData->curSubEx),srchData->curSubEx,0) == 0)
- {
- int matchSize;
- matches = True; /* if got this far */
- /* inc score by the size of the match after
- scaling for the maximum possible match size */
- matchSize = srchData->curSubEx[0].rm_eo -
- srchData->curSubEx[0].rm_so;
- /* NOTE: this scoring code should be identical in the
- Sun-specific and non-Sun code blocks */
- if (matchSize == strlen(srchData->opValue))
- {
- /* if the matchSize is the length of srchData->opValue,
- then we have a complete match. In this case, use the
- specificity of the pattern to pick the best match */
- /* NOTE: opValLen is a crude measure of specificity.
- A better measure would be to count the number of
- literals/ranges that matched exactly. When doing this,
- a perfect match without regex syntax should rank higher
- than a perfect match with regex syntax. This is one
- area where the current algorithm breaks. For example:
- opValue=23, pat1=23, pat2=[0-9]3.
- Both patterns match and pat1 is a better match,
- but not with the current length-based algorithm. */
- /* NOTE: this formula does not advance the score
- to sizeof(opValBuf) for a perfect match. Other match
- formulas use sizeof(opValBuf) as the max value
- to indicate a perfect match. */
- srchData->curScore += matchSize + opValLen;
- }
- else
- {
- /* if its not a complete match, inc score by match size */
- srchData->curScore += matchSize;
- }
- /* sub expression matching stuff already in srchData->curSubEx */
- }
- regfree(&re);
- #endif
- }
- else /* (srchData->curTransType == __DtXLATE_TYPE_PURE || __DtXLATE_TYPE_CONTAINS */
- {
- char * opValueInBuf;
- /* False: strip escape char as well */
- StripMetaAndReplaceEscSubex(&pOpValBuf,False,NULL);
- matches = (strcmp(srchData->opValue,opValBuf) == 0);
- /* if matches, inc score to show a perfect match (max poss value) */
- if (matches) srchData->curScore += sizeof(opValBuf);
- /* don't test for contains if a perfect match or a pure match spec */
- if (matches || srchData->curTransType == __DtXLATE_TYPE_PURE)
- return matches; /* RETURN */
- /* (srchData->curTransType == __DtXLATE_TYPE_CONTAINS) */
- /* is opValue contained in opValBuf? */
- /* is opValBuf contained in opValue? */
- opValueInBuf = NULL;
- matches = (opValBuf[0] != EOS && srchData->opValue[0] != EOS)
- && ((opValueInBuf=strstr(opValBuf,srchData->opValue)) != NULL
- || strstr(srchData->opValue,opValBuf) != NULL);
- /* if matches, inc score to show a contains match */
- if (matches)
- {
- if (opValueInBuf) srchData->curScore += strlen(srchData->opValue);
- else srchData->curScore += strlen(opValBuf);
- }
- }
- return matches;
- } /*$END$*/
- #if DOC
- /*========================================================*/
- $PFUNBEG$: FindStdToOpMatchCB()
- $1LINER$: Matches std value of entry to search pattern; gets op value
- $SUMMARY$:
- $ARGS$:
- $RETURNS$:
- /*================================================$SKIP$==*/
- #endif
- static
- Bool FindStdToOpMatchCB(
- XrmDatabase * database,
- XrmBindingList bindings,
- XrmQuarkList quarks,
- XrmRepresentation * type,
- XrmValue * value,
- XPointer client_data)
- { /*$CODE$*/
- __DtXlateSrchData * srchData = (__DtXlateSrchData *) client_data;
- /* always begin scoring from 0 and replacement values at NULL */
- srchData->curScore = 0;
- memset(srchData->curSpecRefs,0, sizeof(srchData->curSpecRefs));
- #ifdef DBG_MATCHING
- fprintf(stderr,"FindStdToOpMatch: "); PrintDbEntry(quarks,value);
- #endif
- /* check for a match */
- if ( CheckSearchPlatformMatchesSpec(srchData,
- quarks[PLATFORM_QUARK]) == False)
- return False; /* continue enumeration */
- #ifdef DBG_MATCHING
- fprintf(stderr,"platform matches\n");
- #endif
- if ( CheckSearchVerMatchesSpec(srchData,
- quarks[VERSION_QUARK]) == False)
- return False; /* continue enumeration */
- #ifdef DBG_MATCHING
- fprintf(stderr,"ver matches\n");
- #endif
- if ( CheckSearchOperMatchesSpec(srchData,
- quarks[OPERS_QUARK]) == False)
- return False; /* continue enumeration */
- #ifdef DBG_MATCHING
- fprintf(stderr,"oper matches\n");
- #endif
- if ( CheckSearchDirStdToOpMatchesSpec(srchData,
- quarks[DIRECTION_QUARK]) == False)
- return False; /* continue enumeration */
- #ifdef DBG_MATCHING
- fprintf(stderr,"kind matches\n");
- #endif
- /* now check for std value match and, if it is
- the best match so far, record the value */
- if ( CheckSearchStdValueMatchesSpec(srchData,
- &quarks[FIRSTSTD_QUARK]) == False )
- {
- if (srchData->db->debugMode)
- {
- fprintf(stderr,"mismatch ");
- PrintDbEntry(quarks,value);
- }
-
- return False; /* continue enumeration */
- }
- #ifdef DBG_MATCHING
- fprintf(stderr,"std value matches\n");
- #endif
- if (srchData->db->debugMode)
- {
- fprintf(stderr,"match (%d) ",srchData->curScore);
- PrintDbEntry(quarks,value);
- }
-
- /* we have a match! (we made it through all match checks) */
- /* is it better than or same as any earlier match? */
- if ( srchData->curScore >= srchData->bestScore )
- {
- /* recall that all strings are owned by Xrm==>no need to free them */
- srchData->bestScore = srchData->curScore;
- srchData->bestTransType = srchData->curTransType;
- memcpy(srchData->bestSpecRefs,srchData->curSpecRefs,
- sizeof(srchData->bestSpecRefs)); /* no array assignment in C */
- srchData->opValue = value->addr;
- }
- return False; /* continue enumeration */
- } /*$END$*/
- #if DOC
- /*========================================================*/
- $PFUNBEG$: FindOpToStdMatchCB()
- $1LINER$: Matches op value of entry to search pattern; gets std value
- $SUMMARY$:
- $ARGS$:
- $RETURNS$:
- /*================================================$SKIP$==*/
- #endif
- static
- Bool FindOpToStdMatchCB(
- XrmDatabase * database,
- XrmBindingList bindings,
- XrmQuarkList quarks,
- XrmRepresentation * type,
- XrmValue * value,
- XPointer client_data)
- { /*$CODE$*/
- __DtXlateSrchData * srchData = (__DtXlateSrchData *) client_data;
- /* always begin scoring from 0 and subexpression indices at -1 */
- srchData->curScore = 0;
- memset(srchData->curSubEx,-1, sizeof(srchData->curSubEx));
- #ifdef DBG_MATCHING
- fprintf(stderr,"FindOpToStdMatch: "); PrintDbEntry(quarks,value);
- #endif
- /* check for a match */
- if ( CheckSearchPlatformMatchesSpec(srchData,
- quarks[PLATFORM_QUARK]) == False)
- return False; /* continue enumeration */
- #ifdef DBG_MATCHING
- fprintf(stderr,"platform matches\n");
- #endif
- if ( CheckSearchVerMatchesSpec(srchData,
- quarks[VERSION_QUARK]) == False)
- return False; /* continue enumeration */
- #ifdef DBG_MATCHING
- fprintf(stderr,"ver matches\n");
- #endif
- if ( CheckSearchOperMatchesSpec(srchData,
- quarks[OPERS_QUARK]) == False)
- return False; /* continue enumeration */
- #ifdef DBG_MATCHING
- fprintf(stderr,"oper matches\n");
- #endif
- if ( CheckSearchDirOpToStdMatchesSpec(srchData,
- quarks[DIRECTION_QUARK]) == False)
- return False; /* continue enumeration */
- #ifdef DBG_MATCHING
- fprintf(stderr,"kind matches\n");
- #endif
- /* now check for op value match and, if it is
- the best match so far, record the std value */
- if ( CheckSearchOpValueMatchesSpec(srchData,
- value->addr) == False )
- {
- if (srchData->db->debugMode)
- {
- fprintf(stderr,"mismatch ");
- PrintDbEntry(quarks,value);
- }
-
- return False; /* continue enumeration */
- }
- #ifdef DBG_MATCHING
- fprintf(stderr,"op value matches\n");
- #endif
- if (srchData->db->debugMode)
- {
- fprintf(stderr,"match (%d) ",srchData->curScore);
- PrintDbEntry(quarks,value);
- }
- /* we have a match! (we made it through all match checks) */
- /* is it better than or same as any earlier match? */
- if ( srchData->curScore >= srchData->bestScore )
- {
- XrmQuarkList stdQ;
- XrmQuarkList curQ;
- /* recall that all strings are owned by Xrm==>no need to free them */
- srchData->bestScore = srchData->curScore;
- srchData->bestTransType = srchData->curTransType;
- memcpy(srchData->bestSubEx,srchData->curSubEx,
- sizeof(srchData->bestSubEx)); /* no array assignment in C */
- /* store off the std value of the best match */
- stdQ = srchData->stdValueQuarks;
- curQ = &quarks[FIRSTSTD_QUARK];
- while ( (*stdQ = *curQ) != NULLQUARK ) stdQ++, curQ++;
- }
- return False; /* continue enumeration */
- } /*$END$*/
- #if DOC
- /*========================================================*/
- $PFUNBEG$: DoCommonSrchDataPrep
- $1LINER$: Prep srchData to search for a pattern
- $SUMMARY$:
- $ARGS$:
- $RETURNS$:
- /*================================================$SKIP$==*/
- #endif
- static
- void DoCommonSrchDataPrep(
- __DtXlateSrchData * srchData,
- _DtXlateDb db,
- const char * platform,
- const int version,
- const char * operation)
- { /*$CODE$*/
- int verNum = version; /* for lint */
- /* zero the search data */
- memset(srchData,0,sizeof(__DtXlateSrchData));
- /* set the db */
- srchData->db = db;
-
- /* build filter list for enumerating the db */
- if (verNum < MATCHALL_VER) verNum = MATCHALL_VER;
- srchData->platformStr = platform;
- srchData->platformQuark = (platform?XrmStringToQuark(platform):NULLQUARK);
- srchData->version = verNum;
- sprintf(srchData->verStr,"%d",verNum);
- srchData->operStr = operation;
- srchData->operStrLen = strlen(operation);
- srchData->operQuark = (operation ? XrmStringToQuark(operation) : NULLQUARK);
- srchData->lessThanQuark = XrmStringToQuark(LESSTHAN_STR);
- srchData->equalsToQuark = XrmStringToQuark(EQUALS_STR);
- srchData->containsQuark = XrmStringToQuark(CONTAINS_STR);
- srchData->moreThanQuark = XrmStringToQuark(MORETHAN_STR);
- srchData->inhibitQuark = XrmStringToQuark(INHIBIT_STR);
- } /*$END$*/
- /*========================================================*/
- /*=============== Public Xlate routines ==================*/
- /*========================================================*/
- #if DOC
- /*========================================================*/
- $FUNBEG$: _DtXlateOpenDb()
- $1LINER$: Open a translation database
- $SUMMARY$:
- Opens a translation resource database and returns a
- reference to it in ret_db.
- Initializes the _DtXlateDb object to ready for use.
- If an error occurs, _DtXlateDb is set to NULL.
- $ARGS$:
- $RETURNS$:
- 0: no error occurred
- -1: if ret_db is NULL
- if XrmGetFileDatabase() failed on databaseName
- if malloc fails to alloc a db structure
- /*================================================$SKIP$==*/
- #endif
- int _DtXlateOpenDb(
- const char * databaseName,
- _DtXlateDb * ret_db)
- { /*$CODE$*/
- XrmDatabase xrmDb;
- __DtXlateDbRec * dbRec = NULL;
- char * path = NULL;
- if(NULL == ret_db) return -1; /* RETURN */
- *ret_db = NULL;
- /* Do NOT check for whether *ret_db is already
- a valid db; this is none of our affair. */
- /* get an absolute path for the file */
- path = ExpandPath(databaseName);
- if (NULL == path) return -1; /* RETURN */
- xrmDb = XrmGetFileDatabase(path);
- if (NULL == xrmDb) { free(path); return -1; } /* RETURN */
- /* alloc a db ref */
- dbRec = (__DtXlateDbRec *) calloc(1,sizeof(__DtXlateDbRec));
- if(NULL == dbRec)
- {
- XrmDestroyDatabase(xrmDb);
- free(path);
- return -1; /* RETURN */
- }
- /* and populate it */
- dbRec->xrmDb = xrmDb;
- dbRec->initGuard = INIT_OCCURRED;
- /* check for debug mode */
- SetDebugModeState(dbRec);
- if (dbRec->debugMode)
- fprintf(stderr,"_DtXlateOpenDb: opened: %s; new db: %p\n",path, (void *)dbRec);
- *ret_db = dbRec;
- free(path);
- return 0; /* RETURN */
- } /*$END$*/
- #if DOC
- /*========================================================*/
- $FUNBEG$: _DtXlateOpenAndMergeDbs()
- $1LINER$: Opens a translation database and merges with earlier dbs
- $SUMMARY$:
- Opens a translation resource database and returns a
- reference to it in ret_db.
- Initializes the _DtXlateDb object to ready for use.
- $ARGS$:
- $RETURNS$:
- 0: no error occurred
- -1: if io_db is NULL
- if XrmGetFileDatabase() failed on databaseName
- /*================================================$SKIP$==*/
- #endif
- int _DtXlateOpenAndMergeDbs(
- const char * databaseName,
- _DtXlateDb * io_db)
- { /*$CODE$*/
- XrmDatabase xrmDb;
- char * path;
- int ret;
- if(NULL == io_db) return -1; /* RETURN */
- /* if a db has not yet been opened */
- if( NULL == *io_db
- || (*io_db)->initGuard != INIT_OCCURRED
- || (*io_db)->xrmDb == NULL)
- {
- ret = _DtXlateOpenDb(databaseName,io_db); /* RETURN */
- if ( (*io_db) && (*io_db)->debugMode)
- fprintf(stderr,"_DtXlateOpenAndMergeDb: "
- "used _DtXlateOpenDb to open first file\n");
- return ret; /* RETURN */
- }
-
- if ( (*io_db) && (*io_db)->debugMode)
- fprintf(stderr,"_DtXlateOpenAndMergeDb: "
- "target file: %s; existing db: %p\n",databaseName, (void *) *io_db);
- /* a db has been opened, let's merge with it */
- /* get an absolute path for the file */
- path = ExpandPath(databaseName);
- if (NULL == path) goto Failed; /* RETURN */
- xrmDb = XrmGetFileDatabase(path);
- if (NULL == xrmDb) goto Failed; /* RETURN */
- /* merge and destroy xrmDb for me */
- XrmMergeDatabases(xrmDb,&(*io_db)->xrmDb);
- /* check for debug mode */
- SetDebugModeState(*io_db);
- if ((*io_db)->debugMode)
- fprintf(stderr,"_DtXlateOpenAndMergeDb: "
- "opened: %s; merged db: %p\n",path, (void *) *io_db);
- free(path);
- return 0; /* RETURN */
- Failed:
- if ( (*io_db) && (*io_db)->debugMode)
- fprintf(stderr,"_DtXlateOpenAndMergeDb: open failed; file: %s\n",
- (path ? path : (databaseName ? databaseName : "NULL") ) );
- if (path) free(path);
- return -1; /* RETURN */
- } /*$END$*/
- #if DOC
- /*========================================================*/
- $FUNBEG$: _DtXlateMergeDbs()
- $1LINER$: Merges two open dbs into one and closes the merged-in db.
- $SUMMARY$:
- Merges two databases into one and closes the merged db.
- The io_dbToMerge database must be a valid translation database.
- The io_dbToMerge database is merged into the io_mergeIntoDb.
- The io_mergeIntoDb may either be invalid or valid. If invalid,
- the io_dbToMerge database is simply moved over to io_mergeIntoDb.
- If io_mergeIntoDb is valid, the entries in the io_dbToMerge
- database are merged into it and take precedence over entries in the
- io_mergeIntoDb, and the io_dbToMerge database is closed.
- $ARGS$:
- io_dbToMerge: database to merge into io_mergeIntoDb
- io_mergeIntoDb: database to hold merged result
- $RETURNS$:
- 0: no error occurred
- -1: if io_dbToMerge or io_mergeIntoDb is NULL
- if *io_dbToMerge is NULL or uninitialized
- /*================================================$SKIP$==*/
- #endif
- int _DtXlateMergeDbs(
- _DtXlateDb * io_dbToMerge,
- _DtXlateDb * io_mergeIntoDb)
- { /*$CODE$*/
- /* check args */
- if( NULL == io_mergeIntoDb
- || NULL == io_dbToMerge
- || NULL == *io_dbToMerge
- || (*io_dbToMerge)->initGuard != INIT_OCCURRED
- || (*io_dbToMerge)->xrmDb == NULL)
- return -1; /* RETURN */
- /* check for debug mode */
- if ( ((*io_mergeIntoDb) && (*io_mergeIntoDb)->debugMode)
- || (*io_dbToMerge)->debugMode)
- fprintf(stderr,"_DtXlateMergeDbs: "
- "mergeIntoDb: %p; dbToMerge: %p\n", (void *) *io_mergeIntoDb, (void *) *io_dbToMerge);
- /* if db_mergeIntoDb has not yet been opened */
- if( NULL == *io_mergeIntoDb
- || (*io_mergeIntoDb)->initGuard != INIT_OCCURRED
- || (*io_mergeIntoDb)->xrmDb == NULL)
- {
- /* just move dbToMerge into mergeIntoDb */
- *io_mergeIntoDb = *io_dbToMerge;
- DeleteDbMem(io_dbToMerge);
- return 0; /* RETURN */
- }
-
- /* merge and destroy io_dbToMerge->xrmDb for me */
- XrmMergeDatabases((*io_dbToMerge)->xrmDb,&(*io_mergeIntoDb)->xrmDb);
- DeleteDbMem(io_dbToMerge);
- /* check for debug mode */
- SetDebugModeState(*io_mergeIntoDb);
- if ((*io_mergeIntoDb)->debugMode)
- fprintf(stderr,"merged db: %p\n", (void *) *io_mergeIntoDb);
- return 0;
- } /*$END$*/
- #if DOC
- /*========================================================*/
- $FUNBEG$: _DtXlateOpenAllDbs()
- $1LINER$: Open and merge all locale translation databases that can be found
- $SUMMARY$:
- DtXlateOpenAllDbs() locates all translation databases
- present in the search paths directories.
- $ARGS$:
- searchPaths: ':' separated list of directories
- databaseName: name of the database file in those directories
- ret_db: the reference to the open database is stored here
- $RETURNS$:
- 0: at least one database was opened
- -1: no database was opened
- /*================================================$SKIP$==*/
- #endif
- int _DtXlateOpenAllDbs(
- const char * searchPaths,
- const char * databaseName,
- _DtXlateDb * ret_db)
- { /*$CODE$*/
- const char * workStart = searchPaths;
- const char * separator = NULL;
- char dbFile[MAXPATHLEN+1];
- int ret = ~0; /* all bits set */
- /* cycle through the paths, opening each one */
- do
- {
- int workLen = 0;
- const char * slash = NULL;
- dbFile[0] = EOS;
- /* isolate the next part of the path */
- _DtMBStrchr (workStart, PATH_SEPARATOR, -1, &separator);
- if (NULL == separator) _DtMBStrchr (workStart, EOS, -1, &separator);
- if (NULL == separator) break; /* BREAK */
- workLen = separator - workStart; /* don't include +1 for EOS */
- /* copy over the path component */
- strncpy(dbFile,workStart,workLen);
- workStart = separator + 1;
- /* add a slash to end of path component, if needed */
- *(dbFile+workLen) = EOS; /* add an EOS for _DtMBStrrchr to find */
- _DtMBStrrchr(dbFile,DIR_SLASH,-1,&slash);
- if (slash != dbFile+workLen-1) /* is slash last char of path? */
- {
- *(dbFile+workLen) = DIR_SLASH;
- workLen++;
- }
- /* append the filename and EOS */
- strcpy(dbFile+workLen,databaseName);
- /*printf("Working on: %s\n", dbFile); **DBG*/
- /* open and merge the database with previously opened dbs */
- /* by ANDing, we determine whether at least one call returned 0 */
- ret &= _DtXlateOpenAndMergeDbs(dbFile,ret_db);
- } while ( *separator != EOS );
- if (*ret_db && (*ret_db)->debugMode)
- fprintf(stderr,"_DtXlateOpenAllDbs: completed\n"
- " srchpaths: %s; db file: %s\n",searchPaths,databaseName);
- return (ret == 0 ? 0 : -1); /* ret != 0 ==> no db was opened */
- } /*$END$*/
- #if DOC
- /*========================================================*/
- $FUNBEG$: _DtXlateCloseDb()
- $1LINER$: Close an open translation database
- $SUMMARY$:
- _DtXlafteCloseDb() releases all memory associated with
- the translation database. Further use of the database
- object is an error.
- $ARGS$:
- $RETURNS$:
- 0: database was valid and has been closed
- -1: invalid database pointer
- /*================================================$SKIP$==*/
- #endif
- int _DtXlateCloseDb(
- _DtXlateDb * io_db)
- { /*$CODE$*/
- __DtXlateDbRec * dbRec;
-
- if( NULL == io_db
- || NULL == (dbRec = *io_db) /* dbRec assigned */
- || dbRec->initGuard != INIT_OCCURRED)
- return -1; /* RETURN */
-
- XrmDestroyDatabase(dbRec->xrmDb);
- if (dbRec->debugMode) fprintf(stderr,"_DtXlateCloseDb: %p\n", (void *) dbRec);
- /* zero out object mem and free it */
- DeleteDbMem(io_db);
- return 0;
- } /*$END$*/
- #if DOC
- /*========================================================*/
- $FUNBEG$: _DbXlateStdToOpValue()
- $1LINER$: Translates a standardized spec to an operation-specific value
- $SUMMARY$:
- Looks up the best translation of the standard value for an
- operation and places a pointer to the translation string
- at the location pointed to by ret_opValue.
- The translated string was allocated using malloc() and
- must be freed when no longer needed.
- If ret_opValue is NULL, the function merely verifies that
- a valid translation exists.
- $ARGS$:
- db: a translation database
- platform: the platform string (see _DtXlateGetXlateEnv())
- version: the version number (see _DtXlateGetXlateEnv())
- operation: the operation of interest, e.g. "setlocale"
- stdValue: the standard value pattern
- ret_opValue: location where ptr to translated string is stored
- ret_reserved: reserved for future use
- $RETURNS$:
- 0: translation found
- -1: invalid database (NULL ptr, not opened)
- no operation was specified
- query failed to find a match
- /*================================================$SKIP$==*/
- #endif
- int _DtXlateStdToOpValue(
- _DtXlateDb db,
- const char * platform,
- const int version,
- const char * operation,
- const char * stdValue,
- char * * ret_opValue,
- void * ret_reserved)
- { /*$CODE$*/
- __DtXlateSrchData srchData;
- XrmQuark empty = NULLQUARK;
- if ( NULL == db
- || db->initGuard != INIT_OCCURRED
- || NULL == operation
- || operation[0] == EOS)
- return -1; /* RETURN error */
- /* prep srch data for search */
- DoCommonSrchDataPrep(&srchData,db,platform,version,operation);
- /* handle a rare case */
- if (NULL == stdValue)
- {
- if (db->debugMode) fprintf(stderr,"_DtXlateStdToOpValue: NULL std value\n");
- if (ret_opValue) *ret_opValue = NULL;
- return -1; /* RETURN error */
- }
- /* build std value list for use during comparison */
- srchData.stdValueQuarks[0] = NULLQUARK;
- if (NULL != stdValue && stdValue[0] != EOS)
- XrmStringToQuarkList(stdValue,srchData.stdValueQuarks);
- if (db->debugMode)
- fprintf(stderr,"_DtXlateStdToOpValue: %s.%d.%s.%s: <op>\n",
- platform,version,operation,stdValue);
- /* scan through this Db looking for matches and put in search */
- XrmEnumerateDatabase(db->xrmDb,&empty,&empty,
- XrmEnumAllLevels, FindStdToOpMatchCB, (XPointer) &srchData);
- if ( srchData.opValue != NULL
- && srchData.bestTransType != __DtXLATE_TYPE_INHIBIT )
- {
- char * opValue;
-
- if (ret_opValue == NULL)
- {
- if (db->debugMode) fprintf(stderr,"translation exists\n");
- return 0; /* RETURN: translation exists */
- }
-
- /* alloc the string to return */
- opValue = strdup(srchData.opValue);
- if (db->debugMode) fprintf(stderr,"raw opval:%s\n",opValue);
- /* do quote and escape removal and ref replacement in the opValue */
- if ( srchData.bestTransType == __DtXLATE_TYPE_REGEX )
- StripMetaAndReplaceEscSubex(&opValue,False,srchData.bestSpecRefs);
- else
- StripMetaAndReplaceEscSubex(&opValue,False,NULL);
- if (db->debugMode) fprintf(stderr,"op value:%s\n",opValue);
- *ret_opValue = opValue;
- return 0; /* RETURN: search successful */
- }
- return -1; /* RETURN: search failed */
- } /*$END$*/
- #if DOC
- /*========================================================*/
- $FUNBEG$: _DbXlateOpToStdValue()
- $1LINER$: Translates an operation-specific value to a standardized one
- $SUMMARY$:
- Looks up the best translation of the operation value for an
- operation and places a pointer to the standard string
- at the location pointed to by ret_stdValue.
- The standard string was allocated using malloc() and
- must be freed when no longer needed.
- If ret_stdValue is NULL, the function merely verifies that
- a valid translation exists.
- $ARGS$:
- db: a translation database
- platform: the platform string (see _DtXlateGetXlateEnv())
- version: the version number (see _DtXlateGetXlateEnv())
- operation: the operation of interest, e.g. "setlocale"
- opValue: the operation-specific value pattern
- ret_stdValue: location where ptr to standard string is stored
- ret_reserved: reserved for future use
- $RETURNS$:
- 0: translation found
- -1: invalid database (NULL ptr, not opened)
- no operation was specified
- query failed to find a match
- /*================================================$SKIP$==*/
- #endif
- int _DtXlateOpToStdValue(
- _DtXlateDb db,
- const char * platform,
- const int version,
- const char * operation,
- const char * opValue,
- char * * ret_stdValue,
- void * ret_reserved)
- { /*$CODE$*/
- __DtXlateSrchData srchData;
- XrmQuark empty = NULLQUARK;
- char lhs[MAXLHSSIZE];
- if ( NULL == db
- || db->initGuard != INIT_OCCURRED
- || NULL == operation
- || operation[0] == EOS)
- return -1; /* RETURN error */
- /* prep srch data for search */
- DoCommonSrchDataPrep(&srchData,db,platform,version,operation);
- /* after check on value, store op value for use during comparison */
- /* not meaningful to check for a NULL value */
- if (NULL == opValue)
- {
- if (db->debugMode) fprintf(stderr,"_DtXlateOpToStdValue: NULL op value\n");
- if (ret_stdValue) *ret_stdValue = NULL;
- return -1; /* RETURN error */
- }
- srchData.opValue = opValue;
- if (db->debugMode)
- fprintf(stderr,"_DtXlateOpToStdValue: %s.%d.%s.<std>: %s\n",
- platform,version,operation,opValue);
- /* scan through this Db looking for matches and put in search */
- XrmEnumerateDatabase(db->xrmDb,&empty,&empty,
- XrmEnumAllLevels, FindOpToStdMatchCB, (XPointer) &srchData);
- if ( srchData.stdValueQuarks[0] != NULLQUARK
- && srchData.bestTransType != __DtXLATE_TYPE_INHIBIT )
- {
- XrmQuarkList stdQ;
- char * stdValue = lhs;
- int stdValueLen = 0;
- if (ret_stdValue == NULL)
- {
- if (db->debugMode) fprintf(stderr,"translation exists\n");
- return 0; /* RETURN: translation exists */
- }
- /* make a STDVALUE_SEPARATOR separated string out of the std data */
- for ( stdQ = srchData.stdValueQuarks;
- *stdQ != NULLQUARK;
- stdQ++ )
- {
- const char * str = XrmQuarkToString(*stdQ);
- int strLen;
- if (NULL == str || str[0] == EOS) continue;
-
- strLen = strlen(str);
- if (stdValue != lhs)
- {*stdValue++ = STDVALUE_SEPARATOR; stdValueLen++; }
- if ((stdValueLen + strLen) > sizeof(lhs) )
- strLen = sizeof(lhs)-stdValueLen;
- strncpy(stdValue,str,strLen);
- stdValueLen += strLen;
- stdValue += strLen;
- }
- *stdValue = EOS;
- if (db->debugMode) fprintf(stderr,"raw stdval:%s\n",lhs);
- /* do quote and escape removal and ref replacement in the stdValue */
- stdValue = strdup(lhs); /* reset stdValue ptr */
- if ( srchData.bestTransType == __DtXLATE_TYPE_REGEX )
- ReplaceMatchallSubex(&stdValue,srchData.bestSubEx,srchData.opValue);
- if (db->debugMode) fprintf(stderr,"std value:%s\n",stdValue);
- *ret_stdValue = stdValue;
- return 0; /* RETURN: search successful */
- }
- return -1; /* RETURN: search failed */
- } /*$END$*/
- #if DOC
- /*========================================================*/
- $FUNBEG$: _DtXlateGetXlateEnv()
- $1LINER$: Get the DtXlate compilation and execution environments.
- $SUMMARY$:
- _DtXlateGetXlateEnv() recovers the identity of the application
- current platform, the version value of the application
- execution environment, and the version value of the operating
- system version for which DtXlateGetXlateEnv() was
- compiled. These values can be used in formulating queries,
- especially for the _DtXlateStdToOpValue() query.
- The technique used by this routine is as follows. Using
- uname(2), the routine retrieves the sysname, release, and version
- strings. The sysname is used as the platform name. The
- release and version strings are concatenated in that order
- and as treated below as the <op-rel-ver>. An OpToStd translation
- looks for a match to
- <sysname>.?.version.<.<std-version>: <op-rel-ver>
- or
- <sysname>.?.version.=.<std-version>: <op-rel-ver>
- If no match is found, the next fallback position is to
- get the specification with the same sysname and the highest
- std-version integer value. If no specifications exist for
- that sysname, then sysname is set to the empty string and
- std-version is -1.
- ret_AppExecEnvPlatform should point to a character array at least
- _DtPLATFORM_MAX_LEN characters long. The sysname is copied to it.
- ret_AppExecEnvVersion is given the integer value of the
- std-version recovered from the translation.
- ret_XlateCompiledForOSVersion is given the integer value
- determined by using the OSMajorVersion and OSMinorVersion
- constants defined by the build environment of _DtXlate as follows:
- #define _STR(V) #V
- #define STR(V) _STR(V)
- sprintf(buf,"%s%s%s", STR(OSMAJORVERSION),
- nl_langinfo(RADIXCHAR), STR(OSMAJORVERSION));
- verNum = (int) (100.0 * atof(buf));
- For example:
- OSMAJORVERSION & OSMINORVERSION are compile-time constants
- that must be defined as part of the build environment.
- It is assumed that these constants are of the form:
- e.g. Sun 5.3
- #define OSMAJORVERSION 5
- #define OSMINORVERSION 3
-
- 530 = (int) 100.0 * atof("5.3");
-
- e.g. HP-UX 8.09
- #define OSMAJORVERSION 8
- #define OSMINORVERSION 09
-
- 809 = (int) 100.0 * atof("8.09");
-
- Note that it may be necessary for the application to determine
- the version number of an operation in some platform-specific
- and operation-specific manner, for example using a library
- version value. In many cases, however, the O.S. version value
- for which _DtXlate was compiled will be sufficient
- when identifying version numbers for standard development
- environment libraries, such as libc.
- $EXAMPLE$:
- char *
- xlateStd2Op(_DtXlateDb db,Boolean runtimeOp, char * operation,char * stdVal)
- {
- char platform[_DtPLATFORM_MAX_LEN];
- int version;
- char * opVal = NULL;
- int ret;
- if (runtimeOp)
- ret=_DtXlateGetXlateEnv(db,platform,&version,NULL);
- else
- ret=_DtXlateGetXlateEnv(db,platform,NULL,&version);
- if (ret == 0)
- _DtXlateStdToOpValue(db,platform,version,operation,stdVal,&opVal,NULL);
- return opVal; /* will be NULL if error occurred */
- }
- $ARGS$:
- ret_AppExecEnvPlatform: pts to a string at least _DtPLATFORM_MAX_LEN long
- that will hold the string uname(2) returns for sysname
- ret_AppExecEnvVersion: pts to an integer that will receive the platform
- standardized version number, as determined by
- a translation on uname(2) release+version.
- ret_XlateCompiledForOSVersion: pts to an integer that will receive the
- operating system version for which _DtXlate was
- compiled using OSMajorVersion * 100 + OSMinorVersion
- Any of the arguments may be NULL.
- $RETURNS$:
- 0: if no error occurred
- -1: if no translation was possible to get the AppExecEnvVersion
- /*================================================$SKIP$==*/
- #endif
- int _DtXlateGetXlateEnv(
- _DtXlateDb db,
- char * ret_AppExecEnvPlatform,
- int * ret_AppExecEnvVersion,
- int * ret_XlateCompiledForOSVersion)
- { /*$CODE$*/
- struct utsname names;
- int ret = 0;
- char * platform = "NULL";
- int execver = -1;
- int compver = -1;
- /* get host specifics */
- uname(&names);
- /* first get execution host name */
- if (ret_AppExecEnvPlatform)
- {
- strncpy(ret_AppExecEnvPlatform,names.sysname,_DtPLATFORM_MAX_LEN-1);
- ret_AppExecEnvPlatform[_DtPLATFORM_MAX_LEN-1] = EOS;
- platform=ret_AppExecEnvPlatform;
- }
- /* then look up version number of execution host */
- if (ret_AppExecEnvVersion)
- {
- #if defined(sun) || defined(_AIX) || defined(__linux__) || defined(CSRG_BASED)
- char version[SYS_NMLN+SYS_NMLN+2];
- #else
- char version[UTSLEN+UTSLEN+2];
- #endif
- char * stdVer = NULL;
- int verNum = MATCHALL_VER;
- /* cat release version and do a translation on it to a std value */
- /* then convert the std value to a integer */
- strcpy(version,names.release);
- strcat(version,names.version);
- ret = _DtXlateOpToStdValue(db,names.sysname,0,
- _DtXLATE_OPER_VERSION,version,&stdVer,NULL);
- if (ret == 0)
- {
- if (sscanf(stdVer,"%d",&verNum) != 1) verNum = MATCHALL_VER;;
- free(stdVer);
- }
- *ret_AppExecEnvVersion = verNum;
- execver = verNum;
- }
-
- /* then look up version number of execution host */
- if (ret_XlateCompiledForOSVersion)
- {
- char buf[MAXINTSTRSIZE];
- #define _STR(V) #V
- #define STR(V) _STR(V)
- /*===========================
- OSMAJORVERSION & OSMINORVERSION are compile-time constants
- that must be defined as part of the build environment.
- It is assumed that these constants are of the form:
- e.g. Sun 5.3
- #define OSMAJORVERSION 5
- #define OSMINORVERSION 3
-
- 530 = (int) (100.0 * atof("5.3"));
-
- e.g. HP-UX 8.09
- #define OSMAJORVERSION 8
- #define OSMINORVERSION 09
-
- 809 = (int) (100.0 * atof("8.09"));
- ===========================*/
- #if !defined(OSMAJORVERSION) || !defined(OSMINORVERSION) || OSMAJORVERSION == 0
- #error OSMAJORVERSION and/or OSMINORVERSION not defined
- #endif
- #if defined(__linux__) || defined(CSRG_BASED)
- sprintf(buf,"%s%s%s", STR(OSMAJORVERSION),
- nl_langinfo('.'), STR(OSMINORVERSION));
- #else
- sprintf(buf,"%s%s%s", STR(OSMAJORVERSION),
- nl_langinfo(RADIXCHAR), STR(OSMINORVERSION));
- #endif
- *ret_XlateCompiledForOSVersion = (int) (100.0 * atof(buf));
- compver = *ret_XlateCompiledForOSVersion;
- }
- if (db->debugMode)
- fprintf(stderr,"_DtXlateGetXlateEnv: "
- "Platform: %s; Execution Ver: %d; Compiled Ver: %d\n",
- platform,execver,compver);
- return ret;
- } /*$END$*/
- /*========================================================*/
- /*================ Introductory Info =====================*/
- /*========================================================*/
- #if DOC
- /*========================================================*/
- $INTROBEG$: _DtXlate family
- $1LINER$: API to translate any value to a standard value and back again
- $SUMMARY$:
- _DtXlate is a collection of routines that allow translation
- between platform, version, and operation specific values
- into standard values and back again. Translation is
- based on the contents of database files specified using
- Xrm-style resources. The semantics of the translation
- are a combination of standard semantics for specifying
- platform, version, operation, and translation type, and
- caller-specific semantics for the standard value format
- and operation values.
- The API contains routines to process translation databases
- in a useful manner.
- _DtXlateOpenDb() opens a particular translation database
- _DtXlateOpenAndMergeDb() opens a particular database and
- merges it with an already opened one, overriding any
- repeated specifications.
- _DtXlateOpenAllDbs() opens all occurrences of a translation
- database found in a search path and cumulatively merges
- the contents, allowing for the override of existing
- specifications as well as the addition of new ones.
- _DtXlateCloseDb() closes an open database
- _DtXlateOpToStdValue() translates an platform, version,
- and operation specific value into a standard value.
- _DtXlateStdToOpValue() translates a standard value into
- a platform, version, and operation specific value.
- /*=$END$================================================*/
- #endif
- #if DOC
- /*========================================================*/
- $INTROBEG$: Design and Implementation Considerations
- $1LINER$: Factors influencing design and implementation
- $SUMMARY$:
- The syntax of the translation specification table is designed
- to be compatible with Xrm resource specifications. This
- allows Xrm to be used to load, parse, and merge the databases
- for processing. This also causes the specifications to be
- case-sensitive, as case is preserved by Xrm and is used when
- processing queries.
- However, due to the semantics of translation specifications
- and limitations of Xrm, XrmGetResource() queries generally
- will not be useful. Rather, a pattern matching API is provided
- that implements the query capability used for the translations.
- The initial implementation will use XrmEnumerateDatabase().
- Using Xrm leads to an in-memory approach to translation, meaning
- that all the resources files are parsed and loaded into memory
- as the first step of a translation. A line-at-a-time approach,
- that process one line at a time directly from the file in a
- grep- or awk-like manner, is likely more memory-efficient.
- Note that the line-at-a-time approach does not avoid parsing
- all the specification files, as the API supports inheritence
- and override of specifications. Hence, to ensure the correct
- value, the entire file set must be processed. Note also that
- in a situation where translations will be repeatedly performed,
- the Xrm in-memory approach may be more time-efficient, as the
- files need only be parsed once, and then are utilized repeatedly.
- Because of time constraints, a line-at-a-time approach will not
- be used for the first implementation, as Xrm provides all the
- necessary parsing, filtering, and symbol hashing routines
- for free. Given the likely large size of the tables and their
- infrequent use, a line-at-a-time approach is likely the better
- choice.
- /*=$END$================================================*/
- #endif
- #if DOC
- /*========================================================*/
- $INTROBEG$: translation BNF syntax and semantics
- $1LINER$: _DtXlate translation specification syntax and semantics
- $SUMMARY$:
- BNF Syntax of Translation Specification
- =======================================
- <specfile> ::= (<xlatespec> | <comment> | <cr>)*
- <xlatespec> ::= <platform>.<version>.<operations>.<transtype>
- .<stdvalue>:<opvalue> (<comment>|<cr>)
- <platform> ::= <identifier> | <matchall>
- <version> ::= <number> [+ | (- <number>)] | <matchall>
- <operations> ::= <identifier> [',' <identifier>]* | <matchall>
- <transtype> ::= '<' | '=' | '~' | '>' | '0'
- <stdvalue> ::= <identifier> [.<identifier>]*
- <langterr> ::= <identifier> | <matchall>
- <codeset> ::= <identifier> | <matchall>
- <modifier> ::= <identifier> | <matchall>
- <opvalue> ::= (<vischars>|<metachar>)+ | '"'(<anychar>|<metachar>)+'"'
- <matchall> ::= '?'[<number>]
- <cr> ::= '\n'
- <comment> ::= '!' [^<cr>]* <cr>
- <number> ::= [0-9]+
- <identifier> ::= [-_a-ZA-Z0-9]
- <vischar> ::= any non-whitespace character; meta and regular
- expression chars must be escaped with "\\"
- <anychar> ::= any printable character; meta and regular
- expression chars must be escaped with "\\"
- <metachar> ::= '!' | '"' | <backslash> | <valex> | <regex>
- <valex> ::= <backslash><number>
- <regex> ::= see regexp(5)
- <backslash> ::= the backslash character (\).
- Semantics of the Translation Specification
- ==========================================
- <specfile> : a file containing zero or more translation specifications
- or comments
- <xlatespec> : a translation specification defines a fully qualified
- string value which may be recovered by query pattern matching the
- specification. The qualifiers identify the semantics of the usage
- of the value, allowing queries to be meaningful. The entire xlatespec
- must be on one line of the file.
- <platform> : a CDE-standardized identifier for an operating system
- platform. The platform need not be supported by CDE, but CDE must
- have standardized an identifier for the platform in order for it to
- be used. For example, candidate platform identifiers are "HP-UX",
- "AIX", "SunOS", "Solaris", "SCO", etc. These identifiers are the
- values returned by uname(2):utsname.sysname and uname(1) -s, and
- I propose CDE standardize on using these values.
- The identifier string and matching constant value must be added to
- the source code of the translation routine in order for it to be
- recognized. This allows control over the platform registry
- and enables automatic generation of the platform on the execution
- host through the use of #ifdef <PLATFORM_CONST> in the source code.
- <version> : a platform-specific numeric value or range of numberic
- values that allows the value to be qualified to a particular version
- and release (version + release = version) or range of versions and
- releases of the platform. The version numbers must be integral and
- suitable for numeric comparison. The '+' can be used to specify an
- open upwards bound, as in 900+. The '- <number>' can be used to
- specify an upper bound, as in 900-999. If no range is specified,
- the version number must match exactly to the query pattern and/or
- execution environment.
- Platforms may not directly provide version numbers in a numeric
- format suitable for use when comparing with a translation
- specification. As part of the translation API source code,
- conversion routines must be supplied that translate the platform-
- specific values, such as those provided by uname(2), into a
- translation specification-compliant format suitable for comparison
- to <version>. Understanding the conversion routines operation
- will be necessary to ensure correct translation specifications.
- <operations> : a CDE-standardized identifier for the operation(s) to
- which the value applies. The operation(s) need not be supported by every
- platform, but CDE must have standardized an identifier for the operation
- in order for it to be used. More than one identifier may be included by
- concatenating them using the ',' separator, eg. "iconv1,iconv3".
- <transtype> : The <transtype> field records the direction of
- translation that the specification supports: '<', '=', '~', '>', '0'.
- Use '<' if the <opvalue> contains a regular expression; the
- specification may only be used to match an operation value in
- a _DtLcxXlateOpToStd() translation. Use '>' if the <opvalue>
- contains value replacement expressions using values from
- the <stdvalue> strings; the specification may only be used by a
- _DtLcxXlateStdToOp() translation. Use '=' if the <opvalue>
- is a pure string that may be used for either OpToStd() or
- StdToOp() translations, and the specification op-value must exactly
- match the op-value of the translation request. use '~' if the
- <opvalue> is a pure string that may be used for either OpToStd() or
- StdToOp() translations, and the specifation op-value must be
- a string within the op-value of the translation request.
- Use the '0' translation to represent that this particular
- translation should result in an error, that is should not result
- in a translation.
- Translations are two-way operations: from a host- and
- operation-specific value to standardized value, and back again.
- In many cases, a straight string value for string value translation
- is sufficient.
- But often, more sophisticated pattern matching and value generation
- mechanisms are useful to keep the table size small and as general
- as possible. In these cases, wildcard and regular expression
- operators are useful. Unfortunately, these specifications are not
- bi-direction. That is, the pattern matching string can be used
- to match against a pattern, but not to generate a result string.
- For example, the vi expression s/he*lo/hello/ matches "hello"
- as well as "hey look out below", but the reverse direction of
- "hello"->"he*lo" will not work.
- <stdvalue> : a sequence of one or more '.'-separated CDE-standardizd
- identifiers or matchall characters. This represents the canonical
- string used as a standard representation of a semantic value that
- may vary in different situations.
- <opvalue> : a string that has different uses depending on the
- value of <transtype>. If transtype is '<', the string is used
- as a regular expression to match the opValue in _DtLcxXlateOpToStd()
- requests. If the transtype is '>', the string is used as a
- replacement expression to generate a opValue in _DtLcxXlateStdToOp().
- If transtype is '=' or '~', the string is used as a straight string to
- both match for the OpToStd translation and as a value for
- the StdToOp translation.
- %
- If the opvalue contains whitespace, the opvalue must be enclosed in
- double quote characters. If the opvalue contains any meta characters
- that should not be treated as meta characters, they must be escaped by
- two preceding backslashs.Lack of an opvalue is not an error, but will
- be ignored during matches and return an empty string in a StdToOp
- translation; to specify that a given translation does not exist, the
- '0' translation type should be used or the specification should not
- occur.
- <comment> : a comment begins on an empty line with an unescaped !
- and continues to the end of the line.
- <matchall> : The matchall character is a universal quantifier, meaning
- that it symbolizes all possible values of the field where it is used.
- The matchall character may occur only in the qualifers side of
- a translation specification. Traditionally, the matchall character
- has been '*', but because of the semantics of Xrm, if the '*' is used
- as the matchall, Xrm does not restrict enumeration as needed.
- The matchall character may be followed by a number when the <transtype>
- is '>'. When this occurs, the string that matches the matchall
- character may be referenced in the <opvalue> by using the sequence
- \<number>, as in "\1". The occurrence is replaced with the matched
- string.
- /*=$END$================================================*/
- #endif
- #if DOC
- /*========================================================*/
- $INTROBEG$: translation specification examples
- $1LINER$: examples of _DtXlate translation specifications
- $EXAMPLE$:
- !! These are examples of bi-directional straight translations
- HP-UX.900-999.setlocale.=.en_US.hp-roman8: american
- HP-UX.900-999.setlocale.=.en_US.iso88591: american.iso88591
- HP-UX.900-999.setlocale.=.nl_BE.hp-roman8.fold: dutch@fold
- HP-UX.900-999.setlocale.=.nl_BE.hp-roman8.nofold: dutch@nofold
- !! These are examples of OpToStd translations utilizing regular
- !! expression patterns to match the search value.
- HP-UX.?.version.<.900: "A\\.09\\..*" !! any HPUX 9.x version
- HP-UX.?.version.<.807: "A\\.08\\.07.*"
- HP-UX.?.version.<.800: "A\\.08\\..*"
- AIX.?.version.<.320: "2 3"
- AIX.?.version.<.300: "[0-9] 3"
- SunOS.?.version.<.530: "5\\.3.*"
- SunOS.?.version.<.500: "5\\..*"
- !! These are examples of StdToOp translations utilizing matchall
- !! specifiers in the std value to match the search value.
- HP-UX.900+.iconv1.>.?.iso88596: arabic8
- HP-UX.900+.iconv1.>.?.iso88597: greek8
- HP-UX.900+.iconv1.>.?.hp-kana8: kana8
- HP-UX.900+.iconv1.>.?.hp-roman8: roman8
- !! The following examples use value replacement as part of their
- !! specifications. Using this can lead to much sparser tables, but
- !! it depends on op-specific and std values sharing the same strings.
- HP-UX.900-999.setlocale.<.nl_BE.hp-roman8.?1: [dD][uU][tT][cC][hH]@\\(.*\\)
- !HP-UX.900-999.setlocale.<.nl_BE.hp-roman8.?1: dutch@\\(.*\\)
- HP-UX.1000+.setlocale.>.?1.hp-roman8: \\1.roman8 !! all non-modif cases
- HP-UX.1000+.setlocale.>.?1.hp-roman8.?2: \\1.roman8@\\2 !! all modif cases
- /*=$END$================================================*/
- #endif
- #if DOC
- /*========================================================*/
- $INTROBEG$: _DtXlate example usage
- $1LINER$: Examples of how to _DtXlate
- $EXAMPLE$:
- #include <XlationSvc.h>
- main()
- {
- _DtXlateDb db = NULL;
- int ret;
- char plat[_DtPLATFORM_MAX_LEN];
- int execver;
- int compver;
- char * val = NULL;
- char * str = NULL;
- char empty = 0;
- #define OPER_YOUROP "myop"
- env = getenv("MYPATH");
- if (env == NULL) env = ∅
- ret = _DtXlateOpenAllDbs(env,"myfile.xlt",&db);
- ret = _DtXlateGetXlateEnv(db,plat,&execver,&compver);
- printf("Platform: %s\nExec Ver: %d\nComp Ver: %d\n",
- plat,execver,compver);
- ret = _DtXlateStdToOpValue(db,plat,compver,OPER_YOUROP,
- str="en_US.hp-roman8",&val,NULL);
- if (ret==0) printf("setlocale(%s) xlation=%s\n", str, val);
- else printf("no xlation\n", val);
- ret = _DtXlateOpToStdValue(db,plat,execver,OPER_YOUROP,
- str="american",&val,NULL);
- if (ret==0) printf("setlocale(%s) xlation=%s\n", str, val);
- else printf("no xlation\n", val);
- ret = _DtXlateCloseDb(&db);
- }
- /*=$END$================================================*/
- #endif
|