/*
 * Copyright (c) 2004-2005 Endace Technology Ltd, Hamilton, New Zealand.
 * All rights reserved.
 *
 * This source code is proprietary to Endace Technology Limited and no part
 * of it may be redistributed, published or disclosed except as outlined in
 * the written contract supplied with this product.
 *
 * $Id: process_cmdline.c 14049 2011-03-21 03:06:07Z jomi.gregory $
 */

#include "dagutil.h"
#include "dagapi.h"
#include "./process_cmdline.h"
#include "./token_processing.h"
#include "dag_config.h"
#include "dag_component.h"
#include "dagtoken.h"

#include <errno.h>
#include <string.h>
#include <stdlib.h>


/* CVS Header. */
static const char* const kCvsHeader __attribute__ ((unused)) = "$Id: process_cmdline.c 14049 2011-03-21 03:06:07Z jomi.gregory $";
static const char* const kRevisionString = "$Revision: 14049 $";

#define BUFFER_SIZE 256
/* defined for buffers used for '-S' and '-G' attribute operations */ 
#define SET_GET_ATTRIBUTE_BUF_SIZE 288

#define FRAMER_FIRMWARE_FILE_SIZE 256
static void print_version(void);
static void add_print_statistics();
static void add_interval_option(int * val);
static void print_help_header(void);
static void print_token_attribute_usage(void);
static void print_token_functional_usage(void);
/* Commandline argument codes. */
enum
{
    CLA_DEVICE,
    CLA_HELP,
    CLA_PRINT_STATISTICS,
    CLA_PRINT_EXTENDED_CURRENT_STATISTICS,
    CLA_PRINT_EXTENDED_HI_STATISTICS,
    CLA_PRINT_EXTENDED_LO_STATISTICS,
    CLA_REPEAT_INTERVAL,
    CLA_CONNECTION_CONFIG,
    CLA_PRINT_COUNTERS,
    CLA_PRINT_UNIV_COUNTERS,
    CLA_VERBOSE,
    CLA_PORT_A,
    CLA_PORT_B,
    CLA_PORT_C,
    CLA_PORT_D,
    CLA_PORT_E,
    CLA_PORT_F,
    CLA_PORT_G,
    CLA_PORT_H,
    CLA_PORT_I,
    CLA_PORT_J,
    CLA_PORT_K,
    CLA_PORT_L,
    CLA_PORT_M,
    CLA_PORT_N,
    CLA_PORT_O,
    CLA_PORT_P,
    CLA_VERSION,
    CLA_PRINT_TX_STATISTICS,
    CLA_PRINT_TEMPERATURES,
    CLA_PRINT_VOLTAGES,
    CLA_PRINT_TREE,
    CLA_SET_ATTRIBUTE,
    CLA_GET_ATTRIBUTE,
    CLA_ATTRIBUTE_INDEX,
    CLA_FRAMER_FILE,
    CLA_FORCE_NO_DEFAULT
};

typedef struct
{
	const char *token_string;
	int token_code;
	dag_attribute_code_t attribute_code;
} token_attr_code_t;

