earlybrowserreborn - Blame information for rev 4

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 roytam 1 /*
2  * Copyright 1990 Pei-Yuan Wei.  All rights reserved.
3  *
4  * Permission to use, copy, and/or distribute for any purpose and
5  * without fee is hereby granted, provided that both the above copyright
6  * notice and this permission notice appear in all copies and derived works.
7  * Fees for distribution or use of this software or derived works may only
8  * be charged with express written permission of the copyright holder.
9  * This software is provided ``as is'' without express or implied warranty.
10  */
11 /*
12  * mystrings.c  -  Miscelaneous string functions.
13  */
14  
15 #include "utils.h"
16 #include "sys.h"
17 #include <ctype.h>
18 #include "mystrings.h"
19  
20 #define CTRL_d 4
21 /*extern char *malloc();*/
22  
23 char buff[BUFF_SIZE];
24 int buffi;
25  
26 int numOfGBuffs = 0;
27 char *GBuff[NUM_OF_GBUFFS];
28 int GBuffIdx[NUM_OF_GBUFFS];
29 int GBuffSize[NUM_OF_GBUFFS];
30  
31 /* Char strBuff[MAX_LINE_LENGTH]; */
32 char spaces[80] = {"                                                                              "};
33  
34 long itemValArray[40];
35 long itemValArray2[40];
36  
37 /* later, make into flags so no function call is necessary
38  */
39 int cmp_str(s1, s2)
40         char *s1;
41         char *s2;
42 {
43         if (s1[0] == s2[0])
44                 if (!strcmp(s1, s2)) return 1;
45         return 0;
46 }
47  
48 int cmp_int(n1, n2)
49         int n1;
50         int n2;
51 {
52         return n1 == n2;
53 }
54  
55 void SkipBlanks(linep, i)
56      char *linep;
57      int *i;
58 {
59   while (linep[*i]) {
60     if (!ISSPACE(linep[*i])) return;
61     ++(*i);
62   }
63 }
64  
65 int noCaseCharCmp(c1, c2)
66      char c1, c2;
67 {
68   if (c1 > 'Z') c1 -= 32; /* convert to lower case */
69   if (c2 > 'Z') c2 -= 32;
70   if (c1 == c2) return 1;
71   else return 0;
72 }
73  
74 /*
75  * case insensitive strcmp
76  */
77 int noCaseStrCmp(s1, s2)
78      char *s1, *s2;
79 {
80   while (*s1 && *s2) {
81     if (!noCaseCharCmp(*s1++, *s2++)) return 0;
82   }
83   if (*s1 == '\0' && *s2 == '\0') return 1;
84   return 0;
85 }
86  
87 /*
88  ** Stores the next word in linep in *wordp. Current postion in line is
89  ** pointed to by index i.
90  ** spaces around the word is trimed.
91  *
92  * PreCondition: i <= strlen(linep);
93  *               *wordp must be large enough to hold any argument in *linep.
94  * PostCondition: *wordp contains an argument string from *linep.
95  */
96 int NextWord(linep, i, wordp)
97      char *linep;
98      int i;
99      char *wordp;
100 {
101   int j = 0;
102  
103   for (;;) {
104     if (!linep[i]) {
105       wordp[j] = '\0';
106       return i;
107     }
108     if (!ISSPACE(linep[i])) break;
109     ++i;
110   }
111  
112   for (;;) {
113     if (!linep[i]) break;
114     if (ISSPACE(linep[i])) break;
115     wordp[j++] = linep[i++];
116   }
117   wordp[j] = '\0';
118  
119   return i;
120 }
121  
122 /*
123  ** Skips the next word linep in *wordp. Current postion in line is
124  ** pointed to by index i.
125  ** will skip over spaces around the word.
126  *
127  * PreCondition: i <= strlen(linep);
128  *               *wordp must be large enough to hold any argument in *linep.
129  * PostCondition: *wordp contains an argument string from *linep.
130  */
131 int SkipNextWord(linep, i)
132      char *linep;
133      int i;
134 {
135   for (;;) {
136     if (linep[i] == NULL) return i;
137     if (!ISSPACE(linep[i])) break;
138     ++i;
139   }
140   for (;;) {
141     if (linep[i] == NULL) break;
142     if (ISSPACE(linep[i])) break;
143     ++i;
144   }
145   return i;
146 }
147  
148 /*
149  * copys the next phrase, up to the cutOffWord, onto destStr.
150  * if no cutOffWord is found, the phrase string is copied anyway.
151  */
152 int GetNextPhrase(str, i, destStr, cutOffWord)
153      char   *str;
154      int     i;
155      char    *destStr;
156      char    *cutOffWord;
157 {
158   char c;
159   int x, y, ci = i, cuti = 0, parenLevel = 0, quoteToggle = 0;
160   int cutOffWordLen = strlen(cutOffWord);
161   extern int hush;
162  
163   while (c = str[ci]) {
164     if (parenLevel == 0 && quoteToggle == 0)
165       if (c == cutOffWord[cuti]) {
166         ++cuti;
167         if (cuti >= cutOffWordLen) {
168           ++ci;
169           goto gag;
170         }
171       } else {
172         cuti = 0;
173       }
174     if (c == '\"') {
175       if (quoteToggle) quoteToggle = 0;
176       else quoteToggle = 1;
177       cuti = 0;
178     } else if (c == '(') {
179       ++parenLevel;
180       cuti = 0;
181     } else if (c == ')') {
182       --parenLevel;
183       cuti = 0;
184     }
185     ++ci;
186   }
187   cuti = 0;
188  gag:
189   if (cuti) {
190     for (y = 0, x = i; x < (ci - cuti); x++, y++) destStr[y] = str[x];
191     destStr[y] = '\0';
192     /* fprintf(stderr, "cuit=%d '%s' i=%d str='%s' ci=%d '%s'\n",cuti, cutOffWord, i, str, ci, destStr); */
193     return ci;
194   }
195   for (y = 0, x = i; str[x]; x++, y++) destStr[y] = str[x];
196   destStr[y] = '\0';
197   /* fprintf(stderr, "'%s' i=%d str='%s' i=%d '%s'\n",cutOffWord, i, str, i, destStr);*/
198   return i;
199 }
200  
201 /*
202  * gets and returns the next specified lines in a string.
203  * unless preceded by '\\' lines are separated by '\n'
204  *
205  * "lines" specify how many lines to read.
206  * returns: number of characters in returned string
207  *          string containing the next number of "lines"
208  */
209 char *NextLines(textpp, lines, size)
210      char **textpp;
211      int *lines, *size;
212 {
213   char c = '\0', *textSavep, *cp;
214   int linesToGet = *lines;
215  
216   *lines = 0;
217   *size = 0;
218  
219   if (textpp == NULL) return NULL;
220  
221   textSavep = *textpp;
222  
223   while (**textpp) {
224     /* ignore '\n' if preceded by '\\' */    
225     if (**textpp == '\n' || **textpp == '\r') {
226       if (c == '\\') {
227         /* back up -- don't want to include '\\' */
228         c = **textpp;
229         --(*size);
230         ++(*textpp);
231       } else {
232         if (++(*lines) >= linesToGet) {
233           ++(*textpp);
234           break;
235         }
236       }
237     }
238     if (*size > BUFF_SIZE) {
239       /* exceeding line buffer size */
240       *textpp = textSavep;
241       *lines = 0;
242       *size = 0;
243       return NULL;
244     }
245     c = **textpp;
246     buff[(*size)++] = **textpp;
247     ++(*textpp);
248   }
249   buff[(*size)] = '\0';
250   if ((cp = (char*)malloc(sizeof(char) * (*size + 1))) == NULL) {
251     perror("NextLines(): malloc failed.");
252     return NULL;
253   }
254   strcpy(cp, buff);
255   return cp;
256 }
257  
258 /*
259  * skip the next specified lines in a string.
260  * unless preceded by '\\' lines are separated by '\n'
261  *
262  * "lines" specify how many lines to skip.
263  * returns: current textpp value;
264  */
265 char *SkipNextLines(textpp, lines, size)
266      char **textpp;
267      int *lines, *size;
268 {
269   char c = '\0';
270   int linesToGet = *lines;
271  
272   *lines = 0;
273   *size = 0;
274  
275   if (textpp == NULL) return NULL;
276  
277   for (;;) {
278     if (**textpp == '\0') return NULL;
279  
280     /* ignore '\n' if preceded by '\\' */
281     if (**textpp == '\n' || **textpp == '\r') {
282       if (c == '\\') {
283         /* back up -- don't want to include '\\' */
284         c = **textpp;
285         --(*size);
286         ++(*textpp);
287       } else {
288         if (++(*lines) >= linesToGet) {
289           ++(*textpp);
290           return *textpp;
291         }
292       }
293     }
294     c = **textpp;
295     ++(*size);
296     ++(*textpp);
297   }
298 }
299  
300 /*
301  ** Gets a line of strings.
302  *
303  * PreCondition:  commandline must have atleat MAX_LINE_LENGTH characters.
304  * PostCondition: commandline contains a line of strings ended with '\0'.
305  *                terminate line with <return>.
306  * Return: address of the string
307  */
308 char *GetLine(commandline)
309      char *commandline;
310 {
311   char c;
312   int i = 0;
313  
314   while (((c = getchar()) != '\n') && (i < (MAX_LINE_LENGTH - 1))) {
315     if (c == CTRL_d) break;
316     commandline[i++] = c;
317   }
318   commandline[i] = '\0';
319  
320   return commandline;
321 }
322  
323 /*
324  ** Determines if a line is all blank(without any printable characters
325  ** for command). Control character are not accepted as command characters.
326  *
327  * PreCondition: str must end with a zero.
328  */
329 int AllBlank(str)
330      char *str;
331 {
332   if (str) {
333     char c;
334  
335     while (c = *(str++)) {
336       if (!ISSPACE(c)) return 0;
337     }
338   }
339   return 1;
340 }
341  
342 /*
343  ** Searches a char is within a string.
344  *
345  * RETURN: The index value of where the search char is on the string
346  *         -1 if search character is not in the string.
347  * PRECONDITION: str must end with null.
348  */
349 int SearchChar(str,sc)
350      char *str;
351      char sc;
352 {
353   char c;
354   int i = 0;
355  
356   while (c = str[i]) {
357     if (c == sc) return i;
358     i++;
359   }
360   return -1;
361 }
362  
363 /*
364  ** Cut the trailing spaces.  ie. move the '\0' toward the front,
365  ** to fill up the tail spaces.
366  *
367  * PRECONDITION: str must end with null.
368  * RETURN: Number of spaces cut.
369  *         0 if strings is set to NULL.
370  */
371 int CutTailSpace(str)
372      char *str;
373 {
374   if (str) {
375     int l, i = 0;
376  
377     l = strlen(str);
378     if (l <= 0) return 0;
379  
380     for (i = l - 1; (i >= 0) && (str[i] == ' '); i--) str[i] = '\0';
381  
382     return l - i - 1;
383   }
384   return 0;
385 }
386  
387 /*
388  * cuts of the spaces, if any, at the beginning and the end of a string.
389  */
390 char *trimEdgeSpaces(str)
391      char *str;
392 {
393   int i;
394   char c, *cp, *cp2;
395  
4 roytam 396   if (!str) return str;
1 roytam 397   if (!str[0]) return str;
398  
399   for (cp = str; c = *cp; cp++) {
400     if (!ISSPACE(c)) {
401       cp2 = str;
402       if (cp > str) {
403         /* shift string toward left to write over leading spaces */
404         i = cp - str;
405         while (*cp) *(cp2++) = *(cp++);
406         *cp2 = '\0';
407       } else {
408         while (*(++cp2)); /* travel to end of string */
409       }
410       /* go backward and replace blanks with 0 */
411       for(--cp2; cp2 >= str; cp2--) {
412         c = *cp2;
413         if (!ISSPACE(c)) {
414           *(cp2+1) = '\0';
415           return str;
416         }
417       }
418       return str;
419     }
420   }
421   return str;
422 }
423  
424 /*
425  * rids of the leading spaces
426  * shift string toward left to write over leading spaces
427  */
428 char *trimFrontSpaces(str)
429      char *str;
430 {
431   int i = 0, j = 0;
432  
433   do {
434     if (!ISSPACE(str[i])) {
435       if (i > 0) {
436         /* shift string toward left to write over leading spaces */
437         while (str[i]) str[j++] = str[i++];
438         str[j] = '\0';
439       }
440       return str;
441     }
442   } while (str[i++]);
443  
444   return str;
445 }
446  
447 /*
448  ** Convert a string to signed int number value
449  *
450  * PRECONDITION: string must be unsigned and contain only digits with
451  *               possibly sign(first char).
452  *               Camas and decimal points are ignored.
453  * RETURN: proper value. or 0 if str is NULL
454  * NOTE: Spaces at edges are ok. ex: "   ---2345.3555 " -> (-2345)
455  */
456 int strToVal(str)
457      char *str;
458 {
459   int i, j = 1, val = 0, negate = 1;
460  
461   if (str == NULL) return 0;
462  
463   for (i = strlen(str) - 1; i >= 0; i--) {
464     /* fprintf(stderr, "%d %d %d %d\n",(*(str+i)-'0'), val,*(str+i),j);*/
465     if (*(str+i) == '-') negate *= -1;
466     if (*(str+i) == '.') {
467       j = 1;
468       val = 0;
469       continue;
470     }
471     if (isdigit(*(str + i))) {
472       val += (*(str + i) - '0') * j;
473       j *= 10;
474     }
475   }
476   val *= negate;
477   return val;
478 }
479  
480 /*
481  ** puts the signed int val in str form
482  *
483  * PRECONDITION: val must be integer.
484  */
485 char *valToStr(val, str)
486      long val;
487      char *str;
488 {
489   long i, j = 0, digit;
490  
491   if (val > MAX_LONG) val = MAX_LONG;
492  
493   if (val == 0) {
494     str[0] = '0';
495     str[1] = '\0';
496     return str;
497   }
498  
499   if (val < 0) {  /* if value if negative */
500     val *= -1;
501     *(str + j++) = '-';
502   }
503  
504   /* skip all non-zero digit*/
505   for (i = MAX_LONG; i > 0 && (val / i) == 0 ; i /= 10);
506  
507   for (; i > 0; i /= 10) {
508     digit = val / i;
509     *(str + j) = digit + '0';
510     val -= digit * i;
511     j++;
512 /*
513   fprintf(stderr, "%ld %ld %ld %ld %ld %ld\n",
514   (long)digit, (long)(*(str+j)-'0'), (long)val,
515   (long)*(str + j), (long)j,(long)i);
516 */
517   }
518   str[j++] = 0;
519  
520   return str;
521 }
522  
523 /*
524  * find where the common character is
525  * RETURN: -1 if none.
526  */
527 int commonCharAt(str, set)
528      char *str, *set;
529 {
530   int i = 0;
531  
532   while (*set) {
533     if (charIsInStr(*set++, str)) return i;
534     ++i;
535   }
536   return -1;
537 }
538  
539 /*
540  * see if str contains any characters in set.
541  */
542 int anyCommonChar(str, set)
543     char *str, *set;
544 {
545   while (*str)
546     if (charIsInStr(*str++, set)) return 1;
547   return 0;
548 }
549  
550 /*
551  * see if character ch is in string str
552  */
553 int charIsInStr(ch, str)
554     char ch, *str;
555 {
556   while (*str) {
557     if (*str++ == ch)
558       return 1;        /* change 1 to I will make if-then not work...*/
559   }
560   return 0;
561 }
562  
563 int numOfChar(str,sc)
564      char str[];
565      char sc;
566 {
567   char c;
568   int i = 0, j = 0;
569  
570   while (c = str[i]) {
571     if (c == sc) j++;
572     i++;
573   }
574   return j;
575 }
576  
577 /*
578  * trim off the enclosing quotes of a string
579  */
580 char *trimQuote(str)
581      char *str;
582 {
583   char *s, *h = str;
584  
585   while (*str != '\0') {
586     if (*str == '\"') {
587       s = str;
588       while (*s != '\0') {
589         *s = *(s + 1);
590         s++;
591       }
592     }
593     str++;
594   }
595   return h;
596 }
597  
598 /* allocates bigger space, and append to it.. the original string is freed*/
599 char *append(orig, append)
600      char *orig, *append;
601 {
602   char *sp;
603  
604   if (sp = (char*)malloc(sizeof(char)*(strlen(orig) + strlen(append) + 1))) {
605     strcpy(sp, orig);
606     strcat(sp, append);
607     if (orig) free(orig);
608     return sp;
609   } else {
610     fprintf(stderr, "malloc failed.");
611     return NULL;
612   }
613 }
614  
615 /* same as append, with a carriage appended at the end */
616 char *appendLine(orig, append)
617      char *orig, *append;
618 {
619   char *sp;
620  
621   if (sp = (char*)malloc(sizeof(char) * (strlen(orig) + strlen(append) + 2))) {
622     strcpy(sp, orig);
623     strcat(sp, append);
624     strcat(sp, "\n");
625     if (orig) free(orig);
626     return sp;
627   } else {
628     fprintf(stderr, "malloc failed.");
629     return NULL;
630   }
631 }
632  
633 char *saveString(str)
634      char *str;
635 {
636   char *sp;
637  
638   if (!str) return NULL;/*bad*/
639  
640   if (sp = (char*)malloc(sizeof(char) * (strlen(str) + 1))) {
641     strcpy(sp, str);
642     return sp;
643   }
644   fprintf(stderr, "malloc failed.");
645   return NULL;
646 }
647  
648 char *saveStringN(str, size)
649      char *str;
650      int size;
651 {
652   char *sp = (char*)malloc(sizeof(char) * size);
653  
654   if (sp) {
655     strncpy(sp, str, size);
656     return sp;
657   }
658   fprintf(stderr, "malloc failed.");
659   return NULL;
660 }
661  
662 char *VsaveString(group, str)
663      MemoryGroup *group;
664      char *str;
665 {
666   char *sp;
667  
668   if (!str) return NULL;
669  
670   if (sp = (char*)Vmalloc(group, sizeof(char) * (strlen(str) + 1))) {
671     strcpy(sp, str);
672     return sp;
673   } else {
674     fprintf(stderr, "malloc failed.");
675     return NULL;
676   }
677 }
678  
679 int eqStr(cmpStr, fixedStr)
680      char *cmpStr, *fixedStr;
681 {
682   char *sp = (char*)malloc(sizeof(char) * (strlen(cmpStr) + 1));
683  
684   strcpy(sp, cmpStr);
685   trimEdgeSpaces(sp);
686   if (!STRCMP(sp, fixedStr)) {
687     free(sp);
688     return 1;
689   }
690   free(sp);
691   return 0;
692 }
693  
694 char *listSum2Str(list1, list2, listLength, str)
695      int list1[], list2[], listLength;
696      char *str;
697 {
698   int i = 0;
699   char localBuff[40];
700  
701   str[0] = '\0';
702   for (; i < listLength; i++) {
703     strcat(str, valToStr((long)(list1[i] + list2[i]), localBuff));
704     if (i < listLength - 1) strcat(str, ",");
705   }
706   return str;
707 }
708  
709 void insertChar(eStr, col, c)
710     char *eStr;
711     int   col;
712     char  c;
713 {
714   shiftStr(eStr, col, 1);
715   eStr[col] = c;
716 }
717  
718 int shiftStr(strp, starti, shift)
719      char *strp;
720      int starti, shift;
721 {
722   int length, shifts = 0;
723   int i, j = 0;
724  
725   length = strlen(strp);
726   if (shift > 0) {
727     strp[length+shift] = '\0';
728     for (i = length-starti; i > 0; i--) {
729       j++;
730       strp[length+shift-j] = strp[length - j];
731       ++shifts;
732     }
733   } else {
734     i = length - starti;
735     strp[length - shift + j] = '\0';
736     while (i >= 0) {
737       strp[starti + j] = strp[starti - shift + j];
738       --shifts;
739       j++;
740       i--;
741     }
742   }
743   return shifts;
744 }
745  
746 /*
747  * Line numbering start at 0
748  *
749  * Up to the user to free returned data.
750  */
751 char *getLines(low, high, text, size)
752         int low, high;
753         char *text;
754         int *size;
755 {
756         char *cp;
757         char *begin = text;
758         char *end;
759         int i = 0;
760  
761         if (i < low)
762                 for (; *begin; begin++)
763                         if (*begin == '\n')
764                                 if (++i >= low) {
765                                         begin++;
766                                         break;
767                                 }
768         end = begin;
769         if (i <= high)
770                 for (; *end; end++)
771                         if (*end == '\n')
772                                 if (i++ >= high) {
773                                         end++;
774                                         break;
775                                 }
776         *size = end - begin;
777         if (*size > 0) {
778                 cp = (char*)malloc(sizeof(char) * (*size + 1));
779                 strncpy(cp, begin, *size);
780                 cp[*size] = '\0';
781         } else {
782                 cp = (char*)malloc(sizeof(char));
783                 cp[0] = '\0';
784                 *size = 1;
785         }
786         return cp;
787 }
788  
789 /* UNUSED */
790 char *enQuote(str)
791      char *str;
792 {
793   char *buffp = buff;
794  
795   *buffp++ = '\"';
796   while (*str) *buffp++ = *str++;
797   *buffp++ = '\"';
798   *buffp = '\0';
799  
800   return SaveString(buff);
801 }
802  
803 char *enBracket(list)
804      char *list;
805 {
806   char *buffp = buff;
807  
808   *buffp++ = '{';
809   while (*list) *buffp++ = *list++;
810   *buffp++ = '}';
811   *buffp = '\0';
812  
813   return SaveString(buff);
814 }
815  
816 /* not properly done - merely replaces {...} with space
817  * may bomb if list string is empty ""
818  */
819 char *deBracket(list)
820      char *list;
821 {
822   if (!list[0]) {
823     return list;
824   } else {
825     int i;
826     char c;
827  
828     for (i = 0; c = list[i]; i++) {
829       if (c == '{') {
830         list[i] = ' ';
831         break;
832       }
833     }
834     for (i = strlen(list); i >= 0; i--) {
835       if (list[i] == '}') {
836         list[i] = '\0';
837         break;
838       }
839     }
840     trimFrontSpaces(list);
841     return list;
842   }
843 }
844  
845 /*
846  * grabs item(s) out of a {list}
847  */
848 char *listItem(list, li, hi)
849      char *list;
850      int li, hi;
851 {
852   char c;
853   int i, bi = 0, itemNum = 1, paren = 0;
854  
855   /* skip the first left bracket */
856   for (i = 0; (c = *(list + i)) != '\0'; i++) {
857     if (c == '{') {
858       paren = 1;
859       ++i;
860       break;
861     }
862   }
863   buff[bi++] = '{';
864  
865   for (; (c = *(list + i)) != '\0'; i++) {
866     if (itemNum > hi) break;
867     switch (c) {
868     case '{':
869       if (++paren >= 1)
870         if (itemNum >= li) buff[bi++] = '{';
871       break;
872     case '}':
873       if (--paren >= 1)
874         if (itemNum >= li) buff[bi++] = '}';
875       break;
876     case ',':
877       if (paren == 1) ++itemNum;
878       if (paren >= 1) {
879         if (itemNum == li) {
880           if (paren >= 2) buff[bi++] = ',';
881         } else if ((itemNum > li) && (itemNum <= hi)) buff[bi++] = ',';
882       }
883       break;
884     default:
885       if (itemNum >= li) buff[bi++] = c;
886     }
887   }
888   buff[bi++] = '}';
889   buff[bi] = '\0';
890   return SaveString(buff);
891 }
892  
893  
894 /*
895  * individual items must be less than 32 characters long.
896  */
897 int getItemVals(li, hi, itemStr)
898      int li, hi;
899      char *itemStr;
900 {
901   int itemNum= 1;
902   int bi = 0, i, flag = 0, ai=1;
903   char c, str[32]; /* dangerous... */
904  
905   if (itemStr == NULL) {
906     return NULL;
907   }
908   for (i = 0; (c = *(itemStr + i)) != '\0'; i++) {
909     if (itemNum > hi) break;
910     if (c == ',') {
911       itemNum++;
912       if (flag) {
913         str[bi] = '\0';
914         itemValArray[ai++] = (long)strToVal(str);
915         bi = 0;
916       }
917     } else if (itemNum >= li) {
918       if (c != '{' && c != '}') str[bi++] = c;
919       flag = 1;
920     }
921   }
922   str[bi] = '\0';
923   itemValArray[ai++] = (long)strToVal(str);
924   itemValArray[ai] = (long)ai;
925  
926   return ai;
927 }
928  
929 char *extractWord(text, li, hi, retStr)
930         char *text;
931         int li, hi;
932         char *retStr;
933 {
934         int bi = 0, i = 0, itemNum = 1;
935         char c;
936  
937         if (!isalnum(*text)) itemNum = 0;       /* head needs skiping */
938  
939         while ((c = *(text + i)) != '\0') {
940                 if (!isalnum(c)) {
941                         if (itemNum >= hi) goto done;
942                         do {
943                                 if (itemNum >= li) retStr[bi++] = c;
944                                 if ((c = *(text + (++i))) == '\0') goto done;
945                         } while (!isalnum(c));
946                         ++itemNum;
947                 }
948                 if (itemNum >= li) retStr[bi++] = c;
949                 ++i;
950         }
951  done:
952         retStr[bi] = '\0';
953  
954         return retStr;
955 }