1use 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
81pub 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    if RETURN(ctx) {
126        return Ok(());
127    } else {
128        CHKIN(b"ZZEKPDEC", ctx)?;
129    }
130
131    CLEARI(CDSCSZ, PARDSC.as_slice_mut());
135
136    LPARSM(DECL, b",=", MAXTOK, &mut N, TOKENS.as_arg_mut());
182
183    for I in 1..=N {
188        UCASE(&TOKENS[I].to_vec(), &mut TOKENS[I], ctx);
189    }
190
191    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    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    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        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            PARDSC[LENIDX] = IFALSE;
303        } else {
304            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        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    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            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        PARDSC[SIZIDX] = 1;
401    }
402
403    if (PARDSC[TYPIDX] == CHR) {
407        if (PARDSC[SIZIDX] == 1) {
411            PARDSC[CLSIDX] = 3;
412        } else {
413            PARDSC[CLSIDX] = 6;
414        }
415    } else if (PARDSC[TYPIDX] == INT) {
416        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        if (PARDSC[SIZIDX] == 1) {
430            PARDSC[CLSIDX] = 2;
431        } else {
432            PARDSC[CLSIDX] = 5;
433        }
434    }
435
436    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        PARDSC[NFLIDX] = IFALSE;
473    }
474
475    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            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        PARDSC[IXTIDX] = IFALSE;
529    }
530
531    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            if (PARDSC[CLSIDX] == 1) {
555                PARDSC[CLSIDX] = 7;
559            } else if (PARDSC[CLSIDX] == 2) {
560                PARDSC[CLSIDX] = 8;
564            } else if (PARDSC[CLSIDX] == 3) {
565                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            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}