token_attr_code_t token_attr_array[] =
{
	{"", T_ERROR, kAttributeInvalid},
	{"atm", T_ATM, kUint32AttributeNetworkMode},						// in kComponentDemapper, kComponentMapper
	{"atm", T_ATM, kUint32AttributePayloadMapping}, 					// in kComponentPort
	{"", T_TEST_A, kAttributeInvalid},							// Not implemented anywhere
	{"", T_TEST_B, kAttributeInvalid},							// Not implemented anywhere
	{"", T_TEST_C, kAttributeInvalid},							// Not implemented anywhere
	{"(no)ahec", T_ATM_ADD_HEC, kAttributeInvalid},						// Not implemented anywhere
	{"(no)descramble", T_ATM_DESCRAMBLE, kBooleanAttributeDescramble},			// in kComponentPort
	{"(no)afix", T_ATM_FIX_HEC, kAttributeInvalid},						// Not implemented in dagconfig (only in dagthree)
	{"(no)lcell", T_ATM_LCELL, kAttributeInvalid},						// Not implemented in dagconfig (only in dagapi)
	{"ncells=x", T_ATM_NCELLS, kAttributeInvalid},						// Not implemented anywhere
	{"(no)apass", T_ATM_PASS_HEC, kAttributeInvalid},					// Not implemented in dagconfig (only in dagthree)
	{"(no)aidle", T_ATM_PASS_IDLE, kBooleanAttributeIdleCellMode},				// in kComponentDemapper
	{"(no)ascramble", T_ATM_PLOAD_SCRAMBLE, kAttributeInvalid},				// Not implemented in dagconfig (only in dagthree)
	{"default", T_DEFAULT, kAttributeInvalid},						// corresponds to dag_config_default()
	{"default_ds3_atm", T_DEFAULT_DS3_ATM, kNullAttributeDefaultDS3ATM},			// Not implemented in dagconfig (only in dagthree)
	{"default_ds3_hdlc", T_DEFAULT_DS3_HDLC, kNullAttributeDefaultDS3HDLC},			// Not implemented in dagconfig (only in dagthree)
	{"default_e3_atm", T_DEFAULT_E3_ATM, kNullAttributeDefaultE3ATM},			// Not implemented in dagconfig (only in dagthree)
	{"default_e3_hdlc", T_DEFAULT_E3_HDLC, kNullAttributeDefaultE3HDLC},			// Not implemented in dagconfig (only in dagthree)
	{"default_e3_hdlc_fract", T_DEFAULT_E3_HDLC_FRACT, kAttributeInvalid},			// Not implemented in dagconfig (only in dagthree)
	{"default_kentrox", T_DEFAULT_KENTROX, kNullAttributeDefaultKentrox},			// Not implemented in dagconfig (only in dagthree)
	{"clock_(set|clear)", T_DUCK_SET_TO_HOST, kNullAttributeDUCKSetToHost},			// in kComponentDUCK
 	{"syncthresh=x", T_DUCK_SYNC_THRESH, kUint32AttributeDUCKThreshold},			// in kComponentDUCK
	{"eth", T_ETH, kUint32AttributeEthernetMode},						// in kComponentPort
	{"10", T_ETH_10, kUint32AttributeLineRate},						// in the port component
	{"100", T_ETH_100, kUint32AttributeLineRate},						// in the port component
	{"ge_status", T_ETH_1000_STATUS, kAttributeInvalid},					// Not implemented in dagconfig (only in dagthree)
	{"1000", T_ETH_1000, kUint32AttributeLineRate},						// in the port component
	{"10G",T_ETH_10G,kUint32AttributeLineRate},						// in the port component
	{"auto,(no)nic,(no)auto_neg", T_ETH_AUTO, kBooleanAttributeNic},			// in kComponentPort
	{"(w|l)an", T_ETH_WAN, kUint32AttributeEthernetMode},					// in kComponentPort
    /* FIXME 2 attribs maps to same token.have to change if they come together */
	{"(w|l)an", T_ETH_WAN, kBooleanAttributeWanMode},                                       // in kComponentPort
	{"(no)ff00del", T_FF_00_DEL, kBooleanAttributeFF00Delete},				// in kComponentPort
	{"(no)align64", T_GPP_ALIGN64, kBooleanAttributeAlign64},				// in kComponentGpp, kComponentSRGPP
	{"(en|dis)ablea", T_GPP_ENABLE_A, kBooleanAttributeActive},				// in kComponentGpp
	{"(en|dis)ableb", T_GPP_ENABLE_B, kBooleanAttributeActive},				// in kComponentGpp
	{"(en|dis)ablec", T_GPP_ENABLE_C, kBooleanAttributeActive},				// in kComponentGpp
	{"(en|dis)abled", T_GPP_ENABLE_D, kBooleanAttributeActive},				// in kComponentGpp
        {"(en|dis)ablee", T_GPP_ENABLE_E, kBooleanAttributeActive},                             // in kComponentGpp
        {"(en|dis)ablef", T_GPP_ENABLE_F, kBooleanAttributeActive},                             // in kComponentGpp
        {"(en|dis)ableg", T_GPP_ENABLE_G, kBooleanAttributeActive},                             // in kComponentGpp
        {"(en|dis)ableh", T_GPP_ENABLE_H, kBooleanAttributeActive},                             // in kComponentGpp
        {"(en|dis)ablei", T_GPP_ENABLE_I, kBooleanAttributeActive},                             // in kComponentGpp
        {"(en|dis)ablej", T_GPP_ENABLE_J, kBooleanAttributeActive},                             // in kComponentGpp
        {"(en|dis)ablek", T_GPP_ENABLE_K, kBooleanAttributeActive},                             // in kComponentGpp
        {"(en|dis)ablel", T_GPP_ENABLE_L, kBooleanAttributeActive},                             // in kComponentGpp
        {"(en|dis)ablem", T_GPP_ENABLE_M, kBooleanAttributeActive},                             // in kComponentGpp
        {"(en|dis)ablen", T_GPP_ENABLE_N, kBooleanAttributeActive},                             // in kComponentGpp
        {"(en|dis)ableo", T_GPP_ENABLE_O, kBooleanAttributeActive},                             // in kComponentGpp
        {"(en|dis)ablep", T_GPP_ENABLE_P, kBooleanAttributeActive},                             // in kComponentGpp
        {"slen=x", T_GPP_SLEN, kUint32AttributeSnaplength},					// in kComponentGpp, kComponentSRGPP
	{"slen=x", T_GPP_SLEN, kUint32AttributeHDLCSnaplength},	 				// in kComponentDemapper
	{"rawslen=x", T_RAW_SLEN, kUint32AttributeRAWSnaplength},				// in kComponentDemapper
	{"", T_E3_CC_FRACT, kAttributeInvalid},							// Not implemented anywhere
	{"(en|dis)ablea", T_GPP_ENABLE_A, kBooleanAttributeRxEnable},				// in kComponentXGMII for Dag9.2 cards
	{"(en|dis)ableb", T_GPP_ENABLE_B, kBooleanAttributeRxEnable},				// in kComponentXGMII for Dag9.2 cards
	{"(no)varlen,fixed", T_GPP_VARLEN, kBooleanAttributeVarlen},				// in kComponentGpp
	{"hdlc", T_HDLC, kUint32AttributePayloadMapping}, 					// in kComponentPort
	{"ppp", T_PPP, kAttributeInvalid},							// Not implemented anywhere
	{"(no)ifaceswap", T_INTERFACE_SWAP, kBooleanAttributeSwap},				// in kComponentMux (3.7ge)
	{"(no)adm", T_LINK_ADM, kAttributeInvalid},						// Not implemented in dagconfig (only in dagthree)
	{"(no)analog_los", T_LINK_ANALOG_LOS, kAttributeInvalid},				// Not implemented anywhere
	{"async", T_LINK_ASYNC1, kUint32AttributePayloadMapping},				// in kComponentSonic
	{"b8zs", T_LINK_B8ZS, kUint32AttributeZeroCodeSuppress},				// in kcomponetPort
	{"ami", T_LINK_AMI, kUint32AttributeZeroCodeSuppress},					// in kcomponetPort
	{"bitsync", T_LINK_BIT_SYNC, kUint32AttributePayloadMapping},				// in kComponentSonic
	{"bytesync1", T_LINK_BYTE_SYNC1, kUint32AttributePayloadMapping},			// in kComponentSonic
	{"bytesync2", T_LINK_BYTE_SYNC2, kUint32AttributePayloadMapping},			// in kComponentSonic
	{"clear", T_LINK_CLEAR, kAttributeInvalid},						// Not implemented in dagconfig (only in dagthree)
	{"core(on|off),(no)coreon", T_LINK_CORE_ON, kAttributeInvalid},				// Not implemented anywhere
	{"(no)crc", T_LINK_CRC, kUint32AttributeCrcSelect},					// in kComponentDemapper, kComponentMapper, kComponentPort
	{"(no)dcr", T_LINK_DCR, kAttributeInvalid},						// Not implemented anywhere
	{"(no)digital_los", T_LINK_DIGITAL_LOS, kAttributeInvalid},				// Not implemented anywhere
	{"(no)discard", T_LINK_DISCARD, kBooleanAttributeLinkDiscard},				// in kComponentPort
	{"ds3_m23", T_LINK_DS3_M23, kUint32AttributeFramingMode},				// in kComponentPort
	{"ds3_m23_plcp", T_LINK_DS3_M23_PLCP, kUint32AttributeFramingMode},			// in kComponentPort
	{"ds3_m23_if", T_LINK_DS3_M23_IF, kUint32AttributeFramingMode},				// in kComponentPort
	{"ds3_m23_ef", T_LINK_DS3_M23_EF, kUint32AttributeFramingMode},				// in kComponentPort
	{"ds3_m23_ff", T_LINK_DS3_M23_FF, kUint32AttributeFramingMode},				// in kComponentPort
	{"ds3_cbit", T_LINK_DS3_CBIT, kUint32AttributeFramingMode},				// in kComponentPort
	{"ds3_cbit_plcp", T_LINK_DS3_CBIT_PLCP, kUint32AttributeFramingMode},			// in kComponentPort
	{"ds3_cbit_if", T_LINK_DS3_CBIT_IF, kUint32AttributeFramingMode},			// in kComponentPort
	{"ds3_cbit_ef", T_LINK_DS3_CBIT_EF, kUint32AttributeFramingMode},			// in kComponentPort
	{"ds3_cbit_ff", T_LINK_DS3_CBIT_FF, kUint32AttributeFramingMode},			// in kComponentPort
	{"e1_crc", T_LINK_E1_CRC, kUint32AttributeLineType},					// in kComponentE1T1
	{"e1_unframed", T_LINK_E1_UNFRAMED, kUint32AttributeLineType},				// in kComponentE1T1
	{"e1", T_LINK_E1, kUint32AttributeLineType},						// in kComponentE1T1
	{"e3", T_LINK_E3, kUint32AttributeFramingMode},						// in kComponentPort
	{"(no)eql", T_LINK_EQL, kBooleanAttributeEquipmentLoopback},				// in kComponentPort, kComponentPhy
	{"e3_g751", T_LINK_E3_G751, kUint32AttributeFramingMode},				// in kComponentPort
	{"e3_g751_plcp", T_LINK_E3_G751_PLCP, kUint32AttributeFramingMode},			// in kComponentPort
	{"e3_g751_if", T_LINK_E3_G751_IF, kUint32AttributeFramingMode},				// in kComponentPort
	{"e3_cc", T_LINK_E3_CC, kUint32AttributeFramingMode},					// in kComponentPort
	{"fract=x", T_LINK_E3_HDLC_FRACT, kUint32AttributeHDLCFraction},			// in kComponentPort
	{"(no)eql_f", T_D37D_FRAMER_LOOPBACK, kAttributeInvalid},				// Not implemented anywhere
	{"(no)fcl", T_LINK_FCL, kBooleanAttributeFacilityLoopback},				// in kComponentPort, kComponentPhy
	{"(no)hgain,(no)highgain", T_LINK_HGAIN, kAttributeInvalid},				// Not implemented in dagconfig (only in dagthree)
	{"(no)laser", T_LINK_LASER, kBooleanAttributeLaser},					// in kComponentPort, kComponentOptics
	{"(no)muxeql,(no)lseql", T_LINK_LSEQL, kBooleanAttributeLineSideEquipmentLoopback},	// in kComponentPort
	{"(no)muxfcl,(no)lsfcl", T_LINK_LSFCL, kBooleanAttributeLineSideFacilityLoopback},	// in kComponentPort
	{"(no)lt0", T_LINK_LT0, kAttributeInvalid},						// Not implemented in dagconfig (only in dagthree)
	{"(no)lt1", T_LINK_LT1, kAttributeInvalid},						// Not implemented anywhere
	{"(no)m23", T_LINK_M23, kAttributeInvalid},						// Not implemented in dagconfig (only in dagthree)
	{"mode=x", T_LINK_MODE, kUint32AttributeMode},						// in kComponentPort
	{"oc1(c)", T_LINK_OC1, kUint32AttributeLineRate},					// in kComponentDemapper, kComponentSonetPP
	{"oc3(c)", T_LINK_OC3, kUint32AttributeLineRate},					// in kComponentSonic, kComponentDemapper, kComponentSonetPP
	{"oc12(c)", T_LINK_OC12, kUint32AttributeLineRate},					// in kComponentSonic, kComponentDemapper, kComponentSonetPP
	{"oc48(c)", T_LINK_OC48, kUint32AttributeLineRate},					// in kComponentDemapper, kComponentSonetPP
	{"oc192(c)", T_LINK_OC192, kUint32AttributeLineRate},					// in kComponentDemapper, kComponentSonetPP
	{"(no)pdhglobal", T_LINK_PDH_GLOBAL, kAttributeInvalid},				// Not implemented anywhere
	{"(no)reset", T_LINK_RESET, kAttributeInvalid},						// corresponds to dag_config_reset()
	{"(no)rktiopwr", T_LINK_RKTIOPWR, kBooleanAttributeRocketIOPower},			// in kComponentPort
	{"rxtermext", T_LINK_RX_TERMEXT, kAttributeInvalid},					// Not implemented in dagconfig (only in dagthree)
	{"(no)sfppwr", T_LINK_SFPPWR, kBooleanAttributeSfpPwr},					// in kComponentPort, kComponentOptics
	{"t1", T_LINK_T1, kUint32AttributeLineType},						// in kComponetE1T1  (also in dagthree)
	{"t1_esf", T_LINK_T1_ESF, kUint32AttributeLineType},					// in kComponentE1T1 (also in dagthree)
	{"t1_sf", T_LINK_T1_SF, kUint32AttributeLineType},					// in kComponentE1T1 (also in dagthree)
	{"t1_unframed", T_LINK_T1_UNFRAMED, kUint32AttributeLineType},				// in kComponentE1T1 (also in dagthree)
	{"term75", T_LINK_TERM75, kUint32AttributeTermination},				        // in port component 
	{"term100", T_LINK_TERM100,kUint32AttributeTermination},				// in port component
	{"term120", T_LINK_TERM120, kUint32AttributeTermination},				// in port component
	{"termext", T_LINK_TERMEXT, kUint32AttributeTermination},				// in port component
	{"tu11", T_LINK_TU11, kUint32AttributeTributaryUnit},					// in kComponentSonic
	{"tu12", T_LINK_TU12, kUint32AttributeTributaryUnit},					// in kComponentSonic
	{"tunomap", T_LINK_TUNOMAP, kAttributeInvalid},						// Not implemented anywhere
	{"txtermext", T_LINK_TX_TERMEXT, kAttributeInvalid},					// Not implemented in dagconfig (only in dagthree)
	{"vc3", T_LINK_VC3, kUint32AttributeVCSize},						// in kComponentSonic
	{"vc4", T_LINK_VC4, kUint32AttributeVCSize},						// in kComponentSonic
	{"vc4c", T_LINK_VC4C, kUint32AttributeVCSize},						// in kComponentSonic
	{"link=all,link=x", T_LINK_WHICH, kAttributeInvalid},					// Not implemented in dagconfig (only in dagthree)
	{"", T_LIU_LOOPBACK, kAttributeInvalid},						// Not implemented anywhere
	{"master,noslave", T_MASTER, kUint32AttributeMasterSlave},				// in kComponentPort
	{"(P|p)(ort)(a-h|A-H)=(S|s)(tream)x", T_MUX_CONFIG, kAttributeInvalid},			// Not implemented in dagconfig (only in dagthree)
	{"rxmerge", T_MUX_RXMERGE, kAttributeInvalid},						// Not implemented in dagconfig (only in dagthree)
	{"rxsplit", T_MUX_RXSPLIT, kAttributeInvalid},						// Not implemented in dagconfig (only in dagthree)
	{"mem=x1:x2...", T_PBM_MEMCONFIG, kAttributeInvalid},					// corresponds to dag_config_util_domemconfig()
	{"(no)overlap", T_PBM_OVERLAP, kBooleanAttributeOverlap},				// in kComponentPbm
	{"(no)drop", T_PBM_DROP, kBooleanAttributeDrop},					// in kComponentPbm
	{"rxonly", T_PBM_RXONLY, kAttributeInvalid},						// corresponds to dag_config_util_domemconfig(), but on 7.1s it uses kUint32AttributeMem in kComponentStream
	{"rxtx", T_PBM_RXTX, kAttributeInvalid},						// corresponds to dag_config_util_domemconfig() (also in dagthree and dagfour)
	{"txonly", T_PBM_TXONLY, kAttributeInvalid},						// corresponds to dag_config_util_domemconfig(), but on 7.1s it uses kUint32AttributeMem in kComponentStream
	{"crc16", T_POS_CRC16, kUint32AttributeCrcSelect},					// in kComponentDemapper, kComponentMapper
	{"crc32", T_POS_CRC32, kUint32AttributeCrcSelect},					// in kComponentDemapper, kComponentMapper
	{"(no)crcstrip", T_POS_CRCSTRIP, kBooleanAttributeCrcStrip},				// in kComponentPort
	{"(no)pmax", T_POS_MAXCHECK, kBooleanAttributePMaxCheck},				// in kComponentPort
	{"long=x", T_POS_MAXLEN, kUint32AttributeMaxPktLen},					// in kComponentPort
	{"(no)pmin", T_POS_MINCHECK, kBooleanAttributePMinCheck},				// in kComponentPort
	{"short=x", T_POS_MINLEN, kUint32AttributeMinPktLen},					// in kComponentPort
	{"(no)rxpkts", T_POS_RXPKTS, kBooleanAttributeRxPkts},					// in kComponentPort 
	{"(no)pscramble", T_POS_SCRAMBLE, kBooleanAttributePayloadScramble},			// in kComponentDemapper, kComponentMapper, kComponentPort
	{"(no)txpkts", T_POS_TXPKTS, kBooleanAttributeTxPkts},					// in kComponentPort
        {"(no)hec_correction", T_HEC_CORRECTION, kBooleanAttributeHECCorrection},               // in KComponentPort
        {"pos", T_POS, kUint32AttributeNetworkMode},						// in kComponentDemapper, kComponentMapper
	//{"pos", T_POS, kUint32AttributeEthernetMode},						// in kComponentPort
	{"raw", T_RAW, kUint32AttributeNetworkMode},						// in kComponentPort
	{"(no)rx_redundancy", T_REDUNDANCY_CONTROL, kAttributeInvalid},				// Not implemented anywhere
	{"(no)rx_monitor", T_RX_MONITOR_MODE, kBooleanAttributeRXMonitorMode},			// in kComponentPort
	{"(no)rx_equalizer", T_RX_EQUALIZER, kAttributeInvalid},				// Not implemented anywhere
	{"(en|dis)ablesar", T_SAR_ENABLE, kAttributeInvalid},					// Not implemented in dagconfig (only in dagsar)
	{"nni", T_SAR_NNI, kAttributeInvalid},							// Not implemented in dagconfig (only in dagsar)
	{"uni", T_SAR_UNI, kAttributeInvalid},							// Not implemented in dagconfig (only in dagsar)
	{"(no)cells", T_SAR_CELLS, kAttributeInvalid},						// Not implemented in dagconfig (only in dagthree)
	{"(no)frames", T_SAR_FRAMES, kAttributeInvalid},					// Not implemented in dagconfig (only in dagthree)
	{"slave,nomaster", T_SLAVE, kUint32AttributeMasterSlave},				// in kComponentPort
	{"(no)scramble", T_SONET_SCRAMBLE, kBooleanAttributeScramble},				// in kComponentSonic, kComponentDemapper
	{"(no)sfm", T_SFM, kAttributeInvalid},							// Not implemented anywhere
	{"(no)sfm_clock", T_SFM_CLOCK, kAttributeInvalid},					// Not implemented anywhere
	{"terf_strip16", T_TERF_STRIP_16, kUint32AttributeTerfStripCrc},			// in kComponentTerf
	{"terf_strip32", T_TERF_STRIP_32, kUint32AttributeTerfStripCrc},			// in kComponentTerf
	{"noterf_strip", T_TERF_NOSTRIP, kUint32AttributeTerfStripCrc},				// in kComponentTerf
	{"nodelay", T_TR_TERF_NO_DELAY, kUint32AttributeTimeMode},				// in kComponentTerf
	{"relative", T_TR_TERF_RELATIVE, kUint32AttributeTimeMode},				// in kComponentTerf
	{"(no)txrxerror", T_TR_TERF_RX_ERROR, kBooleanAttributeRXErrorA},			// in kComponentTerf
	{"(no)txrxerror", T_TR_TERF_RX_ERROR, kBooleanAttributeRXErrorB},			// in kComponentTerf
	{"(no)txrxerror", T_TR_TERF_RX_ERROR, kBooleanAttributeRXErrorC},			// in kComponentTerf
	{"(no)txrxerror", T_TR_TERF_RX_ERROR, kBooleanAttributeRXErrorD},			// in kComponentTerf
	{"steer=(stream0|parity|crc|iface|colour|dsm)", T_STEER, kUint32AttributeSteer},	// in kComponentPort, kComponentSteering, kComponentMux
	{"head", T_TIMESTAMP_HEAD, kBooleanAttributeTimeStampEnd},				// in kComponentDemapper
	{"tail", T_TIMESTAMP_TAIL, kBooleanAttributeTimeStampEnd},				// in kComponentDemapper
	{"(no)tx_crc", T_TX_CRC, kBooleanAttributeTxCrc},					// in kComponentXGMII
	{"(no)promisc", T_ETH_PROMISC, kAttributeInvalid},					// Not implemented in dagconfig (only in dagfour)
	{"10gbase_sr", T_ETH_10GBASESR, kUint32AttributeEthernetMode},				// in kComponentPort
	{"10gbase_lr", T_ETH_10GBASELR, kUint32AttributeEthernetMode},				// in kComponentPort
	{"10gbase_er", T_ETH_10GBASEER, kUint32AttributeEthernetMode},				// in kComponentPort
	{"sgmii", T_ETH_SGMII, kAttributeInvalid},						// Not implemented anywhere
	{"gbic", T_ETH_GBIC, kAttributeInvalid},						// Not implemented anywhere
	{"(no)pathoam", T_SAR_PATH_OAM, kAttributeInvalid},					// Not implemented in dagconfig (only in dagsar)
	{"hlb=x1-x2:x3-x4:...", T_HLB_RANGE, kStructAttributeHlbRange},				// corresponds to dag_config_util_do_hlb_config()
	{"hat=x1-x2:x3-x4:...", T_HAT_RANGE, kStructAttributeHATRange},				// corresponds to dag_config_util_do_hlb_config()
	{"(no)errorflag", T_SUPPRESS_ERROR, kBooleanAttributeSuppressError},			// in kComponentGeneral
	{"sonet", T_SONET, kBooleanAttributeSonetMode},						// in the port component
	{"sdh", T_SDH, kBooleanAttributeSonetMode},						// in the port component
	{"", T_MAX, kAttributeInvalid},								// Not implemented in dagconfig (only in dagapi)
	{"idelay=x", T_IDELAY, kUint32AttributeIDELAY},						// in the port component
	{"status=x,drop=x,tapmode", T_INFINIBAND_TAPMODE, kAttributeInvalid},			// corresponds to dag_config_set_infiniband_mode()
	{"(invert|normal)polarity", T_INFINIBAND_FRAMER_INVERT_POLARITY, kAttributeInvalid},	// corresponds to dag_config_invert_infiniband_framer_polarity()
	{"stm0", T_LINK_STM0, kUint32AttributeLineRate},					// in kComponentSonetPP
	{"stm1", T_LINK_STM1, kUint32AttributeLineRate},					// in kComponentSonetPP
	{"stm4", T_LINK_STM4, kUint32AttributeLineRate},					// in kComponentSonetPP
	{"stm16", T_LINK_STM16, kUint32AttributeLineRate},					// in kComponentSonetPP
	{"stm64", T_LINK_STM64, kUint32AttributeLineRate},					// in kComponentSonetPP
	{"", 0, kAttributeInvalid}
};

        
static char dagname[BUFFER_SIZE];
static ClArgPtr clarg = 0;
static int dagstream = 0;
static char dagname_buf[BUFFER_SIZE] = "dag0";

