Actual source code: str.c

  1: /*$Id: str.c,v 1.51 2001/04/05 21:06:52 balay Exp $*/
  2: /*
  3:     We define the string operations here. The reason we just do not use 
  4:   the standard string routines in the PETSc code is that on some machines 
  5:   they are broken or have the wrong prototypes.

  7: */
 8:  #include petsc.h
 9:  #include petscsys.h
 10: #if defined(PETSC_HAVE_STRING_H)
 11: #include <string.h>
 12: #endif
 13: #if defined(PETSC_HAVE_STRINGS_H)
 14: #include <strings.h>
 15: #endif
 16: #include "petscfix.h"

 18: /*@C
 19:    PetscStrlen - Gets length of a string

 21:    Not Collective

 23:    Input Parameters:
 24: .  s - pointer to string

 26:    Output Parameter:
 27: .  len - length in bytes

 29:    Level: intermediate

 31:    Note:
 32:    This routine is analogous to strlen().

 34:    Null string returns a length of zero

 36:   Concepts: string length
 37:   
 38: @*/
 39: int PetscStrlen(const char s[],int *len)
 40: {
 42:   if (!s) {
 43:     *len = 0;
 44:   } else {
 45:     *len = strlen(s);
 46:   }
 47:   return(0);
 48: }

 50: /*@C
 51:    PetscStrallocpy - Allocates space to hold a copy of a string then copies the string

 53:    Not Collective

 55:    Input Parameters:
 56: .  s - pointer to string

 58:    Output Parameter:
 59: .  t - the copied string

 61:    Level: intermediate

 63:    Note:
 64:       Null string returns a new null string

 66:   Concepts: string copy
 67:   
 68: @*/
 69: int PetscStrallocpy(const char s[],char **t)
 70: {
 71:   int ierr,len;

 74:   if (s) {
 75:     PetscStrlen(s,&len);
 76:     PetscMalloc((1+len)*sizeof(char),t);
 77:     PetscStrcpy(*t,s);
 78:   } else {
 79:     *t = 0;
 80:   }
 81:   return(0);
 82: }

 84: /*@C
 85:    PetscStrcpy - Copies a string

 87:    Not Collective

 89:    Input Parameters:
 90: .  s - pointer to string

 92:    Output Parameter:
 93: .  t - the copied string

 95:    Level: intermediate

 97:    Note:
 98:      Null string returns a string starting with zero

100:   Concepts: string copy
101:   
102: .seealso: PetscStrncpy(), PetscStrcat(), PetscStrncat()

104: @*/
105: int PetscStrcpy(char s[],const char t[])
106: {
108:   if (t && !s) {
109:     SETERRQ(1,"Trying to copy string into null pointer");
110:   }
111:   if (t) {strcpy(s,t);}
112:   else {s[0] = 0;}
113:   return(0);
114: }

116: /*@C
117:    PetscStrncpy - Copies a string up to a certain length

119:    Not Collective

121:    Input Parameters:
122: +  s - pointer to string
123: -  n - the length to copy

125:    Output Parameter:
126: .  t - the copied string

128:    Level: intermediate

130:    Note:
131:      Null string returns a string starting with zero

133:   Concepts: string copy

135: .seealso: PetscStrcpy(), PetscStrcat(), PetscStrncat()
136:   
137: @*/
138: int PetscStrncpy(char s[],const char t[],int n)
139: {
141:   strncpy(s,t,n);
142:   return(0);
143: }

145: /*@C
146:    PetscStrcat - Concatenates a string onto a given string

148:    Not Collective

150:    Input Parameters:
151: +  s - pointer to string to be added to end
152: -  t - string to be added to

154:    Level: intermediate

156:   Concepts: string copy

158: .seealso: PetscStrcpy(), PetscStrncpy(), PetscStrncat()
159:   
160: @*/
161: int PetscStrcat(char s[],const char t[])
162: {
164:   strcat(s,t);
165:   return(0);
166: }

