GOTO main

FUNCTION struct_contents
    CREATE $(pre)
    CREATE $(suf)

    FOR $({/TYPE)
        IF $(TYPE) = dllh
            # dllh is "added" as base class by caller  
        ELSEIF $(REF) ~ %
        ELSE
            SET $(pre)
            SET $(suf)
            IF $(REF) ~ *
                SET $(pre) *
            ELSEIF $(REF) ~ v
                SET $(suf) [$(SIZE|NO SIZE DEFINED)]
            ENDIF
            IF $(REF) ~ d
                P dll_public$|  p$(IDENT);
            ENDIF
            IF $(REF) ~ d,r,l,o
                SET $(pre) $(pre)*
            ENDIF
            P $(TYPE|NO TYPE FOUND)$\
            # align '  name' ' *name' '**name'
            SET $(pre) '$(pre)'
            P $|$(pre:''=  :'*'= *:'**'=**:'=)$(IDENT)$(suf);$\
            P $| // $(DOCU| *** )
        ENDIF
    ENDFOR
RETURN

FUNCTION define_type
    P struct $(STRUCT) $\
    FOR $({/TYPE.dllh)
        P : public dll<$(STRUCT)> $\
    ENDFOR
    P { // $(SDOCU|$(STRUCT))
    INDENT +1
        CALL struct_contents
    INDENT -1
    P };
RETURN

FUNCTION datatypes
    P // forward decl dll types
    P struct dllpublic_ext;
    P struct dllheader_ext;
    --

    FOR $(STRUCT.dll_public)
    NEXT
        ERROR mandatory STRUCT 'dll_public' is missing
    ENDFOR
    FOR $(STRUCT.dll_header)
    NEXT
        ERROR mandatory STRUCT 'dll_header' is missing
    ENDFOR

    P // "public" version of dll
    FOR $(STRUCT.dll_public)
        CALL define_type
    ENDFOR
    FOR $(STRUCT.dll_header)
        CALL define_type
    ENDFOR
    --

    P template <typename USERTYPE>
    P struct dll {
    INDENT +1
        P dll_header  mh; // ***ANOTHEROLIHACK**
        P USERTYPE   *previous, *next;
        P int get_count() const { return mh.parent ? mh.parent->cnt : 0; }
    INDENT -1
    P };
    --

    P // "private" (i.e. real) version of dll (DoubledLinkedList)
    P struct dllpublic_ext : public dll_public { 
    INDENT +1
        P dllheader_ext$| *first; 
    INDENT -1
    P };
    P // pseudo-base-class of dll<USERTYPE> (bit-equal)
    P struct dllheader_ext : dll<dllheader_ext> {}; // pseudo-base-class of dll<USERTYPE> (bit-equal)
    --

    P // forward decl user datatypes
    FOR $(STRUCT)
        IF $(STRUCT) ~ dll_header,dll_public
        ELSE
            P struct $(STRUCT);
        ENDIF
    ENDFOR
    --

    P // user defined datatypes
    FOR $(STRUCT)
        IF $(STRUCT) ~ dll_header,dll_public
        ELSE
            CALL define_type
        ENDIF
    ENDFOR
    --

RETURN

FUNCTION constants
    IF $(CONST)
        P // some constants
        FOR $(CONST)
            P #define $(CONST) $|$(VALUE) $|// $(DOCU)
        ENDFOR
        --
    ENDIF
RETURN

FUNCTION enums
    IF $(ENUM)
        ERROR never used before - please check generated code
        P // the enums
        FOR $(ENUM)
            P $n// $(SDOCU|$(ENUM))
            P typedef enum enum_$(ENUM) {
            INDENT +1
                FOR $({/VAR)
                    IF $(VAL)
                        P $(VAR)$| = $|$(VAL),$\
                    ELSE
                        P $(VAR),$|$\
                    ENDIF
                    IF $(DOCU)
                        P $|// $(DOCU)
                    ELSE
                        P 
                    ENDIF
                ENDFOR
            INDENT -1
            P } $(ENUM);
        ENDFOR
        --
    ENDIF
RETURN

FUNCTION keys
    P // the keys
    P typedef enum enum_t_key {
    INDENT +1
        FOR $(STRUCT)
            IF $(JOINED)
            ELSEIF $(SKEY)
                P KEY_$(OBJECT_KEY)_$(SKEY)$| = $|0x10000*$(SKEYC),
            ENDIF
        ENDFOR
        P KEY_MAX
    INDENT -1
    P } t_key;
    --
RETURN

# --------------------------------------------------------------------------------

LABEL main
IF $(argc) != 4
    ERROR Wrong number of parameters[$(argc)]. Usage: aisc aisc.pa xxx.aisc outfile
ENDIF

DATA AISC { $(#FILE $(argv[2])) };
DUMPDATA DUMP/aisc.pa__$(argv[2]).dump
MOVETO $(/AISC/DATA/.)

OPEN save $(argv[3])
OUT save

P // -----------------------------------------------------------------
P // Created automagically from ../$(argv[2])
P // using aisc-script '../AISC/aisc.pa'
P // DO NOT EDIT THIS FILE!!!
P // -----------------------------------------------------------------
--
P #ifndef AISC_GEN_SERVER_INCLUDED
P #define AISC_GEN_SERVER_INCLUDED
--
P typedef char       *aisc_string;
P typedef const char *aisc_cstring;
--
P #ifndef AISC_GLOBAL_H
P #include <aisc_global.h>
P #endif
P $(INCLUDE_INCLUDES)
--
CALL constants
CALL enums
CALL keys
CALL datatypes
P extern const char *aisc_server_error;
--

P #else 
P #error header included twice 
P #endif // AISC_GEN_SERVER_INCLUDED
CLOSE save
EXIT