static char get_buffer[SET_GET_ATTRIBUTE_BUF_SIZE];
static char set_buffer[SET_GET_ATTRIBUTE_BUF_SIZE];
static char framerfirmware[FRAMER_FIRMWARE_FILE_SIZE];
static void add_verbose_option(int* val);
/*card ref made global to be used in process_cmdline_options*/
dag_card_ref_t card_ref;
struct dagconfigure_options_t
{
    char mConnCfgFilename[BUFFER_SIZE];
    int mRepeatInterval;
    const char** mConfigureString;
    int mConfigureCount;
    int mConnCfgFileValid;
    int mVerbose;
    int mPortSelect;
    int mVerbosityLevel;
    int mFunc;
    int mInfo;
    int mAttributeIndex;
};

static void
print_version(void)
{
	printf("dagconfig (DAG %s) %s\n", kDagReleaseVersion, kRevisionString);
}

void
add_default_cmdline_options(dagconfigure_options_t* options)
{
	/* Set up default DAG device. */
	if (-1 == dag_parse_name(dagname_buf, dagname, BUFFER_SIZE, &dagstream))
	{
        	dagutil_panic("dag_parse_name(%s): %s\n", dagname_buf, strerror(errno));
	}
    dagclarg_add_string(clarg, "DAG device to use.", "--device", 'd', "device", dagname_buf, DAGNAME_BUFSIZE, CLA_DEVICE);
    dagclarg_add(clarg, "This page.", "--help", 'h', CLA_HELP);
    add_verbose_option(&(options->mVerbosityLevel));
    dagclarg_add(clarg, "Display version information.", "--version", 'V', CLA_VERSION);
    add_print_statistics();
    add_interval_option(&(options->mRepeatInterval));
}

