Back to home page

Enduro/X

 
 

    


0001 /**
0002  * @brief Part of UBF library
0003  *   Utility for generating field header files.
0004  *   Also the usage of default `fld.tbl' is not supported, as seems to be un-needed
0005  *   feature.
0006  *
0007  * @file mkfldhdr.c
0008  */
0009 /* -----------------------------------------------------------------------------
0010  * Enduro/X Middleware Platform for Distributed Transaction Processing
0011  * Copyright (C) 2009-2016, ATR Baltic, Ltd. All Rights Reserved.
0012  * Copyright (C) 2017-2023, Mavimax, Ltd. All Rights Reserved.
0013  * This software is released under one of the following licenses:
0014  * AGPL (with Java and Go exceptions) or Mavimax's license for commercial use.
0015  * See LICENSE file for full text.
0016  * -----------------------------------------------------------------------------
0017  * AGPL license:
0018  *
0019  * This program is free software; you can redistribute it and/or modify it under
0020  * the terms of the GNU Affero General Public License, version 3 as published
0021  * by the Free Software Foundation;
0022  *
0023  * This program is distributed in the hope that it will be useful, but WITHOUT ANY
0024  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
0025  * PARTICULAR PURPOSE. See the GNU Affero General Public License, version 3
0026  * for more details.
0027  *
0028  * You should have received a copy of the GNU Affero General Public License along 
0029  * with this program; if not, write to the Free Software Foundation, Inc.,
0030  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
0031  *
0032  * -----------------------------------------------------------------------------
0033  * A commercial use license is available from Mavimax, Ltd
0034  * contact@mavimax.com
0035  * -----------------------------------------------------------------------------
0036  */
0037 
0038 /*---------------------------Includes-----------------------------------*/
0039 
0040 #include <unistd.h>
0041 #include <stdio.h>
0042 #include <errno.h>
0043 #include <stdlib.h>
0044 #include <atmi.h>
0045 #include <unistd.h>    /* for getopt */
0046 
0047 #include <ubf.h>
0048 #include <ferror.h>
0049 #include <fieldtable.h>
0050 #include <fdatatype.h>
0051 
0052 #include <ndrstandard.h>
0053 #include <ndebug.h>
0054 #include "mkfldhdr.h"
0055 /*---------------------------Externs------------------------------------*/
0056 /*---------------------------Macros-------------------------------------*/
0057 /*---------------------------Enums--------------------------------------*/
0058 /*---------------------------Typedefs-----------------------------------*/
0059 /*---------------------------Globals------------------------------------*/
0060 expublic int G_langmode = HDR_C_LANG; /* Default mode C */
0061 expublic char G_privdata[FILENAME_MAX+1] = {EXEOS}; /* Private data for lang*/
0062 expublic char G_active_file[FILENAME_MAX+1] = {EXEOS}; /* file in progress  */
0063 expublic char *G_output_dir=".";
0064 
0065 expublic renderer_descr_t *M_renderer = NULL;
0066 /*---------------------------Statics------------------------------------*/
0067 exprivate char **M_argv;
0068 exprivate int M_argc;
0069 expublic FILE *G_outf=NULL;
0070 
0071 /**
0072  * Mode functions
0073  */
0074 expublic renderer_descr_t M_renderer_tab[] =
0075 {
0076     {HDR_C_LANG, c_get_fullname, c_put_text_line, c_put_def_line, 
0077                  c_put_got_base_line, c_file_open, c_file_close},
0078     {HDR_GO_LANG, go_get_fullname, go_put_text_line, go_put_def_line, 
0079                  go_put_got_base_line, go_file_open, go_file_close},
0080     {HDR_JAVA_LANG, java_get_fullname, java_put_text_line, java_put_def_line, 
0081                  java_put_got_base_line, java_file_open, java_file_close},
0082     {HDR_PYTHON_LANG, python_get_fullname, python_put_text_line, python_put_def_line, 
0083                  python_put_got_base_line, python_file_open, python_file_close},
0084     {EXFAIL}
0085 };
0086 
0087 /*---------------------------Prototypes---------------------------------*/
0088 
0089 /*
0090  * Function for retrieving next file name
0091  */
0092 exprivate char *(*M_get_next) (int *ret);
0093 exprivate int generate_files(void);
0094 
0095 
0096 /**
0097  * Return next file name from arg
0098  * @param ret
0099  * @return
0100  */
0101 exprivate char *get_next_from_arg (int *ret)
0102 {
0103 
0104     *ret=EXSUCCEED;
0105     if (optind < M_argc)
0106     {
0107         char *fname = M_argv[optind];
0108         optind++;
0109         NDRX_LOG(log_debug, "Got filename: [%s]", fname);
0110 
0111         return fname;
0112     }
0113     
0114     return NULL;
0115 }
0116 
0117 /**
0118  * Read table list from environment variable.
0119  * @param ret
0120  * @return
0121  */
0122 exprivate char *get_next_from_env (int *ret)
0123 {
0124     static int first = 1;
0125     static char *flddir=NULL;
0126     static char *flds=NULL;
0127     static char *p_flds, *p_flddir;
0128     static char tmp_flds[FILENAME_MAX+1];
0129     static char tmp_flddir[FILENAME_MAX+1];
0130     static char tmp[FILENAME_MAX+1];
0131     char *ret_ptr=NULL;
0132     char *ret_dir=NULL;
0133     FILE *fp;
0134     
0135     NDRX_LOG(log_debug, "%s enter", __func__);
0136     if (first)
0137     {
0138         first=0;
0139 
0140         flddir = (char *)getenv(CONF_FLDTBLDIR);
0141         if (NULL==flddir)
0142         {
0143             ndrx_Bset_error_msg(BFTOPEN, "Field table directory not set - "
0144                          "check FLDTBLDIR env var");
0145             *ret=EXFAIL;
0146             return NULL;
0147         }
0148         NDRX_LOG(log_debug, 
0149                 "Load field dir [%s] (multiple directories supported)", 
0150                  flddir);
0151 
0152         flds = (char *)getenv(CONF_FIELDTBLS);
0153         if (NULL==flds)
0154         {
0155             ndrx_Bset_error_msg(BFTOPEN, "Field table list not set - "
0156                  "check FIELDTBLS env var");
0157             *ret=EXFAIL;
0158             return NULL;
0159         }
0160 
0161         NDRX_LOG(log_debug, "About to load fields list [%s]", flds);
0162 
0163         NDRX_STRCPY_SAFE(tmp_flds, flds);
0164         ret_ptr=strtok_r(tmp_flds, ",", &p_flds);
0165 
0166     }
0167     else
0168     {
0169         ret_ptr=strtok_r(NULL, ",", &p_flds);
0170     }
0171     
0172 
0173     NDRX_STRCPY_SAFE(tmp_flddir, flddir);
0174     ret_dir=strtok_r(tmp_flddir, ":", &p_flddir);
0175     while (NULL!=ret_ptr && NULL != ret_dir)
0176     {
0177         snprintf(tmp, sizeof(tmp), "%s/%s", ret_dir, ret_ptr);
0178         /* maybe use stat here? */
0179     if (ndrx_file_exists(tmp))
0180         {
0181             break;
0182         }
0183 #if 0
0184         if (NULL!=(fp=NDRX_FOPEN(tmp, "r")))
0185         {
0186             NDRX_FCLOSE(fp);
0187             break;
0188         }
0189 #endif
0190         ret_dir=strtok_r(NULL, ":", &p_flddir);
0191     }
0192 
0193     if (NULL!=ret_ptr && NULL!=ret_dir)
0194     {
0195         snprintf(tmp, sizeof(tmp), "%s/%s", ret_dir, ret_ptr);
0196         ret_ptr=tmp;
0197     }
0198 
0199     return ret_ptr;
0200 }
0201 
0202 /**
0203  * Header builder main 
0204  * @param argc
0205  * @param argv
0206  * @return
0207  */
0208 int main(int argc, char **argv)
0209 {
0210     int ret=EXSUCCEED;
0211     int c;
0212     int dbglev;
0213     extern char *optarg;
0214     
0215     M_argv = argv;
0216     M_argc = argc;
0217     
0218     M_renderer = &M_renderer_tab[HDR_C_LANG]; /* default renderer */
0219 
0220     /* Parse command line */
0221     while ((c = getopt(argc, argv, "h?D:d:m:p:")) != -1)
0222     {
0223         switch(c)
0224         {
0225             case 'D':
0226                 NDRX_LOG(log_debug, "%c = %s", c, optarg);
0227                 dbglev = atoi(optarg);
0228                 break;
0229             case 'd':
0230                 G_output_dir = optarg;
0231                 NDRX_LOG(log_debug, "%c = %s", c, G_output_dir);
0232                 break;
0233             case ':':
0234                 NDRX_LOG(log_error,"-%c without filename\n", optopt);
0235                 ret=EXFAIL;
0236                 break;
0237             case 'h': case '?':
0238                 printf("usage: %s [-D dbglev, legacy] [-d target directory] [-m lang_mode] [-p priv_data] [field table ...]\n\n",
0239                         argv[0]);
0240                 printf("OPTIONS\n");
0241                 printf("\tlang_mode:\n");
0242                 printf("\t\t0 - C (default)\n");
0243                 printf("\t\t1 - Go\n");
0244                 printf("\t\t2 - Java\n");
0245                 printf("\t\t3 - Python\n");
0246                 printf("\tpriv_data:\n");
0247                 printf("\t\tFor Go - package name\n");
0248                 printf("\t\tFor Java - package name\n");
0249                 
0250                 return EXFAIL;
0251                 break;
0252             /* m - for mode, p - for private mode data (e.g. package name) */
0253             case 'm':
0254                 G_langmode = atoi(optarg);
0255                 
0256                 if (HDR_MIN_LANG > G_langmode || HDR_MAX_LANG < G_langmode)
0257                 {
0258                     NDRX_LOG(log_debug, "Invalid language mode %d", G_langmode);
0259                     return EXFAIL;
0260                 }
0261                 M_renderer = &M_renderer_tab[G_langmode];
0262                 break;
0263             case 'p':
0264                 NDRX_STRCPY_SAFE(G_privdata, optarg);
0265                 break;
0266         }
0267     }
0268     
0269     if (EXSUCCEED==ret)
0270     {
0271         NDRX_LOG(log_debug, "Output directory is [%s]", G_output_dir);
0272         NDRX_LOG(log_debug, "Language mode [%d]", G_langmode);
0273         NDRX_LOG(log_debug, "Private data [%s]", G_privdata);
0274     }
0275     
0276     /* list other options */
0277     if (optind < argc)
0278     {
0279         M_get_next = get_next_from_arg;
0280         NDRX_LOG(log_debug, "Reading files from command line %p", M_get_next);
0281     }
0282     else
0283     {
0284         /* Use environment variables */
0285         M_get_next = get_next_from_env;
0286         NDRX_LOG(log_debug, "Use environment variables %p", M_get_next);
0287     }
0288 
0289     ret=generate_files();
0290 
0291     if (EXSUCCEED!=ret)
0292     {
0293         B_error("mkfldhdr");
0294     }
0295 
0296 
0297     NDRX_LOG(log_debug, "Finished with : %s",
0298             ret==EXSUCCEED?"SUCCESS":"FAILURE");
0299 
0300     return ret;
0301 }
0302 
0303 /**
0304  * Extract file name out of partial pathed file
0305  * 
0306  * @param
0307  * @return
0308  */
0309 char *get_file_name(char *fname)
0310 {
0311     static char fname_conv[FILENAME_MAX+1];
0312     char *p;
0313     
0314     p = strrchr(fname, '/');
0315     
0316     if (NULL==p)
0317     {
0318         /* No back slash found in  */
0319         return fname;
0320     }
0321     else
0322     {
0323         NDRX_STRCPY_SAFE(fname_conv, p+1);
0324         return fname_conv;
0325     }
0326 }
0327 
0328 /**
0329  * Do the hard work - generate header files!
0330  * @return SUCCEED/FAIL
0331  */
0332 exprivate int generate_files(void)
0333 {
0334     int ret=EXSUCCEED;
0335     char *fname;
0336     FILE *inf=NULL, *outf=NULL;
0337     char out_f_name[FILENAME_MAX+1]={EXEOS};
0338 
0339     _ubf_loader_init();
0340 
0341     NDRX_LOG(log_debug, "enter generate_files() func: %p", M_get_next);
0342 
0343     /*
0344      * Process file by file
0345      */
0346     while (NULL!=(fname=M_get_next(&ret)))
0347     {
0348         out_f_name[0] = EXEOS;
0349 
0350         /* Open field table file */
0351         if (NULL==(inf=NDRX_FOPEN(fname, "r")))
0352         {
0353             ndrx_Bset_error_fmt(BFTOPEN, "Failed to open %s with error: [%s]",
0354                                 fname, strerror(errno));
0355             EXFAIL_OUT(ret);
0356         }
0357 
0358         /* Open output file */
0359         if (EXSUCCEED==ret)
0360         {
0361             NDRX_STRCPY_SAFE(G_active_file, get_file_name(fname));
0362             
0363             M_renderer->get_fullname(out_f_name);
0364             
0365             /* build up path for output file name */
0366             if (NULL==(G_outf=NDRX_FOPEN(out_f_name, "w")))
0367             {
0368                 ndrx_Bset_error_fmt(BFTOPEN, "Failed to open %s with error: [%s]",
0369                                             out_f_name, strerror(errno));
0370                 EXFAIL_OUT(ret);
0371             }
0372             else
0373             {
0374                 ret = M_renderer->file_open(out_f_name);
0375             }
0376         }
0377 
0378         /* This will also do the check for duplicates! */
0379         if (EXSUCCEED!=ndrx_ubf_load_def_file(inf, M_renderer->put_text_line,
0380                                 M_renderer->put_def_line, M_renderer->put_got_base_line,
0381                                 /* do not check duplicates if that's ok to have such */
0382                                 fname, !(ndrx_G_apiflags & NDRX_APIFLAGS_UBFDUPFIDOK) ))
0383         {
0384             EXFAIL_OUT(ret);
0385         }
0386 
0387         /* close opened files. */
0388         if (NULL!=inf)
0389         {
0390             NDRX_FCLOSE(inf);
0391             inf=NULL;
0392         }
0393 
0394         if (NULL!=G_outf)
0395         {
0396             M_renderer->file_close(out_f_name);
0397             NDRX_FCLOSE(G_outf);
0398             G_outf=NULL;
0399         }
0400 
0401         NDRX_LOG(log_debug, "%s processed OK, output: %s",
0402                                             fname, out_f_name);
0403     }
0404 
0405 out:
0406     if (EXSUCCEED!=ret && EXEOS!=out_f_name[0])
0407     {
0408         /* unlink last file */
0409         NDRX_LOG(log_debug, "Unlinking %s",out_f_name);
0410         unlink(out_f_name);
0411     }
0412     
0413     return ret;
0414 }
0415 
0416 
0417 /* vim: set ts=4 sw=4 et smartindent: */