168: /*@C
169:    PetscStrncat - Concatenates a string onto a given string, up to a given length

171:    Not Collective

173:    Input Parameters:
174: +  s - pointer to string to be added to end
175: .  t - string to be added to
176: .  n - maximum length to copy 

178:    Level: intermediate

180:   Concepts: string copy

182: .seealso: PetscStrcpy(), PetscStrncpy(), PetscStrcat()
183:   
184: @*/
185: int PetscStrncat(char s[],const char t[],int n)
186: {
188:   strncat(s,t,n);
189:   return(0);
190: }

192: /*@C
193:    PetscStrcmp - Compares two strings,

195:    Not Collective

197:    Input Parameters:
198: +  a - pointer to string first string
199: -  b - pointer to second string

201:    Output Parameter:
202: .  flg - if the two strings are equal

204:    Level: intermediate

206: .seealso: PetscStrgrt(), PetscStrncmp(), PetscStrcasecmp()

208: @*/
209: int PetscStrcmp(const char a[],const char b[],PetscTruth *flg)
210: {
211:   int c;

214:   if (!a && !b) {
215:     *flg = PETSC_TRUE;
216:   } else if (!a || !b) {
217:     *flg = PETSC_FALSE;
218:   } else {
219:     c = strcmp(a,b);
220:     if (c) *flg = PETSC_FALSE;
221:     else   *flg = PETSC_TRUE;
222:   }
223:   return(0);
224: }

226: /*@C
227:    PetscStrgrt - If first string is greater than the second

229:    Not Collective

231:    Input Parameters:
232: +  a - pointer to string first string
233: -  b - pointer to second string

235:    Output Parameter:
236: .  flg - if the first string is greater

238:    Notes:
239:     Null arguments are ok, a null string is considered smaller than 
240:     all others

242:    Level: intermediate

244: .seealso: PetscStrcmp(), PetscStrncmp(), PetscStrcasecmp()

246: @*/
247: int PetscStrgrt(const char a[],const char b[],PetscTruth *t)
248: {
249:   int c;

252:   if (!a && !b) {
253:     *t = PETSC_FALSE;
254:   } else if (a && !b) {
255:     *t = PETSC_TRUE;
256:   } else if (!a && b) {
257:     *t = PETSC_FALSE;
258:   } else {
259:     c = strcmp(a,b);
260:     if (c > 0) *t = PETSC_TRUE;
261:     else       *t = PETSC_FALSE;
262:   }
263:   return(0);
264: }

266: /*@C
267:    PetscStrcasecmp - Returns true if the two strings are the same
268:      except possibly for case.

270:    Not Collective

272:    Input Parameters:
273: +  a - pointer to string first string
274: -  b - pointer to second string

276:    Output Parameter:
277: .  flg - if the two strings are the same

279:    Notes:
280:     Null arguments are ok

282:    Level: intermediate

284: .seealso: PetscStrcmp(), PetscStrncmp(), PetscStrgrt()

286: @*/
287: int PetscStrcasecmp(const char a[],const char b[],PetscTruth *t)
288: {
289:   int c;

292:   if (!a && !b) c = 0;
293:   else if (!a || !b) c = 1;
294: #if defined (PARCH_win32)
295:   else c = stricmp(a,b);
296: #else
297:   else c = strcasecmp(a,b);
298: #endif
299:   if (!c) *t = PETSC_TRUE;
300:   else    *t = PETSC_FALSE;
301:   return(0);
302: }

304: /*@C
305:    PetscStrcmp - Compares two strings, up to a certain length

307:    Not Collective

309:    Input Parameters:
310: +  a - pointer to string first string
311: .  b - pointer to second string
312: -  n - length to compare up to

314:    Output Parameter:
315: .  t - if the two strings are equal

317:    Level: intermediate

319: .seealso: PetscStrgrt(), PetscStrncmp(), PetscStrcasecmp()

321: @*/
322: int PetscStrncmp(const char a[],const char b[],int n,PetscTruth *t)
323: {
324:   int c;

327:   c = strncmp(a,b,n);
328:   if (!c) *t = PETSC_TRUE;
329:   else    *t = PETSC_FALSE;
330:   return(0);
331: }

333: /*@C
334:    PetscStrchr - Locates first occurance of a character in a string

336:    Not Collective

338:    Input Parameters:
339: +  a - pointer to string first string
340: -  b - character

342:    Output Parameter:
343: .  c - location of occurance, PETSC_NULL if not found

345:    Level: intermediate

347: @*/
348: int PetscStrchr(const char a[],char b,char **c)
349: {
351:   *c = (char *)strchr(a,b);
352:   return(0);
353: }