void
add_print_statistics()
{
    dagclarg_add(clarg, "Print the basic link statistics/state.", "--statistics", 's', CLA_PRINT_STATISTICS);
}
void
add_print_tx_statistics()
{
    dagclarg_add(clarg, "Print transmit statistics.", "--txstats", 't',CLA_PRINT_TX_STATISTICS);
}
void
add_print_extended_current_statistics()
{
    dagclarg_add(clarg, "Print current extended statistics.", "--extended", 'e',CLA_PRINT_EXTENDED_CURRENT_STATISTICS);
}
void
add_print_extended_hi_statistics()
{
    dagclarg_add(clarg, "Print hi extended statistics.", "--hi",'H' , CLA_PRINT_EXTENDED_HI_STATISTICS);
}
void
add_print_extended_lo_statistics()
{
    dagclarg_add(clarg, "Print lo extended statistics.", "--lo", 'L', CLA_PRINT_EXTENDED_LO_STATISTICS);
}
void
add_connection_config_option(char* val, int len)
{
    dagclarg_add_string(clarg, "Connection configuration.", "--concfg", 'c', "conncfg", val, len, CLA_CONNECTION_CONFIG);
}

void
add_counters_option()
{
    dagclarg_add(clarg, "Print the counters", "--counters", 'C', CLA_PRINT_COUNTERS);
}

