Mercurial > repos > dawe > srf2fastq
comparison srf2fastq/io_lib-1.12.2/progs/convert_trace.c @ 0:d901c9f41a6a default tip
Migrated tool version 1.0.1 from old tool shed archive to new tool shed repository
author | dawe |
---|---|
date | Tue, 07 Jun 2011 17:48:05 -0400 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:d901c9f41a6a |
---|---|
1 #include <stdio.h> | |
2 #include <stdlib.h> | |
3 #include <string.h> | |
4 #include <fcntl.h> | |
5 #include <unistd.h> | |
6 | |
7 #include <io_lib/Read.h> | |
8 #include <io_lib/traceType.h> | |
9 #include <io_lib/seqIOABI.h> | |
10 #include <io_lib/open_trace_file.h> | |
11 | |
12 static char const rcsid[] = "$Id: convert_trace.c,v 1.12 2008-02-20 16:07:44 jkbonfield Exp $"; | |
13 | |
14 #define MAX(a,b) ((a)>(b)?(a):(b)) | |
15 | |
16 struct opts { | |
17 char *name; | |
18 char *fofn; | |
19 char *passed; | |
20 char *failed; | |
21 char *error; | |
22 int in_format; | |
23 int out_format; | |
24 int scale; | |
25 int sub_background; | |
26 int subtract; | |
27 int normalise; | |
28 int min_normalise; | |
29 int compress_mode; | |
30 int dots; | |
31 int noneg; | |
32 int signed_trace; | |
33 int skipx; | |
34 int start; | |
35 int end; | |
36 }; | |
37 | |
38 /* | |
39 * Removes any negative values from a trace by moving each channel | |
40 * independently so that its lowest value is 0. | |
41 */ | |
42 void noneg(Read *r) { | |
43 int i, j, k; | |
44 signed int min; | |
45 TRACE *t; | |
46 | |
47 /* Find the real end of the data */ | |
48 for (k = r->NPoints-1; k >= 0; k--) | |
49 if (r->traceA[k] || | |
50 r->traceC[k] || | |
51 r->traceG[k] || | |
52 r->traceT[k]) | |
53 break; | |
54 | |
55 for (j = 0; j < 4; j++) { | |
56 switch(j) { | |
57 case 0: | |
58 t = r->traceA; | |
59 break; | |
60 case 1: | |
61 t = r->traceC; | |
62 break; | |
63 case 2: | |
64 t = r->traceG; | |
65 break; | |
66 case 3: | |
67 default: | |
68 t = r->traceT; | |
69 break; | |
70 } | |
71 | |
72 /* Find the lowest -ve value per lane */ | |
73 for (min = i = 0; i <= k; i++) { | |
74 if (min > ((int16_t *)t)[i]) | |
75 min = ((int16_t *)t)[i]; | |
76 } | |
77 | |
78 /* And shift everything back up */ | |
79 for (i = 0; i <= k; i++) { | |
80 t[i] -= min; | |
81 } | |
82 } | |
83 } | |
84 | |
85 | |
86 /* | |
87 * Removes any negative values from a trace by moving the trace up so that | |
88 * the lowest overall value is 0. This differs to noneg above by using | |
89 * a global shift for all channels and also setting the read 'baseline'. | |
90 */ | |
91 void signed_trace(Read *r) { | |
92 int i, k; | |
93 signed int min; | |
94 | |
95 /* Find the real end of the data */ | |
96 for (k = r->NPoints-1; k >= 0; k--) | |
97 if (r->traceA[k] || | |
98 r->traceC[k] || | |
99 r->traceG[k] || | |
100 r->traceT[k]) | |
101 break; | |
102 | |
103 /* Find the lowest -ve value per lane */ | |
104 for (min = i = 0; i <= k; i++) { | |
105 if (min > ((int16_t *)(r->traceA))[i]) | |
106 min = ((int16_t *)(r->traceA))[i]; | |
107 if (min > ((int16_t *)(r->traceC))[i]) | |
108 min = ((int16_t *)(r->traceC))[i]; | |
109 if (min > ((int16_t *)(r->traceG))[i]) | |
110 min = ((int16_t *)(r->traceG))[i]; | |
111 if (min > ((int16_t *)(r->traceT))[i]) | |
112 min = ((int16_t *)(r->traceT))[i]; | |
113 } | |
114 | |
115 r->baseline = -min; | |
116 | |
117 /* And shift everything back up */ | |
118 for (i = 0; i <= k; i++) { | |
119 r->traceA[i] -= min; | |
120 r->traceC[i] -= min; | |
121 r->traceG[i] -= min; | |
122 r->traceT[i] -= min; | |
123 } | |
124 } | |
125 | |
126 /* | |
127 * Scales trace values from 0 to scale, but only if they are larger. | |
128 */ | |
129 void rescale_trace(Read *r, int scale) { | |
130 double s; | |
131 int i; | |
132 | |
133 if (r->maxTraceVal <= scale) | |
134 return; | |
135 | |
136 s = ((double)scale)/r->maxTraceVal; | |
137 | |
138 for (i = 0; i < r->NPoints; i++) { | |
139 r->traceA[i] = r->traceA[i] * s + 0.5; | |
140 r->traceC[i] = r->traceC[i] * s + 0.5; | |
141 r->traceG[i] = r->traceG[i] * s + 0.5; | |
142 r->traceT[i] = r->traceT[i] * s + 0.5; | |
143 } | |
144 | |
145 r->maxTraceVal = scale; | |
146 } | |
147 | |
148 #if 0 | |
149 /* OLD method, treats all channels together and assumes the same baseline for | |
150 * each | |
151 */ | |
152 /* | |
153 * Here we just take the minimum trace value and subtract this from all others. | |
154 * The assumption is that the signal will always be 'base line' on at least | |
155 * one of the four channels. | |
156 */ | |
157 void subtract_background(Read *r) { | |
158 int i, min; | |
159 for (i = 0; i < r->NPoints; i++) { | |
160 min = 999999; | |
161 if (r->traceA[i] < min) min = r->traceA[i]; | |
162 if (r->traceC[i] < min) min = r->traceC[i]; | |
163 if (r->traceG[i] < min) min = r->traceG[i]; | |
164 if (r->traceT[i] < min) min = r->traceT[i]; | |
165 r->traceA[i] -= min; | |
166 r->traceC[i] -= min; | |
167 r->traceG[i] -= min; | |
168 r->traceT[i] -= min; | |
169 } | |
170 } | |
171 #endif | |
172 | |
173 static void subtract_background_ch(TRACE *channel, int nchannel) { | |
174 int i, j, bg; | |
175 int win_len = 501, win_len2 = win_len/2; | |
176 TRACE *copy; | |
177 | |
178 if (NULL == (copy = (TRACE *)malloc(sizeof(*copy) * nchannel))) | |
179 return; | |
180 | |
181 if (nchannel < win_len) | |
182 win_len = nchannel; | |
183 | |
184 /* Take lowest background over win_len and subtract it */ | |
185 for (i = 0; i < nchannel; i++) { | |
186 /* Could optimise this considerably */ | |
187 bg = INT_MAX; | |
188 for (j = -win_len2; j < win_len2; j++) { | |
189 if (i+j < 0) continue; | |
190 if (i+j >= nchannel) break; | |
191 | |
192 if (channel[i + j] < bg) | |
193 bg = channel[i + j]; | |
194 } | |
195 | |
196 copy[i] = channel[i] - bg; | |
197 } | |
198 | |
199 memcpy(channel, copy, nchannel * sizeof(*copy)); | |
200 free(copy); | |
201 } | |
202 | |
203 /* | |
204 * Find the average background level of a trace, and subtract this from the | |
205 * peak heights. | |
206 */ | |
207 void subtract_background(Read *r) { | |
208 subtract_background_ch(r->traceA, r->NPoints); | |
209 subtract_background_ch(r->traceC, r->NPoints); | |
210 subtract_background_ch(r->traceG, r->NPoints); | |
211 subtract_background_ch(r->traceT, r->NPoints); | |
212 } | |
213 | |
214 int int_compar(const void *a, const void *b) { | |
215 return *(const TRACE *)a - *(const TRACE *)b; | |
216 } | |
217 | |
218 int find_bg(TRACE *data, int ndata) { | |
219 int i, bg; | |
220 TRACE *copy = (TRACE *)malloc(ndata * sizeof(TRACE)); | |
221 | |
222 /* Sort the trace samples by amplitude */ | |
223 memcpy(copy, data, ndata * sizeof(TRACE)); | |
224 qsort(copy, ndata, sizeof(TRACE), int_compar); | |
225 | |
226 /* Find the first non-zero value */ | |
227 for (i = 0; i < ndata && !copy[i]; i++) | |
228 ; | |
229 | |
230 /* | |
231 * Now take a slie 0.05 through the remainder of the array and set this | |
232 * as our background. | |
233 */ | |
234 bg = copy[(int)((ndata - i) * 0.05 + i)]; | |
235 | |
236 free(copy); | |
237 return bg; | |
238 } | |
239 | |
240 void trace_freq(TRACE *data, int ndata) { | |
241 int i, bg; | |
242 bg = find_bg(data, ndata); | |
243 | |
244 for (i = 0; i < ndata; i++) { | |
245 data[i] = MAX(data[i] - bg, 0); | |
246 } | |
247 } | |
248 | |
249 /* | |
250 * Separates out the dyes using a deconvolution matrix. | |
251 * The order of elements in the matrix is C A G T. | |
252 * A test matrix for the 373. Taken from the BASS distribution. | |
253 */ | |
254 double matrix[5][4] = { | |
255 { 0.002439782, -0.0015053751, 0.00011857301, 2.8906948e-06}, | |
256 {-0.00075353298, 0.0032971052, -0.006198165, 0.00014828549}, | |
257 { 0.00020249287, -0.0017620348, 0.010530438, -0.0020235507 }, | |
258 {-0.001144423, -4.857673e-06, -0.0018845701, 0.00395431 }, | |
259 {-0.12451385, 0.368916, -2.928292, -3.3142638 } | |
260 }; | |
261 void separate_dyes(Read *r, double M[][4]) { | |
262 int i, j; | |
263 | |
264 for (i = 0; i < r->NPoints; i++) { | |
265 int C, A, G, T; | |
266 double sep[4]; | |
267 | |
268 C = r->traceC[i]; | |
269 A = r->traceA[i]; | |
270 G = r->traceG[i]; | |
271 T = r->traceT[i]; | |
272 | |
273 for (j = 0; j < 4; j++) | |
274 sep[j] = C*M[0][j] + A*M[1][j] + G*M[2][j] + T*M[3][j] + M[4][j]; | |
275 | |
276 for (j = 0; j < 4; j++) | |
277 sep[j] += 10; | |
278 | |
279 /* hack! | |
280 sep[0] += 0.1; | |
281 sep[1] += -0.4; | |
282 sep[2] += 2.9; | |
283 sep[3] += 3.2; | |
284 */ | |
285 | |
286 r->traceC[i] = sep[0] < 0 ? 0 : 1000 * sep[0]; | |
287 r->traceA[i] = sep[1] < 0 ? 0 : 1000 * sep[1]; | |
288 r->traceG[i] = sep[2] < 0 ? 0 : 1000 * sep[2]; | |
289 r->traceT[i] = sep[3] < 0 ? 0 : 1000 * sep[3]; | |
290 } | |
291 } | |
292 | |
293 /* | |
294 * Find the maximum height of traces at the called bases. Use this to clip any | |
295 * other bases. | |
296 */ | |
297 void reset_max_called_height(Read *r) { | |
298 int i, max = 0; | |
299 | |
300 /* Find max */ | |
301 for (i=0; i < r->NBases; i++) { | |
302 switch(r->base[i]) { | |
303 case 'a': | |
304 case 'A': | |
305 if (r->traceA[r->basePos[i]] > max) | |
306 max = r->traceA[r->basePos[i]]; | |
307 break; | |
308 | |
309 case 'c': | |
310 case 'C': | |
311 if (r->traceC[r->basePos[i]] > max) | |
312 max = r->traceC[r->basePos[i]]; | |
313 break; | |
314 | |
315 case 'g': | |
316 case 'G': | |
317 if (r->traceG[r->basePos[i]] > max) | |
318 max = r->traceG[r->basePos[i]]; | |
319 break; | |
320 | |
321 case 't': | |
322 case 'T': | |
323 if (r->traceT[r->basePos[i]] > max) | |
324 max = r->traceT[r->basePos[i]]; | |
325 break; | |
326 } | |
327 } | |
328 | |
329 /* Clip to max */ | |
330 for (i = 0; i < r->NPoints; i++) { | |
331 if (r->traceA[i] > max) | |
332 r->traceA[i] = max; | |
333 if (r->traceC[i] > max) | |
334 r->traceC[i] = max; | |
335 if (r->traceG[i] > max) | |
336 r->traceG[i] = max; | |
337 if (r->traceT[i] > max) | |
338 r->traceT[i] = max; | |
339 } | |
340 if (r->maxTraceVal > max) | |
341 r->maxTraceVal = max; | |
342 } | |
343 | |
344 /* | |
345 * Rescales peak heights based on a moving "marker". The marker tracks | |
346 * up and down (attack and decay) based on the difference between itself and | |
347 * the trace envelope. We then divide by the marker value to attempt to | |
348 * normalise peak heights. | |
349 * | |
350 * min_marker is used to avoid scaling up noise and represents the minimum | |
351 * value the marker is allowed to reach. Make sure it is > 0 or divide by | |
352 * zero may occur. | |
353 */ | |
354 void rescale_heights(Read *r, int min_marker) { | |
355 double marker = 0; | |
356 int i, j, max, mtv = 0; | |
357 TRACE *tx[4]; | |
358 | |
359 tx[0] = r->traceA; | |
360 tx[1] = r->traceC; | |
361 tx[2] = r->traceG; | |
362 tx[3] = r->traceT; | |
363 | |
364 for (i = 0; i < r->NPoints; i++) { | |
365 for (max = j = 0; j < 4; j++) | |
366 if (max < tx[j][i]) | |
367 max = tx[j][i]; | |
368 if (!marker) { | |
369 marker = max; | |
370 } else { | |
371 if (max >= marker) { | |
372 /* attack */ | |
373 marker += (max - marker) / 20.0; | |
374 } else { | |
375 /* decay */ | |
376 marker -= (marker - max) / 10.0; | |
377 } | |
378 } | |
379 if (marker < min_marker) | |
380 marker = min_marker; | |
381 | |
382 for (j = 0; j < 4; j++) { | |
383 double new = tx[j][i] * 2000.0/marker; | |
384 tx[j][i] = new > 32767 ? 32767 : new; | |
385 if (mtv < tx[j][i]) | |
386 mtv = tx[j][i]; | |
387 } | |
388 | |
389 } | |
390 | |
391 r->maxTraceVal = mtv; | |
392 } | |
393 | |
394 /* Removes every other sample as a crude way to reduce file size */ | |
395 void skipx(Read *r) { | |
396 int i, j; | |
397 for (i = j = 0; j < r->NPoints/2; i+=2, j++) { | |
398 r->traceA[j] = (r->traceA[i] + r->traceA[i+1]) / 2; | |
399 r->traceC[j] = (r->traceC[i] + r->traceC[i+1]) / 2; | |
400 r->traceG[j] = (r->traceG[i] + r->traceG[i+1]) / 2; | |
401 r->traceT[j] = (r->traceT[i] + r->traceT[i+1]) / 2; | |
402 } | |
403 r->NPoints = j; | |
404 | |
405 for (i = 0; i < r->NBases; i++) { | |
406 r->basePos[i] /= 2; | |
407 } | |
408 } | |
409 | |
410 void clip_range(Read *r, int left, int right) { | |
411 int i, j; | |
412 if (left != -1) { | |
413 for (i = 0, j = left; j < r->NPoints; i++, j++) { | |
414 r->traceA[i] = r->traceA[j]; | |
415 r->traceC[i] = r->traceC[j]; | |
416 r->traceG[i] = r->traceG[j]; | |
417 r->traceT[i] = r->traceT[j]; | |
418 } | |
419 right -= left; | |
420 } | |
421 if (right > 0) { | |
422 r->NPoints = right; | |
423 } | |
424 } | |
425 | |
426 | |
427 int convert(mFILE *infp, mFILE *outfp, char *infname, char *outfname, | |
428 struct opts *opts) { | |
429 Read *r; | |
430 | |
431 if (NULL == (r = mfread_reading(infp, infname, opts->in_format))) { | |
432 fprintf(stderr, "failed to read file %s\n", infname); | |
433 return 1; | |
434 } | |
435 | |
436 if (opts->start != -1 || opts->end != -1) | |
437 clip_range(r, opts->start, opts->end); | |
438 | |
439 if (opts->skipx) { | |
440 skipx(r); | |
441 } | |
442 | |
443 if (opts->noneg) | |
444 noneg(r); | |
445 | |
446 if (opts->signed_trace) | |
447 signed_trace(r); | |
448 | |
449 if (opts->subtract) { | |
450 int i; | |
451 for (i = 0; i < r->NPoints; i++) { | |
452 r->traceA[i] = MAX(0, r->traceA[i] - opts->subtract); | |
453 r->traceC[i] = MAX(0, r->traceC[i] - opts->subtract); | |
454 r->traceG[i] = MAX(0, r->traceG[i] - opts->subtract); | |
455 r->traceT[i] = MAX(0, r->traceT[i] - opts->subtract); | |
456 } | |
457 } | |
458 | |
459 if (opts->sub_background) { | |
460 /* | |
461 trace_freq(r->traceA, r->NPoints); | |
462 trace_freq(r->traceC, r->NPoints); | |
463 trace_freq(r->traceG, r->NPoints); | |
464 trace_freq(r->traceT, r->NPoints); | |
465 */ | |
466 subtract_background(r); | |
467 /* | |
468 separate_dyes(r, matrix); | |
469 trace_freq(r->traceA, r->NPoints); | |
470 trace_freq(r->traceC, r->NPoints); | |
471 trace_freq(r->traceG, r->NPoints); | |
472 trace_freq(r->traceT, r->NPoints); | |
473 */ | |
474 reset_max_called_height(r); | |
475 } | |
476 | |
477 if (opts->normalise) { | |
478 rescale_heights(r, opts->min_normalise); | |
479 } | |
480 | |
481 if (opts->scale) { | |
482 rescale_trace(r, opts->scale); | |
483 } | |
484 | |
485 if (opts->name) | |
486 r->ident = strdup(opts->name); | |
487 else if (0 == strcmp(outfname, "(stdout)")) | |
488 r->ident = strdup(infname); | |
489 else | |
490 r->ident = strdup(outfname); | |
491 | |
492 if (opts->compress_mode != -1) | |
493 set_compression_method(opts->compress_mode); | |
494 | |
495 if (0 != (mfwrite_reading(outfp, r, opts->out_format))) { | |
496 fprintf(stderr, "failed to write file %s\n", outfname); | |
497 read_deallocate(r); | |
498 return 1; | |
499 } | |
500 | |
501 read_deallocate(r); | |
502 return 0; | |
503 } | |
504 | |
505 | |
506 void usage(void) { | |
507 puts("Usage: convert_trace [options] [informat outformat] < in > out"); | |
508 puts("Or convert_trace [options] -fofn file_of_filenames"); | |
509 puts("\nOptions are:"); | |
510 puts(" -in_format format Format for input (defaults to any"); | |
511 puts(" -out_format format Format for output (default ztr)"); | |
512 puts(" -fofn file_of_filenames Get \"Input Output\" names from a fofn"); | |
513 puts(" -passed fofn Output fofn of passed names"); | |
514 puts(" -error errs Redirect stderr to file \"errs\""); | |
515 puts(" -failed fofn Output fofn of failed names"); | |
516 puts(" -name id ID line for experiment file output"); | |
517 puts(" -subtract_background Auto-subtracts the trace background"); | |
518 puts(" -subtract amount Subtracts a specified background amount"); | |
519 puts(" -normalise Normalises peak heights"); | |
520 puts(" -min_normalise Minimum trace amp for normalising"); | |
521 puts(" -scale range Downscales peaks to 0-range"); | |
522 puts(" -compress mode Compress file output (not if stdout)"); | |
523 puts(" -abi_data counts ABI DATA lanes to copy: eg 9,10,11,12"); | |
524 puts(" -signed Apply global shift to avoid negative values"); | |
525 puts(" -noneg Shift each channel independently to avoid -ve"); | |
526 puts(" -- Explicitly state end of options"); | |
527 exit(1); | |
528 } | |
529 | |
530 int main(int argc, char **argv) { | |
531 struct opts opts; | |
532 | |
533 opts.in_format = TT_ANY; | |
534 opts.out_format = TT_ZTR; | |
535 opts.scale = 0; | |
536 opts.sub_background = 0; | |
537 opts.subtract = 0; | |
538 opts.normalise = 0; | |
539 opts.min_normalise = 100; | |
540 opts.name = NULL; | |
541 opts.compress_mode = -1; | |
542 opts.dots = 0; | |
543 opts.noneg = 0; | |
544 opts.signed_trace = 0; | |
545 opts.fofn = NULL; | |
546 opts.passed = NULL; | |
547 opts.failed = NULL; | |
548 opts.error = NULL; | |
549 opts.skipx = 0; | |
550 opts.start = -1; | |
551 opts.end = -1; | |
552 | |
553 for (argc--, argv++; argc > 0; argc--, argv++) { | |
554 if (**argv != '-') | |
555 break; | |
556 | |
557 if (strcmp(*argv, "-start") == 0) { | |
558 opts.start = atoi(*++argv); | |
559 argc--; | |
560 | |
561 } else if (strcmp(*argv, "-end") == 0) { | |
562 opts.end = atoi(*++argv); | |
563 argc--; | |
564 | |
565 } else if (strcmp(*argv, "-scale") == 0) { | |
566 opts.scale = atoi(*++argv); | |
567 argc--; | |
568 | |
569 } else if (strcmp(*argv, "-fofn") == 0) { | |
570 opts.fofn = *++argv; | |
571 argc--; | |
572 | |
573 } else if (strcmp(*argv, "-passed") == 0) { | |
574 opts.passed = *++argv; | |
575 argc--; | |
576 | |
577 } else if (strcmp(*argv, "-failed") == 0) { | |
578 opts.failed = *++argv; | |
579 argc--; | |
580 | |
581 } else if (strcmp(*argv, "-error") == 0) { | |
582 opts.error = *++argv; | |
583 argc--; | |
584 | |
585 } else if (strcmp(*argv, "-subtract_background") == 0) { | |
586 opts.sub_background = 1; | |
587 | |
588 } else if (strcmp(*argv, "-subtract") == 0) { | |
589 opts.subtract = atoi(*++argv); | |
590 argc--; | |
591 | |
592 } else if (strcmp(*argv, "-normalise") == 0) { | |
593 opts.normalise = 1; | |
594 | |
595 } else if (strcmp(*argv, "-min_normalise") == 0) { | |
596 opts.min_normalise = atoi(*++argv); | |
597 argc--; | |
598 | |
599 } else if (strcmp(*argv, "-dots") == 0) { | |
600 opts.dots = 1; | |
601 | |
602 } else if (strcmp(*argv, "-noneg") == 0) { | |
603 opts.noneg = 1; | |
604 | |
605 } else if (strcmp(*argv, "-signed") == 0) { | |
606 opts.signed_trace = 1; | |
607 | |
608 } else if (strcmp(*argv, "-skipx") == 0) { | |
609 opts.skipx = 1; | |
610 | |
611 } else if (strcmp(*argv, "-in_format") == 0) { | |
612 argv++; | |
613 argc--; | |
614 if (TT_UNK == (opts.in_format = trace_type_str2int(*argv))) | |
615 opts.in_format = atoi(*argv); | |
616 | |
617 } else if (strcmp(*argv, "-name") == 0) { | |
618 opts.name = *++argv; | |
619 argc--; | |
620 | |
621 } else if (strcmp(*argv, "-out_format") == 0) { | |
622 argv++; | |
623 argc--; | |
624 if (TT_UNK == (opts.out_format = trace_type_str2int(*argv))) | |
625 opts.out_format = atoi(*argv); | |
626 | |
627 } else if (strcmp(*argv, "-compress") == 0) { | |
628 opts.compress_mode = compress_str2int(*++argv); | |
629 argc--; | |
630 | |
631 } else if (strcmp(*argv, "-abi_data") == 0) { | |
632 int c1, c2, c3, c4; | |
633 argc--; | |
634 if (4 == sscanf(*++argv, "%d,%d,%d,%d", &c1, &c2, &c3, &c4)) { | |
635 abi_set_data_counts(c1, c2, c3, c4); | |
636 } else { | |
637 usage(); | |
638 } | |
639 | |
640 } else if (strcmp(*argv, "--") == 0) { | |
641 break; | |
642 | |
643 } else { | |
644 usage(); | |
645 } | |
646 } | |
647 | |
648 if (argc == 2) { | |
649 /* Old syntax, for backwards compatibility */ | |
650 | |
651 if (TT_UNK == (opts.in_format = trace_type_str2int(argv[0]))) | |
652 opts.in_format = atoi(argv[0]); | |
653 if (TT_UNK == (opts.out_format = trace_type_str2int(argv[1]))) | |
654 opts.out_format = atoi(argv[1]); | |
655 } else if (argc != 0) { | |
656 usage(); | |
657 } | |
658 | |
659 | |
660 /* | |
661 * Added by SAK: Allow redirection of error output to file, due to | |
662 * problems with Java exec | |
663 */ | |
664 if (NULL != opts.error) { | |
665 int fd; | |
666 | |
667 fprintf(stderr,"* Redirecting stderr to %s\n", opts.error); | |
668 | |
669 close(2); /* close fd with stderr */ | |
670 if (-1 == (fd = creat(opts.error, 0666))) { | |
671 exit(1); | |
672 } | |
673 } | |
674 | |
675 if (!opts.fofn) { | |
676 return convert(mstdin(), mstdout(), "(stdin)", "(stdout)", &opts); | |
677 } | |
678 | |
679 /* else */ { | |
680 mFILE *fpin, *fpout; | |
681 FILE *fppassed = NULL, *fpfailed = NULL; | |
682 char *infname, *outfname; | |
683 int ret, ret_all = 0; | |
684 char line[8192], line2[8192]; | |
685 | |
686 FILE *fofn_fp; | |
687 | |
688 if (NULL == (fofn_fp = fopen(opts.fofn, "r"))) { | |
689 perror(opts.fofn); | |
690 return -1; | |
691 } | |
692 | |
693 if (opts.passed && NULL == (fppassed = fopen(opts.passed, "w"))) { | |
694 perror(opts.passed); | |
695 return -1; | |
696 } | |
697 | |
698 if (opts.failed && NULL == (fpfailed = fopen(opts.failed, "w"))) { | |
699 perror(opts.failed); | |
700 return -1; | |
701 } | |
702 | |
703 while (fgets(line, 8192, fofn_fp) != NULL) { | |
704 int i, j, len; | |
705 | |
706 /* Find input and output name, escaping spaces as needed */ | |
707 len = strlen(line); | |
708 outfname = NULL; | |
709 for (i = j = 0; i < len; i++) { | |
710 if (line[i] == '\\' && i != len-1) { | |
711 line2[j++] = line[++i]; | |
712 } else if (line[i] == ' ') { | |
713 line2[j++] = 0; | |
714 outfname = &line2[j]; | |
715 } else if (line[i] != '\n') { | |
716 line2[j++] = line[i]; | |
717 } | |
718 } | |
719 line2[j] = 0; | |
720 infname = line2; | |
721 | |
722 /* Don't clobber input */ | |
723 if (!strcmp(infname, outfname)) { | |
724 fprintf(stderr,"* Inputfn %s == Outputfn %s ...skipping\n", | |
725 infname, outfname); | |
726 if (fpfailed) | |
727 fprintf(fpfailed, "%s\n", infname); | |
728 continue; | |
729 } | |
730 | |
731 /* Open input and output files */ | |
732 if (opts.in_format == TT_EXP) { | |
733 fpin = open_exp_mfile(infname, NULL); | |
734 } else { | |
735 fpin = open_trace_mfile(infname, NULL); | |
736 } | |
737 if (NULL == fpin) { | |
738 char buf[2048]; | |
739 sprintf(buf, "ERROR %s", infname); | |
740 perror(buf); | |
741 if (opts.dots) { | |
742 fputc('!', stdout); | |
743 fflush(stdout); | |
744 } | |
745 if (fpfailed) | |
746 fprintf(fpfailed, "%s\n", infname); | |
747 continue; | |
748 } | |
749 | |
750 if (outfname) { | |
751 if (NULL == (fpout = mfopen(outfname, "wb+"))) { | |
752 char buf[2048]; | |
753 sprintf(buf, "ERROR %s", outfname); | |
754 perror(buf); | |
755 mfclose(fpin); | |
756 if (opts.dots) { | |
757 fputc('!', stdout); | |
758 fflush(stdout); | |
759 } | |
760 if (fpfailed) | |
761 fprintf(fpfailed, "%s\n", infname); | |
762 continue; | |
763 } | |
764 } else { | |
765 outfname = "(stdout)"; | |
766 fpout = mstdout(); | |
767 } | |
768 | |
769 /* Convert */ | |
770 ret = convert(fpin, fpout, infname, outfname, &opts); | |
771 ret_all |= ret; | |
772 if (opts.dots) { | |
773 fputc(ret ? '!' : '.', stdout); | |
774 fflush(stdout); | |
775 } | |
776 if (ret) { | |
777 if (fpfailed) | |
778 fprintf(fpfailed, "%s\n", infname); | |
779 } else { | |
780 if (fppassed) | |
781 fprintf(fppassed, "%s\n", infname); | |
782 } | |
783 | |
784 /* Tidy up */ | |
785 mfclose(fpin); | |
786 if (fpout != mstdout()) | |
787 mfclose(fpout); | |
788 } | |
789 | |
790 fclose(fofn_fp); | |
791 | |
792 return ret_all; | |
793 } | |
794 } |