355: /*@C
356:    PetscStrrchr - Locates one location past the last occurance of a character in a string,
357:       if the character is not found then returns entire string

359:    Not Collective

361:    Input Parameters:
362: +  a - pointer to string first string
363: -  b - character

365:    Output Parameter:
366: .  tmp - location of occurance, a if not found

368:    Level: intermediate

370: @*/
371: int PetscStrrchr(const char a[],char b,char **tmp)
372: {
374:   *tmp = (char *)strrchr(a,b);
375:   if (!*tmp) *tmp = (char*)a; else *tmp = *tmp + 1;
376:   return(0);
377: }

379: /*@C
380:    PetscStrtolower - Converts string to lower case

382:    Not Collective

384:    Input Parameters:
385: .  a - pointer to string

387:    Level: intermediate

389: @*/
390: int PetscStrtolower(char a[])
391: {
393:   while (*a) {
394:     if (*a >= 'A' && *a <= 'Z') *a += 'a' - 'A';
395:     a++;
396:   }
397:   return(0);
398: }

400: /*@C
401:    PetscTokenFind - Locates next "token" in a string

403:    Not Collective

405:    Input Parameters:
406: .  a - pointer to token

408:    Output Parameter:
409: .  result - location of occurance, a if not found

411:    Notes:

413:      This version is different from the system version in that
414:   it allows you to pass a read-only string into the function.

416:    Level: intermediate

418: .seealso: PetscTokenCreate(), PetscTokenDestroy()
419: @*/
420: int PetscTokenFind(PetscToken *a,char **result)
421: {
422:   char *ptr = a->current;

425:   *result = a->current;
426:   if (ptr && *ptr == 0) *result = 0;
427:   while (ptr) {
428:     if (*ptr == a->token) {
429:       *ptr++ = 0;
430:       while (*ptr == a->token) ptr++;
431:       a->current = ptr;
432:       break;
433:     }
434:     if (*ptr == 0) {
435:       a->current = 0;
436:       break;
437:     }
438:     ptr++;
439:   }
440:   return(0);
441: }

443: /*@C
444:    PetscTokenCreate - Creates a PetscToken used to find tokens in a string

446:    Not Collective

448:    Input Parameters:
449: +  string - the string to look in
450: -  token - the character to look for

452:    Output Parameter:
453: .  a - pointer to token

455:    Notes:

457:      This version is different from the system version in that
458:   it allows you to pass a read-only string into the function.

460:    Level: intermediate

462: .seealso: PetscTokenFind(), PetscTokenDestroy()
463: @*/
464: int PetscTokenCreate(const char a[],const char b,PetscToken **t)
465: {
466:   int         ierr,len;

469:   PetscNew(PetscToken,t);
470:   PetscStrlen(a,&len);
471:   PetscStrallocpy(a,&(*t)->array);
472:   (*t)->current = (*t)->array;
473:   (*t)->token   = b;
474:   return(0);
475: }

477: /*@C
478:    PetscTokenDestroy - Destroys a PetscToken

480:    Not Collective

482:    Input Parameters:
483: .  a - pointer to token

485:    Level: intermediate

487: .seealso: PetscTokenCreate(), PetscTokenFind()
488: @*/
489: int PetscTokenDestroy(PetscToken *a)
490: {

494:   PetscFree(a->array);
495:   PetscFree(a);
496:   return(0);
497: }

499: /*@C
500:    PetscStrstr - Locates first occurance of string in another string

502:    Not Collective

504:    Input Parameters:
505: +  a - pointer to string
506: -  b - string to find

508:    Output Parameter:
509: .  tmp - location of occurance

511:    Level: intermediate

513: @*/
514: int PetscStrstr(const char a[],const char b[],char **tmp)
515: {
517:   *tmp = (char *)strstr(a,b);
518:   return(0);
519: }

