/* c-list.c    v0.1  (C) 1999 adolfo@di-mare.com */

#undef    NDEBUG     /* production code should #define this */
#include "intrat.h"

typedef struct {
    clist   L;
    cl_link lk;   /* list of int_lk */
} Lint;

void Lint_init(Lint *L) {
    cl_init(&L->L);
    cl_link_init(&L->lk);   /* check when NDEBUG */
}

declare_binder(Lint, lk);
const binder * const Bi  = &name_binder(int_lk, ik);

void Lint_copy(Lint *L, Lint *src) {
    cl_copy_binder(&L->L, &src->L, Bi);
}
int  Lint_equal(Lint *L, Lint *src) {
    return cl_equal_binder(&L->L, &src->L, Bi);
}
void Lint_print(Lint *L, FILE *F) {
    cl_print_binder(&L->L, F, Bi);
}
void Lint_done(Lint *L) {
    cl_done_binder(&L->L, Bi);
    cl_link_init(&L->lk);
}

define_binder(Lint, lk,
    Lint_init, Lint_copy, Lint_equal, Lint_print, Lint_done
);


#define  FALSE  0
#define  TRUE  (!FALSE)

void primes(clist *L, unsigned n) {
/*------------------------------------------------*\
| Prepends to L the prime numbers smaller than "n" |
\*------------------------------------------------*/

    int       i,j;
    cl_link * pHere = NULL;  /* points to pInt->ik */

    for (i = 1; i<n; i++) {
        int is_prime = TRUE;
        for (j = 2; j<i; j++) {
            if (0 == i % j) {
               is_prime = FALSE;
            }
        }
        if (is_prime) {
            int_lk * pInt;  /* pointer to the node */
            binder_create(Bi, pInt);

            pInt->n = i;
            cl_link_after(L, pHere, &pInt->ik);
            pHere = &pInt->ik; /* current position */
        }
    }
}


void has_digit(clist *L, int d, FILE *F) {
/*------------------------------------------*\
| Print all numbers in L that have digit "d" |
\*------------------------------------------*/

    cl_link *p;

    fprintf(F, "\nhas_digit(%d) ==\>", d);
    for (p = cl_first(L); (NULL != p); p = cl_next(L,p)) {
        int_lk *pInt = int_lk_cast(p);
        int n = pInt->n;

        int has_it = FALSE;
        pInt = int_lk_cast(p);

        do {
            int digit = n % 10;
            if (d == digit) {
                has_it = TRUE;
            }
            n = n / 10;
        } while (0 != n);

        if (has_it) {
            fprintf(F, " %d", pInt->n);
        }
    }
}


#include <string.h> /* strlen() */
void PI_listlist(const char* V) {
/*---------------------------------------*\
| Uses LL, a list of lists, and prints it |
\*---------------------------------------*/

    int    i,j;
    size_t len = strlen(V);

    clist LL; /* list of lists */

    cl_init(&LL);

    fprintf(stdout, "\n\nPI_listlist() ==\>\n");
    for (i=0; i<len; i++) {
        int VV  = ('.' == V[i] ? 0 : V[i]-'0');

        Lint *L;

        /* add a new element to LL */
        binder_create( &name_binder(Lint,lk), L );

        cl_append(&LL, &L->lk);

        for (j=0; j<VV; j++) {
            int_lk * pInt;

            binder_create(Bi, pInt);
            pInt->n = VV;

            cl_append(&L->L, &pInt->ik);
        }

        fprintf(stdout, ".");
        cl_print_binder(&L->L, stdout, &name_binder(int_lk, ik));
    }
    fprintf(stdout, "\n");

    cl_print_binder(&LL, stdout, &name_binder(Lint, lk));
    fprintf(stdout, "\n");

    cl_done_binder( &LL, &name_binder(Lint, lk));
}


#include <alloc.h>
int main() {
    clist   L;
    unsigned long memAvail = coreleft();

    cl_init(&L);

    primes(&L, 102);
    fprintf(stdout, "\n\nprimes(102) ==\>\n");
    cl_print_binder(&L, stdout, &name_binder(int_lk, ik));
    fprintf(stdout, "\n");

    {   int i;
        for (i=0; i<10; i++) {
            has_digit(&L, i, stdout);
        }
    }

    cl_done_binder( &L,         &name_binder(int_lk, ik));
    if (coreleft() != memAvail) {
        fprintf(stdout, "\n\nBOOM!!!");
    }

    PI_listlist("3.14159");

    if (coreleft() != memAvail) {
        fprintf(stdout, "\n\nBOOM!!!");
    }
    return 0;
}

#if 0
const binder * const BLL = &name_binder(Lint, lk);

int my_random(int *seed) {
    #include <values.h> /* MAXINT */
    long l = ((long) (*seed)) * 16381 + 16411;
     *seed = (int)(l >> 16) & MAXINT;

    return *seed;
}

void alternative() {

    binder not_pointer_BLL;

    set_binder(&not_pointer_BLL, Lint, lk,
        Lint_init, Lint_copy, Lint_equal, Lint_print, Lint_done
    );
}
#endif

/* EOF:   c-list.c */