void
add_univ_counters_option()
{
    dagclarg_add(clarg, "Print universal counters", "--ucounters", 'u', CLA_PRINT_UNIV_COUNTERS);
}

void
add_interval_option(int * val)
{
    dagclarg_add_int(clarg, "Interval to repeat in seconds.", "--interval", 'i', "seconds", val, CLA_REPEAT_INTERVAL);
}

void
add_verbose_option(int* val)
{
    dagclarg_add_int(clarg, "Set the verbosity level.", "--verbose", 'v', "level", val, CLA_VERBOSE);
}
void
add_framer_file_option(int* val)
{
  	dagclarg_add_string(clarg, "framer firmware file.", "--framerfirmware",0, "framerfirmware", framerfirmware, FRAMER_FIRMWARE_FILE_SIZE,CLA_FRAMER_FILE);
}



void
dagconfigure_add_cmdline_options(dagconfigure_options_t* options)
{
	int result = 0;
	int argindex = 0;
	int code = 0;
	int card_type = 0;
	uint32_t iface_count = 0;
	add_default_cmdline_options(options);
	

	/* Parse the command line options. */

	result = dagclarg_parse(clarg, NULL, &argindex, &code);
	
	while (1 == result)
	{
		switch (code)
		{
			case CLA_DEVICE:
				if (-1 == dag_parse_name(dagname_buf, dagname, DAGNAME_BUFSIZE, &dagstream))
				{
					dagutil_panic("dag_parse_name(%s): %s\n", dagname_buf, strerror(errno));
				}
				break;

		}
		result = dagclarg_parse(clarg, NULL, &argindex, &code);

	}
	dagclarg_reset(clarg);

	card_ref = dag_config_init(dagname);
	if (card_ref == NULL)
	{
		return;
	}

	iface_count = dag_config_get_interface_count(card_ref); 

	card_type = dag_config_get_card_type(card_ref);
	switch (card_type)
	{
		case kDag71s:
			add_print_extended_current_statistics();
			add_connection_config_option(options->mConnCfgFilename, BUFFER_SIZE);
			dagclarg_add(clarg, "Port A only (default all).", "--porta", '1', CLA_PORT_A);
			dagclarg_add(clarg, "Port B only (default all).", "--portb", '2', CLA_PORT_B);
			dagclarg_add(clarg, "Port C only (default all).", "--portc", '3', CLA_PORT_C);
			dagclarg_add(clarg, "Port D only (default all).", "--portd", '4', CLA_PORT_D);
			break;
			
		case kDag452gf:
		case kDag452e:
		case kDag454e:
		case kDag452cf:
		case kDag452z:
		case kDag452z8:
			add_print_extended_hi_statistics();
			add_print_extended_current_statistics();
			add_print_extended_lo_statistics();
			add_print_tx_statistics();
			add_counters_option();
			add_univ_counters_option();
			dagclarg_add(clarg, "Port A only (default all).", "--porta", '1', CLA_PORT_A);
			dagclarg_add(clarg, "Port B only (default all).", "--portb", '2', CLA_PORT_B);
			if (card_type == kDag454e)
			{
				dagclarg_add(clarg, "Port C only (default all).", "--portc", '3', CLA_PORT_C);
				dagclarg_add(clarg, "Port D only (default all).", "--portd", '4', CLA_PORT_D);
			}
			break;

#if 0
		case kDag82x:
		case kDag82z:
		case kDag52x:
		case kDag50s:
		case kDag50sg2a:
		case kDag50sg2adup:
		case kDag52sxa:
		case kDag810:
		case kDag840:
		case kDag50z:
		case kDag50dup:
			add_counters_option();
			add_univ_counters_option();
			add_print_extended_current_statistics();
			add_print_tx_statistics();
			if (card_type == kDag50s || card_type == kDag50z || card_type == kDag50dup || card_type == kDag840)
			{
				dagclarg_add(clarg, "Port A only (default all).", "--porta", '1', CLA_PORT_A);
				dagclarg_add(clarg, "Port B only (default all).", "--portb", '2', CLA_PORT_B);
			}
			break;
#endif
			
		case kDag37t:
			/*
			Becasue dagclarg does shallow copies of the string porinters (descrption, cmd) we can't use a dynamically allocated memory
			and put this code in a loop - tried it and it leaks. dagclarg should be mdoified to do deep copies. shallow copying sucks if
			there is no shared pointer implementation
			*/
			add_print_extended_current_statistics();
            dagclarg_add(clarg, "Port A only","--porta", '1', CLA_PORT_A);
			dagclarg_add(clarg, "Port B only","--portb", '2', CLA_PORT_B);
			dagclarg_add(clarg, "Port C only","--portc", '3', CLA_PORT_C);
			dagclarg_add(clarg, "Port D only","--portd", '4', CLA_PORT_D);
			dagclarg_add(clarg, "Port E only","--porte", '5', CLA_PORT_E);
			dagclarg_add(clarg, "Port F only","--portf", '6', CLA_PORT_F);
			dagclarg_add(clarg, "Port G only","--portg", '7', CLA_PORT_G);
			dagclarg_add(clarg, "Port H only","--porth", '8', CLA_PORT_H);
			dagclarg_add(clarg, "Port I only","--porti", 0, CLA_PORT_I);
			dagclarg_add(clarg, "Port J only","--portj", 0, CLA_PORT_J);
			dagclarg_add(clarg, "Port K only","--portk", 0, CLA_PORT_K);
			dagclarg_add(clarg, "Port L only","--portl", 0, CLA_PORT_L);
			dagclarg_add(clarg, "Port M only","--portm", 0, CLA_PORT_M);
			dagclarg_add(clarg, "Port N only","--portn", 0, CLA_PORT_N);
			dagclarg_add(clarg, "Port O only","--porto", 0, CLA_PORT_O);
			dagclarg_add(clarg, "Port P only","--portp", 0, CLA_PORT_P);
			break;
		
		default:
			add_counters_option();
			add_univ_counters_option();
			add_print_extended_current_statistics();
			add_print_tx_statistics();
			if (iface_count > 1)
			{
				dagclarg_add(clarg, "Port A only (default all).", "--porta", '1', CLA_PORT_A);
				dagclarg_add(clarg, "Port B only (default all).", "--portb", '2', CLA_PORT_B);
				
				if (iface_count > 2)
				{
					dagclarg_add(clarg, "Port C only (default all).", "--portc", '3', CLA_PORT_C);
					dagclarg_add(clarg, "Port D only (default all).", "--portd", '4', CLA_PORT_D);
				}
				if (iface_count > 4)
				{
					dagclarg_add(clarg, "Port E only (default all).", "--porte", '5', CLA_PORT_E);
					dagclarg_add(clarg, "Port F only (default all).", "--portf", '6', CLA_PORT_F);
					dagclarg_add(clarg, "Port G only (default all).", "--portg", '7', CLA_PORT_E);
					dagclarg_add(clarg, "Port H only (default all).", "--porth", '8', CLA_PORT_F);
				}
			}
			break;
	}
	
	dagclarg_add(clarg, "Print card temperature monitor information.", "--hmon", 'm', CLA_PRINT_TEMPERATURES);
	dagclarg_add(clarg, "Print card voltage monitor information.", "--voltages", 'n', CLA_PRINT_VOLTAGES);
	dagclarg_add(clarg, "Dag config print tree of components and attributes","--tree", 'T', CLA_PRINT_TREE);
	dagclarg_add_string(clarg, "Set attribute from dagconfig using Name","--setattribute",'S',"setattribute",set_buffer, SET_GET_ATTRIBUTE_BUF_SIZE, CLA_SET_ATTRIBUTE);
    	dagclarg_add_string(clarg,"Get attribute from dagconfig using Name","--getattribute",'G',"getattribute",get_buffer, SET_GET_ATTRIBUTE_BUF_SIZE, CLA_GET_ATTRIBUTE);
	dagclarg_add_int(clarg, "Index of the attribute. To be used with Get or Set attribute", "--attribute-index", 0, "index", &(options->mAttributeIndex) , CLA_ATTRIBUTE_INDEX);
	dagclarg_add_string(clarg, "framer firmware file.", "--framerfirmware", 0, "framer-firmware", framerfirmware, FRAMER_FIRMWARE_FILE_SIZE,CLA_FRAMER_FILE);
	dagclarg_add(clarg, "Do not run default automatically after reset", "--no-default", 0, CLA_FORCE_NO_DEFAULT);

	//dag_config_dispose(card_ref);
}

