aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas White <taw@physics.org>2011-06-08 17:25:01 +0200
committerThomas White <taw@physics.org>2012-02-22 15:27:28 +0100
commit665f9722d96642000f9821c28f0c3fceb2406b10 (patch)
treeef6a32c67c1448dfe9bb02a1c7926850d276555d
parent60572e7d69ffda00c7738168c0cd8ed83c3fb363 (diff)
Tidy up parser and add lots of checks
-rw-r--r--src/detector.c239
1 files changed, 109 insertions, 130 deletions
diff --git a/src/detector.c b/src/detector.c
index 5df070b6..ce62d72b 100644
--- a/src/detector.c
+++ b/src/detector.c
@@ -16,6 +16,7 @@
#include <stdio.h>
#include <string.h>
#include <assert.h>
+#include <ctype.h>
#include "image.h"
#include "utils.h"
@@ -33,119 +34,137 @@ static int atob(const char *a)
}
-static int dir_conv_extract_coeff(const char *a, int *sign, int *axis,
- double *coeff)
+static int assplode_algebraic(const char *a_orig, char ***pbits)
{
- int len;
- int index = 1;
- char tempstr[len];
- double test=0.0;
- int i;
+ int len, i;
+ int nexp;
+ char **bits;
+ char *a;
+ int idx, istr;
+
+ len = strlen(a_orig);
- len = strlen(a);
- for ( i=0; i<len-1; i++ ) tempstr[i] = '0';
- tempstr[len-1] = '\0';
+ /* Add plus at start if no sign there already */
+ if ( (a_orig[0] != '+') && (a_orig[0] != '-') ) {
+ len += 1;
+ a = malloc(len+1);
+ snprintf(a, len+1, "+%s", a_orig);
+ a[len] = '\0';
- if ( a[0] == '+') {
- *sign = 1;
- printf("found +\n");
- } else if ( strcmp(&a[0],"-") == 0 ) {
- *sign = -1;
- printf("found -\n");
} else {
- *sign = 1;
- index = 0;
+ a = strdup(a_orig);
}
- if ( (len - index) < 2 ) {
+ /* Count the expressions */
+ nexp = 0;
+ for ( i=0; i<len; i++ ) {
+ if ( (a[i] == '+') || (a[i] == '-') ) nexp++;
+ }
- *coeff = 1.0;
+ bits = calloc(nexp, sizeof(char *));
- } else if ( (len - index) > 2 ) {
+ /* Break the string up */
+ idx = -1;
+ istr = 0;
+ assert((a[0] == '+') || (a[0] == '-'));
+ for ( i=0; i<len; i++ ) {
- if (index == 0 ) {
- strncpy(tempstr,a,len-2);
- } else {
- strncpy(tempstr,a+1,len-2);
+ char ch;
+
+ ch = a[i];
+
+ if ( (ch == '+') || (ch == '-') ) {
+ if ( idx >= 0 ) bits[idx][istr] = '\0';
+ idx++;
+ bits[idx] = malloc(len+1);
+ istr = 0;
}
- tempstr[len] = '\0';
- test = atof(tempstr);
- *coeff = test;
+ if ( !isdigit(ch) && (ch != '.') && (ch != 'x') && (ch != 'y')
+ && (ch != '+') && (ch != '-') )
+ {
+ ERROR("Invalid character '%C' found.\n", ch);
+ return 0;
+ }
- }
+ assert(idx >= 0);
+ bits[idx][istr++] = ch;
- if ( a[len-1] == 'x' ) {
- *axis = 1;
- } else if ( a[len-1] == 'y' ) {
- *axis = 0;
}
+ if ( idx >= 0 ) bits[idx][istr] = '\0';
- return 0;
+ *pbits = bits;
+ free(a);
+
+ return nexp;
}
-/* Parses the scan directions (accounting for possible rotation) */
-/* Assumes all white spaces have been already removed */
-/* FIXME: doesn't handle many errors */
+/* Parses the scan directions (accounting for possible rotation)
+ * Assumes all white spaces have been already removed */
static int dir_conv(const char *a, double *sx, double *sy)
{
- int n1;
+ int n;
char **bits;
- int axis = 2;
- int sign = 0;
- double coeff = 0.0;
- int index = 1;
-
- n1 = assplode(a, "+-\t", &bits, ASSPLODE_NONE);
+ int i;
- /* Parse the first entry */
- dir_conv_extract_coeff(bits[0], &sign, &axis, &coeff) ;
+ *sx = 0.0; *sy = 0.0;
- if ( a[0] == '+') {
- sign = 1;
- } else if ( a[0] == '-' ) {
- sign = -1;
- } else {
- sign = 1;
- index = 0;
- }
+ n = assplode_algebraic(a, &bits);
- if ( axis == 1 ) {
- *sx = sign*coeff;
- *sy = 0.0;
- } else if (axis == 0) {
- *sx = 0.0;
- *sy = sign*coeff;
- } else {
- printf("testing ; axis %d\n", axis);
+ if ( n == 0 ) {
+ ERROR("Invalid direction '%s'\n", a);
return 1;
}
- index += strlen(bits[0]);
+ for ( i=0; i<n; i++ ) {
- /* Now parse the second part if it exist s*/
- if ( n1 == 2 ) {
+ int len;
+ double val;
+ char axis;
+ int j;
- dir_conv_extract_coeff(bits[1], &sign, &axis, &coeff) ;
+ len = strlen(bits[i]);
+ assert(len != 0);
+ axis = bits[i][len-1];
+ if ( (axis != 'x') && (axis != 'y') ) {
+ ERROR("Invalid symbol '%C' - must be x or y.\n", axis);
+ return 1;
+ }
- if ( a[index] == '+' ) {
- sign = 1;
- } else if ( a[index] == '-' ) {
- sign = -1;
- } else {
- sign = 1;
+ /* Chop off the symbol now it's dealt with */
+ bits[i][len-1] = '\0';
+
+ /* Check for anything that isn't part of a number */
+ for ( j=0; j<strlen(bits[i]); j++ ) {
+ if ( isdigit(bits[i][j]) ) continue;
+ if ( bits[i][j] == '+' ) continue;
+ if ( bits[i][j] == '-' ) continue;
+ if ( bits[i][j] == '.' ) continue;
+ ERROR("Invalid coefficient '%s'\n", bits[i]);
}
- if ( axis == 1 ) {
- *sx = sign*coeff;
- } else if ( axis == 0 ) {
- *sy = sign*coeff;
+ if ( strlen(bits[i]) == 0 ) {
+ val = 1.0;
} else {
- return 1;
+ val = atof(bits[i]);
+ }
+ if ( strlen(bits[i]) == 1 ) {
+ if ( bits[i][0] == '+' ) val = 1.0;
+ if ( bits[i][0] == '-' ) val = -1.0;
+ }
+ if ( axis == 'x' ) {
+ *sx += val;
+ } else if ( axis == 'y' ) {
+ *sy += val;
}
+ free(bits[i]);
+
}
+ free(bits);
+
+ //STATUS("'%s' -> %5.2fx + %5.2fy\n", a, *sx, *sy);
return 0;
}
@@ -535,14 +554,12 @@ static int parse_field_for_panel(struct panel *panel, const char *key,
panel->no_index = atob(val);
} else if ( strcmp(key, "fs") == 0 ) {
if ( dir_conv(val, &panel->fsx, &panel->fsy) != 0 ) {
- ERROR("Invalid fast scan direction '%s'\n",
- val);
+ ERROR("Invalid fast scan direction '%s'\n", val);
reject = 1;
}
} else if ( strcmp(key, "ss") == 0 ) {
if ( dir_conv(val, &panel->ssx, &panel->ssy) != 0 ) {
- ERROR("Invalid slow scan direction '%s'\n",
- val);
+ ERROR("Invalid slow scan direction '%s'\n", val);
reject = 1;
}
} else {
@@ -599,7 +616,7 @@ static void parse_toplevel(struct detector *det, const char *key,
det->mask_good = v;
}
- } else if ( strcmp(key, "peak_sep") == 0 ) {
+ } else if ( strcmp(key, "peak_sep") == 0 ) {
det->defaults.peak_sep = atof(val);
} else if ( strcmp(key, "integr_radius") == 0 ) {
det->defaults.integr_radius = atof(val);
@@ -615,7 +632,6 @@ struct detector *get_detector_geometry(const char *filename)
struct detector *det;
char *rval;
char **bits;
- char variable[128];
int i;
int reject = 0;
int x, y, max_fs, max_ss;
@@ -629,11 +645,6 @@ struct detector *get_detector_geometry(const char *filename)
return NULL;
}
- variable[0] = '\0';
- /*for (i=0;i<128;i++){
- variable[i] = 'a';
- } */
-
det->n_panels = 0;
det->panels = NULL;
det->n_bad = 0;
@@ -670,6 +681,7 @@ struct detector *get_detector_geometry(const char *filename)
struct badregion *badregion = NULL;
struct panel *panel = NULL;
char *key;
+ char wholeval[1024];
rval = fgets(line, 1023, fh);
if ( rval == NULL ) break;
@@ -684,12 +696,11 @@ struct detector *get_detector_geometry(const char *filename)
continue;
}
- /* Remove the blank spaces from the input */
- strcpy(variable,bits[2]);
- if ( n1 > 3 ) {
- for ( i=3; i<n1; i++ ) {
- strcat(variable,bits[i]);
- }
+ /* Stitch the pieces of the "value" back together */
+ wholeval[0] = '\0'; /* Empty string */
+ for ( i=2; i<n1; i++ ) {
+ if ( bits[i][0] == ';' ) break; /* Stop on comment */
+ strncat(wholeval, bits[i], 1023);
}
if ( bits[1][0] != '=' ) {
@@ -724,11 +735,11 @@ struct detector *get_detector_geometry(const char *filename)
key = path[1];
if ( panel != NULL ) {
- if ( parse_field_for_panel(panel, path[1], variable) ) {
+ if ( parse_field_for_panel(panel, path[1], wholeval) ) {
reject = 1;
}
} else {
- if ( parse_field_bad(badregion, path[1], variable) ) {
+ if ( parse_field_bad(badregion, path[1], wholeval) ) {
reject = 1;
}
}
@@ -1105,8 +1116,6 @@ int write_detector_geometry(const char *filename, struct detector *det)
for ( pi=0; pi<det->n_panels; pi++) {
- char signx,signy;
-
p = &(det->panels[pi]);
if ( p == NULL ) return 4;
@@ -1119,38 +1128,8 @@ int write_detector_geometry(const char *filename, struct detector *det)
fprintf(fh, "%s/res = %g\n", p->name, p->res);
fprintf(fh, "%s/peak_sep = %g\n", p->name, p->peak_sep);
fprintf(fh, "%s/clen = %s\n", p->name, p->clen_from);
-
- if ( p->fsx >= 0 ) {
- signx='+';
- } else {
- signx=' ';
- }
-
-
- if ( p->fsy >= 0 ) {
- signy='+';
- } else {
- signy=' ';
- }
-
- fprintf(fh, "%s/fs = %C%fx%C%fy\n", p->name,
- signx, p->fsx, signy, p->fsy);
-
- if ( p->ssx >= 0 ) {
- signx='+';
- } else {
- signx=' ';
- }
-
- if ( p->ssy >= 0 ) {
- signy='+';
- } else {
- signy=' ';
- }
-
- fprintf(fh, "%s/ss = %C%fx%C%fy\n", p->name,
- signx, p->ssx, signy, p->ssy);
-
+ fprintf(fh, "%s/fs = %+fx %+fy\n", p->name, p->fsx, p->fsy);
+ fprintf(fh, "%s/ss = %+fx %+fy\n", p->name, p->ssx, p->ssy);
fprintf(fh, "%s/corner_x = %g\n", p->name, p->cnx);
fprintf(fh, "%s/corner_y = %g\n", p->name, p->cny);
fprintf(fh, "%s/no_index = %d\n", p->name, p->no_index);