/***************************************************************************
*
ArraySeq_mod - description
*
-------------------
*
begin
: Mon 19 Dec 2005 04:20:14 PM EST
*
copyright
: (C) 2005 by Terry D. Boldt
*
email
: fastsnip-wm1@yahoo.com
***************************************************************************/
/***************************************************************************
*
*
* This program is free software; you can redistribute
it and/or modify *
* it under the terms of the GNU General Public
License as published by *
* the Free Software Foundation; either version 2 of
the License, or *
* (at your option) any later
version.
*
*
*
***************************************************************************/
/*
*
* QTAwk plugin function to deomonstrate accessing and
sequencing arrays
*/
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
/* Note QTAwk_plugins.h header file depeneds on "string.h" header file.
* ALWAYS include "string.h" before QTAwk_plugins
*/
#include "QTAwk_plugins.h"
/* define some useful constants
*/
#define TRUE 1
#define FALSE 0
/* define End Of String marker
*/
#define EOS '\x000'
/* define initialization function
*/
unsigned QTAwk_init_load_module(
void)
{
/* array of pointers to string with argument names
for loaded functions
* Here both functions take a single string
function
*/
unsigned char *arguments[] = {
"seq_array",
NULL
};
/* declare error return variable
*/
unsigned char *reg_err;
/* call function to initialize for installing
dynamic function(s)
*/
QTAwk_register_function_count(2);
/* now call function to register each dynamic
function to load
*
* Note that 'QTAwk_register_function' returns
a pointer to a string or NULL
* if no error in registering function. Here we
are ignoring the return value
* until returning from the call.
* We "should" examine the return value for
every call to 'QTAwk_register_function'
* and report any errors.
*/
reg_err =
QTAwk_register_function("ArraySeq_mod_version",NULL,FALSE);
reg_err =
QTAwk_register_function("sequence_array",arguments,FALSE);
QTAwk_set_module_exit_function("ArraySeq_mod_exit");
return reg_err ? -1 : 0;
} /* QTAwk_init_load_module */
/* function registered to accomplish actual work.
*
* All dynamically loaded functions have the following prototype
form:
*
* Variable_ptr
loaded_function(unsigned argument_count);
*
* Where 'Variable_ptr' is a QTAwk variable defined in the QTAwk
plugin
* header file "QTAwk_plugins.h"
* Do NOT manipulate the fields in the structure directly.
Use the function
* calls defined in "QTAwk_plugins.h" for that purpose.
*
*
*
*/
/* version string
*/
static unsigned char ArraySeq_mod_version_string[] = "Array Sequence
Demo. Version 1.00";
/* function to return module version string
*/
Variable_ptr ArraySeq_mod_version(
void)
{
Variable_ptr retval;
retval = QTAwk_get_variable_set((void
*)ArraySeq_mod_version_string,STRING_VAL);
return retval;
} /* ArraySeq_mod_version */
/* function to scan variable indices and match index.
*
* Call with arguments:
* 1. Variable with indices to scan
* 2. pointer to string index to match, NULL if matching
integer index
* 3. integer to match if not matching string index
*
* Returns: TRUE if index matched, FALSE otherwise
*
* NOTE: case ignored based on value of global variable,
'IGNORECASE'.
*
*/
unsigned match_index(
Variable_ptr var,
unsigned char *string_index,
unsigned long integer_index)
{
Variable_ptr array_element;
QTAwk_index index;
QTAwk_index_ptr indexp = &index;
unsigned
seqstate;
unsigned
bool = FALSE;
unsigned
ignore_case = QTAwk_true_false(QTAwk_get_named_variable("IGNORECASE"));
int
(*cmpstr)(const char *string1, const char *string2) = ignore_case ?
strcasecmp : strcmp;
for ( array_element =
QTAwk_first_array_element(var,&seqstate,indexp) ;
array_element;
array_element =
QTAwk_next_array_element(seqstate,indexp) ) {
if ( string_index ) {
if (
cmpstr((const char *)(string_index),(const char
*)(indexp->index_rep.char_index)) == 0 ) {
bool = TRUE;
QTAwk_array_finish(seqstate);
break;
} /*
endif */
} else {
if (
integer_index = indexp->index_rep.numeric_index ) {
bool = TRUE;
QTAwk_array_finish(seqstate);
break;
}/*
endif*/
} /* endif */
} /* endfor */
return bool;
} /* match_index */
static unsigned char *vname = NULL;
static void print_variable_value(
Variable_ptr var)
{
void
*retn_val;
unsigned vtype;
unsigned char *strg_ret;
unsigned char char_ret;
qta_long int_ret;
double
dbl_ret;
/* now get element value and print
*/
vtype = NO_VAL;
retn_val = QTAwk_get_value(var,&vtype);
switch ( vtype ) {
case NO_VAL:
printf("%llu",0LL);
break;
case REGEXP_VAL:
case STRING_VAL:
case STRING_INT:
case STRING_FLT:
strg_ret = (unsigned char *)retn_val;
printf("%s",strg_ret);
break;
case CHAR_VAL:
char_ret = *(unsigned char *)retn_val;
break;
case LONG_VAL:
int_ret = *(qta_long *)retn_val;
printf("%lld",int_ret);
break;
case DOUBLE_VAL:
dbl_ret = *(double *)retn_val;
printf("%f",dbl_ret);
break;
} /* endswitch */
} /* print_variable_value */
static unsigned seq_array_elements(
Variable_ptr arg_array)
{
Variable_ptr array_element;
Variable_ptr sarray;
QTAwk_index_ptr index_chn;
unsigned this_lvl =
FALSE;
unsigned seqstate;
unsigned index_lvls;
unsigned lc;
unsigned
index_this_level;
unsigned
index_all_levels;
unsigned blnk_output =
FALSE;
/* loop through elements at this level
*/
for ( array_element =
QTAwk_first_array_element(arg_array,&seqstate,NULL) ;
array_element ;
array_element =
QTAwk_next_array_element(seqstate,NULL) ) {
this_lvl = TRUE;
/* check if a next level of
index for this element
* If so then go to
next level
* This produces output
by row, e.g., for a 3x3 matrix
* output would be in
the following index order
* [1][1]
* [1][2]
* [1][3]
* [2][1]
* [2][2]
* [2][3]
* [3][1]
* [3][2]
* [3][3]
*
* This is like the
statements:
* for ( i in array ) {
* for ( j in
array[i] ) {
*
print("Element: [" >< i >< "][" >< j >< "]: "
>< array[i][j]);
* }
* }
*
* If a sparse
array then only output elements that actually exist.
*/
/* first check and
output next index level if next level exists, skip this level
* otherwise
output this level
*
index_this_level == indices specified for call variable
*
index_all_levels == total indices needed to fully specify variable
*/
index_this_level =
QTAwk_index_var(array_element,&index_all_levels);
/* if more indices needed,
go to next index level
* else print all
variables at this index level.
*/
if ( (index_this_level <
index_all_levels) ) {
(void)seq_array_elements(array_element);
} else {
if (
index_lvls == 1 ) {
printf("%s",vname);
} else if ( !blnk_output ) {
printf("%s",vname);
blnk_output = TRUE;
}
else printf(" ");
/*
print indices and values
*/
/*
first get indices for this element and print
*/
index_chn = QTAwk_get_indices(array_element,&index_lvls);
for
( lc = 0 ; lc < index_lvls ; lc++ ) {
switch ( index_chn[lc].index_type ) {
case STRING_INDEX_TYPE:
printf("[%s]",index_chn[lc].index_rep.char_index);
break;
case NUM_INDEX_TYPE:
printf("[%lu]",index_chn[lc].index_rep.numeric_index);
break;
} /* endswitch */
} /*
endfor */
/*
must free memory used by stack of index structures
*/
free(index_chn);
printf(" == ");
/*
now print element value
*/
print_variable_value(array_element);
if (
index_all_levels == 1 ) printf("\n");
} /* endif */
} /* endfor */
if ( this_lvl && (index_all_levels > 1) )
printf("\n");
return this_lvl;
} /* seq_array_elements */
/* test sequencing through array elements
*/
Variable_ptr sequence_array(
unsigned arg_cnt)
{
Variable_ptr arg_array;
/* get argument - retrieving by name - use same name
as specified when function
* registered.
*/
arg_array = QTAwk_get_argument(1,"seq_array");
vname = QTAwk_get_name(arg_array);
printf("Sequencing Array: %s\n",vname);
if ( !seq_array_elements(arg_array) )
printf(" Not Indexed\n");
free(vname);
return arg_array;
} /* sequence_array */
/* exit function - executed before unloading module
* Using default function name here.
*/
unsigned ArraySeq_mod_exit(
void)
{
printf("Unloading Array Sequencing module.\n");
} /* ArraySeq_mod_exit */