string.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672
  1. /* Copyright (C) 1995,1996 Robert de Bath <rdebath@cix.compulink.co.uk>
  2. * This file is part of the Linux-8086 C library and is distributed
  3. * under the GNU Library General Public License.
  4. */
  5. #include <string.h>
  6. #include <malloc.h>
  7. #ifdef __AS386_16__
  8. #if __FIRST_ARG_IN_AX__
  9. #define BCC_AX_ASM /* BCC Assembler that can cope with arg in AX */
  10. #else
  11. #define BCC_AX_ASM
  12. #define BCC_ASM /* Use 16 bit BCC assembler */
  13. #endif
  14. #define PARANOID /* Include extra code for cld and ES register */
  15. #endif
  16. /* This is a basic string package; it includes the most used functions
  17. strlen strcat strcpy strcmp strncat strncpy strncmp strchr strrchr strdup
  18. memcpy memccpy memchr memset memcmp memmove
  19. These functions are in seperate files.
  20. strpbrk.o strsep.o strstr.o strtok.o strcspn.o
  21. strspn.o strcasecmp.o strncasecmp.o
  22. */
  23. /********************** Function strlen ************************************/
  24. #ifdef L_strlen
  25. size_t strlen(str)
  26. const char * str;
  27. {
  28. #ifdef BCC_AX_ASM
  29. #asm
  30. #if !__FIRST_ARG_IN_AX__
  31. mov bx,sp
  32. #endif
  33. push di
  34. #ifdef PARANOID
  35. push es
  36. push ds ; Im not sure if this is needed, so just in case.
  37. pop es
  38. cld
  39. #endif ! This is almost the same as memchr, but it can
  40. ! stay as a special.
  41. #if __FIRST_ARG_IN_AX__
  42. mov di,ax
  43. #else
  44. mov di,[bx+2]
  45. #endif
  46. mov cx,#-1
  47. xor ax,ax
  48. repne
  49. scasb
  50. not cx
  51. dec cx
  52. mov ax,cx
  53. #ifdef PARANOID
  54. pop es
  55. #endif
  56. pop di
  57. #endasm
  58. #else
  59. register char * p =(char *) str;
  60. while(*p) p++;
  61. return p-str;
  62. #endif /* ifdef BCC_AX_ASM */
  63. }
  64. #endif
  65. /********************** Function strcat ************************************/
  66. #ifdef L_strcat
  67. char * strcat(d, s)
  68. char *d;
  69. const char * s;
  70. {
  71. (void) strcpy(d+strlen(d), s);
  72. return d;
  73. }
  74. #endif
  75. /********************** Function strcpy ************************************/
  76. #ifdef L_strcpy
  77. char * strcpy(d, s)
  78. char *d;
  79. const char * s;
  80. {
  81. /* This is probably the quickest on an 8086 but a CPU with a cache will
  82. * prefer to do this in one pass */
  83. return memcpy(d, s, strlen(s)+1);
  84. }
  85. #endif
  86. /********************** Function strcmp ************************************/
  87. #ifdef L_strcmp
  88. int strcmp(d, s)
  89. const char *d;
  90. const char * s;
  91. {
  92. /* There are a number of ways to do this and it really does depend on the
  93. types of strings given as to which is better, nevertheless the Glib
  94. method is quite reasonable so we'll take that */
  95. #ifdef BCC_AX_ASM
  96. #asm
  97. mov bx,sp
  98. push di
  99. push si
  100. #ifdef PARANOID
  101. push es
  102. push ds ; Im not sure if this is needed, so just in case.
  103. pop es
  104. cld
  105. #endif
  106. #if __FIRST_ARG_IN_AX__
  107. mov di,ax ; dest
  108. mov si,[bx+2] ; source
  109. #else
  110. mov di,[bx+2] ; dest
  111. mov si,[bx+4] ; source
  112. #endif
  113. sc_1:
  114. lodsb
  115. scasb
  116. jne sc_2 ; If bytes are diff skip out.
  117. testb al,al
  118. jne sc_1 ; If this byte in str1 is nul the strings are equal
  119. xor ax,ax ; so return zero
  120. jmp sc_3
  121. sc_2:
  122. sbb ax,ax ; Collect correct val (-1,1).
  123. orb al,#1
  124. sc_3:
  125. #ifdef PARANOID
  126. pop es
  127. #endif
  128. pop si
  129. pop di
  130. #endasm
  131. #else /* ifdef BCC_AX_ASM */
  132. register char *s1=(char *)d, *s2=(char *)s, c1,c2;
  133. while((c1= *s1++) == (c2= *s2++) && c1 );
  134. return c1 - c2;
  135. #endif /* ifdef BCC_AX_ASM */
  136. }
  137. #endif
  138. /********************** Function strncat ************************************/
  139. #ifdef L_strncat
  140. char * strncat(d, s, l)
  141. char *d;
  142. const char *s;
  143. size_t l;
  144. {
  145. register char *s1=d+strlen(d), *s2;
  146. s2 = memchr(s, 0, l);
  147. if( s2 )
  148. memcpy(s1, s, s2-s+1);
  149. else
  150. {
  151. memcpy(s1, s, l);
  152. s1[l] = '\0';
  153. }
  154. return d;
  155. }
  156. #endif
  157. /********************** Function strncpy ************************************/
  158. #ifdef L_strncpy
  159. char * strncpy(d, s, l) /* FIXME need the fast version of this */
  160. char *d;
  161. const char *s;
  162. size_t l;
  163. {
  164. register char *s1=d;
  165. register const char *s2=s;
  166. while(l > 0)
  167. {
  168. l--;
  169. if( (*s1++ = *s2++) == '\0')
  170. break;
  171. }
  172. /* This _is_ correct strncpy is supposed to zap */
  173. for(; l>0; l--) *s1++ = '\0';
  174. return d;
  175. }
  176. #endif
  177. /********************** Function strncmp ************************************/
  178. #ifdef L_strncmp
  179. int strncmp(d, s, l)
  180. const char *d, *s;
  181. size_t l;
  182. {
  183. #ifdef BCC_AX_ASM
  184. #asm
  185. mov bx,sp
  186. push si
  187. push di
  188. #ifdef PARANOID
  189. push es
  190. push ds ! Im not sure if this is needed, so just in case.
  191. pop es
  192. cld
  193. #endif
  194. #if __FIRST_ARG_IN_AX__
  195. mov si,ax
  196. mov di,[bx+2]
  197. mov cx,[bx+4]
  198. #else
  199. mov si,[bx+2] ! Fetch
  200. mov di,[bx+4]
  201. mov cx,[bx+6]
  202. #endif
  203. inc cx
  204. lp1:
  205. dec cx
  206. je lp2
  207. lodsb
  208. scasb
  209. jne lp3
  210. testb al,al
  211. jne lp1
  212. lp2:
  213. xor ax,ax
  214. jmp lp4
  215. lp3:
  216. sbb ax,ax
  217. or al,#1
  218. lp4:
  219. #ifdef PARANOID
  220. pop es
  221. #endif
  222. pop di
  223. pop si
  224. #endasm
  225. #else
  226. register char c1=0, c2=0;
  227. while(l-- >0)
  228. if( (c1= *d++) != (c2= *s++) || c1 == '\0' )
  229. break;
  230. return c1-c2;
  231. #endif
  232. }
  233. #endif
  234. /********************** Function strchr ************************************/
  235. #ifdef L_strchr
  236. char *
  237. strchr(s, c)
  238. char * s;
  239. int c;
  240. {
  241. #ifdef BCC_AX_ASM
  242. #asm
  243. mov bx,sp
  244. push si
  245. #if __FIRST_ARG_IN_AX__
  246. mov bx,[bx+2]
  247. mov si,ax
  248. #else
  249. mov si,[bx+2]
  250. mov bx,[bx+4]
  251. #endif
  252. xor ax,ax
  253. #ifdef PARANOID
  254. cld
  255. #endif
  256. in_loop:
  257. lodsb
  258. cmp al,bl
  259. jz got_it
  260. or al,al
  261. jnz in_loop
  262. pop si
  263. ret
  264. got_it:
  265. lea ax,[si-1]
  266. pop si
  267. #endasm
  268. #else /* ifdef BCC_AX_ASM */
  269. register char ch;
  270. for(;;)
  271. {
  272. if( (ch= *s) == c ) return s;
  273. if( ch == 0 ) return 0;
  274. s++;
  275. }
  276. #endif /* ifdef BCC_AX_ASM */
  277. }
  278. #endif
  279. /********************** Function strrchr ************************************/
  280. #ifdef L_strrchr
  281. char * strrchr(s, c)
  282. char * s;
  283. int c;
  284. {
  285. register char * prev = 0;
  286. register char * p = s;
  287. /* For null it's just like strlen */
  288. if( c == '\0' ) return p+strlen(p);
  289. /* everything else just step along the string. */
  290. while( (p=strchr(p, c)) != 0 )
  291. {
  292. prev = p; p++;
  293. }
  294. return prev;
  295. }
  296. #endif
  297. /********************** Function strdup ************************************/
  298. #ifdef L_strdup
  299. char * strdup(s)
  300. const char * s;
  301. {
  302. register size_t len;
  303. register char * p;
  304. len = strlen(s)+1;
  305. p = (char *) malloc(len);
  306. if(p) memcpy(p, s, len); /* Faster than strcpy */
  307. return p;
  308. }
  309. #endif
  310. /********************** Function memcpy ************************************/
  311. #ifdef L_memcpy
  312. void *
  313. memcpy(d, s, l)
  314. void *d;
  315. const void *s;
  316. size_t l;
  317. {
  318. #ifdef BCC_AX_ASM
  319. #asm
  320. mov bx,sp
  321. push di
  322. push si
  323. #ifdef PARANOID
  324. push es
  325. push ds ; Im not sure if this is needed, so just in case.
  326. pop es
  327. cld
  328. #endif
  329. #if __FIRST_ARG_IN_AX__
  330. mov di,ax ; dest
  331. mov si,[bx+2] ; source
  332. mov cx,[bx+4] ; count
  333. #else
  334. mov di,[bx+2] ; dest
  335. mov si,[bx+4] ; source
  336. mov cx,[bx+6] ; count
  337. mov ax,di
  338. #endif
  339. ; If di is odd mov 1 byte before doing word move
  340. ; this will speed slightly but
  341. ; NB 8086 has no problem with mis-aligned access.
  342. shr cx,#1 ; Do this faster by doing a mov word
  343. rep
  344. movsw
  345. adc cx,cx ; Retrieve the leftover 1 bit from cflag.
  346. rep
  347. movsb
  348. #ifdef PARANOID
  349. pop es
  350. #endif
  351. pop si
  352. pop di
  353. #endasm
  354. #else /* ifdef BCC_AX_ASM */
  355. register char *s1=d, *s2=(char *)s;
  356. for( ; l>0; l--) *((unsigned char*)s1++) = *((unsigned char*)s2++);
  357. return d;
  358. #endif /* ifdef BCC_AX_ASM */
  359. }
  360. #endif
  361. /********************** Function memccpy ************************************/
  362. #ifdef L_memccpy
  363. void * memccpy(d, s, c, l) /* Do we need a fast one ? */
  364. void *s, *d;
  365. int c;
  366. size_t l;
  367. {
  368. register char *s1=d, *s2=s;
  369. while(l-- > 0)
  370. if((*s1++ = *s2++) == c )
  371. return s1;
  372. return 0;
  373. }
  374. #endif
  375. /********************** Function memchr ************************************/
  376. #ifdef L_memchr
  377. void * memchr(str, c, l)
  378. const void * str;
  379. int c;
  380. size_t l;
  381. {
  382. #ifdef BCC_ASM
  383. #asm
  384. mov bx,sp
  385. push di
  386. #ifdef PARANOID
  387. push es
  388. push ds ; Im not sure if this is needed, so just in case.
  389. pop es
  390. cld
  391. #endif
  392. mov di,[bx+2]
  393. mov ax,[bx+4]
  394. mov cx,[bx+6]
  395. test cx,cx
  396. je is_z ! Zero length, do not find.
  397. repne ! Scan
  398. scasb
  399. jne is_z ! Not found, ret zero
  400. dec di ! Adjust ptr
  401. mov ax,di ! return
  402. jmp xit
  403. is_z:
  404. xor ax,ax
  405. xit:
  406. #ifdef PARANOID
  407. pop es
  408. #endif
  409. pop di
  410. #endasm
  411. #else /* ifdef BCC_ASM */
  412. register char *p=(char *)str;
  413. while(l-- > 0)
  414. {
  415. if(*p == c) return p;
  416. p++;
  417. }
  418. return 0;
  419. #endif /* ifdef BCC_ASM */
  420. }
  421. #endif
  422. /********************** Function memset ************************************/
  423. #ifdef L_memset
  424. void * memset(str, c, l)
  425. void * str;
  426. int c;
  427. size_t l;
  428. {
  429. #ifdef BCC_AX_ASM
  430. #asm
  431. mov bx,sp
  432. push di
  433. #ifdef PARANOID
  434. push es
  435. push ds ; Im not sure if this is needed, so just in case.
  436. pop es
  437. cld
  438. #endif
  439. #if __FIRST_ARG_IN_AX__
  440. mov di,ax ; Fetch
  441. mov ax,[bx+2]
  442. mov cx,[bx+4]
  443. #else
  444. mov di,[bx+2] ; Fetch
  445. mov ax,[bx+4]
  446. mov cx,[bx+6]
  447. #endif
  448. ; How much difference does this alignment make ?
  449. ; I don`t think it`s significant cause most will already be aligned.
  450. ; test cx,cx ; Zero size - skip
  451. ; je xit
  452. ;
  453. ; test di,#1 ; Line it up
  454. ; je s_1
  455. ; stosb
  456. ; dec cx
  457. ;s_1:
  458. mov ah,al ; Replicate byte
  459. shr cx,#1 ; Do this faster by doing a sto word
  460. rep ; Bzzzzz ...
  461. stosw
  462. adc cx,cx ; Retrieve the leftover 1 bit from cflag.
  463. rep ; ... z
  464. stosb
  465. xit:
  466. mov ax,[bx+2]
  467. #ifdef PARANOID
  468. pop es
  469. #endif
  470. pop di
  471. #endasm
  472. #else /* ifdef BCC_AX_ASM */
  473. register char *s1=str;
  474. while(l-->0) *s1++ = c;
  475. return str;
  476. #endif /* ifdef BCC_AX_ASM */
  477. }
  478. #endif
  479. /********************** Function memcmp ************************************/
  480. #ifdef L_memcmp
  481. int memcmp(s, d, l)
  482. const void *s, *d;
  483. size_t l;
  484. {
  485. #ifdef BCC_ASM
  486. #asm
  487. mov bx,sp
  488. push di
  489. push si
  490. #ifdef PARANOID
  491. push es
  492. push ds ! Im not sure if this is needed, so just in case.
  493. pop es
  494. cld
  495. #endif
  496. mov si,[bx+2] ! Fetch
  497. mov di,[bx+4]
  498. mov cx,[bx+6]
  499. xor ax,ax
  500. rep ! Bzzzzz
  501. cmpsb
  502. je xit ! All the same!
  503. sbb ax,ax
  504. sbb ax,#-1 ! choose +/-1
  505. xit:
  506. #ifdef PARANOID
  507. pop es
  508. #endif
  509. pop si
  510. pop di
  511. #endasm
  512. #else /* ifdef BCC_ASM */
  513. register const char *s1=d, *s2=s;
  514. register char c1=0, c2=0;
  515. while(l-- > 0)
  516. if( (c1= *s1++) != (c2= *s2++) )
  517. break;
  518. return c1-c2;
  519. #endif /* ifdef BCC_ASM */
  520. }
  521. #endif
  522. /********************** Function memmove ************************************/
  523. #ifdef L_memmove
  524. void *
  525. memmove(d, s, l)
  526. void *d, *s;
  527. size_t l;
  528. {
  529. register char *s1=d, *s2=s;
  530. /* This bit of sneakyness c/o Glibc, it assumes the test is unsigned */
  531. if( s1-s2 >= l ) return memcpy(d,s,l);
  532. /* This reverse copy only used if we absolutly have to */
  533. s1+=l; s2+=l;
  534. while(l-- >0)
  535. *(--s1) = *(--s2);
  536. return d;
  537. }
  538. #endif
  539. /********************** Function movedata ***********************************/
  540. #ifdef L_movedata
  541. /* NB There isn't any C version of this function ... */
  542. #ifdef BCC_AX_ASM
  543. void
  544. __movedata(srcseg, srcoff, destseg, destoff, len)
  545. unsigned int srcseg, srcoff, destseg, destoff, len;
  546. {
  547. #asm
  548. push bp
  549. mov bp,sp
  550. push si
  551. push di
  552. push ds
  553. #ifdef PARANOID
  554. push es
  555. cld
  556. #endif
  557. ! sei ! Are we _really_ paranoid ?
  558. #if !__FIRST_ARG_IN_AX__
  559. mov ds,[bp+4] ! Careful, [bp+xx] is SS based.
  560. mov si,[bp+6]
  561. mov es,[bp+8]
  562. mov di,[bp+10]
  563. mov cx,[bp+12]
  564. #else
  565. mov ds,ax
  566. mov si,[bp+4]
  567. mov es,[bp+6]
  568. mov di,[bp+8]
  569. mov cx,[bp+10]
  570. #endif
  571. rep
  572. movsb
  573. ! cli ! Are we _really_ paranoid ?
  574. #ifdef PARANOID
  575. pop es
  576. #endif
  577. pop ds
  578. pop di
  579. pop si
  580. pop bp
  581. #endasm
  582. }
  583. #endif
  584. #endif
  585. /********************** THE END ********************************************/