strings.pp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602
  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. {$ASMMODE ATT}
  68. function strcopy(dest,source : pchar) : pchar;
  69. begin
  70. asm
  71. cld
  72. movl 12(%ebp),%edi
  73. movl $0xffffffff,%ecx
  74. xorb %al,%al
  75. repne
  76. scasb
  77. not %ecx
  78. movl 8(%ebp),%edi
  79. movl 12(%ebp),%esi
  80. movl %ecx,%eax
  81. shrl $2,%ecx
  82. rep
  83. movsl
  84. movl %eax,%ecx
  85. andl $3,%ecx
  86. rep
  87. movsb
  88. movl 8(%ebp),%eax
  89. leave
  90. ret $8
  91. end;
  92. end;
  93. function strecopy(dest,source : pchar) : pchar;
  94. begin
  95. asm
  96. cld
  97. movl 12(%ebp),%edi
  98. movl $0xffffffff,%ecx
  99. xorl %eax,%eax
  100. repne
  101. scasb
  102. not %ecx
  103. movl 8(%ebp),%edi
  104. movl 12(%ebp),%esi
  105. movl %ecx,%eax
  106. shrl $2,%ecx
  107. rep
  108. movsl
  109. movl %eax,%ecx
  110. andl $3,%ecx
  111. rep
  112. movsb
  113. movl 8(%ebp),%eax
  114. decl %edi
  115. movl %edi,%eax
  116. leave
  117. ret $8
  118. end ['EAX','ESI','EDI'];
  119. end;
  120. function strlcopy(dest,source : pchar;maxlen : longint) : pchar;
  121. begin
  122. asm
  123. movl 8(%ebp),%edi
  124. movl 12(%ebp),%esi
  125. movl 16(%ebp),%ecx
  126. cld
  127. .LSTRLCOPY1:
  128. lodsb
  129. stosb
  130. decl %ecx // Lower maximum
  131. jz .LSTRLCOPY2 // 0 reached ends
  132. orb %al,%al
  133. jnz .LSTRLCOPY1
  134. movl 8(%ebp),%eax
  135. leave
  136. ret $12
  137. .LSTRLCOPY2:
  138. xorb %al,%al // If cutted
  139. stosb // add a #0
  140. movl 8(%ebp),%eax
  141. leave
  142. ret $12
  143. end ['EAX','ECX','ESI','EDI'];
  144. end;
  145. function strlen(p : pchar) : longint;
  146. begin
  147. asm
  148. cld
  149. movl 8(%ebp),%edi
  150. movl $0xffffffff,%ecx
  151. xorl %eax,%eax
  152. repne
  153. scasb
  154. movl $0xfffffffe,%eax
  155. subl %ecx,%eax
  156. leave
  157. ret $4
  158. end ['EDI','ECX','EAX'];
  159. end;
  160. function strend(p : pchar) : pchar;
  161. begin
  162. asm
  163. cld
  164. movl 8(%ebp),%edi
  165. movl $0xffffffff,%ecx
  166. xorl %eax,%eax
  167. repne
  168. scasb
  169. movl %edi,%eax
  170. decl %eax
  171. leave
  172. ret $4
  173. end ['EDI','ECX','EAX'];
  174. end;
  175. function strpcopy(d : pchar;const s : string) : pchar;
  176. begin
  177. asm
  178. pushl %esi // Save ESI
  179. cld
  180. movl 8(%ebp),%edi // load destination address
  181. movl 12(%ebp),%esi // Load Source adress
  182. movl %edi,%ebx // Set return value
  183. lodsb // load length in ECX
  184. movzbl %al,%ecx
  185. rep
  186. movsb
  187. xorb %al,%al // Set #0
  188. stosb
  189. movl %ebx,%eax // return value to EAX
  190. popl %esi
  191. leave // ... and ready
  192. ret $8
  193. end ['EDI','ESI','EBX','EAX','ECX'];
  194. end;
  195. {$ASMMODE DIRECT}
  196. function strpas(p : pchar) : string;
  197. begin
  198. asm
  199. cld
  200. movl 12(%ebp),%edi
  201. movl $0xff,%ecx
  202. xorl %eax,%eax
  203. movl %edi,%esi
  204. repne
  205. scasb
  206. movl %ecx,%eax
  207. movl 8(%ebp),%edi
  208. notb %al
  209. decl %eax
  210. stosb
  211. cmpl $7,%eax
  212. jl .LStrPas2
  213. movl %edi,%ecx // Align on 32bits
  214. negl %ecx
  215. andl $3,%ecx
  216. subl %ecx,%eax
  217. rep
  218. movsb
  219. movl %eax,%ecx
  220. andl $3,%eax
  221. shrl $2,%ecx
  222. rep
  223. movsl
  224. .LStrPas2:
  225. movl %eax,%ecx
  226. rep
  227. movsb
  228. end ['ECX','EAX','ESI','EDI'];
  229. end;
  230. {$ASMMODE ATT}
  231. function strcat(dest,source : pchar) : pchar;
  232. begin
  233. strcat:=strcopy(strend(dest),source);
  234. end;
  235. function strlcat(dest,source : pchar;l : longint) : pchar;
  236. var
  237. destend : pchar;
  238. begin
  239. destend:=strend(dest);
  240. l:=l-(destend-dest);
  241. strlcat:=strlcopy(destend,source,l);
  242. end;
  243. function strcomp(str1,str2 : pchar) : longint;
  244. begin
  245. asm
  246. // Find terminating zero
  247. movl 12(%ebp),%edi
  248. movl $0xffffffff,%ecx
  249. cld
  250. xorl %eax,%eax
  251. repne
  252. scasb
  253. not %ecx
  254. movl 12(%ebp),%edi
  255. movl 8(%ebp),%esi
  256. repe
  257. cmpsb
  258. movb -1(%esi),%al
  259. movzbl -1(%edi),%ecx
  260. subl %ecx,%eax
  261. leave
  262. ret $8
  263. end ['EAX','ECX','ESI','EDI'];
  264. end;
  265. function strlcomp(str1,str2 : pchar;l : longint) : longint;
  266. begin
  267. asm
  268. // Find terminating zero
  269. movl 12(%ebp),%edi
  270. movl $0xffffffff,%ecx
  271. cld
  272. xorl %eax,%eax
  273. repne
  274. scasb
  275. not %ecx
  276. cmpl 16(%ebp),%ecx
  277. jl .LSTRLCOMP1
  278. movl 16(%ebp),%ecx
  279. .LSTRLCOMP1:
  280. movl 12(%ebp),%edi
  281. movl 8(%ebp),%esi
  282. repe
  283. cmpsb
  284. movb -1(%esi),%al
  285. movzbl -1(%edi),%ecx
  286. subl %ecx,%eax
  287. leave
  288. ret $12
  289. end ['EAX','ECX','ESI','EDI'];
  290. end;
  291. function stricomp(str1,str2 : pchar) : longint;
  292. begin
  293. asm
  294. // Find terminating zero
  295. movl 12(%ebp),%edi
  296. movl $0xffffffff,%ecx
  297. cld
  298. xorl %eax,%eax
  299. repne
  300. scasb
  301. not %ecx
  302. movl 12(%ebp),%edi
  303. movl 8(%ebp),%esi
  304. .LSTRICOMP2:
  305. repe
  306. cmpsb
  307. jz .LSTRICOMP3 // If last reached then exit
  308. movb (%esi),%al
  309. movzbl (%edi),%ebx
  310. cmpb $97,%al
  311. jb .LSTRICOMP1
  312. cmpb $122,%al
  313. ja .LSTRICOMP1
  314. subb $0x20,%al
  315. .LSTRICOMP1:
  316. cmpb $97,%bl
  317. jb .LSTRICOMP4
  318. cmpb $122,%bl
  319. ja .LSTRICOMP4
  320. subb $0x20,%bl
  321. .LSTRICOMP4:
  322. subl %ebx,%eax
  323. jz .LSTRICOMP2 // If still equal, compare again
  324. .LSTRICOMP3:
  325. leave
  326. ret $8
  327. end ['EAX','ECX','ESI','EDI'];
  328. end;
  329. function strlicomp(str1,str2 : pchar;l : longint) : longint;
  330. begin
  331. asm
  332. // Search terminating zero
  333. movl 12(%ebp),%edi
  334. movl $0xffffffff,%ecx
  335. cld
  336. xorl %eax,%eax
  337. repne
  338. scasb
  339. not %ecx
  340. cmpl 16(%ebp),%ecx
  341. jl .LSTRLICOMP5
  342. movl 16(%ebp),%ecx
  343. .LSTRLICOMP5:
  344. movl 12(%ebp),%edi
  345. movl 8(%ebp),%esi
  346. .LSTRLICOMP2:
  347. repe
  348. cmpsb
  349. jz .LSTRLICOMP3 // If last reached, exit
  350. movb (%esi),%al
  351. movzbl (%edi),%ebx
  352. cmpb $97,%al
  353. jb .LSTRLICOMP1
  354. cmpb $122,%al
  355. ja .LSTRLICOMP1
  356. subb $0x20,%al
  357. .LSTRLICOMP1:
  358. cmpb $97,%bl
  359. jb .LSTRLICOMP4
  360. cmpb $122,%bl
  361. ja .LSTRLICOMP4
  362. subb $0x20,%bl
  363. .LSTRLICOMP4:
  364. subl %ebx,%eax
  365. jz .LSTRLICOMP2
  366. .LSTRLICOMP3:
  367. leave
  368. ret $12
  369. end ['EAX','ECX','ESI','EDI'];
  370. end;
  371. function strmove(dest,source : pchar;l : longint) : pchar;
  372. begin
  373. move(source^,dest^,l);
  374. strmove:=dest;
  375. end;
  376. function strscan(p : pchar;c : char) : pchar;
  377. begin
  378. asm
  379. movl 8(%ebp),%edi
  380. movl $0xffffffff,%ecx
  381. cld
  382. xorb %al,%al
  383. repne
  384. scasb
  385. not %ecx
  386. movb 12(%ebp),%al
  387. movl 8(%ebp),%edi
  388. repne
  389. scasb
  390. movl $0,%eax
  391. jnz .LSTRSCAN
  392. movl %edi,%eax
  393. decl %eax
  394. .LSTRSCAN:
  395. leave
  396. ret $6
  397. end;
  398. end;
  399. function strrscan(p : pchar;c : char) : pchar;
  400. begin
  401. asm
  402. movl 8(%ebp),%edi
  403. movl $0xffffffff,%ecx
  404. cld
  405. xorb %al,%al
  406. repne
  407. scasb
  408. not %ecx
  409. movb 12(%ebp),%al
  410. movl 8(%ebp),%edi
  411. addl %ecx,%edi
  412. decl %edi
  413. std
  414. repne
  415. scasb
  416. movl $0,%eax
  417. jnz .LSTRRSCAN
  418. movl %edi,%eax
  419. incl %eax
  420. .LSTRRSCAN:
  421. leave
  422. ret $6
  423. end;
  424. end;
  425. function strupper(p : pchar) : pchar;
  426. begin
  427. asm
  428. movl 8(%ebp),%esi
  429. movl %esi,%edi
  430. .LSTRUPPER1:
  431. lodsb
  432. cmpb $97,%al
  433. jb .LSTRUPPER3
  434. cmpb $122,%al
  435. ja .LSTRUPPER3
  436. subb $0x20,%al
  437. .LSTRUPPER3:
  438. stosb
  439. orb %al,%al
  440. jnz .LSTRUPPER1
  441. movl 8(%ebp),%eax
  442. leave
  443. ret $4
  444. end;
  445. end;
  446. function strlower(p : pchar) : pchar;
  447. begin
  448. asm
  449. movl 8(%ebp),%esi
  450. movl %esi,%edi
  451. .LSTRLOWER1:
  452. lodsb
  453. cmpb $65,%al
  454. jb .LSTRLOWER3
  455. cmpb $90,%al
  456. ja .LSTRLOWER3
  457. addb $0x20,%al
  458. .LSTRLOWER3:
  459. stosb
  460. orb %al,%al
  461. jnz .LSTRLOWER1
  462. movl 8(%ebp),%eax
  463. leave
  464. ret $4
  465. end;
  466. end;
  467. function strpos(str1,str2 : pchar) : pchar;
  468. var
  469. p : pchar;
  470. lstr2 : longint;
  471. begin
  472. strpos:=nil;
  473. p:=strscan(str1,str2^);
  474. if p=nil then
  475. exit;
  476. lstr2:=strlen(str2);
  477. while p<>nil do
  478. begin
  479. if strlcomp(p,str2,lstr2)=0 then
  480. begin
  481. strpos:=p;
  482. exit;
  483. end;
  484. inc(longint(p));
  485. p:=strscan(p,str2^);
  486. end;
  487. end;
  488. procedure strdispose(p : pchar);
  489. begin
  490. if p<>nil then
  491. freemem(p,strlen(p)+1);
  492. end;
  493. function strnew(p : pchar) : pchar;
  494. var
  495. len : longint;
  496. begin
  497. strnew:=nil;
  498. if (p=nil) or (p^=#0) then
  499. exit;
  500. len:=strlen(p)+1;
  501. getmem(strnew,len);
  502. if strnew<>nil then
  503. strmove(strnew,p,len);
  504. end;
  505. function stralloc(L : longint) : pchar;
  506. begin
  507. StrAlloc:=Nil;
  508. GetMem (Stralloc,l);
  509. end;
  510. end.
  511. {
  512. $Log$
  513. Revision 1.4 1998-05-31 14:15:52 peter
  514. * force to use ATT or direct parsing
  515. Revision 1.3 1998/05/30 14:30:22 peter
  516. * force att reading
  517. Revision 1.2 1998/05/23 01:14:06 peter
  518. + I386_ATT switch
  519. }