8#include "tpcclibConfig.h"
20static char *info[] = {
21 "Simple artithmetic calculations on values in Interfile-type (IFT) files.",
22 "Keys are case-insensitive. Only numerical values are accepted.",
24 "Usage: @P [options] file1 key1 operation file2 key2 [outputfile]",
29 "The following characters are accepted as operators: +, -, x, and :.",
30 "Value(s) in file1 are modified using specified value in file2.",
31 "If IFT does not contain keys, or all values in file1 are to be processed,",
32 "then enter 'all' or 'none' as the key name.",
33 "Contents of file1, including changed and preserved ones, are saved in",
34 "outputfile, or if not given , then file1 is overwritten.",
37 " @P par.ift p1 x const.ift factor newpar.ift",
39 "See also: iftlist, iftisval, iftedit, iftadd, iftdel, parformat, taccalc",
41 "Keywords: header, IFT, tool",
68 if(operation==1)
return(v1+v2);
69 if(operation==2)
return(v1-v2);
70 if(operation==3)
return(v1*v2);
71 if(operation==4)
return(v1/v2);
80int main(
int argc,
char **argv)
82 int ai, help=0, version=0, verbose=1;
85 char iftfile1[FILENAME_MAX], iftfile2[FILENAME_MAX], iftfile3[FILENAME_MAX];
86 char key1[128], key2[128];
93 if(argc==1) {
tpcPrintUsage(argv[0], info, stderr);
return(1);}
94 iftfile1[0]=iftfile2[0]=iftfile3[0]=(char)0;
95 key1[0]=key2[0]=(char)0;
97 for(ai=1; ai<argc; ai++)
if(*argv[ai]==
'-') {
99 fprintf(stderr,
"Error: invalid option '%s'\n", argv[ai]);
104 if(help==2) {
tpcHtmlUsage(argv[0], info,
"");
return(0);}
113 if(ai<argc)
strlcpy(iftfile1, argv[ai++], FILENAME_MAX);
114 if(ai<argc)
strlcpy(key1, argv[ai++], 128);
116 if(strcasecmp(argv[ai],
"DIV")==0) {
120 case '+' : operation=1;
break;
121 case '-' : operation=2;
break;
122 case '*' : operation=3;
break;
123 case '.' : operation=3;
break;
124 case 'X' : operation=3;
break;
125 case 'x' : operation=3;
break;
126 case '/' : operation=4;
break;
127 case ':' : operation=4;
break;
131 fprintf(stderr,
"Error: invalid operator.\n");
136 if(ai<argc)
strlcpy(iftfile2, argv[ai++], FILENAME_MAX);
137 if(ai<argc)
strlcpy(key2, argv[ai++], 128);
138 if(ai<argc)
strlcpy(iftfile3, argv[ai++], FILENAME_MAX);
140 fprintf(stderr,
"Error: too many arguments.\n");
145 if(!key2[0]) {
tpcPrintUsage(argv[0], info, stdout);
return(1);}
147 if(strcasecmp(key1,
"ALL")==0 || strcasecmp(key1,
"NONE")==0) key1[0]=(char)0;
148 if(strcasecmp(key2,
"ALL")==0 || strcasecmp(key2,
"NONE")==0) key2[0]=(char)0;
150 if(!iftfile3[0]) strcpy(iftfile3, iftfile1);
154 for(ai=0; ai<argc; ai++) printf(
"%s ", argv[ai]);
155 printf(
"\n"); fflush(stdout);
156 printf(
"iftfile1 := %s\n", iftfile1);
157 printf(
"key1 := %s\n", key1);
158 printf(
"operation := %d\n", operation);
159 printf(
"iftfile2 := %s\n", iftfile2);
160 printf(
"key2 := %s\n", key2);
161 printf(
"iftfile3 := %s\n", iftfile3);
172 if(verbose>1) printf(
"reading %s\n", iftfile1);
173 FILE *fp=fopen(iftfile1,
"r");
if(fp==NULL) {
174 fprintf(stderr,
"Error: cannot open file %s\n", iftfile1);
177 if(key1[0]) key_required=1;
else key_required=0;
178 ret=
iftRead(&ift1, fp, key_required, 1, &status); fclose(fp);
180 fprintf(stderr,
"Error (%d): %s\n", ret,
errorMsg(status.
error));
183 if(verbose>2) printf(
"list size: %d item(s)\n", ift1.
keyNr);
185 if(verbose>1) printf(
"reading %s\n", iftfile2);
186 fp=fopen(iftfile2,
"r");
if(fp==NULL) {
187 fprintf(stderr,
"Error: cannot open file %s\n", iftfile2);
190 if(key2[0]) key_required=1;
else key_required=0;
191 ret=
iftRead(&ift2, fp, key_required, 1, &status); fclose(fp);
193 fprintf(stderr,
"Error (%d): %s\n", ret,
errorMsg(status.
error));
196 if(verbose>2) printf(
"list size: %d item(s)\n", ift2.
keyNr);
203 if(ift1.
keyNr==ift2.
keyNr && !key1[0] && !key2[0]) {
204 if(verbose>1) printf(
"operating items as pairs\n");
212 if(verbose>1) printf(
"files do not have key names\n");
213 for(
int li=0; li<ift1.
keyNr; li++) {
216 if(ret || isnan(v1) || isnan(v2)) {
217 if(verbose>1) printf(
"invalid values in item %d\n", 1+li);
220 v3=doubleOperate(v1, v2, operation);
222 else snprintf(newstr, 128,
"%g %s", v3,
unitName(u1));
223 if(verbose>3) printf(
"new_value := '%s'\n", newstr);
228 if(verbose>1) printf(
"files have key names, using matching keys\n");
230 for(
int li=0; li<ift1.
keyNr; li++) {
235 if(ret || isnan(v1) || isnan(v2)) {
236 if(verbose>1) printf(
"invalid values in item %d\n", 1+li);
239 v3=doubleOperate(v1, v2, operation);
241 else snprintf(newstr, 128,
"%g %s", v3,
unitName(u1));
242 if(verbose>3) printf(
"new_value := '%s'\n", newstr);
250 fprintf(stderr,
"Error: no valid calculations could be done.\n");
254 if(okNr<ift1.keyNr && verbose>0)
255 fprintf(stderr,
"Notice: some lines omitted.\n");
263 if(!key1[0] && !key2[0]) {
266 double v, v2=nan(
"");
267 for(
int li=0; li<ift2.
keyNr; li++) {
269 if(ret==0 && !isnan(v)) {v2=v; u2=u; n++;}
271 if(verbose>2) printf(
"file2 contains %d valid values\n", n);
273 if(verbose>1) printf(
"using the single value in file2 for all file1 values\n");
278 for(
int li=0; li<ift1.
keyNr; li++) {
280 if(ret || isnan(v1)) {
281 if(verbose>1) printf(
"invalid values in item %d\n", 1+li);
284 if(verbose>2 && u1!=u2)
285 fprintf(stderr,
"Warning: different units\n");
286 v3=doubleOperate(v1, v2, operation);
288 else snprintf(newstr, 128,
"%g %s", v3,
unitName(u1));
289 if(verbose>3) printf(
"new_value := '%s'\n", newstr);
294 fprintf(stderr,
"Error: no valid calculations could be done.\n");
298 if(okNr<ift1.keyNr && verbose>0)
299 fprintf(stderr,
"Notice: some lines omitted.\n");
310 if(n<1) fprintf(stderr,
"Error: key '%s' not found in file1.\n", key1);
311 if(n>1) fprintf(stderr,
"Error: %d items matching key '%s' found in file1.\n", n, key1);
319 if(n<1) fprintf(stderr,
"Error: key '%s' not found in file2.\n", key2);
320 if(n>1) fprintf(stderr,
"Error: %d items matching key '%s' found in file2.\n", n, key2);
331 if(key2[0] && !key1[0]) {
332 if(verbose>1) printf(
"using the specified item in file2 for all file1 values\n");
337 if(ret || isnan(v2)) {
338 fprintf(stderr,
"Error: invalid value in file2.\n");
344 for(li=0; li<ift1.
keyNr; li++) {
346 if(ret || isnan(v1)) {
347 if(verbose>1) printf(
"invalid values in item %d\n", 1+li);
350 if(verbose>2 && u1!=u2)
351 fprintf(stderr,
"Warning: different units\n");
352 v3=doubleOperate(v1, v2, operation);
354 else snprintf(newstr, 128,
"%g %s", v3,
unitName(u1));
355 if(verbose>3) printf(
"new_value := '%s'\n", newstr);
360 fprintf(stderr,
"Error: no valid calculations could be done.\n");
364 if(okNr<ift1.keyNr && verbose>0)
365 fprintf(stderr,
"Notice: some lines omitted.\n");
375 if(key2[0] && key1[0]) {
376 if(verbose>1) printf(
"using the specified item in file1 and file2\n");
381 if(ret || isnan(v2)) {
382 fprintf(stderr,
"Error: invalid value in file2.\n");
388 if(ret || isnan(v1)) {
389 fprintf(stderr,
"Error: invalid value in file1.\n");
394 if(verbose>2 && u1!=u2)
395 fprintf(stderr,
"Warning: different units\n");
396 v3=doubleOperate(v1, v2, operation);
398 else snprintf(newstr, 128,
"%g %s", v3,
unitName(u1));
399 if(verbose>3) printf(
"new_value := '%s'\n", newstr);
401 fprintf(stderr,
"Error: no valid calculations could be done.\n");
415 if(key1[0] && !key2[0]) {
416 if(verbose>1) printf(
"using the specified item in file1\n");
421 if(ret || isnan(v1)) {
422 fprintf(stderr,
"Error: invalid value in file1.\n");
427 int n=0, u, u2=0, okNr=0;
428 double v, v2=nan(
"");
429 for(
int lj=0; lj<ift2.
keyNr; lj++) {
431 if(ret==0 && !isnan(v)) {v2=v; u2=u; n++;}
433 if(verbose>2) printf(
"file2 contains %d valid values\n", n);
435 fprintf(stderr,
"Error: no valid values in file2.\n");
439 if(verbose>1) printf(
"using the single value in file2\n");
442 if(verbose>2 && u1!=u2)
443 fprintf(stderr,
"Warning: different units\n");
444 v3=doubleOperate(v1, v2, operation);
446 else snprintf(newstr, 128,
"%g %s", v3,
unitName(u1));
447 if(verbose>3) printf(
"new_value := '%s'\n", newstr);
451 if(verbose>1) printf(
"trying to search same key in file2\n");
454 fprintf(stderr,
"Error: cannot find matching item in file2.\n");
459 if(ret || isnan(v2)) {
460 fprintf(stderr,
"Error: invalid value in file2.\n");
466 if(verbose>2 && u1!=u2)
467 fprintf(stderr,
"Warning: different units\n");
468 v3=doubleOperate(v1, v2, operation);
470 else snprintf(newstr, 128,
"%g %s", v3,
unitName(u1));
471 if(verbose>3) printf(
"new_value := '%s'\n", newstr);
476 fprintf(stderr,
"Error: no valid calculations could be done.\n");
487 fprintf(stderr,
"Error: no valid calculations could be done.\n");
496 if(verbose>1) printf(
"writing modified IFT in %s\n", iftfile3);
497 fp=fopen(iftfile3,
"w");
if(fp==NULL) {
498 fprintf(stderr,
"Error: cannot open file %s\n", iftfile3);
501 ret=
iftWrite(&ift1, fp, &status); fclose(fp);
int iftReplaceValue(IFT *ift, int i, const char *value, TPCSTATUS *status)
int iftDelete(IFT *ift, int index)
int iftFindNrOfKeys(IFT *ift, const char *key)
int iftFindKey(IFT *ift, const char *key, int start_index)
int iftGetDoubleWithUnit(IFT *ift, int index, double *v, int *unit)
int iftWrite(IFT *ift, FILE *fp, TPCSTATUS *status)
int iftRead(IFT *ift, FILE *fp, int is_key_required, int is_comment_accepted, TPCSTATUS *status)
int tpcProcessStdOptions(const char *s, int *print_usage, int *print_version, int *verbose_level)
int tpcHtmlUsage(const char *program, char *text[], const char *path)
void tpcPrintBuild(const char *program, FILE *fp)
void tpcPrintUsage(const char *program, char *text[], FILE *fp)
void statusInit(TPCSTATUS *s)
char * errorMsg(tpcerror e)
void statusSet(TPCSTATUS *s, const char *func, const char *srcfile, int srcline, tpcerror error)
size_t strlcpy(char *dst, const char *src, size_t dstsize)
int verbose
Verbose level, used by statusPrint() etc.
tpcerror error
Error code.
Header file for library libtpcextensions.
@ UNIT_UNKNOWN
Unknown unit.
char * unitName(int unit_code)
Header file for library libtpcift.