const char*
options_get_connection_config_filename(const dagconfigure_options_t* options)
{
    return options->mConnCfgFilename;
}

int
options_get_repeat_interval(dagconfigure_options_t* options)
{
    return options->mRepeatInterval;
}

int
options_get_verbostiy_level(const dagconfigure_options_t* options)
{
    return options->mVerbosityLevel;
}

int
options_get_port_select(const dagconfigure_options_t* options)
{
    return options->mPortSelect;
}

int
options_get_verbosity_level(const dagconfigure_options_t* options)
{
    return options->mVerbosityLevel;
}

int
options_get_verbose(const dagconfigure_options_t* options)
{
    return options->mVerbose;
}

int
options_get_func(const dagconfigure_options_t* options)
{
    return options->mFunc;
}
int
options_get_info(const dagconfigure_options_t* options)
{
    return options->mInfo;
}
dagconfigure_options_t*
dagconfigure_options_init(int argc, const char** const argv)
{
    dagconfigure_options_t* options = NULL;
    options = (dagconfigure_options_t*)malloc(sizeof(dagconfigure_options_t));
    memset(options, 0, sizeof(dagconfigure_options_t));
    options->mPortSelect = 0xffff; /* All ports (have 16 ports on the 3.7t hence need 16 bits for each one. */
    options->mFunc = FUNC_DEFAULT;
    options->mInfo = INFO_NONE;
    options->mAttributeIndex = 0;/* if the index is not given,print the first attribute's details */
    clarg = dagclarg_init(argc, (const char** const)argv);
    return options;
}

