summaryrefslogtreecommitdiff
path: root/v4.0/src/CMD/FC
diff options
context:
space:
mode:
Diffstat (limited to 'v4.0/src/CMD/FC')
-rw-r--r--v4.0/src/CMD/FC/ERROR.C16
-rw-r--r--v4.0/src/CMD/FC/FC.C864
-rw-r--r--v4.0/src/CMD/FC/FC.H14
-rw-r--r--v4.0/src/CMD/FC/FC.LNK4
-rw-r--r--v4.0/src/CMD/FC/FGETL.C52
-rw-r--r--v4.0/src/CMD/FC/GETL.ASM146
-rw-r--r--v4.0/src/CMD/FC/INTERNAT.H30
-rw-r--r--v4.0/src/CMD/FC/ITOUPPER.ASM119
-rw-r--r--v4.0/src/CMD/FC/MAKEFILE64
-rw-r--r--v4.0/src/CMD/FC/MAXMIN.ASM37
-rw-r--r--v4.0/src/CMD/FC/MESSAGES.ASM31
-rw-r--r--v4.0/src/CMD/FC/MOVE.ASM73
-rw-r--r--v4.0/src/CMD/FC/NTOI.C37
-rw-r--r--v4.0/src/CMD/FC/STRING.ASM115
-rw-r--r--v4.0/src/CMD/FC/TOOLS.H94
-rw-r--r--v4.0/src/CMD/FC/TTYPES.H71
-rw-r--r--v4.0/src/CMD/FC/UPDATE.C128
-rw-r--r--v4.0/src/CMD/FC/XTAB.ASM100
18 files changed, 1995 insertions, 0 deletions
diff --git a/v4.0/src/CMD/FC/ERROR.C b/v4.0/src/CMD/FC/ERROR.C
new file mode 100644
index 0000000..47bc02d
--- /dev/null
+++ b/v4.0/src/CMD/FC/ERROR.C
@@ -0,0 +1,16 @@
1/* error.c - return text of error corresponding to the most recent DOS error */
2
3#include "tools.h"
4
5extern int errno;
6extern sys_nerr;
7extern char *sys_errlist[];
8extern char UnKnown[];
9
10char *error ()
11{
12 if (errno < 0 || errno >= sys_nerr)
13 return UnKnown;
14 else
15 return sys_errlist[errno];
16}
diff --git a/v4.0/src/CMD/FC/FC.C b/v4.0/src/CMD/FC/FC.C
new file mode 100644
index 0000000..d1dc0f6
--- /dev/null
+++ b/v4.0/src/CMD/FC/FC.C
@@ -0,0 +1,864 @@
1/* file compare
2
3 Fcom compares two files in either a line-by-line mode or in a strict
4 byte-by-byte mode.
5
6 The byte-by-byte mode is simple; merely read both files and print the
7 offsets where they differ and the contents.
8
9 The line compare mode attempts to isolate differences in ranges of lines.
10 Two buffers of lines are read and compared. No hashing of lines needs
11 to be done; hashing only speedily tells you when things are different,
12 not the same. Most files run through this are expected to be largely
13 the same. Thus, hashing buys nothing.
14
15
16***********************************************************************
17The algorithm that immediately follows does not work. There is an error
18somewhere in the range of lines 11 on. An alternative explanation follows.
19 KGS
20************************************************************************
21
22 [0] Fill buffers
23 [1] If both buffers are empty then
24 [1.1] Done
25 [2] Adjust buffers so 1st differing lines are at top.
26 [3] If buffers are empty then
27 [3.1] Goto [0]
28
29 This is the difficult part. We assume that there is a sequence of inserts,
30 deletes and replacements that will bring the buffers back into alignment.
31
32 [4] xd = yd = FALSE
33 [5] xc = yc = 1
34 [6] xp = yp = 1
35 [7] If buffer1[xc] and buffer2[yp] begin a "sync" range then
36 [7.1] Output lines 1 through xc-1 in buffer 1
37 [7.2] Output lines 1 through yp-1 in buffer 2
38 [7.3] Adjust buffer 1 so line xc is at beginning
39 [7.4] Adjust buffer 2 so line yp is at beginning
40 [7.5] Goto [0]
41 [8] If buffer1[xp] and buffer2[yc] begin a "sync" range then
42 [8.1] Output lines 1 through xp-1 in buffer 1
43 [8.2] Output lines 1 through yc-1 in buffer 2
44 [8.3] Adjust buffer 1 so line xp is at beginning
45 [8.4] Adjust buffer 2 so line yc is at beginning
46 [8.5] Goto [0]
47 [9] xp = xp + 1
48 [10] if xp > xc then
49 [10.1] xp = 1
50 [10.2] xc = xc + 1
51 [10.3] if xc > number of lines in buffer 1 then
52 [10.4] xc = number of lines
53 [10.5] xd = TRUE
54 [11] if yp > yc then
55 [11.1] yp = 1
56 [11.2] yc = yc + 1
57 [11.3] if yc > number of lines in buffer 2 then
58 [11.4] yc = number of lines
59 [11.5] yd = TRUE
60 [12] if not xd or not yd then
61 [12.1] goto [6]
62
63 At this point there is no possible match between the buffers. For
64 simplicity, we punt.
65
66 [13] Display error message.
67
68EXPLANATION 2
69
70 This is a variation of the Largest Common Subsequence problem. A
71 detailed explanation of this can be found on p 189 of Data Structures
72 and Algorithms by Aho Hopcroft and Ulman.
73
74
75
76 FC maintains two buffers within which it tries to find the Largest Common
77 Subsequence (The largest common subsequence is simply the pattern in
78 buffer1 that yields the most matches with the pattern in buffer2, or the
79 pattern in buffer2 that yields the most matches with the pattern in buffer1)
80
81 FC makes a simplifying assumption that the contents of one buffer can be
82 converted to the contents of the other buffer by deleting the lines that are
83 different between the two buffers.
84
85 Two indices into each buffer are maintained:
86
87 xc, yc == point to the last line that has been scanned up to now
88
89 xp, yp == point to the first line that has not been exhaustively
90 compared to lines 0 - #c in the other buffer.
91
92 FC now makes a second simplifying assumption:
93 It is unnecessary to do any calculations on lines that are equal.
94
95 Hence FC scans File1 and File two line by line until a difference is
96 encountered.
97
98
99 When a difference is encountered the two buffers are filled such that
100 the line containing the first difference heads the buffer. The following
101 exhaustive search algorithm is applied to find the first "sync" occurance.
102 (The below is simplified to use == for comparison. In practice more than
103 one line needs to match for a "sync" to be established).
104
105
106 FOR xc,yc = 1; xc,yx <= sizeof( BUFFERS ); xc++, yc++
107
108 FOR xp,yp = 1; xp,yp <= xc,yc; xp++, yp++
109
110 IF ( BUFFER1[xp] == BUFFER2[yc] )
111
112 Then the range of lines BUFFER1[ 1 ... xp ] and
113 BUFFER2[ 1 ... yc ] need to be deleted for the
114 two files to be equal. Therefore DISPLAY these
115 ranges, and begin scanning both files starting at
116 the matching lines.
117 FI
118
119 IF ( BUFFER1[yp] == BUFFER2[xc] )
120
121 Then the range of lines BUFFER2[ 1 ... yp ] and
122 BUFFER1[ 1 ... xc ] need to be deleted for the
123 two files to be equal. Therefore DISPLAY these
124 ranges, and begin scanning both files starting at
125 the matching lines.
126 FI
127 FOREND
128 FOREND
129
130 If a match is not found within the buffers, the message "RESYNC FAILED"
131 is issued and further comparison is aborted since there is no valid way
132 to find further matching lines.
133
134
135
136
137END EXPLANATION 2
138
139
140
141
142
143 Certain flags may be set to modify the behavior of the comparison:
144
145 -a abbreviated output. Rather than displaying all of the modified
146 ranges, just display the beginning, ... and the ending difference
147 -b compare the files in binary (or byte-by-byte) mode. This mode is
148 default on .EXE, .OBJ, .LIB, .COM, .BIN, and .SYS files
149 -c ignore case on compare (cmp = strcmpi instead of strcmp)
150 -l compare files in line-by-line mode
151 -lb n set the size of the internal line buffer to n lines from default
152 of 100
153 -w ignore blank lines and white space (ignore len 0, use strcmps)
154 -t do not untabify (use fgets instead of fgetl)
155 -n output the line number also
156 -NNNN set the number of lines to resynchronize to n which defaults
157 to 2. Failure to have this value set correctly can result in
158 odd output:
159 file1: file2:
160 abcdefg abcdefg
161 aaaaaaa aaaaaab
162 aaaaaaa aaaaaaa
163 aaaaaaa aaaaaaa
164 abcdefg abcdefg
165
166 with default sync of 2 yields: with sync => 3 yields:
167
168 *****f1 *****f1
169 abcdefg abcdefg
170 aaaaaaa aaaaaaa
171 *****f2 aaaaaaa
172 abcdefg *****f2
173 aaaaaab abcdefg
174 aaaaaaa aaaaaab
175 aaaaaaa
176 *****f1
177 aaaaaaa
178 aaaaaaa
179 abcdefg
180 *****f2
181 aaaaaaa
182 abcdefg
183
184
185
186
187
188
189WARNING:
190 This program makes use of GOTO's and hence is not as straightforward
191 as it could be! CAVEAT PROGRAMMER.
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207 */
208
209
210#include "tools.h"
211#include "fc.h"
212
213/* #define DEBUG FALSE */
214
215extern int fgetl(),
216 strcmp ();
217
218extern byte toupper ();
219
220int (*funcRead) (), /* function to use to read lines */
221 (*fCmp) (); /* function to use to compare lines */
222
223extern byte BadSw[],
224 Bad_ver[],
225 BadOpn[],
226 LngFil[],
227 NoDif[],
228 NoMem[],
229 UseMes[],
230 ReSyncMes[];
231
232int ctSync = -1, /* number of lines required to sync */
233 cLine = -1; /* number of lines in internal buffs */
234
235flagType fAbbrev = FALSE, /* abbreviated output */
236 fBinary = FALSE, /* binary comparison */
237 fLine = FALSE, /* line comparison */
238 fNumb = FALSE, /* display line numbers */
239 fCase = TRUE, /* case is significant */
240 fIgnore = FALSE; /* ignore spaces and blank lines */
241
242#ifdef DEBUG
243
244flagType fDebug = FALSE;
245#endif
246
247struct lineType *buffer1,
248 *buffer2;
249
250byte line[MAXARG]; /* single line buffer */
251
252byte *extBin[] = { ".EXE", ".OBJ", ".LIB",
253 ".COM", ".BIN", ".SYS", NULL };
254
255
256main (c, v)
257int c;
258byte *v[];
259{
260
261 int i;
262 int j;
263 int fileargs;
264 char *strpbrk(),
265 *slash;
266 char n[2][80];
267 char temp;
268
269
270
271 extern byte _osmajor, _osminor;
272 word version; /* _osmajor._osminor, used for */
273 /* version binding checks. */
274
275
276
277 /* Issue error message if DOS version is not within valid range. */
278 version = ((word)_osmajor << 8) + (word)_osminor;
279 if (( LOWVERSION > version) || (version > HIGHVERSION))
280 {
281 usage (Bad_ver, 1);
282 }
283
284 funcRead = (int (*) ())FNADDR(fgetl);
285
286 fileargs=0;
287
288 for (i=1; i < c ; i++)
289 {
290/**
291 * If argument doesn't begin with a /, parse a filename off of it
292 * then examine the argument for following switches.
293 *
294**/
295 if (*v[i] != '/')
296 {
297 slash= strpbrk( v[i],"/" );
298
299 if ( slash )
300 {
301 temp = *slash;
302 *slash='\0' ;
303 strcpy(n[fileargs++],v[i]);
304 *slash =temp ;
305 }
306 else
307 strcpy(n[fileargs++],v[i]);
308 }
309
310 for ( j=0 ; j < strlen( v[i] ) ; j++)
311 {
312 if(*(v[i]+j)=='/')
313 {
314 switch(toupper( *(v[i]+j+1)))
315 {
316 case 'A' :
317 fAbbrev = TRUE;
318 break;
319 case 'B' :
320 fBinary = TRUE;
321 break;
322 case 'C' :
323 fCase = FALSE;
324 break;
325#ifdef DEBUG
326 case 'D' :
327 fDebug = TRUE;
328 break;
329#endif
330 case 'W' :
331 fIgnore = TRUE;
332 break;
333 case 'L' :
334 if (toupper(*(v[i]+j+2))=='B')
335 {
336 cLine = ntoi ((v[i]+j+3),10);
337 break;
338 }
339 else
340 fLine = TRUE;
341 break;
342 case 'N' :
343 fNumb = TRUE;
344 break;
345 case 'T' :
346 funcRead =(int (*) ())FNADDR(fgets);
347 break;
348 default:
349 if (*strbskip((v[i]+j+1),"0123456789") == 0)
350 {
351 ctSync = ntoi ((v[i]+j+1), 10);
352 }
353 else
354 {
355 usage (NULL, 1);
356 }
357 } /* end switch */
358 } /* end if */
359 } /* end parse of argument for '/' */
360 } /* End ARGUMENT Search */
361
362
363
364 if (fileargs != 2)
365 usage (NULL, 1);
366
367 if (ctSync != -1)
368 fLine = TRUE;
369 else
370 ctSync = 2;
371
372 if (cLine == -1)
373 cLine = 100;
374
375 if (!fBinary && !fLine)
376 {
377 extention (n[0], line);
378
379 for (i = 0; extBin[i]; i++)
380 if (!strcmpi (extBin[i], line))
381 fBinary = TRUE;
382
383 if (!fBinary)
384 fLine = TRUE;
385 }
386
387 if (fBinary && (fLine || fNumb))
388 usage (BadSw, 1);
389
390 if (fIgnore)
391 {
392 if (fCase)
393 fCmp = FNADDR(strcmps);
394 else
395 fCmp = FNADDR(strcmpis);
396 }
397 else
398 {
399 if (fCase)
400 fCmp = FNADDR(strcmp);
401 else
402 fCmp = FNADDR(strcmpi);
403 }
404
405 if (fBinary)
406 BinaryCompare (n[0], n[1]);
407 else
408 LineCompare (n[0], n[1]);
409
410}
411
412usage (p, erc)
413unsigned char *p;
414{
415 if (p)
416 printf ("fc: %s\n", p);
417 else
418 printf (UseMes);
419
420 exit (erc);
421}
422
423BinaryCompare (f1, f2)
424unsigned char *f1, *f2;
425{
426 register int c1, c2;
427 long pos;
428 FILE *fh1, *fh2;
429 flagType fSame;
430
431 fSame = TRUE;
432
433 if ((fh1 = fopen (f1, "rb")) == NULL)
434 {
435 sprintf (line, BadOpn, f1, error ());
436 usage (line, 1);
437 }
438
439 if ((fh2 = fopen (f2, "rb")) == NULL)
440 {
441 sprintf (line, BadOpn, f2, error ());
442 usage (line, 1);
443 }
444 pos = 0L;
445
446 while (TRUE)
447 {
448 if ((c1 = getc (fh1)) != EOF)
449 {
450 if ((c2 = getc (fh2)) != EOF)
451 {
452 if (c1 == c2)
453 ;
454 else
455 {
456 fSame = FALSE;
457 printf ("%08lX: %02X %02X\n", pos, c1, c2);
458 }
459 }
460 else
461 {
462 sprintf (line, LngFil, f1, f2);
463 usage (line, 1);
464 }
465 }
466 else
467 {
468 if ((c2 = getc (fh2)) == EOF)
469 {
470 if (fSame)
471 usage (NoDif, 0);
472 else
473 exit (1);
474 }
475 else
476 {
477 sprintf (line, LngFil, f2, f1);
478 usage (line, 1);
479 }
480 }
481 pos++;
482 }
483}
484
485/* compare a range of lines */
486flagType compare (l1, s1, l2, s2, ct)
487int l1, l2, ct;
488register int s1, s2;
489{
490
491#ifdef DEBUG
492 if (fDebug)
493 printf ("compare (%d, %d, %d, %d, %d)\n", l1, s1, l2, s2, ct);
494#endif
495
496 if (ct == 0 || s1+ct > l1 || s2+ct > l2)
497 return FALSE;
498
499 while (ct--)
500 {
501
502#ifdef DEBUG
503 if (fDebug)
504 printf ("'%s' == '%s'? ", buffer1[s1].text, buffer2[s2].text);
505#endif
506
507 if ((*fCmp)(buffer1[s1++].text, buffer2[s2++].text))
508 {
509
510#ifdef DEBUG
511 if (fDebug)
512 printf ("No\n");
513#endif
514 return FALSE;
515 }
516 }
517
518#ifdef DEBUG
519 if (fDebug)
520 printf ("Yes\n");
521#endif
522
523 return TRUE;
524}
525
526LineCompare (f1, f2)
527unsigned char *f1, *f2;
528{
529 FILE *fh1, *fh2;
530 int l1, l2, i, xp, yp, xc, yc;
531 flagType xd, yd, fSame;
532 int line1, line2;
533
534 fSame = TRUE;
535
536 if ((fh1 = fopen (f1, "rb")) == NULL)
537 {
538 sprintf (line, BadOpn, f1, error ());
539 usage (line, 1);
540 }
541
542 if ((fh2 = fopen (f2, "rb")) == NULL)
543 {
544 sprintf (line, BadOpn, f2, error ());
545 usage (line, 1);
546 }
547
548 if ((buffer1 = (struct lineType *)malloc (cLine * (sizeof *buffer1))) == NULL ||
549 (buffer2 = (struct lineType *)malloc (cLine * (sizeof *buffer1))) == NULL)
550 usage (NoMem);
551
552 l1 = l2 = 0;
553 line1 = line2 = 0;
554l0:
555
556#ifdef DEBUG
557 if (fDebug)
558 printf ("At scan beginning\n");
559#endif
560
561 l1 += xfill (buffer1+l1, fh1, cLine-l1, &line1);
562 l2 += xfill (buffer2+l2, fh2, cLine-l2, &line2);
563
564 if (l1 == 0 && l2 == 0)
565 {
566 if (fSame)
567 usage (NoDif, 0);
568 return;
569 }
570 xc = min (l1, l2);
571
572 for (i=0; i < xc; i++)
573 {
574 if (!compare (l1, i, l2, i, 1))
575 break;
576 }
577
578 if (i != xc)
579 i = max (i-1, 0);
580
581 l1 = adjust (buffer1, l1, i);
582 l2 = adjust (buffer2, l2, i);
583
584 /* KLUDGE ALERT!! GOTO USED */
585 if (l1 == 0 && l2 == 0)
586 goto l0;
587
588 l1 += xfill (buffer1+l1, fh1, cLine-l1, &line1);
589 l2 += xfill (buffer2+l2, fh2, cLine-l2, &line2);
590
591#ifdef DEBUG
592 if (fDebug)
593 printf ("buffers are adjusted, %d, %d remain\n", l1, l2);
594#endif
595
596 xd = yd = FALSE;
597 xc = yc = 1;
598 xp = yp = 1;
599
600l6:
601
602#ifdef DEBUG
603 if (fDebug)
604 printf ("Trying resync %d,%d %d,%d\n", xc, xp, yc, yp);
605#endif
606
607 i = min (l1-xc,l2-yp);
608 i = min (i, ctSync);
609
610 if (compare (l1, xc, l2, yp, i))
611 {
612 fSame = FALSE;
613 printf ("***** %s\n", f1);
614 dump (buffer1, 0, xc);
615 printf ("***** %s\n", f2);
616 dump (buffer2, 0, yp);
617 printf ("*****\n\n");
618
619 l1 = adjust (buffer1, l1, xc);
620 l2 = adjust (buffer2, l2, yp);
621
622 /* KLUDGE ALERT!! GOTO USED */
623 goto l0;
624 }
625 i = min (l1-xp, l2-yc);
626 i = min (i, ctSync);
627
628 if (compare (l1, xp, l2, yc, i))
629 {
630 fSame = FALSE;
631 printf ("***** %s\n", f1);
632 dump (buffer1, 0, xp);
633 printf ("***** %s\n", f2);
634 dump (buffer2, 0, yc);
635 printf ("*****\n\n");
636
637 l1 = adjust (buffer1, l1, xp);
638 l2 = adjust (buffer2, l2, yc);
639
640 /* KLUDGE ALERT!! GOTO USED */
641 goto l0;
642 }
643
644 if (++xp > xc)
645 {
646 xp = 1;
647 if (++xc >= l1)
648 {
649 xc = l1;
650 xd = TRUE;
651 }
652 }
653
654 if (++yp > yc)
655 {
656 yp = 1;
657 if (++yc >= l2)
658 {
659 yc = l1;
660 yd = TRUE;
661 }
662 }
663
664 if (!xd || !yd)
665 goto l6;
666 fSame = FALSE;
667
668 if (l1 >= cLine || l2 >= cLine)
669 printf ("%s", ReSyncMes);
670
671 printf ("***** %s\n", f1);
672 dump (buffer1, 0, l1-1);
673 printf ("***** %s\n", f2);
674 dump (buffer2, 0, l2-1);
675 printf ("*****\n\n");
676 exit (1);
677}
678
679
680
681/* return number of lines read in */
682xfill (pl, fh, ct, plnum)
683struct lineType *pl;
684FILE *fh;
685int ct;
686int *plnum;
687{
688 int i;
689
690#ifdef DEBUG
691 if (fDebug)
692 printf ("xfill (%04x, %04x)\n", pl, fh);
693#endif
694
695 i = 0;
696 while (ct-- && (*funcRead) (pl->text, MAXARG, fh) != NULL)
697 {
698 if (funcRead == (int (*) ())FNADDR(fgets))
699 pl->text[strlen(pl->text)-1] = 0;
700 if (fIgnore && !strcmps (pl->text, ""))
701 pl->text[0] = 0;
702 if (strlen (pl->text) != 0 || !fIgnore)
703 {
704 pl->line = ++*plnum;
705 pl++;
706 i++;
707 }
708 }
709
710#ifdef DEBUG
711 if (fDebug)
712 printf ("xfill returns %d\n", i);
713#endif
714
715 return i;
716}
717
718
719/* adjust returns number of lines in buffer */
720adjust (pl, ml, lt)
721struct lineType *pl;
722int ml;
723int lt;
724{
725
726#ifdef DEBUG
727 if (fDebug)
728 printf ("adjust (%04x, %d, %d) = ", pl, ml, lt);
729 if (fDebug)
730 printf ("%d\n", ml-lt);
731#endif
732
733 if (ml <= lt)
734 return 0;
735
736#ifdef DEBUG
737 if (fDebug)
738 printf ("move (%04x, %04x, %04x)\n", &pl[lt], &pl[0], sizeof (*pl)*(ml-lt));
739#endif
740
741 Move ((unsigned char far *)&pl[lt], (char far *)&pl[0], sizeof (*pl)*(ml-lt));
742 return ml-lt;
743}
744
745
746/* dump
747 * dump outputs a range of lines.
748 *
749 * INPUTS
750 * pl pointer to current lineType structure
751 * start starting line number
752 * end ending line number
753 *
754 * CALLS
755 * pline, printf
756 *
757 */
758dump (pl, start, end)
759struct lineType *pl;
760int start, end;
761{
762 if (fAbbrev && end-start > 2)
763 {
764 pline (pl+start);
765 printf ("...\n");
766 pline (pl+end);
767 }
768 else
769 while (start <= end)
770 pline (pl+start++);
771}
772
773
774
775
776/* PrintLINE
777 * pline prints a single line of output. If the /n flag
778 * has been specified, the line number of the printed text is added.
779 *
780 * Inputs
781 * pl pointer to current lineType structure
782 * fNumb TRUE if /n specified
783 *
784 */
785pline (pl)
786struct lineType *pl;
787{
788 if (fNumb)
789 printf ("%5d: ", pl->line);
790
791 printf ("%s\n", pl->text);
792}
793
794/*
795 * strcmpi will compare two string lexically and return one of
796 * the following:
797 * - 0 if the strings are equal
798 * - 1 if first > the second
799 * - (-1) if first < the second
800 *
801 * This was written to replace the run time library version of
802 * strcmpi which does not correctly compare the european character set.
803 * This version relies on a version of toupper which uses IToupper.
804 */
805
806int strcmpi(str1, str2)
807unsigned char *str1, *str2;
808{
809 unsigned char c1, c2;
810
811 while ((c1 = toupper(*str1++)) == (c2 = toupper(*str2++))) {
812 if (c1 == '\0')
813 return(0);
814 }
815
816 if (c1 > c2)
817 return(1);
818 else
819 return(-1);
820}
821
822
823/* compare two strings, ignoring white space, case is significant, return
824 * 0 if identical, <>0 otherwise
825 */
826strcmps (p1, p2)
827unsigned char *p1, *p2;
828{
829 while (TRUE) {
830 while (ISSPACE(*p1))
831 p1++;
832 while (ISSPACE(*p2))
833 p2++;
834 if (*p1 == *p2)
835 if (*p1++ == 0)
836 return 0;
837 else
838 p2++;
839 else
840 return *p1-*p2;
841 }
842}
843
844
845/* compare two strings, ignoring white space, case is not significant, return
846 * 0 if identical, <>0 otherwise
847 */
848int strcmpis (p1, p2)
849unsigned char *p1, *p2;
850{
851 while (TRUE) {
852 while (ISSPACE(*p1))
853 p1++;
854 while (ISSPACE(*p2))
855 p2++;
856 if (toupper (*p1) == toupper (*p2))
857 if (*p1++ == 0)
858 return 0;
859 else
860 p2++;
861 else
862 return *p1-*p2;
863 }
864}
diff --git a/v4.0/src/CMD/FC/FC.H b/v4.0/src/CMD/FC/FC.H
new file mode 100644
index 0000000..aa826c3
--- /dev/null
+++ b/v4.0/src/CMD/FC/FC.H
@@ -0,0 +1,14 @@
1struct lineType {
2 int line; /* line number */
3 unsigned char text[MAXARG]; /* body of line */
4};
5
6#define byte unsigned char
7#define word unsigned short
8
9#define LOWVERSION 0x0300 + 10
10#define HIGHVERSION 0x0400 + 00
11
12extern unsigned char _ctype_[];
13#define _SPACE 0x8 /* tab, carriage return, new line, */
14#define ISSPACE(c) ( (_ctype_+1)[c] & _SPACE )
diff --git a/v4.0/src/CMD/FC/FC.LNK b/v4.0/src/CMD/FC/FC.LNK
new file mode 100644
index 0000000..89d9fff
--- /dev/null
+++ b/v4.0/src/CMD/FC/FC.LNK
@@ -0,0 +1,4 @@
1fc.obj error.obj fgetl.obj getl.obj itoupper.obj ..\..\inc\kstring.obj +
2maxmin.obj move.obj ntoi.obj string.obj update.obj xtab.obj messages.obj
3fc.exe
4
diff --git a/v4.0/src/CMD/FC/FGETL.C b/v4.0/src/CMD/FC/FGETL.C
new file mode 100644
index 0000000..a425b39
--- /dev/null
+++ b/v4.0/src/CMD/FC/FGETL.C
@@ -0,0 +1,52 @@
1/* fgetl.c - expand tabs and return lines w/o separators */
2
3#include "tools.h"
4
5/* returns line from file (no CRLFs); returns NULL if EOF */
6fgetl (buf, len, fh)
7char *buf;
8int len;
9FILE *fh;
10{
11 register int c;
12 register char *p;
13
14 /* remember NUL at end */
15 len--;
16 p = buf;
17 while (len) {
18 c = getc (fh);
19 if (c == EOF || c == '\n')
20 break;
21#if MSDOS
22 if (c != '\r')
23#endif
24 if (c != '\t') {
25 *p++ = c;
26 len--;
27 }
28 else {
29 c = min (8 - ((p-buf) & 0x0007), len);
30 Fill (p, ' ', c);
31 p += c;
32 len -= c;
33 }
34 }
35 *p = 0;
36 return ! ( (c == EOF) && (p == buf) );
37}
38
39/* writes a line to file (with trailing CRLFs) from buf, return <> 0 if
40 * writes fail
41 */
42fputl (buf, len, fh)
43char *buf;
44int len;
45FILE *fh;
46{
47#if MSDOS
48 return (fwrite (buf, 1, len, fh) != len || fputs ("\r\n", fh) == EOF) ? EOF : 0;
49#else
50 return (fwrite (buf, 1, len, fh) != len || fputs ("\n", fh) == EOF) ? EOF : 0;
51#endif
52}
diff --git a/v4.0/src/CMD/FC/GETL.ASM b/v4.0/src/CMD/FC/GETL.ASM
new file mode 100644
index 0000000..508eca9
--- /dev/null
+++ b/v4.0/src/CMD/FC/GETL.ASM
@@ -0,0 +1,146 @@
1;
2; blindingly fast assembly help for Z
3;
4
5.xlist
6include version.inc
7include cmacros.inc
8.list
9
10sBegin data
11assumes ds,data
12
13bufstart dd ?
14staticW bufsrc,?
15staticW buflen,?
16staticW buflength,?
17staticW buffh,?
18globalB fGetlCR,?
19bufpos dd ?
20
21sEnd
22sBegin code
23
24assumes cs,code
25
26;
27; getlpos returns current seek position in file
28;
29cProc getlpos,<PUBLIC>
30cBegin
31 mov dx,word ptr bufpos+2
32 mov ax,word ptr bufpos
33cEnd
34
35;
36; getlinit (buf, len, fh) initializes the getl routine for buffer buf and fh fh
37;
38cProc getlinit,<PUBLIC>
39parmD buf
40parmW len
41parmW fh
42cBegin
43 mov ax,off_buf
44 mov word ptr bufstart,ax
45 mov ax,seg_buf
46 mov word ptr bufstart+2,ax
47 mov ax,fh
48 mov buffh,ax
49 mov ax,len
50 mov buflength,ax
51 mov buflen,0
52 mov word ptr bufpos,0
53 mov word ptr bufpos+2,0
54 mov fGetlCR,0
55cEnd
56
57;
58; getl (dst, len) returns TRUE if a line was read.
59;
60cProc getl,<PUBLIC>,<DS,SI,DI>
61parmW dst
62parmW dstlen
63cBegin
64 assumes ss,data
65 cld
66 push ds
67 pop es
68 mov ds,word ptr bufstart+2
69 assumes ds,nothing
70 mov si,bufsrc
71 mov di,dst
72 mov cx,buflen
73 mov dx,dstlen
74 dec dx ; room for NUL at end
75 jcxz fill
76
77movc: lodsb ; get a byte
78 cmp al,13 ; is it special?
79 jbe spec ; yes, go handle special case
80stoc: stosb ; put character in buffer
81 dec dx ; one less space in buffer
82endl: loopnz movc ; go back for more characters
83 jnz fill ; no more characters => go fill buffer
84 ; cx = 0, buflen = length moved
85fin: dec cx
86fin1: xor ax,ax
87 stosb
88 mov bufsrc,si ; length moved = buflen - cx
89 xchg buflen,cx
90 sub cx,buflen
91 add word ptr bufpos,cx
92 adc word ptr bufpos+2,0
93 not ax
94 jmp short getldone
95
96fill:
97 mov cx, buflen ; add length moved to bufpos
98 add word ptr bufpos,cx
99 adc word ptr bufpos+2,0
100 push dx
101 mov dx,word ptr bufstart
102 mov cx,buflength
103 mov bx,buffh
104 mov ah,3Fh
105 int 21h
106 mov cx,ax
107 mov buflen,ax
108 mov si,dx
109 pop dx
110 or ax,ax
111 jnz movc
112; if we've stored chars then terminate line else return with 0
113 cmp di,dst
114 jnz fin1
115 jmp short getldone
116
117setnz: or al,1
118 mov fGetlCR,-1 ; indicate we've seen a CR
119 jmp endl
120
121spec: jz setnz
122 cmp al,10
123 jz fin
124 cmp al,9
125 jnz stoc
126 push cx
127 mov ax,di
128 sub ax,dst
129 and ax,7
130 mov cx,8
131 sub cx,ax
132 cmp cx,dx
133 jbe ok
134 mov cx,dx
135ok: sub dx,cx
136 mov al," "
137 rep stosb
138 pop cx
139 jmp endl
140
141getldone:
142cEnd
143
144sEnd
145
146end
diff --git a/v4.0/src/CMD/FC/INTERNAT.H b/v4.0/src/CMD/FC/INTERNAT.H
new file mode 100644
index 0000000..0cd839c
--- /dev/null
+++ b/v4.0/src/CMD/FC/INTERNAT.H
@@ -0,0 +1,30 @@
1/*
2 Data structure for international table
3 */
4
5struct InterTbl
6{
7 unsigned dateform ; /* Date format */
8 char currsym[5] ; /* Currency symbol as ASCIZ string */
9 char thousp[2] ; /* Thousands separator as ASCIZ string */
10 char decsp[2] ; /* Decimal separator as ASCIZ string */
11 char datesp[2] ; /* Date separator as ASCIZ string */
12 char timesp[2] ; /* Time separator as ASCIZ string */
13 unsigned char bits ; /* Bit field */
14 unsigned char numdig ; /* Number of signifigant decimal digits */
15 unsigned char timeform ;/* Time format */
16 unsigned long casecall ;/* Case mapping call */
17 char datasp[2] ; /* Data list separator as ASCIZ string */
18 int reserv[5] ; /* RESERVED */
19} ;
20
21
22#define DATEFORM_USA 0
23#define DATEFORM_EUROPE 1
24#define DATEFORM_JAPAN 2
25
26#define BITS_CURRENCY 0x0001
27#define BITS_NUMSPC 0x0002
28
29#define TIMEFORM_12 0
30#define TIMEFORM_24 1
diff --git a/v4.0/src/CMD/FC/ITOUPPER.ASM b/v4.0/src/CMD/FC/ITOUPPER.ASM
new file mode 100644
index 0000000..289c691
--- /dev/null
+++ b/v4.0/src/CMD/FC/ITOUPPER.ASM
@@ -0,0 +1,119 @@
1.xlist
2include version.inc
3include cmacros.inc
4.list
5
6sBegin code
7assumes cs,code
8
9;
10; c = IToupper (c, routine);
11;
12; c is char to be converted
13; routine is case map call in international table
14;
15
16cProc IToupper,<PUBLIC>
17parmW c
18parmD routine
19cBegin
20 mov ax,c
21 or ah,ah
22 jnz donothing
23 cmp al,'a'
24 jb noconv
25 cmp al,'z'
26 ja noconv
27 sub al,20H
28noconv:
29 call routine
30donothing:
31cEnd
32
33
34;Get_Lbtbl
35;
36; Get pointer to LBTBL from DOS if we are running on a version
37; of DOS which supports it. If not, initialize the table with
38; a pointer to a local "default" table with KANJI lead bytes.
39;
40;Input: word pointer to LONG "Lbtbl"
41;Output: long initialized to Lead byte pointer
42;
43
44cProc get_lbtbl,<PUBLIC>
45
46parmW pointer_to_table
47
48; on entry, low word of DWORD pointer has offset of
49; a default table of lead bytes defined within the C program
50; If function 63 is supported, the DWORD pointer to DOS'
51; table will be placed here instead.
52cBegin
53 push si
54 push di
55 mov bx,pointer_to_table ;get pointer
56 mov si,[bx] ;default table pointer in DS:SI
57 push es
58 push ds
59 mov ax,6300h ;make Get Lead Byte call
60 int 21h
61 mov ss:[bx],si ;si didn't change if non ECS dos
62 mov ss:[bx+2],ds ;store segment
63 pop ds
64 pop es
65 pop di
66 pop si
67cEnd
68
69
70;
71; test_ECS(char,DWORD_prt) test the char to find out if it is
72; a valid lead byte using passed DWORD
73; Input: char PTR to the Lead Byte table.
74; DWORD PTR to table
75; Output: AX=FFFF (is_lead) Lead byte table may be default in
76; AX=0 (not_lead) program or ECS table in DOS when
77; running on a version which supports it.
78;
79cProc test_ECS,<PUBLIC> ;test for lead byte ;if Lead, then
80 ; return AX=Is_lead
81 ; else
82 ; return AX=FALSE
83Is_lead EQU 0FFFFH
84Not_lead EQU 0
85
86parmW char
87parmD pointer ;DWORD PTR to Lead Byte Table
88cBegin
89 mov ax,char
90 xchg ah,al
91 push SI
92 push DS
93 LDS SI,pointer
94ktlop:
95 lodsb
96 or al,al
97 jz notlead
98 cmp al,ah
99 ja notlead
100 lodsb
101 cmp ah,al
102 ja ktlop
103 mov ax,Is_lead
104notl_exit:
105 pop ds
106 pop si
107 jmp cexit
108notlead:
109 mov ax,not_lead
110 jmp notl_exit
111cexit:
112cEnd
113
114
115
116
117sEnd
118
119end
diff --git a/v4.0/src/CMD/FC/MAKEFILE b/v4.0/src/CMD/FC/MAKEFILE
new file mode 100644
index 0000000..393a2bb
--- /dev/null
+++ b/v4.0/src/CMD/FC/MAKEFILE
@@ -0,0 +1,64 @@
1#** makefile for fc
2
3DEST =fc
4MSG =messages
5
6# Path Definitions
7
8BIOS =..\..\BIOS
9BOOT =..\..\BOOT
10dos =..\..\DOS
11inc =..\..\INC
12hinc =..\..\h
13H =..\..\H
14
15# List of object files required
16
17OBJ = fc.obj \
18 error.obj \
19 fgetl.obj \
20 getl.obj \
21 itoupper.obj \
22 $(inc)\kstring.obj \
23 maxmin.obj \
24 move.obj \
25 ntoi.obj \
26 string.obj \
27 update.obj \
28 xtab.obj \
29 messages.obj
30
31# Rules and Dependencies follow
32
33all: $(DEST).exe
34
35$(inc)\printf.obj: $(inc)\printf.asm
36
37$(inc)\kstring.obj: $(inc)\kstring.c $(hinc)\internat.h
38
39getl.obj: getl.asm $(inc)\cmacros.inc $(inc)\version.inc
40
41itoupper.obj: itoupper.asm $(inc)\cmacros.inc $(inc)\version.inc
42
43maxmin.obj: maxmin.asm $(inc)\cmacros.inc $(inc)\version.inc
44
45$(MSG).obj: $(MSG).asm
46
47move.obj: move.asm $(inc)\cmacros.inc $(inc)\version.inc
48
49string.obj: string.asm $(inc)\cmacros.inc $(inc)\version.inc
50
51xtab.obj: xtab.asm $(inc)\cmacros.inc $(inc)\version.inc
52
53error.obj: error.c tools.h ttypes.h
54
55$(DEST).obj: $(DEST).c $(DEST).h tools.h ttypes.h
56
57fgetl.obj: fgetl.c tools.h ttypes.h
58
59ntoi.obj: ntoi.c tools.h ttypes.h
60
61update.obj: update.c tools.h ttypes.h
62
63$(DEST).exe: $(OBJ) $(DEST).lnk
64 $(link) @$(DEST).lnk;
diff --git a/v4.0/src/CMD/FC/MAXMIN.ASM b/v4.0/src/CMD/FC/MAXMIN.ASM
new file mode 100644
index 0000000..eb9ce53
--- /dev/null
+++ b/v4.0/src/CMD/FC/MAXMIN.ASM
@@ -0,0 +1,37 @@
1;
2; maximum and minimum routines.
3;
4
5.xlist
6include version.inc
7include cmacros.inc
8.list
9
10sBegin code
11assumes cs,code
12
13cProc max,<PUBLIC>
14parmW a
15parmW b
16cBegin
17 mov ax,a
18 cmp ax,b
19 jg maxdone
20 mov ax,b
21maxdone:
22cEnd
23
24cProc min,<PUBLIC>
25parmW a
26parmW b
27cBegin
28 mov ax,a
29 cmp ax,b
30 jl mindone
31 mov ax,b
32mindone:
33cEnd
34
35sEnd
36
37end
diff --git a/v4.0/src/CMD/FC/MESSAGES.ASM b/v4.0/src/CMD/FC/MESSAGES.ASM
new file mode 100644
index 0000000..5b1879f
--- /dev/null
+++ b/v4.0/src/CMD/FC/MESSAGES.ASM
@@ -0,0 +1,31 @@
1;
2; message file for FC command
3;
4
5CONST SEGMENT WORD PUBLIC 'DATA'
6CONST ENDS
7
8_BSS SEGMENT WORD PUBLIC 'DATA'
9_BSS ENDS
10
11_DATA SEGMENT WORD PUBLIC 'DATA'
12_DATA ENDS
13
14DGROUP GROUP CONST, _BSS, _DATA
15
16 ASSUME DS:DGROUP
17
18_DATA SEGMENT
19PUBLIC _BadSw, _UseMes, _BadOpn, _LngFil, _NoDif, _NoMem, _Bad_ver, _ReSyncMes, _UnKnown
20
21_BadSw DB "Incompatible switches",0
22_Bad_ver DB "Incorrect DOS version",0
23_UseMes DB "usage: fc [/a] [/b] [/c] [/l] [/lbNN] [/w] [/t] [/n] [/NNNN] file1 file2",0ah,0
24_BadOpn DB "cannot open %s - %s",0
25_LngFil DB "%s longer than %s",0
26_NoDif DB "no differences encountered",0
27_NoMem DB "out of memory",0ah,0
28_ReSyncMes DB "Resync failed. Files are too different\n",0
29_UnKnown DB "Unknown error",0
30_DATA ENDS
31END
diff --git a/v4.0/src/CMD/FC/MOVE.ASM b/v4.0/src/CMD/FC/MOVE.ASM
new file mode 100644
index 0000000..d40e5d6
--- /dev/null
+++ b/v4.0/src/CMD/FC/MOVE.ASM
@@ -0,0 +1,73 @@
1;
2; memory routines
3;
4
5.xlist
6include version.inc
7include cmacros.inc
8.list
9
10sBegin code
11assumes cs,code
12
13cProc Move,<PUBLIC>,<DS,SI,DI>
14parmD src
15parmD dst
16parmW count
17cBegin
18 mov cx,count
19 jcxz NoByte ; No characters to move
20 les di,dst ; grab pointers
21 lds si,src
22 cld
23 mov ax,ds
24 cmp ax,Seg_dst
25 jnz SimpleMove ; segments are NOT the same, no opt
26 cmp si,di ; is the start of source before dest
27 jb TestMove ; yes, try to optimize
28
29SimpleMove:
30 shr cx,1
31 rep movsw
32 jnc NoByte
33 movsb
34 jmp short NoByte
35
36TestMove:
37 mov ax,di
38 sub ax,si ; ax = difference between regions
39 cmp ax,cx ; is difference greater than region?
40 jae SimpleMove ; yes, no optimize
41 mov ax,cx ; optimize by copying down from top
42 dec ax
43 add di,ax
44 add si,ax
45 std
46 rep movsb ; no word optimization here
47
48NoByte:
49 cld
50cEnd
51
52cProc Fill,<PUBLIC>,<DI>
53parmD dst
54parmB value
55parmW count
56cBegin
57 cld
58 les di,dst
59 mov al,value
60 mov ah,value
61 mov cx,count
62 shr cx,1
63 jcxz fill1
64 rep stosw
65fill1:
66 jnc fill2
67 stosb
68fill2:
69cEnd
70
71sEnd
72
73end
diff --git a/v4.0/src/CMD/FC/NTOI.C b/v4.0/src/CMD/FC/NTOI.C
new file mode 100644
index 0000000..267fce7
--- /dev/null
+++ b/v4.0/src/CMD/FC/NTOI.C
@@ -0,0 +1,37 @@
1/* convert an arbitrary based number to an integer */
2
3#include <ctype.h>
4#include "tools.h"
5
6/* p points to characters, return -1 if no good characters found
7 * and base is 2 <= base <= 16
8 */
9int ntoi (p, base)
10char *p;
11int base;
12{
13 register int i, c;
14 flagType fFound;
15
16 if (base < 2 || base > 16)
17 return -1;
18 i = 0;
19 fFound = FALSE;
20 while (c = *p++) {
21 c = tolower (c);
22 if (!isxdigit (c))
23 break;
24 if (c <= '9')
25 c -= '0';
26 else
27 c -= 'a'-10;
28 if (c >= base)
29 break;
30 i = i * base + c;
31 fFound = TRUE;
32 }
33 if (fFound)
34 return i;
35 else
36 return -1;
37}
diff --git a/v4.0/src/CMD/FC/STRING.ASM b/v4.0/src/CMD/FC/STRING.ASM
new file mode 100644
index 0000000..d72f7a4
--- /dev/null
+++ b/v4.0/src/CMD/FC/STRING.ASM
@@ -0,0 +1,115 @@
1;
2; string functions for lattice C
3;
4
5.xlist
6include version.inc
7include cmacros.inc
8.list
9
10sBegin data
11assumes ds,data
12
13externB XLTab
14externB XUTab
15
16sEnd
17
18sBegin code
19assumes cs,code
20
21externP strlen
22
23;
24; strbscan (string, set) returns pointer to 1st char in set or end
25;
26cProc strbscan,<PUBLIC>,<SI,DI>
27parmW str
28parmW set
29cBegin
30 push ds
31 pop es
32 cCall strlen,<set>
33 inc ax
34 mov bx, ax
35 mov si,str
36 cld
37bscan:
38 lodsb
39 mov cx,bx
40 mov di,set
41;
42; While not in the set
43;
44 repnz scasb
45 jnz bscan
46 lea ax,[si-1]
47cEnd
48
49;
50; strbskip ( string, set ) returns pointer to 1st char not in set
51;
52cProc strbskip,<PUBLIC>,<SI,DI>
53parmW str
54parmW set
55cBegin
56 push ds
57 pop es
58 cCall strlen,<set>
59 inc ax
60 mov bx, ax
61 mov si,str
62 cld
63bskip:
64 lodsb
65 or al,al
66 jz eskip
67 mov cx,bx
68 mov di,set
69;
70; While not in the set
71;
72 repnz scasb
73 jz bskip
74eskip:
75 lea ax,[si-1]
76cEnd
77
78;
79; strpre (s1, s2) returns -1 if s1 is a prefix of s2, 0 otherwise. Ignores
80; case.
81;
82cProc strpre,<PUBLIC>,<si,di>
83parmW pref
84parmW str
85cBegin
86 cld
87 mov si,pref
88 mov di,str
89 mov bx,dataOFFSET xltab
90preCompare:
91 lodsb
92 mov ah,[di]
93 inc di
94
95 xlat
96 xchg ah,al
97 xlat
98
99 cmp ah,al
100 jnz preDif
101 or ah,ah
102 jnz preCompare
103preYes:
104 mov ax,-1
105 jmp short preDone
106preDif:
107 or ah,ah
108 jz preYes
109 xor ax,ax
110preDone:
111cEnd
112
113sEnd
114
115end
diff --git a/v4.0/src/CMD/FC/TOOLS.H b/v4.0/src/CMD/FC/TOOLS.H
new file mode 100644
index 0000000..f6bc435
--- /dev/null
+++ b/v4.0/src/CMD/FC/TOOLS.H
@@ -0,0 +1,94 @@
1/*
2 * tools.h - Header file for accessing TOOLS.LIB routines
3 * includes stdio.h and ctype.h
4 *
5 * 4/14/86 dl added U_* flags for upd return values
6 *
7 * 31-Jul-1986 mz Add Connect definitions
8 */
9
10#define TRUE -1
11#define FALSE 0
12
13#if MSDOS
14#define PSEPSTR "\\"
15#define PSEPCHR '\\'
16#else
17#define PSEPSTR "/"
18#define PSEPCHR '/'
19#endif
20
21typedef char flagType;
22typedef long ptrType;
23
24#define SETFLAG(l,f) ((l) |= (f))
25#define TESTFLAG(v,f) (((v)&(f))!=0)
26#define RSETFLAG(l,f) ((l) &= ~(f))
27
28#define SHIFT(c,v) {c--; v++;}
29
30#define LOW(w) ((int)(w)&0xFF)
31#define HIGH(w) LOW((int)(w)>>8)
32#define WORD(h,l) ((LOW((h))<<8)|LOW((l)))
33#define POINTER(seg,off) ((((long)(seg))<<4)+ (long)(off))
34
35#define FNADDR(f) (f)
36
37#define SELECT if(FALSE){
38#define CASE(x) }else if((x)){
39#define OTHERWISE }else{
40#define ENDSELECT }
41
42/* buffer description for findfirst and findnext */
43
44struct findType {
45 char reserved[21]; /* reserved for start up */
46 char attr; /* attribute found */
47 unsigned time; /* time of last modify */
48 unsigned date; /* date of last modify */
49 long length; /* file size */
50 char name[13]; /* asciz file name */
51};
52
53/* attributes */
54#define A_RO 1 /* read only */
55#define A_H 2 /* hidden */
56#define A_S 4 /* system */
57#define A_V 8 /* volume id */
58#define A_D 16 /* directory */
59#define A_A 32 /* archive */
60
61#define A_MOD (A_RO+A_H+A_S+A_A) /* changeable attributes */
62
63#define HASATTR(a,v) TESTFLAG(a,v) /* true if a has attribute v */
64
65extern char XLTab[], XUTab[];
66
67#define MAXARG 128
68#define MAXPATHLEN 128
69
70#include "ttypes.h"
71
72struct vectorType {
73 int max; /* max the vector can hold */
74 int count; /* count of elements in vector */
75 unsigned elem[1]; /* elements in vector */
76};
77
78/* return flags for upd */
79#define U_DRIVE 0x8
80#define U_PATH 0x4
81#define U_NAME 0x2
82#define U_EXT 0x1
83
84/* Connect definitions */
85
86#define REALDRIVE 0x8000
87#define ISTMPDRIVE(x) (((x)&REALDRIVE)==0)
88#define TOKTODRV(x) ((x)&~REALDRIVE)
89
90/* Heap Checking return codes */
91
92#define HEAPOK 0
93#define HEAPBADBEGIN -1
94#define HEAPBADNODE -2
diff --git a/v4.0/src/CMD/FC/TTYPES.H b/v4.0/src/CMD/FC/TTYPES.H
new file mode 100644
index 0000000..739df6f
--- /dev/null
+++ b/v4.0/src/CMD/FC/TTYPES.H
@@ -0,0 +1,71 @@
1/* ttypes.h - type definitions for tools library */
2
3#include <stdio.h>
4
5/* assembly routines */
6flagType int25 (char, char far *, unsigned int, unsigned int);
7flagType int26 (char, char far *, unsigned int, unsigned int);
8flagType kbhit ();
9char getch ();
10void Move (char far *, char far *, unsigned int);
11void Fill (char far *, char, unsigned int);
12char *strbscan (char *, char *);
13char *strbskip (char *, char *);
14flagType strpre (char *, char *);
15int strcmpi (unsigned char *, unsigned char *);
16char *fcopy (char *, char *);
17long getlpos ();
18void getlinit ( char far *, int, int);
19int getl (char *, int);
20
21/* c routines */
22/*global*/ char *lower(char *);
23/*global*/ char *upper(char *);
24/*global*/ char *error(void);
25/*global*/ long fexpunge(char *,FILE *);
26/*global*/ char *fcopy(char *,char *);
27/*global*/ int fgetl(char *,int ,FILE *);
28/*global*/ int fputl(char *,int ,FILE *);
29/*global*/ int ffirst(char *,int ,struct findType *);
30/*global*/ int fnext(struct findType *);
31/*global*/ char forsemi(char *,char ( *)(), );
32/*global*/ long freespac(int );
33/*global*/ long sizeround(long ,int );
34/*global*/ int rspawnl(char *,char *,char *, );
35/*global*/ int rspawnv(char *,char *,char *,char *[0]);
36/*global*/ char *MakeStr(char *);
37/*global*/ int mapenv(char *,char *);
38/*global*/ char *ismark(char *);
39/*global*/ FILE *swopen(char *,char *);
40/*global*/ int swclose(FILE *);
41/*global*/ int swread(char *,int ,FILE *);
42/*global*/ char *swfind(char *,FILE *,char *);
43/*global*/ char *getenvini(char *,char *);
44/*global*/ char fPathChr(int );
45/*global*/ char fSwitChr(int );
46/*global*/ char fPFind(char *,unsigned int * *);
47/*global*/ char findpath(char *,char *,char );
48/*global*/ FILE *pathopen(char *,char *,char *);
49/*global*/ int forfile(char *,int ,void ( *)(), );
50/*global*/ int rootpath(char *,char *);
51/*global*/ int sti(char *,int );
52/*global*/ int ntoi(char *,int );
53/*global*/ int strcmps(unsigned char *,unsigned char *);
54/*global*/ int strcmpis(unsigned char *,unsigned char *);
55/*global*/ char *strend(char *);
56/*global*/ int upd(char *,char *,char *);
57/*global*/ int drive(char *,char *);
58/*global*/ int extention(char *,char *);
59/*global*/ int filename(char *,char *);
60/*global*/ int filenamx(char *,char *);
61/*global*/ int path(char *,char *);
62/*global*/ int curdir(char *,char );
63/*global*/ int getattr(char *);
64/*global*/ int fdelete(char *);
65/*global*/ char *fmove(char *, char *);
66/*global*/ char *fappend(char *, int);
67/*global*/ long ctime2l(char *);
68/*global*/ struct tm *ctime2tm(char *);
69/*global*/ long date2l(int, int, int, int, int, int);
70/*global*/ struct vectorType *VectorAlloc(int);
71/*global*/ flagType fAppendVector(struct vectorType**, unsigned int);
diff --git a/v4.0/src/CMD/FC/UPDATE.C b/v4.0/src/CMD/FC/UPDATE.C
new file mode 100644
index 0000000..8263db1
--- /dev/null
+++ b/v4.0/src/CMD/FC/UPDATE.C
@@ -0,0 +1,128 @@
1/*
2 * update takes a def string and update and fills the
3 * update with missing defs the update allowing
4 * specification of missing parameters.
5 * the parts are: ^{[~:]#:}{%#</|\>}{[~.]#}{.[~./\:]}$
6 * maximum size of MAXPATHLEN (80) bytes
7 *
8 * 4/14/86 dl use U_ flags
9 *
10 */
11
12#include "tools.h"
13
14int upd (def, update, dst)
15char *def, *update, *dst;
16{
17 char *p, buf[MAXPATHLEN];
18 int f;
19
20 f = 0;
21 p = buf;
22#if MSDOS
23 if (drive(update, p) || drive (def, p))
24 SETFLAG(f, U_DRIVE);
25 p += strlen (p);
26#endif
27
28 if (path(update, p) || path (def, p))
29 SETFLAG(f, U_PATH);
30 p += strlen (p);
31
32 if (filename(update, p) || filename (def, p))
33 SETFLAG(f, U_NAME);
34 p += strlen (p);
35
36 if (extention(update, p) || extention (def, p))
37 SETFLAG(f, U_EXT);
38
39 strcpy (dst, buf);
40
41 return f;
42}
43
44#if MSDOS
45/* copy a drive from source to dest if present, return TRUE if we found one */
46drive (src, dst)
47char *src, *dst;
48{
49 register char *p;
50
51 p = strbscan (src, ":");
52 if (*p++ == NULL)
53 p = src;
54 strcpy (dst, src);
55 dst[p-src] = 0;
56 return strlen (dst) != 0;
57}
58#endif
59
60/* copy an extention from source to dest if present. include the period.
61 Return TRUE if one found.
62 */
63extention (src, dst)
64char *src, *dst;
65{
66 register char *p, *p1;
67
68 p = src - 1;
69 while (*(p=strbscan(1+(p1=p), ".")) != NULL)
70 ;
71 /* p1 points to last . or begin of string p points to eos */
72 if (*strbscan (p1, "\\/:") != NULL || *p1 != '.')
73 p1 = p;
74 strcpy (dst, p1);
75 return strlen (dst) != 0;
76}
77
78/* copy a filename part from source to dest if present. return true if one
79 is found
80 */
81filename (src, dst)
82char *src, *dst;
83{
84 register char *p, *p1;
85
86 p = src-1;
87 while (*(p=strbscan (p1=p+1, "\\/:")) != NULL)
88 ;
89 /* p1 points after last / or at bos */
90 p = strbscan (p1, ".");
91 strcpy (dst, p1);
92 dst[p-p1] = 0;
93 return strlen (dst) != 0;
94}
95
96/* copy a filename.ext part from source to dest if present. return true if one
97 is found
98 */
99fileext (src, dst)
100char *src, *dst;
101{
102 *dst = '\0';
103 if ( filename (src, dst) ) {
104 dst += strlen (dst);
105 extention (src, dst);
106 return TRUE;
107 }
108 return FALSE;
109}
110
111/* copy the paths part of the file description. return true if found
112 */
113path (src, dst)
114char *src, *dst;
115{
116 register char *p, *p1;
117
118 if (*(p=strbscan (src, ":")) != NULL)
119 src = p+1;
120 p = src-1;
121 /* p points to beginning of possible path (after potential drive spec) */
122 while (*(p=strbscan (p1=p+1, "\\/:")) != NULL)
123 ;
124 /* p1 points after final / or bos */;
125 strcpy (dst, src);
126 dst[p1-src] = 0;
127 return strlen (dst) != 0;
128}
diff --git a/v4.0/src/CMD/FC/XTAB.ASM b/v4.0/src/CMD/FC/XTAB.ASM
new file mode 100644
index 0000000..3b42529
--- /dev/null
+++ b/v4.0/src/CMD/FC/XTAB.ASM
@@ -0,0 +1,100 @@
1;
2; xlat tables for case conversion
3;
4
5.xlist
6include version.inc
7include cmacros.inc
8.list
9
10sBegin data
11
12public _XLTab, _XUTab
13
14assumes ds,data
15
16;
17; table for lowercase translation
18;
19
20_XLTab LABEL BYTE
21
22 db 000h, 001h, 002h, 003h, 004h, 005h, 006h, 007h
23 db 008h, 009h, 00Ah, 00Bh, 00Ch, 00Dh, 00Eh, 00Fh
24
25 db 010h, 011h, 012h, 013h, 014h, 015h, 016h, 017h
26 db 018h, 019h, 01Ah, 01Bh, 01Ch, 01Dh, 01Eh, 01Fh
27
28 db ' !"#$%&', 027h
29 db '()*+,-./'
30
31 db '01234567'
32 db '89:;<=>?'
33
34 db '@abcdefg'
35 db 'hijklmno'
36
37 db 'pqrstuvw'
38 db 'xyz[\]^_'
39
40 db '`abcdefg'
41 db 'hijklmno'
42
43 db 'pqrstuvw'
44 db 'xyz{|}~', 07Fh
45
46 db 080h, 081h, 082h, 083h, 084h, 085h, 086h, 087h
47 db 088h, 089h, 08Ah, 08Bh, 08Ch, 08Dh, 08Eh, 08Fh
48 db 090h, 091h, 092h, 093h, 094h, 095h, 096h, 097h
49 db 098h, 099h, 09Ah, 09Bh, 09Ch, 09Dh, 09Eh, 09Fh
50 db 0A0h, 0A1h, 0A2h, 0A3h, 0A4h, 0A5h, 0A6h, 0A7h
51 db 0A8h, 0A9h, 0AAh, 0ABh, 0ACh, 0ADh, 0AEh, 0AFh
52 db 0B0h, 0B1h, 0B2h, 0B3h, 0B4h, 0B5h, 0B6h, 0B7h
53 db 0B8h, 0B9h, 0BAh, 0BBh, 0BCh, 0BDh, 0BEh, 0BFh
54 db 0C0h, 0C1h, 0C2h, 0C3h, 0C4h, 0C5h, 0C6h, 0C7h
55 db 0C8h, 0C9h, 0CAh, 0CBh, 0CCh, 0CDh, 0CEh, 0CFh
56 db 0D0h, 0D1h, 0D2h, 0D3h, 0D4h, 0D5h, 0D6h, 0D7h
57 db 0D8h, 0D9h, 0DAh, 0DBh, 0DCh, 0DDh, 0DEh, 0DFh
58 db 0E0h, 0E1h, 0E2h, 0E3h, 0E4h, 0E5h, 0E6h, 0E7h
59 db 0E8h, 0E9h, 0EAh, 0EBh, 0ECh, 0EDh, 0EEh, 0EFh
60 db 0F0h, 0F1h, 0F2h, 0F3h, 0F4h, 0F5h, 0F6h, 0F7h
61 db 0F8h, 0F9h, 0FAh, 0FBh, 0FCh, 0FDh, 0FEh, 0FFh
62
63_XUTab LABEL BYTE
64
65 db 000h, 001h, 002h, 003h, 004h, 005h, 006h, 007h
66 db 008h, 009h, 00Ah, 00Bh, 00Ch, 00Dh, 00Eh, 00Fh
67 db 010h, 011h, 012h, 013h, 014h, 015h, 016h, 017h
68 db 018h, 019h, 01Ah, 01Bh, 01Ch, 01Dh, 01Eh, 01Fh
69 db ' !"#$%&', 027h
70 db '()*+,-./'
71 db '01234567'
72 db '89:;<=>?'
73 db '@ABCDEFG'
74 db 'HIJKLMNO'
75 db 'PQRSTUVW'
76 db 'XYZ[\]^_'
77 db '`ABCDEFG'
78 db 'HIJKLMNO'
79 db 'PQRSTUVW'
80 db 'XYZ{|}~', 07Fh
81 db 080h, 081h, 082h, 083h, 084h, 085h, 086h, 087h
82 db 088h, 089h, 08Ah, 08Bh, 08Ch, 08Dh, 08Eh, 08Fh
83 db 090h, 091h, 092h, 093h, 094h, 095h, 096h, 097h
84 db 098h, 099h, 09Ah, 09Bh, 09Ch, 09Dh, 09Eh, 09Fh
85 db 0A0h, 0A1h, 0A2h, 0A3h, 0A4h, 0A5h, 0A6h, 0A7h
86 db 0A8h, 0A9h, 0AAh, 0ABh, 0ACh, 0ADh, 0AEh, 0AFh
87 db 0B0h, 0B1h, 0B2h, 0B3h, 0B4h, 0B5h, 0B6h, 0B7h
88 db 0B8h, 0B9h, 0BAh, 0BBh, 0BCh, 0BDh, 0BEh, 0BFh
89 db 0C0h, 0C1h, 0C2h, 0C3h, 0C4h, 0C5h, 0C6h, 0C7h
90 db 0C8h, 0C9h, 0CAh, 0CBh, 0CCh, 0CDh, 0CEh, 0CFh
91 db 0D0h, 0D1h, 0D2h, 0D3h, 0D4h, 0D5h, 0D6h, 0D7h
92 db 0D8h, 0D9h, 0DAh, 0DBh, 0DCh, 0DDh, 0DEh, 0DFh
93 db 0E0h, 0E1h, 0E2h, 0E3h, 0E4h, 0E5h, 0E6h, 0E7h
94 db 0E8h, 0E9h, 0EAh, 0EBh, 0ECh, 0EDh, 0EEh, 0EFh
95 db 0F0h, 0F1h, 0F2h, 0F3h, 0F4h, 0F5h, 0F6h, 0F7h
96 db 0F8h, 0F9h, 0FAh, 0FBh, 0FCh, 0FDh, 0FEh, 0FFh
97
98sEnd
99
100end