garg.cpp

Go to the documentation of this file.
00001 // garg.cpp -- Version 0.5
00002 
00003 #include <stdlib.h>
00004 #include <string.h>
00005 #include "garg.h"
00006 #include "gstring.h"
00007 ////////////////////////////////////////////////////////////
00008 // Static members
00009 // ---------------------------------------------------------
00010 bool gParam::doAutoTrim=true;
00011 
00012 ////////////////////////////////////////////////////////////
00013 gParam::gParam ()
00014     : paramCriteria( gParam::e_Normal )
00015 {
00016 }
00017 
00018 gParam::gParam (gString& copy, char* sParamSplit, eParamCriteria aParamCriteria)
00019     : paramCriteria( aParamCriteria )
00020 {
00021  if ( sParamSplit!=nil ) {
00022      ASSERTION(sParamSplit[0]!=0,"sParamSplit[0]!=0");
00023      strParamSplit = sParamSplit;
00024      thisSplit( copy.Str(), strParamSplit, *this );
00025  }
00026  else {
00027      Add( copy );
00028  }
00029 }
00030 
00031 gParam::gParam (char* s, char* sParamSplit, eParamCriteria aParamCriteria)
00032     : paramCriteria( aParamCriteria )
00033 {
00034  ASSERTION(s!=nil,"s!=nil");
00035 
00036  if ( sParamSplit!=nil ) {
00037      ASSERTION(sParamSplit[0]!=0,"sParamSplit[0]!=0");
00038      strParamSplit = sParamSplit;
00039      thisSplit( s, strParamSplit, *this );
00040  }
00041  else {
00042      Add( (t_uchar*)s );
00043  }
00044 }
00045 
00046 gParam::~gParam ()
00047 {
00048 }
00049 
00050 gStorage* gParam::GetNewObjectFromFormat (char* s)
00051 {
00052  unsigned i, n, pos, nFmts=0;
00053  gList tempL;
00054  gList fmtL;
00055  gStorage* res=nil;
00056 
00057  if ( s==nil || s[0]==0 ) return nil;
00058  strParamSplit = "%";
00059  if ( thisSplit( s, strParamSplit, tempL )<1 ) return nil;
00060  n = tempL.N();
00061  ASSERTION(n>=2,"n>=2");  //Probably 'AddParams' used with wrong strings
00062  pos = tempL.Match("");
00063  for (i=pos+1; i<=n; i++) {
00064      nFmts++;
00065      fmtL.Add( tempL.Str(i) );
00066  }
00067  if ( nFmts==0 ) return nil;
00068  gString sFmt( fmtL.Str(1) );
00069  ASSERTION(sFmt.IsEmpty()==false,"sFmt.IsEmpty()==false");
00070  ASSERTION(nFmts==1,"nFmts==1");
00071  t_uchar chr = sFmt[1];
00072  switch ( chr ) {
00073  case 'u':
00074      res = new gUInt;
00075      break;
00076  case 'd':
00077      res = new gInt;
00078      break;
00079  case 's':
00080      res = new gString;
00081      break;
00082  case 'f':
00083      res = new gReal;
00084      break;
00085  default:
00086      break;
00087  }
00088  return res;
00089 }
00090 
00091 /* --- old method kept, because this method was already highly used and it worked with " (double-quotes) perfectly
00092  unsigned gParam::Find (gString& s, gString& sSubStr, int iCriteria)
00093  {
00094  if ( (eParamCriteria)iCriteria!=e_NormalQuoted ) return s.Find( sSubStr );
00095  gString sTemp( s );
00096  short quoteCount=0;
00097  unsigned idx, len=sTemp.Length();
00098  for (idx=1; idx<=len; idx++) {
00099      if ( sTemp[idx]=='"' ) {
00100          quoteCount = quoteCount==0;
00101          continue;
00102      }
00103      if ( quoteCount ) sTemp[idx] = (t_uchar)127;
00104  }
00105  // A string like "abc' def" will not count the single-quote char!
00106  return sTemp.Find( sSubStr );
00107  }
00108 --- temp */
00109 
00110 unsigned gParam::Find (gString& s, gString& sSubStr, int iCriteria)
00111 {
00112  if ( (eParamCriteria)iCriteria!=e_NormalQuoted ) return s.Find( sSubStr );
00113  gString sTemp( s );
00114  short quoteCount=0;
00115  short singlCount=0; //single-quote
00116  unsigned idx, len=sTemp.Length();
00117  for (idx=1; idx<=len; idx++) {
00118      if ( sTemp[idx]=='"' && singlCount==0 ) {
00119          quoteCount = quoteCount==0;
00120          continue;
00121      }
00122      else {
00123          if ( sTemp[idx]=='\'' && quoteCount==0 ) {
00124              singlCount = singlCount==0;
00125              continue;
00126          }
00127      }
00128      if ( quoteCount || singlCount ) sTemp[idx] = (t_uchar)127;
00129  }
00130  // A string like "abc' def" will not count the single-quote char!
00131  return sTemp.Find( sSubStr );
00132 }
00133 
00134 
00135 int gParam::thisSplit (char* s, gString& strSplit, gList& resL)
00136 {
00137  ;
00138  // E.g.: split ("abc|def x|yz"," "), or ("@abc@def","@")
00139  //     results in  ==>  abc|def, x|yz
00140  // Returns number of splits
00141  ;
00142  // Note:
00143  //   paramCriteria=e_StopSplitOnFirst means only the first split is done
00144 
00145  int result=0;
00146  unsigned countSplits=0;
00147  unsigned pos, splitLen=strSplit.Length();
00148  gString aS( s );
00149 
00150  ASSERTION(splitLen>0,"splitLen>0");
00151 
00152  while ( (pos = Find(aS,strSplit,(int)paramCriteria))>0 ) {
00153      gString bS( aS );
00154      countSplits++;
00155      if ( pos==1 ) {
00156          if ( paramCriteria!=e_NormalQuoted )
00157              resL.Add( (t_uchar*)"\0" );
00158      }
00159      else {
00160          aS[pos] = 0;
00161          if ( doAutoTrim ) aS.Trim();
00162          resL.Add( aS );
00163          result++;
00164      }
00165      bS.Delete(1,pos+splitLen-1);
00166      aS.Copy( bS );
00167      //printf("DBG: SPLIT:[%s]\n",aS.Str());
00168      if ( paramCriteria==gParam::e_StopSplitOnFirst && countSplits>=(unsigned)paramCriteria ) break;
00169  }
00170  if ( aS.Length()==0 ) return result;
00171  result++;
00172  if ( doAutoTrim ) aS.Trim();
00173  resL.Add( aS );
00174  return result;
00175 }
00176 ////////////////////////////////////////////////////////////
00177 sParamRaw::sParamRaw (eParamFollow aParamFollow)
00178     : paramFollow( aParamFollow ),
00179       posControl( 0 ),
00180       myParamVal( nil )
00181 {
00182 }
00183 
00184 sParamRaw::~sParamRaw ()
00185 {
00186  delete myParamVal;
00187 }
00188 
00189 gStorage* sParamRaw::GetParamVal ()
00190 {
00191  ASSERTION(myParamVal!=nil,"myParamVal!=nil");
00192  return myParamVal;
00193 }
00194 
00195 bool sParamRaw::BuildParamVal (char* s)
00196 {
00197  bool isOk;
00198  gParam param;
00199 
00200  delete myParamVal;
00201  myParamVal = param.GetNewObjectFromFormat( s );
00202  isOk = myParamVal!=nil;
00203 #ifdef gDEBUG_PARAM
00204  if ( isOk ) {
00205      gUCharBuffer ucBuf;
00206      myParamVal->ToString( ucBuf.uBuf );
00207      printf("DBG: PARAM_VAL: [%s]=[",ucBuf.uBuf);
00208      myParamVal->Show(); printf("]\n");
00209  }
00210  else {
00211      printf("DBG: PARAM_VAL invalid: %s\n",s);
00212  }
00213 #endif //gDEBUG_PARAM
00214  ASSERTION(isOk,"Invalid parameter format");
00215  return isOk;
00216 }
00217 
00218 bool sParamRaw::AddMember (char* s)
00219 {
00220  gString sMember( s );
00221  unsigned pos = sMember.FindExcept( "-" );
00222  members.Add( s );
00223  if ( pos>posControl ) {
00224      sufStr = (char*)(s+pos-1);
00225      posControl = pos;
00226  }
00227  return pos>0;
00228 }
00229 ////////////////////////////////////////////////////////////
00230 void gParamVal::CopyParam (gParamVal& copy)
00231 {
00232  cVal = copy.cVal;
00233  allStr = copy.allStr;
00234  sufStr = copy.sufStr;
00235  sVal = copy.sVal;
00236  lVal = copy.lVal;
00237  realVal = copy.realVal;
00238  repeats = copy.repeats;
00239  errorCode = copy.errorCode;
00240 }
00241 
00242 bool gParamVal::FillParam (gString& newSVal, gStorage* aObj)
00243 {
00244  // Given an object (aObj, even not filled), try to convert
00245  // string 'newSVal' into respective field.
00246 
00247  char* s;
00248  char* sDup;
00249  char** endptr;
00250  char c;
00251  long val;
00252  unsigned len;
00253 
00254  if ( aObj==nil ) return false;
00255 
00256  sVal = newSVal;
00257  s = sVal.Str();
00258  len = sVal.Length();
00259  c = s[0];
00260  errorCode = 0;
00261  eStorage thisKind = aObj->Kind();
00262  switch ( thisKind ) {
00263  case e_UInt:
00264  case e_SInt:
00265      val = atol(s);
00266      if ( val==0 && c!='0' ) errorCode = 2;
00267      SetLong( val );
00268      DBGPRINT("DBG: Value(%s)=%ld, errorCode=%d (thisKind=%d)\n",s,val,errorCode,thisKind);
00269      break;
00270  case e_ULongInt:
00271  case e_SLongInt:
00272  case e_Real:
00273      sDup = strdup( s );
00274      endptr = &sDup;
00275      realVal = (float)strtod( s, endptr );
00276      lVal = (long long)realVal;
00277      c = sDup[0];
00278      errorCode = c==0 ? 0 : 3;
00279      break;
00280  default:
00281      errorCode = 1;
00282      break;
00283  }
00284 
00285  return errorCode==0;
00286 }
00287 
00288 bool gParamVal::AddToList (gList& resL)
00289 {
00290  gParamVal* newObj;
00291  newObj = new gParamVal;
00292  ASSERTION(newObj!=nil,"newObj!=nil");
00293  newObj->CopyParam( *this );
00294  return resL.AppendObject( newObj );
00295 }
00296 
00297 gParamVal* gParamVal::FindObj (gList& copyL, t_uchar chr, unsigned& idx)
00298 {
00299  // Returns the pointer of the list with 'cVal' equal to chr.
00300  // 'idx' gets the index in the list (or 0 if not found).
00301  unsigned i, n=copyL.N();
00302  gStorage* res;
00303 
00304  idx = 0;
00305  for (i=1; i<=n; i++) {
00306      res = copyL.GetElementPtr( i )->me;
00307      ASSERTION(res!=nil,"res!=nil");
00308      gParamVal* aParamPtr = (gParamVal*)res;
00309      if ( chr==aParamPtr->cVal ) {
00310          idx = i;
00311          return aParamPtr;
00312      }
00313  }
00314  return nil;
00315 }
00316 
00317 unsigned gParamVal::FindMainChar (gList& copyL, t_uchar chr)
00318 {
00319  ;
00320  // Finds chr as the main 'cVal' within list 'copyL'.
00321  // Returns 0 if no chr was found.
00322  ;
00323  unsigned idx;
00324  FindObj( copyL, chr, idx );
00325  return idx;
00326 }
00327 
00328 gStorage* gParamVal::NewObject ()
00329 {
00330  gParamVal* a;
00331  a = new gParamVal;
00332  a->CopyParam( *this );
00333  return a;
00334 }
00335 
00336 t_uchar* gParamVal::ToString (t_uchar* uBuf)
00337 {
00338  return sufStr.UStr();
00339 }
00340 
00341 void gParamVal::Show (bool doShowAll)
00342 {
00343  if ( realVal>=MAX_REAL_LVAL ) {
00344      printf("cVal=%c, allStr=%s, sufStr=%s, sVal=%s, lVal=%ld, repeats=%d, err=%d%s",
00345             cVal,
00346             allStr.Str(),
00347             sufStr.Str(),
00348             sVal.Str(),
00349             GetLongValue(),
00350             repeats,
00351             errorCode,
00352             doShowAll?"@":"\0");
00353  }
00354  else {
00355      printf("cVal=%c, allStr=%s, sufStr=%s, sVal=%s, rVal=%0.1f, repeats=%d, err=%d%s",
00356               cVal,
00357               allStr.Str(),
00358               sufStr.Str(),
00359               sVal.Str(),
00360               realVal,
00361               repeats,
00362               errorCode,
00363               doShowAll?"@":"\0");
00364  }
00365 }
00366 ////////////////////////////////////////////////////////////
00367 gParamElem::gParamElem (eParamConfig aParamConfig)
00368     : paramConfig(aParamConfig),
00369       mainChr(0)
00370 {
00371 }
00372 
00373 gParamElem::~gParamElem ()
00374 {
00375 }
00376 
00377 unsigned gParamElem::Add (gString& copy)
00378 {
00379  return Add( copy.Str() );
00380 }
00381 
00382 unsigned gParamElem::Add (char* s)
00383 {
00384  ASSERTION(s!=nil,"s!=nil");
00385  gList::Add( s );
00386 
00387  gString sPreStr( s[0]!='-' ? (char*)"-" : (char*)"\0" );
00388  sPreStr.Add( s );
00389 
00390  gParam paramTry1( sPreStr, ":" );
00391  unsigned n1( paramTry1.N() );
00392 
00393  gParam paramTry2( sPreStr, "=" );
00394  unsigned n2( paramTry2.N() );
00395 
00396  if ( n1>=2 ) {
00397      sRaw.paramFollow = sParamRaw::e_ParamNextArg;
00398      sRaw.AddMember( paramTry1.Str(1) );
00399      sRaw.BuildParamVal( paramTry1.Str(2) );
00400  }
00401  else {
00402      if ( n2>=2 ) {
00403          sRaw.paramFollow = sParamRaw::e_ParamThisArg;
00404          sRaw.paramSep = (char*)"=";
00405          sRaw.AddMember( paramTry2.Str(1) );
00406          sRaw.BuildParamVal( paramTry2.Str(2) );
00407      }
00408      else {
00409          sRaw.AddMember( sPreStr.Str() );
00410      }
00411  }
00412  return 0;
00413 }
00414 
00415 gStorage* gParamElem::NewObject ()
00416 {
00417  ASSERTION_FALSE("Not needed");
00418  return nil;
00419 }
00420 ////////////////////////////////////////////////////////////
00421 gArg::gArg (char** argv, char** envp)
00422     : nParamDashWordSimple( 0 ),
00423       internParams( nil ),
00424       keepPos( 0 )
00425 {
00426  ASSERTION(argv!=nil,"argv!=nil");
00427  prog = *argv;
00428  argv++;
00429  while ( *argv ) {
00430      Add( (t_uchar*)*argv );
00431      argv++;
00432  }
00433  if ( envp!=nil ) {
00434      while ( *envp ) {
00435          env.Add( (t_uchar*)*envp );
00436          envp++;
00437      }
00438  }
00439 
00440  for (short i=0; i<256; i++) paramLetter[i] = e_ParamNotUsed;
00441  thisProgramName();
00442 }
00443 
00444 gArg::~gArg ()
00445 {
00446  delete[] internParams;
00447 }
00448 
00449 gParamVal* gArg::GetOptionPtr (unsigned idx)
00450 {
00451  unsigned n=opt.N();
00452  ASSERTION(idx>=1 && idx<=n,"GetOptionPtr");
00453  return (gParamVal*)opt.GetObjectPtr( idx );
00454 }
00455 
00456 int gArg::AddParams (t_uint16 paramStart, char* s)
00457 {
00458  bool isOk;
00459  int result=0;
00460  unsigned i, n;
00461 
00462  ASSERTION(s!=nil,"s!=nil");
00463 
00464  gParam params(s," ");
00465  for (i=1, n=params.N(); i<=n; i++) {
00466      isOk = thisAddOneParam( paramStart++, params.Str(i), param );
00467      result += isOk==true;
00468  }
00469  return result;
00470 }
00471 
00472 int gArg::FlushParams ()
00473 {
00474  bool isOk;
00475  int result;
00476 
00477  // Builds the internParams array
00478  isOk = thisBuildInternParam( param, "|" );
00479  // printf("DBG: isOk?%c : ",ISyORn(isOk)); param.Show(true);
00480  if ( isOk==false ) return -1;
00481 
00482  gList resArgL;
00483  gList resOptL;
00484  gList resErrL;
00485 
00486  result = thisFlushAll( *this,
00487                         param,
00488                         NumberParams(),
00489                         internParams,
00490                         resArgL,
00491                         resOptL,
00492                         resErrL );
00493 
00494  DBGPRINT("DBG: FlushParams(result=%d)\n",result);
00495 #ifdef DEBUG
00496  DBGPRINT("DBG: resArgL(%d): ",result); resArgL.Show();
00497  DBGPRINT("DBG: resOptL(%d): ",result); resOptL.Show();
00498  DBGPRINT("DBG: resErrL(%d): ",result); resErrL.Show();
00499 #endif //DEBUG
00500 
00501  CopyList( resArgL );
00502  opt.CopyList( resOptL );
00503  errors.CopyList( resErrL );
00504 
00505  return result;
00506 }
00507 
00508 bool gArg::FindOption (char c)
00509 {
00510  gParamVal* aParamPtr;
00511  unsigned i, n=opt.N();
00512  t_uchar chr=(t_uchar)c;
00513 
00514  keepPos = 0;
00515  if ( paramLetter[chr]==e_ParamNotUsed ) return false;
00516  // Find 'chr' in 'opt'
00517  for (i=1; i<=n; i++) {
00518      aParamPtr = GetOptionPtr( i );
00519      if ( chr==aParamPtr->cVal ) {
00520          keepPos = i;
00521          return true;
00522      }
00523  }
00524  return false;
00525 }
00526 
00527 bool gArg::FindOption (char* s)
00528 {
00529  long val;
00530  return FindOption( s, val );
00531 }
00532 
00533 bool gArg::FindOption (char* s, int& val)
00534 {
00535  long lVal;
00536  if ( FindOption( s, lVal )==false ) return false;
00537  if ( sizeof(int)!=sizeof(long) ) {
00538      if ( lVal>65535L ) return false;
00539  }
00540  val = (int)lVal;
00541  return true;
00542 }
00543 
00544 bool gArg::FindOption (char* s, long& val)
00545 {
00546  gParamVal* aParamPtr;
00547  keepPos = opt.Match( s );
00548  if ( keepPos==0 ) return false;
00549  aParamPtr = GetOptionPtr( keepPos );
00550  val = (long)(aParamPtr->lVal);
00551  return true;
00552 }
00553 
00554 bool gArg::FindOption (char c, gString& sRes)
00555 {
00556  gParamVal* aParamPtr;
00557  if ( FindOption( c )==false ) return false;
00558  ASSERTION(keepPos>0,"keepPos>0");
00559  aParamPtr = GetOptionPtr( keepPos );
00560  sRes = aParamPtr->sVal;
00561  return true;
00562 }
00563 
00564 bool gArg::FindOption (char* s, gString& sRes)
00565 {
00566  gParamVal* aParamPtr;
00567  if ( FindOption( s )==false ) return false;
00568  aParamPtr = GetOptionPtr( keepPos );
00569  sRes = aParamPtr->sVal;
00570  return true;
00571 }
00572 
00573 bool gArg::FindOptionOccurr (char* s, short& nRepeats)
00574 {
00575  gParamVal* aParamPtr;
00576  if ( FindOption( s )==false ) return false;
00577  aParamPtr = (gParamVal*)opt.GetObjectPtr( keepPos );
00578  nRepeats = aParamPtr->repeats;
00579  return true;
00580 }
00581 
00582 bool gArg::FindOptionOccurr (char* s, bool& b1)
00583 {
00584  bool b2;
00585  return FindOptionOccurr( s, b1, b2 );
00586 }
00587 
00588 bool gArg::FindOptionOccurr (char* s, bool& b1, bool& b2)
00589 {
00590  short nRepeats;
00591  b1 = b2 = false;
00592  if ( FindOptionOccurr( s, nRepeats )==false ) return false;
00593  if ( nRepeats<=0 ) return false;
00594  b1 = nRepeats>=1;
00595  b2 = nRepeats>=2;
00596  return true;
00597 }
00598 
00599 t_uchar* gArg::ToString (t_uchar* uBuf)
00600 {
00601  return gList::ToString( uBuf );
00602 }
00603 
00604 bool gArg::thisProgramName ()
00605 {
00606  unsigned pos = prog.FindBack( gSLASHCHR );
00607  programName.CopyFromTo( prog, pos==0 ? 0 : pos+1 );
00608  return programName.IsEmpty()==false;
00609 }
00610 
00611 bool gArg::thisAddOneParam (t_uint16 paramStart, char* sParam, gList& resL)
00612 {
00613  ASSERTION(paramStart>0,"paramStart>0");
00614  ASSERTION(sParam!=nil,"sParam!=nil");
00615  if ( sParam[0]==0 ) return false;
00616 
00617  resL.Add( sParam );
00618 
00619  return true;
00620 }
00621 
00622 bool gArg::thisBuildInternParam (gList& paramIn, char* strSepSplit)
00623 {
00624  // Builds the internParams array separated from, e.g. pipe (|)
00625  bool isOk;
00626  bool isDashWordSimple;
00627  unsigned i, n=paramIn.N();
00628 
00629  ASSERTION(strSepSplit!=nil && strSepSplit[0]!=0,"strSepSplit!=nil");
00630 
00631  delete[] internParams;
00632  internParams = new gParamElem[n+1];
00633 
00634  for (i=1; i<=n; i++) {
00635      gParam aParam( paramIn.Str(i), strSepSplit );
00636      isOk = thisProcessParamElem( aParam, internParams[i], isDashWordSimple );
00637      ASSERTION(isOk,"gArg::thisBuildInternParam(1)");
00638      nParamDashWordSimple += (short)isDashWordSimple;
00639  }
00640  return true;
00641 }
00642 
00643 bool gArg::thisProcessParamElem (gParam& aParam,
00644                                  gParamElem& paramElem,
00645                                  bool& isDashWordSimple)
00646 {
00647  bool isSingleDash, isRepeatedChr;
00648  unsigned i, paramN, pos, len;
00649  t_uchar chr, chr2=0, chrMain=0;
00650  eParamConfig paramConfig=e_ParamNotUsed;
00651  gList posNonDash;
00652 
00653  isDashWordSimple = false;
00654 
00655  paramN = aParam.N();
00656  if ( paramN==0 ) return false;
00657 
00658  //printf("DBG: param(%u): ",paramN); aParam.Show();
00659 
00660  // Check which style has been used. Examples:
00661  //      ==> -z|--zero   Single
00662  //      ==> -v|-vv      Repeat
00663  // in parallel, "-z|--zero" ...
00664 
00665  gString sFirst( aParam.Str(1) );
00666  chr = sFirst[1];
00667  len = sFirst.Length();
00668  if ( chr=='-' ) {
00669      isSingleDash = sFirst.Match("-");
00670      ASSERTION(sFirst.Match("--")==false,"sFirst.Match('--')==false");
00671      // Check all params have dash (-)
00672      for (i=1; i<=paramN; i++) {
00673          gString sTemp( aParam.Str(i) );
00674          posNonDash.Add( sTemp.FindExcept( "-" ) );
00675          if ( sTemp[1]!='-' ) return false;
00676      }
00677      chr2 = sFirst[2];
00678      chrMain = chr2=='-' ? 0 : chr2;
00679      isRepeatedChr = chr2==sFirst[3];
00680      isDashWordSimple = isSingleDash==false && isRepeatedChr==false && chr2!='-' && len>2 && paramN==1;
00681      if ( isDashWordSimple ) {
00682          paramConfig = e_ParamDashSimple;
00683          chrMain = '~';
00684      }
00685      else {
00686          // If more than one occurrence for character, return&fail
00687          if ( chrMain!=0 && paramLetter[chrMain]!=e_ParamNotUsed ) return false;
00688          paramConfig = e_ParamUsedSingle;
00689          if ( isSingleDash ) {
00690              chrMain = '-';
00691          }
00692          else {
00693              if ( isRepeatedChr ) paramConfig = e_ParamUsedRepeat;
00694          }
00695          if ( chrMain!=0 ) paramLetter[chrMain] = paramConfig;
00696      }
00697  }
00698  else {
00699      if ( chr<=' ' ) return false;
00700      // Check no params have dash
00701      for (i=2; i<=paramN; i++) {
00702          if ( aParam.Str(i)[0]=='-' ) return false;
00703      }
00704      paramLetter[0] = paramConfig = e_ParamNonPosix;
00705  }
00706 
00707  paramElem.paramConfig = paramConfig;
00708  paramElem.mainChr = chrMain;
00709  for (i=1; i<=paramN; i++) {
00710      gString thisParamStr( aParam.Str(i) );
00711      pos = posNonDash.GetUInt(i);
00712      switch ( paramConfig ) {
00713      case e_ParamNonPosix:
00714          paramElem.Add( thisParamStr );
00715          break;
00716      case e_ParamUsedSingle:
00717      case e_ParamUsedRepeat:
00718          if ( pos==2 ) pos=1; else pos=0;
00719          paramElem.Add( thisParamStr.Str()+pos );
00720          break;
00721      case e_ParamDashSimple:
00722          ASSERTION(paramN==1,"paramN==1");
00723          ASSERTION(pos=1,"pos==1");
00724          paramElem.Add( thisParamStr );
00725          break;
00726      case e_ParamNotUsed:
00727      default:
00728          return false;
00729      }
00730  }
00731 
00732  return true;
00733 }
00734 
00735 unsigned gArg::thisFindParamFromChr (t_uchar inChr,
00736                                      unsigned nParams,
00737                                      gParamElem* intParams)
00738 {
00739  unsigned i;
00740  t_uchar chr;
00741 
00742  if ( nParams==0 ) return false;
00743  ASSERTION(inChr!=0,"inChr!=0");
00744  for (i=1; i<=nParams; i++) {
00745      chr = intParams[i].MainChar();
00746      if ( chr==inChr ) return i;
00747  }
00748  return 0;
00749 }
00750 
00751 unsigned gArg::thisFindParamFromStr (char* s,
00752                                      unsigned nParams,
00753                                      gParamElem* intParams,
00754                                      bool& doMatch,
00755                                      unsigned& possibleParamIdx)
00756 {
00757  bool isThisParam;
00758  unsigned i, k, n, pos, paramRef, paramIdx;
00759  gList posL, posK;
00760  gString sArg( s );
00761 
00762  doMatch = false;
00763  possibleParamIdx = 0;
00764 
00765  if ( nParams==0 ) return false;
00766  ASSERTION(s!=nil,"s!=nil");
00767  for (i=1; i<=nParams; i++) {
00768      pos = intParams[i].sRaw.members.Match( s );
00769      if ( pos>0 ) {
00770          doMatch = true;
00771          return i;
00772      }
00773      for (k=1; k<=intParams[i].sRaw.members.N(); k++) {
00774          gString paramStr( intParams[i].sRaw.members.Str(k) );
00775          pos = sArg.Find( paramStr );
00776          if ( pos==1 && paramStr.Length()>2 ) {
00777              posL.Add( i );
00778              posK.Add( k );
00779          }
00780      }
00781  }
00782 
00783  // Iterate through posL
00784  n = posL.N();
00785  for (i=1; i<=n; i++) {
00786      paramRef = posL.GetUInt( i );
00787      isThisParam = intParams[paramRef].sRaw.paramFollow==sParamRaw::e_ParamThisArg;
00788      if ( isThisParam==false ) continue;
00789      gString aParamSep( intParams[paramRef].sRaw.paramSep );
00790      // Add separator to option (e.g. "--zero=")
00791      // and check "--zero=" is first position within sArg
00792      paramIdx = posK.GetUInt( i );
00793      gString sTemp( intParams[paramRef].sRaw.members.Str( paramIdx ) );
00794      sTemp.Add( aParamSep.Str() );
00795      pos = sArg.Find( sTemp );
00796      if ( pos>0 ) {
00797          possibleParamIdx = paramIdx;
00798          return paramRef;
00799      }
00800  }
00801  return 0;
00802 }
00803 
00804 bool gArg::thisFillParamFromChr (t_uchar inChr,
00805                                  unsigned nParams,
00806                                  gParamElem* intParams,
00807                                  gParamVal& paramVal)
00808 {
00809  unsigned paramRef, pos;
00810 
00811  paramRef = thisFindParamFromChr( inChr, nParams, intParams );
00812  if ( paramRef==0 ) return false;
00813 
00814  paramVal.cVal = inChr;
00815  pos = intParams[paramRef].sRaw.members.Find( "--", 1, e_FindExactPosition );
00816  if ( pos>0 ) paramVal.allStr = intParams[paramRef].sRaw.members.Str( pos );
00817  paramVal.sufStr = intParams[paramRef].sRaw.sufStr;
00818  paramVal.repeats = intParams[paramRef].paramConfig==e_ParamUsedRepeat ? 1 : -1;
00819  return true;
00820 }
00821 
00822 bool gArg::thisFillParamFromStr (char* s,
00823                                  unsigned paramRef,
00824                                  unsigned nParams,
00825                                  gParamElem* intParams,
00826                                  gParamVal& paramVal)
00827 {
00828  unsigned pos;
00829 
00830  if ( paramRef==0 ) return false;
00831 
00832  pos = intParams[paramRef].sRaw.members.Find( "--", 1, e_FindExactPosition );
00833  if ( pos>0 ) paramVal.allStr = intParams[paramRef].sRaw.members.Str( pos );
00834  paramVal.cVal = intParams[paramRef].MainChar();
00835  paramVal.sufStr = intParams[paramRef].sRaw.sufStr;
00836  paramVal.repeats = intParams[paramRef].paramConfig==e_ParamUsedRepeat ? 1 : -1;
00837  return true;
00838 }
00839 
00840 int gArg::thisFlushAll (gList& inputL,
00841                         gList& paramIn,
00842                         unsigned nParams,
00843                         gParamElem* intParams,
00844                         gList& resArgL,
00845                         gList& resOptL,
00846                         gList& resErrL)
00847 {
00848  // Parses arguments found in 'inputL' and computes 'resArgL','resOptL'
00849  // Expands POSIX options found in 'inputL' (e.g. -vh into -v -h)
00850  // into resOptL.
00851  // Remaining relevant arguments are stored at resArgL.
00852  //
00853  // Returns the internal code of error (0 on no error)
00854  ;
00855  bool isOk, isSingleDash, hasSingleDash;
00856  bool doExpandPOSIX = nParamDashWordSimple<=0;
00857  unsigned i, iterChar, n, pos, posExc, len, paramRef;
00858  unsigned inputSize = inputL.N();
00859  t_uchar chr;
00860  eParamConfig paramConfig;
00861  short* paramUsage;
00862  int countValErrors=0;
00863  int result=0;
00864 
00865  if ( nParams==0 ) return 0;
00866 
00867  paramUsage = new short[inputSize+1];
00868 
00869  for (i=1; i<=inputSize; i++) paramUsage[i] = 0;
00870 
00871  // First step is to find POSIX expansions
00872  gList dashPos;
00873  pos = inputL.FindAny( "-", 1, e_FindExactPosition, dashPos );
00874  n = dashPos.N();
00875  for (i=1; i<=n; i++) {
00876      pos = dashPos.GetUInt(i);
00877      paramUsage[pos] = 1;
00878      gString sTemp( inputL.Str(pos) );
00879      gString sArg( sTemp );
00880      posExc = sTemp.FindExcept( "-" );
00881      isSingleDash = sTemp.Match( "-" );
00882      if ( isSingleDash ) {
00883          if ( paramLetter[(int)'-']==e_ParamNotUsed ) continue;
00884          resOptL.Add( sTemp );
00885          continue;
00886      }
00887      ASSERTION(posExc>0,"posExc>0");
00888      hasSingleDash = posExc==2;
00889      sTemp.Delete(1,posExc-1);
00890      len = sTemp.Length();
00891 
00892      // If has a single dash (e.g. -z or -zero) => hasSingleDash=true
00893      // we have to look for the word, or any of the expanded POSIX options.
00894      // Exception is doExpandPOSIX==false, where no expansion will be made.
00895      if ( hasSingleDash==true && doExpandPOSIX==true ) {
00896          bool areAllChrsAllowed=true;
00897          bool isRelaxedThrough=false;
00898 
00899          // Validate all combinations, e.g. -vh,
00900          // both -v and -h must be parameters allowed.
00901          for (iterChar=1; iterChar<=len; iterChar++) {
00902              chr = sTemp[iterChar];
00903              paramConfig = paramLetter[chr];
00904              isOk = paramConfig!=e_ParamNotUsed;
00905              // Ok, unless at least one of the params has values: [(X Y)] or [(X=Y)]
00906              paramRef = thisFindParamFromChr( chr, nParams, intParams );
00907              if ( paramRef>0 ) {
00908                  ASSERTION(isOk,"isOk");
00909                  isRelaxedThrough = iterChar==1 && intParams[paramRef].sRaw.paramFollow==sParamRaw::e_ParamThisArg;
00910                  // Cannot have any follow parameters if more than one
00911                  // parameter is in the -string.
00912                  // Example: "-v -s:%u" and we have -vs
00913                  isOk =
00914                      intParams[paramRef].sRaw.paramFollow==sParamRaw::e_ParamNoVal ||
00915                      len==1 ||
00916                      isRelaxedThrough;
00917                  DBGPRINT("DBG: stringlen=%u, thisFindParamFromChr('%c',...):%u:isOk?%c\n",len,chr,paramRef,ISyORn(isOk));
00918              }
00919              if ( isOk==false && isRelaxedThrough==false ) areAllChrsAllowed = false;
00920          }
00921          if ( areAllChrsAllowed==false ) {
00922              resArgL.Add( sArg );
00923              resErrL.Add( sArg );
00924              result++;
00925              continue;
00926          }
00927 
00928          // We know all of them are to be expanded
00929          for (iterChar=1; iterChar<=len; iterChar++) {
00930              bool isRepeatable;
00931              chr = sTemp[iterChar];
00932              gParamVal paramVal;
00933              paramRef = thisFindParamFromChr( chr, nParams, intParams );
00934              isOk = thisFillParamFromChr( chr, nParams, intParams, paramVal );
00935              isRepeatable = paramVal.repeats!=-1;
00936              // DBGPRINT("Expanding arg%u (%u/%u), char%u: ",pos,i,n,iterChar); paramVal.Show(false); DBGPRINT("\n");
00937              ASSERTION(isOk,"isOk");
00938              // Argument found is to be expanded:
00939              // the only exception is if one arg 'repeats'
00940              // where this field will be incremented.
00941              unsigned posChr=0;
00942              if ( isRepeatable ) {
00943                  gParamVal* aParamPtr = paramVal.FindObj( resOptL, chr, posChr );
00944                  if ( posChr>0 ) {
00945                      aParamPtr->repeats++;
00946                  }
00947              }
00948 
00949              sParamRaw::eParamFollow aParamFollow = intParams[paramRef].sRaw.paramFollow;
00950              bool hasFurtherVal = aParamFollow!=sParamRaw::e_ParamNoVal;
00951              bool hasValWithin = aParamFollow==sParamRaw::e_ParamThisArg;
00952              if ( posChr==0 ) {
00953                  paramVal.FindObj( resOptL, chr, posChr );
00954                  if ( posChr==0 ) {
00955                      if ( hasFurtherVal ) {
00956                          gString sTempVal( sTemp );
00957 
00958                          // If hasFurtherVal, either 'hasValWithin' or not.
00959                          // E.g. "-s=10" => hasValWithin=true!
00960                          // E.g. "-s 10" => hasValWithin=false!
00961                          // In the second case an additional arg must exist
00962                          if ( hasValWithin ) {
00963                              gString aParamSep( intParams[paramRef].sRaw.paramSep );
00964                              iterChar = len+1; //Exit expansion
00965                              sTempVal.Delete( 1, 1 );
00966                              chr = sTempVal[1];
00967                              unsigned posParamSep;
00968                              posParamSep = sTempVal.Find( aParamSep );
00969                              if ( posParamSep!=1 ) {
00970                                  resArgL.Add( sArg );
00971                                  resErrL.Add( sArg );
00972                                  result++;
00973                                  continue;
00974                              }
00975                              if ( aParamSep.Length()>0 )
00976                                  sTempVal.Delete( 1, aParamSep.Length() );
00977                          }
00978                          else {
00979                              if ( pos>=inputSize ) {
00980                                  resArgL.Add( sArg );
00981                                  resErrL.Add( sArg );
00982                                  result++;
00983                                  continue;
00984                              }
00985                              // Mark argument as used by value ('2')
00986                              paramUsage[pos+1] = 2;
00987                              sTempVal = inputL.Str(pos+1);
00988                          }
00989                          // Fill contents of the parameter
00990                          // ==> paramVal.sVal = sTempVal
00991                          paramVal.FillParam( sTempVal, intParams[paramRef].sRaw.GetParamVal() );
00992                          countValErrors += paramVal.errorCode>=2;
00993                      }// end IF hasFurtherVal (single chr option)
00994 
00995                      // Finally add the parameter filled to the list of options
00996                      paramVal.AddToList( resOptL );
00997                  }
00998                  else {
00999                      // It is not a valid parameter if already parsed...
01000                      // which is the case here.
01001                      resArgL.Add( sArg );
01002                      resErrL.Add( sArg );
01003                      result++;
01004                      continue;
01005                  }
01006              }
01007          }
01008      }// end IF single-dash=T & doExpandPOSIX=T
01009      if ( hasSingleDash==true && doExpandPOSIX==false ) {
01010          ASSERTION_FALSE("TODO");
01011      }
01012      if ( hasSingleDash==false ) {
01013          // It is a double-dash option
01014 
01015          bool doMatch=false;
01016          unsigned possibleParamIdx = 0;
01017          gParamVal paramVal;
01018 
01019          paramRef = thisFindParamFromStr( sArg.Str(), nParams, intParams, doMatch, possibleParamIdx );
01020          if ( paramRef==0 ) {
01021              resArgL.Add( sArg );
01022              resErrL.Add( sArg );
01023              result++;
01024              continue;
01025          }
01026 
01027          isOk = thisFillParamFromStr( sArg.Str(), paramRef, nParams, intParams, paramVal );
01028          ASSERTION(isOk,"isOk");
01029 
01030          sParamRaw::eParamFollow aParamFollow = intParams[paramRef].sRaw.paramFollow;
01031          bool hasFurtherVal = aParamFollow!=sParamRaw::e_ParamNoVal;
01032          bool hasValWithin = aParamFollow==sParamRaw::e_ParamThisArg;
01033 
01034          if ( hasFurtherVal ) {
01035              gString sTempVal( sArg );
01036 
01037              DBGPRINT("DBG: sTempVal[%u/%u]: '%s', hasFurtherVal?%c, hasValWithin?%c, possibleParamIdx=%u\n",
01038                       i, n,
01039                       sTempVal.Str(),
01040                       ISyORn(hasFurtherVal),
01041                       ISyORn(hasValWithin),
01042                       possibleParamIdx);
01043 
01044              // If hasFurtherVal, either 'hasValWithin' or not.
01045              // E.g. "-s=10" or "--size=10" => hasValWithin=true!
01046              // E.g. "-s 10" or "--size 10" => hasValWithin=false!
01047              // In the second case an additional arg must exist
01048              if ( hasValWithin ) {
01049                  ASSERTION(possibleParamIdx>0,"possibleParamIdx>0");
01050                  gString sParamString( intParams[paramRef].sRaw.members.Str(possibleParamIdx) );
01051                  gString aParamSep( intParams[paramRef].sRaw.paramSep );
01052                  sTempVal.Delete( 1, sParamString.Length() + aParamSep.Length() );
01053              }
01054              else {
01055                  if ( pos>=inputSize ) {
01056                      resArgL.Add( sArg );
01057                      resErrL.Add( sArg );
01058                      result++;
01059                      continue;
01060                  }
01061                  // Mark argument as used by value ('2')
01062                  paramUsage[pos+1] = 2;
01063                  sTempVal = inputL.Str(pos+1);
01064              }
01065              // Fill contents of the parameter
01066              // ==> paramVal.sVal = sTempVal
01067              paramVal.FillParam( sTempVal, intParams[paramRef].sRaw.GetParamVal() );
01068              countValErrors += paramVal.errorCode>=2;
01069          }// end IF hasFurtherVal (multi chr option)
01070 
01071          // Finally add the parameter filled to the list of options
01072          paramVal.AddToList( resOptL );
01073      }
01074  }
01075 
01076  for (i=1; i<=inputSize; i++) {
01077      if ( paramUsage[i]<=0 ) {
01078          resArgL.Add( inputL.Str(i) );
01079      }
01080  }
01081 
01082  delete[] paramUsage;
01083 
01084  if ( countValErrors!=0 ) return -1;
01085 
01086  return result;
01087 }
01088 
01089 void gArg::Show (bool doShowAll)
01090 {
01091  unsigned i;
01092  if ( doShowAll ) {
01093      short lIdx;
01094      char shBuf[30];
01095      printf("paramLetter:\n");
01096      for (lIdx=0; lIdx<256; lIdx++) {
01097          if ( paramLetter[lIdx]!=e_ParamNotUsed ) {
01098              shBuf[0] = (char)lIdx;
01099              shBuf[1] = 0;
01100              if ( lIdx<=' ' && lIdx>=127 )
01101                  sprintf( shBuf, "%02X", lIdx );
01102              printf("ASCII%03d: %-2s %u\n",
01103                     lIdx, shBuf, paramLetter[lIdx]);
01104          }
01105      }
01106  }
01107  for (i=1; i<=NumberParams(); i++) {
01108      printf("PARAM%02u/%02u: paramConfig=%u, mainChr=%c%s",
01109             i, NumberParams(),
01110             internParams[i].paramConfig,
01111             internParams[i].MainChar(),
01112             doShowAll?" :":"\n");
01113      if ( doShowAll ) {
01114          internParams[i].Show(true);
01115          sParamRaw::eParamFollow aParamFollow=internParams[i].sRaw.paramFollow;
01116          printf("RAW(%s),paramSep=%s: %s::",
01117                 internParams[i].sRaw.sufStr.Str(),
01118                 internParams[i].sRaw.paramSep.Str(),
01119                 aParamFollow==sParamRaw::e_ParamNoVal?"[]":
01120                 (aParamFollow==sParamRaw::e_ParamThisArg?"[(X=Y)]":"[(X Y)]"));
01121          internParams[i].sRaw.members.Show(true);
01122      }
01123  }
01124 }
01125 ////////////////////////////////////////////////////////////
01126 

Generated on Sat Aug 18 02:40:50 2007 for xpfweb_v2x lib by  doxygen 1.4.2