Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Path: utzoo!mnetor!seismo!rutgers!ames!ucbcad!ucbvax!ULKYVX.BITNET!RDROYA01 From: RDROYA01@ULKYVX.BITNET (Robert Royar) Newsgroups: comp.sys.atari.st Subject: String.c Message-ID: <8705271729.AA20883@ucbvax.Berkeley.EDU> Date: Wed, 27-May-87 12:07:00 EDT Article-I.D.: ucbvax.8705271729.AA20883 Posted: Wed May 27 12:07:00 1987 Date-Received: Sat, 30-May-87 01:31:18 EDT Sender: daemon@ucbvax.BERKELEY.EDU Distribution: world Organization: University of Louisville Lines: 347 This is a repost. The file I sent two weeks ago never got through. Could someone on BITNET send me a message to RDROYA01@ULKYVX detailing an address path to comp.sys.atari.st using bitnet or arpanet gateways? The routines in this file serve three purposes. They give Alcyon programmers who don't need all of the GEMLIB startup stuff or other baggage some useful string routines. Many are in GEMLIB already, but you can use these in very small TOS programs, such as auto folder programs. The second purpose is to provide the additional routines strpos, strrpos, strpbrk, strrpbrk, strscn, and strcscn which are not part of the Alcyon distribution. The last purpose is to fix a bug in the Atari/DRI index strchr routine. As written in the startup.s file, it does not return a pointer to the end of string when given the following: index("hello",'\0'); Harbison and Steele say that index/strchr should return a pointer to the NULL at the end of "hello" rather than a NULL pointer in this case. The bug was added by DRI and perpetuated by Atari. The Alcyon library's versions of strchr and strrchr both return pointers to the NULL at the end of "hello" when given the input above. I wonder if Atari can spell hermeneutics? And now, two questions. 1. Does anyone have the proper definition of the __fds structure that the Alcyon file ops use for each file? I know there is a definition in OSIF.H, but it refers to CP/M specific stuff like user numbers and passwords which don't seem to correspond to anything under GEM. Under the CP/M system you can get at the low level file handle for streams by working with the fds (note that fileno(fp) != file handle of the file). Note also that the Atari written low level C open routine fails to check for the file type (i.e. RO RW). If you've used the stack a bit and try to open a RO file for reading, the open will fail, simply because xopen fails to push the mode onto the stack. It would be relatively easy to replace xopen knowing the real __fds structure, a lot easier than rewriting the entire stream package. 2. Does anyone have a TOS-based font loader? I'd like something that will reset the default font and will allow the new font to be used by TOS-based programs. Is this impossible? It seems all that would be needed would be to load a new font, reset the old pointers (via linea), and Ptermres(). Anyway here's the string manipulation code: O O x (cut here) ---------------------------/-\------------------------------------------ #include /* return length of str excluding the NULL */ strlen(str) register char *str; { register int len; len = 0; while(*str) { ++str; ++len; } return(len); } /* append str2 to str1, returning the beginning of str1 */ char * strcat(str1,str2) register char *str1, *str2; { register char *sptr; sptr = str1; while(*str1) ++str1; while(*str2) *str1++ = *str2++; *str1 = '\0'; return(sptr); } /* copy str2 to str1, returning the beginning of str1 */ char * strcpy(dest,src) register char *dest, *src; { register char *sptr; sptr = dest; while(*src) *dest++ = *src++; *dest = '\0'; return(sptr); } /* is str1 == str2? 0==yes; -#== str2 > str1; +#== str1 > str2 */ strcmp(str1,str2) register char *str1, *str2; { while(*str1) { if(*str1 != *str2) return(*str1-*str2); ++str1; ++str2; } if(*str2=='\0') return(0); else return(-1); } /* not in GEMLIB */ /* index 0 position of first occurence c in string str. -1 if c is not in str */ strpos(str, c) register char *str; register char c; { register int pos; pos = 0; while(*str) { if (*str++ == c) return(pos); ++pos; } if (c == '\0') return(pos); else return(-1); } /* Not in GEMLIB */ /* index 0 of position of last occurence of c in str. -1 if c not in str */ strrpos(str, c) register char *str; register char c; { register int pos; pos = 0; while(*str) { ++str; ++pos; } if (c == '\0') return(pos); while(pos >= 0) { if (*str-- == c) return(pos); --pos; } return(-1); } /* Not in GEMLIB */ /* find first occurence (in str) of one of the characters in set. Return * a pointer to it or NULL on failure. */ char * strpbrk(str, set) register char *str, *set; { register char *ptr; while(*set) if ((ptr=index(str,*set++))!=NULL) return(ptr); return(NULL); } /* Not in GEMLIB */ /* same as strpbrk, but find last occurence */ char * strrpbrk(str, set) register char *str, *set; { register char *rptr; while(*set) if ((rptr=rindex(str,*set++))!=NULL) return(rptr); return(NULL); } /* Not in GEMLIB */ /* search str for the first occurence of a character not in set. Return * the position of the last character in str in the set, or strlen if * all of set are in str. */ strspn(str, set) register char *str, *set; { register char *ptr; /* set is empty so the first char of str will not be in it */ if (*set == '\0') return(0); ptr = str; while(*str) { if (index(set,*str)==NULL) return(strpos(ptr,*str)); ++str; } return(strlen(ptr)); } /* Not in GEMLIB */ /* find first occurence of char in str that is included in set. Return * its position. */ strcspn(str, set) register char *str, *set; { register char *ptr; ptr = str; while(*str) { if (index(set,*str)) return(strpos(ptr,*str)); ++str; } return(strlen(ptr)); } /* return pointer to last occurence of c in str. (AKA strrchr). */ char * rindex(str, c) register char *str; register char c; { register char *sptr; sptr = str; while(*sptr) ++sptr; if (c == '\0') return(sptr); while(str != sptr) if (*sptr-- == c) return(++sptr); return(NULL); } /* strcat with max */ char * strncat(str1,str2,len) register char *str1, *str2; register int len; { register char *sptr; if (len <= 0) return(str1); sptr = str1; while(*sptr) ++sptr; while(*str2) { *sptr++ = *str2++; if (!--len) break; } *sptr = '\0'; return(str1); } /* strcpy with MAX */ char * strncpy(dest,src,len) register char *dest, *src; register int len; { register char *sptr; if (len <= 0) return(dest); sptr = dest; while(*src) { *sptr++ = *src++; if (!--len) break; } if (len) while(len-- > 0) *sptr++ = '\0'; return(dest); } /* compare len chars of str1 to len chars of str2 */ strncmp(str1,str2,len) register char *str1, *str2; register int len; { if (len <= 0) return(0); while(*str1) { if(*str1 != *str2) return(*str1-*str2); ++str1; ++str2; if (!--len) break; } if (!len) return(0); if(*str2=='\0') return(0); else return(-1); } /* As supplied the index function does not return a pointer to * the EOS when the requested character (in d0) was a '\0'. * Harbison and Steele (p. 262) say that a pointer to the NULL * should return if the indexed character is a '\0'. Replace * the index routine in your startup file with this routine. * Index function to find out if a particular character is in a string. * .globl _index .globl _strchr _index: _strchr: move.l 4(a7),a0 * a0 -> String move.w 8(a7),d0 * D0 = desired character xindex: tst.b (a0) * EOS? bne notend * No, continue to look tst.b d0 * Are we looking for the NULL ? bne out2 * Go around move.l a0,d0 * Load D0 with end of string rts out2: clr.l d0 * Not found rts * Quit notend: cmp.b (a0)+,d0 * check for character bne xindex * move.l a0,d0 * Found it subq.l #1,d0 * set return pointer rts */