string.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674
  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. const 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 (char*)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. const char * s;
  283. int c;
  284. {
  285. register char * prev = 0;
  286. register char * p = (char*)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 *d;
  365. const void *s;
  366. int c;
  367. size_t l;
  368. {
  369. register char *s1=d, *s2=(char*)s;
  370. while(l-- > 0)
  371. if((*s1++ = *s2++) == c )
  372. return s1;
  373. return 0;
  374. }
  375. #endif
  376. /********************** Function memchr ************************************/
  377. #ifdef L_memchr
  378. void * memchr(str, c, l)
  379. const void * str;
  380. int c;
  381. size_t l;
  382. {
  383. #ifdef BCC_ASM
  384. #asm
  385. mov bx,sp
  386. push di
  387. #ifdef PARANOID
  388. push es
  389. push ds ; Im not sure if this is needed, so just in case.
  390. pop es
  391. cld
  392. #endif
  393. mov di,[bx+2]
  394. mov ax,[bx+4]
  395. mov cx,[bx+6]
  396. test cx,cx
  397. je is_z ! Zero length, do not find.
  398. repne ! Scan
  399. scasb
  400. jne is_z ! Not found, ret zero
  401. dec di ! Adjust ptr
  402. mov ax,di ! return
  403. jmp xit
  404. is_z:
  405. xor ax,ax
  406. xit:
  407. #ifdef PARANOID
  408. pop es
  409. #endif
  410. pop di
  411. #endasm
  412. #else /* ifdef BCC_ASM */
  413. register char *p=(char *)str;
  414. while(l-- > 0)
  415. {
  416. if(*p == c) return p;
  417. p++;
  418. }
  419. return 0;
  420. #endif /* ifdef BCC_ASM */
  421. }
  422. #endif
  423. /********************** Function memset ************************************/
  424. #ifdef L_memset
  425. void * memset(str, c, l)
  426. void * str;
  427. int c;
  428. size_t l;
  429. {
  430. #ifdef BCC_AX_ASM
  431. #asm
  432. mov bx,sp
  433. push di
  434. #ifdef PARANOID
  435. push es
  436. push ds ; Im not sure if this is needed, so just in case.
  437. pop es
  438. cld
  439. #endif
  440. #if __FIRST_ARG_IN_AX__
  441. mov di,ax ; Fetch
  442. mov ax,[bx+2]
  443. mov cx,[bx+4]
  444. #else
  445. mov di,[bx+2] ; Fetch
  446. mov ax,[bx+4]
  447. mov cx,[bx+6]
  448. #endif
  449. ; How much difference does this alignment make ?
  450. ; I don`t think it`s significant cause most will already be aligned.
  451. ; test cx,cx ; Zero size - skip
  452. ; je xit
  453. ;
  454. ; test di,#1 ; Line it up
  455. ; je s_1
  456. ; stosb
  457. ; dec cx
  458. ;s_1:
  459. mov ah,al ; Replicate byte
  460. shr cx,#1 ; Do this faster by doing a sto word
  461. rep ; Bzzzzz ...
  462. stosw
  463. adc cx,cx ; Retrieve the leftover 1 bit from cflag.
  464. rep ; ... z
  465. stosb
  466. xit:
  467. mov ax,[bx+2]
  468. #ifdef PARANOID
  469. pop es
  470. #endif
  471. pop di
  472. #endasm
  473. #else /* ifdef BCC_AX_ASM */
  474. register char *s1=str;
  475. while(l-->0) *s1++ = c;
  476. return str;
  477. #endif /* ifdef BCC_AX_ASM */
  478. }
  479. #endif
  480. /********************** Function memcmp ************************************/
  481. #ifdef L_memcmp
  482. int memcmp(s, d, l)
  483. const void *s, *d;
  484. size_t l;
  485. {
  486. #ifdef BCC_ASM
  487. #asm
  488. mov bx,sp
  489. push di
  490. push si
  491. #ifdef PARANOID
  492. push es
  493. push ds ! Im not sure if this is needed, so just in case.
  494. pop es
  495. cld
  496. #endif
  497. mov si,[bx+2] ! Fetch
  498. mov di,[bx+4]
  499. mov cx,[bx+6]
  500. xor ax,ax
  501. rep ! Bzzzzz
  502. cmpsb
  503. je xit ! All the same!
  504. sbb ax,ax
  505. sbb ax,#-1 ! choose +/-1
  506. xit:
  507. #ifdef PARANOID
  508. pop es
  509. #endif
  510. pop si
  511. pop di
  512. #endasm
  513. #else /* ifdef BCC_ASM */
  514. register const char *s1=d, *s2=s;
  515. register char c1=0, c2=0;
  516. while(l-- > 0)
  517. if( (c1= *s1++) != (c2= *s2++) )
  518. break;
  519. return c1-c2;
  520. #endif /* ifdef BCC_ASM */
  521. }
  522. #endif
  523. /********************** Function memmove ************************************/
  524. #ifdef L_memmove
  525. void *
  526. memmove(d, s, l)
  527. void *d;
  528. const void *s;
  529. size_t l;
  530. {
  531. register char *s1=d, *s2=(char*)s;
  532. /* This bit of sneakyness c/o Glibc, it assumes the test is unsigned */
  533. if( s1-s2 >= l ) return memcpy(d,s,l);
  534. /* This reverse copy only used if we absolutly have to */
  535. s1+=l; s2+=l;
  536. while(l-- >0)
  537. *(--s1) = *(--s2);
  538. return d;
  539. }
  540. #endif
  541. /********************** Function movedata ***********************************/
  542. #ifdef L_movedata
  543. /* NB There isn't any C version of this function ... */
  544. #ifdef BCC_AX_ASM
  545. void
  546. __movedata(srcseg, srcoff, destseg, destoff, len)
  547. unsigned int srcseg, srcoff, destseg, destoff, len;
  548. {
  549. #asm
  550. push bp
  551. mov bp,sp
  552. push si
  553. push di
  554. push ds
  555. #ifdef PARANOID
  556. push es
  557. cld
  558. #endif
  559. ! sei ! Are we _really_ paranoid ?
  560. #if !__FIRST_ARG_IN_AX__
  561. mov ds,[bp+4] ! Careful, [bp+xx] is SS based.
  562. mov si,[bp+6]
  563. mov es,[bp+8]
  564. mov di,[bp+10]
  565. mov cx,[bp+12]
  566. #else
  567. mov ds,ax
  568. mov si,[bp+4]
  569. mov es,[bp+6]
  570. mov di,[bp+8]
  571. mov cx,[bp+10]
  572. #endif
  573. rep
  574. movsb
  575. ! cli ! Are we _really_ paranoid ?
  576. #ifdef PARANOID
  577. pop es
  578. #endif
  579. pop ds
  580. pop di
  581. pop si
  582. pop bp
  583. #endasm
  584. }
  585. #endif
  586. #endif
  587. /********************** THE END ********************************************/