source: PSPA/madxPSPA/tools/numdiff/src/constraint.c @ 430

Last change on this file since 430 was 430, checked in by touze, 11 years ago

import madx-5.01.00

File size: 6.7 KB
Line 
1/*
2 o---------------------------------------------------------------------o
3 |
4 | Numdiff
5 |
6 | Copyright (c) 2012+ laurent.deniau@cern.ch
7 | Gnu General Public License
8 |
9 o---------------------------------------------------------------------o
10 
11   Purpose:
12     create constraints content
13     print, scan constraints from file
14 
15 o---------------------------------------------------------------------o
16*/
17
18#include <assert.h>
19#include <string.h>
20#include <ctype.h>
21#include "constraint.h"
22#include "utils.h"
23#include "error.h"
24#include "args.h"
25
26#define T struct constraint
27
28// ----- constants
29
30const char * const eps_cmd_cstr[] = {
31  [eps_invalid]             = "invalid",
32  [eps_dig]                 = "dig",
33  [eps_rel]                 = "rel",
34  [eps_rel|eps_dig]         = "rel&dig",
35  [eps_abs]                 = "abs",
36  [eps_abs|eps_dig]         = "abs&dig",
37  [eps_abs|eps_rel]         = "abs&rel",
38  [eps_abs|eps_rel|eps_dig] = "abs&rel&dig",
39  [eps_equ]                 = "equ",
40  [eps_ign]                 = "ign",
41  [eps_omit]                = "omit",
42  [eps_skip]                = "skip",
43  [eps_goto]                = "goto",
44};
45
46// ----- private
47
48static void
49printSlc(const struct slice *s, FILE *out)
50{
51  if (slice_first(s) <= 1 && slice_isInfinite(s) && slice_isDense(s)) {
52    putc('*', out);
53    return;
54  }
55
56  fprintf(out, "%u", slice_first(s));
57
58  if (slice_isUnit(s)) return;
59
60  if (slice_isInfinite(s)) {
61    putc('-', out);
62    putc('$', out);
63  } else
64   fprintf(out, "-%u", slice_last(s));
65
66  if (slice_stride(s) != 1)
67    fprintf(out, "/%u", slice_stride(s));   
68}
69
70static int
71readSlcOrRng(struct slice *s, FILE *in)
72{
73  int c, r = 1;
74  uint first=0, last=0, stride=1;
75
76  // skip spaces
77  while((c = getc(in)) != EOF && isblank(c)) ;
78  if (c == EOF) return EOF;
79
80  // ('*'|num)
81  if (c == '*') { last = UINT_MAX; goto finish; }
82  else {
83    ungetc(c, in);
84    if (fscanf(in, "%u", &first) != 1) return EOF;
85  }
86
87  // (':'|'-')?
88  c = getc(in);
89       if (c == ':') r = 0;  // slice
90  else if (c == '-') ;       // range
91  else { ungetc(c, in); last = first; goto finish; }
92
93  // ('$'|num)
94  c = getc(in);
95  if (c == '$') last = UINT_MAX;
96  else {
97    ungetc(c, in);
98    if (fscanf(in, "%u", &last) != 1) return EOF;
99  }
100
101  // ('/'num)?
102  c = getc(in);
103  if (c != '/') { ungetc(c, in); stride = 1; goto finish; }
104  else
105    if (fscanf(in, "%u", &stride) != 1) return EOF;
106
107finish:
108  if (r)
109    *s = slice_initLastStride(first, last, stride);
110  else
111    *s = slice_initSizeStride(first, last, stride);
112
113  trace("<-readSlcOrRng %u%c%u/%u", first, r ? '-' : ':', last, stride);
114
115  return 0;
116}
117
118static int
119readEps(struct eps *e, FILE *in, int row)
120{
121  int c = 0, n = 0, cmd = eps_invalid;
122  char str[16];
123
124  while (1) {
125    // parse next constraint
126    *str = 0;
127    n = fscanf(in, "%*[ \t]%10[^= \t\n\r!#]", str);
128    if (n == EOF || *str == 0) break;
129
130         if (strcmp(str, "skip") == 0) {
131      cmd |= eps_skip; trace("[%d] skip", row);
132    }
133    else if (strcmp(str, "ign") == 0) {
134      cmd |= eps_ign;  trace("[%d] ign", row);
135    }
136    else if (strcmp(str, "equ") == 0) {
137      cmd |= eps_equ;  trace("[%d] equ", row);
138    }
139    else if (strcmp(str, "either") == 0) {
140      e->either = 1;  trace("[%d] either", row);
141    }
142    else if (strcmp(str, "dig") == 0 && (n = fscanf(in, "=%lf", &e->dig)) == 1) {
143      cmd |= eps_dig;  trace("[%d] dig=%g", row, e->dig);
144      ensure(e->dig > 1.0, "invalid digital error (%s.cfg:%d)", option.indexed_filename, row);
145    }
146    else if (strcmp(str, "rel") == 0 && (n = fscanf(in, "=%lf", &e->rel)) == 1) {
147      cmd |= eps_rel;  trace("[%d] rel=%g", row, e->rel);
148      ensure(e->rel > 0.0 && (option.largerr || e->rel < 1.0), "invalid relative constraint (%s.cfg:%d)", option.indexed_filename, row);
149    }
150    else if (strcmp(str, "abs") == 0 && (n = fscanf(in, "=%lf", &e->abs)) == 1) {
151      cmd |= eps_abs;  trace("[%d] abs=%g", row, e->abs);
152      ensure(e->abs > 0.0 && (option.largerr || e->abs < 1.0), "invalid absolute constraint (%s.cfg:%d)", option.indexed_filename, row);
153    }
154    else if (strcmp(str, "omit") == 0 && (n = fscanf(in, "='%48[^']'", e->tag)) == 1) {
155      cmd |= eps_omit | eps_equ; e->tag[sizeof e->tag-1] = 0;
156                       trace("[%d] omit='%s'", row, e->tag);
157      ensure(*e->tag, "invalid empty tag (%s.cfg:%d)", option.indexed_filename, row);
158    }
159    else if (strcmp(str, "goto") == 0 && (n = fscanf(in, "='%48[^']'", e->tag)) == 1) {
160      cmd |= eps_goto; e->tag[sizeof e->tag-1] = 0;
161                       trace("[%d] goto='%s'", row, e->tag);
162      ensure(*e->tag, "invalid empty tag (%s.cfg:%d)", option.indexed_filename, row);
163    }
164    else {
165                       trace("[%d] invalid '%s'", row, str);
166      cmd = eps_invalid;
167      break;
168    }
169
170    // next char
171    ungetc((c = getc(in)), in);
172    if (c == EOF || (isspace(c) && !isblank(c)) || c == '#' || c == '!') break; 
173  }
174
175  e->cmd = (enum eps_cmd)cmd;  // because of icc spurious warnings
176
177  trace("<-readEps cmd = %d, str = '%s', c = '%c'", cmd, str, c);
178
179  return cmd == eps_invalid || n == EOF ? EOF : 0;
180}
181
182// ----- interface
183
184void
185constraint_print(const T* cst, FILE *out)
186{
187  if (!out) out = stdout;
188  if (!cst) { fprintf(out, "(null)"); return; }
189
190  printSlc(&cst->row, out);
191  putc(' ', out);
192  printSlc(&cst->col, out);
193  putc(' ', out);
194
195  if (cst->eps.either)         fprintf(out, "either ");
196  if (cst->eps.cmd & eps_dig)  fprintf(out, "dig=%g ", cst->eps.dig);   
197  if (cst->eps.cmd & eps_rel)  fprintf(out, "rel=%g ", cst->eps.rel);   
198  if (cst->eps.cmd & eps_abs)  fprintf(out, "abs=%g ", cst->eps.abs);   
199  if (cst->eps.cmd & eps_equ)  fprintf(out, "equ ");   
200  if (cst->eps.cmd & eps_ign)  fprintf(out, "ign ");   
201  if (cst->eps.cmd & eps_omit) fprintf(out, "omit='%s' ", cst->eps.tag);
202  if (cst->eps.cmd & eps_skip) fprintf(out, "skip ");   
203  if (cst->eps.cmd & eps_goto) fprintf(out, "goto='%s' ", cst->eps.tag);
204}
205
206void
207constraint_scan(T* cst, FILE *in, int *row)
208{
209  int c;
210  assert(cst && row);
211
212  *cst = (T){ .eps.cmd = (enum eps_cmd)eps_invalid };  // because of icc spurious warnings
213
214  if (!in) in = stdin;
215
216retry:
217
218  while((c = getc(in)) != EOF && isblank(c)) ;
219
220  // end of file
221  if (c == EOF) return;
222
223  ungetc(c, in);
224
225  // comment or empty line
226  if (c == '\n' || c == '\r' || c == '#' || c == '!') {
227    if (skipLine(in, 0) == '\n') ++*row;
228    goto retry;
229  }
230
231  cst->line = *row;
232  ensure(readSlcOrRng(&cst->row, in      ) != EOF, "invalid row range (%s.cfg:%d)"   , option.indexed_filename, *row);
233  ensure(readSlcOrRng(&cst->col, in      ) != EOF, "invalid column range (%s.cfg:%d)", option.indexed_filename, *row);
234  ensure(readEps     (&cst->eps, in, *row) != EOF, "invalid constraint or command (%s.cfg:%d)", option.indexed_filename, *row);
235  if (skipLine(in, 0) == '\n') ++*row;
236}
237
Note: See TracBrowser for help on using the repository browser.