void
dagconfigure_options_dispose(dagconfigure_options_t* options)
{
	free(options);
	dagclarg_dispose(clarg);
}


int
process_cmdline_options(dagconfigure_options_t* options, int argc, const char** const argv)
{
    int result = 0;
    int argindex;
    int code;
    int first_port_select = 1;
    int port_bit = 0x8000;
    const char *attr_value;
    int value = 0;
    uint32_t attribute_index = 0;
    /* Parse the command line options. */
	result = dagclarg_parse(clarg, NULL, &argindex, &code);
	while (1 == result)
	{
		port_bit = 0x8000;
		switch (code)
		{
            case CLA_DEVICE:
                if (-1 == dag_parse_name(dagname_buf, dagname, DAGNAME_BUFSIZE, &dagstream))
                {
                    dagutil_panic("dag_parse_name(%s): %s\n", dagname_buf, strerror(errno));
                }
                break;

            case CLA_HELP:
		//TODO: get back the dagclarg_display_usage
		// and extend the actual options supported
		print_help_header();
		dagclarg_display_usage(clarg, stdout);
                print_token_attribute_usage();
		print_token_functional_usage();
                return EXIT_SUCCESS;

            case CLA_PRINT_STATISTICS:
                options->mFunc |= FUNC_PRINT_INFO;
                options->mInfo |= INFO_STATS;
                break;
                
            case CLA_PRINT_EXTENDED_CURRENT_STATISTICS:
                options->mFunc |= FUNC_PRINT_INFO;
                options->mInfo |= INFO_EXT_STATS; 
                break;
                
            case CLA_PRINT_EXTENDED_HI_STATISTICS:
                options->mFunc |= FUNC_PRINT_INFO;
                options->mInfo |= INFO_EXT_HI_STATS;
                break;
                
            case CLA_PRINT_EXTENDED_LO_STATISTICS:
                options->mFunc |= FUNC_PRINT_INFO;
                options->mInfo |= INFO_EXT_LO_STATS;
                break;
                
            case CLA_CONNECTION_CONFIG:
                options->mConnCfgFileValid = 1;
                break;
                
            case CLA_PRINT_COUNTERS:
                options->mFunc |= FUNC_PRINT_INFO;
                options->mInfo |= INFO_COUNTERS;
                break;

            case CLA_PRINT_UNIV_COUNTERS:
                options->mFunc |= FUNC_PRINT_INFO;
                options->mInfo |= INFO_UNIV_COUNTERS;
                break;

            case CLA_PRINT_TX_STATISTICS:
                options->mFunc |= FUNC_PRINT_INFO;
                options->mInfo |= INFO_TX_STATISTICS;
                break;

            case CLA_PRINT_TEMPERATURES:
                options->mFunc |= FUNC_PRINT_INFO;
                options->mInfo |= INFO_TEMPERATURE;
                break;
				
            case CLA_PRINT_VOLTAGES:
                options->mFunc |= FUNC_PRINT_INFO;
                options->mInfo |= INFO_VOLTAGE;
                break;

            case CLA_PRINT_TREE:
	    	options->mFunc |= FUNC_PRINT_INFO;
                options->mInfo |= INFO_TREE;
		break;
            case CLA_VERBOSE:
                options->mVerbose = 1;
                break;

	    case CLA_FRAMER_FILE:
		dag_config_amcc_framer_firmware_load(card_ref,framerfirmware);
		break;

            case CLA_PORT_A:
                port_bit >>= 1;
            case CLA_PORT_B:
                port_bit >>= 1;
            case CLA_PORT_C:
                port_bit >>= 1;
            case CLA_PORT_D:
                port_bit >>= 1;
            case CLA_PORT_E:
                port_bit >>= 1;
            case CLA_PORT_F:
                port_bit >>= 1;
            case CLA_PORT_G:
                port_bit >>= 1;
            case CLA_PORT_H:
                port_bit >>= 1;
            case CLA_PORT_I:
                port_bit >>= 1;
            case CLA_PORT_J:
                port_bit >>= 1;
            case CLA_PORT_K:
                port_bit >>= 1;
            case CLA_PORT_L:
                port_bit >>= 1;
            case CLA_PORT_M:
                port_bit >>= 1;
            case CLA_PORT_N:
                port_bit >>= 1;
            case CLA_PORT_O:
                port_bit >>= 1;
            case CLA_PORT_P:
                if (1 == first_port_select)
                {
                    options->mPortSelect = 0;
                    first_port_select = 0;
                }
		options->mPortSelect |= port_bit;
                break;
	   case CLA_SET_ATTRIBUTE:
        /* Quick fix to enable verbosity for set value*/
        if (options_get_verbose(options) == 1)
        {
            dagutil_set_verbosity(options_get_verbosity_level(options));
        }
		if(options->mFunc == FUNC_DEFAULT)
		{
			options->mFunc = FUNC_NONE;
		}
        /* to keep the old behavior take attribute index only if port select is not given*/
        if ((options->mPortSelect == 0xffff))
        {
            /* port select is not given. Use the given attribute index */
            attribute_index = options->mAttributeIndex;
        }
		else if((options->mPortSelect & 0x01) == 1)
		{
			attribute_index = 0;
		}
		else if ((options->mPortSelect & 0x2) == 2)
		{
			attribute_index = 1;
		}
        
		value = dag_config_set_named_attribute_uuid(card_ref,set_buffer,attribute_index);
		if(value == kDagErrNone)
		{	
			attr_value = dag_config_get_named_attribute_value(card_ref,set_buffer,attribute_index);
			if(dag_config_get_last_error(card_ref) == kDagErrNone)
				printf("%s value set to %s\n",set_buffer,attr_value);
			else
				printf("Not able to get the value of %s\n",set_buffer);
		}
		else
			printf("Not able to set the value of the attribute \n");
		
	    	break;
	   case CLA_GET_ATTRIBUTE:
        /* Quick fix to enable verbosity for Get value*/
        if (options_get_verbose(options) == 1)
        {
            dagutil_set_verbosity(options_get_verbosity_level(options));
        }
		if(options->mFunc == FUNC_DEFAULT)
		{
			options->mFunc = FUNC_NONE;
		}
        /* to keep the old behavior take attribute index only if port select is not given*/
        if ((options->mPortSelect == 0xffff))
        {
            /* port select is not given. Use the given attribute index */
            attribute_index = options->mAttributeIndex;
        }
		else if((options->mPortSelect & 0x01) == 1)
		{
			attribute_index = 0;
		}
		else if((options->mPortSelect & 0x02) == 2)
		{
			attribute_index = 1;
		}
         	attr_value = dag_config_get_named_attribute_value(card_ref,get_buffer,attribute_index);
		if(dag_config_get_last_error(card_ref) == kDagErrNone)
			printf(" %s = %s\n",get_buffer,attr_value);
		else
			printf("Not able to set the value of the attribute error = %d\n",dag_config_get_last_error(card_ref));
		break;
	
            case CLA_REPEAT_INTERVAL:
                if(options->mRepeatInterval == 0)
                {
                    options->mRepeatInterval = 1;
                }
                break;
            case CLA_FORCE_NO_DEFAULT:
                    token_proc_set_default_on_reset(0);
                break;
	     case CLA_VERSION:
		print_version();
		return EXIT_SUCCESS;
		break;
        }
        result = dagclarg_parse(clarg, NULL, &argindex, &code);
    }
	if (-1 == result)
	{
		/* Error occurred. */
		if (CLA_REPEAT_INTERVAL == code)
		{
			/* No argument found for -i.
			 * As a special case, we permit -i to have no argument and assume a default of 1. 
			 */
			options->mRepeatInterval = 1;
		}
		else
		{
			if (argindex < argc)
			{
				dagutil_error("while processing option %s\n", argv[argindex]);
			}
			print_help_header();
			dagclarg_display_usage(clarg, stdout);
			print_token_attribute_usage();
			print_token_functional_usage();
			return EXIT_FAILURE;
		}
    }

    options->mConfigureString = (const char**)dagclarg_get_unprocessed_args(clarg, &options->mConfigureCount);
    dag_config_dispose(card_ref);
    return -1;
}

