13 int fileCount=0,/* total number of files in record*/
14 funcCount=0,/* Number of functions to use */
15 openCount=0,/* Number of distinct open files */
16 baseFiles=-1;/* number of files which used to find combinations*/
22 EPP* fileinfo[MAX_OUTTABLE_FILES];
23 EPP_LINK links[MAX_OUTTABLE_FILES];
24 unsigned short int *table;
25 typedef struct record *rec;
26 int tuple_size, limit, delta, count;
27 struct FuncItem funcList[MAX_OUTTABLE_FILES];
28 struct FileInfo openFiles[MAX_OUTTABLE_FILES];
30 void error(const char *format,...)
33 vfprintf(stderr,format,ap);
40 printf("Usage: outtable [-%%][-u][-c][-d char][-b file][-z value][-Z value] files.."
41 "-function file(s)...\n");
42 printf("Where function are:\n");
43 for(f=funcTable;f->func;f++){
44 printf("%c-%s %s",sep,f->name,f->nargs==1?"file":"file file");
49 void scanOpt(int *i,int argc, char **argv)
52 for (*i=1;*i<argc;(*i)++) {
53 if (argv[*i][0]=='-') {
54 if (strlen(argv[*i])==2) {
67 delimiter=argv[++*i][0];
69 case 'z': {char *errptr;
70 zUnit=strtod(argv[++(*i)],&errptr);
72 error("Invalid Z unit %s\n",argv[*i]);
74 case 'Z': { char *errptr;
75 zOffset=strtod(argv[++(*i)],&errptr);
77 error("invalid Z offset %s\n",argv[*i]);
83 exit (argv[*i][1]=='h');
85 } else if (strlen(argv[*i])==3&&argv[*i][1]=='d') {
86 delimiter=argv[*i][2];
87 } else if (argv[*i][1]=='-') {
89 if (!strcmp(argv[*i],"--help")) {
91 } else if (!strcmp(argv[*i],"--version")) {
92 show_version("outtable","$Revision: 1.1 $");
94 } else if (!strcmp(argv[*i],"--cells")) {
96 } else if (!strcmp(argv[*i],"--union")) {
98 } else if (!strcmp(argv[*i],"--base")) {
100 } else if (!strcmp(argv[*i],"--delimiter")) {
101 delimiter=argv[++*i][0];
107 /* Starts with - but not recognized as option -
108 should be function */
112 /* Doesn't start with - should be filename */
120 struct FuncInfo * findFunction(char *name)
122 for(f=funcTable;strcmp(name,f->name)&&f->func;f++);
123 if (f->func) return f;
127 void openFile(char *name) {
131 strcpy(Name,default_ext(name,".epp"));
132 for (i=0,f=openFiles;i<openCount&&strcmp(Name,f->name);i++,f++);
134 fileinfo[fileCount++]=f->epp;
137 f->epp=open_epp(Name);
138 f->name=strdup(Name);
141 error("Couldn't open file %s\n",name);
147 void parseArgs(int i, int argc, char **argv) {
148 struct FuncInfo *func;
151 if (argv[i][0]=='-') {
152 if (!(func=findFunction(argv[i]+1))) {
153 error("Undefined function %s\n",argv[i]);
155 /* Make function list entry */
156 funcList[funcCount].func=func->func;
157 funcList[funcCount].index=fileCount;
158 funcList[funcCount].data=malloc(func->datasize);
159 /* Note, that definition of combinations finished */
160 if (baseFiles<0) baseFiles=fileCount;
161 for (j=0;j<func->nargs;j++) {
162 if (i==argc) error("Not enough args for function -%s\n",func->name);
167 error("Files to define combinations should precede functions\n");
173 int compare(struct record *r1, struct record *r2)
175 for (i=0;i<fileCount;i++)
176 { if (r1->classes[i]>r2->classes[i]) return 1;
178 if (r1->classes[i]<r2->classes[i]) return -1;
183 /* Searches table for record which contains classes, specified
184 in record key. if found, returns non-zero and places index of it
185 into index. If not, returns zero and places index, where to insert
187 int search(struct record *key,int *index)
188 {int l=0,h=count-1,i,c;
191 c=compare((struct record *)(table+(tuple_size)*i),key);
195 if (!c) { *index=i;return 1;}
201 /* Inserts given record into table at position index.
202 Fills count field of inserted record by 1
204 void insert(struct record *key,int index)
208 table=realloc(table,(limit+=delta)*(tuple_size)*sizeof(short int));
210 error("Couldn't realloc table. Table limit is %d\n",limit);
214 for(i=count;i>index;i--)
215 memcpy(table+(i)*(tuple_size),table+(i-1)*(tuple_size),
216 (tuple_size)*sizeof(short int));
217 l=(long int *)(table+index*(tuple_size));
219 memcpy(table+index*tuple_size+2,key->classes,fileCount*sizeof(short int));
223 adds pixel into table, i.e. if record with such combination of classes
224 already exists, increments its count. Otherwise inserts new record.
226 void add_pixel(struct record *key)
227 {int index;long int *l;
228 if (search(key,&index))
230 l=((long int *)(table+index*(tuple_size)));
233 else insert(key,index);
237 Processes cell - forms record and adds it to table
239 void do_cell(int x,int y)
242 unsigned short int *c=r.classes;
243 for(k=0;k<fileCount;k++,c++) {
245 *c=epp_get(fileinfo[k],linked_col(links[k],x),linked_row(links[k],y));
247 *c=epp_get(fileinfo[k],x,y);
248 if(*c==fileinfo[k]->offsite&&!useOffsite) return;
253 * Print combinations along with cell areas
256 void print_table(void)
260 for(i=0,t=table;i<count;i++,t+=tuple_size) {
261 for(j=0;j<fileCount;j++)
262 printf("%d%c",((struct record *)t)->classes[j],delimiter);
264 printf("%ld\n",((struct record *)t)->count);
266 printf("%0.8g\n",((struct record *)t)->count*cellArea);
270 * Compute functions and print results
274 void init_functions(void)
277 for(i=0,f=funcList;i<funcCount;i++,f++) {
278 f->func(FuncInit,f->data,NULL,f->index);
281 void print_row(struct record *row)
284 /* first, print away all things defining a combination */
285 for(j=0;j<fileCount;j++)
286 printf("%d%c",row->classes[j],delimiter);
287 /* second, compute all functions and print away results */
288 for(j=0,f=funcList;j<funcCount;j++,f++)
289 printf("%g%c",f->func(FuncResult,f->data,row,f->index),
290 j==funcCount-1?'\n':delimiter);
293 void process_table(void)
296 struct record *prev=NULL;
298 /* reset all functions persistend data */
300 fileCount=baseFiles;/* for compare to compare only files,
301 defining combinations*/
302 for(i=0,t=table;i<count;i++,t+=tuple_size) {
303 if (prev&&compare(prev,(struct record *)t)) {
304 /* combination changed, print a row */
308 for (j=0,f=funcList;j<funcCount;j++,f++) {
309 f->func(FuncIterate,f->data,(struct record *)t,f->index);
311 prev=(struct record *)t;
318 int main(int argc, char **argv)
321 scanOpt(&i, argc, argv);
322 parseArgs(i, argc, argv);
324 error("No files specified\n");
326 /* Find out base file */
330 int saveCount=fileCount;
332 base=fileinfo[saveCount];
336 /* Determine cell area */
340 cellArea=base->cell_area;
342 /* establish coordinate links */
343 for (i=0;i<fileCount;i++) {
344 if (is_aligned(base,fileinfo[i])) {
347 links[i]=link_epp(base,fileinfo[i]);
350 /* create table of combinations */
352 tuple_size=2+fileCount;
354 tuple_size=3+fileCount;
358 table=malloc(limit*tuple_size*sizeof(short int));
360 error("Cannot allocate %d records\n",limit);
362 /* iterate through base file */
363 rows=base->lr-base->fr;
364 install_progress_indicator(verbose?show_percent:check_int);
365 for(i=base->fr,k=1;base->lr;i++,k++)
366 { for(j=base->fc;j<base->lc;j++)
368 if (EndLineProc) if ((*EndLineProc)(j,k,rows)) {
376 /* there are some functions. Process them */
382 for(i=0;i<openCount;i++) {
383 close_epp(openFiles[i].epp);