1 /*
2 * $Id: misc.c,v 1.5 2004/05/31 16:08:41 andrew_belov Exp $
3 * ---------------------------------------------------------------------------
4 * Various system-independent routines are kept here. This module is needed if
5 * the ENVIRON.C is linked, since both of them cross-reference each other.
6 *
7 */
8
9 #include "arj.h"
10
11 DEBUGHDR(__FILE__) /* Debug information block */
12
13 /* Compact filelist array */
14
15 #if SFX_LEVEL>=ARJSFXV
16 static unsigned char FAR * FAR *flist_array=NULL;
17 static FILE_COUNT cfa_allocated; /* # of allocated blocks */
18 #endif
19
20 /* Extended wildcard specifiers */
21
22 static char xwild_symbols[]="?*[]^";
23
24 /* Forward references */
25
26 static int xwild_propagate(char *wcstr, char *str);
27
28 #if SFX_LEVEL>=ARJ
29
30 /* Dumb extended wildcard lookup routine */
31
xwild_lookup(char * str)32 static int xwild_lookup(char *str)
33 {
34 char *p;
35 char c;
36
37 for(p=str; *p!='\0'; p++)
38 {
39 c=*p;
40 if(c=='*'||c=='?'||c=='['||c=='^')
41 return(XW_OK);
42 }
43 return(XW_NONE);
44 }
45
46 /* An extended wildcard parser */
47
xwild_parser(char * wcstr,int * rc)48 static int xwild_parser(char *wcstr, int *rc)
49 {
50 char *p;
51 char c;
52
53 *rc=XWP_NONE;
54 for(p=wcstr; *p!='\0'; p++)
55 {
56 c=*p;
57 if(c=='^')
58 {
59 p++;
60 if(*p=='\0')
61 {
62 *rc=XWP_TERM;
63 return(XW_NONE);
64 }
65 }
66 else if(c=='[')
67 {
68 p++;
69 if((c=*p)==']')
70 {
71 *rc=XWP_NBRACKET;
72 return(XW_NONE);
73 }
74 if(c=='\0')
75 {
76 *rc=XWP_OBRACKET;
77 return(XW_NONE);
78 }
79 while(*p!=']')
80 {
81 if(*p=='^')
82 {
83 p++;
84 if((c=*p)=='\0')
85 {
86 *rc=XWP_TERM;
87 return(XW_NONE);
88 }
89 }
90 else
91 p++;
92 if((c=*p)=='\0')
93 {
94 *rc=XWP_OBRACKET;
95 return(XW_NONE);
96 }
97 if(*p=='-')
98 {
99 c=*++p;
100 if(c=='\0'||c==']')
101 {
102 *rc=XWP_MDASH;
103 return(XW_NONE);
104 }
105 if(*p=='^')
106 p++;
107 if((c=*p++)=='\0')
108 {
109 *rc=XWP_TERM;
110 return(XW_NONE);
111 }
112 }
113 }
114 }
115 else
116 p++;
117 }
118 return(XW_OK);
119 }
120
121 /* Extended wildcard expansion and matching routine */
122
xwild_match(char * wcstr,char * str)123 static int xwild_match(char *wcstr, char *str)
124 {
125 char *wptr;
126 char *sptr;
127 char c, sc;
128 char fchar;
129 int xchar;
130 int pflag;
131 int unproc;
132 char xc, xpc; /* Wildcard processed characters */
133
134 wptr=wcstr;
135 sptr=str;
136 while(*wptr!='\0')
137 {
138 if((c=*sptr)=='\0')
139 return((*wptr=='*'&&*++wptr=='\0')?XW_OK:XW_OWC);
140 fchar=*wptr;
141 switch(fchar)
142 {
143 case '*':
144 return(xwild_propagate(wptr, sptr));
145 case '[':
146 xchar=0;
147 wptr++;
148 if(*wptr=='!')
149 {
150 xchar=1;
151 wptr++;
152 }
153 unproc=0;
154 pflag=1;
155 while(pflag!=0)
156 {
157 if(*wptr!=']')
158 {
159 c=(*wptr=='^')?*++wptr:*wptr; /* Escape character */
160 xpc=xc=toupper(c);
161 if(c=='\0')
162 return(XW_TERM);
163 wptr++;
164 if(*wptr=='-')
165 {
166 c=*++wptr;
167 if(c=='\0'&&c!=']')
168 return(XW_TERM);
169 xc=toupper(c);
170 if(xc=='^')
171 {
172 c=*++wptr;
173 xc=toupper(c);
174 if(xc=='\0')
175 return(XW_TERM);
176 }
177 wptr++;
178 }
179 sc=toupper(*sptr);
180 if((xpc>=xc&&sc>=xc&&sc<=xpc)||(sc>=xpc&&sc<=xc))
181 {
182 unproc=1;
183 pflag=0;
184 }
185 }
186 else
187 pflag=0;
188 }
189 if((xchar!=0&&unproc)||(xchar==0&&!unproc))
190 return(XW_UNPROC);
191 if(!unproc)
192 break;
193 /* Skip the rest, applying usual check-ups */
194 while(*wptr!=']')
195 {
196 if(*wptr=='\0')
197 return(XW_TERM);
198 if(*wptr=='^')
199 {
200 if(*++wptr=='\0')
201 return(XW_TERM);
202 }
203 wptr++;
204 }
205 break;
206 case '?':
207 break; /* Skip the comparison */
208 case '^':
209 wptr++;
210 if(*wptr=='\0')
211 return(XW_TERM);
212 default: /* fallthru */
213 if(toupper(*wptr)!=toupper(*sptr))
214 return(XW_MISMATCH);
215 break;
216 }
217 wptr++;
218 sptr++;
219 }
220 return((*sptr=='\0')?XW_OK:XW_PREM_END);
221 }
222
223 /* Propagates (expands) wildcard markers */
224
xwild_propagate(char * wcstr,char * str)225 static int xwild_propagate(char *wcstr, char *str)
226 {
227 int rc=0;
228 char c;
229
230 while(*wcstr=='?'||*wcstr=='*')
231 {
232 if(*wcstr=='?')
233 {
234 if(*++str=='\0')
235 return(XW_OWC);
236 }
237 wcstr++;
238 }
239 if(*wcstr=='\0')
240 return(XW_OK);
241 if((c=*wcstr)=='^')
242 {
243 if((c=*++wcstr)=='\0')
244 return(XW_TERM);
245 }
246 do
247 {
248 if(toupper(c)==toupper(*str)||c=='[')
249 rc=xwild_match(wcstr, str);
250 if(*str++=='\0')
251 rc=XW_OWC;
252 } while(rc!=XW_OK&&rc!=XW_OWC&&rc!=XW_TERM);
253 return(rc);
254 }
255
256 /* Wildcard matching routine wrapper (provides boolean RCs) */
257
xwild_compare(char * wcstr,char * str)258 static int xwild_compare(char *wcstr, char *str)
259 {
260 int xrc;
261
262 xrc=xwild_match(wcstr, str);
263 return((xrc==XW_OK)?XW_OK:XW_NONE);
264 }
265
266 /* Change all UNIX-style path specifiers to DOS-style ones in a given string */
267
unix_path_to_dos(char * path)268 void unix_path_to_dos(char *path)
269 {
270 int i=0;
271 if(translate_unix_paths)
272 {
273 while(path[i]!='\0')
274 {
275 if(path[i]==PATHSEP_UNIX)
276 path[i]=PATHSEP_DEFAULT;
277 i++;
278 }
279 }
280 }
281
282 #endif
283
284 #if SFX_LEVEL>=ARJSFXV
285
286 /* Allocate a block of memory that will exactly fit the length of string,
287 and copy the string into this newly-created block. */
288
malloc_str(char * str)289 void *malloc_str(char *str)
290 {
291 return(strcpy((char *)malloc_msg(strlen(str)+1), str));
292 }
293
294 #endif
295
296 #if SFX_LEVEL>=ARJ
297
298 /* The same as malloc_str, but it allocates near memory for far strings */
299
malloc_far_str(char FAR * str)300 void *malloc_far_str(char FAR *str)
301 {
302 char *k;
303
304 k=malloc_msg(far_strlen(str)+1);
305 far_strcpy((char FAR *)k, str);
306 return(k);
307 }
308
309 #endif
310
311 #if SFX_LEVEL>=ARJ
312
313 /* Converts current time to a standard timestamp */
314
cur_time_stamp(struct timestamp * dest)315 void cur_time_stamp(struct timestamp *dest)
316 {
317 time_t cur_unixtime;
318
319 cur_unixtime=time(NULL);
320 ts_store(dest, OS_UNIX, cur_unixtime);
321 }
322
323 /* A strchr() function for far strings */
324
325 #if COMPILER!=MSC&&defined(TILED)
far_strchr(char FAR * str,char chr)326 char FAR *far_strchr(char FAR *str, char chr)
327 {
328 while(str[0]!=chr)
329 {
330 if(str[0]=='\0') return(NULL);
331 str++;
332 }
333 return(str);
334 }
335 #endif
336
337 #endif
338
339 #if SFX_LEVEL>=ARJSFXV||defined(REARJ)
340
341 /* A strcmp() function for far strings */
342
343 #if COMPILER!=MSC&&defined(TILED)
far_strcmp(char FAR * str1,char FAR * str2)344 int far_strcmp(char FAR *str1, char FAR *str2)
345 {
346 unsigned int k;
347
348 for(k=0; str1[k]!='\0'&&str2[k]!='\0'; k++);
349 return((int)(str1[k]-str2[k]));
350 }
351 #endif
352
353 /* A stricmp() function for far strings */
354
355 #if COMPILER!=MSC&&defined(TILED)
far_stricmp(char FAR * str1,char FAR * str2)356 int far_stricmp(char FAR *str1, char FAR *str2)
357 {
358 unsigned int k;
359
360 for(k=0; toupper(str1[k]!='\0')&&toupper(str2[k]!='\0'); k++);
361 return(toupper(str1[k])-toupper(str2[k]));
362 }
363 #endif
364
365 #endif
366
367 #if SFX_LEVEL>=ARJ||defined(REARJ)
368
369 /* A strcat() function for far strings */
370
371 #if COMPILER!=MSC&&defined(TILED)
far_strcat(char FAR * dest,char FAR * src)372 char FAR *far_strcat(char FAR *dest, char FAR *src)
373 {
374 char FAR *tmp_dest;
375
376 tmp_dest=dest;
377 while(tmp_dest[0]!='\0')
378 tmp_dest++;
379 do
380 (tmp_dest++)[0]=src[0];
381 while((src++)[0]!='\0');
382 return(dest);
383 }
384 #endif
385
386 #endif
387
388 #if SFX_LEVEL>=ARJSFXV||defined(REARJ)
389
390 /* A strcpy() function for far strings */
391
392 #if COMPILER!=MSC&&defined(TILED)
far_strcpy(char FAR * dest,char FAR * src)393 char FAR *far_strcpy(char FAR *dest, char FAR *src)
394 {
395 int k;
396
397 for(k=0; src[k]!='\0'; k++)
398 dest[k]=src[k];
399 dest[k]='\0';
400 return(dest);
401 }
402 #endif
403
404 #endif
405
406 #if SFX_LEVEL>=ARJ
407
408 /* A strlen() function for far strings */
409
410 #if COMPILER!=MSC&&defined(TILED)
far_strlen(char FAR * str)411 unsigned int far_strlen(char FAR *str)
412 {
413 unsigned int k=0;
414
415 while(str[k]!='\0')
416 k++;
417 return(k);
418 }
419 #endif
420
421 #endif
422
423 #if SFX_LEVEL>=ARJSFXV
424
425 /* Fills a buffer with the specified value */
426
427 #if COMPILER!=MSC&&defined(TILED)
far_memset(void FAR * buf,int filler,unsigned int size)428 void FAR *far_memset(void FAR *buf, int filler, unsigned int size)
429 {
430 char FAR *p;
431 unsigned int l;
432
433 p=(char FAR *)buf;
434 for(l=0; l<size; l++)
435 *p++=(char)filler;
436 return(buf);
437 }
438 #endif
439
440 #endif
441
442 #if SFX_LEVEL>=ARJSFXV
443
444 /* Copies at most n characters */
445
far_strcpyn(char FAR * dest,char FAR * src,int limit)446 char FAR *far_strcpyn(char FAR *dest, char FAR *src, int limit)
447 {
448 int k;
449
450 for(k=1; k<limit&&src[0]!='\0'; k++)
451 {
452 (dest++)[0]=(src++)[0];
453 }
454 if(limit>0)
455 dest[0]='\0';
456 return(dest);
457 }
458
459 #endif
460
461 #if SFX_LEVEL>=ARJSFX
462
463 /* Converts the given string to 7-bit */
464
to_7bit(char * str)465 void to_7bit(char *str)
466 {
467 while(*str!='\0')
468 *str++&=0x7F;
469 }
470
471 #endif
472
473 #if SFX_LEVEL>=ARJSFX||defined(REARJ)
474
475 /* Convert a string to uppercase, depending on locale */
476
strupper(char * s)477 void strupper(char *s)
478 {
479 #if SFX_LEVEL>=ARJSFXV||defined(REARJ)
480 toupper_loc(s, strlen(s));
481 #else
482 while(*s!='\0')
483 {
484 *s=toupper(*s);
485 s++;
486 }
487 #endif
488 }
489
490 #endif
491
492 #if SFX_LEVEL>=ARJSFXV
493
494 /* Convert a string to lowercase (note: no locale hack here - the one in
495 strupper() was made exclusively for filename matching under DOS) */
496
strlower(char * s)497 void strlower(char *s)
498 {
499 while(*s!='\0')
500 {
501 *s=tolower(*s);
502 s++;
503 }
504 }
505
506 #endif
507
508 #if SFX_LEVEL>=ARJ
509
510 /* Finds an entry in the filelist, returns 1 if matched. Wildcards allowed. */
511
flist_find(struct flist_root * root,char * name)512 int flist_find(struct flist_root *root, char *name)
513 {
514 char tmp_name[FILENAME_MAX]; /* Hash filename storage */
515 char n_path[FILENAME_MAX], f_path[FILENAME_MAX];
516 FILE_COUNT entry;
517 int pathname_length;
518 int tmp_pathname_length;
519
520 if(root==NULL)
521 return(0);
522 pathname_length=split_name(name, n_path, NULL);
523 for(entry=0; entry<root->files; entry++)
524 {
525 flist_retrieve(tmp_name, NULL, root, entry);
526 tmp_pathname_length=split_name(tmp_name, f_path, NULL);
527 if(marksym_expansion)
528 {
529 if(tmp_pathname_length!=0&&strlen(tmp_name)==tmp_pathname_length&&xwild_compare(f_path, n_path)==XW_OK)
530 return(1);
531 if(tmp_pathname_length==0||xwild_compare(f_path, n_path)==XW_OK)
532 {
533 if(xwild_compare(tmp_name+tmp_pathname_length, name+pathname_length)==XW_OK)
534 return(1);
535 }
536 }
537 else
538 {
539 /* If it was a directory specification, return OK */
540 if(tmp_pathname_length!=0&&strlen(tmp_name)==tmp_pathname_length&&!strncmp_os(tmp_name, name, tmp_pathname_length))
541 return(1);
542 /* For filename specifications, proceed with compare */
543 if(tmp_pathname_length==0||(tmp_pathname_length==pathname_length&&!strncmp_os(tmp_name, name, tmp_pathname_length)))
544 if(match_wildcard(&name[pathname_length], &tmp_name[tmp_pathname_length]))
545 return(1);
546 }
547 }
548 return(0);
549 }
550
551 /* Checks if a file already exists in the archive */
552
flist_is_in_archive(struct flist_root * root,char * name)553 int flist_is_in_archive(struct flist_root *root, char *name)
554 {
555 char tmp_name[CCHMAXPATHCOMP]; /* For names retrieved from the hash */
556 char case_name[CCHMAXPATHCOMP]; /* and for converting them to u-case */
557 FILE_COUNT entry;
558
559 for(entry=0; entry<root->files; entry++)
560 {
561 if(cfa_get(entry)==FLFLAG_PROCESSED)
562 {
563 flist_retrieve(tmp_name, NULL, root, entry);
564 default_case_path(case_name, tmp_name);
565 if(!stricmp(name, case_name))
566 return(1);
567 }
568 }
569 return(0);
570 }
571
572 /* Returns 1 if the file properties given match the current search narrowing
573 criteria (such as "same or newer", and so on) */
574
match_attrib(struct file_properties * properties)575 int match_attrib(struct file_properties *properties)
576 {
577 int matched;
578
579 /* First, check if the attributes match */
580 if(filter_attrs)
581 {
582 matched=0;
583 if(file_attr_mask&TAG_DIREC&&properties->type==ARJT_DIR)
584 matched=1;
585 if(file_attr_mask&TAG_UXSPECIAL&&properties->type==ARJT_UXSPECIAL)
586 matched=1;
587 if(file_attr_mask&TAG_NORMAL&&
588 !(properties->attrib&FATTR_DIREC)&&
589 !(properties->attrib&FATTR_RDONLY)&&
590 !(properties->attrib&FATTR_SYSTEM)&&
591 !(properties->attrib&FATTR_HIDDEN)&&
592 properties->type!=ARJT_UXSPECIAL)
593 matched=1;
594 if(file_attr_mask&TAG_RDONLY&&properties->attrib&FATTR_RDONLY)
595 matched=1;
596 if(file_attr_mask&TAG_HIDDEN&&properties->attrib&FATTR_HIDDEN)
597 matched=1;
598 if(file_attr_mask&TAG_SYSTEM&&properties->attrib&FATTR_SYSTEM)
599 matched=1;
600 if(file_attr_mask&TAG_ARCH&&!(properties->attrib&FATTR_ARCH))
601 return(0);
602 if(file_attr_mask&TAG_NOT_ARCH&&properties->attrib&FATTR_ARCH)
603 return(0);
604 if(!matched)
605 return(0);
606 }
607 if(filter_fa_arch==FAA_BACKUP||filter_fa_arch==FAA_BACKUP_CLEAR)
608 {
609 if(!properties->isarchive)
610 return(0);
611 }
612 /* Now, check the file against the time limits for it */
613 /* ftime */
614 if(ts_valid(tested_ftime_newer)&&(filter_same_or_newer==TCHECK_NDAYS||filter_same_or_newer==TCHECK_FTIME))
615 {
616 if(properties->ftime<ts_native(&tested_ftime_newer, OS))
617 return(0);
618 }
619 if(ts_valid(tested_ftime_older)&&(filter_older==TCHECK_NDAYS||filter_older==TCHECK_FTIME))
620 {
621 if(properties->ftime>=ts_native(&tested_ftime_older, OS))
622 return(0);
623 }
624 /* ctime */
625 if(ts_valid(tested_ftime_newer)&&filter_same_or_newer==TCHECK_CTIME)
626 {
627 if(properties->ctime<ts_native(&tested_ftime_newer, OS))
628 return(0);
629 }
630 if(ts_valid(tested_ftime_older)&&filter_older==TCHECK_CTIME)
631 {
632 if(properties->ctime>=ts_native(&tested_ftime_older, OS))
633 return(0);
634 }
635 /* atime */
636 if(ts_valid(tested_ftime_newer)&&filter_same_or_newer==TCHECK_ATIME)
637 {
638 if(properties->atime<ts_native(&tested_ftime_newer, OS))
639 return(0);
640 }
641 if(ts_valid(tested_ftime_older)&&filter_older==TCHECK_ATIME)
642 {
643 if(properties->atime>=ts_native(&tested_ftime_older, OS))
644 return(0);
645 }
646 return(1);
647 }
648
649 /* Frees memory allocated for the hash table */
650
flist_cleanup(struct flist_root * root)651 void flist_cleanup(struct flist_root *root)
652 {
653 flist_cleanup_proc(root);
654 }
655
656 /* Adds an entry to the filelist if it does not already exist. Returns -1 if
657 an error occured. */
658
flist_add(struct flist_root * root,struct flist_root * search_flist,char * name,FILE_COUNT * count,struct file_properties * properties)659 int flist_add(struct flist_root *root, struct flist_root *search_flist, char *name, FILE_COUNT *count, struct file_properties *properties)
660 {
661 FILE_COUNT i;
662
663 if(search_flist!=NULL)
664 {
665 /* If an existing entry has been found, don't add anything */
666 if(flist_find(search_flist, name))
667 {
668 if(count!=NULL)
669 (*count)++;
670 return(0);
671 }
672 }
673 if(root!=NULL&&root->fsptr!=NULL&&!xwild_compare(root->fsptr, name))
674 {
675 if(count!=NULL)
676 (*count)++;
677 return(0);
678 }
679 if(properties!=NULL&&root==&flist_main&&!match_attrib(properties))
680 {
681 if(count!=NULL)
682 (*count)++;
683 return(0);
684 }
685 #if TARGET==UNIX
686 /* Resolve hard links if there are any */
687 if(properties!=NULL&&
688 properties->l_search.refcount>1&&
689 !suppress_hardlinks)
690 link_search(&l_entries, &properties->l_search, properties, root->files);
691 #endif
692 return(add_entry(root, name, count, properties));
693 }
694
695 /* Initializes the filelist storage structures */
696
flist_init(struct flist_root * root,FILE_COUNT maxfiles,char type)697 void flist_init(struct flist_root *root, FILE_COUNT maxfiles, char type)
698 {
699 flist_init_proc(root, maxfiles, type);
700 }
701
702 /* Retrieves an entry from the filelist */
703
flist_retrieve(char * dest,struct file_properties * properties,struct flist_root * root,FILE_COUNT entry)704 void flist_retrieve(char *dest, struct file_properties *properties, struct flist_root *root, FILE_COUNT entry)
705 {
706 retrieve_entry(dest, properties, root, entry);
707 }
708
709 /* Converts an extended wildcard to canonical wildcard */
710
xwild_to_canonical(char * name)711 static void xwild_to_canonical(char *name)
712 {
713 char *tmp_name;
714 char *xwptr;
715 int entry;
716
717 tmp_name=malloc_str(name);
718 xwptr=strpbrk(tmp_name, xwild_symbols);
719 if(xwptr!=NULL)
720 {
721 *(xwptr+1)='\0';
722 entry=split_name(tmp_name, NULL, NULL);
723 if(entry>0)
724 {
725 tmp_name[entry-1]='\0';
726 sprintf(name, "%s%c%s", tmp_name, PATHSEP_DEFAULT, all_wildcard);
727 }
728 else
729 strcpy(name, all_wildcard);
730 }
731 free(tmp_name);
732 }
733
734 #endif
735
736 #if SFX_LEVEL>=ARJSFXV
737
738 /* Expands wildcards and prepares a file list */
739
flist_add_files(struct flist_root * root,struct flist_root * search_flist,char * name,int expand_wildcards,int recurse_subdirs,int file_type,FILE_COUNT * count)740 int flist_add_files(struct flist_root *root, struct flist_root *search_flist, char *name, int expand_wildcards, int recurse_subdirs, int file_type, FILE_COUNT *count)
741 {
742 int result;
743 char *tmp_name;
744 #if SFX_LEVEL>=ARJ
745 int parse_rc;
746 #endif
747
748 #if SFX_LEVEL>=ARJ
749 if(expand_wildcards&&marksym_expansion&&xwild_lookup(name)==XW_OK&&
750 xwild_parser(name, &parse_rc)==XW_OK)
751 {
752 /* ASR fix for variable all_wildcard length follows: */
753 tmp_name=(char *)malloc_msg(strlen(name)+strlen(all_wildcard)+1);
754 strcpy(tmp_name, name);
755 root->fsptr=malloc_str(tmp_name);
756 xwild_to_canonical(tmp_name);
757 result=wild_list(root, search_flist, tmp_name, expand_wildcards, recurse_subdirs, file_type, count);
758 root->no_dupl=1;
759 free(tmp_name);
760 }
761 else
762 {
763 result=wild_list(root, search_flist, name, expand_wildcards, recurse_subdirs, file_type, count);
764 root->no_dupl=1;
765 }
766 #else
767 if((tmp_name=(char *)malloc(strlen(name)+1))==NULL)
768 {
769 msg_cprintf(0, M_HASH_MEM_LACK, name);
770 result=-1;
771 }
772 else
773 {
774 result=0;
775 strcpy(tmp_name, name);
776 case_path(tmp_name);
777 if(add_entry(root, search_flist, tmp_name, count))
778 result=-1;
779 free(tmp_name);
780 }
781 #endif
782 return(result);
783 }
784
785 #if SFX_LEVEL>=ARJSFXV
786
787 /* Returns pointer to the idx-th element, enlarging the CFA if required */
788
cfa_get_index(FILE_COUNT idx)789 static unsigned char FAR *cfa_get_index(FILE_COUNT idx)
790 {
791 FILE_COUNT fblock;
792
793 if(flist_array==NULL)
794 cfa_allocated=0L;
795 fblock=idx/CFA_BLOCK_SIZE;
796 /* Enlarge the CFA */
797 if(fblock>=cfa_allocated)
798 {
799 flist_array=(unsigned char FAR * FAR *)
800 farrealloc_msg(
801 flist_array,
802 (fblock+1)*sizeof(char FAR *)
803 );
804 while(cfa_allocated<=fblock)
805 flist_array[cfa_allocated++]=NULL;
806 }
807 /* Allocate a new block if it has been empty before */
808 if(flist_array[fblock]==NULL)
809 flist_array[fblock]=(char FAR *)farmalloc_msg((CFA_BLOCK_SIZE+3)>>2);
810 return(flist_array[fblock]+((idx%CFA_BLOCK_SIZE)>>2));
811 }
812
813 /* Releases the CFA structure */
814
cfa_shutdown()815 void cfa_shutdown()
816 {
817 unsigned long i;
818
819 if(flist_array!=NULL)
820 {
821 for(i=0; i<cfa_allocated; i++)
822 {
823 if(flist_array[i]!=NULL)
824 {
825 farfree(flist_array[i]);
826 flist_array[i]=NULL;
827 }
828 }
829 farfree(flist_array);
830 flist_array=NULL;
831 }
832 }
833
834 /* Retrieves a CFA element */
835
cfa_get(FILE_COUNT num)836 int cfa_get(FILE_COUNT num)
837 {
838 int pos_num;
839 unsigned char bit_mask, value_bits;
840
841 pos_num=(int)(num%4)<<1;
842 bit_mask=(unsigned char)3<<pos_num;
843 value_bits=*cfa_get_index(num)&bit_mask;
844 return(value_bits>>pos_num);
845 }
846
847 /* Stores an element in the CFA */
848
cfa_store(FILE_COUNT num,int value)849 void cfa_store(FILE_COUNT num, int value)
850 {
851 int pos_num;
852 unsigned char bit_mask, value_bits;
853 unsigned char FAR *p;
854
855 pos_num=(int)(num%4)<<1;
856 bit_mask=(unsigned char)3<<pos_num;
857 value_bits=(unsigned char)value<<pos_num;
858 p=cfa_get_index(num);
859 *p=(*p&=~bit_mask)|value_bits;
860 }
861
862 /* Initializes the CFA structures */
863
cfa_init(FILE_COUNT capacity)864 int cfa_init(FILE_COUNT capacity)
865 {
866 unsigned long bytes;
867 FILE_COUNT i;
868
869 bytes=(unsigned long)capacity>>2;
870 flist_array=farmalloc_msg(bytes+1);
871 for(i=0; i<capacity; i++)
872 cfa_store(i, FLFLAG_TO_PROCESS);
873 return(0); /* ASR fix for High C -- 01/04/2001 */
874 }
875
876 #endif
877
878 /* Allocates a block of memory, executes error stub if failed */
879
malloc_msg(unsigned int size)880 void *malloc_msg(unsigned int size)
881 {
882 void *tmp;
883
884 #ifdef DEBUG
885 if(debug_enabled&&strchr(debug_opt, 'm')!=NULL)
886 printf("(Nm%u", size);
887 #endif
888 if((tmp=malloc(size))==NULL)
889 error(M_OUT_OF_NEAR_MEMORY);
890 #ifdef DEBUG
891 if(debug_enabled&&strchr(debug_opt, 'm')!=NULL)
892 printf(")");
893 #endif
894 return(tmp);
895 }
896
897 #endif
898
899 #if SFX_LEVEL>=ARJSFXV||defined(ARJUTIL)
900
901 /* Allocates a block of far memory, executes error stub if failed.
902 Implementation-dependent (farmalloc for Borland, _fmalloc for MS C) */
903
farmalloc_msg(unsigned long size)904 void FAR *farmalloc_msg(unsigned long size)
905 {
906 void FAR *tmp;
907
908 #if defined(DEBUG)&&!defined(ARJUTIL)
909 if(debug_enabled&&strchr(debug_opt, 'm')!=NULL)
910 printf("(Fm%u", size);
911 #endif
912 if((tmp=farmalloc(size))==NULL)
913 #ifdef ARJUTIL
914 {
915 printf("Failed to farmalloc(%lu)\n", size);
916 exit(1);
917 }
918 #else
919 error(M_OUT_OF_MEMORY);
920 #endif
921 #if defined(DEBUG)&&!defined(ARJUTIL)
922 if(debug_enabled&&strchr(debug_opt, 'm')!=NULL)
923 printf(")");
924 #endif
925 return(tmp);
926 }
927
928 #endif
929
930 #if SFX_LEVEL>=ARJSFX
931
932 /* Reallocates a block of far memory, executes error stub if failed.
933 Implementation-dependent (farrealloc for Borland, _frealloc for MS C) */
934
farrealloc_msg(void FAR * memblock,unsigned long size)935 void FAR *farrealloc_msg(void FAR *memblock, unsigned long size)
936 {
937 void FAR *tmp;
938
939 if((tmp=farrealloc(memblock, size))==NULL)
940 error(M_OUT_OF_MEMORY);
941 return(tmp);
942 }
943
944 #endif
945
946 #ifdef REARJ
947
948 /* Replaces all LF characters with 0's, returning the end of string */
949
tokenize_lf(char * str)950 char *tokenize_lf(char *str)
951 {
952 while(*str!='\0')
953 {
954 if(*str=='\n')
955 *str='\0';
956 str++;
957 }
958 return(str);
959 }
960
961 #endif
962