Back to home page

Enduro/X

 
 

    


0001 /**
0002  * @brief UBF library, filed table handling routins (i.e. .fd files)
0003  *   !!! THERE IS NO SUPPORT for multiple directories with in FLDTBLDIR !!!
0004  *   Also the usage of default `fld.tbl' is not supported, as seems to be un-needed
0005  *   feature.
0006  *   The emulator of UBF library
0007  *   Enduro Execution Library
0008  *
0009  * @file fieldtable.c
0010  */
0011 /* -----------------------------------------------------------------------------
0012  * Enduro/X Middleware Platform for Distributed Transaction Processing
0013  * Copyright (C) 2009-2016, ATR Baltic, Ltd. All Rights Reserved.
0014  * Copyright (C) 2017-2023, Mavimax, Ltd. All Rights Reserved.
0015  * This software is released under one of the following licenses:
0016  * AGPL (with Java and Go exceptions) or Mavimax's license for commercial use.
0017  * See LICENSE file for full text.
0018  * -----------------------------------------------------------------------------
0019  * AGPL license:
0020  *
0021  * This program is free software; you can redistribute it and/or modify it under
0022  * the terms of the GNU Affero General Public License, version 3 as published
0023  * by the Free Software Foundation;
0024  *
0025  * This program is distributed in the hope that it will be useful, but WITHOUT ANY
0026  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
0027  * PARTICULAR PURPOSE. See the GNU Affero General Public License, version 3
0028  * for more details.
0029  *
0030  * You should have received a copy of the GNU Affero General Public License along 
0031  * with this program; if not, write to the Free Software Foundation, Inc.,
0032  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
0033  *
0034  * -----------------------------------------------------------------------------
0035  * A commercial use license is available from Mavimax, Ltd
0036  * contact@mavimax.com
0037  * -----------------------------------------------------------------------------
0038  */
0039 
0040 /*---------------------------Includes-----------------------------------*/
0041 #include <string.h>
0042 #include <ubf_int.h>
0043 #include <stdlib.h>
0044 #include <errno.h>
0045 
0046 #include <fieldtable.h>
0047 #include <fdatatype.h>
0048 #include <ferror.h>
0049 #include <utlist.h>
0050 
0051 #include "ndebug.h"
0052 #include "ubf_tls.h"
0053 #include <thlock.h>
0054 #include <ubfdb.h>
0055 /*---------------------------Externs------------------------------------*/
0056 /*---------------------------Macros-------------------------------------*/
0057 
0058 
0059 /**
0060  * Used for Tuxedo compatibility, reverse search
0061  * Head is last element.
0062  */
0063 #define DL_REV_SEARCH(head,out,elt,cmp)                                         \
0064 do {                                                                            \
0065     if (head) {                                                                 \
0066         for(out=head->NDRX_PREV;;out=out->NDRX_PREV) {                          \
0067         if ((cmp(out,elt))==0) break;                                           \
0068         if (out==head) {out=NULL; break;}                                       \
0069         }                                                                       \
0070     }                                                                           \
0071 } while(0) 
0072 
0073 /*---------------------------Enums--------------------------------------*/
0074 /*---------------------------Typedefs-----------------------------------*/
0075 /*---------------------------Globals------------------------------------*/
0076 /*---------------------------Statics------------------------------------*/
0077 
0078 /* Hash tables V2 
0079  * We have dynamically allocated linear space for UBF_field defs.
0080  * Field defs by it self are linked lists, if hashkey gets the same (by modulus).
0081  * To get the entry out the search in linked list is done from the data key,
0082  * this is because, we never know is the node correct or not, even if there is only
0083  * one element in the list.
0084  * 
0085  * The example of data structures:
0086  * 
0087  *  + [UBF DEF 1] -> [UBF DEF 2] ->..-> [UBF DEF X]
0088  *  |   + [UBF DEF 4] -> [UBF DEF 5] ->..-> [UBF DEF Y]
0089  *  |   |
0090  * [0]-[1]-[2]..-..[n] # Linear array for hash key modulus
0091  * 
0092  * This ensures that our hash tables can correctly get data out (no duplicates!!)
0093  */
0094 exprivate  UBF_field_def_t ** M_bfldidhash2 = NULL; /* FLD ID hash */
0095 exprivate  UBF_field_def_t ** M_fldnmhash2 = NULL; /* FLD NM hash */
0096 exprivate  volatile int M_field_def_loaded = EXFALSE;       /* IS UBF loaded? */
0097 exprivate  int M_hash2_size = 16000; /* Default size for Hash2 */
0098 
0099 /*---------------------------Prototypes---------------------------------*/
0100 exprivate void _bfldidhash_add(UBF_field_def_t *p_fld);
0101 exprivate void _fldnmexhash_add(UBF_field_def_t *p_fld);
0102 exprivate int _ubf_load_fld_def(int base,
0103                               char *fldinfo,
0104                               int (*put_def_line) (UBF_field_def_t *def),
0105                               int check_dup,
0106                               char *fname,
0107                               int line);
0108 
0109 static unsigned int str_hash_from_key_fn( void *k );
0110 static int str_keys_equal_fn ( void *key1, void *key2 );
0111 
0112 
0113 /**
0114  * Hash 2 structure init
0115  * @return SUCCEED/FAIL
0116  */
0117 exprivate int init_hash_area(void)
0118 {
0119     int ret=EXSUCCEED;
0120     char *p;
0121     int malloc_size = sizeof(ft_node_t *)*M_hash2_size;
0122     int i;
0123     static int first = 1;
0124     UBF_field_def_t *elt, *tmp, *head;
0125 
0126     /* Init the table memory */
0127     if (first)
0128     {
0129         if (NULL!=(p=getenv("NDRX_UBFMAXFLDS")))
0130         {
0131             M_hash2_size = atoi(p);
0132             malloc_size = sizeof(ft_node_t *)*M_hash2_size;
0133         }
0134         UBF_LOG(log_debug, "Using NDRX_UBFMAXFLDS: %d", M_hash2_size);
0135         first = 0;
0136     }
0137 
0138     if (NULL==M_bfldidhash2)
0139     {
0140         M_bfldidhash2 = NDRX_MALLOC(malloc_size);
0141         if (NULL==M_bfldidhash2)
0142         {
0143             ndrx_Bset_error_fmt(BMALLOC, "Failed to malloc bfldidhash2, requested: %d bytes err: %s",
0144                         malloc_size, strerror(errno));
0145             ret=EXFAIL;
0146             goto out;
0147         }
0148     }
0149     else
0150     {
0151         /* Free up data if any, this could make init slower
0152          * but normally after first fail, it should not retry the op anyway
0153          */
0154         for (i=0; i<M_hash2_size; i++)
0155         {
0156             if (NULL!=M_bfldidhash2[i])
0157             {
0158                 head = M_bfldidhash2[i];
0159                 DL_FOREACH_SAFE(head,elt,tmp)
0160                 {
0161                     DL_DELETE(head, elt);
0162                 }
0163             } /* if */
0164         } /* for */
0165     }
0166 
0167     if (NULL==M_fldnmhash2)
0168     {
0169         M_fldnmhash2 = NDRX_MALLOC(malloc_size);
0170         if (NULL==M_fldnmhash2)
0171         {
0172             ndrx_Bset_error_fmt(BMALLOC, "Failed to malloc fldnmhash2, requested: %d bytes err: %s",
0173                         malloc_size, strerror(errno));
0174             ret=EXFAIL;
0175             goto out;
0176         }
0177     }
0178     else
0179     {
0180         /* Free up data if any, this could make init slower
0181          * but normally after first fail, it should not retry the op anyway
0182          */
0183         for (i=0; i<M_hash2_size; i++)
0184         {
0185             if (NULL!=M_fldnmhash2[i])
0186             {
0187                 head = M_fldnmhash2[i];
0188                 DL_FOREACH_SAFE(head,elt,tmp)
0189                 {
0190                     DL_DELETE(head, elt);
0191                 }
0192             } /* if */
0193         } /* for */
0194     }
0195     
0196     /* clean up space */
0197     memset(M_bfldidhash2, 0, malloc_size);
0198     /* clean up space */
0199     memset(M_fldnmhash2, 0, malloc_size);
0200     
0201 out:
0202     return ret;
0203 }
0204 
0205 /**
0206  * Add Field ID Hash record
0207  */
0208 exprivate void _bfldidhash_add(UBF_field_def_t *p_fld)
0209 {
0210     int hash_key = p_fld->bfldid % M_hash2_size; /* Simple mod based hash */
0211     
0212     DL_APPEND(M_bfldidhash2[hash_key], p_fld);
0213 }
0214 
0215 /**
0216  * Compares two field defs and returns equality result
0217  * @param a
0218  * @param b
0219  * @return 0 - equal/ -1 - not equal
0220  */
0221 exprivate int UBF_field_def_id_cmp(UBF_field_def_t *a, UBF_field_def_t *b)
0222 {
0223     return (a->bfldid==b->bfldid?EXSUCCEED:EXFAIL);
0224 }
0225 
0226 /**
0227  * Get field entry from int hash
0228  */
0229 expublic UBF_field_def_t * _bfldidhash_get(BFLDID id)
0230 {
0231     /* Get the linear array key */
0232     int hash_key = id % M_hash2_size; /* Simple mod based hash */
0233     UBF_field_def_t *ret=NULL;
0234     UBF_field_def_t tmp;
0235     
0236     tmp.bfldid=id;
0237     /* Use reverse search for correct duplicate field handling. */
0238     DL_REV_SEARCH(M_bfldidhash2[hash_key],ret,&tmp,UBF_field_def_id_cmp);
0239     
0240     return ret;
0241 }
0242 
0243 /**
0244  * Add Field Name Hash record
0245  */
0246 exprivate void _fldnmexhash_add(UBF_field_def_t *p_fld)
0247 {
0248     /* Get the linear array key */
0249     int hash_key = str_hash_from_key_fn(p_fld->fldname) % M_hash2_size;
0250     DL_APPEND(M_fldnmhash2[hash_key], p_fld);
0251 
0252 #ifdef EXTRA_FT_DEBUG
0253     printf("field [%s] key [%d] result [0%x] - [0%x] added\n", p_fld->fldname, hash_key, p_fld, M_fldnmhash2[hash_key]);
0254 #endif
0255 }
0256 
0257 
0258 /**
0259  * Compare two fields by using name
0260  * @param a
0261  * @param b
0262  * @return 0 - equal/ -1 - not equal
0263  */
0264 exprivate int UBF_field_def_nm_cmp(UBF_field_def_t *a, UBF_field_def_t *b)
0265 {
0266     return strcmp(a->fldname, b->fldname);
0267 }
0268 
0269 /**
0270  * Get field name entry from hash table.
0271  * @returns - NULL not found or ptr to UBF_field_def_t
0272  */
0273 expublic UBF_field_def_t * ndrx_fldnmhash_get(char *key)
0274 {
0275     /* Get the linear array key */
0276     int hash_key = str_hash_from_key_fn(key) % M_hash2_size;
0277     UBF_field_def_t *ret=NULL;
0278     UBF_field_def_t tmp;
0279     NDRX_STRCPY_SAFE(tmp.fldname, key);
0280     DL_REV_SEARCH(M_fldnmhash2[hash_key],ret,&tmp,UBF_field_def_nm_cmp);
0281 
0282 #ifdef EXTRA_FT_DEBUG
0283     printf("field [%s] key [%d] result [0%x] - [0%x]\n", key, hash_key, ret, M_bfldidhash2[hash_key]);
0284 #endif
0285     return ret;
0286 }
0287 
0288 /**
0289  * Initialize UBF buffer
0290  *
0291  * Probably we need to build two hashes, one for BFLDID as key
0292  * And second hash we use field name as key
0293  *
0294  */
0295 exprivate int _ubf_load_def_table(void)
0296 {
0297     char *flddir=NULL;
0298     char *flds=NULL;
0299     char *p, *pd;
0300     char *p_flds, *p_flddir;
0301     FILE *fp;
0302     char tmp_flds[FILENAME_MAX+1];
0303     char tmp_flddir[FILENAME_MAX+1];
0304     char tmp[FILENAME_MAX+1];
0305     int exist_fld;
0306 
0307     int ret=EXSUCCEED;
0308 
0309     flddir = getenv(CONF_FLDTBLDIR);
0310     if (NULL==flddir)
0311     {
0312         ndrx_Bset_error_msg(BFTOPEN, "Field table directory not set - "
0313                                  "check FLDTBLDIR env var");
0314         ret=EXFAIL;
0315         goto out;
0316     }
0317     UBF_LOG(log_debug, 
0318             "Load field dir [%s] (multiple directories supported)", flddir);
0319 
0320     flds = getenv(CONF_FIELDTBLS);
0321     if (NULL==flds)
0322     {
0323         ndrx_Bset_error_msg(BFTOPEN, "Field table list not set - "
0324                  "check FIELDTBLS env var");
0325         ret=EXFAIL;
0326         goto out;
0327     }
0328 
0329     UBF_LOG(log_debug, "About to load fields list [%s]", flds);
0330 
0331     _ubf_loader_init();
0332 
0333     NDRX_STRCPY_SAFE(tmp_flds, flds);
0334     p=strtok_r(tmp_flds, ",", &p_flds);
0335     while (NULL!=p)
0336     {
0337         exist_fld=EXFALSE;
0338         NDRX_STRCPY_SAFE(tmp_flddir, flddir);
0339         pd=strtok_r(tmp_flddir, ":", &p_flddir);
0340         while ( NULL!=pd && EXFALSE==exist_fld)
0341         {
0342             snprintf(tmp, sizeof(tmp), "%s/%s", pd, p);
0343             UBF_LOG(log_debug, "Open field table file [%s]", tmp);
0344             
0345             /* Open field table file */
0346             if (NULL==(fp=NDRX_FOPEN(tmp, "r")))
0347             {
0348                 UBF_LOG(log_debug, "Failed to open %s with error: [%s]", 
0349                         tmp, strerror(errno));
0350             }
0351             else
0352             {
0353                 ret=ndrx_ubf_load_def_file(fp, NULL, NULL, NULL, tmp, EXFALSE);
0354                 exist_fld=EXTRUE;
0355                 NDRX_FCLOSE(fp);
0356             }
0357             pd=strtok_r(NULL, ":", &p_flddir);
0358         }
0359 
0360         if ( EXFALSE==exist_fld )
0361         {
0362             /*
0363              * Support #738
0364             ndrx_Bset_error_fmt(BFTOPEN, "Failed to open %s in [%s]", p, flddir);
0365             ret=EXFAIL;
0366             goto out;
0367              */
0368             userlog("Field table [%s] not found in [%s]", p, flddir);
0369         }
0370         /* Close file */
0371         p=strtok_r(NULL, ",", &p_flds);
0372     }
0373     
0374     /* Load FIeld database... if have one! */
0375 
0376     M_field_def_loaded = EXTRUE;
0377 
0378 out:
0379 
0380     return ret;
0381 }
0382 
0383 /**
0384  * Initialized loader.
0385  * @return
0386  */
0387 expublic int _ubf_loader_init(void)
0388 {
0389     return init_hash_area(); /* << V2 */
0390 }
0391 
0392 /**
0393  * Load file defintion
0394  * @param fp
0395  * @return
0396  */
0397 expublic int ndrx_ubf_load_def_file(FILE *fp, 
0398                 int (*put_text_line) (char *text), /* callback for putting text line */
0399                 int (*put_def_line) (UBF_field_def_t *def),  /* callback for writting defintion */
0400                 int (*put_got_base_line) (char *base), /* callback for base line */
0401                 char *fname,
0402                 int check_dup)
0403 {
0404     int ret=EXSUCCEED;
0405     int base=0;
0406     char tmp[FILENAME_MAX+1];
0407     char fldname[UBFFLDMAX+1];
0408     int line=0;
0409     
0410     /* Load into hash */
0411     while (EXSUCCEED==ret && NULL!=fgets(tmp, 1024, fp))
0412     {
0413         line++;
0414         
0415         UBF_LOG(log_dump, "Loading debug line [%s]", tmp);
0416         /* Parse out the line & load into hash */
0417         switch (tmp[0])
0418         {
0419             case '$':
0420                 /* Callback for putting text line line */
0421                 if (NULL!=put_text_line)
0422                     ret=put_text_line(tmp+1);
0423 
0424             case '#':
0425             case '\n':
0426                 /* Do nothing */
0427                 break;
0428             case '*':
0429                 /* Load base */
0430                 sscanf(tmp, "%s%d", fldname, &base);
0431                 if (0!=strcmp("*base", fldname))
0432                 {
0433                     base=0;
0434                 }
0435                 
0436                 /* callback for baseline! */
0437                 if (NULL!=put_got_base_line)
0438                     ret=put_got_base_line(tmp);
0439 
0440                 break;
0441             default:
0442                 ret=_ubf_load_fld_def(base, tmp, put_def_line, check_dup, 
0443                                         fname, line);
0444             break;
0445         }
0446     }
0447     return ret;
0448 }
0449 
0450 /**
0451  * Parse field info table & load into hashes.
0452  */
0453 exprivate int _ubf_load_fld_def(int base, 
0454                               char *fldinfo,
0455                               int (*put_def_line) (UBF_field_def_t *def),
0456                               int check_dup,
0457                               char *fname,
0458                               int line)
0459 {
0460     int ret=EXSUCCEED;
0461     char ftype[NDRX_UBF_TYPE_LEN+1]={'\0'};
0462     UBF_field_def_t *fld, *fld2;
0463     UBF_field_def_t *reserved;
0464     dtype_str_t *p = G_dtype_str_map;
0465     _UBF_INT dtype;
0466     BFLDID number;
0467 
0468     fld = NDRX_CALLOC(1, sizeof(UBF_field_def_t));
0469     fld2 = NDRX_CALLOC(1, sizeof(UBF_field_def_t));
0470 
0471     if (NULL==fld || NULL==fld2)
0472     {
0473         ndrx_Bset_error_msg(BMALLOC, "Failed to allocate field def space!");
0474         ret=EXFAIL;
0475         goto out;
0476     }
0477 
0478     sscanf(fldinfo, "%s%d%s", fld->fldname, &(fld->bfldid), ftype);
0479     fld->bfldid+=base;
0480     /* Map type */
0481     while(EXEOS!=p->fldname[0])
0482     {
0483         if (0==strcmp(p->fldname, ftype) || (p->altname && 0==strcmp(p->altname, ftype)))
0484         {
0485             fld->fldtype = p->fld_type;
0486             dtype = p->fld_type;
0487             break;
0488         }
0489         p++;
0490     }
0491     dtype<<=EFFECTIVE_BITS;
0492 
0493     /* Add leading type bits... */
0494     number = fld->bfldid; /* keep the number value */
0495     fld->bfldid |= dtype;
0496 
0497     UBF_LOG(log_dump, "Adding [%s] - id [%d] - [%s]",
0498                             fld->fldname, fld->bfldid, fldinfo);
0499 
0500     if (EXEOS==p->fldname[0])
0501     {
0502         ndrx_Bset_error_fmt(BFTSYNTAX, "Failed to find data type for [%s] in %s:%d!",
0503                                     ftype, fname, line);
0504         ret=EXFAIL;
0505     }
0506     else
0507     {
0508         /* check dup before adding! */
0509         if (check_dup)
0510         {
0511             if (NULL!=(reserved=ndrx_fldnmhash_get(fld->fldname)))
0512             {
0513                 /* ERROR! ID Already defined! */
0514                 ndrx_Bset_error_fmt(BFTSYNTAX, "Duplicate name [%s] already taken by "
0515                                 "[%s]:%d %s:%d!",
0516                                 fld->fldname, reserved->fldname, number,
0517                                 fname, line);
0518                 ret=EXFAIL;
0519             }
0520 
0521             if (EXSUCCEED==ret && NULL!=(reserved=_bfldidhash_get(fld->bfldid)))
0522             {
0523                 /* ERROR! Name already taken */
0524                 ndrx_Bset_error_fmt(BFTSYNTAX, "Duplicate ID [%s]:%d already taken by [%s]:%d "
0525                                     "%s:%d!",
0526                                  fld->fldname, number, reserved->fldname, number,
0527                                  fname, line);
0528                 ret=EXFAIL;
0529             }
0530         }
0531 
0532         if (EXSUCCEED==ret)
0533         {
0534             _bfldidhash_add(fld);
0535             *fld2 = *fld;
0536             _fldnmexhash_add(fld2);
0537         }
0538     }
0539 
0540     /*
0541      * Call callback for putting data line.
0542      */
0543     if (EXSUCCEED==ret && NULL!=put_def_line)
0544     {
0545         ret=put_def_line(fld);
0546     }
0547     
0548 out:
0549     if (EXSUCCEED!=ret)
0550     {
0551         if (NULL!=fld)
0552         {
0553             NDRX_FREE(fld);
0554         }
0555 
0556         if (NULL!=fld2)
0557         {
0558             NDRX_FREE(fld2);
0559         }
0560 
0561     }
0562     return ret;
0563 }
0564 
0565 /**
0566  * Make key out of string. Gen
0567  */
0568 static unsigned int str_hash_from_key_fn( void *k )
0569 {
0570     unsigned int hash = 5381;
0571     int c;
0572     char *str = (char *)k;
0573 
0574     while ((c = (int)*str++))
0575         hash = ((hash << 5) + hash) + c; /* hash * 33 + c */
0576 
0577     return hash;
0578 }
0579 
0580 /**
0581  * Check that string keys are qual
0582  */
0583 static int str_keys_equal_fn( void *key1, void *key2 )
0584 {
0585     return (0==strcmp(key1, key2)?1:0);
0586 }
0587 
0588 /**
0589  * Checks and reads type table (.fd files)
0590  * @return SUCCEED/FAIL
0591  */
0592 expublic int ndrx_prepare_type_tables(void)
0593 {
0594     /* If not loaded. */
0595     if (!M_field_def_loaded)
0596     {
0597         /* Lock */
0598         MUTEX_LOCK;
0599         {
0600             int ret=EXSUCCEED;
0601 
0602             /* if still not loaded by concurrent thread, then load */
0603             if (!M_field_def_loaded)
0604             {
0605                 ret=_ubf_load_def_table();
0606             }
0607             /* Feature #295 */
0608             if (EXSUCCEED==ret)
0609             {
0610                 /* try to load UBF DB */
0611                 if (EXFAIL==ndrx_ubfdb_Bflddbload())
0612                 {
0613                     ret=EXFAIL;
0614                 }
0615             }
0616 
0617             MUTEX_UNLOCK;
0618             return ret;
0619         }
0620     }
0621     else
0622     {
0623         return EXSUCCEED;
0624     }
0625 }
0626 
0627 /**
0628  * Internal version of Bfname. Does not set error.
0629  */
0630 expublic char * ndrx_Bfname_int (BFLDID bfldid)
0631 {
0632     UBF_field_def_t *p_fld;
0633     UBF_TLS_ENTRY;
0634 
0635     if (EXSUCCEED!=ndrx_prepare_type_tables())
0636     {
0637         if (BFTOPEN==Berror || BFTSYNTAX==Berror)
0638         {
0639             ndrx_Bunset_error();
0640         }
0641 
0642         snprintf(G_ubf_tls->bfname_buf, sizeof(G_ubf_tls->bfname_buf), 
0643                 "((BFLDID32)%d)", bfldid);
0644 
0645         return G_ubf_tls->bfname_buf;
0646     }
0647 
0648     /* Now try to find the data! */
0649     p_fld = _bfldidhash_get(bfldid);
0650     
0651     if (NULL==p_fld && NULL!=ndrx_G_ubf_db)
0652     {
0653         char *p;
0654         p = ndrx_ubfdb_Bflddbname(bfldid);
0655         if (NULL==p)
0656         {
0657             if (BNOTFLD==Berror)
0658             {
0659                 ndrx_Bunset_error();
0660             }
0661         }
0662         else
0663         {
0664             return p; /* return ptr to field */
0665         }
0666     }
0667     
0668     if (NULL==p_fld)
0669     {
0670         snprintf(G_ubf_tls->bfname_buf, sizeof(G_ubf_tls->bfname_buf),
0671                 "((BFLDID32)%d)", bfldid);
0672         return G_ubf_tls->bfname_buf;
0673     }
0674     else
0675     {
0676         return p_fld->fldname;
0677     }
0678 }
0679 
0680 /**
0681  * Parse bfldid out from ((BFLDID32)%d) synatx
0682  * @param fldnm
0683  * @return BADFLD in failure/BFLDID
0684  */
0685 exprivate BFLDID get_from_bfldidstr(char *fldnm)
0686 {
0687     BFLDID ret;
0688     sscanf(fldnm, "((BFLDID32)%d)", &ret);
0689     UBF_LOG(log_warn, "Parsed ((BFLDID32)%%d) from [%s] got id %d",
0690                                     fldnm, ret);
0691     return ret;
0692 }
0693 
0694 /*
0695  * Return BFLDID from name! (internal version, parses ((BFLDID)%d)
0696  * Does not reports errors.
0697  */
0698 expublic BFLDID ndrx_Bfldid_int (char *fldnm)
0699 {
0700     UBF_field_def_t *p_fld=NULL;
0701     BFLDID bfldid;
0702 
0703     if (EXSUCCEED!=ndrx_prepare_type_tables())
0704     {
0705         /* extending support for BFLDID syntax for read. */
0706         if (0==strncmp(fldnm, "((BFLDID32)", 11))
0707         {
0708             bfldid = get_from_bfldidstr(fldnm);
0709             return bfldid;
0710         }
0711         else
0712         {
0713             return BBADFLDID;
0714         }
0715     }
0716     
0717     /* Now we can try to do lookup */
0718     p_fld = ndrx_fldnmhash_get(fldnm);
0719     
0720     if (NULL==p_fld && NULL!=ndrx_G_ubf_db)
0721     {
0722         if (BBADFLDID==(bfldid = ndrx_ubfdb_Bflddbid(fldnm)))
0723         {
0724             if (BNOTFLD==Berror)
0725             {
0726                 ndrx_Bunset_error();
0727             }
0728         }
0729         else
0730         {
0731             return bfldid;
0732         }
0733     }
0734 
0735     if (NULL!=p_fld)
0736     {
0737         return p_fld->bfldid;
0738     }
0739     else if (0==strncmp(fldnm, "((BFLDID32)", 11))
0740     {
0741         bfldid = get_from_bfldidstr(fldnm);
0742         return bfldid;
0743     }
0744     else
0745     {
0746         return BBADFLDID;
0747     }
0748 }
0749 /* vim: set ts=4 sw=4 et smartindent: */