home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #27 / NN_1992_27.iso / spool / alt / sources / 2595 < prev    next >
Encoding:
Text File  |  1992-11-20  |  51.2 KB  |  2,313 lines

  1. Newsgroups: alt.sources
  2. Path: sparky!uunet!zaphod.mps.ohio-state.edu!sol.ctr.columbia.edu!eff!world!jhallen
  3. From: jhallen@world.std.com (Joseph H Allen)
  4. Subject: JOE 1.0.5 Part 9 of 10
  5. Message-ID: <By2Moo.L6s@world.std.com>
  6. Organization: The World Public Access UNIX, Brookline, MA
  7. Date: Sat, 21 Nov 1992 14:53:11 GMT
  8. Lines: 2303
  9.  
  10. Submitted-by: jhallen@world.std.com
  11. Archive-name: joe1.0.5part9
  12.  
  13. X
  14. aELEMENT(*vadel(vary,pos,n))
  15. aELEMENT(*vary);
  16. int pos,n;
  17. {
  18. if(pos>=aLEN(vary)) return vary;
  19. if(pos+n>=aLen(vary)) return vatrunc(vary,pos);
  20. mfwrd(vary+pos,vary+pos+n,aLen(vary)-(pos+n)+1);
  21. aLen(vary)-=n;
  22. return vary;
  23. }
  24. X
  25. int _acmp(a,b)
  26. aELEMENT(*a);
  27. aELEMENT(*b);
  28. {
  29. return acmp(*a,*b);
  30. }
  31. X
  32. aELEMENT(*vasort(ary,len))
  33. aELEMENT(*ary);
  34. int len;
  35. {
  36. if(!ary || !len) return ary;
  37. qsort(ary,len,sizeof(aCAST),_acmp);
  38. return ary;
  39. }
  40. X
  41. int vabsearch(ary,len,el)
  42. aELEMENT(*ary);
  43. aELEMENT(el);
  44. int len;
  45. {
  46. int x,y,z;
  47. if(!ary || !len) return 0;
  48. y=len;
  49. x=0;
  50. z=~0;
  51. while(z!=(x+y)/2)
  52. X {
  53. X z=(x+y)/2;
  54. X switch(acmp(el,ary[z]))
  55. X  {
  56. X case  1: x=z; break;
  57. X case -1: y=z; break;
  58. X case  0: return z;
  59. X  }
  60. X }
  61. return y;
  62. }
  63. X
  64. int vafirst(ary,len,el)
  65. aELEMENT(*ary);
  66. aELEMENT(el);
  67. int len;
  68. {
  69. int x;
  70. if(!ary || !len) return ~0;
  71. for(x=0;x!=len;++x) if(!acmp(ary[x],el)) return x;
  72. return ~0;
  73. }
  74. X
  75. int valast(ary,len,el)
  76. aELEMENT(*ary);
  77. aELEMENT(el);
  78. int len;
  79. {
  80. int x=len;
  81. if(!ary || !len) return ~0;
  82. do
  83. X {
  84. X --x;
  85. X if(!acmp(ary[x],el)) return x;
  86. X }
  87. X while(x);
  88. return ~0;
  89. }
  90. X
  91. int vacmpn(a,alen,b,blen)
  92. aELEMENT(*a);
  93. aELEMENT(*b);
  94. int alen, blen;
  95. {
  96. int x,l;
  97. int t;
  98. if(!a && !b) return 0;
  99. if(!a) return -1;
  100. if(!b) return 1;
  101. if(alen>blen) l=aLen(a);
  102. else l=blen;
  103. for(x=0;x!=l;++x) if(t=acmp(a[x],b[x])) return t;
  104. if(alen>blen) return  1;
  105. if(alen<blen) return -1;
  106. return 0;
  107. }
  108. X
  109. int vacmp(a,b)
  110. aELEMENT(*a);
  111. aELEMENT(*b);
  112. {
  113. return vacmpn(av(a),av(b));
  114. }
  115. X
  116. int vaa(a,alen,b,blen)
  117. aELEMENT(*a);
  118. aELEMENT(*b);
  119. int alen, blen;
  120. {
  121. int x;
  122. if(!a && !b) return 0;
  123. if(!a || !b) return ~0;
  124. if(alen<blen) return ~0;
  125. if(!blen) return 0;
  126. for(x=0;x!=alen-blen;++x) if(!vacmpn(a,blen,b,blen)) return x;
  127. return ~0;
  128. }
  129. X
  130. int vascan(a,alen,b,blen)
  131. aELEMENT(*a);
  132. aELEMENT(*b);
  133. int alen, blen;
  134. {
  135. int x;
  136. for(x=0;x!=alen;++x)
  137. X {
  138. X int z=vabsearch(b,blen,a[x]);
  139. X if(z<blen && !acmp(b[z],a[x])) return x;
  140. X }
  141. return ~0;
  142. }
  143. X
  144. int vaspan(a,alen,b,blen)
  145. aELEMENT(*a);
  146. aELEMENT(*b);
  147. int alen, blen;
  148. {
  149. int x;
  150. for(x=0;x!=alen;++x)
  151. X {
  152. X int z=vabsearch(b,blen,a[x]);
  153. X if(z==blen || acmp(b[z],a[x])) break;
  154. X }
  155. return x;
  156. }
  157. X
  158. aELEMENT(*vawords(a,s,len,sep,seplen))
  159. aELEMENT(*a);
  160. char *s, *sep;
  161. int len, seplen;
  162. {
  163. int x;
  164. if(!a) a=vamk(10);
  165. else a=vatrunc(a,0);
  166. loop:
  167. x=vsspan(s,len,sep,seplen);
  168. s+=x; len-=x;
  169. if(len)
  170. X {
  171. X x=vsscan(s,len,sep,seplen);
  172. X if(x!= ~0)
  173. X  {
  174. X  a=vaadd(a,vsncpy(vsmk(x),0,s,x));
  175. X  s+=x; len-=x;
  176. X  if(len) goto loop;
  177. X  }
  178. X else a=vaadd(a,vsncpy(vsmk(len),0,s,len));
  179. X }
  180. return a;
  181. }
  182. X
  183. aELEMENT(*vaiwords(a,s,len,inc,inclen))
  184. aELEMENT(*a);
  185. char *s, *inc;
  186. int len, inclen;
  187. {
  188. int x;
  189. if(!a) a=vamk(10);
  190. else a=vatrunc(a,0);
  191. loop:
  192. x=vsscan(s,len,inc,inclen);
  193. s+=x; len-=x;
  194. if(len)
  195. X {
  196. X x=vsspan(s,len,inc,inclen);
  197. X if(x!= ~0)
  198. X  {
  199. X  a=vaadd(a,vsncpy(vsmk(x),0,s,x));
  200. X  s+=x; len-=x;
  201. X  if(len) goto loop;
  202. X  }
  203. X else a=vaadd(a,vsncpy(vsmk(len),0,s,len));
  204. X }
  205. return a;
  206. }
  207. SHAR_EOF
  208. chmod 0600 va.c ||
  209. echo 'restore of va.c failed'
  210. Wc_c="`wc -c < 'va.c'`"
  211. test 6830 -eq "$Wc_c" ||
  212.     echo 'va.c: original size 6830, current size' "$Wc_c"
  213. fi
  214. # ============= va.h ==============
  215. if test -f 'va.h' -a X"$1" != X"-c"; then
  216.     echo 'x - skipping va.h (File already exists)'
  217. else
  218. echo 'x - extracting va.h (Text)'
  219. sed 's/^X//' << 'SHAR_EOF' > 'va.h' &&
  220. /* Variable length arrays of strings
  221. X   Copyright (C) 1992 Joseph H. Allen
  222. X
  223. This file is part of JOE (Joe's Own Editor)
  224. X
  225. JOE is free software; you can redistribute it and/or modify it under the 
  226. terms of the GNU General Public License as published by the Free Software 
  227. Foundation; either version 1, or (at your option) any later version.  
  228. X
  229. JOE is distributed in the hope that it will be useful, but WITHOUT ANY 
  230. WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 
  231. FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more 
  232. details.  
  233. X
  234. You should have received a copy of the GNU General Public License along with 
  235. JOE; see the file COPYING.  If not, write to the Free Software Foundation, 
  236. 675 Mass Ave, Cambridge, MA 02139, USA.  */ 
  237. X
  238. #ifndef _Iva
  239. #define _Iva
  240. X
  241. #include "config.h"
  242. #include "vs.h"
  243. X
  244. /* Functions and global variable you have to define.  Replace these with
  245. X * macros or defines here if they are not to be actual functions 
  246. X */
  247. X
  248. #define aELEMENT(a) char *a
  249. #define aCAST char *
  250. /* aELEMENT(adup()); */
  251. #define adup(s) vsdup(s)
  252. /* aELEMENT(adel()); */
  253. #define adel(s) vsrm(s)
  254. /* int acmp(); */
  255. #define acmp(a,b) vscmp((a),(b))
  256. /* extern aELEMENT(ablank); */
  257. #define ablank NULL
  258. /* extern aELEMENT(aterm); */
  259. #define aterm NULL
  260. X
  261. /************************/
  262. /* Creation/Destruction */
  263. /************************/
  264. X
  265. /* aELEMENT(*vamk(int len));
  266. X * Create a variable length array.  Space for 'len' elements is preallocated.
  267. X */
  268. aELEMENT(*vamk());
  269. X
  270. /* void varm(aELEMENT(*vary));
  271. X * Free an array and everything which is in it.  Does nothing if 'vary' is
  272. X * 0.
  273. X */
  274. void varm();
  275. X
  276. /********************/
  277. /* Space management */
  278. /********************/
  279. X
  280. /* int aSIZ(aELEMENT(*vary));
  281. X * int aSiz(aELEMENT(*vary));
  282. X * Access size part of array.  This int indicates the number of elements which
  283. X * can fit in the array before realloc needs to be called.  It does not include
  284. X * the extra space needed for the terminator and the header.
  285. X *
  286. X * aSIZ returns 0 if you pass it 0.  aSiz does not do this checking,
  287. X * but can be used as an lvalue.
  288. X */
  289. #define aSIZ(a) ((a)?*((int *)(a)-2):0)
  290. #define aSiz(a) (*((int *)(a)-2))
  291. X
  292. /* int aLEN(aELEMENT(*vary));
  293. X * int aLen(aELEMENT(*vary));
  294. X * Access length part of array.  This int indicates the number of elements
  295. X * currently in the array (not including the terminator).  This should be
  296. X * used primarily for reading the size of the array.  It can be used for
  297. X * setting the size of the array, but it must be used with care since it
  298. X * does not eliminate elements (if the size decreases) or make sure there's
  299. X * enough room (if the size increases).  See vensure and vtrunc.
  300. X *
  301. X * aLEN return a length of zero if 'vary' is 0.
  302. X * aLen doesn't do this checking, but can be used as an lvalue
  303. X */
  304. #define aLEN(a) ((a)?*((int *)(a)-1):0)
  305. #define aLen(a) (*((int *)(a)-1))
  306. X
  307. /* int alen(aELEMENT(*ary));
  308. X * Compute length of char or variable length array by searching for termination
  309. X * element.  Returns 0 if 'vary' is 0.
  310. X */
  311. int alen();
  312. X
  313. /* aELEMENT(*vaensure(aELEMENT(*vary),int len));
  314. X * Make sure there's enough space in the array for 'len' elements.  Whenever
  315. X * vaensure reallocs the array, it allocates 25% more than the necessary
  316. X * minimum space in anticipation of future expansion.  If 'vary' is 0,
  317. X * it creates a new array.
  318. X */
  319. aELEMENT(*vaensure());
  320. X
  321. /* aELEMENT(*vazap(aELEMENT(*vary),int pos,int n));
  322. X * Destroy n elements from an array beginning at pos.  Is ok if pos/n go
  323. X * past end of array.  This does not change the aLEN() value of the array.
  324. X * This does nothing and returns 0 if 'vary' is 0.  Note that this
  325. X * function does not actually write to the array.  This does not stop if
  326. X * a aterm is encountered.
  327. X */
  328. aELEMENT(*vazap());
  329. X
  330. /* aELEMENT(*vatrunc(aELEMENT(*vary),int len));
  331. X * Truncate array to indicated size.  This zaps or expands with blank elements
  332. X * and sets the LEN() of the array.  A new array is created if 'vary' is 0.
  333. X */
  334. aELEMENT(*vatrunc());
  335. X
  336. /************************************/
  337. /* Function which write to an array */
  338. /************************************/
  339. X
  340. /* aELEMENT(*vafill(aELEMENT(*vary),int pos,aELEMENT(el),int len));
  341. X * Set 'len' element of 'vary' beginning at 'pos' to duplications of 'el'.
  342. X * Ok, if pos/len are past end of array.  If 'vary' is 0, a new array is
  343. X * created.
  344. X *
  345. X * This does not zap previous values.  If you need that to happen, call
  346. X * vazap first.  It does move the terminator around properly though.
  347. X */
  348. aELEMENT(*vafill());
  349. X
  350. /* aELEMENT(*vancpy(aELEMENT(*vary),int pos,aELEMENT(*array),int len));
  351. X * Copy 'len' elements from 'array' onto 'vary' beginning at position 'pos'.
  352. X * 'array' can be a normal char array since the length is passed seperately.  The
  353. X * elements are copied, not duplicated.  A new array is created if 'vary' is
  354. X * 0.  This does not zap previous elements.
  355. X */
  356. aELEMENT(*vancpy());
  357. X
  358. /* aELEMENT(*vandup(aELEMENT(*vary),int pos,aELEMENT(*array),int len));
  359. X * Duplicate 'len' elements from 'array' onto 'vary' beginning at position
  360. X * 'pos'.  'array' can be a char array since its length is passed seperately.  A
  361. X * new array is created if 'vary' is 0.
  362. X */
  363. aELEMENT(*vandup());
  364. X
  365. /* aELEMENT(*vafield(aELEMENT(*vary),int pos,int len));
  366. X * Make sure a field exists at 'pos' of length 'len'.  If there isn't one,
  367. X * 'vary' is extended with blank elements.  This does not eliminate elements
  368. X * which already exist in the field.  Use vazap for that.
  369. X */
  370. aELEMENT(*vafield());
  371. X
  372. /* aELEMENT(*vadup(aELEMENT(*vary)));
  373. X * Duplicate array.  This is just a functionalized version of:
  374. X *
  375. X *   vandup(NULL,0,vary,aLEN(vary));
  376. X *
  377. X * but since you need to be able to refer to this particular function by
  378. X * address often it's given here.
  379. X *
  380. X * (actually, there's bazillions of these simple combinations of the above
  381. X * functions and the macros of the next section.  You'll probably want to make
  382. X * functionalized instances of the ones you use most often - especially since
  383. X * the macros aren't safe).
  384. X */ 
  385. aELEMENT(*vadup());
  386. X
  387. /* aELEMENT(*vaset(aELEMENT(*vary),int pos,aELEMENT(element)));
  388. X * Set an element in an array.  Any value of 'pos' is valid.  A new array
  389. X * is created if 'vary' is 0.  The previous contents of the position is
  390. X * deleted.    This does not duplicate 'element'.  If you need 'element'
  391. X * duplicated, call: vaset(vary,pos,adup(element));
  392. X */
  393. aELEMENT(*_vaset());
  394. X
  395. #define vaset(v,p,el)  \
  396. X (!(v) || (p)>aLen(v) || (p)==aLen(v) && (p)==aSiz(v) ?  \
  397. X  _vaset((v),(p),(el)) \
  398. X : \
  399. X  ((p)==aLen(v) ? \
  400. X   ((v)[(p)+1]=(v)[p], (v)[p]=(el), aLen(v)=(p)+1, (v)) \
  401. X  : \
  402. X   (adel((v)[p]), (v)[p]=(el), (v)) \
  403. X  ) \
  404. X )   
  405. X
  406. /* aELEMENT(*vaadd(aELEMENT(*vary),aELEMENT(element)));
  407. X * Concatenate a single element to the end of 'vary'.  A new array is created
  408. X * if 'vary' is 0.  This does not duplicate element: call
  409. X * vaadd(vary,adup(element));  If you need it duplicated.
  410. X */
  411. #define vaadd(v,el) \
  412. X (!(v) || aLen(v)==aSiz(v) ? \
  413. X  _vaset((v),aLEN(v),(el)) \
  414. X : \
  415. X  ((v)[aLen(v)+1]=(v)[aLen(v)], (v)[aLen(v)]=(el), \
  416. X   aLen(v)=aLen(v)+1, (v)) \
  417. X )
  418. X
  419. /**************************************/
  420. /* Functions which read from an array */
  421. /**************************************/
  422. X
  423. /* These macros are used to generate the address/size pairs which get
  424. X * passed to the functions of the previous section.
  425. X */
  426. X
  427. /* { aELEMENT(*),int } av(aELEMENT(*array));
  428. X * Return array,size pair.  Uses aLEN to get size.
  429. X */
  430. #define av(a) (a),aLEN(a)
  431. X
  432. /* { aELEMENT(*),int } az(aELEMENT(*array));
  433. X * Return array,size pair.  Uses alen to get size.
  434. X */
  435. #define az(a) (a),alen(a)
  436. X
  437. /* { aELEMENT(*),int } ac(aELEMENT(*array));
  438. X * Return array,size pair.  Uses 'sizeof' to get size.
  439. X */
  440. #define ac(a) (a),(sizeof(a)/sizeof(aCAST))
  441. X
  442. /* { aELEMENT(*),int } arest(aELEMENT(*vary),int pos);
  443. X * Return array,size pair of rest of array beginning at pos.  If
  444. X * pos is past end of array, gives size of 0.
  445. X */
  446. #define arest(a,p) ((a)+(p)),(((p)>aLEN(a))?0:aLen(a)-(p))
  447. X
  448. /* { aELEMENT(*),int } apart(aELEMENT(*vary),int pos,int len);
  449. X * Return array,size pair of 'len' elements of array beginning with pos.  If
  450. X * pos is past end of array, gives size of 0.  If pos+len is past end of array,
  451. X * returns number of elements to end of array.
  452. X */
  453. #define apart(a,p,l) \
  454. X ((a)+(p)),((p)>=aLEN(a)?0:((p)+(l)>aLen(a)?aLen(a)-(p):(l)))
  455. X
  456. /* aELEMENT(vaget(aELEMENT(*vary),int pos));
  457. X * Get an element from an array.  Any value of pos is valid; if it's past the
  458. X * end of the array or if 'vary' is 0, the terminator is returned.  This
  459. X * does not make a duplicate of the returned element.  If you want that, pass
  460. X * the return value of this to adup.
  461. X */
  462. #define vaget(a,p) ((p)>=aLEN(a)?aterm:(a)[p])
  463. X
  464. /**********************/
  465. /* Insertion/Deletion */
  466. /**********************/
  467. X
  468. /* aELEMENT(*vains(aELEMENT(*vary),int pos,int n));
  469. X * Insert n empty slots into the array.  If 'pos' >= the length of the array,
  470. X * the array is simply extended.  The new slots are not set to anything.
  471. X * This does not set the elements in the created hole to any particular
  472. X * value: use vafill if you need that to occur.
  473. X */
  474. aELEMENT(*vains());
  475. X
  476. /* aELEMENT(*vadel(aELEMENT(*vary),int pos,int n));
  477. X * Delete n slots from the array.  This does not zap the elements first; call
  478. X * vazap first if you need this to happen.
  479. X */
  480. aELEMENT(*vadel());
  481. X
  482. /*************************/
  483. /* Searching and Sorting */
  484. /*************************/
  485. X
  486. /* aELEMENT(*vasort(aELEMENT(*ary),int len))
  487. X * Sort the elements of an array (char or variable length) using qsort().
  488. X */
  489. aELEMENT(*vasort());
  490. X
  491. /* int vabsearch(aELEMENT(*ary),int len,aELEMENT(element));
  492. X * Do a binary search on a sorted variable length or char array.  Returns position
  493. X * of matching element or the position where the element should be if it was
  494. X * not found.  (You should test with acmp to find out which).
  495. X *
  496. X * Hmm... this should really indicate whether or not the element was found.
  497. X */
  498. int vabsearch();
  499. X
  500. /* int vafirst(aELEMENT(*ary),int len,aELEMENT(element));
  501. X * Find offset to first matching element in 'vary' or return ~0 if not found.
  502. X */
  503. int vafirst();
  504. X
  505. /* int valast(aELEMENT(*ary),int len,aELEMENT(element));
  506. X * Find offset to last matching element in 'vary' or return ~0 if none found.
  507. X */
  508. int valast();
  509. X
  510. /* int vaa(aELEMENT(*a),int alen,aELEMENT(*b),int blen);
  511. X * Do a substring search on 'a'.  Return offset from 'a' to first matching
  512. X * occurance of 'b' in 'a' or return ~0 if none found.
  513. X */
  514. int vaa();
  515. X
  516. /* int vacmpn(aELEMENT(*a),int alen,aELEMENT(*b),int blen);
  517. X *
  518. X * Compare two arrays using acmp.  If 'a' > 'b', return 1.  If 'a' == 'b',
  519. X * return 0.  If 'a' < 'b', return -1.  Longer strings are > shorter ones if
  520. X * their beginning match.
  521. X */
  522. int vacmpn();
  523. X
  524. /* int vacmp(aELEMENT(*a),aELEMENT(*b));
  525. X *
  526. X * Functionalized version of: vacmpn(av(a),av(b));
  527. X */
  528. int vacmp();
  529. X
  530. /* int vascan(aELEMENT(*a),int alen,aELEMENT(*b),int blen);
  531. X * Find offset of first matching element in 'a' which matches any
  532. X * of the elements passed in 'b'.  Array 'b' must be sorted.
  533. X *
  534. X * Hmm... this really needs to return what the found element is.
  535. X */
  536. int vascan();
  537. X
  538. /* int vaspan(aELEMENT(*a),int alen,aELEMENT(*b),int blen);
  539. X * Find offset of first matching element in 'a' which does not match any
  540. X * of the elements passed in 'b'.  Array 'b' must be sorted.
  541. X */
  542. int vaspan();
  543. X
  544. /* aELEMENT(*vawords(aELEMENT(*a),char *s,int len,char *sep,int seplen));
  545. X * Generate list of strings out of words in 's' seperated with the characters
  546. X * in 'sep'.  The characters in 'sep' must be sorted.
  547. X */
  548. aELEMENT(*vawords());
  549. X
  550. /* aELEMENT(*vaiwords(aELEMENT(*a),char *s,int len,char *sep,int seplen));
  551. X * Same as above, but you give the characters to be included in the words
  552. X * instead of the seperators.
  553. X */
  554. aELEMENT(*vaiwords());
  555. X
  556. #endif
  557. SHAR_EOF
  558. chmod 0600 va.h ||
  559. echo 'restore of va.h failed'
  560. Wc_c="`wc -c < 'va.h'`"
  561. test 11674 -eq "$Wc_c" ||
  562.     echo 'va.h: original size 11674, current size' "$Wc_c"
  563. fi
  564. # ============= vfile.c ==============
  565. if test -f 'vfile.c' -a X"$1" != X"-c"; then
  566.     echo 'x - skipping vfile.c (File already exists)'
  567. else
  568. echo 'x - extracting vfile.c (Text)'
  569. sed 's/^X//' << 'SHAR_EOF' > 'vfile.c' &&
  570. /* Software virtual memory system
  571. X   Copyright (C) 1992 Joseph H. Allen
  572. X
  573. This file is part of JOE (Joe's Own Editor)
  574. X
  575. JOE is free software; you can redistribute it and/or modify it under the 
  576. terms of the GNU General Public License as published by the Free Software 
  577. Foundation; either version 1, or (at your option) any later version.  
  578. X
  579. JOE is distributed in the hope that it will be useful, but WITHOUT ANY 
  580. WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 
  581. FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more 
  582. details.  
  583. X
  584. You should have received a copy of the GNU General Public License along with 
  585. JOE; see the file COPYING.  If not, write to the Free Software Foundation, 
  586. 675 Mass Ave, Cambridge, MA 02139, USA.  */ 
  587. X
  588. #include <stdio.h>
  589. #include <sys/types.h>
  590. #include <sys/stat.h>
  591. #include <fcntl.h>
  592. #include "config.h"
  593. #include "vs.h"
  594. #include "blocks.h"
  595. #include "heap.h"
  596. #include "queue.h"
  597. #include "pathfunc.h"
  598. #include "toomany.h"
  599. #include "random.h"
  600. #include "vfile.h"
  601. X
  602. static VFILE vfiles={{&vfiles,&vfiles}};    /* Known vfiles */
  603. static VPAGE *freepages=0;    /* Linked list of free pages */
  604. static VPAGE *htab[HTSIZE];    /* Hash table of page headers */
  605. static long curvalloc=0;    /* Amount of memory in use */
  606. static long maxvalloc= ILIMIT;    /* Maximum allowed */
  607. char *vbase;            /* Data first entry in vheader refers to */
  608. VPAGE **vheaders=0;        /* Array of header addresses */
  609. static int vheadsz=0;        /* No. entries allocated to vheaders */
  610. X
  611. void vflsh()
  612. {
  613. VPAGE *vp;
  614. VPAGE *vlowest;
  615. long addr;
  616. VFILE *vfile;
  617. int x;
  618. for(vfile=vfiles.link.next;
  619. X    vfile!=&vfiles;
  620. X    vfile=vfile->link.next)
  621. X {
  622. X loop:
  623. X addr= MAXLONG;
  624. X vlowest=0;
  625. X for(x=0;x!=HTSIZE;x++)
  626. X  for(vp=htab[x];vp;vp=vp->next)
  627. X   if(vp->addr<addr && vp->dirty && vp->vfile==vfile && !vp->count)
  628. X    addr=vp->addr, vlowest=vp;
  629. X if(vlowest)
  630. X  {
  631. X  if(!vfile->name) vfile->name=mktmp("/tmp/");
  632. X  if(!vfile->fd)
  633. X   {
  634. X   vfile->fd=Fopen(vfile->name);
  635. X   }
  636. X  Fseek(vfile->fd,addr);
  637. X  if(addr+PGSIZE>vsize(vfile))
  638. X   {
  639. X   Fwrite(vfile->fd,vlowest->data,(int)(vsize(vfile)-addr));
  640. X   vfile->size=vsize(vfile);
  641. X   }
  642. X  else
  643. X   {
  644. X   Fwrite(vfile->fd,vlowest->data,PGSIZE);
  645. X   if(addr+PGSIZE>vfile->size) vfile->size=addr+PGSIZE;
  646. X   }
  647. X  vlowest->dirty=0;
  648. X  goto loop;
  649. X  }
  650. X }
  651. }
  652. X
  653. void vflshf(vfile)
  654. VFILE *vfile;
  655. {
  656. VPAGE *vp;
  657. VPAGE *vlowest;
  658. long addr;
  659. int x;
  660. loop:
  661. addr= MAXLONG;
  662. vlowest=0;
  663. for(x=0;x!=HTSIZE;x++)
  664. X for(vp=htab[x];vp;vp=vp->next)
  665. X  if(vp->addr<addr && vp->dirty && vp->vfile==vfile && !vp->count)
  666. X   addr=vp->addr, vlowest=vp;
  667. if(vlowest)
  668. X {
  669. X if(!vfile->name) vfile->name=mktmp("/tmp/");
  670. X if(!vfile->fd)
  671. X  {
  672. X  vfile->fd=Fopen(vfile->name);
  673. X  }
  674. X Fseek(vfile->fd,addr);
  675. X if(addr+PGSIZE>vsize(vfile))
  676. X  {
  677. X  Fwrite(vfile->fd,vlowest->data,(int)(vsize(vfile)-addr));
  678. X  vfile->size=vsize(vfile);
  679. X  }
  680. X else
  681. X  {
  682. X  Fwrite(vfile->fd,vlowest->data,PGSIZE);
  683. X  if(addr+PGSIZE>vfile->size) vfile->size=addr+PGSIZE;
  684. X  }
  685. X vlowest->dirty=0;
  686. X goto loop;
  687. X }
  688. }
  689. X
  690. char *vlock(vfile,addr)
  691. VFILE *vfile;
  692. long addr;
  693. {
  694. VPAGE *vp, *pp;
  695. int x,y;
  696. int ofst=(addr&(PGSIZE-1));
  697. addr-=ofst;
  698. X
  699. for(vp=htab[((addr>>LPGSIZE)+(int)vfile)&(HTSIZE-1)];vp;vp=vp->next)
  700. X if(vp->vfile==vfile && vp->addr==addr) return ++vp->count, vp->data+ofst;
  701. X
  702. if(freepages)
  703. X {
  704. X vp=freepages;
  705. X freepages=vp->next;
  706. X goto gotit;
  707. X }
  708. X
  709. if(curvalloc+PGSIZE<=maxvalloc)
  710. X {
  711. X vp=(VPAGE *)malloc(sizeof(VPAGE)*INC);
  712. X if(vp)
  713. X  {
  714. X  vp->data=(char *)memalign(PGSIZE,PGSIZE*INC);
  715. X  if(vp->data)
  716. X   {
  717. X   int q;
  718. X   curvalloc+=PGSIZE*INC;
  719. X   if(!vheaders)
  720. X    vheaders=(VPAGE **)malloc((vheadsz=INC)*sizeof(VPAGE *)),
  721. X    vbase=vp->data;
  722. X   else
  723. X    if(vp->data<vbase)
  724. X     {
  725. X     VPAGE **t=vheaders;
  726. X     int amnt=(physical(vbase)-physical(vp->data))>>LPGSIZE;
  727. X     vheaders=(VPAGE **)malloc((amnt+vheadsz)*sizeof(VPAGE *));
  728. X     mcpy(vheaders+amnt,t,vheadsz*sizeof(VPAGE *));
  729. X     vheadsz+=amnt;
  730. X     vbase=vp->data;
  731. X     free(t);
  732. X     }
  733. X    else if(((physical(vp->data+PGSIZE*INC)-physical(vbase))>>LPGSIZE)>vheadsz)
  734. X     {
  735. X     vheaders=(VPAGE **)realloc(vheaders,
  736. X      (vheadsz=(((physical(vp->data+PGSIZE*INC)-physical(vbase))>>LPGSIZE)))*sizeof(VPAGE *));
  737. X     }
  738. X   for(q=1;q!=INC;++q)
  739. X    {
  740. X    vp[q].next=freepages;
  741. X    freepages=vp+q;
  742. X    vp[q].data=vp->data+q*PGSIZE;
  743. X    vheader(vp->data+q*PGSIZE)=vp+q;
  744. X    }
  745. X   vheader(vp->data)=vp;
  746. X   goto gotit;
  747. X   }
  748. X  free(vp);
  749. X  vp=0;
  750. X  }
  751. X }
  752. X
  753. for(y=HTSIZE, x=(random()&(HTSIZE-1));y;x=((x+1)&(HTSIZE-1)), --y)
  754. X for(pp=(VPAGE *)(htab+x),vp=pp->next;vp;pp=vp, vp=vp->next)
  755. X  if(!vp->count && !vp->dirty)
  756. X   {
  757. X   pp->next=vp->next;
  758. X   goto gotit;
  759. X   }
  760. vflsh();
  761. for(y=HTSIZE, x=(random()&(HTSIZE-1));y;x=((x+1)&(HTSIZE-1)), --y)
  762. X for(pp=(VPAGE *)(htab+x),vp=pp->next;vp;pp=vp, vp=vp->next)
  763. X  if(!vp->count && !vp->dirty)
  764. X   {
  765. X   pp->next=vp->next;
  766. X   goto gotit;
  767. X   }
  768. write(2,"Out of memory\r\n",15);
  769. exit(1);
  770. X
  771. gotit:
  772. vp->addr=addr;
  773. vp->vfile=vfile;
  774. vp->dirty=0;
  775. vp->count=1;
  776. vp->next=htab[((addr>>LPGSIZE)+(int)vfile)&(HTSIZE-1)];
  777. htab[((addr>>LPGSIZE)+(int)vfile)&(HTSIZE-1)]=vp;
  778. X
  779. if(addr<vfile->size)
  780. X {
  781. X if(!vfile->fd)
  782. X  {
  783. X  vfile->fd=Fopen(vfile->name);
  784. X  }
  785. X Fseek(vfile->fd,addr);
  786. X if(addr+PGSIZE>vfile->size)
  787. X  {
  788. X  Fread(vfile->fd,vp->data,(int)(vfile->size-addr));
  789. X  mset(vp->data+vfile->size-addr,0,PGSIZE-(int)(vfile->size-addr));
  790. X  }
  791. X else Fread(vfile->fd,vp->data,PGSIZE);
  792. X }
  793. else mset(vp->data,0,PGSIZE);
  794. X
  795. return vp->data+ofst;
  796. }
  797. X
  798. VFILE *vtmp()
  799. {
  800. VFILE *new=(VFILE *)malloc(sizeof(VFILE));
  801. new->fd= 0;
  802. new->name=0;
  803. new->alloc=0;
  804. new->size=0;
  805. new->left=0;
  806. new->lv=0;
  807. new->vpage=0;
  808. new->flags=1;
  809. new->vpage1=0;
  810. new->addr= -1;
  811. return enqueb(VFILE,link,&vfiles,new);
  812. }
  813. X
  814. VFILE *vopen(name)
  815. char *name;
  816. {
  817. VFILE *new=(VFILE *)malloc(sizeof(VFILE));
  818. new->name=vsncpy(NULL,0,sz(name));
  819. new->fd=Fopen(name);
  820. if(!new->fd)
  821. X {
  822. X fprintf(stderr,"Couldn\'t open \'%s\'\n",name);
  823. X free(new);
  824. X return 0;
  825. X }
  826. new->size=new->fd->size;
  827. new->alloc=new->size;
  828. new->left=0;
  829. new->lv=0;
  830. new->vpage=0;
  831. new->flags=0;
  832. new->vpage1=0;
  833. new->addr= -1;
  834. return enqueb(VFILE,link,&vfiles,new);
  835. }
  836. X
  837. void vclose(vfile)
  838. VFILE *vfile;
  839. {
  840. VPAGE *vp, *pp;
  841. int x;
  842. if(vfile->name)
  843. X {
  844. X if(vfile->flags) unlink(vfile->name);
  845. X else vflshf(vfile);
  846. X vsrm(vfile->name);
  847. X }
  848. if(vfile->fd) Fclose(vfile->fd);
  849. free(deque(VFILE,link,vfile));
  850. for(x=0;x!=HTSIZE;x++)
  851. X for(pp=(VPAGE *)(htab+x), vp=pp->next;vp;)
  852. X  if(vp->vfile==vfile)
  853. X   {
  854. X   pp->next=vp->next;
  855. X   vp->next=freepages;
  856. X   freepages=vp;
  857. X   vp=pp->next;
  858. X   }
  859. X  else pp=vp, vp=vp->next;
  860. }
  861. X
  862. /* this is now broken */
  863. void vlimit(amount)
  864. long amount;
  865. {
  866. VPAGE *vp, *pp;
  867. int x,y;
  868. maxvalloc=amount;
  869. while(curvalloc>maxvalloc)
  870. X if(freepages)
  871. X  {
  872. X  vp=freepages;
  873. X  freepages=vp->next;
  874. X  free(vp->data);
  875. X  free(vp);
  876. X  curvalloc-=PGSIZE;
  877. X  }
  878. X else
  879. X  {
  880. X  again:
  881. X  for(y=HTSIZE, x=(random()&(HTSIZE-1));y;x=((x+1)&(HTSIZE-1)), --y)
  882. X   for(pp=(VPAGE *)(htab+x),vp=pp->next;vp;pp=vp, vp=vp->next)
  883. X    if(!vp->count && !vp->dirty)
  884. X     {
  885. X     pp->next=vp->next;
  886. X     free(vp->data);
  887. X     free(vp);
  888. X     if((curvalloc-=PGSIZE)<=maxvalloc) return;
  889. X     goto again;
  890. X     }
  891. X  vflsh();
  892. X  again1:
  893. X  for(y=HTSIZE, x=(random()&(HTSIZE-1));y;x=((x+1)&(HTSIZE-1)), --y)
  894. X   for(pp=(VPAGE *)(htab+x),vp=pp->next;vp;pp=vp, vp=vp->next)
  895. X    if(!vp->count && !vp->dirty)
  896. X     {
  897. X     pp->next=vp->next;
  898. X     free(vp->data);
  899. X     free(vp);
  900. X     if((curvalloc-=PGSIZE)<=maxvalloc) return;
  901. X     goto again1;
  902. X     }
  903. X  return;
  904. X  }
  905. }
  906. X
  907. long valloc(vfile,size)
  908. VFILE *vfile;
  909. long size;
  910. {
  911. long start=vsize(vfile);
  912. vfile->alloc=start+size;
  913. if(vfile->lv)
  914. X {
  915. X if(vheader(vfile->vpage)->addr+PGSIZE>vfile->alloc)
  916. X  vfile->lv=PGSIZE-(vfile->alloc-vheader(vfile->vpage)->addr);
  917. X else vfile->lv=0;
  918. X }
  919. return start;
  920. }
  921. X
  922. void vseek(vfile,addr)
  923. VFILE *vfile;
  924. long addr;
  925. {
  926. vfile->alloc=vsize(vfile);
  927. if(addr>vfile->alloc) vfile->alloc=addr;
  928. if(!vfile->vpage) vfile->vpage=vlock(vfile,addr&~(long)(PGSIZE-1));
  929. else if(vheader(vfile->vpage)->addr!=(addr&~(long)(PGSIZE-1)))
  930. X {
  931. X vunlock(vfile->vpage);
  932. X vfile->vpage=vlock(vfile,addr&~(long)(PGSIZE-1));
  933. X }
  934. vfile->bufp=vfile->vpage+(addr&(PGSIZE-1));
  935. vfile->left=vfile->vpage+PGSIZE-vfile->bufp;
  936. if(vheader(vfile->vpage)->addr+PGSIZE>vfile->alloc)
  937. X vfile->lv=PGSIZE-(vfile->alloc-vheader(vfile->vpage)->addr);
  938. else vfile->lv=0;
  939. }
  940. X
  941. int _vrgetc(vfile)
  942. VFILE *vfile;
  943. {
  944. if(vtell(vfile)==0) return MAXINT;
  945. vseek(vfile,vtell(vfile)-1);
  946. ++vfile->bufp;
  947. --vfile->left;
  948. return vrgetc(vfile);
  949. }
  950. X
  951. int _vgetc(vfile)
  952. VFILE *vfile;
  953. {
  954. if(vtell(vfile)==vsize(vfile)) return MAXINT;
  955. vseek(vfile,vtell(vfile));
  956. return vgetc(vfile);
  957. }
  958. X
  959. int nmvgetc(v) VFILE *v; { return vgetc(v); } 
  960. X
  961. int _vputc(vfile,c)
  962. VFILE *vfile;
  963. char c;
  964. {
  965. vseek(vfile,vtell(vfile));
  966. return vputc(vfile,c);
  967. }
  968. X
  969. short vgetw(vfile)
  970. VFILE *vfile;
  971. {
  972. short w;
  973. if(vtell(vfile)+2>vsize(vfile)) return -1;
  974. w=vgetc(vfile);
  975. w+=((short)vgetc(vfile)<<8);
  976. return w;
  977. }
  978. X
  979. short vputw(vfile,w)
  980. VFILE *vfile;
  981. short w;
  982. {
  983. vputc(vfile,w);
  984. vputc(vfile,w>>8);
  985. return w;
  986. }
  987. X
  988. long vgetl(vfile)
  989. VFILE *vfile;
  990. {
  991. long w;
  992. if(vtell(vfile)+4>vsize(vfile)) return -1;
  993. w=vgetc(vfile);
  994. w+=((long)vgetc(vfile)<<8);
  995. w+=((long)vgetc(vfile)<<16);
  996. w+=((long)vgetc(vfile)<<24);
  997. return w;
  998. }
  999. X
  1000. long vputl(vfile,w)
  1001. VFILE *vfile;
  1002. long w;
  1003. {
  1004. vputc(vfile,w);
  1005. vputc(vfile,w>>8);
  1006. vputc(vfile,w>>16);
  1007. vputc(vfile,w>>24);
  1008. return w;
  1009. }
  1010. X
  1011. int _rc(vfile,addr)
  1012. VFILE *vfile;
  1013. long addr;
  1014. {
  1015. if(vfile->vpage1) vunlock(vfile->vpage1);
  1016. vfile->vpage1=vlock(vfile,vfile->addr=(addr&~(long)(PGSIZE-1)));
  1017. return rc(vfile,addr);
  1018. }
  1019. X
  1020. int _wc(vfile,addr,c)
  1021. VFILE *vfile;
  1022. long addr;
  1023. char c;
  1024. {
  1025. if(addr+1>vsize(vfile)) valloc(vfile,addr+1-vsize(vfile));
  1026. if(vfile->vpage1) vunlock(vfile->vpage1);
  1027. vfile->vpage1=vlock(vfile,vfile->addr=(addr&~(long)(PGSIZE-1)));
  1028. return wc(vfile,addr,c);
  1029. }
  1030. X
  1031. short rw(vfile,addr)
  1032. VFILE *vfile;
  1033. long addr;
  1034. {
  1035. short c;
  1036. if(addr+2>vsize(vfile)) return -1;
  1037. c=rc(vfile,addr);
  1038. c+=((short)rc(vfile,addr+1)<<8);
  1039. return c;
  1040. }
  1041. X
  1042. short ww(vfile,addr,c)
  1043. VFILE *vfile;
  1044. long addr;
  1045. short c;
  1046. {
  1047. if(addr+2>vsize(vfile)) valloc(vfile,addr+2-vsize(vfile));
  1048. wc(vfile,addr,c);
  1049. wc(vfile,addr+1,c>>8);
  1050. return c;
  1051. }
  1052. X
  1053. long rl(vfile,addr)
  1054. VFILE *vfile;
  1055. long addr;
  1056. {
  1057. long c;
  1058. if(addr+4>vsize(vfile)) return -1;
  1059. c=rc(vfile,addr);
  1060. c+=((long)rc(vfile,addr+1)<<8);
  1061. c+=((long)rc(vfile,addr+2)<<16);
  1062. c+=((long)rc(vfile,addr+3)<<24);
  1063. return c;
  1064. }
  1065. X
  1066. long wl(vfile,addr,c)
  1067. VFILE *vfile;
  1068. long addr;
  1069. long c;
  1070. {
  1071. if(addr+4>vsize(vfile)) valloc(vfile,addr+4-vsize(vfile));
  1072. wc(vfile,addr,c);
  1073. wc(vfile,addr+1,c>>8);
  1074. wc(vfile,addr+2,c>>16);
  1075. wc(vfile,addr+3,c>>24);
  1076. return c;
  1077. }
  1078. X
  1079. void vread(v,blk,size)
  1080. VFILE *v;
  1081. char *blk;
  1082. int size;
  1083. {
  1084. long addr=vtell(v);
  1085. char *src;
  1086. int x;
  1087. while(size)
  1088. X {
  1089. X src=vlock(v,addr);
  1090. X x=PGSIZE-(addr&(PGSIZE-1));
  1091. X if(x>=size)
  1092. X  {
  1093. X  vseek(v,addr+size);
  1094. X  mcpy(blk,src,size);
  1095. X  vunlock(src);
  1096. X  return;
  1097. X  }
  1098. X size-=x;
  1099. X addr+=x;
  1100. X mcpy(blk,src,x);
  1101. X blk+=x;
  1102. X vunlock(src);
  1103. X }
  1104. vseek(v,addr);
  1105. }
  1106. X
  1107. void vwrite(v,blk,size)
  1108. VFILE *v;
  1109. char *blk;
  1110. int size;
  1111. {
  1112. long addr=vtell(v);
  1113. char *src;
  1114. int x;
  1115. if(addr+size>vsize(v)) valloc(v,addr+size-vsize(v));
  1116. while(size)
  1117. X {
  1118. X src=vlock(v,addr);
  1119. X x=PGSIZE-(addr&(PGSIZE-1));
  1120. X if(x>=size)
  1121. X  {
  1122. X  vseek(v,addr+size);
  1123. X  mcpy(src,blk,size);
  1124. X  vchanged(src);
  1125. X  vunlock(src);
  1126. X  return;
  1127. X  }
  1128. X size-=x;
  1129. X addr+=x;
  1130. X mcpy(src,blk,x);
  1131. X blk+=x;
  1132. X vchanged(src);
  1133. X vunlock(src);
  1134. X }
  1135. vseek(v,addr);
  1136. }
  1137. X
  1138. /* Write string to vfile */
  1139. X
  1140. void vputs(v,s)
  1141. VFILE *v;
  1142. char *s;
  1143. {
  1144. while(*s) vputc(v,*s), ++s;
  1145. }
  1146. X
  1147. /* Read a line from a file */
  1148. X
  1149. char *vgets(v,s)
  1150. VFILE *v;
  1151. char *s;
  1152. {
  1153. int c;
  1154. int x=0;
  1155. if(!sSIZ(s)) s=vstrunc(s,0);
  1156. while(c=vgetc(v), c!= MAXINT && c!='\n')
  1157. X {
  1158. X if(x==sSiz(s)) s=vsensure(s,x+10);
  1159. X s[x++]=c;
  1160. X }
  1161. if(x==sSiz(s)) s=vsensure(s,x+1);
  1162. sLen(s)=x;
  1163. s[x]=0;
  1164. return s;
  1165. }
  1166. SHAR_EOF
  1167. chmod 0600 vfile.c ||
  1168. echo 'restore of vfile.c failed'
  1169. Wc_c="`wc -c < 'vfile.c'`"
  1170. test 11446 -eq "$Wc_c" ||
  1171.     echo 'vfile.c: original size 11446, current size' "$Wc_c"
  1172. fi
  1173. # ============= vfile.h ==============
  1174. if test -f 'vfile.h' -a X"$1" != X"-c"; then
  1175.     echo 'x - skipping vfile.h (File already exists)'
  1176. else
  1177. echo 'x - extracting vfile.h (Text)'
  1178. sed 's/^X//' << 'SHAR_EOF' > 'vfile.h' &&
  1179. /* Software virtual memory system
  1180. X   Copyright (C) 1992 Joseph H. Allen
  1181. X
  1182. This file is part of JOE (Joe's Own Editor)
  1183. X
  1184. JOE is free software; you can redistribute it and/or modify it under the 
  1185. terms of the GNU General Public License as published by the Free Software 
  1186. Foundation; either version 1, or (at your option) any later version.  
  1187. X
  1188. JOE is distributed in the hope that it will be useful, but WITHOUT ANY 
  1189. WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 
  1190. FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more 
  1191. details.  
  1192. X
  1193. You should have received a copy of the GNU General Public License along with 
  1194. JOE; see the file COPYING.  If not, write to the Free Software Foundation, 
  1195. 675 Mass Ave, Cambridge, MA 02139, USA.  */ 
  1196. X
  1197. #ifndef _Ivfile
  1198. #define _Ivfile 1
  1199. X
  1200. #include "config.h"
  1201. #include "queue.h"
  1202. #include "toomany.h"
  1203. X
  1204. typedef struct vpage VPAGE;
  1205. typedef struct vfile VFILE;
  1206. X
  1207. #define PGSIZE 1024        /* Page size in bytes (Must be power of 2) */
  1208. #define LPGSIZE 10        /* LOG base 2 of PGSIZE */
  1209. #define ILIMIT (PGSIZE*256)    /* Max amount to buffer */
  1210. #define HTSIZE 256        /* Entries in hash table.  Must be pwr of 2 */
  1211. #define INC 8            /* Pages to allocate each time */
  1212. X
  1213. /* Page header */
  1214. X
  1215. struct vpage
  1216. X {
  1217. X VPAGE *next;            /* Next page with same hash value */
  1218. X VFILE *vfile;            /* Owner vfile */
  1219. X long addr;            /* Address of this page */
  1220. X int count;            /* Reference count */
  1221. X int dirty;            /* Set if page changed */
  1222. X char *data;            /* The data in the page */
  1223. X };
  1224. X
  1225. /* File structure */
  1226. X
  1227. struct vfile
  1228. X {
  1229. X LINK(VFILE) link;        /* Doubly linked list of vfiles */
  1230. X long size;            /* Number of bytes in physical file */
  1231. X long alloc;            /* Number of bytes allocated to file */
  1232. X File *fd;            /* Physical file */
  1233. X int writeable;            /* Set if we can write */
  1234. X char *name;            /* File name.  0 if unnamed */
  1235. X int flags;            /* Set if this is only a temporary file */
  1236. X
  1237. X /* For array I/O */
  1238. X char *vpage1;            /* Page address */
  1239. X long addr;            /* File address of above page */
  1240. X
  1241. X /* For stream I/O */
  1242. X char *bufp;            /* Buffer pointer */
  1243. X char *vpage;            /* Buffer pointer points in here */
  1244. X int left;            /* Space left in bufp */
  1245. X int lv;                /* Amount of append space at end of buffer */
  1246. X };
  1247. X
  1248. extern char *vbase;        /* Data first entry in vheader refers to */
  1249. extern VPAGE **vheaders;    /* Array of headers */
  1250. X
  1251. /* VFILE *vtmp(V);
  1252. X *
  1253. X * Open a temporary virtual file.  File goes away when closed.  No actual
  1254. X * file is generated if everything fits in memory.
  1255. X */
  1256. VFILE *vtmp();
  1257. X
  1258. /* VFILE *vopen(char *name);
  1259. X *
  1260. X * Open a file for reading and if possible, writing.  If the file could not
  1261. X * be opened, NULL is returned.
  1262. X */
  1263. VFILE *vopen();
  1264. X
  1265. /* long vsize(VFILE *);
  1266. X *
  1267. X * Return size of file
  1268. X */
  1269. X
  1270. #define vsize(vfile) \
  1271. X    ( \
  1272. X      (vfile)->left<(vfile)->lv ? \
  1273. X        (vfile)->alloc+(vfile)->lv-(vfile)->left \
  1274. X      : \
  1275. X        (vfile)->alloc \
  1276. X    )
  1277. X
  1278. /* void vclose(VFILE *vfile);
  1279. X *
  1280. X * Close a file.
  1281. X */
  1282. void vclose();
  1283. X
  1284. /* void vlimit(long amount);
  1285. X *
  1286. X * Set limit (in bytes) on amount of memory the virtual file system may
  1287. X * use.  This limit can be exceeded if all existing vpages are being referenced
  1288. X * and a new vpage is requested.
  1289. X *
  1290. X * When vlimit is called, the limit is immediatly enforced by elimiting
  1291. X * non-referenced vpages.
  1292. X */
  1293. X
  1294. void vlimit();
  1295. X
  1296. /* void vflsh(void); 
  1297. X *
  1298. X * Write all changed pages to the disk
  1299. X */
  1300. X
  1301. void vflsh();
  1302. X
  1303. /* void vflshf(VFILE *vfile);
  1304. X *
  1305. X * Write changed pages for a specific file to the disk
  1306. X */
  1307. X
  1308. void vflshf();
  1309. X
  1310. /* char *vlock(VFILE *vfile,long addr);
  1311. X *
  1312. X * Translate virtual address to physical address.  'addr' does not have
  1313. X * to be on any particular alignment, but if you wish to access more than
  1314. X * a single byte, you have to be aware of where page boundaries are (virtual
  1315. X * address multiples of PGSIZE).
  1316. X *
  1317. X * The page containing the data is locked in memory (so that it won't be
  1318. X * freed or used for something else) until 'vunlock' is used.
  1319. X *
  1320. X * Warning:  If you allocate more than one page and use (change) them out of
  1321. X * order, vflsh will screw up if writing past the end of a file is illegal
  1322. X * in the host filesystem.
  1323. X *
  1324. X * Also:  This function does not allocate space to the file.  Use valloc()
  1325. X * for that.  You can vlock() pages past the allocated size of the file, but
  1326. X * be careful when you do this (you normally shouldn't- the only time you
  1327. X * ever might want to is to implement your own version of valloc()).
  1328. X */
  1329. X
  1330. char *vlock();
  1331. X
  1332. /* VPAGE *vheader(char *);
  1333. X * Return address of page header for given page
  1334. X */
  1335. X
  1336. #define vheader(p) (vheaders[(physical((char *)(p))-physical(vbase))>>LPGSIZE])
  1337. X
  1338. /* void vchanged(char *);
  1339. X *
  1340. X * Indicate that a vpage was changed so that it will be written back to the
  1341. X * file.  Any physical address which falls within the page may be given.
  1342. X */
  1343. X
  1344. #define vchanged(vpage) ( vheader(vpage)->dirty=1 )
  1345. X
  1346. /* void vunlock(char *);
  1347. X * Unreference a vpage (call one vunlock for every vlock)
  1348. X * Any physical address which falls within the page may be given.
  1349. X */
  1350. X
  1351. #define vunlock(vpage)  ( --vheader(vpage)->count )
  1352. X
  1353. /* void vupcount(char *);
  1354. X * Indicate that another reference is being made to a vpage
  1355. X */
  1356. X
  1357. #define vupcount(vpage) ( ++vheader(vpage)->count )
  1358. X
  1359. /* long valloc(VFILE *vfile,long size);
  1360. X *
  1361. X * Allocate space at end of file
  1362. X *
  1363. X * Returns file address of beginning of allocated space
  1364. X */
  1365. X
  1366. long valloc();
  1367. X
  1368. /******************************************************************************
  1369. X * The folloing functions implement stream I/O on top of the above software   *
  1370. X * virtual memory system                                                      *
  1371. X ******************************************************************************/
  1372. X
  1373. /* void vseek(VFILE *vfile,long addr);
  1374. X *
  1375. X * Seek to a file address.  Allocates space to the file if you seek past the
  1376. X * end.
  1377. X */
  1378. void vseek();
  1379. X
  1380. /* int vrgetc(VFILE *);
  1381. X * int vgetc(VFILE *);
  1382. X *
  1383. X * Get next character / Get previous character functions.
  1384. X * They return MAXINT for end of file / beginning of file.
  1385. X */
  1386. X
  1387. int _vgetc();
  1388. int _vrgetc();
  1389. X
  1390. #define vrgetc(v) \
  1391. X        ( (v)->left!=PGSIZE ? ( ++(v)->left, (int)(unsigned)*(--(v)->bufp) ) : _vrgetc(v) )
  1392. X
  1393. #define vgetc(v) \
  1394. X    ( (v)->left>(v)->lv ? ( --(v)->left, (int)(unsigned)*((v)->bufp++) ) : _vgetc(v) )
  1395. X
  1396. /* int vputc(VFILE *,I);
  1397. X *
  1398. X * Put character.  Returns character which is written.
  1399. X */
  1400. X
  1401. int _vputc();
  1402. X
  1403. #define vputc(v,c) \
  1404. X    ( \
  1405. X      (v)->left ? \
  1406. X       ( \
  1407. X       --(v)->left, \
  1408. X       vchanged((v)->vpage), \
  1409. X        (int)(unsigned)(*((v)->bufp++)=(c)) \
  1410. X       ) \
  1411. X      : \
  1412. X       _vputc((v),(c)) \
  1413. X    )
  1414. X
  1415. /* long vtell(VFILE *);
  1416. X *
  1417. X * Return current file position
  1418. X */
  1419. X
  1420. #define vtell(v) \
  1421. X    ( \
  1422. X     (v)->vpage ? \
  1423. X      ( vheader((v)->vpage)->addr+(v)->bufp-(v)->vpage ) \
  1424. X     : \
  1425. X      0L \
  1426. X    )
  1427. X
  1428. /* long vgetl(VFILE *);
  1429. X *
  1430. X * Get long.  No alignment requirements.  Returns -1 if goes past end of file.
  1431. X */
  1432. X
  1433. long vgetl();
  1434. X
  1435. /* short vgetw(VFILE *);
  1436. X *
  1437. X * Get short.  No alignment requirements.  Returns -1 if goes past end of file.
  1438. X */
  1439. X
  1440. short vgetw();
  1441. X
  1442. /* long vputl(VFILE *,long);
  1443. X *
  1444. X * Put long.  No alignment requirements.
  1445. X * Returns value written.
  1446. X */
  1447. X
  1448. long vputl();
  1449. X
  1450. /* short vputw(VFILE *,short);
  1451. X *
  1452. X * Put long.  No alignement requirements.
  1453. X * Returns value written.
  1454. X */
  1455. X
  1456. short vputw();
  1457. X
  1458. /* char *vgets(VFILE *v,char *s,U p);
  1459. X *
  1460. X * Read line into a variable length string beginning at 'p'.  If 's' is 0, a
  1461. X * new string is created.  The \n is not copied into the string.
  1462. X *
  1463. X * This requires that you use the 'vs.h' / 'vs.c' library.
  1464. X */
  1465. X
  1466. char *vgets();
  1467. X
  1468. /* void vputs(VFILE *v,char *s);
  1469. X *
  1470. X * Write string. \n is not appended */
  1471. X
  1472. void vputs();
  1473. X
  1474. /* void vread(VFILE *,char *,U size);
  1475. X *
  1476. X * Read bytes from a virtual file into a local data block
  1477. X */
  1478. X
  1479. void vread();
  1480. X
  1481. /* void vwrite(VFILE *,char *,U size);
  1482. X *
  1483. X * Write bytes from a local data block into a virtual file
  1484. X */
  1485. X
  1486. void vwrite();
  1487. X
  1488. /*************************************************************************** 
  1489. X * The following functions implement array I/O on top of the above virtual *
  1490. X * memory system (cheap memory mapped files)                               *
  1491. X ***************************************************************************/
  1492. X
  1493. /* int rc(VFILE *vfile,long addr);
  1494. X *
  1495. X * Read character.  Returns MAXINT if past end of file.
  1496. X */
  1497. X
  1498. int _rc();
  1499. X
  1500. #define rc(v,a) \
  1501. X    ( \
  1502. X      (a)>=vsize(v) ? MAXINT : \
  1503. X        ( \
  1504. X          (v)->addr==((a)&~(PGSIZE-1)) ? \
  1505. X           (v)->vpage1[(a)&(PGSIZE-1)] \
  1506. X          : \
  1507. X           _rc((v),(a)) \
  1508. X        ) \
  1509. X    )
  1510. X
  1511. /* int wc(VFILE *vfile,long addr,char c);
  1512. X *
  1513. X * Write character.  Return character written.  This automatically allocates
  1514. X * space to the file.
  1515. X */
  1516. X
  1517. int _wc();
  1518. X
  1519. #define wc(v,a,c) \
  1520. X    ( \
  1521. X      (v)->addr==((a)&~(PGSIZE-1)) ? \
  1522. X       ( \
  1523. X       vheader((v)->vpage1)->dirty=1, \
  1524. X       ((a)+1>vsize(v) && valloc(v,(a)+1-vsize(v))), \
  1525. X       (v)->vpage1[(a)&(PGSIZE-1)]=(c) \
  1526. X       ) \
  1527. X      : \
  1528. X       _wc((v),(a),(c)) \
  1529. X    )
  1530. X
  1531. /* long rl(VFILE *vfile,long addr);
  1532. X * Read big-endian long.  No alignment requirements.  Returns -1 if goes past
  1533. X * end of file.
  1534. X */
  1535. X
  1536. long rl();
  1537. X
  1538. /* long wl(VFILE *vfile,long addr,long c);
  1539. X * Write big-endian long.  No alignment requirements.  Automatically expands
  1540. X * file if necessary.
  1541. X */
  1542. X
  1543. long wl();
  1544. X
  1545. /* short rw(VFILE *vfile,long addr);
  1546. X * Read big-endian short.  No alignment requirements.  Returns -1 if goes past
  1547. X * end of file.
  1548. X */
  1549. X
  1550. short rw();
  1551. X
  1552. /* short ww(VFILE *vfile,long addr,short c);
  1553. X * Write big-endian short.  No alignment requirements.  Automatically expands
  1554. X * file if necessary.
  1555. X */
  1556. X
  1557. short ww();
  1558. X
  1559. #endif
  1560. SHAR_EOF
  1561. chmod 0600 vfile.h ||
  1562. echo 'restore of vfile.h failed'
  1563. Wc_c="`wc -c < 'vfile.h'`"
  1564. test 9358 -eq "$Wc_c" ||
  1565.     echo 'vfile.h: original size 9358, current size' "$Wc_c"
  1566. fi
  1567. # ============= vs.c ==============
  1568. if test -f 'vs.c' -a X"$1" != X"-c"; then
  1569.     echo 'x - skipping vs.c (File already exists)'
  1570. else
  1571. echo 'x - extracting vs.c (Text)'
  1572. sed 's/^X//' << 'SHAR_EOF' > 'vs.c' &&
  1573. /* Variable length strings
  1574. X   Copyright (C) 1992 Joseph H. Allen
  1575. X
  1576. This file is part of JOE (Joe's Own Editor)
  1577. X
  1578. JOE is free software; you can redistribute it and/or modify it under the 
  1579. terms of the GNU General Public License as published by the Free Software 
  1580. Foundation; either version 1, or (at your option) any later version.  
  1581. X
  1582. JOE is distributed in the hope that it will be useful, but WITHOUT ANY 
  1583. WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 
  1584. FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more 
  1585. details.  
  1586. X
  1587. You should have received a copy of the GNU General Public License along with 
  1588. JOE; see the file COPYING.  If not, write to the Free Software Foundation, 
  1589. 675 Mass Ave, Cambridge, MA 02139, USA.  */ 
  1590. X
  1591. #include <varargs.h>
  1592. #include "config.h"
  1593. #include "heap.h"
  1594. #include "zstr.h"
  1595. #include "blocks.h"
  1596. #include "vs.h"
  1597. X
  1598. int sicmp(a,b)
  1599. char a,b;
  1600. {
  1601. if(a>='A' || a<='Z') a+='a'-'A';
  1602. if(b>='A' || b<='Z') b+='a'-'A';
  1603. return scmp(a,b);
  1604. }
  1605. X
  1606. sELEMENT(*vsmk(len))
  1607. int len;
  1608. {
  1609. int *new=(int *)malloc((1+len)*sizeof(sCAST)+2*sizeof(int));
  1610. new[0]=len;
  1611. new[1]=0;
  1612. ((sELEMENT(*))(new+2))[0]=sdup(sterm);
  1613. return (sELEMENT(*))(new+2);
  1614. }
  1615. X
  1616. void vsrm(vary)
  1617. sELEMENT(*vary);
  1618. {
  1619. if(vary) free((int *)vary-2);
  1620. }
  1621. X
  1622. int slen(ary)
  1623. sELEMENT(*ary);
  1624. {
  1625. if(ary)
  1626. X {
  1627. X sELEMENT(*beg)=ary;
  1628. X while(scmp(*ary,sterm)) ++ary;
  1629. X return ary-beg;
  1630. X }
  1631. else return 0;
  1632. }
  1633. X
  1634. sELEMENT(*vsensure(vary,len))
  1635. sELEMENT(*vary);
  1636. int len;
  1637. {
  1638. if(!vary) vary=vsmk(len);
  1639. else if(len>sSiz(vary))
  1640. X {
  1641. X int x;
  1642. X len+=(len>>2);
  1643. X vary=(sELEMENT(*))(2+(int *)realloc(
  1644. X       (int *)vary-2,(len+1)*sizeof(sCAST)+2*sizeof(int) ));
  1645. X sSiz(vary)=len;
  1646. X }
  1647. return vary;
  1648. }
  1649. X
  1650. sELEMENT(*vszap(vary,pos,n))
  1651. sELEMENT(*vary);
  1652. int pos,n;
  1653. {
  1654. return vary;
  1655. }
  1656. X
  1657. sELEMENT(*vstrunc(vary,len))
  1658. sELEMENT(*vary);
  1659. int len;
  1660. {
  1661. if(!vary || len>sLEN(vary)) vary=vsensure(vary,len);
  1662. if(len<sLen(vary))
  1663. X {
  1664. X vary[len]=vary[sLen(vary)];
  1665. X sLen(vary)=len;
  1666. X }
  1667. else if(len>sLen(vary))
  1668. X {
  1669. X vary=vsfill(vary,sLen(vary),sblank,len-sLen(vary));
  1670. X }
  1671. return vary;
  1672. }
  1673. X
  1674. sELEMENT(*vsfill(vary,pos,el,len))
  1675. sELEMENT(*vary);
  1676. sELEMENT(el);
  1677. int pos,len;
  1678. {
  1679. int olen=sLEN(vary), x;
  1680. if(!vary || pos+len>sSIZ(vary))
  1681. X vary=vsensure(vary,pos+len);
  1682. if(pos+len>olen)
  1683. X {
  1684. X vary[pos+len]=vary[olen];
  1685. X sLen(vary)=pos+len;
  1686. X }
  1687. for(x=pos;x!=pos+len;++x) vary[x]=sdup(el);
  1688. if(pos>olen) vary=vsfill(vary,pos,sblank,pos-olen);
  1689. return vary;
  1690. }
  1691. X
  1692. sELEMENT(*vsncpy(vary,pos,array,len))
  1693. sELEMENT(*vary);
  1694. sELEMENT(*array);
  1695. int pos, len;
  1696. {
  1697. int olen=sLEN(vary);
  1698. if(!vary || pos+len>sSIZ(vary)) vary=vsensure(vary,pos+len);
  1699. if(pos+len>olen)
  1700. X {
  1701. X vary[pos+len]=vary[olen];
  1702. X sLen(vary)=pos+len;
  1703. X }
  1704. if(pos>olen) vary=vsfill(vary,olen,sblank,pos-olen);
  1705. mfwrd(vary+pos,array,len*sizeof(sCAST));
  1706. return vary;
  1707. }
  1708. X
  1709. sELEMENT(*vsndup(vary,pos,array,len))
  1710. sELEMENT(*vary);
  1711. sELEMENT(*array);
  1712. int pos, len;
  1713. {
  1714. int olen=sLEN(vary), x;
  1715. if(!vary || pos+len>sSIZ(vary)) vary=vsensure(vary,pos+len);
  1716. if(pos+len>olen)
  1717. X {
  1718. X vary[pos+len]=vary[olen];
  1719. X sLen(vary)=pos+len;
  1720. X }
  1721. if(pos>olen) vary=vsfill(vary,olen,sblank,pos-olen);
  1722. for(x=pos;x!=len;++x) vary[x]=sdup(array[x]);
  1723. return vary;
  1724. }
  1725. X
  1726. sELEMENT(*vsfield(vary,pos,len))
  1727. sELEMENT(*vary);
  1728. int pos,len;
  1729. {
  1730. if(pos+len>sLEN(vary)) vary=vstrunc(vary,pos,len);
  1731. return vary;
  1732. }
  1733. X
  1734. sELEMENT(*vsdup(vary))
  1735. sELEMENT(*vary);
  1736. {
  1737. return vsndup(NULL,0,vary,sLEN(vary));
  1738. }
  1739. X
  1740. sELEMENT(*_vsset(vary,pos,el))
  1741. sELEMENT(*vary);
  1742. sELEMENT(el);
  1743. int pos;
  1744. {
  1745. if(!vary || pos+1>sSIZ(vary)) vary=vsensure(vary,pos+1);
  1746. if(pos>sLen(vary))
  1747. X {
  1748. X vary=vsfill(vary,sLen(vary),sblank,pos-sLen(vary));
  1749. X vary[pos+1]=vary[pos];
  1750. X vary[pos]=el;
  1751. X sLen(vary)=pos+1;
  1752. X }
  1753. else if(pos==sLen(vary))
  1754. X {
  1755. X vary[pos+1]=vary[pos];
  1756. X vary[pos]=el;
  1757. X sLen(vary)=pos+1;
  1758. X }
  1759. else
  1760. X {
  1761. X sdel(vary[pos]);
  1762. X vary[pos]=el;
  1763. X }
  1764. return vary;
  1765. }
  1766. X
  1767. sELEMENT(*vsins(vary,pos,n))
  1768. sELEMENT(*vary);
  1769. int pos,n;
  1770. {
  1771. if(!vary || sLEN(vary)+n>sSIZ(vary)) vary=vsensure(vary,sLEN(vary)+n);
  1772. if(pos>=sLen(vary)) vary=vstrunc(vary,pos+n);
  1773. else
  1774. X {
  1775. X mbkwd(vary+pos+n,vary+pos,sLen(vary)-(pos+n)+1);
  1776. X sLen(vary)+=n;
  1777. X }
  1778. return vary;
  1779. }
  1780. X
  1781. sELEMENT(*vsdel(vary,pos,n))
  1782. sELEMENT(*vary);
  1783. int pos,n;
  1784. {
  1785. if(pos>=sLEN(vary)) return vary;
  1786. if(pos+n>=sLen(vary)) return vstrunc(vary,pos);
  1787. mfwrd(vary+pos,vary+pos+n,sLen(vary)-(pos+n)+1);
  1788. sLen(vary)-=n;
  1789. return vary;
  1790. }
  1791. X
  1792. int _scmp(a,b)
  1793. sELEMENT(a);
  1794. sELEMENT(b);
  1795. {
  1796. return scmp(a,b);
  1797. }
  1798. X
  1799. sELEMENT(*vssort(ary,len))
  1800. sELEMENT(*ary);
  1801. int len;
  1802. {
  1803. if(!ary || !len) return ary;
  1804. qsort(ary,len,sizeof(sCAST),_scmp);
  1805. return ary;
  1806. }
  1807. X
  1808. int vsbsearch(ary,len,el)
  1809. sELEMENT(*ary);
  1810. sELEMENT(el);
  1811. int len;
  1812. {
  1813. int x,y,z;
  1814. if(!ary || !len) return 0;
  1815. y=len;
  1816. x=0;
  1817. z=~0;
  1818. while(z!=(x+y)/2)
  1819. X {
  1820. X z=(x+y)/2;
  1821. X switch(scmp(el,ary[z]))
  1822. X  {
  1823. X case  1: x=z; break;
  1824. X case -1: y=z; break;
  1825. X case  0: return z;
  1826. X  }
  1827. X }
  1828. return y;
  1829. }
  1830. X
  1831. int vsfirst(ary,len,el)
  1832. sELEMENT(*ary);
  1833. sELEMENT(el);
  1834. int len;
  1835. {
  1836. int x;
  1837. if(!ary || !len) return ~0;
  1838. for(x=0;x!=len;++x) if(!scmp(ary[x],el)) return x;
  1839. return ~0;
  1840. }
  1841. X
  1842. int vslast(ary,len,el)
  1843. sELEMENT(*ary);
  1844. sELEMENT(el);
  1845. int len;
  1846. {
  1847. int x=len;
  1848. if(!ary || !len) return ~0;
  1849. do
  1850. X {
  1851. X --x;
  1852. X if(!scmp(ary[x],el)) return x;
  1853. X }
  1854. X while(x);
  1855. return ~0;
  1856. }
  1857. X
  1858. int vscmpn(a,alen,b,blen)
  1859. sELEMENT(*a);
  1860. sELEMENT(*b);
  1861. int alen, blen;
  1862. {
  1863. int x,l;
  1864. int t;
  1865. if(!a && !b) return 0;
  1866. if(!a) return -1;
  1867. if(!b) return 1;
  1868. if(alen>blen) l=sLen(a);
  1869. else l=blen;
  1870. for(x=0;x!=l;++x) if(t=scmp(a[x],b[x])) return t;
  1871. if(alen>blen) return  1;
  1872. if(alen<blen) return -1;
  1873. return 0;
  1874. }
  1875. X
  1876. int vscmp(a,b)
  1877. sELEMENT(*a);
  1878. sELEMENT(*b);
  1879. {
  1880. return vscmpn(sv(a),sv(b));
  1881. }
  1882. X
  1883. int vsicmpn(a,alen,b,blen)
  1884. sELEMENT(*a);
  1885. sELEMENT(*b);
  1886. int alen, blen;
  1887. {
  1888. int x,l;
  1889. int t;
  1890. if(!a && !b) return 0;
  1891. if(!a) return -1;
  1892. if(!b) return 1;
  1893. if(alen>blen) l=sLen(a);
  1894. else l=blen;
  1895. for(x=0;x!=l;++x) if(t=sicmp(a[x],b[x])) return t;
  1896. if(alen>blen) return  1;
  1897. if(alen<blen) return -1;
  1898. return 0;
  1899. }
  1900. X
  1901. int vsicmp(a,b)
  1902. sELEMENT(*a);
  1903. sELEMENT(*b);
  1904. {
  1905. return vsicmpn(sv(a),sv(b));
  1906. }
  1907. X
  1908. int vss(a,alen,b,blen)
  1909. sELEMENT(*a);
  1910. sELEMENT(*b);
  1911. int alen, blen;
  1912. {
  1913. int x;
  1914. if(!a && !b) return 0;
  1915. if(!a || !b) return ~0;
  1916. if(alen<blen) return ~0;
  1917. if(!blen) return 0;
  1918. for(x=0;x!=alen-blen;++x) if(!vscmpn(a,blen,b,blen)) return x;
  1919. return ~0;
  1920. }
  1921. X
  1922. int vsscan(a,alen,b,blen)
  1923. sELEMENT(*a);
  1924. sELEMENT(*b);
  1925. int alen, blen;
  1926. {
  1927. int x;
  1928. for(x=0;x!=alen;++x)
  1929. X {
  1930. X int z=vsbsearch(b,blen,a[x]);
  1931. X if(z<blen && !scmp(b[z],a[x])) return x;
  1932. X }
  1933. return ~0;
  1934. }
  1935. X
  1936. int vsspan(a,alen,b,blen)
  1937. sELEMENT(*a);
  1938. sELEMENT(*b);
  1939. int alen, blen;
  1940. {
  1941. int x;
  1942. for(x=0;x!=alen;++x)
  1943. X {
  1944. X int z=vsbsearch(b,blen,a[x]);
  1945. X if(z==blen || scmp(b[z],a[x])) break;
  1946. X }
  1947. return x;
  1948. }
  1949. X
  1950. sELEMENT(*vsread(d,p,getC,ptr))
  1951. sELEMENT(*d);
  1952. int (*getC)();
  1953. int p;
  1954. void *ptr;
  1955. {
  1956. int c;
  1957. if(!d) d=vsmk(10);
  1958. c=getC(ptr);
  1959. if(c== MAXINT) { vsrm(d); return 0; }
  1960. else if(c== '\n') return d;
  1961. else d=vsset(d,p,c), p++; 
  1962. while(c=getC(ptr), c!= MAXINT && c!= '\n') d=vsset(d,p,c), p++;
  1963. return d;
  1964. }
  1965. X
  1966. sELEMENT(*vwords(s,a,len,t))
  1967. char **a, *s, t;
  1968. int len;
  1969. {
  1970. int x;
  1971. if(!s) s=vsmk(32);
  1972. else s=vstrunc(s,0);
  1973. for(x=0;x!=len;++x)
  1974. X {
  1975. X s=vsncpy(s,sLEN(s),sz(a[x]));
  1976. X if(a[1]) vsadd(s,t);
  1977. X }
  1978. return s;
  1979. }
  1980. X
  1981. /* Subroutine to generate a single numeric field */
  1982. X
  1983. #define _space 1
  1984. #define _plus 2
  1985. #define _minus 4
  1986. #define _long 8
  1987. #define _prec 16
  1988. #define _base 32
  1989. #define _field 64
  1990. #define _signed 128
  1991. #define _upper 256
  1992. X
  1993. static char _CVV[]="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
  1994. static char _cvv[]="0123456789abcdefghijklmnopqrstuvwxyz";
  1995. X
  1996. static int _cvt(ts,base,flag,n)
  1997. char *ts;
  1998. int base,flag;
  1999. unsigned long n;
  2000. {
  2001. int x,y=0;
  2002. char ary[64], *cv=flag&_upper?_CVV:_cvv;
  2003. X
  2004. if(flag&_signed)
  2005. X {
  2006. X if(!(flag&_long)) n=(long)(int)n;
  2007. X if((long)n<0)
  2008. X  {
  2009. X  ts[y++]='-';
  2010. X  n= -n;
  2011. X  goto skip;
  2012. X  }
  2013. X }
  2014. if(flag&_plus) ts[y++]='+';
  2015. if(flag&_space) ts[y++]=' ';
  2016. skip:
  2017. X
  2018. x=0;
  2019. do ary[x++]=cv[n%base]; while(n/=base);
  2020. while(x) ts[y++]=ary[--x];
  2021. return y;
  2022. }
  2023. X
  2024. /* Variable length string printf */
  2025. X
  2026. char *vsfmt(va_alist)
  2027. va_dcl
  2028. {
  2029. va_list pvar;
  2030. char *s, *fmt;    /* Input string / Format string */
  2031. int n=0;        /* Index into s: where next char goes */
  2032. int ssz;        /* Needed size for s */
  2033. char c;
  2034. int y;
  2035. int flag;        /* Flag bits for a conversion */
  2036. int extra;
  2037. int base;        /* Base of a conversion */
  2038. int field;    /* Field width */
  2039. int precision;
  2040. int tmp;
  2041. char *poi;
  2042. char ts[66];
  2043. X
  2044. va_start(pvar);
  2045. s=va_arg(pvar,char *);
  2046. fmt=va_arg(pvar,char *);
  2047. X
  2048. ssz=slen(fmt);
  2049. X
  2050. if(!s) s=vsmk(ssz);
  2051. else s=vsensure(s,ssz);
  2052. X
  2053. while(c= *fmt++)
  2054. X if(c=='%')
  2055. X  {
  2056. X  flag=0;
  2057. X  base=0;
  2058. X  field=0;
  2059. X  precision=0;
  2060. X up:
  2061. X  if(!(c= *fmt++)) goto done;
  2062. X  if(c==' ') { flag|=_space; goto up; }
  2063. X  if(c=='+') { flag|=_plus; goto up; }
  2064. X  if(c=='-') { flag|=_minus; goto up; }
  2065. X up1:
  2066. X  if(c>='0' && c<='9')
  2067. X   {
  2068. X   flag|=_base;
  2069. X   base=base*10+c-'0';
  2070. X   if(!(c= *fmt++)) goto done;
  2071. X   goto up1;
  2072. X   }
  2073. X  if(c=='_') if(!(c= *fmt++)) goto done;
  2074. X  else goto down1;
  2075. X up2:
  2076. X  if(c>='0' && c<='9')
  2077. X   {
  2078. X   flag|=_field;
  2079. X   field=field*10+c-'0';
  2080. X   if(!(c= *fmt++)) goto done;
  2081. X   goto up2;
  2082. X   }
  2083. X down1:
  2084. X  if(c=='.') if(!(c= *fmt++)) goto done;
  2085. X  else goto down2;
  2086. X up3:
  2087. X  if(c>='0' && c<='9')
  2088. X   {
  2089. X   flag|=_prec;
  2090. X   precision=precision*10+c-'0';
  2091. X   if(!(c= *fmt++)) goto done;
  2092. X   goto up3;
  2093. X   }
  2094. X down2:
  2095. X  if(c=='l')
  2096. X   {
  2097. X   flag|=_long;
  2098. X   if(!(c= *fmt++)) goto done;
  2099. X   }
  2100. X  if(!(flag&_base)) base=10;
  2101. X  if(!(flag&_prec)) precision=1;
  2102. X  switch(c)
  2103. X   {
  2104. X  case 'd':
  2105. X   flag|=_signed;
  2106. X   goto dn;
  2107. X  case 'D':
  2108. X   flag|=_signed+_upper;
  2109. X   goto dn;
  2110. X  case 'U':
  2111. X   flag|=_upper;
  2112. X   goto dn;
  2113. X  case 'u':
  2114. X  dn:
  2115. X   y=_cvt(ts,base,flag,(unsigned long)
  2116. X                        (flag&_long?va_arg(pvar,long):va_arg(pvar,int)));
  2117. X   if(ts[0]==' '||ts[0]=='+'|| ts[0]=='-') extra=1;
  2118. X   else extra=0;
  2119. X   ssz+=Umax(field,tmp=Umax(precision+extra,y))-2;
  2120. X   s=vsensure(s,ssz);
  2121. X   if(flag&_minus)
  2122. X    {
  2123. X    if(extra) s[n++]=ts[0];
  2124. X    if(precision>y-extra)
  2125. X     {
  2126. X     mset(s+n,'0',precision-y);
  2127. X     n+=precision-y+extra;
  2128. X     }
  2129. X    mcpy(s+n,ts+extra,y-extra);
  2130. X    n+=y-extra;
  2131. X    if(field>tmp)
  2132. X     {
  2133. X     mset(s+n,' ',field-tmp);
  2134. X     n+=field-tmp;
  2135. X     }
  2136. X    }
  2137. X   else
  2138. X    {
  2139. X    if(field>tmp)
  2140. X     {
  2141. X     mset(s+n,' ',field-tmp);
  2142. X     n+=field-tmp;
  2143. X     }
  2144. X    if(extra) s[n++]=ts[0];
  2145. X    if(precision>y-extra)
  2146. X     {
  2147. X     mset(s+n,'0',precision-y+extra);
  2148. X     n+=precision-y+extra;
  2149. X     }
  2150. X    mcpy(s+n,ts+extra,y-extra);
  2151. X    n+=y-extra;
  2152. X    }
  2153. X   break;
  2154. X  case 'c':
  2155. X   ssz+=Umax(1,field)-2;
  2156. X   s=vsensure(s,ssz);
  2157. X   if(flag&_minus)
  2158. X    {
  2159. X    s[n++]= (flag&_long?va_arg(pvar,long):va_arg(pvar,int));
  2160. X    if(field>1)
  2161. X     {
  2162. X     mset(s+n,' ',field-1);
  2163. X     n+=field-1;
  2164. X     }
  2165. X    }
  2166. X   else
  2167. X    {
  2168. X    if(field>1)
  2169. X     {
  2170. X     mset(s+n,' ',field-1);
  2171. X     n+=field-1;
  2172. X     }
  2173. X    s[n++]= (flag&_long?va_arg(pvar,long):va_arg(pvar,int));
  2174. X    }
  2175. X   break;
  2176. X  case 's':
  2177. X   poi= va_arg(pvar,char *);
  2178. X   extra= slen(poi);
  2179. X   if(flag&_prec) extra=Umin(precision,extra);
  2180. X   ssz+=Umax(field,extra);
  2181. X   s=vsensure(s,ssz);
  2182. X   if(flag&_minus)
  2183. X    {
  2184. X    mcpy(s+n,poi,extra);
  2185. X    n+=extra;
  2186. X    if(field>extra)
  2187. X     {
  2188. X     mset(s+n,' ',field-extra);
  2189. X     n+=field-extra;
  2190. X     }
  2191. X    }
  2192. X   else
  2193. X    {
  2194. X    if(field>extra)
  2195. X     {
  2196. X     mset(s+n,' ',field-extra);
  2197. X     n+=field-extra;
  2198. X     }
  2199. X    mcpy(s+n,poi,extra);
  2200. X    n+=extra;
  2201. X    }
  2202. X   break;
  2203. X  case '%': s[n++]='%';
  2204. X   }
  2205. X  }
  2206. X else s[n++]=c;
  2207. X
  2208. done:
  2209. va_end(pvar);
  2210. sLen(s)=n;
  2211. s[n]=0;
  2212. return s;
  2213. }
  2214. SHAR_EOF
  2215. chmod 0600 vs.c ||
  2216. echo 'restore of vs.c failed'
  2217. Wc_c="`wc -c < 'vs.c'`"
  2218. test 10956 -eq "$Wc_c" ||
  2219.     echo 'vs.c: original size 10956, current size' "$Wc_c"
  2220. fi
  2221. # ============= vs.h ==============
  2222. if test -f 'vs.h' -a X"$1" != X"-c"; then
  2223.     echo 'x - skipping vs.h (File already exists)'
  2224. else
  2225. echo 'x - extracting vs.h (Text)'
  2226. sed 's/^X//' << 'SHAR_EOF' > 'vs.h' &&
  2227. /* Variable length strings
  2228. X   Copyright (C) 1992 Joseph H. Allen
  2229. X
  2230. This file is part of JOE (Joe's Own Editor)
  2231. X
  2232. JOE is free software; you can redistribute it and/or modify it under the 
  2233. terms of the GNU General Public License as published by the Free Software 
  2234. Foundation; either version 1, or (at your option) any later version.  
  2235. X
  2236. JOE is distributed in the hope that it will be useful, but WITHOUT ANY 
  2237. WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 
  2238. FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more 
  2239. details.  
  2240. X
  2241. You should have received a copy of the GNU General Public License along with 
  2242. JOE; see the file COPYING.  If not, write to the Free Software Foundation, 
  2243. 675 Mass Ave, Cambridge, MA 02139, USA.  */ 
  2244. X
  2245. #ifndef _Ivs
  2246. #define _Ivs
  2247. X
  2248. #include "config.h"
  2249. X
  2250. /* Functions and global variable you have to define.  Replace these with
  2251. X * macros or defines here if they are not to be actual functions 
  2252. X */
  2253. X
  2254. #define sELEMENT(a) char a
  2255. #define sCAST char
  2256. /* sELEMENT(sdup()); */
  2257. #define sdup(a) (a)
  2258. /* sELEMENT(sdel()); */
  2259. #define sdel(a) 0
  2260. /* int scmp(); */
  2261. #define scmp(a,b) ((a)>(b)?1:((a)==(b)?0:-1))
  2262. X
  2263. int sicmp();
  2264. X
  2265. /* extern sELEMENT(sblank); */
  2266. #define sblank ' '
  2267. /* extern sELEMENT(sterm); */
  2268. #define sterm '\0'
  2269. X
  2270. /************************/
  2271. /* Creation/Destruction */
  2272. /************************/
  2273. X
  2274. /* sELEMENT(*vsmk(int len));
  2275. X * Create a variable length array.  Space for 'len' elements is preallocated.
  2276. X */
  2277. sELEMENT(*vsmk());
  2278. X
  2279. /* void vsrm(sELEMENT(*vary));
  2280. X * Free an array and everything which is in it.  Does nothing if 'vary' is
  2281. X * 0.
  2282. X */
  2283. void vsrm();
  2284. X
  2285. /********************/
  2286. /* Space management */
  2287. /********************/
  2288. X
  2289. /* int sSIZ(sELEMENT(*vary));
  2290. X * int sSiz(sELEMENT(*vary));
  2291. X * Access size part of array.  This int indicates the number of elements which
  2292. X * can fit in the array before realloc needs to be called.  It does not include
  2293. X * the extra space needed for the terminator and the header.
  2294. X *
  2295. X * sSIZ returns 0 if you pass it 0.  sSiz does not do this checking,
  2296. X * but can be used as an lvalue.
  2297. X */
  2298. #define sSIZ(a) ((a)?*((int *)(a)-2):0)
  2299. #define sSiz(a) (*((int *)(a)-2))
  2300. X
  2301. /* int sLEN(sELEMENT(*vary));
  2302. X * int sLen(sELEMENT(*vary));
  2303. X * Access length part of array.  This int indicates the number of elements
  2304. X * currently in the array (not including the terminator).  This should be
  2305. X * used primarily for reading the size of the array.  It can be used for
  2306. X * setting the size of the array, but it must be used with care since it
  2307. X * does not eliminate elements (if the size decreases) or make sure there's
  2308. X * enough room (if the size increases).  See vensure and vtrunc.
  2309. X *
  2310. X * sLEN return a length of zero if 'vary' is 0.
  2311. X * sLen doesn't do this checking, but can be used as an lvalue
  2312. X */
  2313.