521: /*@C
522:    PetscGetPetscDir - Gets the directory PETSc is installed in

524:    Not Collective

526:    Output Parameter:
527: .  dir - the directory

529:    Level: developer

531: @*/
532: int PetscGetPetscDir(char **dir)
533: {
535:   *dir = PETSC_DIR;
536:   return(0);
537: }

539: /*@C
540:    PetscStrreplace - Replaces substrings in string with other substrings

542:    Not Collective

544:    Input Parameters:
545: +   comm - MPI_Comm of processors that are processing the string
546: .   a - the string to look in
547: .   b - the resulting copy of a with replaced strings
548: -   len - the length of b

550:    Notes:
551:       Replaces   ${PETSC_ARCH},${BOPT},${PETSC_DIR},${PETSC_LIB_DIR},${DISPLAY},
552:       ${HOMEDIRECTORY},${WORKINGDIRECTORY},${USERNAME} with appropriate values
553:       as well as any environmental variables.
554:    
555:    Level: intermediate

557: @*/
558: int PetscStrreplace(MPI_Comm comm,const char a[],char *b,int len)
559: {
560:   int        ierr,i = 0,l,l1,l2,l3;
561:   char       *work,*par,*epar,env[256];
562:   char       *s[] = {"${PETSC_ARCH}","${BOPT}","${PETSC_DIR}","${PETSC_LIB_DIR}","${DISPLAY}","${HOMEDIRECTORY}","${WORKINGDIRECTORY}","${USERNAME}",0};
563:   char       *r[] = {PETSC_ARCH,PETSC_BOPT,PETSC_DIR,PETSC_LIB_DIR,0,0,0,0,0};
564:   PetscTruth flag;

567:   if (len <= 0) SETERRQ(1,"Length of b must be greater than 0");
568:   if (!a || !b) SETERRQ(1,"a and b strings must be nonnull");
569:   PetscMalloc(len*sizeof(char*),&work);

571:   /* get values for replaced variables */
572:   PetscMalloc(256*sizeof(char),&r[4]);
573:   PetscMalloc(256*sizeof(char),&r[5]);
574:   PetscMalloc(256*sizeof(char),&r[6]);
575:   PetscMalloc(256*sizeof(char),&r[7]);
576:   PetscGetDisplay(r[4],256);
577:   PetscGetHomeDirectory(r[5],256);
578:   PetscGetWorkingDirectory(r[6],256);
579:   PetscGetUserName(r[7],256);

581:   /* replace the requested strings */
582:   PetscStrncpy(b,a,len);
583:   while (s[i]) {
584:     PetscStrlen(s[i],&l);
585:     PetscStrstr(b,s[i],&par);
586:     while (par) {
587:       *par  =  0;
588:       par  += l;

590:       PetscStrlen(b,&l1);
591:       PetscStrlen(r[i],&l2);
592:       PetscStrlen(par,&l3);
593:       if (l1 + l2 + l3 >= len) {
594:         SETERRQ(1,"b len is not long enough to hold new values");
595:       }
596:       ierr  = PetscStrcpy(work,b);
597:       ierr  = PetscStrcat(work,r[i]);
598:       ierr  = PetscStrcat(work,par);
599:       ierr  = PetscStrncpy(b,work,len);
600:       ierr  = PetscStrstr(b,s[i],&par);
601:     }
602:     i++;
603:   }
604:   PetscFree(r[4]);
605:   PetscFree(r[5]);
606:   PetscFree(r[6]);
607:   PetscFree(r[7]);

609:   /* look for any other ${xxx} strings to replace from environmental variables */
610:   PetscStrstr(b,"${",&par);
611:   while (par) {
612:     *par = 0;
613:     par += 2;
614:     ierr  = PetscStrcpy(work,b);
615:     PetscStrstr(par,"}",&epar);
616:     *epar = 0;
617:     epar += 1;
618:     PetscOptionsGetenv(comm,par,env,256,&flag);
619:     if (!flag) {
620:       SETERRQ1(1,"Substitution string ${%s} not found as environmental variable",par);
621:     }
622:     PetscStrcat(work,env);
623:     PetscStrcat(work,epar);
624:     PetscStrcpy(b,work);
625:     PetscStrstr(b,"${",&par);
626:   }
627:   PetscFree(work);

629:   return(0);
630: }