# -*-c-*-
#
# $Id: 33MQINQ,v 23.1 2003/04/10 19:07:21 biersma Exp $
#
# (c) 1999-2003 Morgan Stanley Dean Witter and Co.
# See ..../src/LICENSE for terms of distribution.
#

void
MQINQ(Hconn,Hobj,CompCode,Reason,...)
	MQHCONN		Hconn
	MQHOBJ		Hobj
	MQLONG		CompCode
	MQLONG		Reason

	PPCODE:
        {
	  MQLONG	SelectorCount = 0L;
	  PMQLONG	pSelectors = (PMQLONG)0L;
	  MQLONG	IntAttrCount = 0L;
	  PMQLONG	pIntAttrs = (PMQLONG)0L;
	  MQLONG	CharAttrLength = 0;
	  PMQCHAR	pCharAttrs = (PMQCHAR)0L;
	  SV            *tempSV = (SV *)0;
	  SV		**svp;
	  MQLONG	loop = 0;
	  MQLONG	tempSelector = 0;
	  int		tempLen = 0;
	  char		attrKey[8];
	  
	  HV		*AttributeLengthHV;

	  /*
	    Initialize these for the various random failure cases.
	   */
	  CompCode = MQCC_FAILED;
	  Reason = MQRC_UNEXPECTED_ERROR;
	  sv_setiv(ST(2),(IV)CompCode);
	  sv_setiv(ST(3),(IV)Reason);

	  if ( (AttributeLengthHV = perl_get_hv("MQSeries::Constants::AttributeLength",0)) == NULL ) {
	    warn("Unable to access %%MQSeries::Constants::AttributeLength hash\n");
	    XSRETURN_EMPTY;
	  }
	
	  /*
	    I'd like this to be an error, but prior to touching this code, it wasn't.
	    So, if you pass in nothing, you'll get nothing.
	   */
	  if ( (SelectorCount = (MQLONG)items - 4) <= 0 ) {
	    CompCode = MQCC_OK;
	    Reason = MQRC_NONE;
	    sv_setiv(ST(2),(IV)CompCode);
	    sv_setiv(ST(3),(IV)Reason);
	    XSRETURN_EMPTY;
	  }
	
	  if ( (pSelectors = (PMQLONG)malloc(SelectorCount*sizeof(MQLONG))) == NULL ) {
	    warn("Unable to allocate memory for Selectors in MQINQ.\n");
	    XSRETURN_EMPTY;
	  }

	  for (loop = 0; loop < SelectorCount; loop++) {

	    tempSV = ST(loop+4);
	    tempSelector = SvIV(tempSV);

	    if ( (tempSelector >= MQIA_FIRST) && (tempSelector <= MQIA_LAST) )	    
	      IntAttrCount++;
	    else if ( (tempSelector >= MQCA_FIRST) && (tempSelector <= MQCA_LAST) ) {
	      sprintf(attrKey,"%d",tempSelector);
	      svp = hv_fetch(AttributeLengthHV,attrKey,strlen(attrKey),0);
	      if ( svp == NULL ) {
		free(pSelectors);
		warn("Unknown attribute selector value '%d' passed to MQINQ\n",tempSelector);
		XSRETURN_EMPTY;
	      }
	      CharAttrLength += SvIV(*svp);
	    }
	    else {
	      free(pSelectors);
	      warn("Selector value %d invalid in MQINQ\n",tempSelector);
	      XSRETURN_EMPTY;
	    }
	    pSelectors[loop] = tempSelector;

	  }

	  if ( IntAttrCount > 0 ) {
	    if ( (pIntAttrs = (PMQLONG)malloc(IntAttrCount*sizeof(MQLONG))) == NULL ) {
	      free(pSelectors);
	      warn("Unable to allocate memory in MQINQ\n");
	      XSRETURN_EMPTY;
	    }
	  }

	  if ( CharAttrLength > 0 ) {
	    if ( (pCharAttrs = (PMQCHAR)malloc(CharAttrLength)) == NULL ) {
	      free(pSelectors);
	      if (pIntAttrs) 
		free(pIntAttrs);
	      warn("Unable to allocate memory in MQINQ\n");
	      XSRETURN_EMPTY;
	    }
	  }

	  MQINQ(Hconn,
		Hobj,
		SelectorCount,
		pSelectors,
		IntAttrCount,
		pIntAttrs,
		CharAttrLength,
		pCharAttrs,
		&CompCode,
		&Reason);

	  sv_setiv(ST(2),(IV)CompCode);
	  sv_setiv(ST(3),(IV)Reason);

	  if (CompCode == MQCC_OK) {

	    PMQLONG pCurIntAttr = pIntAttrs;
	    PMQCHAR pCurCharAttr = pCharAttrs;

	    for (loop = 0; loop < SelectorCount; loop++) {

	      tempSelector = pSelectors[loop];

	      if ( (tempSelector >= MQIA_FIRST) && (tempSelector <= MQIA_LAST) ) {
		XPUSHs(sv_2mortal(newSViv(*pCurIntAttr)));
		pCurIntAttr++;
	      }
	      else if ( (tempSelector >= MQCA_FIRST) && (tempSelector <= MQCA_LAST) ) {
		sprintf(attrKey,"%d",tempSelector);
		svp = hv_fetch(AttributeLengthHV,attrKey,strlen(attrKey),0);
		if ( svp == NULL ) {
		  free(pSelectors);
		  if (pIntAttrs)
		    free(pIntAttrs);
		  if (pCharAttrs)
		    free(pCharAttrs);
		  /* Reset cc/rc to the random failure case */
		  CompCode = MQCC_FAILED;
		  Reason = MQRC_UNEXPECTED_ERROR;
		  sv_setiv(ST(2),(IV)CompCode);
		  sv_setiv(ST(3),(IV)Reason);
		  warn("Unknown selector attribute '%d' returned from MQINQ\n",tempSelector);
		  XSRETURN_EMPTY;
		}
		tempLen = SvIV(*svp);
		XPUSHs(sv_2mortal(newSVpvn(pCurCharAttr,tempLen)));
		pCurCharAttr += tempLen;
	      }
	      else {
		free(pSelectors);
		if (pIntAttrs)
		  free(pIntAttrs);
		if (pCharAttrs)
		  free(pCharAttrs);
		/* Reset cc/rc to the random failure case */
		CompCode = MQCC_FAILED;
		Reason = MQRC_UNEXPECTED_ERROR;
		sv_setiv(ST(2),(IV)CompCode);
		sv_setiv(ST(3),(IV)Reason);
		warn("Invalid selector attribute '%d' returned from MQINQ\n",tempSelector);
		XSRETURN_EMPTY;
	      }
	    }
	  } /* end if (CompCode == MQCC_OK) */

        }
