You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
691 lines
23 KiB
691 lines
23 KiB
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <ctype.h>
|
|
#include <errno.h>
|
|
|
|
#include "commonlib.h"
|
|
#include "lp_lib.h"
|
|
#include "lp_report.h"
|
|
#include "ini.h"
|
|
|
|
typedef int (__WINAPI fn_int_get_function)(lprec *lp);
|
|
typedef long (__WINAPI fn_long_get_function)(lprec *lp);
|
|
typedef MYBOOL (__WINAPI fn_MYBOOL_get_function)(lprec *lp);
|
|
typedef REAL (__WINAPI fn_REAL_get_function)(lprec *lp);
|
|
typedef void (__WINAPI fn_int_set_function)(lprec *lp, int value);
|
|
typedef void (__WINAPI fn_long_set_function)(lprec *lp, long value);
|
|
typedef void (__WINAPI fn_MYBOOL_set_function)(lprec *lp, MYBOOL value);
|
|
typedef void (__WINAPI fn_REAL_set_function)(lprec *lp, REAL value);
|
|
|
|
#define intfunction 1
|
|
#define longfunction 2
|
|
#define MYBOOLfunction 3
|
|
#define REALfunction 4
|
|
|
|
#define setvalues(values, basemask) values, sizeof(values) / sizeof(*values), basemask
|
|
#define setNULLvalues NULL, 0, 0
|
|
#define setvalue(value) value, #value
|
|
#define setintfunction(get_function, set_function) { get_function }, { set_function }, intfunction
|
|
#define setlongfunction(get_function, set_function) { (fn_int_get_function *) get_function }, {(fn_int_set_function *) set_function }, longfunction
|
|
#define setMYBOOLfunction(get_function, set_function) { (fn_int_get_function *) get_function }, { (fn_int_set_function *) set_function }, MYBOOLfunction
|
|
#define setREALfunction(get_function, set_function) {(fn_int_get_function *) get_function }, { (fn_int_set_function *) set_function }, REALfunction
|
|
|
|
#define WRITE_COMMENTED 0
|
|
#define WRITE_ACTIVE 1
|
|
|
|
struct _values {
|
|
int value;
|
|
char *svalue;
|
|
};
|
|
|
|
struct _functions {
|
|
char *par; /* name of parameter in ini file */
|
|
union {
|
|
fn_int_get_function *int_get_function; /* set via setintfunction */
|
|
fn_long_get_function *long_get_function; /* set via setlongfunction */
|
|
fn_MYBOOL_get_function *MYBOOL_get_function; /* set via setMYBOOLfunction */
|
|
fn_REAL_get_function *REAL_get_function; /* set via setREALfunction */
|
|
} get_function;
|
|
union {
|
|
fn_int_set_function *int_set_function; /* set via setintfunction */
|
|
fn_long_set_function *long_set_function; /* set via setlongfunction */
|
|
fn_MYBOOL_set_function *MYBOOL_set_function; /* set via setMYBOOLfunction */
|
|
fn_REAL_set_function *REAL_set_function; /* set via setREALfunction */
|
|
} set_function;
|
|
int type; /* set via set*function */
|
|
struct _values *values; /* set via setvalues to a structure of _values */
|
|
int elements; /* or via setNULLvalues if the value is shown as is */
|
|
unsigned int basemask;
|
|
int mask; /* WRITE_ACTIVE or WRITE_COMMENTED */
|
|
};
|
|
|
|
static struct _values anti_degen[] =
|
|
{
|
|
{ setvalue(ANTIDEGEN_NONE) },
|
|
{ setvalue(ANTIDEGEN_FIXEDVARS) },
|
|
{ setvalue(ANTIDEGEN_COLUMNCHECK) },
|
|
{ setvalue(ANTIDEGEN_STALLING) },
|
|
{ setvalue(ANTIDEGEN_NUMFAILURE) },
|
|
{ setvalue(ANTIDEGEN_LOSTFEAS) },
|
|
{ setvalue(ANTIDEGEN_INFEASIBLE) },
|
|
{ setvalue(ANTIDEGEN_DYNAMIC) },
|
|
{ setvalue(ANTIDEGEN_DURINGBB) },
|
|
{ setvalue(ANTIDEGEN_RHSPERTURB) },
|
|
{ setvalue(ANTIDEGEN_BOUNDFLIP) },
|
|
};
|
|
|
|
static struct _values basiscrash[] =
|
|
{
|
|
{ setvalue(CRASH_NONE) },
|
|
/* { setvalue(CRASH_NONBASICBOUNDS) }, */ /* not yet implemented */
|
|
{ setvalue(CRASH_MOSTFEASIBLE) },
|
|
{ setvalue(CRASH_LEASTDEGENERATE) },
|
|
};
|
|
|
|
static struct _values bb_floorfirst[] =
|
|
{
|
|
{ setvalue(BRANCH_CEILING) },
|
|
{ setvalue(BRANCH_FLOOR) },
|
|
{ setvalue(BRANCH_AUTOMATIC) },
|
|
};
|
|
|
|
static struct _values bb_rule[] =
|
|
{
|
|
{ setvalue(NODE_FIRSTSELECT) },
|
|
{ setvalue(NODE_GAPSELECT) },
|
|
{ setvalue(NODE_RANGESELECT) },
|
|
{ setvalue(NODE_FRACTIONSELECT) },
|
|
{ setvalue(NODE_PSEUDOCOSTSELECT) },
|
|
{ setvalue(NODE_PSEUDONONINTSELECT) },
|
|
{ setvalue(NODE_PSEUDORATIOSELECT) },
|
|
{ setvalue(NODE_USERSELECT) },
|
|
{ setvalue(NODE_WEIGHTREVERSEMODE) },
|
|
{ setvalue(NODE_BRANCHREVERSEMODE) },
|
|
{ setvalue(NODE_GREEDYMODE) },
|
|
{ setvalue(NODE_PSEUDOCOSTMODE) },
|
|
{ setvalue(NODE_DEPTHFIRSTMODE) },
|
|
{ setvalue(NODE_RANDOMIZEMODE) },
|
|
{ setvalue(NODE_GUBMODE) },
|
|
{ setvalue(NODE_DYNAMICMODE) },
|
|
{ setvalue(NODE_RESTARTMODE) },
|
|
{ setvalue(NODE_BREADTHFIRSTMODE) },
|
|
{ setvalue(NODE_AUTOORDER) },
|
|
{ setvalue(NODE_RCOSTFIXING) },
|
|
{ setvalue(NODE_STRONGINIT) },
|
|
};
|
|
|
|
static struct _values improve[] =
|
|
{
|
|
{ setvalue(IMPROVE_NONE) },
|
|
{ setvalue(IMPROVE_SOLUTION) },
|
|
{ setvalue(IMPROVE_DUALFEAS) },
|
|
{ setvalue(IMPROVE_THETAGAP) },
|
|
{ setvalue(IMPROVE_BBSIMPLEX) },
|
|
};
|
|
|
|
static REAL __WINAPI get_mip_gap_abs(lprec *lp)
|
|
{
|
|
return(get_mip_gap(lp, TRUE));
|
|
}
|
|
|
|
static REAL __WINAPI get_mip_gap_rel(lprec *lp)
|
|
{
|
|
return(get_mip_gap(lp, FALSE));
|
|
}
|
|
|
|
static void __WINAPI set_mip_gap_abs(lprec *lp, REAL mip_gap)
|
|
{
|
|
set_mip_gap(lp, TRUE, mip_gap);
|
|
}
|
|
|
|
static void __WINAPI set_mip_gap_rel(lprec *lp, REAL mip_gap)
|
|
{
|
|
set_mip_gap(lp, FALSE, mip_gap);
|
|
}
|
|
|
|
static struct _values pivoting[] =
|
|
{
|
|
{ setvalue(PRICER_FIRSTINDEX) },
|
|
{ setvalue(PRICER_DANTZIG) },
|
|
{ setvalue(PRICER_DEVEX) },
|
|
{ setvalue(PRICER_STEEPESTEDGE) },
|
|
{ setvalue(PRICE_PRIMALFALLBACK) },
|
|
{ setvalue(PRICE_MULTIPLE) },
|
|
{ setvalue(PRICE_PARTIAL) },
|
|
{ setvalue(PRICE_ADAPTIVE) },
|
|
{ setvalue(PRICE_RANDOMIZE) },
|
|
{ setvalue(PRICE_AUTOPARTIAL) },
|
|
{ setvalue(PRICE_LOOPLEFT) },
|
|
{ setvalue(PRICE_LOOPALTERNATE) },
|
|
{ setvalue(PRICE_HARRISTWOPASS) },
|
|
{ setvalue(PRICE_TRUENORMINIT) },
|
|
};
|
|
|
|
static struct _values presolving[] =
|
|
{
|
|
{ setvalue(PRESOLVE_NONE) },
|
|
{ setvalue(PRESOLVE_ROWS) },
|
|
{ setvalue(PRESOLVE_COLS) },
|
|
{ setvalue(PRESOLVE_LINDEP) },
|
|
{ setvalue(PRESOLVE_AGGREGATE) },
|
|
{ setvalue(PRESOLVE_SPARSER) },
|
|
{ setvalue(PRESOLVE_SOS) },
|
|
{ setvalue(PRESOLVE_REDUCEMIP) },
|
|
{ setvalue(PRESOLVE_KNAPSACK) },
|
|
{ setvalue(PRESOLVE_ELIMEQ2) },
|
|
{ setvalue(PRESOLVE_IMPLIEDFREE) },
|
|
{ setvalue(PRESOLVE_REDUCEGCD) },
|
|
{ setvalue(PRESOLVE_PROBEFIX) },
|
|
{ setvalue(PRESOLVE_PROBEREDUCE) },
|
|
{ setvalue(PRESOLVE_ROWDOMINATE) },
|
|
{ setvalue(PRESOLVE_COLDOMINATE) },
|
|
{ setvalue(PRESOLVE_MERGEROWS) },
|
|
{ setvalue(PRESOLVE_IMPLIEDSLK) },
|
|
{ setvalue(PRESOLVE_COLFIXDUAL) },
|
|
{ setvalue(PRESOLVE_BOUNDS) },
|
|
{ setvalue(PRESOLVE_DUALS) },
|
|
{ setvalue(PRESOLVE_SENSDUALS) },
|
|
};
|
|
|
|
static char *STRLWR(char *str)
|
|
{
|
|
char *ptr;
|
|
|
|
for(ptr = str; *ptr; ptr++)
|
|
*ptr = (char) tolower((unsigned char) *ptr);
|
|
|
|
return(str);
|
|
}
|
|
|
|
static char *STRUPR(char *str)
|
|
{
|
|
char *ptr;
|
|
|
|
for(ptr = str; *ptr; ptr++)
|
|
*ptr = (char) toupper((unsigned char) *ptr);
|
|
|
|
return(str);
|
|
}
|
|
|
|
static void __WINAPI set_presolve1(lprec *lp, int do_presolve)
|
|
{
|
|
set_presolve(lp, do_presolve, get_presolveloops(lp));
|
|
}
|
|
|
|
static void __WINAPI set_presolve2(lprec *lp, int maxloops)
|
|
{
|
|
set_presolve(lp, get_presolve(lp), maxloops);
|
|
}
|
|
|
|
static struct _values print_sol[] =
|
|
{
|
|
{ FALSE, "0" },
|
|
{ TRUE, "1" },
|
|
{ setvalue(AUTOMATIC) },
|
|
};
|
|
|
|
static struct _values scaling[] =
|
|
{
|
|
{ setvalue(SCALE_NONE) },
|
|
{ setvalue(SCALE_EXTREME) },
|
|
{ setvalue(SCALE_RANGE) },
|
|
{ setvalue(SCALE_MEAN) },
|
|
{ setvalue(SCALE_GEOMETRIC) },
|
|
{ setvalue(SCALE_CURTISREID) },
|
|
{ setvalue(SCALE_QUADRATIC) },
|
|
{ setvalue(SCALE_LOGARITHMIC) },
|
|
{ setvalue(SCALE_USERWEIGHT) },
|
|
{ setvalue(SCALE_POWER2) },
|
|
{ setvalue(SCALE_EQUILIBRATE) },
|
|
{ setvalue(SCALE_INTEGERS) },
|
|
{ setvalue(SCALE_DYNUPDATE) },
|
|
{ setvalue(SCALE_ROWSONLY) },
|
|
{ setvalue(SCALE_COLSONLY) },
|
|
};
|
|
|
|
static struct _values simplextype[] =
|
|
{
|
|
{ setvalue(SIMPLEX_PRIMAL_PRIMAL) },
|
|
{ setvalue(SIMPLEX_DUAL_PRIMAL) },
|
|
{ setvalue(SIMPLEX_PRIMAL_DUAL) },
|
|
{ setvalue(SIMPLEX_DUAL_DUAL) },
|
|
};
|
|
|
|
static struct _values verbose[] =
|
|
{
|
|
{ setvalue(NEUTRAL) },
|
|
{ setvalue(CRITICAL) },
|
|
{ setvalue(SEVERE) },
|
|
{ setvalue(IMPORTANT) },
|
|
{ setvalue(NORMAL) },
|
|
{ setvalue(DETAILED) },
|
|
{ setvalue(FULL) },
|
|
};
|
|
|
|
static struct _functions functions[] =
|
|
{
|
|
/* solve options */
|
|
{ "ANTI_DEGEN", setintfunction(get_anti_degen, set_anti_degen), setvalues(anti_degen, ~0), WRITE_ACTIVE },
|
|
{ "BASISCRASH", setintfunction(get_basiscrash, set_basiscrash), setvalues(basiscrash, ~0), WRITE_ACTIVE },
|
|
{ "IMPROVE", setintfunction(get_improve, set_improve), setvalues(improve, ~0), WRITE_ACTIVE },
|
|
{ "MAXPIVOT", setintfunction(get_maxpivot, set_maxpivot), setNULLvalues, WRITE_ACTIVE },
|
|
{ "NEGRANGE", setREALfunction(get_negrange, set_negrange), setNULLvalues, WRITE_ACTIVE },
|
|
{ "PIVOTING", setintfunction(get_pivoting, set_pivoting), setvalues(pivoting, PRICER_LASTOPTION), WRITE_ACTIVE },
|
|
{ "PRESOLVE", setintfunction(get_presolve, set_presolve1), setvalues(presolving, ~0), WRITE_ACTIVE },
|
|
{ "PRESOLVELOOPS", setintfunction(get_presolveloops, set_presolve2), setNULLvalues, WRITE_ACTIVE },
|
|
{ "SCALELIMIT", setREALfunction(get_scalelimit, set_scalelimit), setNULLvalues, WRITE_ACTIVE },
|
|
{ "SCALING", setintfunction(get_scaling, set_scaling), setvalues(scaling, SCALE_CURTISREID), WRITE_ACTIVE },
|
|
{ "SIMPLEXTYPE", setintfunction(get_simplextype, set_simplextype), setvalues(simplextype, ~0), WRITE_ACTIVE },
|
|
{ "OBJ_IN_BASIS", setMYBOOLfunction(is_obj_in_basis, set_obj_in_basis), setNULLvalues, WRITE_COMMENTED },
|
|
|
|
/* B&B options */
|
|
{ "BB_DEPTHLIMIT", setintfunction(get_bb_depthlimit, set_bb_depthlimit), setNULLvalues, WRITE_ACTIVE },
|
|
{ "BB_FLOORFIRST", setintfunction(get_bb_floorfirst, set_bb_floorfirst), setvalues(bb_floorfirst, ~0), WRITE_ACTIVE },
|
|
{ "BB_RULE", setintfunction(get_bb_rule, set_bb_rule), setvalues(bb_rule, NODE_STRATEGYMASK), WRITE_ACTIVE },
|
|
{ "BREAK_AT_FIRST", setMYBOOLfunction(is_break_at_first, set_break_at_first), setNULLvalues, WRITE_COMMENTED },
|
|
{ "BREAK_AT_VALUE", setREALfunction(get_break_at_value, set_break_at_value), setNULLvalues, WRITE_COMMENTED },
|
|
{ "MIP_GAP_ABS", setREALfunction(get_mip_gap_abs, set_mip_gap_abs), setNULLvalues, WRITE_ACTIVE },
|
|
{ "MIP_GAP_REL", setREALfunction(get_mip_gap_rel, set_mip_gap_rel), setNULLvalues, WRITE_ACTIVE },
|
|
{ "EPSINT", setREALfunction(get_epsint, set_epsint), setNULLvalues, WRITE_ACTIVE },
|
|
|
|
/* tolerances, values */
|
|
{ "EPSB", setREALfunction(get_epsb, set_epsb), setNULLvalues, WRITE_ACTIVE },
|
|
{ "EPSD", setREALfunction(get_epsd, set_epsd), setNULLvalues, WRITE_ACTIVE },
|
|
{ "EPSEL", setREALfunction(get_epsel, set_epsel), setNULLvalues, WRITE_ACTIVE },
|
|
{ "EPSPERTURB", setREALfunction(get_epsperturb, set_epsperturb), setNULLvalues, WRITE_ACTIVE },
|
|
{ "EPSPIVOT", setREALfunction(get_epspivot, set_epspivot), setNULLvalues, WRITE_ACTIVE },
|
|
{ "INFINITE", setREALfunction(get_infinite, set_infinite), setNULLvalues, WRITE_ACTIVE },
|
|
|
|
/* read-only options */
|
|
{ "DEBUG", setMYBOOLfunction(is_debug, set_debug), setNULLvalues, WRITE_COMMENTED },
|
|
{ "OBJ_BOUND", setREALfunction(get_obj_bound, set_obj_bound), setNULLvalues, WRITE_COMMENTED },
|
|
{ "PRINT_SOL", setintfunction(get_print_sol, set_print_sol), setvalues(print_sol, ~0), WRITE_COMMENTED },
|
|
{ "TIMEOUT", setlongfunction(get_timeout, set_timeout), setNULLvalues, WRITE_COMMENTED },
|
|
{ "TRACE", setMYBOOLfunction(is_trace, set_trace), setNULLvalues, WRITE_COMMENTED },
|
|
{ "VERBOSE", setintfunction(get_verbose, set_verbose), setvalues(verbose, ~0), WRITE_COMMENTED },
|
|
};
|
|
|
|
static void write_params1(lprec *lp, FILE *fp, char *header, int newline)
|
|
{
|
|
int ret = 0, ret2, i, j, k, value, value2, elements, majorversion, minorversion, release, build;
|
|
unsigned int basemask;
|
|
REAL a = 0;
|
|
char buf[4096], par[20];
|
|
|
|
ini_writeheader(fp, header, newline);
|
|
lp_solve_version(&majorversion, &minorversion, &release, &build);
|
|
sprintf(buf, "lp_solve version %d.%d settings\n", majorversion, minorversion);
|
|
ini_writecomment(fp, buf);
|
|
for(i = 0; i < sizeof(functions) / sizeof(*functions); i++) {
|
|
switch(functions[i].type) {
|
|
case intfunction:
|
|
if(functions[i].get_function.int_get_function == NULL)
|
|
continue;
|
|
ret = functions[i].get_function.int_get_function(lp);
|
|
break;
|
|
case longfunction:
|
|
if(functions[i].get_function.long_get_function == NULL)
|
|
continue;
|
|
ret = functions[i].get_function.long_get_function(lp);
|
|
break;
|
|
case MYBOOLfunction:
|
|
if(functions[i].get_function.MYBOOL_get_function == NULL)
|
|
continue;
|
|
ret = (int) functions[i].get_function.MYBOOL_get_function(lp);
|
|
break;
|
|
case REALfunction:
|
|
if(functions[i].get_function.REAL_get_function == NULL)
|
|
continue;
|
|
a = functions[i].get_function.REAL_get_function(lp);
|
|
break;
|
|
}
|
|
buf[0] = 0;
|
|
if(functions[i].values == NULL) {
|
|
switch(functions[i].type) {
|
|
case intfunction:
|
|
case longfunction:
|
|
case MYBOOLfunction:
|
|
sprintf(buf, "%d", ret);
|
|
break;
|
|
case REALfunction:
|
|
sprintf(buf, "%g", a);
|
|
break;
|
|
}
|
|
}
|
|
else {
|
|
elements = functions[i].elements;
|
|
basemask = functions[i].basemask;
|
|
for(j = 0; j < elements; j++) {
|
|
value = functions[i].values[j].value;
|
|
ret2 = ret;
|
|
if(((unsigned int) value) < basemask)
|
|
ret2 &= basemask;
|
|
if(value == 0) {
|
|
if(ret2 == 0) {
|
|
if(*buf)
|
|
strcat(buf, " + ");
|
|
strcat(buf, functions[i].values[j].svalue);
|
|
}
|
|
}
|
|
else if((ret2 & value) == value) {
|
|
for(k = 0; k < elements; k++) {
|
|
value2 = functions[i].values[k].value;
|
|
if((k != j) && (value2 > value) && ((value2 & value) == value) && ((ret2 & value2) == value2))
|
|
break;
|
|
}
|
|
if(k == elements) {
|
|
if(*buf)
|
|
strcat(buf, " + ");
|
|
strcat(buf, functions[i].values[j].svalue);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if(functions[i].mask & WRITE_ACTIVE)
|
|
par[0] = 0;
|
|
else
|
|
strcpy(par, ";");
|
|
strcat(par, functions[i].par);
|
|
ini_writedata(fp, STRLWR(par), buf);
|
|
}
|
|
}
|
|
|
|
static void readoptions(char *options, char **header)
|
|
{
|
|
char *ptr1, *ptr2;
|
|
|
|
if(options != NULL) {
|
|
ptr1 = options;
|
|
while(*ptr1) {
|
|
ptr2 = strchr(ptr1, '-');
|
|
if(ptr2 == NULL)
|
|
break;
|
|
ptr2++;
|
|
if(tolower((unsigned char) *ptr2) == 'h') {
|
|
for(++ptr2; (*ptr2) && (isspace(*ptr2)); ptr2++);
|
|
for(ptr1 = ptr2; (*ptr1) && (!isspace(*ptr1)); ptr1++);
|
|
*header = (char *) calloc(1 + (int) (ptr1 - ptr2), 1);
|
|
memcpy(*header, ptr2, (int) (ptr1 - ptr2));
|
|
}
|
|
}
|
|
}
|
|
|
|
if(*header == NULL)
|
|
*header = strdup("Default");
|
|
}
|
|
|
|
MYBOOL __WINAPI write_params(lprec *lp, char *filename, char *options)
|
|
{
|
|
int k, ret, params_written;
|
|
FILE *fp, *fp0;
|
|
int state = 0, looping, newline;
|
|
char buf[4096], *filename0, *ptr1, *ptr2, *header = NULL;
|
|
|
|
readoptions(options, &header);
|
|
|
|
k = (int) strlen(filename);
|
|
filename0 = (char *) malloc(k + 1 + 1);
|
|
strcpy(filename0, filename);
|
|
ptr1 = strrchr(filename0, '.');
|
|
ptr2 = strrchr(filename0, '\\');
|
|
if((ptr1 == NULL) || ((ptr2 != NULL) && (ptr1 < ptr2)))
|
|
ptr1 = filename0 + k;
|
|
memmove(ptr1 + 1, ptr1, k + 1 - (int) (ptr1 - filename0));
|
|
ptr1[0] = '_';
|
|
if(rename(filename, filename0)) {
|
|
switch(errno) {
|
|
case ENOENT: /* File or path specified by oldname not found */
|
|
FREE(filename0);
|
|
filename0 = NULL;
|
|
break;
|
|
case EACCES: /* File or directory specified by newname already exists or could not be created (invalid path); or oldname is a directory and newname specifies a different path. */
|
|
FREE(filename0);
|
|
FREE(header);
|
|
return(FALSE);
|
|
break;
|
|
}
|
|
}
|
|
|
|
if((fp = ini_create(filename)) == NULL)
|
|
ret = FALSE;
|
|
else {
|
|
params_written = FALSE;
|
|
newline = TRUE;
|
|
if(filename0 != NULL) {
|
|
fp0 = ini_open(filename0);
|
|
if(fp0 == NULL) {
|
|
rename(filename0, filename);
|
|
FREE(filename0);
|
|
FREE(header);
|
|
return(FALSE);
|
|
}
|
|
looping = TRUE;
|
|
while(looping) {
|
|
switch(ini_readdata(fp0, buf, sizeof(buf), TRUE)) {
|
|
case 0: /* End of file */
|
|
looping = FALSE;
|
|
break;
|
|
case 1: /* header */
|
|
ptr1 = strdup(buf);
|
|
STRUPR(buf);
|
|
ptr2 = strdup(header);
|
|
STRUPR(ptr2);
|
|
if(strcmp(buf, ptr2) == 0) {
|
|
write_params1(lp, fp, ptr1, newline);
|
|
params_written = TRUE;
|
|
newline = TRUE;
|
|
state = 1;
|
|
}
|
|
else {
|
|
state = 0;
|
|
ini_writeheader(fp, ptr1, newline);
|
|
newline = TRUE;
|
|
}
|
|
FREE(ptr2);
|
|
FREE(ptr1);
|
|
break;
|
|
case 2: /* data */
|
|
if(state == 0) {
|
|
ini_writedata(fp, NULL, buf);
|
|
newline = (*buf != 0);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
ini_close(fp0);
|
|
}
|
|
|
|
if(!params_written)
|
|
write_params1(lp, fp, header, newline);
|
|
|
|
ini_close(fp);
|
|
ret = TRUE;
|
|
}
|
|
|
|
if(filename0 != NULL) {
|
|
remove(filename0);
|
|
FREE(filename0);
|
|
}
|
|
|
|
FREE(header);
|
|
|
|
return( (MYBOOL) ret );
|
|
}
|
|
|
|
|
|
MYBOOL __WINAPI read_params(lprec *lp, char *filename, char *options)
|
|
{
|
|
int ret, looping, line;
|
|
FILE *fp;
|
|
hashtable *hashfunctions, *hashparameters;
|
|
hashelem *hp;
|
|
int i, j, elements, n, intvalue, state = 0;
|
|
REAL REALvalue;
|
|
char buf[4096], *header = NULL, *ptr, *ptr1, *ptr2;
|
|
|
|
if((fp = ini_open(filename)) == NULL)
|
|
ret = FALSE;
|
|
else {
|
|
/* create hashtable of all callable commands to find them quickly */
|
|
hashfunctions = create_hash_table(sizeof(functions) / sizeof(*functions), 0);
|
|
for (n = 0, i = 0; i < (int) (sizeof(functions)/sizeof(*functions)); i++) {
|
|
puthash(functions[i].par, i, NULL, hashfunctions);
|
|
if(functions[i].values != NULL)
|
|
n += functions[i].elements;
|
|
}
|
|
/* create hashtable of all arguments to find them quickly */
|
|
hashparameters = create_hash_table(n, 0);
|
|
for (n = 0, i = 0; i < (int) (sizeof(functions)/sizeof(*functions)); i++) {
|
|
if(functions[i].values != NULL) {
|
|
elements = functions[i].elements;
|
|
for(j = 0; j < elements; j++)
|
|
if((strcmp(functions[i].values[j].svalue, "0") != 0) &&
|
|
(strcmp(functions[i].values[j].svalue, "1") != 0))
|
|
puthash(functions[i].values[j].svalue, j, NULL, hashparameters);
|
|
}
|
|
}
|
|
|
|
readoptions(options, &header);
|
|
|
|
STRUPR(header);
|
|
ret = looping = TRUE;
|
|
line = 0;
|
|
while((ret) && (looping)) {
|
|
line++;
|
|
switch(ini_readdata(fp, buf, sizeof(buf), FALSE)) {
|
|
case 0: /* End of file */
|
|
looping = FALSE;
|
|
break;
|
|
case 1: /* header */
|
|
switch(state) {
|
|
case 0:
|
|
STRUPR(buf);
|
|
if(strcmp(buf, header) == 0)
|
|
state = 1;
|
|
break;
|
|
case 1:
|
|
looping = FALSE;
|
|
break;
|
|
}
|
|
break;
|
|
case 2: /* data */
|
|
if(state == 1) {
|
|
for(ptr = buf; (*ptr) && (isspace(*ptr)); ptr++);
|
|
}
|
|
else
|
|
ptr = NULL;
|
|
if((ptr != NULL) && (*ptr)) {
|
|
STRUPR(buf);
|
|
ptr = strchr(buf, '=');
|
|
if(ptr == NULL) {
|
|
report(lp, IMPORTANT, "read_params: No equal sign on line %d\n", line);
|
|
ret = FALSE;
|
|
}
|
|
else {
|
|
*ptr = 0;
|
|
for(ptr1 = buf; isspace(*ptr1); ptr1++);
|
|
for(ptr2 = ptr - 1; (ptr2 >= ptr1) && (isspace(*ptr2)); ptr2--);
|
|
if(ptr2 <= ptr1) {
|
|
report(lp, IMPORTANT, "read_params: No parameter name before equal sign on line %d\n", line);
|
|
ret = FALSE;
|
|
}
|
|
else {
|
|
ptr2[1] = 0;
|
|
hp = findhash(ptr1, hashfunctions);
|
|
if(hp == NULL) {
|
|
report(lp, IMPORTANT, "read_params: Unknown parameter name (%s) before equal sign on line %d\n", ptr1, line);
|
|
ret = FALSE;
|
|
}
|
|
else {
|
|
i = hp->index;
|
|
ptr1 = ++ptr;
|
|
intvalue = 0;
|
|
REALvalue = 0;
|
|
if(functions[i].values == NULL) {
|
|
switch(functions[i].type) {
|
|
case intfunction:
|
|
case longfunction:
|
|
case MYBOOLfunction:
|
|
intvalue = strtol(ptr1, &ptr2, 10);
|
|
while((*ptr2) && (isspace(*ptr2)))
|
|
ptr2++;
|
|
if(*ptr2) {
|
|
report(lp, IMPORTANT, "read_params: Invalid integer value on line %d\n", line);
|
|
ret = FALSE;
|
|
}
|
|
break;
|
|
case REALfunction:
|
|
REALvalue = strtod(ptr1, &ptr2);
|
|
while((*ptr2) && (isspace(*ptr2)))
|
|
ptr2++;
|
|
if(*ptr2) {
|
|
report(lp, IMPORTANT, "read_params: Invalid real value on line %d\n", line);
|
|
ret = FALSE;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
else {
|
|
while(ret) {
|
|
ptr = strchr(ptr1, '+');
|
|
if(ptr == NULL)
|
|
ptr = ptr1 + strlen(ptr1);
|
|
for(; isspace(*ptr1); ptr1++);
|
|
for(ptr2 = ptr - 1; (ptr2 >= ptr1) && (isspace(*ptr2)); ptr2--);
|
|
if(ptr2 <= ptr1)
|
|
break;
|
|
else {
|
|
ptr2[1] = 0;
|
|
hp = findhash(ptr1, hashparameters);
|
|
if (hp == NULL) {
|
|
report(lp, IMPORTANT, "read_params: Invalid parameter name (%s) on line %d\n", ptr1, line);
|
|
ret = FALSE;
|
|
}
|
|
else {
|
|
j = hp->index;
|
|
if((j >= functions[i].elements) ||
|
|
(strcmp(functions[i].values[j].svalue, ptr1))) {
|
|
report(lp, IMPORTANT, "read_params: Inappropriate parameter name (%s) on line %d\n", ptr1, line);
|
|
ret = FALSE;
|
|
}
|
|
else {
|
|
intvalue += functions[i].values[j].value;
|
|
}
|
|
}
|
|
ptr1 = ptr + 1;
|
|
}
|
|
}
|
|
}
|
|
if(ret) {
|
|
switch(functions[i].type) {
|
|
case intfunction:
|
|
functions[i].set_function.int_set_function(lp, intvalue);
|
|
break;
|
|
case longfunction:
|
|
functions[i].set_function.long_set_function(lp, intvalue);
|
|
break;
|
|
case MYBOOLfunction:
|
|
functions[i].set_function.MYBOOL_set_function(lp, (MYBOOL) intvalue);
|
|
break;
|
|
case REALfunction:
|
|
functions[i].set_function.REAL_set_function(lp, REALvalue);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
FREE(header);
|
|
free_hash_table(hashfunctions);
|
|
free_hash_table(hashparameters);
|
|
|
|
ini_close(fp);
|
|
}
|
|
|
|
return( (MYBOOL) ret );
|
|
}
|