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