TPCCLIB
Loading...
Searching...
No Matches
tacstudy.c
Go to the documentation of this file.
1
9/*****************************************************************************/
10#include "tpcclibConfig.h"
11/*****************************************************************************/
12#include <stdio.h>
13#include <stdlib.h>
14#include <string.h>
15#include <ctype.h>
16/*****************************************************************************/
17#include "tpcextensions.h"
18#include "tpcift.h"
19#include "tpctac.h"
20/*****************************************************************************/
21
22/*****************************************************************************/
23static char *info[] = {
24 "Set or get the valid TPC study number in regional TAC or SIF file.",
25 "Valid TPC study number can not exceed 10 characters, and it must not",
26 "contain spaces; it contains 1-5 letters (upper- or lowercase)",
27 "followed by 1-5 digits.",
28 " ",
29 "If study number is not given as argument, or file does not contain it,",
30 "it is automatically extracted from filename, when possible, by this and",
31 "other applications.",
32 " ",
33 "Note that many file formats (including PMOD) do not support study numbers,",
34 "but this application can still optionally add the study number as",
35 "a comment, for example:",
36 "# studynr := ab1006",
37 " ",
38 "Usage: @P [Options] filename [studynumber]",
39 " ",
40 "Options:",
41 " -fn[=<N>]",
42 " Get study number from filename, optionally from the N first letters",
43 " (max 10) of file name, excluding possible path and extension.",
44 " -df=<N>",
45 " Delete the first N letters from study number.",
46 " -lower",
47 " Convert study number letters to lowercase.",
48 " --force",
49 " Validity of new study number is not verified, and written in file",
50 " as comment line, if not otherwise supported. Maximum length for",
51 " study number is either 255 or 10 characters, depending on file format.",
52 " -value",
53 " Print only the study number without file name.",
54 " -stdoptions", // List standard options like --help, -v, etc
55 " ",
56 "See also: tacunit, tacadd, iftlist, iftedit, tacformat",
57 " ",
58 "Keywords: TAC, tool, simulation, study number",
59 0};
60/*****************************************************************************/
61
62/*****************************************************************************/
63/* Turn on the globbing of the command line, since it is disabled by default in
64 mingw-w64 (_dowildcard=0); in MinGW32 define _CRT_glob instead, if necessary;
65 In Unix&Linux wildcard command line processing is enabled by default. */
66/*
67#undef _CRT_glob
68#define _CRT_glob -1
69*/
70int _dowildcard = -1;
71/*****************************************************************************/
72
73/*****************************************************************************/
77int main(int argc, char **argv)
78{
79 int ai, help=0, version=0, verbose=1;
80 int ret, toLower=0, force=0, print_value=0;
81 unsigned int fromFilename=0, deleteFirst=0;
82 char *cptr, datfile[FILENAME_MAX], studynr[FILENAME_MAX];
83 char oldstudynr[FILENAME_MAX], tmp[FILENAME_MAX];
84 TAC tac;
85
86
87 /*
88 * Get and check arguments
89 */
90 if(argc==1) {tpcPrintUsage(argv[0], info, stderr); return(1);}
91 tacInit(&tac);
92 datfile[0]=studynr[0]=oldstudynr[0]=(char)0;
93 /* Options */
94 for(ai=1; ai<argc; ai++) if(*argv[ai]=='-') {
95 if(tpcProcessStdOptions(argv[ai], &help, &version, &verbose)==0) continue;
96 cptr=argv[ai]+1; if(*cptr=='-') cptr++; if(!*cptr) continue;
97 if(strcasecmp(cptr, "LOWER")==0) {
98 toLower=1; continue;
99 } else if(strncasecmp(cptr, "DF=", 3)==0) {
100 cptr+=3; deleteFirst=atoi(cptr);
101 if(deleteFirst>0 && deleteFirst<11) continue;
102 } else if(strcasecmp(cptr, "FN")==0) {
103 fromFilename=1; continue;
104 } else if(strncasecmp(cptr, "FN=", 3)==0) {
105 cptr+=3; fromFilename=atoi(cptr);
106 if(fromFilename>0) continue; // max length is check later
107 } else if(strcasecmp(cptr, "FORCE")==0) {
108 force=1; continue;
109 } else if(strcasecmp(cptr, "VALUE")==0) {
110 print_value=1; continue;
111 }
112 fprintf(stderr, "Error: invalid option '%s'\n", argv[ai]);
113 return(1);
114 } else break; // tac name argument may start with '-'
115
116 /* Print help or version? */
117 if(help==2) {tpcHtmlUsage(argv[0], info, ""); return(0);}
118 if(help) {tpcPrintUsage(argv[0], info, stdout); return(0);}
119 if(version) {tpcPrintBuild(argv[0], stdout); return(0);}
120
121 /* Process other arguments, starting from the first non-option */
122 for(; ai<argc; ai++) {
123 if(!datfile[0]) {
124 strlcpy(datfile, argv[ai], FILENAME_MAX); continue;
125 } else if(!studynr[0]) {
126 strlcpy(studynr, argv[ai], FILENAME_MAX);
127 /* In case that this is filename, remove path and extension */
128 filenameRmPath(studynr); filenameRmExtension(studynr);
129 /* If anything is accepted, then be it */
130 if(force==1 && strlen(studynr)>1) continue;
131 /* If not forced, then check the validity as study number */
132 ret=0;
133 if(studynrVerify(studynr, 1)!=0) {
134 /* Not valid; treat it like filename */
135 ret=studynrFromFilename(argv[ai], studynr, force);
136 if(fromFilename>1) studynr[fromFilename]=(char)0;
137 }
138 if(ret==0) continue;
139 fprintf(stderr, "Error: invalid argument for study number '%s'\n", argv[ai]);
140 return(1);
141 }
142 fprintf(stderr, "Error: invalid argument '%s'\n", argv[ai]);
143 return(1);
144 }
145
146 /* Is something missing? */
147 if(!datfile[0]) {tpcPrintUsage(argv[0], info, stdout); return(1);}
148
149 /* In verbose mode print arguments and options */
150 if(verbose>1) {
151 printf("datfile := %s\n", datfile);
152 printf("studynr := %s\n", studynr);
153 printf("force := %d\n", force);
154 printf("toLower := %d\n", toLower);
155 printf("fromFilename := %d\n", fromFilename);
156 printf("deleteFirst := %d\n", deleteFirst);
157 printf("print_value := %d\n", print_value);
158 }
159
160 TPCSTATUS status; statusInit(&status);
161 statusSet(&status, __func__, __FILE__, __LINE__, TPCERROR_OK);
162 status.verbose=verbose-1;
163
164
165 /* Check other arguments and options */
166 if(fromFilename>1 && ((int)fromFilename-(int)deleteFirst)>10) {
167 fprintf(stderr, "Error: too high value with option -fn.\n");
168 return(1);
169 }
170
171 /* Take new study number from filename */
172 if(!studynr[0] && fromFilename>0) {
173 if(verbose>1) printf("getting new study number from filename\n");
174 strcpy(tmp, datfile); filenameRmPath(tmp); filenameRmExtension(tmp);
175 if(fromFilename>1) {
176 tmp[fromFilename+deleteFirst]=(char)0;
177 strcpy(studynr, tmp);
178 } else {
179 studynrFromFilename(tmp, studynr, force);
180 }
181 if(verbose>2) printf("studynr := %s\n", studynr);
182 if(strlen(studynr)<1) {
183 fprintf(stderr, "Error: cannot get study number from filename.\n");
184 return(4);
185 }
186 }
187
188 /*
189 * Read datafile
190 */
191 if(verbose>1) printf("reading %s\n", datfile);
192 ret=tacRead(&tac, datfile, &status);
193 if(ret) {
194 fprintf(stderr, "Error: %s (%s)\n", errorMsg(status.error), datfile);
195 tacFree(&tac);
196 return(2);
197 }
198 /* Get the current study number */
199 ret=tacGetHeaderStudynr(&tac.h, oldstudynr, &status);
200 /* Delete '.' from study number string */
201 if(strcmp(oldstudynr, ".")==0) strcpy(oldstudynr, "");
202 if(verbose>1) printf("infile.studynr := %s\n", oldstudynr);
203 /* Convert to lowercase if necessary */
204 if(toLower>0) {
205 int i, len;
206 len=strlen(oldstudynr);
207 for(i=0; i<len; i++) {
208 if(isdigit((int)oldstudynr[i])) continue;
209 oldstudynr[i]=(char)tolower((int)oldstudynr[i]);
210 }
211 }
212 /* Delete first letters if necessary */
213 if(deleteFirst>0 && deleteFirst<strlen(oldstudynr)) {
214 strcpy(tmp, oldstudynr+deleteFirst); strcpy(oldstudynr, tmp);
215 }
216
217 /* If new study number was not given then just print the current one */
218 if(!studynr[0]) {
219 strcpy(tmp, datfile); filenameRmPath(tmp);
220 if(print_value) printf("%s\n", oldstudynr);
221 else printf("%s := %s\n", tmp, oldstudynr);
222 tacFree(&tac);
223 return(0); /* and that's it */
224 }
225
226 /* Check the specified study number */
227 if(studynr[0]) {
228 if(verbose>2) printf("processing specified study number\n");
229
230 /* Convert to lowercase if necessary */
231 if(toLower>0) {
232 if(verbose>2) printf("converting to lower case letters\n");
233 //studynr_to_lowercase(studynr);
234 int i, len;
235 len=strlen(studynr);
236 for(i=0; i<len; i++) {
237 if(isdigit((int)studynr[i])) continue;
238 studynr[i]=(char)tolower((int)studynr[i]);
239 }
240 }
241
242 /* Delete first letters if necessary */
243 if(deleteFirst>0) {
244 if(verbose>2) printf("deleting first characters\n");
245 if(studynr[0] && deleteFirst<strlen(studynr)) {
246 strcpy(tmp, studynr+deleteFirst); strcpy(studynr, tmp);}
247 }
248
249 /* Check that it is not too long */
250 if(strlen(studynr)>MAX_STUDYNR_LEN) {
251 if(verbose>2) printf("new study number was too long, shortened\n");
252 studynr[MAX_STUDYNR_LEN-1]=(char)0;
253 }
254 if(verbose>1) printf("studynr := %s\n", studynr);
255
256 /* Test that it is still valid */
257 if(force==0) {
258 if(verbose>2) printf("verifying new study number because not forced\n");
259 if(studynrVerify(studynr, 1)!=0) {
260 fprintf(stderr, "Error: invalid study number.\n");
261 if(verbose>2) printf(" studynr := '%s'\n", studynr);
262 tacFree(&tac);
263 return(1);
264 }
265 }
266 }
267
268 /* Change studynumber */
269 if(verbose>0)
270 fprintf(stdout, "%s: '%s' -> '%s'\n", datfile, oldstudynr, studynr);
271 ret=tacSetHeaderStudynr(&tac.h, studynr);
272 if(ret!=TPCERROR_OK) {
273 fprintf(stderr, "Error: cannot set new study number.\n");
274 if(verbose>2) printf(" ret := %d\n", ret);
275 tacFree(&tac);
276 return(1);
277 }
278 /* and write the modified file */
279 if(verbose>1) printf("writing %s\n", datfile);
280 FILE *fp; fp=fopen(datfile, "w");
281 if(fp==NULL) {
282 fprintf(stderr, "Error: cannot open file for writing (%s)\n", datfile);
283 tacFree(&tac); return(11);
284 }
285 ret=tacWrite(&tac, fp, TAC_FORMAT_UNKNOWN, force, &status);
286 fclose(fp);
287 tacFree(&tac);
288 if(ret!=TPCERROR_OK) {
289 fprintf(stderr, "Error: %s\n", errorMsg(status.error));
290 return(12);
291 }
292
293 return(0);
294}
295/*****************************************************************************/
296
297/*****************************************************************************/
void filenameRmPath(char *s)
Definition filename.c:20
int filenameRmExtension(char *s)
Definition filename.c:71
int tpcProcessStdOptions(const char *s, int *print_usage, int *print_version, int *verbose_level)
Definition proginfo.c:47
int tpcHtmlUsage(const char *program, char *text[], const char *path)
Definition proginfo.c:169
void tpcPrintBuild(const char *program, FILE *fp)
Definition proginfo.c:339
void tpcPrintUsage(const char *program, char *text[], FILE *fp)
Definition proginfo.c:114
void statusInit(TPCSTATUS *s)
Definition statusmsg.c:104
char * errorMsg(tpcerror e)
Definition statusmsg.c:68
void statusSet(TPCSTATUS *s, const char *func, const char *srcfile, int srcline, tpcerror error)
Definition statusmsg.c:142
size_t strlcpy(char *dst, const char *src, size_t dstsize)
Definition stringext.c:632
Definition tpctac.h:87
IFT h
Optional (but often useful) header information.
Definition tpctac.h:141
int verbose
Verbose level, used by statusPrint() etc.
tpcerror error
Error code.
int studynrFromFilename(const char *fname, char *studynr, int force)
Definition studynr.c:79
int studynrVerify(const char *s, int zero_ok)
Definition studynr.c:22
void tacFree(TAC *tac)
Definition tac.c:106
void tacInit(TAC *tac)
Definition tac.c:24
int tacGetHeaderStudynr(IFT *h, char *s, TPCSTATUS *status)
Definition tacift.c:26
int tacSetHeaderStudynr(IFT *h, const char *s)
Definition tacift.c:79
int tacRead(TAC *d, const char *fname, TPCSTATUS *status)
Definition tacio.c:413
int tacWrite(TAC *tac, FILE *fp, tacformat format, int extra, TPCSTATUS *status)
Definition tacio.c:332
Header file for library libtpcextensions.
@ TPCERROR_OK
No error.
#define MAX_STUDYNR_LEN
Define max study number length.
Header file for library libtpcift.
Header file for library libtpctac.
@ TAC_FORMAT_UNKNOWN
Unknown format.
Definition tpctac.h:28