FICO
FICO Xpress Optimization Examples Repository
FICO Optimization Community FICO Xpress Optimization Home
Back to examples browserPrevious exampleNext example

Module implementing driver 'toC' to save the compilation result to a C file

Description
A module implementing the driver 'toC' to save the result of a Mosel model compilation to a C file: the execution of the generated program performs the model processing.

Further explanation of this example: Whitepaper 'Generalized file handling in Mosel', Section 8.2 Example: code generation


Source Files





export.c

/******************************************
  Mosel NI Examples
  =================
    
  File export.c
  `````````````
  Example module defining an IO driver
  that generates a C-file embedding a
  model

  (c) 2008 Fair Isaac Corporation
      author: Y. Colombani, 2003
*******************************************/

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "xprm_ni.h"

static char prg_part1[]=
"#include <stdio.h>\n"
"#include \"xprm_rt.h\"\n\n"

"static unsigned int bimfile[]={";

static char prg_part2[]=
"0};\n\n"

"int main(int argc,char *argv[])\n"
"{\n"
" char modname[40];\n"
" XPRMmodel mod;\n"
" int rts;\n\n"

" rts=XPRMinit();\n"
" if((rts!=0)&&(rts!=32))\n"
" {\n"
"  char msg[512];\n\n"
  
"  XPRMgetlicerrmsg(msg,512);\n"
"  fprintf(stderr,\"%s\",msg);\n"
"  return 1;\n"
" }\n\n"

#ifdef _WIN32
" sprintf(modname,\"mem:%#Ix/%u\",\n"
"        (size_t)bimfile,";
#else
" sprintf(modname,\"mem:%#lx/%u\",\n"
"        (unsigned long)bimfile,";
#endif

static char prg_part3[]=
                                ");\n"
" if((mod=XPRMloadmod(modname,NULL))==NULL)\n"
"  return 2;\n"
" if(XPRMrunmod(mod,&rts,NULL))\n"
"  return 3;\n"
" else\n"
"  return rts;\n"
"}\n";

typedef struct
        {
         unsigned int total;      /* Total number of bytes written so far */
         union
         {
          char c[4];
          unsigned int i;
         } map;                   /* Mapping between 4 chars and an integer */
         int nb_remain;           /* Number of bytes not yet written */
         int nb_printed;          /* Number of numbers written on the line */
        } s_tocdata;

/*******************************************************/
/* toC driver: to generate a C program from a bim file */
/* Example: "export.toC:mymodel.c"                     */
/* Using it from Mosel console:                        */
/* compile mymodel '' export.toC:mymodel.c             */
/*******************************************************/
                                        /* Functions of 'toC' driver */
static void *toc_open(XPRMcontext ctx,int *mode,const char *fname);
static int toc_close(XPRMcontext ctx,s_tocdata *td,int mode);
static long toc_write(XPRMcontext ctx,s_tocdata *td,char *buffer,
                                                        unsigned long size);
static XPRMiofcttab iodrv_toc[]=
        {
         {XPRM_IOCTRL_OPEN,(void *)toc_open},
         {XPRM_IOCTRL_CLOSE,(void *)toc_close},
         {XPRM_IOCTRL_WRITE,(void *)toc_write},
         {XPRM_IOCTRL_INFO,"extended_filename"},
         {0,NULL}
        };

                                        /* Drivers of export module: toC */
static XPRMiodrvtab iodrv_export[]=
        {
         {"toC",iodrv_toc},
         {NULL,NULL}
        };

                                        /* Table of services: only IO drivers */
static XPRMdsoserv tabserv[]=
        {
         {XPRM_SRV_IODRVS,iodrv_export}
        };

                                        /* DSO interface: only services */
static XPRMdsointer dsointer= 
        { 
         0,NULL,
         0,NULL,
         0,NULL,
         sizeof(tabserv)/sizeof(mm_dsoserv),tabserv
        };

static XPRMnifct mm;             /* For storing Mosel NI function table */

/************************************************/
/* Initialize the library just after loading it */
/************************************************/
DSO_INIT export_init(XPRMnifct nifct, int *interver,int *libver, XPRMdsointer **interf)
{
 mm=nifct;                      /* Save the table of Mosel NI functions */
 *interver=XPRM_NIVERS;         /* The interface version we are using */
 *libver=XPRM_MKVER(0,0,1);     /* The version of the module: 0.0.1 */
 *interf=&dsointer;             /* Our interface */
 return 0;
}

/*****************************/
/* Open the C-file to create */
/*****************************/
static void *toc_open(XPRMcontext ctx,int *mode,const char *fname)
{
 s_tocdata *td;

                                /* 1st: open actual file */
 if(mm->fopen(ctx,*mode,fname)<0)
 {
  *mode|=XPRM_F_SILENT;                /* Error message already displayed */
                                       /* switch so silent mode */
  return NULL;
 }
 else
 {
  td=(s_tocdata *)malloc(sizeof(s_tocdata));
  td->total=0;
  td->nb_remain=0;
  td->nb_printed=0;
  mm->printf(ctx,"%s\n",prg_part1);    /* Display the beginning of program */
  return td;
 }
}

/********************/
/* Close the C-file */
/********************/
static int toc_close(XPRMcontext ctx,s_tocdata *td,int mode)
{
 if(td->nb_remain>0)                    /* Send bytes to be written */
 {
  td->total+=td->nb_remain;
  for(;td->nb_remain<4;td->nb_remain++)
   td->map.c[td->nb_remain]=0;
  mm->printf(ctx,"%#x,",td->map.i);
 }                                      /* and complete program */
 mm->printf(ctx,"%s%u%s",prg_part2,td->total,prg_part3);
 return mm->fclose(ctx,mode);
}

/**************************/
/* Write a list of values */
/**************************/
static long toc_write(XPRMcontext ctx,s_tocdata *td,char *buffer,
                                                        unsigned long size)
{
 int i;

 if(size+td->nb_remain<4)              /* Not enough for an integer... */
 {
  for(i=0;i<size;i++)
    td->map.c[td->nb_remain+i]=buffer[i];
  td->nb_remain+=size;                 /* store them for next call */
 }
 else
 {
  if(td->nb_remain>0)                  /* Bytes from previous call first... */
  {
   for(i=0;i<4-td->nb_remain;i++)
    td->map.c[td->nb_remain+i]=buffer[i];
   mm->printf(ctx,"%#x,",td->map.i);
   td->total+=4;
   td->nb_printed++;
   size-=4-td->nb_remain;
   buffer-=4-td->nb_remain;
  }
  while(size>=4)                       /* then the buffer we receive */
  {
   td->map.c[0]=buffer[0];
   td->map.c[1]=buffer[1];
   td->map.c[2]=buffer[2];
   td->map.c[3]=buffer[3];
   mm->printf(ctx,"%#x,",td->map.i);
   size-=4;
   buffer+=4;
   td->total+=4;
   if(++td->nb_printed>=6)
   {
    td->nb_printed=0;
    mm->printf(ctx,"\n");
   }
  }
  td->nb_remain=size;                  /* Keep track of remaining bytes */
  memcpy(td->map.c,buffer,size);
 }
 return 1;
}


Back to examples browserPrevious exampleNext example