strings.pp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592
  1. {
  2. $Id$
  3. This file is part of the Free Pascal run time library.
  4. Copyright (c) 1993,97 by the Free Pascal development team.
  5. Strings unit for PChar (asciiz/C compatible strings) handling
  6. See the file COPYING.FPC, included in this distribution,
  7. for details about the copyright.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  11. **********************************************************************}
  12. unit strings;
  13. interface
  14. { Returns the length of a string }
  15. function strlen(p : pchar) : longint;
  16. { Converts a Pascal string to a null-terminated string }
  17. function strpcopy(d : pchar;const s : string) : pchar;
  18. { Converts a null-terminated string to a Pascal string }
  19. function strpas(p : pchar) : string;
  20. { Copies source to dest, returns a pointer to dest }
  21. function strcopy(dest,source : pchar) : pchar;
  22. { Copies at most maxlen bytes from source to dest. }
  23. { Returns a pointer to dest }
  24. function strlcopy(dest,source : pchar;maxlen : longint) : pchar;
  25. { Copies source to dest and returns a pointer to the terminating }
  26. { null character. }
  27. function strecopy(dest,source : pchar) : pchar;
  28. { Returns a pointer tro the terminating null character of p }
  29. function strend(p : pchar) : pchar;
  30. { Appends source to dest, returns a pointer do dest}
  31. function strcat(dest,source : pchar) : pchar;
  32. { Compares str1 und str2, returns }
  33. { a value <0 if str1<str2; }
  34. { 0 when str1=str2 }
  35. { and a value >0 if str1>str2 }
  36. function strcomp(str1,str2 : pchar) : longint;
  37. { The same as strcomp, but at most l characters are compared }
  38. function strlcomp(str1,str2 : pchar;l : longint) : longint;
  39. { The same as strcomp but case insensitive }
  40. function stricomp(str1,str2 : pchar) : longint;
  41. { Copies l characters from source to dest, returns dest. }
  42. function strmove(dest,source : pchar;l : longint) : pchar;
  43. { Appends at most l characters from source to dest }
  44. function strlcat(dest,source : pchar;l : longint) : pchar;
  45. { Returns a pointer to the first occurrence of c in p }
  46. { If c doesn't occur, nil is returned }
  47. function strscan(p : pchar;c : char) : pchar;
  48. { Returns a pointer to the last occurrence of c in p }
  49. { If c doesn't occur, nil is returned }
  50. function strrscan(p : pchar;c : char) : pchar;
  51. { converts p to all-lowercase, returns p }
  52. function strlower(p : pchar) : pchar;
  53. { converts p to all-uppercase, returns p }
  54. function strupper(p : pchar) : pchar;
  55. { The same al stricomp, but at most l characters are compared }
  56. function strlicomp(str1,str2 : pchar;l : longint) : longint;
  57. { Returns a pointer to the first occurrence of str2 in }
  58. { str2 Otherwise returns nil }
  59. function strpos(str1,str2 : pchar) : pchar;
  60. { Makes a copy of p on the heap, and returns a pointer to this copy }
  61. function strnew(p : pchar) : pchar;
  62. { Allocates L bytes on the heap, returns a pchar pointer to it }
  63. function stralloc(L : longint) : pchar;
  64. { Releases a null-terminated string from the heap }
  65. procedure strdispose(p : pchar);
  66. implementation
  67. function strcopy(dest,source : pchar) : pchar;
  68. begin
  69. asm
  70. cld
  71. movl 12(%ebp),%edi
  72. movl $0xffffffff,%ecx
  73. xorb %al,%al
  74. repne
  75. scasb
  76. not %ecx
  77. movl 8(%ebp),%edi
  78. movl 12(%ebp),%esi
  79. movl %ecx,%eax
  80. shrl $2,%ecx
  81. rep
  82. movsl
  83. movl %eax,%ecx
  84. andl $3,%ecx
  85. rep
  86. movsb
  87. movl 8(%ebp),%eax
  88. leave
  89. ret $8
  90. end;
  91. end;
  92. function strecopy(dest,source : pchar) : pchar;
  93. begin
  94. asm
  95. cld
  96. movl 12(%ebp),%edi
  97. movl $0xffffffff,%ecx
  98. xorl %eax,%eax
  99. repne
  100. scasb
  101. not %ecx
  102. movl 8(%ebp),%edi
  103. movl 12(%ebp),%esi
  104. movl %ecx,%eax
  105. shrl $2,%ecx
  106. rep
  107. movsl
  108. movl %eax,%ecx
  109. andl $3,%ecx
  110. rep
  111. movsb
  112. movl 8(%ebp),%eax
  113. decl %edi
  114. movl %edi,%eax
  115. leave
  116. ret $8
  117. end ['EAX','ESI','EDI'];
  118. end;
  119. function strlcopy(dest,source : pchar;maxlen : longint) : pchar;
  120. begin
  121. asm
  122. movl 8(%ebp),%edi
  123. movl 12(%ebp),%esi
  124. movl 16(%ebp),%ecx
  125. cld
  126. .LSTRLCOPY1:
  127. lodsb
  128. stosb
  129. decl %ecx // Lower maximum
  130. jz .LSTRLCOPY2 // 0 reached ends
  131. orb %al,%al
  132. jnz .LSTRLCOPY1
  133. movl 8(%ebp),%eax
  134. leave
  135. ret $12
  136. .LSTRLCOPY2:
  137. xorb %al,%al // If cutted
  138. stosb // add a #0
  139. movl 8(%ebp),%eax
  140. leave
  141. ret $12
  142. end ['EAX','ECX','ESI','EDI'];
  143. end;
  144. function strlen(p : pchar) : longint;
  145. begin
  146. asm
  147. cld
  148. movl 8(%ebp),%edi
  149. movl $0xffffffff,%ecx
  150. xorl %eax,%eax
  151. repne
  152. scasb
  153. movl $0xfffffffe,%eax
  154. subl %ecx,%eax
  155. leave
  156. ret $4
  157. end ['EDI','ECX','EAX'];
  158. end;
  159. function strend(p : pchar) : pchar;
  160. begin
  161. asm
  162. cld
  163. movl 8(%ebp),%edi
  164. movl $0xffffffff,%ecx
  165. xorl %eax,%eax
  166. repne
  167. scasb
  168. movl %edi,%eax
  169. decl %eax
  170. leave
  171. ret $4
  172. end ['EDI','ECX','EAX'];
  173. end;
  174. function strpcopy(d : pchar;const s : string) : pchar;
  175. begin
  176. asm
  177. pushl %esi // Save ESI
  178. cld
  179. movl 8(%ebp),%edi // load destination address
  180. movl 12(%ebp),%esi // Load Source adress
  181. movl %edi,%ebx // Set return value
  182. lodsb // load length in ECX
  183. movzbl %al,%ecx
  184. rep
  185. movsb
  186. xorb %al,%al // Set #0
  187. stosb
  188. movl %ebx,%eax // return value to EAX
  189. popl %esi
  190. leave // ... and ready
  191. ret $8
  192. end ['EDI','ESI','EBX','EAX','ECX'];
  193. end;
  194. function strpas(p : pchar) : string;
  195. begin
  196. asm
  197. cld
  198. movl 12(%ebp),%edi
  199. movl $0xff,%ecx
  200. xorl %eax,%eax
  201. movl %edi,%esi
  202. repne
  203. scasb
  204. movl %ecx,%eax
  205. movl 8(%ebp),%edi
  206. notb %al
  207. decl %eax
  208. stosb
  209. cmpl $7,%eax
  210. jl .LStrPas2
  211. movl %edi,%ecx // Align on 32bits
  212. negl %ecx
  213. andl $3,%ecx
  214. subl %ecx,%eax
  215. rep
  216. movsb
  217. movl %eax,%ecx
  218. andl $3,%eax
  219. shrl $2,%ecx
  220. rep
  221. movsl
  222. .LStrPas2:
  223. movl %eax,%ecx
  224. rep
  225. movsb
  226. end ['ECX','EAX','ESI','EDI'];
  227. end;
  228. function strcat(dest,source : pchar) : pchar;
  229. begin
  230. strcat:=strcopy(strend(dest),source);
  231. end;
  232. function strlcat(dest,source : pchar;l : longint) : pchar;
  233. var
  234. destend : pchar;
  235. begin
  236. destend:=strend(dest);
  237. l:=l-(destend-dest);
  238. strlcat:=strlcopy(destend,source,l);
  239. end;
  240. function strcomp(str1,str2 : pchar) : longint;
  241. begin
  242. asm
  243. // Find terminating zero
  244. movl 12(%ebp),%edi
  245. movl $0xffffffff,%ecx
  246. cld
  247. xorl %eax,%eax
  248. repne
  249. scasb
  250. not %ecx
  251. movl 12(%ebp),%edi
  252. movl 8(%ebp),%esi
  253. repe
  254. cmpsb
  255. movb -1(%esi),%al
  256. movzbl -1(%edi),%ecx
  257. subl %ecx,%eax
  258. leave
  259. ret $8
  260. end ['EAX','ECX','ESI','EDI'];
  261. end;
  262. function strlcomp(str1,str2 : pchar;l : longint) : longint;
  263. begin
  264. asm
  265. // Find terminating zero
  266. movl 12(%ebp),%edi
  267. movl $0xffffffff,%ecx
  268. cld
  269. xorl %eax,%eax
  270. repne
  271. scasb
  272. not %ecx
  273. cmpl 16(%ebp),%ecx
  274. jl .LSTRLCOMP1
  275. movl 16(%ebp),%ecx
  276. .LSTRLCOMP1:
  277. movl 12(%ebp),%edi
  278. movl 8(%ebp),%esi
  279. repe
  280. cmpsb
  281. movb -1(%esi),%al
  282. movzbl -1(%edi),%ecx
  283. subl %ecx,%eax
  284. leave
  285. ret $12
  286. end ['EAX','ECX','ESI','EDI'];
  287. end;
  288. function stricomp(str1,str2 : pchar) : longint;
  289. begin
  290. asm
  291. // Find terminating zero
  292. movl 12(%ebp),%edi
  293. movl $0xffffffff,%ecx
  294. cld
  295. xorl %eax,%eax
  296. repne
  297. scasb
  298. not %ecx
  299. movl 12(%ebp),%edi
  300. movl 8(%ebp),%esi
  301. .LSTRICOMP2:
  302. repe
  303. cmpsb
  304. jz .LSTRICOMP3 // If last reached then exit
  305. movb (%esi),%al
  306. movzbl (%edi),%ebx
  307. cmpb $97,%al
  308. jb .LSTRICOMP1
  309. cmpb $122,%al
  310. ja .LSTRICOMP1
  311. subb $0x20,%al
  312. .LSTRICOMP1:
  313. cmpb $97,%bl
  314. jb .LSTRICOMP4
  315. cmpb $122,%bl
  316. ja .LSTRICOMP4
  317. subb $0x20,%bl
  318. .LSTRICOMP4:
  319. subl %ebx,%eax
  320. jz .LSTRICOMP2 // If still equal, compare again
  321. .LSTRICOMP3:
  322. leave
  323. ret $8
  324. end ['EAX','ECX','ESI','EDI'];
  325. end;
  326. function strlicomp(str1,str2 : pchar;l : longint) : longint;
  327. begin
  328. asm
  329. // Search terminating zero
  330. movl 12(%ebp),%edi
  331. movl $0xffffffff,%ecx
  332. cld
  333. xorl %eax,%eax
  334. repne
  335. scasb
  336. not %ecx
  337. cmpl 16(%ebp),%ecx
  338. jl .LSTRLICOMP5
  339. movl 16(%ebp),%ecx
  340. .LSTRLICOMP5:
  341. movl 12(%ebp),%edi
  342. movl 8(%ebp),%esi
  343. .LSTRLICOMP2:
  344. repe
  345. cmpsb
  346. jz .LSTRLICOMP3 // If last reached, exit
  347. movb (%esi),%al
  348. movzbl (%edi),%ebx
  349. cmpb $97,%al
  350. jb .LSTRLICOMP1
  351. cmpb $122,%al
  352. ja .LSTRLICOMP1
  353. subb $0x20,%al
  354. .LSTRLICOMP1:
  355. cmpb $97,%bl
  356. jb .LSTRLICOMP4
  357. cmpb $122,%bl
  358. ja .LSTRLICOMP4
  359. subb $0x20,%bl
  360. .LSTRLICOMP4:
  361. subl %ebx,%eax
  362. jz .LSTRLICOMP2
  363. .LSTRLICOMP3:
  364. leave
  365. ret $12
  366. end ['EAX','ECX','ESI','EDI'];
  367. end;
  368. function strmove(dest,source : pchar;l : longint) : pchar;
  369. begin
  370. move(source^,dest^,l);
  371. strmove:=dest;
  372. end;
  373. function strscan(p : pchar;c : char) : pchar;
  374. begin
  375. asm
  376. movl 8(%ebp),%edi
  377. movl $0xffffffff,%ecx
  378. cld
  379. xorb %al,%al
  380. repne
  381. scasb
  382. not %ecx
  383. movb 12(%ebp),%al
  384. movl 8(%ebp),%edi
  385. repne
  386. scasb
  387. movl $0,%eax
  388. jnz .LSTRSCAN
  389. movl %edi,%eax
  390. decl %eax
  391. .LSTRSCAN:
  392. leave
  393. ret $6
  394. end;
  395. end;
  396. function strrscan(p : pchar;c : char) : pchar;
  397. begin
  398. asm
  399. movl 8(%ebp),%edi
  400. movl $0xffffffff,%ecx
  401. cld
  402. xorb %al,%al
  403. repne
  404. scasb
  405. not %ecx
  406. movb 12(%ebp),%al
  407. movl 8(%ebp),%edi
  408. addl %ecx,%edi
  409. decl %edi
  410. std
  411. repne
  412. scasb
  413. movl $0,%eax
  414. jnz .LSTRRSCAN
  415. movl %edi,%eax
  416. incl %eax
  417. .LSTRRSCAN:
  418. leave
  419. ret $6
  420. end;
  421. end;
  422. function strupper(p : pchar) : pchar;
  423. begin
  424. asm
  425. movl 8(%ebp),%esi
  426. movl %esi,%edi
  427. .LSTRUPPER1:
  428. lodsb
  429. cmpb $97,%al
  430. jb .LSTRUPPER3
  431. cmpb $122,%al
  432. ja .LSTRUPPER3
  433. subb $0x20,%al
  434. .LSTRUPPER3:
  435. stosb
  436. orb %al,%al
  437. jnz .LSTRUPPER1
  438. movl 8(%ebp),%eax
  439. leave
  440. ret $4
  441. end;
  442. end;
  443. function strlower(p : pchar) : pchar;
  444. begin
  445. asm
  446. movl 8(%ebp),%esi
  447. movl %esi,%edi
  448. .LSTRLOWER1:
  449. lodsb
  450. cmpb $65,%al
  451. jb .LSTRLOWER3
  452. cmpb $90,%al
  453. ja .LSTRLOWER3
  454. addb $0x20,%al
  455. .LSTRLOWER3:
  456. stosb
  457. orb %al,%al
  458. jnz .LSTRLOWER1
  459. movl 8(%ebp),%eax
  460. leave
  461. ret $4
  462. end;
  463. end;
  464. function strpos(str1,str2 : pchar) : pchar;
  465. var
  466. p : pchar;
  467. lstr2 : longint;
  468. begin
  469. strpos:=nil;
  470. p:=strscan(str1,str2^);
  471. if p=nil then
  472. exit;
  473. lstr2:=strlen(str2);
  474. while p<>nil do
  475. begin
  476. if strlcomp(p,str2,lstr2)=0 then
  477. begin
  478. strpos:=p;
  479. exit;
  480. end;
  481. inc(longint(p));
  482. p:=strscan(p,str2^);
  483. end;
  484. end;
  485. procedure strdispose(p : pchar);
  486. begin
  487. if p<>nil then
  488. freemem(p,strlen(p)+1);
  489. end;
  490. function strnew(p : pchar) : pchar;
  491. var
  492. len : longint;
  493. begin
  494. strnew:=nil;
  495. if (p=nil) or (p^=#0) then
  496. exit;
  497. len:=strlen(p)+1;
  498. getmem(strnew,len);
  499. if strnew<>nil then
  500. strmove(strnew,p,len);
  501. end;
  502. function stralloc(L : longint) : pchar;
  503. begin
  504. StrAlloc:=Nil;
  505. GetMem (Stralloc,l);
  506. end;
  507. end.
  508. {
  509. $Log$
  510. Revision 1.2 1998-05-23 01:14:06 peter
  511. + I386_ATT switch
  512. }