const char**
options_get_configure_string(const dagconfigure_options_t* options)
{
    return options->mConfigureString;
}

int
options_get_configure_string_count(const dagconfigure_options_t* options)
{
    return options->mConfigureCount;
}

const char*
get_dagname(void)
{
    return dagname;
}


static void
print_help_header(void)
{
	const char* help_header = "Description\n\
    dagconfig  is  used  to configure and display statistics from an Endace\n\
    card.  This tool replaces earlier  card  specific  configuration  tools\n\
    such  as  dagthree  (1),  dagfour  (1)  and dagsix (1) and works on all\n\
    Endace cards. The tool is built using Endace’s Configuration and  Status\n\
    API.\n\n";

	printf("%s",help_header);
}

static bool
attribute_is_printable(dag_card_ref_t card_ref, attr_uuid_t attr)
{
	dag_attribute_code_t code;
	int verbosity = dagutil_get_verbosity();

	code = dag_config_get_attribute_code(attr);
	assert(code != kAttributeInvalid );
	
	if(verbosity > 3) 
		return true;
	
	switch (code)
	{
            case kBooleanAttributeSfpPwr:
               if (dag_config_get_card_type(card_ref) == kDag71s)
                  return true;
               else
                  return false;

	default:
		// Do nothing
		break;
	}

	return true;
}

/**
This method of printing help is different from 
the other dag tools because help for dagconfig requires
more detail. 
**/
static void 
print_token_attribute_usage(void)
{
	uint8_t index = 0;
	int instances = 0;
	attr_uuid_t attr_uuid;
	uint8_t count = 0;
	uint8_t i;
	uint32_t iface_count = 0;

	printf("\nTokens:\n");

	/* Go through the entire token-attribute array */
	while (token_attr_array[index].token_code != 0)
	{
		/* Process only tokens that don't correspond to invalid attributes */
		if (token_attr_array[index].attribute_code != kAttributeInvalid)
		{
			instances = dag_config_get_attribute_count(card_ref, token_attr_array[index].attribute_code);

			if (instances > 0)
			{
				/* To handle the case of kBooleanAttributeActive */
				if ((token_attr_array[index].attribute_code == kBooleanAttributeActive) && (count == 0))
				{
					/* Need to use interface count instead of instances as 'active' may be present in both GPP and port/phy components */
					iface_count = dag_config_get_interface_count(card_ref);

					for (i = 0; i < iface_count; i++)
					{
						attr_uuid =  dag_config_get_indexed_attribute_uuid(card_ref, token_attr_array[index + i].attribute_code, i);
						printf ("    %-45s%-s\n", token_attr_array[index + i].token_string, dag_config_get_attribute_description(attr_uuid));
					}
					count = 1;
				}
				
				/* Handle everything attribute in the table except 'active' */
				if (token_attr_array[index].attribute_code != kBooleanAttributeActive)
				{
					attr_uuid =  dag_config_get_indexed_attribute_uuid(card_ref, token_attr_array[index].attribute_code, 0);
					if (attribute_is_printable(card_ref, attr_uuid))
						printf ("    %-45s%-s\n", token_attr_array[index].token_string, dag_config_get_attribute_description(attr_uuid));
				}				
			}
		}
		++index;
	}

}

/* This function prints help for tokens that correspond to some functional usage. This is a temporary solution */
static void 
print_token_functional_usage(void)
{
	const char* token_func_usage = "\
    default\t\t\t\t\t Configure the card to its default state.\n\
    reset\t\t\t\t\t Reset the card.\n\
    mem=x1:x2...\t\t\t\t Distribute x1, x2, etc MB of memory to the receive and transmit streams from pre-allocated card memory.\n\
    rxonly\t\t\t\t\t Distribute all pre-allocated card memory to the first receive stream.\n\
    txonly\t\t\t\t\t Distribute all pre-allocated card memory to the first transmit stream.\n\
    rxtx\t\t\t\t\t Distribute the pre-allocated card memory to the first receive and transmit streams.\n";

	printf("%s",token_func_usage);

	if (dag_config_get_recursive_component_count(card_ref, kComponentCrossPointSwitch) > 0 )
	{
		/* its an infiniband 8.5i card */
		printf("    tapmode\t\t\t\t\t Configure the card in tap mode.\n    monitormode\t\t\t\t\t Configure the card in monitor mode.\n");
	}
	printf("\n");
}

