rsspice/generated/spicelib/
zzekpdec.rs

1//
2// GENERATED FILE
3//
4
5use super::*;
6use f2rust_std::*;
7
8const ITRUE: i32 = 1;
9const IFALSE: i32 = -1;
10const CTRUE: &[u8] = b"T";
11const CFALSE: &[u8] = b"F";
12const CDOFF: i32 = 24;
13const CDSCSZ: i32 = 11;
14const CLSIDX: i32 = 1;
15const TYPIDX: i32 = (CLSIDX + 1);
16const LENIDX: i32 = (TYPIDX + 1);
17const SIZIDX: i32 = (LENIDX + 1);
18const NAMIDX: i32 = (SIZIDX + 1);
19const IXTIDX: i32 = (NAMIDX + 1);
20const IXPIDX: i32 = (IXTIDX + 1);
21const NFLIDX: i32 = (IXPIDX + 1);
22const ORDIDX: i32 = (NFLIDX + 1);
23const METIDX: i32 = (ORDIDX + 1);
24const CHR: i32 = 1;
25const DP: i32 = 2;
26const INT: i32 = 3;
27const TIME: i32 = 4;
28const NATTR: i32 = 5;
29const MAXTOK: i32 = 20;
30const TOKLEN: i32 = 32;
31const MSGLEN: i32 = 320;
32const NRKEY: i32 = 1;
33const TYPPOS: i32 = 1;
34const SIZPOS: i32 = (TYPPOS + 1);
35const IDXPOS: i32 = (SIZPOS + 1);
36const NFLPOS: i32 = (IDXPOS + 1);
37const FXCPOS: i32 = (NFLPOS + 1);
38
39struct SaveVars {
40    ATTKEY: ActualCharArray,
41    REQKEY: StackArray<i32, 1>,
42}
43
44impl SaveInit for SaveVars {
45    fn new() -> Self {
46        let mut ATTKEY = ActualCharArray::new(TOKLEN, 1..=NATTR);
47        let mut REQKEY = StackArray::<i32, 1>::new(1..=NRKEY);
48
49        {
50            use f2rust_std::data::Val;
51
52            let mut clist = [
53                Val::C(b"DATATYPE"),
54                Val::C(b"SIZE"),
55                Val::C(b"INDEXED"),
56                Val::C(b"NULLS_OK"),
57                Val::C(b"FIXED_COUNT"),
58            ]
59            .into_iter();
60            ATTKEY
61                .iter_mut()
62                .for_each(|n| fstr::assign(n, clist.next().unwrap().into_str()));
63
64            debug_assert!(clist.next().is_none(), "DATA not fully initialised");
65        }
66        {
67            use f2rust_std::data::Val;
68
69            let mut clist = [Val::I(1)].into_iter();
70            REQKEY
71                .iter_mut()
72                .for_each(|n| *n = clist.next().unwrap().into_i32());
73
74            debug_assert!(clist.next().is_none(), "DATA not fully initialised");
75        }
76
77        Self { ATTKEY, REQKEY }
78    }
79}
80
81//$Procedure      ZZEKPDEC ( EK, parse column declaration )
82pub fn ZZEKPDEC(DECL: &[u8], PARDSC: &mut [i32], ctx: &mut Context) -> f2rust_std::Result<()> {
83    let save = ctx.get_vars::<SaveVars>();
84    let save = &mut *save.borrow_mut();
85
86    let mut PARDSC = DummyArrayMut::new(PARDSC, 1..);
87    let mut MSG = [b' '; MSGLEN as usize];
88    let mut TOKENS = ActualCharArray::new(TOKLEN, 1..=MAXTOK);
89    let mut ATTLOC = StackArray::<i32, 11>::new(1..=CDSCSZ);
90    let mut J: i32 = 0;
91    let mut N: i32 = 0;
92    let mut PTR: i32 = 0;
93    let mut TOKLOC: i32 = 0;
94    let mut ATTFND = StackArray::<bool, 11>::new(1..=CDSCSZ);
95    let mut FOUND: bool = false;
96
97    //
98    // SPICELIB functions
99    //
100
101    //
102    // Local parameters
103    //
104
105    //
106    // Parameters naming indices of keywords in the attribute list
107    // ATTKEY:
108    //
109
110    //
111    // Local variables
112    //
113
114    //
115    // Saved variables
116    //
117
118    //
119    // Initial values
120    //
121
122    //
123    // Standard SPICE error handling.
124    //
125    if RETURN(ctx) {
126        return Ok(());
127    } else {
128        CHKIN(b"ZZEKPDEC", ctx)?;
129    }
130
131    //
132    // Start with a clean slate.
133    //
134    CLEARI(CDSCSZ, PARDSC.as_slice_mut());
135
136    //
137    // Our declaration language has been cleverly designed so that the
138    // characters
139    //
140    //    ','
141    //    '='
142    //
143    // act as delimiters that LPARSM can make use
144    // of.  LPARSM will hand us back a token list that contains these
145    // pairs of consecutive tokens:
146    //
147    //    +----------------------+
148    //    | CLASS                |
149    //    +----------------------+
150    //    | <integer>            |
151    //    +----------------------+
152    //
153    //    +----------------------+
154    //    | DATATYPE             |
155    //    +----------------------+
156    //    | <type>               |
157    //    +----------------------+
158    //
159    //    +----------------------+
160    //    | SIZE                 |
161    //    +----------------------+
162    //    | <size specification> |  ( 'VARIABLE' or <integer> )
163    //    +----------------------+
164    //
165    //    +----------------------+
166    //    | INDEXED              |  (fixed-size columns only, optional)
167    //    +----------------------+
168    //    | <TRUE/FALSE>         |
169    //    +----------------------+
170    //
171    //    +----------------------+
172    //    | NULLS_OK             |  (optional)
173    //    +----------------------+
174    //    | <TRUE/FALSE>         |
175    //    +----------------------+
176    //
177    //
178    // The order of the token pairs is not necessarily as shown.
179    //
180    //
181    LPARSM(DECL, b",=", MAXTOK, &mut N, TOKENS.as_arg_mut());
182
183    //
184    // Make sure the tokens are in upper case.  They are already
185    // left-justified.
186    //
187    for I in 1..=N {
188        UCASE(&TOKENS[I].to_vec(), &mut TOKENS[I], ctx);
189    }
190
191    //
192    // See which clauses are present in the declaration, and keep track
193    // of the token indices of the keywords that start the clauses.
194    //
195    for I in 1..=NATTR {
196        ATTFND[I] = false;
197    }
198
199    for I in 1..=N {
200        J = 1;
201        FOUND = false;
202
203        while ((J <= NATTR) && !FOUND) {
204            if fstr::eq(TOKENS.get(I), save.ATTKEY.get(J)) {
205                FOUND = true;
206                ATTFND[J] = true;
207                ATTLOC[J] = I;
208            } else {
209                J = (J + 1);
210            }
211        }
212    }
213
214    //
215    // Make sure we got the required keyword tokens we were expecting.
216    //
217    for I in 1..=NRKEY {
218        if !ATTFND[save.REQKEY[I]] {
219            SETMSG(
220                b"Required keyword # was not found in column declaration #.",
221                ctx,
222            );
223            ERRCH(b"#", &save.ATTKEY[save.REQKEY[I]], ctx);
224            ERRCH(b"#", DECL, ctx);
225            SIGERR(b"SPICE(BADCOLUMDECL)", ctx)?;
226            CHKOUT(b"ZZEKPDEC", ctx)?;
227            return Ok(());
228        }
229    }
230
231    //
232    // If we got this far, we can start to fill in the data type
233    // descriptor.  Starting at the location of the DATATYPE keyword,
234    // we should see one of the following token sequences:
235    //
236    //    DATATYPE  =  DOUBLE PRECISION
237    //    DATATYPE  =  INTEGER
238    //    DATATYPE  =  TIME
239    //    DATATYPE  =  CHARACTER*<integer>
240    //    DATATYPE  =  CHARACTER*(<integer>)
241    //    DATATYPE  =  CHARACTER**
242    //    DATATYPE  =  CHARACTER*(*)
243    //
244    // The character declarations may have white space surrounding
245    // the length specifier.
246    //
247    // Find the location where the data type token should be.
248    //
249    TOKLOC = (ATTLOC[TYPPOS] + 1);
250
251    if (N < TOKLOC) {
252        SETMSG(
253            b"Column data type specification did not follow \"DATATYPE\" keyword in declaration #.",
254            ctx,
255        );
256        ERRCH(b"#", DECL, ctx);
257        SIGERR(b"SPICE(BADCOLUMNDECL)", ctx)?;
258        CHKOUT(b"ZZEKPDEC", ctx)?;
259        return Ok(());
260    }
261
262    if fstr::eq(TOKENS.get(TOKLOC), b"INTEGER") {
263        PARDSC[TYPIDX] = INT;
264        PARDSC[LENIDX] = 1;
265    } else if EQSTR(&TOKENS[TOKLOC], b"DOUBLE PRECISION") {
266        PARDSC[TYPIDX] = DP;
267        PARDSC[LENIDX] = 1;
268    } else if EQSTR(&TOKENS[TOKLOC], b"TIME") {
269        PARDSC[TYPIDX] = TIME;
270        PARDSC[LENIDX] = 1;
271    } else if fstr::eq(fstr::substr(TOKENS.get(TOKLOC), 1..=9), b"CHARACTER") {
272        PARDSC[TYPIDX] = CHR;
273        //
274        // To simplify picking up the length specification, compress
275        // out blanks and parentheses.  This should leave us with
276        // a token of the form
277        //
278        //    CHARACTER*<integer>
279        //
280        // or
281        //
282        //    CHARACTER**
283        //
284        //
285        CMPRSS(b" ", 0, &TOKENS[TOKLOC].to_vec(), &mut TOKENS[TOKLOC]);
286        CMPRSS(b"(", 0, &TOKENS[TOKLOC].to_vec(), &mut TOKENS[TOKLOC]);
287        CMPRSS(b")", 0, &TOKENS[TOKLOC].to_vec(), &mut TOKENS[TOKLOC]);
288
289        if fstr::ne(fstr::substr(TOKENS.get(TOKLOC), 10..=10), b"*") {
290            SETMSG(b"Required asterisk missing from character column declaration:  #  in declaration:  #", ctx);
291            ERRCH(b"#", &TOKENS[TOKLOC], ctx);
292            ERRCH(b"#", DECL, ctx);
293            SIGERR(b"SPICE(BADCOLUMNDECL)", ctx)?;
294            CHKOUT(b"ZZEKPDEC", ctx)?;
295            return Ok(());
296        }
297
298        if fstr::eq(fstr::substr(TOKENS.get(TOKLOC), 11..=11), b"*") {
299            //
300            // The string length is variable.
301            //
302            PARDSC[LENIDX] = IFALSE;
303        } else {
304            //
305            // The portion of the token following the asterisk should be a
306            // string length.
307            //
308            fstr::assign(&mut MSG, b" ");
309            NPARSI(
310                fstr::substr(&TOKENS[TOKLOC], 11..),
311                &mut PARDSC[LENIDX],
312                &mut MSG,
313                &mut PTR,
314                ctx,
315            );
316
317            if fstr::ne(&MSG, b" ") {
318                SETMSG(
319                    b"String length specification # didn\'t parse as an integer in declaration   #",
320                    ctx,
321                );
322                ERRCH(b"#", fstr::substr(&TOKENS[TOKLOC], 11..), ctx);
323                ERRCH(b"#", DECL, ctx);
324                SIGERR(b"SPICE(BADCOLUMNDECL)", ctx)?;
325                CHKOUT(b"ZZEKPDEC", ctx)?;
326                return Ok(());
327            }
328        }
329    } else {
330        //
331        // The type specification is invalid.
332        //
333        SETMSG(
334            b"Data type specification # is unrecognized in declaration #.",
335            ctx,
336        );
337        ERRCH(b"#", &TOKENS[TOKLOC], ctx);
338        ERRCH(b"#", DECL, ctx);
339        SIGERR(b"SPICE(BADCOLUMNDECL)", ctx)?;
340        CHKOUT(b"ZZEKPDEC", ctx)?;
341        return Ok(());
342    }
343
344    //
345    // Next, parse the size specification, if we have one.  If it's
346    // valid, it's either the string 'VARIABLE' or it's an integer.
347    //
348    if ATTFND[SIZPOS] {
349        TOKLOC = (ATTLOC[SIZPOS] + 1);
350
351        if (N < TOKLOC) {
352            SETMSG(
353                b"Column size specification did not follow \"SIZE\" keyword in declaration #.",
354                ctx,
355            );
356            ERRCH(b"#", DECL, ctx);
357            SIGERR(b"SPICE(BADCOLUMNDECL)", ctx)?;
358            CHKOUT(b"ZZEKPDEC", ctx)?;
359            return Ok(());
360        }
361
362        if fstr::eq(TOKENS.get(TOKLOC), b"VARIABLE") {
363            //
364            // Variable size entries are not allowed for CHARACTER*(*)
365            // columns.
366            //
367            if (PARDSC[TYPIDX] == CHR) {
368                if (PARDSC[LENIDX] == IFALSE) {
369                    SETMSG(b"Column size specification was VARIABLE for a CHARACTER*(*) column in  declaration #.", ctx);
370                    ERRCH(b"#", DECL, ctx);
371                    SIGERR(b"SPICE(BADCOLUMNDECL)", ctx)?;
372                    CHKOUT(b"ZZEKPDEC", ctx)?;
373                    return Ok(());
374                }
375            }
376
377            PARDSC[SIZIDX] = IFALSE;
378        } else {
379            NPARSI(
380                &TOKENS[TOKLOC],
381                &mut PARDSC[SIZIDX],
382                &mut MSG,
383                &mut PTR,
384                ctx,
385            );
386
387            if fstr::ne(&MSG, b" ") {
388                SETMSG(b"Column element size  specification # didn\'t parse as an integer in in declaration #", ctx);
389                ERRCH(b"#", &TOKENS[TOKLOC], ctx);
390                ERRCH(b"#", DECL, ctx);
391                SIGERR(b"SPICE(BADCOLUMNDECL)", ctx)?;
392                CHKOUT(b"ZZEKPDEC", ctx)?;
393                return Ok(());
394            }
395        }
396    } else {
397        //
398        // If the size is not specified, it defaults to 1.
399        //
400        PARDSC[SIZIDX] = 1;
401    }
402
403    //
404    // The data type and entry size determine the column's class.
405    //
406    if (PARDSC[TYPIDX] == CHR) {
407        //
408        // The character classes are 3 for scalars, 6 for arrays.
409        //
410        if (PARDSC[SIZIDX] == 1) {
411            PARDSC[CLSIDX] = 3;
412        } else {
413            PARDSC[CLSIDX] = 6;
414        }
415    } else if (PARDSC[TYPIDX] == INT) {
416        //
417        // The integer classes are 1 for scalars, 4 for arrays.
418        //
419        if (PARDSC[SIZIDX] == 1) {
420            PARDSC[CLSIDX] = 1;
421        } else {
422            PARDSC[CLSIDX] = 4;
423        }
424    } else if ((PARDSC[TYPIDX] == DP) || (PARDSC[TYPIDX] == TIME)) {
425        //
426        // The d.p. classes are 2 for scalars, 6 for arrays.  TIME
427        // values are represented using d.p. classes as well.
428        //
429        if (PARDSC[SIZIDX] == 1) {
430            PARDSC[CLSIDX] = 2;
431        } else {
432            PARDSC[CLSIDX] = 5;
433        }
434    }
435
436    //
437    // Parse the `NULLS_OK' clause, if we have one.
438    //
439    if ATTFND[NFLPOS] {
440        TOKLOC = (ATTLOC[NFLPOS] + 1);
441
442        if (N < TOKLOC) {
443            SETMSG(
444                b"Boolean value did not follow \"NULLS_OK\" keyword in declaration #.",
445                ctx,
446            );
447            ERRCH(b"#", DECL, ctx);
448            SIGERR(b"SPICE(BADCOLUMNDECL)", ctx)?;
449            CHKOUT(b"ZZEKPDEC", ctx)?;
450            return Ok(());
451        }
452
453        if fstr::eq(TOKENS.get(TOKLOC), b"TRUE") {
454            PARDSC[NFLIDX] = ITRUE;
455        } else if fstr::eq(TOKENS.get(TOKLOC), b"FALSE") {
456            PARDSC[NFLIDX] = IFALSE;
457        } else {
458            SETMSG(
459                b"Invalid token # follows NULLS_OK keyword in declaration #. ",
460                ctx,
461            );
462            ERRCH(b"#", &TOKENS[TOKLOC], ctx);
463            ERRCH(b"#", DECL, ctx);
464            SIGERR(b"SPICE(BADCOLUMNDECL)", ctx)?;
465            CHKOUT(b"ZZEKPDEC", ctx)?;
466            return Ok(());
467        }
468    } else {
469        //
470        // As a default, nulls are not allowed.
471        //
472        PARDSC[NFLIDX] = IFALSE;
473    }
474
475    //
476    //
477    // Parse the `INDEXED' clause, if we have one.
478    //
479    if ATTFND[IDXPOS] {
480        TOKLOC = (ATTLOC[IDXPOS] + 1);
481
482        if (N < TOKLOC) {
483            SETMSG(
484                b"Boolean value did not follow \"INDEXED\" keyword in declaration #.",
485                ctx,
486            );
487            ERRCH(b"#", DECL, ctx);
488            SIGERR(b"SPICE(BADCOLUMNDECL)", ctx)?;
489            CHKOUT(b"ZZEKPDEC", ctx)?;
490            return Ok(());
491        }
492
493        if fstr::eq(TOKENS.get(TOKLOC), b"TRUE") {
494            //
495            // If we have a fixed-size column whose size is 1, then it's
496            // possible to index that column.  Otherwise, we should not
497            // have an `INDEXED' clause.
498            //
499            if (PARDSC[SIZIDX] != 1) {
500                SETMSG(
501                    b"Non-scalar columns cannot be indexed. Declaration was #.",
502                    ctx,
503                );
504                ERRCH(b"#", DECL, ctx);
505                SIGERR(b"SPICE(BADCOLUMNDECL)", ctx)?;
506                CHKOUT(b"ZZEKPDEC", ctx)?;
507                return Ok(());
508            }
509
510            PARDSC[IXTIDX] = ITRUE;
511        } else if fstr::eq(TOKENS.get(TOKLOC), b"FALSE") {
512            PARDSC[IXTIDX] = IFALSE;
513        } else {
514            SETMSG(
515                b"Invalid token # follows INDEXED keyword in declaration #. ",
516                ctx,
517            );
518            ERRCH(b"#", &TOKENS[TOKLOC], ctx);
519            ERRCH(b"#", DECL, ctx);
520            SIGERR(b"SPICE(BADCOLUMNDECL)", ctx)?;
521            CHKOUT(b"ZZEKPDEC", ctx)?;
522            return Ok(());
523        }
524    } else {
525        //
526        // As a default, the column is not indexed.
527        //
528        PARDSC[IXTIDX] = IFALSE;
529    }
530
531    //
532    // Parse the `FIXED_COUNT' clause, if we have one.
533    //
534    if ATTFND[FXCPOS] {
535        TOKLOC = (ATTLOC[FXCPOS] + 1);
536
537        if (N < TOKLOC) {
538            SETMSG(
539                b"Boolean value did not follow \"FIXED_COUNT\" keyword in declaration #.",
540                ctx,
541            );
542            ERRCH(b"#", DECL, ctx);
543            SIGERR(b"SPICE(BADCOLUMNDECL)", ctx)?;
544            CHKOUT(b"ZZEKPDEC", ctx)?;
545            return Ok(());
546        }
547
548        if fstr::eq(TOKENS.get(TOKLOC), b"TRUE") {
549            //
550            // The column is a fixed-count column.  Only scalar columns
551            // are permitted to have fixed count.  We adjust the column
552            // class to indicate fixed-count columns.
553            //
554            if (PARDSC[CLSIDX] == 1) {
555                //
556                // Map scalar integers.
557                //
558                PARDSC[CLSIDX] = 7;
559            } else if (PARDSC[CLSIDX] == 2) {
560                //
561                // Map scalar d.p. numbers.
562                //
563                PARDSC[CLSIDX] = 8;
564            } else if (PARDSC[CLSIDX] == 3) {
565                //
566                // Map scalar strings.
567                //
568                PARDSC[CLSIDX] = 9;
569            } else {
570                SETMSG(
571                    b"FIXED_COUNT attribute used in non-scalar column declaration #. ",
572                    ctx,
573                );
574                ERRCH(b"#", DECL, ctx);
575                SIGERR(b"SPICE(BADCOLUMNDECL)", ctx)?;
576                CHKOUT(b"ZZEKPDEC", ctx)?;
577                return Ok(());
578            }
579        } else if fstr::ne(TOKENS.get(TOKLOC), b"FALSE") {
580            //
581            // No action is required if the FIXED_COUNT keyword is set
582            // to FALSE, but no value other than FALSE or TRUE may appear
583            // on the RHS.
584            //
585            SETMSG(
586                b"Invalid token # follows NULLS_OK keyword in declaration #. ",
587                ctx,
588            );
589            ERRCH(b"#", &TOKENS[TOKLOC], ctx);
590            ERRCH(b"#", DECL, ctx);
591            SIGERR(b"SPICE(BADCOLUMNDECL)", ctx)?;
592            CHKOUT(b"ZZEKPDEC", ctx)?;
593            return Ok(());
594        }
595    }
596
597    CHKOUT(b"ZZEKPDEC", ctx)?;
598    Ok(())
599}