/*
 * c_argv - a custom function display info about its args
 *
 * Copyright (C) 1999-2006,2021,2023,2026  Landon Curt Noll
 *
 * Calc is open software; you can redistribute it and/or modify it under
 * the terms of the version 2.1 of the GNU Lesser General Public License
 * as published by the Free Software Foundation.
 *
 * Calc is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General
 * Public License for more details.
 *
 * A copy of version 2.1 of the GNU Lesser General Public License is
 * distributed with calc under the filename COPYING-LGPL.  You should have
 * received a copy with calc; if not, write to Free Software Foundation, Inc.
 * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 *
 * Under source code control:   1997/03/09 20:27:37
 * File existed as early as:    1997
 *
 * chongo <was here> /\oo/\     http://www.isthe.com/chongo/
 * Share and enjoy!  :-)        http://www.isthe.com/chongo/tech/comp/calc/
 */

/*
 * ISO C requires a translation unit to contain at least one declaration,
 * so we declare a global variable whose value is based on if CUSTOM is defined.
 */
#if defined(CUSTOM)
int c_argv_allowed = 1; /* CUSTOM defined */
#else
int c_argv_allowed = 0; /* CUSTOM undefined */
#endif

#if defined(CUSTOM)

/*
 * important <system> header includes
 */
#  include <stdio.h>
#  include <stdint.h>
#  include <stdbool.h>

/*
 * conditional <system> head includes
 */
#  include "../value.h"
#  include "../custom.h"
#  include "../calc.h"
#  include "../have_unused.h"

#  include "../banned.h" /* include after all other includes */

/*
 * c_argv - a custom function display info about its args
 *
 * given:
 *      vals[i]   and arg to display information about
 *
 * returns:
 *      count
 */
/*ARGSUSED*/
VALUE
c_argv(char *UNUSED(name), int count, VALUE **vals)
{
    VALUE result;    /* what we will return */
    ZVALUE zfilelen; /* length of a file as a ZVALUE */
    NUMBER *filelen; /* pointer to length of a file as a NUMBER */
    char *type;      /* the name of the arg type */
    int i;

    /*
     * print info on each arg
     */
    for (i = 0; i < count; ++i) {

        /*
         * print arg number with leading tab as configured
         */
        printf("%sarg[%d]", (conf->tab_ok ? "\t" : ""), i);

        /*
         * print the arg type
         */
        switch (vals[i]->v_type) {
        case V_NULL: /* null value */
            type = "null";
            break;
        case V_INT: /* normal integer */
            type = "int";
            break;
        case V_NUM: /* number */
            type = "rational_value";
            break;
        case V_COM: /* complex number */
            type = "complex_value";
            break;
        case V_ADDR: /* address of variable value */
            type = "address";
            break;
        case V_STR: /* address of string */
            type = "string";
            break;
        case V_MAT: /* address of matrix structure */
            type = "matrix";
            break;
        case V_LIST: /* address of list structure */
            type = "list";
            break;
        case V_ASSOC: /* address of association structure */
            type = "assoc";
            break;
        case V_OBJ: /* address of object structure */
            type = "object";
            break;
        case V_FILE: /* opened file id */
            type = "file";
            break;
        case V_RAND: /* subtractive 100 random state */
            type = "rand_state";
            break;
        case V_RANDOM: /* address of Blum random state */
            type = "random_state";
            break;
        case V_CONFIG: /* configuration state */
            type = "config_state";
            break;
        case V_HASH: /* hash state */
            type = "hash_state";
            break;
        case V_BLOCK: /* memory block */
            type = "octet_block";
            break;
        case V_OCTET: /* octet (unsigned char) */
            type = "octet";
            break;
        default:
            type = "unknown";
            break;
        }
        printf("\t%-16s", type);

        /*
         * print size and sizeof information
         *
         * We have to treat files in a special way
         * because their length can be very long.
         */
        if (vals[i]->v_type == V_FILE) {
            /* get the file length */
            if (getsize(vals[i]->v_file, &zfilelen) == 0) {
                filelen = qalloc();
                filelen->num = zfilelen;
                qprintfd(filelen, 0L);
                qfree(filelen);
            } else {
                /* getsize error */
                printf("\tsize=unknown");
            }
            printf("\tsizeof=%ld\n", (long int)lsizeof(vals[i]));
        } else {
            printf("\tsize=%ld\tsizeof=%ld\n", elm_count(vals[i]), (long int)lsizeof(vals[i]));
        }
    }

    /*
     * return count
     */
    result.v_type = V_NUM;
    result.v_num = itoq(count);
    return result;
}

#endif
