HOPS
HOPS class reference
frqsupport.h
Go to the documentation of this file.
1 /*
2  * Parser support for frqs as an alias for freqs
3  *
4  * This file contains code to parse a frqstyle frequency code list.
5  * There are two usages: after 'frqs' in which case we need to interpret
6  * the string and walk through the parser steps of code setup. OR,
7  * in most other places, interpret a frqstyle frequency code list
8  * for use with other parameters.
9  *
10  * Code is inserted if ALLOW_FRQS_CODE is defined; otherwise
11  * this is a header file for required routines (if needed outside
12  * of parser, which is not very likely).
13  */
14 #ifndef frqsupport_h
15 #define frqsupport_h
16 /*
17  * First the header info, if any, then code within ALLOW_FRQS_CODE
18  */
19 
20 #if defined(ALLOW_FRQS_CODE)
21 /* for code legality checking */
22 static char fchars[] = FCHARS;
23 
24 /* convenience for readable code */
25 #define FREE_DEST_RETURN(MSG,PRI,VAL) do { \
26  msg(MSG,PRI,VAL); free(dest); return(NULL); } while(0)
27 /* expansion case: A~B -> A..B; @|N -> @@@..@ */
28 static char *frqs_expand_notches(char *chans, char *master)
29 {
30  char *dest = calloc(MAXNOTCH+1, sizeof(char)), *scp, *dcp;
31  msg("FRQS: frqs_expand_notches(%s) -- input",1,chans);
32  if (!dest) {
33  perror("malloc");
34  return(NULL);
35  }
36  /* increment of scp may be more, depending */
37  for (scp = chans, dcp = dest; *scp; scp++) {
38  if (*scp == '~') { // expand
39  char *aa, *bb;
40  aa = strchr(master, scp[-1]);
41  if (!aa) FREE_DEST_RETURN("~ at start of string or after @!",3,0);
42  else if (scp[1] == '\0')
43  FREE_DEST_RETURN("~ at end of string or followed by @!",3,0);
44  bb = strchr(master, scp[1]);
45  if (!bb) FREE_DEST_RETURN("Odd, %c not in codes",3,*scp);
46  while (*(++aa) != *bb && (*aa))
47  *dcp++ = *aa; // pull next char from master codes
48  // bb will be inserted next iteration
49  } else if (scp[0] == '@' && scp[1] == '|') { // N @
50  int nn = atoi(scp+2);
51  if (!isdigit(scp[2]))
52  FREE_DEST_RETURN("@| followed by non-digit: %s!",3,scp);
53  /* advance past @|N or @|NN -- one less than auto-increment */
54  if (nn < 9) scp += 2; else scp += 3;
55  while (nn-- > 0)
56  *dcp++ = '@';
57  } else {
58  *dcp++ = *scp;
59  }
60  }
61  msg("FRQS: frqs_expand_notches(%s) -- output",1,dest);
62  return(dest);
63 }
64 #undef FREE_DEST_RETURN
65 
66 /* convenience for readable code */
67 #define FREE_CHANS_RETURN(MSG,PRI,VAL,XIT) do { \
68  msg(MSG,PRI,VAL); \
69  if(chans != ochans) free(chans); return(XIT); } while(0)
70 /* handler for chan_notches case: expansion, checking, and insertion */
71 int frqs_chan_notches(char *chans, char *master, struct c_block *cb_ptr)
72 {
73  char *ochans = chans, *fcp, *ncp;
74  msg("FRQS: frqs_chan_notches(%s) -- input",1,chans);
75  /* consider expansion cases */
76  if (strchr(chans, '@') || strchr(chans, '|') || strchr(chans, '~')) {
77  chans = frqs_expand_notches(chans, master);
78  if (!chans) return(-1);
79  }
80  if (strlen(chans) > cb_ptr->nnotches)
81  FREE_CHANS_RETURN("Too many chan_notches %d",3,strlen(chans),-2);
82  /* check and insert each freq code */
83  for (fcp = chans, ncp = cb_ptr->chan_notches; *fcp; fcp++, ncp++) {
84  if (*fcp != '@' && !strchr(master, *fcp))
85  FREE_CHANS_RETURN("Channel %c is not active?",3,*fcp,-3);
86  *ncp = *fcp;
87  }
88  /* (if expanded) free the expanded string and return success */
89  cb_ptr->chan_notches[cb_ptr->nnotches] = '\0';
90  msg("FRQS: frqs_chan_notches(%s) -- output",1,cb_ptr->chan_notches);
91  if (chans != ochans) free(chans);
92  return(0);
93 }
94 #undef FREE_DEST_RETURN
95 
96 /* propagate clone and chid updates through all blocks */
97 static void frqs_clone_clones(struct c_block *cond_start, int havechid)
98 {
99  struct c_block *cb_ptr;
100  int jj, nn = strlen(cond_start->chid);
101  for (cb_ptr=cond_start; cb_ptr!=NULL; cb_ptr=cb_ptr->cb_chain) {
102  strcpy(cb_ptr->clones[0], cond_start->clones[0]);
103  strcpy(cb_ptr->clones[1], cond_start->clones[1]);
104  strcpy(cb_ptr->chid, cond_start->chid);
105  for (jj = 0; jj < nn; jj++)
106  cb_ptr->chid_rf[jj] = cond_start->chid_rf[jj];
107  }
108 }
109 
110 /* this is called on the string after CLONE_IDS_. */
111 static int frqs_clone_ids(char *cinfo,char *master, struct c_block *cond_start)
112 {
113  int clen = strlen(cinfo), ncan = clen/2, havechid, ii, mclen;
114  char *clones = cinfo + ncan, *cand, *copy;
115  int ndx[MAXFREQ/2], kk;
116  msg("FRQS: frqs_clone_ids '%s' -- input",1,cinfo);
117  /* first check the length */
118  if (2*(ncan) != clen || ncan >= MAXFREQ/2) {
119  msg("Clone string length issues (%d is not 2*%d or > %d)", 3,
120  clen, ncan, MAXFREQ/2);
121  return(-1);
122  }
123  /* then check to see if chids were populated as chid_rf must match */
124  havechid = (cond_start->chid_rf[0] != 0.0) ? 1 : 0;
125  mclen = strlen(master);
126  /* if havechid, then master codes and cond_start->chid should be same */
127  if (havechid) {
128  if (strlen(cond_start->chid) != mclen) {
129  msg("chan_ids was used but illegally (%d != %d, cannot clone", 3,
130  strlen(cond_start->chid), mclen);
131  return(-2);
132  }
133  }
134  /* now check that all the candidates are in master codes */
135  /* while we are in there, capture index in master codes */
136  for (ii = 0, cand = cinfo; cand - cinfo < ncan; cand++) {
137  copy = strchr(master, *cand);
138  if (!copy) {
139  msg("clone candidate %c not in code list, cannot clone", 3, cand);
140  return(-3);
141  }
142  ndx[ii++] = copy - master;
143  }
144  /* if chids were used, then can also check that new names are not */
145  /* either way, we need to make sure the new names are legal */
146  for (cand = clones; cand - clones < ncan; cand++) {
147  if (havechid && strchr(master, *cand)) {
148  msg("clone alias %c is already used, cannot clone", 3, cand);
149  return(-4);
150  }
151  if (!strchr(fchars, *cand)) {
152  msg("clone code %c is not legal, cannot clone", 3, cand);
153  }
154  }
155  /* Ok, install the aliases, and if chids used, copy the freq as well */
156  for (ii = 0; ii < ncan; ii++) {
157  /* the clones */
158  cond_start->clones[1][ii] = clones[ii];
159  cond_start->clones[0][ii] = cinfo[ii]; /* the clone sources */
160  if (havechid && mclen < MAXFREQ) {
161  // adjust cond_start->chid and master codes synchronously
162  kk = mclen+ii;
163  if (kk > MAXFREQ) {
164  msg("No more room for codes starting with %c", 3, clones[ii]);
165  return(-6);
166  }
167  cond_start->chid[kk] = clones[ii];
168  cond_start->chid_rf[kk] = cond_start->chid_rf[ndx[ii]];
169  master[kk] = clones[ii];
170  // null termination for string usages
171  cond_start->chid[kk+1] = master[kk+1] = 0;
172  msg("short master code path %d\n%s: of %s (freq %f)", 1,
173  kk, progname, master, cond_start->chid_rf[kk]);
174  } else { // using all codes; have to find rather than append
175  kk = fcode(clones[ii], master);
176  if (kk<0 || kk>MAXFREQ-1) {
177  msg("64 fcodes in use, but clone label not found", 3);
178  return(-5);
179  }
180  // this sets it equal to zero if chids not used,
181  // and correctly if it chids is used.
182  cond_start->chid_rf[kk] = cond_start->chid_rf[ndx[ii]];
183  msg("long master code path %d\n%s: of %s (freq %f)", 1,
184  kk, progname, master, cond_start->chid_rf[kk]);
185  }
186  msg("found %d for %c", 1, kk, clones[ii]);
187  // else clone label is in master codes and does not need to be added.
188  msg(havechid
189  ? "clone %c (%c -> %c) at address %d (->%d), freqs %f -> %f"
190  : "clone %c (%c -> %c) at master address %d (->%d)",
191  1, master[kk], clones[ii], cinfo[ii], kk, ndx[ii],
192  cond_start->chid_rf[kk], cond_start->chid_rf[ndx[ii]]);
193  // finally, make the clone as acceptable as the source
194  cond_start->accept_sbs[kk] = cond_start->accept_sbs[ndx[ii]];
195  }
196  /* ensure null termination, yes, anal compulsive */
197  cond_start->clones[1][ii] = cond_start->clones[0][ii] = '\0';
198  /* next step will be in make passes where the cloning takes place */
199  msg("FRQS: (master) fcode set is now %s with %s -> %s", 1,
200  master, cond_start->clones[1], cond_start->clones[0]);
201  frqs_clone_clones(cond_start, havechid);
202  return(0);
203 }
204 
205 /* this is called to notice CHAN_PARAM tokens for channel parsing */
206 static int frqs_CHAN_PARAM(int toknum)
207 {
208  extern int token_cat[]; /* lives in parse_control_file.c */
209  int ii;
210  for (ii = 0; ii < MAX_TOKENS; ii++)
211  if (token_cat[toknum] == CHAN_PARAM) return(1);
212  return(0);
213 }
214 
215 /* this is invoked from (SAVE_CODES or) NEW_CODES */
216 /* if chid is used, master codes will have already been rewritten */
217 static int frqs_new_codes(char *parsed_codes, char *master,
218  struct c_block *cond_start)
219 {
220  static char *temp_codes, sblabels[] = { 'D', '+', '-' };
221  struct c_block *cb_start, *cb_ptr, *cb_tail;
222  int fc, nc, pp, tt, xx, len, sideband, sbndx, one;
223 
224  temp_codes = calloc((len = strlen(parsed_codes))+8, 1);
225  if (!temp_codes) { perror("malloc"); return(-1); }
226  strcpy(temp_codes, parsed_codes);
227  memset(parsed_codes, 0, MAXFREQ);
228  msg("FRQS: frqs_old_codes: '%s' with %d (cond_start: %p)", 1,
229  temp_codes, len, cond_start);
230  for (pp = tt = 0; tt < len; tt++) {
231  if (temp_codes[tt] == '~') { /* expansion case--is DSB only */
232  sideband = DSB;
233  one = (temp_codes[tt-1] == '+' || temp_codes[tt-1] == '-') ? 2 : 1;
234  /* get code of preceding channel */
235  fc = fcode(temp_codes[tt-one], master);
236  if (fc < 0) {
237  msg("FRQS: bogus ~ channel expansion after '%c'", 3,
238  temp_codes[tt-one]);
239  return(-2);
240  }
241  /* get code of following channel */
242  nc = fcode(temp_codes[tt+1], master);
243  if (nc < 0) {
244  msg("FRQS: bogus ~ channel expansion before '%c'", 3,
245  temp_codes[tt+one]);
246  return(-3);
247  }
248  while (++fc < nc) {
249  parsed_codes[pp++] = master[fc];
250  if (cond_start) {
251  msg("FRQS: %c accept_sbs[%d] = %d (sideband %c)", 1,
252  master[fc], fc, sideband, sblabels[0]);
253  for (cb_ptr=cond_start; cb_ptr!=NULL;
254  cb_ptr=cb_ptr->cb_chain)
255  cb_ptr -> accept_sbs[fc] = sideband;
256  }
257  }
258  } else { /* normal codes */
259  /* see after INSERT_V_CHAR */
260  if (temp_codes[tt+1] == '+') { sideband = USB; sbndx = 1; }
261  else if (temp_codes[tt+1] == '-') { sideband = LSB; sbndx = 2; }
262  else { sideband = DSB; sbndx = 0; }
263  /* else other actions..., e.g. @ for clone? */
264  fc = fcode(temp_codes[tt], master);
265  if (fc >= 0) parsed_codes[pp++] = master[fc];
266  else msg("FRQS: bad freq code '%c'(%d)", 3,
267  temp_codes[tt], sbndx=-1);
268  if (sbndx > 0) { parsed_codes[pp++] = sblabels[sbndx]; tt++; }
269  if (sbndx < 0) return(-4);
270  if (cond_start) {
271  /* set the sideband in all code blocks if cond_start non-NULL */
272  msg("FRQS: %c accept_sbs[%d] = %d (sideband %c)", 1,
273  master[fc], fc, sideband, sblabels[sbndx]);
274  for (cb_ptr=cond_start; cb_ptr!=NULL; cb_ptr=cb_ptr->cb_chain)
275  cb_ptr -> accept_sbs[fc] = sideband;
276  }
277  }
278  }
279  len = strlen(parsed_codes);
280  msg(cond_start
281  ? "FRQS: frqs_new_codes: '%s' with %d"
282  : "FRQS: frqs_exp_codes: '%s' with %d",
283  1, parsed_codes, len);
284  return(0);
285 }
286 
287 /* this is invoked on (char_values+tval) when frqs are in use */
288 static char *frqs_expand_codes(char *cf_chan_string, char *master)
289 {
290  char *newchans = calloc(268, 1);
291  msg("FRQS: frqs_expand_codes: '%s' (%d) -- input",1,
292  cf_chan_string, strlen(cf_chan_string));
293  strncpy(newchans, cf_chan_string, 256);
294  if (frqs_new_codes(newchans, master, NULL)) {
295  free(newchans);
296  return(NULL);
297  }
298  msg("FRQS: frqs_expand_codes: '%s' -- output",1,newchans);
299  return(newchans);
300 }
301 
302 /* deal with interpretation of display_chans */
303 static int frqs_display_chans(char *chans, char *master,
304  struct c_block *cond_start)
305 {
306  char *expcodes;
307  char *atskip = strchr(chans, '@');
308  struct c_block *cb_ptr;
309  msg("FRQS: frqs_display_chans: '%s' '%s' -- input",1,
310  chans, atskip ? atskip : "");
311  if (atskip) *atskip = 0;
312  expcodes = frqs_expand_codes(chans, master);
313  if (!expcodes) {
314  msg ("problem expanding display_chans %s",3, chans);
315  return(-1);
316  }
317  if (atskip) { *atskip = '@'; strcat(expcodes, atskip); }
318  for (cb_ptr=cond_start; cb_ptr!=NULL; cb_ptr=cb_ptr->cb_chain)
319  strcpy(cb_ptr->display_chans, expcodes);
320  msg("FRQS: frqs_display_chans: '%s' -- output",1, expcodes);
321  free(expcodes);
322  return(0);
323 }
324 
325 #else /* defined(ALLOW_FRQS_CODE) */
326 // no ALLOW_FRQS_CODE
327 #endif /* defined(ALLOW_FRQS_CODE) */
328 
329 #endif /* frqsupport_h */
330 /*
331  * eof
332  */
char chid[MAXFREQ+1]
Definition: control.h:108
char chan_notches[MAXNOTCH+1]
Definition: control.h:89
#define LSB
Definition: control.h:140
char clones[2][MAXFREQ/2+1]
Definition: control.h:110
#define USB
Definition: control.h:139
#define FCHARS
Definition: control.h:166
char display_chans[MAXFREQ+5]
Definition: control.h:112
int nnotches
Definition: control.h:87
#define DSB
Definition: control.h:141
#define MAXNOTCH
Definition: control.h:8
double chid_rf[MAXFREQ]
Definition: control.h:109
int accept_sbs[MAXFREQ]
Definition: control.h:42
struct c_block * cb_chain
Definition: control.h:24
Definition: control.h:23
char progname[]
Definition: msg.c:3
void msg(const char *string, int level,...)
Definition: msg.c:25
int token_cat[MAX_TOKENS]
Definition: parse_control_file.c:23
int fcode(char c, char *codes)
Definition: parser.c:113
#define MAX_TOKENS
Definition: parser.h:169
#define CHAN_PARAM
Definition: parser.h:195
#define MAXFREQ
Definition: sizelimits.h:1