2
* $Id: fardata.c,v 1.6 2004/04/17 11:39:43 andrew_belov Exp $
3
* ---------------------------------------------------------------------------
4
* This file contains routines dealing with far data segment and CRC.
10
#include <dos.h> /* Weird, eh? */
13
/* ASR fix 02/05/2003: need that regardless of COLOR_OUTPUT to support -jp
17
#define CHUNK_SIZE 512 /* Size of the output block */
18
#define CHUNK_THRESHOLD (CHUNK_SIZE-256) /* Safety bound */
21
DEBUGHDR(__FILE__) /* Debug information block */
25
/* Forward Declaration */
27
int vcprintf(int ccode, FMSG *fmt, va_list args);
33
/* Checks if the error can have an error code or not */
35
static int is_std_error(FMSG *errmsg)
37
return(errmsg==M_DISK_FULL||errmsg==M_CANT_DELETE||errmsg==M_CANTOPEN||
38
errmsg==M_CANTRENAME||errmsg==M_CANTREAD||errmsg==M_CANT_DELETE||
39
errmsg==M_CANT_COPY_TEMP)?1:0;
44
/* Makes various cleanup depending on the error message received and quits. */
46
int error_proc(FMSG *errmsg, ...)
52
/* Check if the message could have a standard error code */
53
if(errno!=0&&is_std_error(errmsg))
59
#if SFX_LEVEL>=ARJSFXV
60
if(quiet_mode==ARJ_SILENT)
61
freopen(dev_con, m_w, stdout);
64
file_settype(stdout, ARJT_TEXT);
66
/* For SFX archives, don't forget to display our logo */
67
#if SFX_LEVEL==ARJSFXV
69
#elif SFX_LEVEL==ARJSFX
72
msg_cprintf(0, M_ARJSFX_BANNER, exe_name);
73
msg_cprintf(0, M_PROCESSING_ARCHIVE, archive_name);
78
#elif SFX_LEVEL>=ARJSFXV
79
fputc(LF, new_stdout);
83
/* Format and print the error message */
84
va_start(marker, errmsg);
86
vcprintf(H_ERR, errmsg, marker);
88
tmp_errmsg=malloc_fmsg(errmsg);
89
#if SFX_LEVEL>=ARJSFXV
90
vfprintf(new_stdout, (FMSG *)tmp_errmsg, marker);
92
vprintf(tmp_errmsg, marker);
94
free_fmsg(tmp_errmsg);
99
#elif SFX_LEVEL>=ARJSFXV
100
fputc(LF, new_stdout);
104
/* Terminate the execution with a specific errorlevel */
105
#if SFX_LEVEL>=ARJSFXV
106
/* If there's no errorlevel yet, select errorlevel by message class */
108
errorlevel=subclass_errors(errmsg);
109
/* If the error was the lack of memory, display final memory statistics to
112
if(errorlevel==ARJ_ERL_NO_MEMORY)
118
exit(REARJ_ERL_WARNING);
119
#elif defined(REGISTER)
120
exit(REGISTER_ERL_ERROR);
121
#elif SFX_LEVEL>=ARJSFX
122
exit(ARJSFX_ERL_ERROR);
131
/* A printf() function for far strings */
133
int msg_printf(FMSG *fmt, ...)
139
storage=malloc_far_str(fmt);
140
va_start(marker, fmt);
141
result=vfprintf(new_stdout, (FMSG *)storage, marker);
147
/* A fprintf() function for far strings */
149
int msg_fprintf(FILE *stream, FMSG *fmt, ...)
155
storage=malloc_far_str(fmt);
156
va_start(marker, fmt);
157
result=vfprintf(stream, storage, marker);
163
/* A sprintf() function for far strings */
165
int msg_sprintf(char *str, FMSG *fmt, ...)
171
storage=malloc_far_str(fmt);
172
va_start(marker, fmt);
173
result=vsprintf(str, storage, marker);
184
* A Q&D custom printf() implementation. Derived from:
186
* vsprintf.c -- Lars Wirzenius & Linus Torvalds.
187
* Wirzenius wrote this portably, Torvalds f*cked it up :-)
191
/* Length-limited strlen() */
193
static int strnlen(const char FAR *s, int count)
197
for(sc=s; *sc!='\0'&&count--; ++sc)
202
/* Hex representation of digits */
204
static char adigit(unsigned long n, int is_uc)
209
return((is_uc?'A':'a')+n);
212
/* Q'n'D strtoul() implementation */
214
unsigned long simple_strtoul(const FMSG *cp, FMSG **endp, unsigned int base)
216
unsigned long result=0, value;
225
if((*cp=='x')&&isxdigit(cp[1]))
232
while(isxdigit(*cp)&&(value=isdigit(*cp)?
234
(islower(*cp)?toupper(*cp):*cp)-'A'+10)<base)
236
result=result*base+value;
244
/* Convert digits and skip over them */
246
static int skip_atoi(FMSG **s)
251
i=i*10+*((*s)++)-'0';
255
#define ZEROPAD 1 /* pad with zero */
256
#define SIGN 2 /* unsigned/signed long */
257
#define PLUS 4 /* show plus */
258
#define SPACE 8 /* space if plus */
259
#define LEFT 16 /* left justified */
260
#define SPECIAL 32 /* 0x */
261
#define LARGE 64 /* use 'ABCDEF' instead of 'abcdef' */
262
#define FAR_STR 128 /* Far strings (Fs) */
264
/* Number representation routine */
266
static int number(char *istr, long num, int base, int size, int precision, int type)
268
char c, sign, tmp[66];
280
c=(type&ZEROPAD)?'0':' ';
315
__res=((unsigned long)num)%(unsigned long)base;
316
num=((unsigned long)num)/(unsigned long)base;
317
tmp[i++]=adigit(__res, ucase_dig);
322
if(!(type&(ZEROPAD+LEFT)))
336
*str++=ucase_dig?'X':'x';
353
/* Flushes the output buffer downstream. The buffer gets clobbered. */
355
static void flush_cbuf(int ccode, char *text)
357
char *n_text, *t_text;
361
if(quiet_mode==ARJ_SILENT||(quiet_mode==ARJ_QUIET&&!(ccode&H_FORCE)))
364
need_pause=(prompt_for_more&&!yes_on_all_queries&&!print_with_more);
367
if(!redirected&&!no_colors)
368
textcolor(color_table[ccode&H_COLORMASK].color);
370
while((c=*t_text)!='\0')
378
#if SFX_LEVEL>=ARJSFXV
379
fprintf(new_stdout, strform, n_text);
380
fprintf(new_stdout, lf);
382
printf(strform, n_text);
397
textcolor(color_table[ccode&H_COLORMASK].color);
399
printf(strform, n_text);
405
if(lines_scrolled>=lines_per_page-1)
412
/* Restore the color after implicit recursion to msg_cprintf() */
414
textcolor(color_table[ccode&H_COLORMASK].color);
416
if(!rc&&(ccode&H_WEAK))
417
longjmp(main_proc, 1);
426
#if SFX_LEVEL>=ARJSFXV
427
fprintf(new_stdout, strform, n_text);
429
printf(strform, n_text);
434
printf(strform, n_text);
438
/* vcprintf() implementation */
440
int vcprintf(int ccode, FMSG *fmt, va_list args)
446
int flags; /* flags to number() */
447
int field_width; /* width of output field */
448
int precision; /* min. # of digits for integers; max
449
number of chars for from string */
450
int qualifier; /* 'h', 'l', or 'L' for integer
452
int far_str; /* Far string qualifier */
453
char buf[CHUNK_SIZE]; /* Output buffer */
456
int ocode; /* Output color code for formatted
457
fields (that's what the whole
458
routine is about!) */
463
ocode=(ccode&H_NFMT)?H_STD:ccode;
464
for(p_buf=0; *fmt; ++fmt)
466
if(last_fmt&&ccode&H_NFMT)
472
flush_cbuf(ocode, buf);
474
if(*fmt!='%'||*(fmt+1)=='%')
476
if(p_buf>=CHUNK_SIZE-1)
481
flush_cbuf(ccode, buf);
485
++fmt; /* Skip over the 2nd percent - we've handled
489
/* A format symbol is found - flush the buffer if:
490
1. It's H_NFMT, so we need to change the brush, OR
491
2. CHUNK_THRESHOLD has been exceeded (for numeric) */
492
if(ccode&H_NFMT||p_buf>=CHUNK_THRESHOLD)
497
flush_cbuf(ccode, buf);
503
++fmt; /* This also skips first '%' */
506
case '-': flags|=LEFT; goto repeat;
507
case '+': flags|=PLUS; goto repeat;
508
case ' ': flags|=SPACE; goto repeat;
509
case '#': flags|=SPECIAL; goto repeat;
510
case '0': flags|=ZEROPAD; goto repeat;
511
case 'F': flags|=FAR_STR; goto repeat;
513
/* Get field width */
516
field_width=skip_atoi((FMSG **)&fmt);
520
/* It's the next argument */
521
field_width=va_arg(args, int);
524
field_width=-field_width;
528
/* Get the precision */
534
precision=skip_atoi((FMSG **)&fmt);
538
/* It's the next argument */
539
precision=va_arg(args, int);
544
/* Get the conversion qualifier */
546
if(*fmt=='h'||*fmt=='l'||*fmt=='L')
557
while(--field_width>0)
559
buf[p_buf++]=(unsigned char)va_arg(args, int);
560
while(--field_width>0)
565
s=(char FAR *)va_arg(args, char NEAR *);
567
s=va_arg(args, char FAR *);
572
len=strnlen(s, precision);
575
while(len<field_width--)
577
if(p_buf>=CHUNK_SIZE-1)
582
flush_cbuf(ocode, buf);
589
if(p_buf>=CHUNK_SIZE-1)
594
flush_cbuf(ocode, buf);
598
while(len<field_width--)
600
if(p_buf>=CHUNK_SIZE-1)
605
flush_cbuf(ocode, buf);
613
field_width=2*sizeof(void *);
616
p_buf+=number(buf+p_buf, (unsigned long)va_arg(args, void *), 16,
617
field_width, precision, flags);
622
ipl=va_arg(args, long *);
627
ipi=va_arg(args, int *);
631
/* Integer number formats - set up the flags and "break" */
655
num=va_arg(args, unsigned long);
656
else if(qualifier=='h')
660
num=va_arg(args, int); /* num=va_arg(args, short); */
662
num=va_arg(args, int); /* num=va_arg(args, unsigned short);*/
665
num=va_arg(args, short);
667
num=va_arg(args, unsigned short);
671
num=va_arg(args, int);
673
num=va_arg(args, unsigned int);
674
p_buf+=number(buf+p_buf, num, base, field_width, precision, flags);
680
flush_cbuf(last_fmt?ocode:ccode, buf);
685
#endif /* CUSTOM_PRINTF */
687
#if SFX_LEVEL>=ARJSFX||defined(REARJ)
689
/* Helper routine for scrprintf() */
691
int msg_cprintf(int ccode, FMSG *fmt, ...)
693
#ifndef CUSTOM_PRINTF
699
#ifndef CUSTOM_PRINTF
701
storage=malloc_far_str(fmt);
706
va_start(marker, fmt);
707
#if defined(CUSTOM_PRINTF)
708
result=vcprintf(ccode, fmt, marker);
709
#elif SFX_LEVEL>=ARJSFXV
710
result=vfprintf(new_stdout, (FMSG *)storage, marker);
712
result=vprintf(storage, marker);
715
#if defined(FMSG_ST)&&!defined(CUSTOM_PRINTF)
723
#if SFX_LEVEL>=ARJSFX&&defined(TILED)
725
/* A model-independent movedata() function (it must go to ENVIRON.C) */
727
void far_memmove(char FAR *dest, char FAR *src, int length)
729
movedata(FP_SEG(src), FP_OFF(src), FP_SEG(dest), FP_OFF(dest), length);
736
/* Initializes CRC32 subsystem (only used by main()) */
743
/* Returns CRC32 for the given block */
745
void crc_for_block(char *block, unsigned int length)
747
crc32_for_block(block, length);
750
/* Returns CRC32 for the given string */
752
void crc_for_string(char *str)
754
crc32_for_string(str);
761
/* Parse the color table */
763
int parse_colors(char *opt)
772
textcolor(7); /* HACK */
777
for(p=opt; !isdigit(*p); p++)
790
for(i=0; color_table[i].arg!='\0'||!(++rc); i++)
792
if(color_table[i].arg==tolower(*opt))
794
color_table[i].color=(char)c;
800
while(*opt!='\0'&&!isdigit(*opt))
802
while(*opt!='\0'&&(isdigit(*opt)||!isalpha(*opt)))