/* This C language subroutine computes the length of the maximum initial segment of the string pointed to by s1 which consists entirely of characters not from the string pointed to be s1. The Run Time Library for the C Language. Gordon A. Sterling (617) 461 - 3076 DSP Development Tools Engineering Created on 1/19/91 Updated on 5/94 by AS Updated on 3/95 by AS - separated polymorphic functions #include
size_t strcspn(const char *s1, const char *s2); */ #include "lib_glob.h" #include "str_glob.h" .SEGMENT/CODE Code_Space_Name; .FILE RTL_FILENAME; .GLOBAL _strcspn; .GLOBAL ___strcspnDD; _strcspn: ___strcspnDD: strcspn_core: R0=PASS R4, R12=dma_i; /* Check for NULL for s1 */ IF NE R0=PASS R8; /* Check for NULL for s2 */ /* Here is an explaination of what is going on. The array to be scaned (s1) is */ /* incremented in the outer loop, while the array of characters to check (s2) is*/ /* scanned in the inner loop. There was some trouble with JUMPs using LA. If */ /* the jump occured during the final iteration of either loop, the loop stack */ /* already cleared, so the LA would underflow the stacks. */ /* The loops are now based on EQ. The EQ signal occurs when the NULL of either */ /* string is reached. There are a few things that are obscure at the end of the*/ /* loop. The inner loop will execute a few extra times even after the end of s2*/ /* has been read. This is not a problem however, because all the operation are */ /* conditioned on NE. Once a match is found, or the end of s2, the loop will be*/ /* NOPs. When the inner loop exits, one of two things has occured. The first */ /* case is if the end of s2 is found, without finding a match. When this occurs*/ /* the COMP() right outside the loop will necessary be NE (because R2 == NULL */ /* and R4 != NULL). This will cause the next instruction to be executed. This */ /* will test the if string s1 has reached the NULL. If s1 is NULL, then EQ will*/ /* be set, which will cause the loop to terminate when it reached the end of the*/ /* outer loop. */ /* The other case where is inner loop will exit is when a match is found between*/ /* a character in s1 and s2. When this occurs, R2 == R4, so the COMP() outside */ /* of the loop will set EQ. This will cause the next instruction to be a NOP, */ /* and the EQ condition will still be set. This will cause the outer loop to */ /* terminate. */ /* The condition code must be set 2 cycles before the end of the loop, or the */ /* loop will continue to execute. Any change to the last four instructions of */ /* the outer loop must keep this in mind. */ dm_vs_dm: IF EQ JUMP (PC, restore_state) (DB); /* Condition code set by caller*/ R0=R0-R0, dma_i=R4; /* Point to s1 */ dm_bse=R8; /* Point to s2 with base pointer*/ R4=DM(dma_i, dm_1); /* Read s1 */ R4=PASS R4, R8=DM(dm_ptr, dm_1);/* Test for NULL s1, read s2 */ IF EQ JUMP (PC, restore_state); /* Return a zero for NULL s1 */ DO scan_dmdms1 UNTIL EQ; /* Scan through s1 */ DO scan_dmdms2 UNTIL EQ; /* Scan through s2 */ IF NE R2=PASS R8; /* Check for EOS(s2) */ scan_dmdms2: IF NE COMP(R2,R4), R8=DM(dm_ptr, dm_1);/* Does s1==s2 */ COMP(R2,R4), R4=DM(dma_i, dm_1);/* Read next character of s1 */ IF NE R4=PASS R4, dm_ptr=dm_bse;/* If EOS(s1), exit loop */ R2=PASS R2; /* Test for EOS(s2) */ NOP; /* BUG FIX */ scan_dmdms1: IF EQ R0=R0+1, R8=DM(dm_ptr, dm_1);/* Increment Count */ restore_state: FETCH_RETURN dma_i=R12; RETURN (DB); RESTORE_STACK RESTORE_FRAME .ENDSEG;