IMD 1.16: 31/05/2007 20:05:27 FOGCPM.116 CAL C 0README UT2README UTSUTOOL DOC1UTOOL MANw UTOOL2 MAN1-07-00 86 CAT C &'(CH C )*+,CMP C -.COMM C "/0123CRT C 45FIND C $6789:HCAT C ;<=>INCL C ?@AKWIC C BCLLINE C DLPR C EFGMAKDOC C HIJMYLIB3 C ]KLMNOPPREP C +QRSTUVSORT C 9WXYZ[\]^SPLIT C _`abSPLTSCANC ScdefghijklmSPLTSCANDOCAnopqrstuvTABS C #wxyz{TAIL C |}TEE C ~TR C UNIQ C UNROT C UTDIR C VSPLIT C WC COM<WC C README UT -CPM116 DOC--FOGCPM116/* cal.c -- UTOOL. Calendar. Print lines with date match. author: David H. Wolen last change: 6/2/83 usage: cal file mm/dd/yy prog |cal -r mm/dd/yy mm/dd/yy cal file -ge mm/dd/yy options: -g (>) -l (<) -e (=) -r (>= date1 and <= date2) input: file or STDIN output: STDOUT notes: -ge, -le, -gl, are ok (effect is "or" relation) only first valid date on line is examined for match if -r, no other options are allowed if no options, default is -e linkage: a:clink cal -f dio -ca (uses deff3.crl) */ #include "a:bdscio.h" #include "a:dio.h" #define STDIN 0 #define STDOUT 1 #define BASEYR 45 /* yy < BASEYR converted to 20yy */ /* yy >= BASEYR converted to 19yy */ struct date {int day; int month; int year; }; main(argc,argv) int argc; char *argv[]; { struct dateThis library contains updates and a few bug fixes to the utools programs on -fog/utl.026 through .030. The following files are included: readme.ut2 - this file utool2.mqn - squeezed "manual pages" for the .com files included field.com - select fields from a file. This works with fields that are comma separated. You could use it to re-arrange a MailMerge address file. This is a new program. fieldcc.com - select column delimited fields from a file. This works with fields that are always in the same columns on a file. You could use it to re-arrange dates from yy/mm/dd to mm/dd/yy. This is a new program. find.com - find patterns in text files. This is an update of the version currently in foglib. The main addition is the ability to handle "index cards". These are multi-line records (up to 2K characters each) that are treated as one continued line. findmf.com - simple pattern match over multiple files (uses wildcards). This is a new program. lpr.com - send stdin tfile: readme.uts date: 9/10/83 author: David H. Wolen This disk contains the source for the UTOOLS -- a set of utility programs I recently submitted to the foglib. See the appropriate foglib disks for user oriented documentation. The programs are written in C, using version 1.46 of the BDS compiler. The following notes about bringing up the UTOOLS on your own are disorganized and probably incomplete -- that should be fair warning. Also, note that you'll need some files from the BDS C distribution package to complete this package. I'm not including them because I'm not sure if the source for them is public domain. 1. I've enabled alloc and free by making the appropriate change to bdscio.h and recompiling the indicated libraries. See the instructions in bdscio.h. Alloc and free are only (I think) used by the tail tool. The other tools that do storage allocation don't need to free it so they use sbrk instead (reducing memory requirements and the size of the .com file). 2. I've enabled console buffering by making the appropriate change to dio.h. See the instructions in dio.h. 3. Just about all the UTOOLS use something from mylib3.c. I've made it my deff3.crl. There are probably some routines on mylib3.c that aren't used by the UTOOLS. Note -- there's a bug in 1.46 that prevents deff3.crl from being picked up automatically if you compile with source on b and b as the logged drive. 4. Before my upgrade to double density, I kept dio.h and dio.crl on the same drive as the source. With double density, I keep everything but the source on A and compile with A as the logged drive. Some of the "linkage" comments in the source code reflect the first method, while others reflect the second -- you've been warned. Also, you may have to change the drive designation in the #include lines to correspond to your compile procedure. 5. The utdir tool needs wildexp.c which comes with the WTW Associates 341 N. First St. Campbell, Ca. 95008 Documentation for the UTOOLS (utool.doc 2/23/83) (author of both tools and documentation: David H. Wolen) Mos o th UTOOL ar derive fro th program describe i Softwar Tool an Softwar Tool i Pasca (bot b Kernigha an Plauger) The wer writte i an teste o a Osborn (Z80A CP/ 2.2 singl density) Th UTOOL provid feature calle I/ redirectio an pipes Externally thes feature resembl thos provide unde th UNI operatin syste -- henc th nam UTOOLS Th manua pag fo eac UTOO describe allow abl inpu an output I th inpu i STDIN tha mean inpu ca com fro th keyboar o fro file I th outpu i STDOUT tha mean th outpu ca g t th screen file bot scree an file o serv a inpu t anothe UTOOL Th follow in example assum tha th UTOOL ar o th drive an fil t b rea o writte wil b o th drive an i th logge drive It' bes t mak th logge driv becaus th UTOOL sometime hav t mak an releas temporar fil o th logge drive Ther probabl isn' enoug roo o fo that. Examples of I/O redirection and piping: 1 Keyboar inpu an scree outpu (usefu fo learnin ho UTOOL works). B>a:cat ca wil wait fo yo t typ i dat an wil ech i t th scree afte yo typ eac line En eac lin wit a:cat >outfile 3 Keyboar input Outpu t bot th scree an file Note no space between the + and the file name. B>a:cat +outfile .pa 4 Fil inpu an scree output Again not tha ther can' be any space between the < and the file name. B>a:cat a:cat |a:lpr Thi exampl woul sen th line yo type a th keyboar to the printer (after you typed the ^z to finish). Here are some useful pipelines. 1 Mak keywor i contex index treatin uppe an lowe cas alph th same Displa o th screen pausin afte eac screen full. Input is a normal ascii file. B>a:kwic ) -l (<) -e (=) -r (>= date1 and <= date2) input: file or STDIN output: STDOUT notes: -ge, -le, -gl, are ok (effect is "or" relation) only first valid date on line is examined for match if -r, no other options are allowed if no options, default is -e */ /* cat.c -- UTOOL. Concatenate files ver 2. author: David H. Wolen last change: 6/12/83 usage: (1) copy console input to file (^z to stop) cat >ofile (2) concat inp files and write on output file cat ifile1 ifile2 >ofile (3) concat input files and pass to std input of prog2 cat ifile1 ifile2 |prog2 (4) clean up WordStar doc file cat -w file.doc >ofile option: -w clean up WordStar doc files by zeroing hi bits and converting strange characters to blanks input: files or STDIN output: STDOUT */ /* ch.c -- UTOOL. Change pattern in text file. author: David H. Wolen last change: 3/4/83 usage: ch pattern [newstuff] input: STDIN output: STDOUT notes: 1. metacharacters in pattern (same as find) % begin of line # # enclose capital letters " " enclose imbedded blanks ? match any char except newline $ end of line [c1-c2] char class [!c1-c2] negated char class * closure (0 or more occurrences of prev 1 char pattern) escaped chars: \n (newline) \t (tab) \r (cr) \f (form feed) \b (backspace) \q (") \p (#) 2. If newstuff is omitted, deletion of pattern occurs. 3. Newstuff consists of zero or more of the following: c literal char & ditto, i.e. whatever was matched \c escaped char # # and " " as above */ /* cmp.c -- UTOOL. Compare 2 files or file and std input for equality. author: David H. Wolen last change: 11/23/82 usage: cmp file1 file2 prog |cmp file1 input: 2 files or file and STDIN output: STDOUT */ /* comm.c -- UTOOL. Print lines common to two sorted files author: David H. Wolen last change: 11/29/82 usage: comm -123 file1 file2 prog |comm file1 options: -n (n=1,2,3) print only named columns (default is print all 3) input: 2 files or file and STDIN  output: STDOUT notes: (1) if only one file is given, STDIN is file 2 (2) col 1 is lines only in file 1 col 2 is lines only in file 2 col 3 is lines in both files */ /* crt.c -- UTOOL. Display text file (including ws doc) a screen at a time. author: David H. Wolen last change: 6/12/83 usage: crt -n file prog |crt forward a screen anything else to quit option: -n line numbers input: file or STDIN output: STDOUT */ /* find.c -- UTOOL. Find patterns in text files (ver. 3) author: David H. Wolen last change: 5/2/83 usage: find [-axn] pattern1 [pattern2 ... pattern10] options: -a output lines which contain all patterns (default is output lines matching any pattern) -x output lines that fail the match criteria -n line numbers for output  -c just output count of matching lines -f fold (ignore case in character comparisons) input: STDIN output: STDOUT notes: 1. -x pat1 pat2 : output if line contains neither pat 2. -ax pat1 pat2 : output if line doesn't contain both pats 3. metacharacters in pattern % match pattern at beginning of line # # enclose capital letters " " enclose embedded blanks ? match any char except newline $ end of line [c1-c2] character class [!c1-c2] negated character class * closure (0 or more occurrences of prev pattern) escaped chars: \n (newline) \t (tab) \r (cr) \f (form feed) \b (backspace) \q (") \p (#) 4. first pattern can't begin with "-" 5. up to MAXPATS patterns allowed (currently 10) 6. if -c and -n, the latter will be ignored */ /* hcat.c -- UTOOL. Horizontally concatenate text files. author: David H. Wolen last change: 3/16/83 usage: hcat file1 n2 file2 n3 file3 ... hcat file1 31 file2 51 file3 (begin file1 in col 1, file2 in col 31, file3 in col 51) input: one or more files output: STDOUT notes: 1. max of 6 input files 2. first file starts in col 1 */ /* incl.c -- UTOOL. Expand included files author: David H. Wolen last change: 12/5/82 usage: incl to resume, anything else to quit. (default false) input: STDIN output: printer notes: (1) form feed after each page and at eof (2) if both -l and -n are used, margin value must preceed page size value. */ /* prep.c -- UTOOL. Convert a text file (including ws doc files) to one word per line. author: David H. Wolen last change: 3/9/83 usage: prep outfile n1-n2 n3-n4 ... fieldcc outfile 1-5 8-12 6-7 input: STDIN output: STDOUT notes: (a) ni are origin 1. (b) if a field is invalid for a particular line, the output for that field will be null. (c) a maximum of 10 fields are allowed */ /* find.c -- UTOOL. Find patterns in text files (ver. 3.1) author: David H. Wolen last change: 12/18/83 usage: find [-axn] pattern1 [pattern2 ... pattern10] options: -a output lines which contain all patterns (default is output lines matching any pattern) -x output lines that fail the match criteria -n line numbers for output -c just output count of matching lines -f fold (ignore case in character comparisons) input: STDIN output: STDOUT notes: 1. -x pat1 pat2 : output if line contains neither pat 2. -ax pat1 pat2 : output if line doesn't contain both pats 3. metacharacters in pattern % match pattern at beginning of line # # enclose capital letters " " enclose embedded blanks ? match any char except newline $ end of line  [c1-c2] character class [!c1-c2] negated character class * closure (0 or more occurrences of prev pattern) escaped chars: \n (newline) \t (tab) \r (cr) \f (form feed) \b (backspace) \q (") \p (#) 4. first pattern can't begin with "-" 5. up to MAXPATS patterns allowed (currently 10) 6. if -c and -n, the latter will be ignored 7. version 3.1 handles continued input lines indicated by & in column one. The max continued line length is 2048 char. With keyboard input and output, there is now a lag since it has to see if the following line begins with &. */ /* findmf.c -- UTOOL. Simple pattern match with multiple file input (including wildcards). Ignores case. author: David H. Wolen last change: 12/14/83 usage: findmf pat filespec  findmf pat *.c findmf pat *.* !*.com (the *.* is required for this program) findmf pat fn.ft fn.ft fn.ft findmf pat test?.c findmf "last change" *.c input: files output: STDOUT notes: (a) wildcards of * (match one or more characters) and ? (match a single character) are allowed in filespec (b) the construction *.* !*.com means all files except .com (c) drive prefixes are allowed (d) output lines are prefixed with file name (e) the expanded filespec can't contain more than 200 files */ /* lpr.c -- UTOOL. Send stdin to printer author: David H. Wolen last change: 10/14/84 usage: prog |lpr -lnp 5 55 lpr to resume, anything else to quit.  (default false) input: STDIN output: printer notes: (1) form feed after each page and at eof (2) if both -l and -n are used, margin value must preceed page size value. (3) handles tabs (tabs every 8 spaces) (4) ignores any imbedded form feeds in input */ /* sort.c -- UTOOL. (ver. 2.2) Incore sort of ascii lines. Max file size 2000 lines or about 30K. author: David H. Wolen last change: 9/22/85 usage: sort outfile sort as part of the description of a file indicates that the program is distributed on a "try first, pay if you like it" basis. If you find the program(s) meet your need, please refer to the author's documentation for information on becoming a registered user. Only by registering and paying for the programs you like and use will the authors of such programs continue development. Often, more complete documentation, additional modules, and new releases are available only to registered users. DISK 1 of 3. UTOOLS -- collection of utilities written in 'C' Filename Description -07-00 .86 This is the release date of the disk. -CPM116 .DOC This is the description of the disk contents. UTOOL .DOC BDA0 7K [UTOOLS 1 of 67] A collection of Unix-like utilities written in 'C' (from Kernighan and Plauger books. Written in BDS 'C' ver 1.46 Includes source code, sample programs, and much more. UTOOL2 .MAN 2192 7K [UTOOLS 2 of 67] UTOOL .MAN 87D6 15K [UTOOLS 3 of 67] CMP .C C5D6 2K [UTOOLS 4 of 67] COMM .C 1999 5K [UTOOLS 5 of 67] CRT .C 0FBA 2K [UTOOLS 6 of 67] FIND .C 0C7C 5K [UTOOLS 7 of 67] HCAT .C DF7E 4K [UTOOLS 8 of 67] INCL .C 8340 3K [UTOOLS 9 of 67] KWIC .C E3A3 2K [UTOOLS 10 of 67] LLINE .C 8DB2 1K [UTOOLS 11 of 67] LPR .C 174F 3K [UTOOLS 12 of 67] MAKDOC .C 231B 3K [UTOOLS 13 of 67] MYLIB3 .C 4067 12K [UTOOLS 14 of 67] PREP .C 97F0 6K [UTOOLS 15 of 67] SORT .C 9B72 8K [UTOOLS 16 of 67] SPLIT .C 248D 4K [UTOOLS 17 of 67] SPLTSCAN.C 266A 11K [UTOOLS 18 of 67] SPLTSCAN.DOC E3AC 9K [UTOOLS 19 of 67] TABS .C 879B 5K [UTOOLS 20 of 67] TAIL .C 07C9 2K [UTOOLS 21 of 67] TEE .C 5459 3K [UTOOLS 22 of 67] TR .C EEA3 4K [UTOOLS 23 of 67] UNIQ .C EC89 2K [UTOOLS 24 of 67] UNROT .C 9D17 3K [UTOOLS 25 of 67] UTDIR .C 521C 2K [UTOOLS 26 of 67] VSPLIT .C 2173 3K [UTOOLS 27 of 67] WC .COM B7CF 8K [UTOOLS 28 of 67] Counts lines, words, and characters. WC .C 1383 1K [UTOOLS 29 of 67] README .UT D67D 1K [UTOOLS 30 of 67] README .UT2 35C2 2K [UTOOLS 31 of 67] README .UTS 0268 3K [UTOOLS 32 of 67] CAL .C E3D6 6K [UTOOLS 33 of 67] CAT .C FBAF 3K [UTOOLS 34 of 67] CH .C A21F 4K [UTOOLS 35 of 67] INCL .C 8340 3K [UTOOLS 9 of 67] KWIC .C E3A3 2K [UTOOLS 10 of 67] LLINE .C 8DB2 1K [UTOOLS 11 of 67] LPR .C 174F 3K [UTOOLS 12 of 67] MAKDOC .C 231B 3K [UTOOLS 13 of 67] MYLIB3 .C 4067 12char in dest are mapped to last char in dest. Adjacent instances of such chars in src cause a single instance of last char in dest to be output. (6) use " " to enclose blanks in src and dest (7) use # # to enclose capital letters in src and dest */ /* uniq.c -- UTOOL. Filters out adjacent duplicate lines in sorted file. Lines must be identical (including same length) to be filtered out. author: David H. Wolen last change: 12/2/82 option: -c prefixes each output line with count usage: sort outfile -c input: STDIN output: STDOUT */ /* unrot.c -- UTOOL. Unrotate lines rotated by kwic. Last step in making keyword-in-context index. author: David H. Wolen last change: 12/2/82 usage: kwic outfile input: STDIN output: STDOUT */ /* utdir.c -- UTOOL. Sorted file directory. author: David H. Wolen last change: 6/5/83 usage: utdir *.* all files on current drive utdir !*.com all files on current drive except .com utdir b:*.* !b:*.c all files on b: except .c utdir ?.com all .com files with single letter file name on current drive options: none input: command line only output: STDOUT notes: 1. max of 200 files after expansion 2. metacharacters in filename: ! except ? wildcard match a single character * wildcard match 1 or more characters */ /* vsplit.c -- UTOOL. Vertically split a text file. author: David H. Wolen last change: 2/20/83 usage: vsplit cc col vsplit ll 80 (output first 80 cols of each line) vsplit lr 10 (delete first 10 cols, output rest) vsplit rl 10 (delete last 10 cols, output rest) vsplit rr 15 (output last 15 cols) options: ll split from left, output left part lr split from left, output right part rl split from right, output left part rr split from right, output right part input: STDIN output: STDOUT notes: 1. If input line contains only , so will output 2. If ll and col  > line length, output will be whole line 3. If lr and col > line length, output will be 4. If ll and col <= 0, output will be 5. If lr and col <= 0, output will be whole line 6. If rl and col > line length, output will be 7. If rr and col > line length, output will be whole line 8. If rl and col <= 0, output will be whole line 9. If rr and col <= 0, output will be */ /* wc.c -- UTOOL. Count lines, words and characters in standard input. Can handle Wordstar doc files. author: David H. Wolen last change: 9/9/82 usage: wc , so will output 2. If ll and col /* field.c -- UTOOL. select fields from a file author: David H. Wolen last change: 11/14/83 usage: field n1 n2 ... input: STDIN output: STDOUT notes: (a) fields are numbered from 1 (b) a field may be selected more than once (c) fields are separated by commas on input and output (d) maximum input and output line length is 149 characters (e) maximum number of input fields is 70 */ /* fieldcc.c -- UTOOL. Select column delimited fields from a file author: David H. Wolen last change: 5/26/84 usage: fieldcc outfile n1-n2 n3-n4 ... fieldcc outfile 1-5 8-12 6-7 input: STDIN output: STDOUT notes: (a) ni are origin 1. (b) if a field is invalid for a particular line, the output for that field will be null. (c) a maximum of 10 fields are allowed */ /* find.c -- UTOOL. Find patterns in text files (ver. 3.1) author: David H. Wolen last change: 12/18/83 usage: find [-axn] pattern1 [pattern2 ... pattern10] options: -a output lines which contain all patterns (default is output lines matching any pattern) -x output lines that fail the match criteria -n line numbers for output -c just output count of matching lines -f fold (ignore case in character comparisons) input: STDIN output: STDOUT notes: 1. -x pat1 pat2 : output if line contains neither pat 2. -ax pat1 pat2 : output if line doesn't contain both pats 3. metacharacters in pattern % match pattern at beginning of line # # enclose capital letters " " enclose embedded blanks ? match any char except newline $ end of line  [c1-c2] character class [!c1-c2] negated character class * closure (0 or more occurrences of prev pattern) escaped chars: \n (newline) \t (tab) \r (cr) \f (form feed) \b (backspace) \q (") \p (#) 4. first pattern can't begin with "-" 5. up to MAXPATS patterns allowed (currently 10) 6. if -c and -n, the latter will be ignored 7. version 3.1 handles continued input lines indicated by & in column one. The max continued line length is 2048 char. With keyboard input and output, there is now a lag since it has to see if the following line begins with &. */ /* findmf.c -- UTOOL. Simple pattern match with multiple file input (including wildcards). Ignores case. author: David H. Wolen last change: 12/14/83 usage: findmf pat filespec  findmf pat *.c findmf pat *.* !*.com (the *.* is required for this program) findmf pat fn.ft fn.ft fn.ft findmf pat test?.c findmf "last change" *.c input: files output: STDOUT notes: (a) wildcards of * (match one or more characters) and ? (match a single character) are allowed in filespec (b) the construction *.* !*.com means all files except .com (c) drive prefixes are allowed (d) output lines are prefixed with file name (e) the expanded filespec can't contain more than 200 files */ /* lpr.c -- UTOOL. Send stdin to printer author: David H. Wolen last change: 10/14/84 usage: prog |lpr -lnp 5 55 lpr to resume, anything else to quit.   (default false) input: STDIN output: printer notes: (1) form feed after each page and at eof (2) if both -l and -n are used, margin value must preceed page size value. (3) handles tabs (tabs every 8 spaces) (4) ignores any imbedded form feeds in input */ /* sort.c -- UTOOL. (ver. 2.2) Incore sort of ascii lines. Max file size 2000 lines or about 30K. author: David H. Wolen last change: 9/22/85 usage: sort outfile sort to stop) cat >ofile (2) concat inp files and write on output file cat ifile1 ifile2 >ofile (3) concat input files and pass to std input of prog2 cat ifile1 ifile2 |prog2 (4) clean up WordStar doc file cat -w file.doc >ofile option: -w clean up WordStar doc files by zeroing hi bits and converting strange characters to blanks input: files or STDIN output: STDOUT linkage: a:clink cat -f dio -ca */ #include "a:bdscio.h" #include "a:dio.h" #define STDERR 4 main(argc,argv) int argc; char *argv[]; { char ibuf[BUFSIZ], undoc(), *s; int c, isstdin, wsflg; dioinit(&argc,argv); wsflg=FALSE; while(--argc > 0 && (*++argv)[0] == '-') for(s=argv[0]+1; *s != '\0'; s++) switch(*s) {case 'W': wsflg=TRUE; break; default: fprintf(STDERR,"cat: invalid option\n"); exit(dioflush()); } if(argc <= 0) isstdin=TRUE; else isstdin=FALSE; if(isstdin) /* std input */ while((c=getchar()) != EOF) {if(wsflg) putchar(undoc(c)); else putchar(c); } if(!isstdin) /* files */ while(argc-- > 0) {if(fopen(*argv++,ibuf)==ERROR) {fprintf(STDERR,"cat: can't open %s\n",*argv); exit(dioflush()); } while((c=getc(ibuf)) != EOF && c != CPMEOF) {if(wsflg) putchar(undoc(c)); else putchar(c);  } } dioflush(); }  default: fprintf(STDERR,"cat: invalid option\n"); exit(dioflush()); } if(argc <= 0) isstdin=TRUE; else isstdin=FALSE; if(isstdin) /* std input */ while((c=getchar()) != EOF) {if(wsflg) putchar(undoc(c)); else putchar(c); } if(!isstdin) /* files */ while(argc-- > 0) {if(fopen(*argv++,ibuf)==ERROR) {fprintf(STDERR,"cat: can't open %s\n",*argv); exit(dioflush()); } while((c=getc(ibuf)) != EOF && c != CPMEOF) {if(wsflg) putchar(undoc(c)); else putchar(c);/* ch.c -- UTOOL. Change pattern in text file. author: David H. Wolen last change: 3/4/83 usage: ch pattern [newstuff] input: STDIN output: STDOUT notes: 1. metacharacters in pattern (same as find) % begin of line # # enclose capital letters " " enclose imbedded blanks ? match any char except newline $ end of line [c1-c2] char class [!c1-c2] negated char class * closure (0 or more occurrences of prev 1 char pattern) escaped chars: \n (newline) \t (tab) \r (cr) \f (form feed) \b (backspace) \q (") \p (#) 2. If newstuff is omitted, deletion of pattern occurs. 3. Newstuff consists of zero or more of the following: c literal char & ditto, i.e. whatever was matched  \c escaped char # # and " " as above linkage: a:clink ch -f dio -ca (uses deff3.crl) */ #include "a:bdscio.h" #include "dio.h" #define STDIN 0 #define DITTO 127 /* rubout */ main(argc,argv) int argc; char *argv[]; { char lin[MAXLINE], pat[MAXLINE], sub[MAXLINE], arg[MAXLINE]; dioinit(&argc,argv); if(argc <= 1) error("ch: missing pattern"); rcarg(arg,*++argv); if(!getpat(arg,pat)) error("ch: illegal 'from' pattern"); if(argc == 2) /* null 'to' string */ arg[0]='\0'; else rcarg(arg,*++argv); if(!getsub(arg,sub)) error("ch: illegal 'to' string"); while(fgets(lin,STDIN)) subline(lin,pat,sub); dioflush(); } /* subline -- substitute sub for pat in lin and print */ subline(lin,pat,sub) char *lin, *pat, *sub; { int i, lastm, m; lastm= -1; i=0; while(lin[i] != '\0') {m=amatch(lin,i,pat,0); if(m >= 0 && lastm != m) /* replace matched text */ {putsub(lin,i,m,sub); lastm=m; } if(m < 0 || m == i) /* no match or null match */ {putchar(lin[i]); i++; } else /* skip matched text */ i=m; } } /* getsub -- get substitution string into sub */ getsub(arg,sub) char *arg, *sub; { return(makesub(arg,0,'\0',sub) >= 0); } /* makesub -- make substitution string from arg in sub */ makesub(arg,from,delim,sub) char *arg, delim, *sub; { int i, j; j=0; i=from; while(arg[i] != delim && arg[i] != '\0') {if(arg[i] == '&') addstr(DITTO,sub,&j,MAXLINE); else addstr(esc(arg,&i),sub,&j,MAXLINE); i++; } if(arg[i] != delim) /* missing delimiter */ return(-1); else if(!addstr('\0',sub,&j,MAXLINE)) /* no room */ return(-1); else return(i); } /* putsub -- output substitution text */ putsub(lin,s1,s2,sub) char *lin, *sub; int s1, s2; { int i, j; i=0; while(sub[i] != '\0') {if(sub[i] == DITTO) for(j=s1; j <= s2-1; j++) putchar(lin[j]); else putchar(sub[i]); i++; } } ub) char *arg, *sub; { return(makesub(arg,0,'\0',sub) >= 0); } /* makesub -- make substitution string from arg in sub */ makesub(arg,from,delim,sub) char *arg, delim, *sub; { int i, j; j=0; i=from; while(arg[i] != delim && arg[i] != '\0') {if(arg[i] == '&') addstr(DITTO,sub,&j,MAXLINE); else addstr(esc(arg,&i),sub,&j,MAXLINE); i++; } if(arg[i] != delim) /* missing delimite /* cmp.c -- UTOOL. Compare 2 files or file and std input for equality. author: David H. Wolen last change: 11/23/82 usage: cmp file1 file2 prog |cmp file1 input: 2 files or file and STDIN output: STDOUT linkage: a:clink cmp -f dio -ca (uses deff3.crl) */ #include "a:bdscio.h" #include "dio.h" #define STDIN 0 main(argc,argv) int argc; char *argv[]; { char buf1[BUFSIZ], buf2[BUFSIZ], line1[MAXLINE], line2[MAXLINE]; int isstdin, lineno, m1, m2; dioinit(&argc,argv); switch(argc) { case 2: /* stdin and 1 file */ isstdin=TRUE; if(fopen(argv[1],buf2)==ERROR) error("cmp: can't open file"); break; case 3: /* 2 files */ isstdin=FALSE; if(fopen(argv[1],buf1)==ERROR) error("cmp: can't open file 1"); if(fopen(argv[2],buf2)==ERROR)  error("cmp: can't open file 2"); break; default: error("usage: cmp file1 file2 or STDIN file"); } lineno=0; while(1) {m1=(isstdin) ? fgets(line1,STDIN) : fgets(line1,buf1); m2=fgets(line2,buf2); if(!m1 || !m2) break; lineno++; if(!eqs(line1,line2)) printf("%d\n%s%s",lineno,line1,line2); } if(!m1 && m2) out("cmp: eof on file 1"); else if(!m2 && m1) out("cmp: eof on file 2"); dioflush(); }  1 file */ isstdin=TRUE; if(fopen(argv[1],buf2)==ERROR) error("cmp: can't open file"); break; case 3: /* 2 files */ isstdin=FALSE; if(fopen(argv[1],buf1)==ERROR) error("cmp: can't open file 1"); if(fopen(argv[2],buf2)==ERROR) /* comm.c -- UTOOL. Print lines common to two sorted files author: David H. Wolen last change: 11/29/82 usage: comm -123 file1 file2 prog |comm file1 options: -n (n=1,2,3) print only named columns (default is print all 3) input: 2 files or file and STDIN output: STDOUT notes: (1) if only one file is given, STDIN is file 2 (2) col 1 is lines only in file 1 col 2 is lines only in file 2 col 3 is lines in both files linkage: a:clink comm -f dio -ca (uses deff3.crl) */ #include "a:bdscio.h" #include "dio.h" #define STDIN 0 #define STDOUT 1 main(argc,argv) int argc; char *argv[]; { int isstdin, c1flg, c2flg, c3flg, stat1, stat2, k; char *s, buf1[BUFSIZ], buf2[BUFSIZ], line1[MAXLINE], line2[MAXLINE]; dioinit(&argc,argv); c1flg=c2flg=c3flg=FALSE; /* process options */ while(--argc > 0 && (*++argv)[0] == '-') for(s=argv[0]+1; *s != '\0'; s++) switch(*s) {case '1': c1flg=TRUE; break; case '2': c2flg=TRUE; break; case '3': c3flg=TRUE; break; default: error("comm: invalid option"); } if(!c1flg && !c2flg && !c3flg) c1flg=c2flg=c3flg=TRUE; /* open file or files */ switch(argc) {case 1: /* 1 file and STDIN */ isstdin=TRUE; if(fopen(*argv,buf1)==ERROR) error("comm: can't open file"); break; case 2: /* 2 files */ isstdin=FALSE; if(fopen(*argv++,buf1)==ERROR) error("comm: can't open file 1"); if(fopen(*argv,buf2)==ERROR) error("comm: can't open file 2"); break; default: error("usage: comm [-123] file1 file2 or file STDIN"); } /* process */ stat1=fgets(line1,buf1); stat2=(isstdin) ? fgets(line2,STDIN) : fgets(line2,buf2); while(1) {if(!stat1 || !stat2) break; k=strcmp(line1,line2); if(k < 0) /* line only in file 1 */ {if(c1flg) prntcol(line1,1,c1flg,c2flg,c3flg); stat1=fgets(line1,buf1); } else if(k > 0) /* line only in file 2 */ {if(c2flg) prntcol(line2,2,c1flg,c2flg,c3flg); stat2=(isstdin) ? fgets(line2,STDIN) : fgets(line2,buf2); } else /* line in both files */ {if(c3flg) prntcol(line1,3,c1flg,c2flg,c3flg); stat1=fgets(line1,buf1); stat2=(isstdin) ? fgets(line2,STDIN) : fgets(line2,buf2); } } if(!stat1 && c2flg) /* end of file 1, print rest of file 2 */ while(stat2) {prntc ol(line2,2,c1flg,c2flg,c3flg); stat2=(isstdin) ? fgets(line2,STDIN) : fgets(line2,buf2); } else if(!stat2 && c1flg) /* end of file 2, print rest of file 1 */ while(stat1) {prntcol(line1,1,c1flg,c2flg,c3flg); stat1=fgets(line1,buf1); } dioflush(); } /* prntcol -- print line as column col */ prntcol(line,col,c1flg,c2flg,c3flg) char *line; int col, c1flg, c2flg, c3flg; { int i; for(i=0; isspace(line[i]); i++) ; /* skip leading white space */ switch(col) {case 1: fputs(&line[i],STDOUT); break; case 2: if(c1flg) /* 15 blanks */ fputs(" ",STDOUT); fputs(&line[i],STDOUT); break; case 3: if(c1flg) /* 10 blanks */ fputs(" ",STDOUT); if(c2flg) /* 15 blanks */  fputs(" ",STDOUT); fputs(&line[i],STDOUT); break; default: error("prntcol: can't happen"); } } lg,c2flg,c3flg); stat1=fgets(line1,buf1); } dioflush(); } /* prntcol -- print line as column col */ prntcol(line,col,c1flg,c2flg,c3flg) char *line; int col, c1flg, c2flg, c3flg; { int i; for(i=0; isspace(line[i]); i++) ; /* skip leading white space */ switch(col) {case 1: fputs(&line[i],STDOUT); break; case 2: if(c1flg) /* 15 blanks */ fputs(" ",STDOUT); fputs(&line[i],STDOUT); break; case 3: if(c1flg) /* 10 blanks */ fputs(" ",STDOUT); if(c2flg) /* 15 blanks */ /* crt.c -- UTOOL. Display text file (including ws doc) a screen at a time. author: David H. Wolen last change: 6/12/83 usage: crt -n file prog |crt forward a screen anything else to quit option: -n line numbers input: file or STDIN output: STDOUT linkage: a:clink crt -f dio -ca (uses deff3.crl) */ #include "a:bdscio.h" #include "a:dio.h" #define PSIZE 22 /* lines per screen */ #define STDIN 0 main(argc,argv) int argc; char *argv[]; { char ibuf[BUFSIZ], line[MAXLINE], *s; int lnflag, lcount, lineno, i, isstdin, len; dioinit(&argc,argv); lnflag=FALSE; lineno=1; lcount=1; while(--argc>0 && (*++argv)[0]=='-') for(s=argv[0]+1; *s != '\0'; s++) switch(*s) {case 'N': /* line numbers */ lnflag=TRUE; break; default: error("usage: crt -n file or STDIN"); } switch(argc) {case 0: /* STDIN */ isstdin=TRUE; break; case 1: /* file input */ isstdin=FALSE; if(fopen(*argv,ibuf)==ERROR) error("crt: can't open file"); break; default: error("usage: crt -n file or STDIN"); } while(isstdin ? fgets(line,STDIN) : fgets(line,ibuf)) {len=strlen(line); for(i=0; i < len; i++) line[i]=undoc(line[i]); if(lnflag) printf("%4d: ",lineno++); puts(line); if(++lcount <= PSIZE) continue; if(bdos(1)=='\r') /* console input */ {lcount=1; continue; } else break; } dioflush(); } /* find.c -- UTOOL. Find patterns in text files (ver. 3) author: David H. Wolen last change: 5/2/83 usage: find [-axn] pattern1 [pattern2 ... pattern10] options: -a output lines which contain all patterns (default is output lines matching any pattern) -x output lines that fail the match criteria -n line numbers for output -c just output count of matching lines -f fold (ignore case in character comparisons) input: STDIN output: STDOUT notes: 1. -x pat1 pat2 : output if line contains neither pat 2. -ax pat1 pat2 : output if line doesn't contain both pats 3. metacharacters in pattern % match pattern at beginning of line # # enclose capital letters " " enclose embedded blanks ? match any char except newline $ end of line [c1-c2] character class [!c1-c2] negated character class * closure (0 or more occurrences of prev pattern) escaped chars: \n (newline) \t (tab) \r (cr) \f (form feed) \b (backspace) \q (") \p (#) 4. first pattern can't begin with "-" 5. up to MAXPATS patterns allowed (currently 10) 6. if -c and -n, the latter will be ignored linkage: a:clink find -f dio -ca (uses deff3.crl) */ #include "a:bdscio.h" #include "dio.h" #define STDIN 0 #define MAXPATS 10 /* max patterns */ main(argc,argv) int argc; char *argv[]; { int lineno, except, number, all, numpats, print, count, icount, fold; char line[MAXLINE], *s, newarg[MAXLINE], foldtemp[MAXLINE], pat[MAXPATS][MAXLINE]; dioinit(&argc,argv); lineno=0; except=number=all=count=fold=FALSE; numpats=icount=0; /* process options */ while(--argc > 0 && (*++argv)[0] == '-') for(s=argv[0]+1; *s != '\0'; s++) switch(*s) {case 'A': all=TRUE; break; case 'N': number=TRUE; break; case 'X': except=TRUE; break; case 'C': count=TRUE; break; case 'F': fold=TRUE; break; default: error("find: invalid option"); } /* process patterns */ if(argc <= 0) error("find: missing pattern"); while(argc > 0) {if(++numpats > MAXPATS) error("find: too many patterns"); rcarg(newarg,*argv++); if(fold) {stoupper(foldtemp,newarg); strcpy(newarg,foldtemp); } if(!getpat(newarg,pat[numpats-1])) error("find: illegal pattern"); argc--; } /* look for patterns in stdin */  while(fgets(line,STDIN)) {lineno++; if(fold) stoupper(foldtemp,line); else strcpy(foldtemp,line); if(gmatch(foldtemp,pat,numpats,all)) print=TRUE; else print=FALSE; if(except) print= !print; if(print && !count) {if(number) printf("%d: ",lineno); printf("%s",line); } else if(print && count) icount++; } if(count) printf("%d matched\n",icount); dioflush(); } /* gmatch -- match patterns */ gmatch(line,pat,numpats,all) char *line, pat[MAXPATS][MAXLINE]; int numpats, all; { int gotone, i; for(i=0; i < numpats; i++) {gotone=match(line,pat[i]); if(!all && gotone) return(TRUE); else if(all && !gotone) return(FALSE); } return(all); } /* match -- find match anywhere in line */ match(lin,pat) char *lin, *pat; { int i, pos; pos= -1; i=0; while(lin[i] != '\0' && pos < 0) {pos=amatch(lin,i,pat,0); i++; } return(pos >= 0); } /* stoupper -- convert string to upper case usage: stoupper(outstr,instr); */ stoupper(s,t) char *s, *t; { while(*s++ = toupper(*t++)) ; }  icount++; } if(count) printf("%d matched\n",icount); dioflush(); } /* gmatch -- match patterns */ gmatch(line,pat,numpats,all) char *line, pat[MAXPATS][MAXLINE]; int numpats, all; { int gotone, i; for(i=0; i < numpats; i++) {gotone=match(line,pat[i]); if(!all && gotone) return(TRUE); else if(all && !gotone) return(FALSE); } return(all); } /* match -- find match anywhere in/* hcat.c -- UTOOL. Horizontally concatenate text files. author: David H. Wolen last change: 3/16/83 usage: hcat file1 n2 file2 n3 file3 ... hcat file1 31 file2 51 file3 (begin file1 in col 1, file2 in col 31, file3 in col 51) input: one or more files output: STDOUT notes: 1. max of 6 input files 2. first file starts in col 1 linkage: a:clink hcat -f dio -ca (uses deff3.crl) */ #include "a:bdscio.h" #include "dio.h" #define MAXHCFILS 6 /* max input files */ struct fs /* file data */ {char ibuf[BUFSIZ]; char line[MAXLINE]; int iseof; int col; }; main(argc,argv) int argc; char *argv[]; { int i, nfiles; char outline[MAXLINE]; struct fs fstuff[MAXHCFILS]; dioinit(&argc,argv); if(argc/2 > MAXHCFILS) error("hcat: too many input files"); /* process arguments */ for(i=0; i < argc/2; i++) {if(i == 0) /* start cols (1 for first file) */ fstuff[i].col=1; else if((fstuff[i].col=atoi(*++argv)) <= 0) error("hcat: bad column argument"); if(fopen(*++argv,fstuff[i].ibuf) == ERROR) /* files */ error("hcat: can't open file"); fstuff[i].iseof = FALSE; } nfiles=i; /* process */ while(hcmore(fstuff,nfiles)) /* until all files are at eof */ {for(i=0; i < nfiles; i++) /* get line from each file */ {if(!fstuff[i].iseof) if(!fgets(fstuff[i].line,fstuff[i].ibuf)) fstuff[i].iseof=TRUE; } setmem(outline,MAXLINE,' '); for(i=0; i < nfiles; i++) /* form output line */ {if(!fstuff[i].iseof) dohc(fstuff[i].line,fstuff[i].col,outline,MAXLINE); } if(hcmore(fstuff,nfiles))  {trail(outline,MAXLINE); /* delete trailing blanks */ puts(outline); } } dioflush(); } /* hcmore -- return false if all input files at eof; else true */ hcmore(fstuff,nfiles) struct fs fstuff[]; int nfiles; { int i; for(i=0; i < nfiles; i++) {if(!fstuff[i].iseof) return(TRUE); } return(FALSE); } /* dohc -- insert line into outline starting at col. Won't insert past end of outline. */ dohc(line,col,outline,maxout) char *line, *outline; int col, maxout; { int i, j; for(i=0, j=col-1; j < (maxout-1) && line[i] != '\n'; i++, j++) outline[j]=line[i]; } /* trail -- delete trailing blanks from line */ trail(outline,maxout) char *outline; int maxout; { int i, nfiles; for(i=maxout-3; i >= 0; i--) if(outline[i] != ' ') break; outline[++i]='\n'; outline[++i]='\0'; }  } dioflush(); } /* hcmore -- return false if all input files at eof; else true */ hcmore(fstuff,nfiles) struct fs fstuff[]; int nfiles; { int i; for(i=0; i < nfiles; i++) {if(!fstuff[i].iseof) return(TRUE); } return(FALSE); } /* dohc -- insert line into outline starting at col. Won't insert past end of outline. */ dohc(line,col,outline,maxout) char *line, *outline; int col, maxout; { int i, j; for(i=0, j=col-1; j < (maxout-1) && line[i] != '\n'; i++, j++) outline[j]=line[i]; } /* trail -- delete trailing blanks from line */ trail(outline,maxout) char *outline; int maxout; { int i, nfiles; for(i=maxout-3; i >= 0; i--) if(outline[i] != ' ') break; outline[++i]='\n'; outline[++i]='\0'; }/* incl.c -- UTOOL. Expand included files author: David H. Wolen last change: 12/5/82 usage: incl outfile input: STDIN output: STDOUT compiler: BDS C ver. 1.46 (with dio) linkage: clink b:lline -f a:dio -o b: (uses deff3.crl) */ #include "a:bdscio.h" #include "a:dio.h" #define STDIN 0 main(argc,argv) int argc; char *argv[]; { int len, maxlen; char line[MAXLINE], savline[MAXLINE]; dioinit(&argc,argv); maxlen=0; while(fgets(line,STDIN)) {len=strlen(line) -1; /* don't count \n */ if(len > maxlen) {maxlen=len; strcpy(savline,line); } } if(maxlen == 0) error("lline: empty input"); printf("longest line is %d characters long:\n",maxlen); printf("%s",savline); dioflush(); } /* lpr.c -- UTOOL. Send stdin to printer author: David H. Wolen last change: 12/1/82 usage: prog |lpr -lnp 5 55 lpr to resume, anything else to quit. (default false) input: STDIN output: printer notes: (1) form feed after each page and at eof (2) if both -l and -n are used, margin value must preceed page size value. linkage: a:clink lpr -f dio -ca (uses deff3.crl) */ #include "a:bdscio.h" #include "dio.h" #define STDIN 0 #define STDLST 2 main(argc,argv) int argc; char *argv[]; { int margflg, lmarg, psflg, psize, pause, lcount, i; char line[MAXLINE], *s; dioinit(&argc,argv); margflg=psflg=pause=FALSE; lmarg=8; psize=50; while(--argc > 0 && (*++argv)[0]=='-') for(s=argv[0]+1; *s != '\0'; s++) switch(*s) {case 'L': margflg=TRUE; break; case 'N': psflg=TRUE; break; case 'P': pause=TRUE; break; default: error("lpr: invalid option"); } if(margflg) {if( (lmarg=atoi(*argv++)) < 0) error("lpr: left margin < 0"); } if(psflg) {if( (psize=atoi(*argv)) < 1) error("lpr: page size < 1"); } lcount=1; while(fgets(line,STDIN)) {for(i=0; i 1) fputs("\f",STDLST); dioflush(); } flg=TRUE; break; case 'N': psflg=TRUE; break; case 'P': pause=TRUE; break; default: error("lpr: invalid option"); } if(margflg) {if( (lmarg=atoi(*argv++)) < 0) error("lpr: left margin < 0"); } if(psflg) {if( (psize=atoi(*argv)) < 1) error("lpr: page size < 1"); } lcount=1; while(fgets(line,STDIN)) {for(i=0; iprog.pdo (programmer doc) makdoc prog.c >prog.hlp (user help file) options: -p output programmer oriented material in addition to user's manual page input: file or STDIN output: STDOUT notes: (1) -p prints program preface and function descriptions. Normal usage omits the linkage and compiler lines from the preface and omits the function descriptions. (2) filename can't begin with - compiler: BDS C ver. 1.46 (with dio) linkage: clink b:makdoc -f dio (uses deff3.crl) */ #include "a:bdscio.h" #include "a:dio.h" #define STDIN 0 #define STDOUT 1 main(argc,argv) int argc; char *argv[]; { int isstdin, print, udoc; char line[MAXLINE], ibuf[BUFSIZ], *s; dioinit(&argc,argv); udoc=TRUE; while(--argc > 0 && (*++argv)[0]=='-') for(s=argv[0]+1; *s != '\0'; s++) switch(*s) {case 'P': udoc=FALSE; break; default: error("makdoc: invalid option"); } if(argc <= 0) isstdin=TRUE; else {isstdin=FALSE; if(fopen(*argv,ibuf) == ERROR) error("makdoc: can't open file"); } print=FALSE; if(udoc) /* make user doc */ {while(isstdin ? fgets(line,STDIN) : fgets(line,ibuf)) {if(index(line,"/*")==0) print=TRUE; if(print && index(line,"linkage:") < 0 && index(line,"compiler:") < 0) fputs(line,STDOUT); if(index(line,"*/") >= 0) break; } } if(!udoc) /* make programmer doc */ {while(isstdin ? fgets(line,STDIN) : fgets(line,ibuf)) {if(index(line,"/*")==0) print=TRUE;  if(print) fputs(line,STDOUT); if(index(line,"*/") >= 0) print=FALSE; } } dioflush(); }  <= 0) isstdin=TRUE; else {isstdin=FALSE; if(fopen(*argv,ibuf) == ERROR) error("makdoc: can't open file"); } print=FALSE; if(udoc) /* make user doc */ {while(isstdin ? fgets(line,STDIN) : fgets(line,ibuf)) {if(index(line,"/*")==0) print=TRUE; if(print && index(line,"linkage:") < 0 && index(line,"compiler:") < 0) fputs(line,STDOUT); if(index(line,"*/") >= 0) break; } } if(!udoc) /* make programmer doc */ {while(isstdin ? fgets(line,STDIN) : fgets(line,ibuf)) {if(index(line,"/*")==0) print=TRUE; /* mylib3.c -- source for deff3.crl author: David H. Wolen last change: 6/12/83 contents: fefc rcarg error out argrange eqs addstr dodash isalpnum esc cindex amatch patsize omatch locate getpat makepat getccl stclos undoc */ #include "a:bdscio.h" #define STDERR 4 #define MAXI 5 #define ESCAPE '\\' #define NEGATE '!' #define LITCHAR 'c' #define BOL '%' #define EOL '$' #define ANY '?' #define CCL '[' #define CCLEND ']' #define NCCL '^' #define CLOSURE '*' #define CLOSIZE 1 /* fefc -- end, fflush, close output file */ fefc(iobuf) char *iobuf; { putc(CPMEOF,iobuf); fflush(iobuf); fclose(iobuf); } /* rcarg -- restore case of argument. Intended to deal with CP/M desire to make command line args upper case. Any characters within # # in inarg are turned to upper case; other characters are turned to lower case. usage: rcarg(outarg,inarg); */ rcarg(outarg,inarg) char *outarg, *inarg; { int makelow; makelow=TRUE; for(; *inarg ; inarg++) {if(*inarg=='#') makelow=!makelow; else if(makelow) *outarg++ = tolower(*inarg); else if(!makelow) *outarg++ = *inarg; } *outarg = '\0'; } /* error -- print error message, dioflush and stop */ error(msg) char *msg; { fputs(msg,STDERR); fputs("\n",STDERR); exit(dioflush()); } /* out -- display message on console regardless of dio */ out(string) char *string; { fprintf(STDERR,"%s\n",string); } /* argrange -- converts an integer range argument of the form n1-n2 to two positive integers. Returns ERROR if no "-" or ni has too many digits or <0 or missing usage:  if(argrange(arg,&n1,&n2)==ERROR) ... */ argrange(arg,n1,n2) char *arg; int *n1, *n2; { char cn[MAXI+1]; int i, j; for(i=0; (arg[i]!='-')&&(arg[i]!='\0'); i++) ; if(i>MAXI) return(ERROR); if(arg[i]!='-') return(ERROR); for(j=0; j= maxset) return(FALSE); else {outset[*j]=c; (*j)++; return(TRUE); } } /* dodash -- expand set at src[i] into dest[j]. Stop at delim. usage: dodash('\0',inset,&i,outset,&j,maxset); */ dodash(delim,src,i,dest,j,maxset) char delim, *src, *dest; int *i, *j, maxset; { int k; char esc(); while(src[*i] != delim && src[*i] != '\0') {if(src[*i] == ESCAPE) addstr(esc(src,i),dest,j,maxset); else if(src[*i] != '-') addstr(src[*i],dest,j,maxset); else if(*j <= 0 || src[*i+1] == '\0') addstr('-',dest,j,maxset); /* literal - */ else if(isalpnum(src[*i-1]) && isalpnum(src[*i+1]) && src[*i-1] <= src[*i+1]) {for(k=src[*i-1]+1; k <= src[*i+1]; k++) addstr(k,dest,j,maxset); (*i)++; } else addstr('-',dest,j,maxset); (*i)++; } } /* isalpnum -- true if c is letter or digit usage: if(isalpnum(c)) ... */ isalpnum(c) char c; { if(c >= 'A' && c <= 'Z') return(TRUE); if(c >= 'a' && c <= 'z') return(TRUE); if(c >= '0' && c <= '9') return(TRUE); return(FALSE); } /* esc -- map s[i] into escaped character, increment i. usage: c=esc(inset,&i); */ char esc(s,i) char *s; int *i; { if(s[*i] != ESCAPE) return(s[*i]); if(s[*i+1] == '\0') /* \ not special at end */ return(ESCAPE); (*i)++; if(s[*i] == 'n' || s[*i] == 'N') return('\n'); if(s[*i] == 't' || s[*i] == 'T') return('\t'); if(s[*i] == 'b' || s[*i] == 'B') return('\b'); if(s[*i] == 'r' || s[*i] == 'R') return('\r'); if(s[*i] == 'f' || s[*i] == 'F') return('\f'); if(s[*i] == 'p' || s[*i] == 'P') return('#'); if(s[*i] == 'q' || s[*i] == 'Q') return('"'); return(s[*i]); } /* cindex -- find position of character c in string s. -1 for not found. usage: if(cindex(string,c) >= 0) ... */ cindex(s,c) char *s, c; { int i; i=0; while(s[i] != c && s[i] != '\0') i++; if(s[i] == '\0') return(-1); else return(i); } /* amatch -- look for match of pat[j]... at lin[offset]... usage: pos=amatch(lin,i,pat,0); */ amatch(lin,offset,pat,j) char *lin, *pat; int offset, j; { int i, k, done, offset2; done=FALSE; offset2=offset; while(!done && pat[j] != '\0') {if(pat[j] == CLOSURE) {j += patsize(pat,j); i=offset2; while(!done && lin[i] != '\0') if(!omatch(lin,&i,pat,j)) done=TRUE; done=FALSE; while(!done && i >= offset2) {k=amatch(lin,i,pat,j+patsize(pat,/* prep.c -- UTOOL. Convert a text file (including ws doc files) to one word per line. author: David H. Wolen last change: 3/9/83 usage: prep 0 && (*++argv)[0]=='-') for(s=argv[0]+1; *s != '\0'; s++) switch(*s) {case 'O': only=TRUE; break; case 'I': ignore=TRUE; break; case 'D': sequence=TRUE; break; default: error("prep: invalid option"); } if(only && ignore) error("prep: can't use both -o and -i"); if(only || ignore) readlist(*argv); while(getword(word)) {wcount++; if(ignore) {if(!pmatch(word) && sequence) fprintf(STDOUT,"%d: %s\n",wcount,word); if(!pmatch(word) && !sequence) fprintf(STDOUT,"%s\n",word); } else if(only) {if(pmatch(word) && sequence) fprintf(STDOUT,"%d: %s\n",wcount,word); if(pmatch(word) && !sequence) fprintf(STDOUT,"%s\n",word); } else {if(sequence) fprintf(STDOUT,"%d: %s\n",wcount,word); else fprintf(STDOUT,"%s\n",word); } } dioflush(); } /* readlist -- read and store exclusion or inclusion list. Check to be sure list is sorted and unique. */ readlist(filename) char *filename; { int len, i; char ibuf[BUFSIZ], line[MAXLINE], *sbrk(), *p; if(fopen(filename,ibuf)==ERROR) error("prep: can't open list file"); nlist=0; while(fgets(line,ibuf)) {if(nlist > LINES) error("prep: too many lines in list file"); line[strlen(line)-1]='\0'; /* zap '\n' */ len=strlen(line) +1; if((p=sbrk(len))==ERROR) error("prep: too many chars on list file"); strcpy(p,line); listp[nlist++]=p; } if(nlist < 1) error("prep: empty list file"); for(i=1; i=0) error("prep: list isn't sorted or has duplicates"); } /* pstrcmp -- compare strings. Return <0 if s0 if s>t. For equality, strings must be equal in length. Fold lower into upper case before comparison. */ pstrcmp(s,t) char *s, *t; { for(; *s != '\0'; s++, t++) if(toupper(*s) != toupper(*t)) return(toupper(*s)-toupper(*t)); if(*t == '\0') return(0); else return(-1); } /* getword -- get the next word from the standard input. Return TRUE for got a word, FALSE for EOF. */ getword(word) char *word; { int i, c; i=0; while(1) /* find start of word */ {if((c=getchar())==EOF) return(FALSE); c &= 0177; /* Wordstar hi bit */ if(isalpha(c)) break; } word[i++]=tolower(c); while(1) {if((c=getchar())==EOF) /* push back EOF for next call */ {ungetch(c); break; } c &= 0177; if(!isalpha(c) && c!='\'') break; /* allow ' within a word */ else word[i++]=tolower(c); } if(word[i-1]=='\'') word[i-1]='\0'; else word[i]='\0'; return(TRUE); } /* pmatch -- return TRUE if word is in list, else FALSE. Ignore case in the comparison. */ pmatch(word) char *word; { int low, mid, high; low=0; high=nlist-1; while(low <= high) /* binary search */ {mid=(low+high)/2; if(pstrcmp(word,listp[mid]) < 0) high=mid-1; else if (pstrcmp(word,listp[mid]) >0) low=mid+1; else /* found match */ return(TRUE); } return(FALSE); } F for next call */ {ungetch(c); break; } c &= 0177; if(!isalpha(c) && c!='\'') break; /* allow ' within a word */ else word[i++]=tolower(c); } if(word[i-1]=='\'') word[i-1]='\0'; else word[i]='\0'; return(TRUE); } /* pmatch -- return TRUE if word is in list, else FALSE. Ignore case in the comparison. */ pmatch(word) char *word; { int low, mid, high; low=0; high=nlist-1; while(low <= high) /* binary search */ {mid=/* sort.c -- UTOOL. (ver. 2) Incore sort of ascii lines. Max file size 2000 lines or about 30K. author: David H. Wolen last change: 5/5/83 usage: sort outfile sort 0 && (*++argv)[0]=='-') for(s=argv[0]+1; *s != '\0'; s++) switch(*s) {case 'F': foldflag=TRUE; break; case 'K': keyflag=TRUE; break; case 'R': revflag=TRUE; break; case 'N': numflag=TRUE; break; case 'U': uniqflag=TRUE; break; default: fprintf(STDERR, "sort: invalid option %c\n",*s); exit(dioflush()); } if(numflag&&keyflag) {fprintf(STDERR,"sort: -n and -k don't go together\n"); exit(dioflush()); } if(numflag&&foldflag) {fprintf(STDERR,"sort: -n and -f don't go together\n"); exit(dioflush()); } /* process key fields, if any */ if(keyflag) {if(argc<=0) {fprintf(STDERR,"sort: missing keys\n"); exit(dioflush()); } if(argc>MAXKEYS) {fprintf(STDERR,"sort: more than %d keys\n",MAXKEYS); exit(dioflush()); } for(i=0; iMAXLINE-1)||(k2>MAXLINE-1)) return(-5); else return(0); } /* filein -- read input, store lines, store pointers to lines */ filein() { int len, nlines; char *p, *sbrk(), line[MAXLINE]; nlines=0; while(fgets(line,STDIN)) {if(nlines>LINES) return(-1); line[strlen(line)-1]='\0'; /* zap '\n' */ len=strlen(line) + 1; /* account for null byte */ if((p=sbrk(len))==ERROR) return(-2); strcpy(p,line); lineptr[nlines++]=p; } return(nlines); } /* xsort -- shell sort pointers to text lines */ xsort(v,n,fold,keys,reverse,numeric) char *v[]; int n, fold, keys, reverse, numeric; { int gap, i, j; for(gap=n/2;gap>0;gap/=2) for(i=gap;i=0;j-=gap) {if(scmp(v[j],v[j+gap],fold,keys,reverse,numeric) <= 0) break; swap(&v[j],&v[j+gap]); } } /* scmp -- string compare. Return <0 if s0 if s>t (lie if reverse) */ scmp(s,t,fold,keys,reverse,numeric) char *s, *t; int fold, keys, reverse, numeric; { int result; if(numeric) /* leading integers */ result=atoi(s) -atoi(t); else if(keys) /* fields */ result=strcmpaf(s,t,fold); else /* whole line */ result=xstrcmp(s,t,fold); if(reverse) /* lie for descending sort */ result *= -1; return(result); } /* swap -- exchange pointers. K&R p. 117 */ swap(px,py) char *px[], *py[]; { char *temp; temp=*px; *px=*py; *py=temp; } /* xstrcmp -- return <0 if s0 if s>t. If fold, fold lower into upper case before compare. */ xstrcmp(s,t,fold) char *s, *t; int fold; { char s1, t1; for(; *s != '\0'; s++, t++) {s1= (fold) ? toupper(*s) : *s; t1= (fold) ? toupper(*t) : *t; if(s1 != t1) return(s1-t1); } if(*t=='\0') return(0); else return(-1); } /* strcmpaf -- compare using fields. Return <0 for s<t, 0 for s==t, >0 for s>t. If fold, fold lower into upper case before comparison. */ strcmpaf(s,t,fold) char *s, *t; int fold; { int i,j; char s1, t1; for(i=0; keys[0][i]>=0; i++) for(j=keys[0][i]; j<=keys[1][i]; j++) {s1 = (fold) ? toupper(s[j]) : s[j]; t1 = (fold) ? toupper(t[j]) : t[j]; if(s1 != t1) return (s1-t1); } return(0); } /* output -- write output. Delete non-unique lines (current sort def of equality) if requested */ output(nlines,unique,fold,keys,reverse,numeric) int nlines, unique, fold, keys, reverse, numeric; { int i; if(unique) /* delete non-unique lines */ {fprintf(STDOUT,"%s\n",lineptr[0]); for(i=1; i < nlines; i++) if(scmp(lineptr[i],lineptr[i-1],fold,keys,reverse,numeric) != 0) fprintf(STDOUT,"%s\n",lineptr[i]); } else /* output all lines */ for(i=0; i < nlines; i++) fprintf(STDOUT,"%s\n",lineptr[i]); } *t; int fold; { int i,j; char s1, t1; for(i=0; keys[0][i]>=0; i++) for(j=keys[0][i]; j<=keys[1][i]; j++) {s1 = (fold) ? toupper(s[j]) : s[j]; t1 = (fold) ? toupper(t[j]) : t[j]; if(s1 != t1) return (s1-t1); } return(0); } /* output -- write output. Delete non-unique lines (current sort def of equality) if requested */ output(nlines,unique,fold,keys,reverse,numeric) int nlines, unique, fold, keys, reverse, numeric; { int i; if(unique) /* delete non-unique lines */ {fprintf(STDOUT,"%s\n",lineptr[0]); for(i=1; i < nlines; i++) if(scmp(lineptr[i],lineptr[i-1],fold,keys,reverse,numeric) != 0) fprintf(STDOUT,"%s\n",lineptr[i]); } else /* output all l/* split.c -- UTOOL. Read STDIN and write it out in n-line chunks to files author: David H. Wolen last change: 3/31/83 usage: split [-n] [outname] split = 25) /* put rest of input on last output file */ while((gotit=fgets(line,STDIN))) fputs(line,obuf); fefc(obuf); return(gotit); } fnamprfx.c where c= a ... z */ makename(prefix,index,outname) char *prefix, *outname; int index; { char suffix[3], *letters; letters="abcdefghijklmnopqrstuvwxyz"; /* poor man's static */ strcpy(outname,prefix); suffix[0]='.'; suffix[1]=letters[index]; suffix[2]='\0'; strcat(outname,suffix); } /* spcopy -- copy nl lines from STDIN to outname */ spcopy(nl,outname,ifile) int nl, ifile; char *outname; { char line[MAXLINE], obuf[BUFSIZ]; /* split, splitr, scan, scanr, scann, scannr -- character handling functions similar to HIS TEX */ /* split - splits instring. Puts leftmost col characters in starl and the rest in starr. instring must be terminated by '\0' . starl and starr will be terminated by '\0 . Strange cases are handled as in TEX. */ #include "a:bdscio.h" #define CLASC '_' #define STDERR 4 split(instring,col,starl,starr) /* split from left */ char instring[], starl[], starr[]; int col; { int i,j; /* special cases */ if(instring[0]=='\0') {starl[0]=starr[0]='\0'; return; } if(col<=0) {starl[0]='\0'; strcpy(starr,instring); return; } if(col>strlen(instring)) {strcpy(starl,instring); starr[0]='\0'; return; } /* normal case */ for(i=0;i1 char in scann %s",pat); fprintf(STDERR," used first\n"); } for(i=0;instring[i]!='\0';i++) if(pat[0]!=instring[i]) break; if(instring[i]=='\0') {strcpy(starl,instring); starr[0]=starm[0]='\0'; return(TRUE); } else {split(instring,i,starl,starr); starm[0]='\0'; if(starr[0]=='\0') return(TRUE); else return(FALSE); } /* normal case with class */ class: if(getclass(pat,&alp,&num,&low,&up)==ERROR) {fprintf(STDERR,"\nbad class in scann is %s",pat); fprintf(STDERR," treated as null\n"); strcpy(starl,instring); starm[0]=starr[0]='\0'; return(FALSE); } for(i=0;instring[i]!='\0';i++) {if(alp && !isalpha(instring[i])) break; if (num && !isdigit(instring[i])) break; if (low && !islower(instring[i])) break; if (up && !isupper(instring[i])) break; } if(instring[i]=='\0') {strcpy(starl,instring); starm[0]=starr[0]='\0'; return(TRUE); } else {split(instring,i,starl,starr); starm[0]='\0'; if(starr[0]=='\0') return(TRUE); else return(FALSE); } } /* scanr - scans instring from right for pat. pat can contain characters or a class (prefixed by _). instring must be terminated by '\0'. Returns TRUE or FALSE. */ scanr(instring,pat,starl,starm,starr) /* scan from right */ char instring[], pat[], starl[], starm[], starr[]; { int i, alp, num, low, up; /* special cases */ if(instring[0]=='\0') {starl[0]=starm[0]=starr[0]='\0'; return(FALSE); } if(pat[0]=='\0') {strcpy(starr,instring); starl[0]=starm[0]='\0'; return(FALSE); } /* normal case without class */ if(pat[0]==CLASC) goto class; if(index(instring,pat)<0) {strcpy(starr,instring); starl[0]=starm[0]='\0'; return(FALSE); } else {scan(instring,pat,starl,starm,starr); return(TRUE); } /* normal case with class */ class: if(getclass(pat,&alp,&num,&low,&up)==ERROR) {fprintf(STDERR,"\nbad class in scanr %s",pat); fprintf(STDERR," treated as null\n"); strcpy(starr,instring); starl[0]=starm[0]='\0'; return(FALSE); } for(i=strlen(instring)-1;i>=0;i--) {if(alp && isalpha(instring[i])) break; if(num && isdigit(instring[i])) break; if(low && islower(instring[i])) break; if(up && isupper(instring[i])) break; } if(i<0) {strcpy(starr,instring); starl[0]=starm[0]='\0'; return(FALSE); } else {split(instring,i+1,starl,starr); starm[0]='\0'; return(TRUE); } } /* scannr - scans instring from right for non-match on pat. pat can contain one character or a class (prefixed by _). instring must be terminated by '\0'. Returns TRUE or FALSE (as in TEX, the TRUE and FALSE results are not intuitively obvious). */ scannr(instring,pat,starl,starm,starr) /* scan from right for non-match */ char instring[], pat[], starl[], starm[], starr[]; { int col, i, alp, num, low, up; /* special cases */ if(pat[0]=='\0') {fprintf(STDERR,"\nerror in scannr null pat\n"); starl[0]=starm[0]=starr[0]='\0'; return(FALSE); } if(instring[0]=='\0') {starl[0]=starm[0]=starr[0]='\0'; return(FALSE); } /* normal case without class */ if(pat[0]==CLASC) goto class; if(pat[1]!='\0') {fprintf(STDERR,"\npat>1 char in scannr %s",pat); fprintf(STDERR," used first\n"); } for(i=strlen(instring)-1;i >= 0;i--) if(pat[0]!=instring[i]) break; if(i<0) {starl[0]=starm[0]='\0'; strcpy(starr,instring); return(TRUE); } else {starm[0]='\0'; split(instring,i+1,starl,starr); return(FALSE); } /* normal case with class */ class: if(getclass(pat,&alp,&num,&low,&up)==ERROR) {fprintf(STDERR,"\nbad class in scannr %s",pat); fprintf(STDERR," treated as null\n"); starl[0]=starm[0]=starr[0]='\0'; return(FALSE); } for(i=strlen(instring)-1;i >= 0;i--) {if(alp && !isalpha(instring[i])) break; if(num && !isdigit(instring[i])) break; if(low && !islower(instring[i])) break; if(up && !isupper(instring[i])) break; } if(i<0) {starl[0]=starm[0]='\0'; strcpy(starr,instring); return(TRUE); } else {starm[0]='\0'; split(instring,i+1,starl,starr); return(FALSE); } } {starm[0]='\0'; split(instring,i+1,starl,starr); return(FALSE); } /* normal case with class */ class: if(getclass(pat,&alp,&num,&low,&up)==ERROR) {fprintf(STDERR,"\nbad class in scannr %s",pat); fprintf(STDERR," treated as null\n"); starl[0]=starm[0]=starr[0]='\0'; return(FALSE); } for(i=strlen(instring)-1;i >= 0;i--) {if(alp && !isalpha(instring[i])) break; if(num && !isdigit(instring[i])) break; if(low && !islower(instring[i])) break; if(up && !isupper(instring[i])) break;.he spltscan.doc Character handling functions similar to those in Honeywell's TEX. 1. split(instring,col,starl,starr) 2. splitr(instring,col,starl,starr) 3. match=scan(instring,pat,starl,starm,starr) 4. match=scann(instring,pat,starl,starm,starr) 5. match=scanr(instring,pat,starl,starm,starr) 6. match=scannr(instring,pat,starl,starm,starr) General notes: instring is the input string to be split or scanned. It must be terminated by '\0'. starl,starm and starr are output strings. They will be terminated by '\0'. col, input to split and splitr, is an integer. pat, input to the scan functions, is the pattern to be matched and must be terminated by '\0'. If pat's first character is '_' (CLASC), then it indicates a class match instead of a literal match. The classes available are: _a alphabetic. 52 ascii upper and lower. _n numeric. digits 0-9.  _an alphanumeric. 52 alpha and the 10 digits. _lc lower case. 26 ascii lower case alpha. _uc upper case. 26 ascii upper case alpha. match, output by scan functions, is 0 (FALSE) or 1 (TRUE). Specific details on each function follow. .pa 1. split(instring,col,starl,starr) normal case 0 < col <= strlen(instring) starl will contain the leftmost col characters of instring. starr will contain the rest. special cases (a) if instring is null (instring[0]=='\0') then starl and starr will be null. (b) if col>strlen(instring) then starl will contain all of instring and starr will be null. (c) if col <=0 then starr will contain all of instring and starl will be null. 2. splitr(instring,col,starl,starr) normal case 0 < col <= strlen(instring) starr will contain the rightmost col characters of instring. starl will contain the rest. special cases (a) if instring is null, then starl and starr will be null. (b) if col>strlen(instring), then starr will contain all of instring and starl will be null. (c) if col<=0 then starr will be null and starl will contain all of instring. .pa 3. match=scan(instring,pat,starl,starm,starr) normal case: where pat is a string I栠 pa i i instring star wil contai th character t th lef o it star wil contai pat star wil contai th character t th righ o i an matc wil b (TRUE) I pa isn' i instring star wil contai instring star an star wil b null and match will be 0 (FALSE). normal case: where pat is a class I a occurrenc o th clas i i instring star wil contai th character t th lef o th firs occurrence star wil b null star wil contai th rest an matc wil b (FALSE) I ther isn' an occurrenc o th clas i instring star wil contai instring star an star wil b nul an matc wil be 0 (FALSE). special cases (a) if instring is null, starl, starm and starr will be null and match will be 0 (FALSE). (b) if pat is null and instring isn't null, starl will contain instring, starm and starr will be null and match will be 0 (FALSE). .pa 4. match=scann(instring,pat,starl,starm,starr) normal case: where pat is a string pa mus b singl character I pa i i instring star wil contai an leadin occurrence o pat star wil b null star wil contai th res o instrin an matc wil b (TRUE i star i nul (e.g i eac o th character o instrin matche pat an (FALSE otherwise I pa isn' i instring star an star wil b null star wil contain instring and match will be 0 (FALSE). normal case: where pat is a class I instrin contain a occurrenc o th class the star wil contai al leadin occurrence o th class star wil b null star wil contai th res o instring an matc wil b (TRUE i star i nul (e.g i al character o instrin matc th class an (FALSE otherwise I instrin doesn' contai an occurrenc o th class star an star wil b null star wil contai instrin an matc will be 0 (FALSE). special cases (a) If instring and/or pat is null, starl, starm and starr will be null. match will be 0 (FALSE). In contrast, TEX considers it an error if pat is null here and doesn't bother to return any values (it just issues the warning message). .pa 5. match=scanr(instring,pat,starl,starm,starr) normal case: where pat is a string I pa i i instring star wil contai character t th lef o pat star wil contai pa an star wil contai character t th righ o pat an matc wil b (TRUE) I pa isn' i instring star an star wil b null star wil contai instrin an matc will be 0 (FALSE). normal case: where pat is a class I instrin contain a occurrenc o th class star wil contai th rightmos occurrenc o th clas an an character t th lef o it star wil b null star wil contai th res o instrin an matc wil b堠 (TRUE) I instrin doesn' contai an occurrenc o th class star an star wil b null star wil contai instrin an matc wil b (FALSE). special cases (a) If instring is null, then starl, starm and starr will be null. match will be 0 (FALSE). (b) If pat is null and instring isn't, then starl and starm will be null. starr will contain instring and match will be 0 (FALSE). .pa 6. match=scannr(instring,pat,starl,starm,starr) normal case: where pat is a string pa mus b singl character I pa i i instring star wil contai th rightmos characte tha doesn' matc pa an al character t th lef o it star wil b null an star wil contai th res o instring matc wil b (TRUE i star isn' nul (e.g i al th character o instrin matc pat) an (FALSE i star i null I pa isn' i instring star wil contai instring star an star wil b null and match will be 0 (FALSE). normal case: where pat is a class I instrin contain a occurrenc o th class star wil contai th rightmos characte tha doesn' matc th clas an al character t th lef o it star wil b null star wil contai th res o instring I star isn' nul (e.g i al th character o instrin matc th class the matc wil b (TRUE) I star i null matc wil b (FALSE) I instrin doesn' contai an occurrenc o th class star wil contai instring star an star wil b nul an match will be 0 (FALSE). special cases I instri and/o pa i null starl star an star wil b null matc wil b (FALSE) I contrast TEؠ consider i a erro i pa i nul an issue message without bothering to set any variables. null and match will be 0 (FALSE). normal case: where pat is a class I instrin contain a occurrenc o th class star wil contai th rightmos characte tha doesn' matc th clas an al character t th lef o it star wil b null star wil contai th res o instring I star isn' nul (e.g i al th character o instrin matc th class the matc wil b (TRUE) I star i null matc wil b (FALSE) I instrin doesn' contai an occurrenc o th class star wil contai instring star an star wil b nul an match will be 0 (FALSE). special cases I instri and/o pa i null starl star an star wil b null matc wil b (FALSE) I contrast /* tabs.c -- UTOOL. Convert tabs to blanks (-d) or blanks to tabs and blanks (-e). author: David H. Wolen last change: 2/12/83 usage: tabs -d tabs -e 5 21 &5 options: -d detab (convert tab chars to blanks) -e entab (convert blanks to tab chars and blanks) input: STDIN output: STDOUT notes: (1) either -d or -e is required (2) default tab stops are at columns 8, 16, 24, ... (3) &n in the command line sets tabs every n columns. E.G. "5 21 &5" sets tabs at columns 5, 21, 26, 31, ... Anything after the &n will be ignored. linkage: a:clink tabs -f dio -ca (uses deff3.crl) */ #include "a:bdscio.h" #include "dio.h" #define TABSPACE 8 /* default tabs every 8 columns */ int tabflags[MAXLINE]; /* [0] isn't used */ main(argc,argv) int argc; char *argv[]; { int dodetab, doentab; char *s; dioinit(&argc,argv); dodetab=doentab=FALSE; /* process options */ while(--argc > 0 && (*++argv)[0] == '-') for(s=argv[0]+1; *s != '\0'; s++) switch(*s) {case 'D': dodetab=TRUE; break; case 'E': doentab=TRUE; break; default: error("tabs: invalid option. Use -d or -e"); } if( (!dodetab && !doentab) || (dodetab && doentab) ) error("tabs: must give -d or -e"); /* main */ if(settabs(argc,argv) == ERROR) error("tabs: bad tab argument"); if(dodetab) detab(); else if(doentab) entab(); dioflush(); } /* settabs -- set initial tab stops from command line or default */ settabs(argc,argv) int argc; char *argv[]; { int i, lastab, itab, doincr; for(i=0; i < MAXLINE; i++) tabflags[i]=FALSE; if(argc <= 0) /* default tab stops */ {for(i=1; i < MAXLINE; i++) tabflags[i]=(i % TABSPACE == 0); return(OK); } lastab=0; /* tabs from command line */ doincr=FALSE; while(argc-- > 0) {if( *argv[0] == '&') {*argv[0]=' '; doincr=TRUE; } itab=atoi(*argv); if( itab <= 0) return(ERROR); itab=min(itab,MAXLINE-1); if(doincr) {for(i=lastab+1; i < MAXLINE; i++) tabflags[i]=((i-lastab) % itab == 0); return(OK); } else {tabflags[itab]=TRUE; lastab=itab; argv++; } } return(OK); } /* detab -- convert tab chars to blanks */ detab() { int c, col; col=1; while( (c=getchar()) != EOF) {if(c == '\t') do {putchar(' '); col++; } while(!tabpos(col)); else if(c == '\n') {putchar('\n'); col=1; } else {putchar(c); col++; } } } /* tabpos -- return true if col is a tab stop, else false */ tabpos(col) int col; { if(col >= MAXLINE) return(TRUE); else return(tabflags[col]); } /* entab -- convert blanks to tab chars and blanks */ entab() { int c, col, newcol; col=1; do {newcol=col; while( (c=getchar()) == ' ') /* collect blanks */ {newcol++; if(tabpos(newcol)) {putchar('\t'); col=newcol; } } while(col < newcol) /* output leftover blanks */ {putchar(' '); col++; } if(c != EOF) {putchar(c); if(c == '\n') col=1; else col++; } } while(c != EOF); }  } } /* tabpos -- return true if col is a tab stop, else false */ tabpos(col) int col; { if(col >= MAXLINE) return(TRUE); else return(tabflags[col]); } /* entab -- convert blanks to tab chars and blanks */ entab() { int c, col, newcol; col=1; do {newcol=col; while( (c=getchar()) == ' ') /* collect blanks */ {newcol++; if(tabpos(newcol)) {putchar('\t'); col=newcol; } } while(col < newcol) /* output le/* tail.c -- UTOOL. Print last n lines of file. author: David H. Wolen last change: 01/25/83 usage: tail [n] options: n number of lines to print. Range 1--1000. Default 32. input: STDIN output: STDOUT linkage: a:clink tail -f dio -ca (uses deff3.crl) */ #include "a:bdscio.h" #include "dio.h" #define STDIN 0 #define STDOUT 1 #define LINES 1000 /* max lines to display */ #define OS1LINES 32 /* default lines to display */ #define SIZECP 2 /* size of pointer to char in bytes */ main(argc,argv) int argc; char *argv[]; { int ntail, nsave, i; char *linbuf[LINES], line[MAXLINE]; dioinit(&argc,argv); _allocp=NULL; nsave=0; if(argc > 1) /* number of lines to print given on command line */ {ntail=atoi(*++argv); if(ntail < 1 || ntail > LINES) error("tail: lines to print must be 1--1000"); } else  /* use default */ ntail=OS1LINES; while(fgets(line,STDIN)) saveline(line,linbuf,&nsave,ntail); if(nsave <= 0) error("tail: empty input"); for(i=0; i < nsave; i++) fputs(linbuf[i],STDOUT); dioflush(); } /* saveline -- store lines and save pointers to them */ saveline(line,linbuf,nsave,ntail) char *line, *linbuf[]; int *nsave, ntail; { char *alloc(), *p; if(*nsave < ntail) {if((p=alloc(strlen(line)+1)) == NULL) error("tail: out of room in saveline #1"); strcpy(p,line); linbuf[(*nsave)++]=p; } else {free(linbuf[0]); movmem(&linbuf[1],&linbuf[0],(ntail-1)*SIZECP); if((p=alloc(strlen(line)+1)) == NULL) error("tail: out of room in saveline #2"); strcpy(p,line); linbuf[ntail-1]=p; } } /* tee.c -- UTOOL. Copy STDIN to STDOUT and named file. author: David H. Wolen last change: 1/16/83 usage: tee [-a] outfile options: -a append to outfile instead of copying to it input: STDIN output: STDOUT and file notes: (a) if -a and outfile doesn't exist, the option is ignored. (b) if -a, it creates and releases a temp file (temptee.$$$) on the logged drive. linkage: a:clink tee -f dio -ca (uses deff3.crl) */ #include "a:bdscio.h" #include "dio.h" #define STDIN 0 #define STDOUT 1 main(argc,argv) int argc; char *argv[]; { int append; char *s, ibuf[BUFSIZ], obuf[BUFSIZ]; dioinit(&argc,argv); append=FALSE; /* process options */ while(--argc > 0 && (*++argv)[0] == '-') for(s=argv[0]+1; *s != '\0'; s++) switch(*s) {case 'A': append=TRUE;  break; default: error("usage: tee [-a] outfile"); } if(!append) {if(fcreat(*argv,obuf) == ERROR) error("tee: can't create output file"); if(tfcopy(STDIN,obuf,TRUE) == ERROR) error("tee: file output error"); fefc(obuf); } else {if(fcreat("temptee.$$$",obuf) == ERROR) error("tee: can't create temp file"); if(fopen(*argv,ibuf) != ERROR) if(tfcopy(ibuf,obuf,FALSE) == ERROR) terror("tee: file output error copying prior to append"); if(tfcopy(STDIN,obuf,TRUE) == ERROR) terror("tee: file output error during append"); fefc(obuf); unlink(*argv); if(rename("temptee.$$$",*argv) == ERROR) error("tee: output is on temptee.$$$ ; can't rename"); } dioflush(); } /* tfcopy -- copy file fin to fout, line by line. Returns OK or ERROR. If echo, output goes to both fout and STDOUT. */ tfcopy(fin,fout,echo) char *fin, *fout; int echo; { int c; char line[MAXLINE]; while(fgets(line,fin)) {if(fputs(line,fout) == ERROR) return(ERROR); if(echo) fputs(line,STDOUT); } return(OK); } /* terror -- release temp file, then normal error */ terror(msg) char *msg; { unlink("temptee.$$$"); error(msg); } utput error copying prior to append"); if(tfcopy(STDIN,obuf,TRUE) == ERROR) terror("tee: file output error during append"); fefc(obuf); unlink(*argv); if(rename("temptee.$$$",*argv) == ERROR) error("tee: output is on temptee.$$$ ; can't rename"); } dioflush(); } /* tfcopy -- cop/* tr.c -- UTOOL. Transliterate characters author: David H. Wolen last change: 12/31/82 usage: tr src dest tr #A-Z# a-z (change case) tr " \t\n" \n (make one word per line) tr !\n (delete everything but newlines) tr 0-9 9 (change digit strings to single digit 9) input: STDIN output: STDOUT notes: (1) - denotes range (2) ! denotes "all but" (3) \n (newline) \t (tab) \b (backspace) \r (carr ret) \f (form feed) \p (#) \q (") (4) if dest is absent, all chars represented by src are deleted (5) if dest is shorter than src, all chars of src that would map to or beyond last char in dest are mapped to last char in dest. Adjacent instances of such chars in src cause a single instance of last char in dest to be output. (6) use " " to enclose blanks in src and dest (7) use # # to enclose capital letters in src and dest linkage: a:clink tr -f dio -ca (uses deff3.crl) */ #include "a:bdscio.h" #include "dio.h" #define NEGATE '!' #define ESCAPE '\\' main(argc,argv) int argc; char *argv[]; { int c, i, lastto, allbut, squash; char arg[MAXLINE], fromset[MAXLINE], toset[MAXLINE]; dioinit(&argc,argv); if(argc <= 1) error("usage: tr from to"); rcarg(arg,*++argv); allbut=(arg[0] == NEGATE); if(allbut) i=1; else i=0; if(!makset(arg,i,fromset,MAXLINE)) error("tr: from set too large"); if(argc == 2) /* empty toset */ toset[0]='\0'; else {rcarg(arg,*++argv); if(!makset(arg,0,toset,MAXLINE)) error("tr: to set too large"); } if(strlen(fromset) < strlen(toset)) error("tr: from shorter than to"); lastto=strlen(toset) -1; squash=(strlen(fromset) > lastto +1) || allbut; do {i=xindex(fromset,(c=getchar()),allbut,lastto); if(squash && i >= lastto && lastto >= 0) {putchar(toset[lastto]); do i=xindex(fromset,(c=getchar()),allbut,lastto); while(i >= lastto); } if(c != EOF) {if(i >= 0 && lastto >= 0) /* translate */ putchar(toset[i]); else if(i < 0) /* copy */ putchar(c); } /* else delete */ } while(c != EOF); dioflush(); } /* makset -- make set from inset[k] in outset. Returns FALSE for no room */ makset(inset,k,outset,maxset) char *inset, *outset; int k, maxset; { int j, kk; j=0; kk=k; dodash('\0',inset,&kk,outset,&j,maxset); return(addstr('\0',outset,&j,maxset)); } /* xindex -- conditionally invert value from cindex */ xindex(inset,c,allbut,lastto) char *inset; int allbut, lastto, c; { if(c == EOF) return(-1); if(!allbut) return(cindex(inset,c)); if(cindex(inset,c) >= 0) return(-1); else return(lastto+1); }  while(i >= lastto); } if(c != EOF) {if(i >= 0 && lastto >= 0) /* translate */ putchar(toset[i]); else if(i < 0) /* copy */ putchar(c); } /* else delete */ } while(c != EOF); dioflush(); } /* makset -- make set from inset[k] in outset. Returns FALSE for no room */ makset(inset,k,outset,maxset) char *inset, *outset; int k, maxset; { int j, kk; j=0; kk=k; dodash('\0',inset,&kk,outset,&j,maxset); ret/* uniq.c -- UTOOL. Filters out adjacent duplicate lines in sorted file. Lines must be identical (including same length) to be filtered out. author: David H. Wolen last change: 12/2/82 option: -c prefixes each output line with count usage: sort outfile -c input: STDIN output: STDOUT linkage: a:clink uniq -f dio -ca (uses deff3.crl) */ #include "a:bdscio.h" #include "dio.h" #define STDIN 0 #define STDOUT 1 #define STDERR 4 main(argc,argv) int argc; char *argv[]; { int count, cflag; char *s, line1[MAXLINE], line2[MAXLINE]; dioinit(&argc, argv); cflag=FALSE; while( --argc>0 && (*++argv)[0]=='-') for(s=argv[0]+1; *s != '\0'; s++) switch(*s) {case 'C': cflag=TRUE; break; default: error("uniq: -c is only valid option"); } if(!fgets(line1,STDIN)) error("uniq: empty input file"); count=1; while(fgets(line2,STDIN)) if(eqs(line1,line2)) count++; else {if(cflag) fprintf(STDOUT,"%d %s",count,line1); else fputs(line1,STDOUT); strcpy(line1,line2); count=1; } if(cflag) fprintf(STDOUT,"%d %s",count,line1); else fputs(line1,STDOUT); dioflush(); } UT 1 #define STDERR 4 main(argc,argv) int argc; char *argv[]; { int count, cflag; char *s, line1[MAXLINE], line2[MAXLINE]; dioinit(&argc, argv); cflag=FALSE; while( --argc>0 && (*++argv)[0]=='-') for(s=argv[0]+1; *s != '\0'; s++) switch(*s) {case 'C': cflag=TRUE; break; default: error("uniq: -c is only valid option"); } if(!fgets(line1,STDIN)) error("uniq: empt/* unrot.c -- UTOOL. Unrotate lines rotated by kwic. Last step in making keyword-in-context index. author: David H. Wolen last change: 12/2/82 usage: kwic outfile input: STDIN output: STDOUT linkage: a:clink unrot -f dio -ca */ #include "a:bdscio.h" #include "dio.h" #define STDIN 0 #define STDOUT 1 #define FOLD '$' /* indicates begin of folded line */ #define MAXOUT 92 /* width of output lines */ main(argc,argv) int argc; char *argv[]; { char inline[MAXLINE], outline[MAXOUT]; int i, j, middle; dioinit(&argc,argv); middle = max(MAXOUT/2,0) -1; while(fgets(inline,STDIN)) {for(i=0; i 0 && inline[i-1] == ' ') if(nextj(1,inline,i,j) >= MAXOUT-3)  j=0; if(j >= MAXOUT -3) j=0; outline[j]=inline[i]; } if(inline[i] == FOLD) /* copy 2nd half working backwards */ {j=middle-1; for(i=strlen(inline)-2; i >= 0; i--) { if(inline[i] == FOLD) break; j--; if(inline[i+1] == ' ') if(nextj(-1,inline,i,j) < 0) j=MAXOUT-3; if(j < 0) j=MAXOUT-3; outline[j]=inline[i]; } } for(i=MAXOUT-3; i >= 0; i--) if(outline[i] != ' ') /* delete trail blanks and terminate line */ break; outline[++i]='\n'; outline[++i]='\0'; fputs(outline,STDOUT); } dioflush(); } /* nextj -- see if enough space for another word */ nextj(incr,lbuf,i,j) char *lbuf; int incr, i, j; { int k; for(k=i; k >= 0; k += incr) {if(lbuf[k] == ' ' || lbuf[k] == FOLD || lbuf[k] == '\n') break; j += incr; } return(j); }  break; j--; if(inline[i+1] == ' ') if(nextj(-1,inline,i,j) < 0) j=MAXOUT-3; if(j < 0) j=MAXOUT-3; outline[j]=inline[i]; } } for(i=MAXOUT-3; i >= 0; i--) if(outline[i] != ' ') /* delete trail blanks and terminate line */ break; outline[++i]='\n'; outline[++i]='\0'; fputs(outline,STDOUT); } dioflush(); } /* nextj -- /* utdir.c -- UTOOL. Sorted file directory. author: David H. Wolen last change: 6/5/83 usage: utdir *.* all files on current drive utdir !*.com all files on current drive except .com utdir b:*.* !b:*.c all files on b: except .c utdir ?.com all .com files with single letter file name on current drive options: none input: command line only output: STDOUT notes: 1. max of 200 files after expansion 2. metacharacters in filename: ! except ? wildcard match a single character * wildcard match 1 or more characters linkage: a:clink utdir -f a:dio -f a:wildexp -ca */ #include "a:bdscio.h" #include "a:dio.h" main(argc,argv) int argc; char *argv[]; { int i, strcmp(); if(wildexp(&argc,&argv) == ERROR) error("utdir: error in wildexp"); dioinit(&argc,argv); if(argc == 1) error("utdir: no matching files"); qsort(&argv[1],argc-1,2,&strcmp); /* skip first argv */ for(i=1; i < argc; i++) printf("%s\n",argv[i]); dioflush(); } /* strcmp -- special version. Library version has args *s, *t */ strcmp(s,t) char **s, **t; { char *s1, *t1; int i; s1=*s; t1=*t; i=0; while(s1[i] == t1[i]) if(s1[i++] == '\0') return(0); return(s1[i] - t1[i]); }  ! except ? wildcard match a single character * wildcard match 1 or more characters linkage: a:clink utdir -f a:dio -f a:wildexp -ca */ #include "a:bdscio.h" #include "a:dio.h" main(argc,argv) int argc; char *argv[]; { int i, strcmp(); if(wildexp(&argc,&argv) == ERROR) error("utdir: /* vsplit.c -- UTOOL. Vertically split a text file. author: David H. Wolen last change: 2/20/83 usage: vsplit cc col vsplit ll 80 (output first 80 cols of each line) vsplit lr 10 (delete first 10 cols, output rest) vsplit rl 10 (delete last 10 cols, output rest) vsplit rr 15 (output last 15 cols) options: ll split from left, output left part lr split from left, output right part rl split from right, output left part rr split from right, output right part input: STDIN output: STDOUT notes: 1. If input line contains only , so will output 2. If ll and col > line length, output will be whole line 3. If lr and col > line length, output will be 4. If ll and col <= 0, output will be 5. If lr and col <= 0, output will be whole line  6. If rl and col > line length, output will be 7. If rr and col > line length, output will be whole line 8. If rl and col <= 0, output will be whole line 9. If rr and col <= 0, output will be linkage: a:clink vsplit spltscan -f dio -ca (uses deff3.crl) */ #include "a:bdscio.h" #include "dio.h" #define STDIN 0 #define STDOUT 1 main(argc,argv) int argc; char *argv[]; { int leftsplt, leftout, col; char line[MAXLINE], left[MAXLINE], right[MAXLINE]; dioinit(&argc,argv); /* process options */ if(argc < 3) error("usage: vsplit option col"); if(eqs(argv[1],"LL")) leftsplt=leftout=TRUE; else if(eqs(argv[1],"LR")) {leftsplt=TRUE; leftout=FALSE; } else if(eqs(argv[1],"RL")) {leftsplt=FALSE; leftout=TRUE; } else if(eqs(argv[1],"RR")) leftsplt=leftout=FALSE;  else error("vsplit: valid options are ll lr rl rr"); col=atoi(argv[2]); /* main */ while(fgets(line,STDIN)) {line[strlen(line)-1]='\0'; /* zap newline */ if(leftsplt) split(line,col,left,right); else splitr(line,col,left,right); if(leftout) fprintf(STDOUT,"%s\n",left); else fprintf(STDOUT,"%s\n",right); } dioflush(); }  char line[MAXLINE], left[MAXLINE], right[MAXLINE]; dioinit(&argc,argv); /* process options */ if(argc < 3) error("usage: vsplit option col"); if(eqs(argv[1],"LL")) leftsplt=leftout=TRUE; else if(eqs(argv[1],"LR")) {leftsplt=TRUE; leftout=FALSE; } else if(eqs(argv[1],"RL")) {leftsplt=FALSE; leftout=TRUE; } else if(eqs(argv[1],"RR")) leftsplt=leftout=FALSE; *K͞+'+FÎr ͖ 8{ Ăw#w#w^#V#*~#fo^#*~#fo^#V#*n^#*n^#V# ~#fo^#& ~#fo!+!#!+!#!+!+}|z{|}|z7||7zZZ)|/g}/o#|͉k|/g}/o#ɯ2qZZk:q|/g}/o#|/g}/o#:q<2qqDM!xxGyO҃)v|͔`i|)Öxڷz/W{/_ѯzW{_=yOxGæ2qZZ͉M|}ȯ|g}o)|/g}/o#z/W{/_!9~#fo! ! ! ! ! ! !9~#A"s!`*"!"!Y">2>2>22!"!"!@"!" ʞ!F#x±~#±!b2r~# "2r+}|~#G:rx"2r+w# +6#!6#2w2x*s!>r<o&F=-` r'~h6!+`W?_!~7z?` :>ª@w#G.¶ww#?*>?w#> w#.7:77!a{   `OE!y6$ -7rBo&))T])))!y':7?h#D/6:?>$:?$:)?$l,:>#)Ÿ#>67:+?7#*+?|°#2ͩ7#>67:+?7>#7>67:,?7#*+?"?)#>7:+?7>s7>@2?#2ͩ7#)$:"?=2"?))$>s7#͎)5$2:>/$2ͩ7#3ͩ7#* ?"?*+?"?:)?ʟ$:>€$)s$>>7:+?72ͩ7#2ͩ72?#)s$>7:+?7>{72ͩ7#)¸$:)?‘$>}72v$:)?1.͎)$>&773v$:)?$l,Ä#:?$u-l,$:)?>%>7l,>7>@2)?$* ?"?R3ͩ7:?2?"?|O%}@%3ͩ7V%C%4ͩ7>G>)7[%#͔+:*ͅ-í æ !9DM͐! ͡! s#r! s#r! s#r! w#wͤ`is#rz}`i~#fo|g}os#r! ^#Vr+s͐|+! ^#Vr+s͐|R͐|R͐|]! w#wz͐|z! 6#6! ^#Vr+s͐͐͐!!ͧͪ! 9lines=%u words=%u chars=%u Ã]Æ!9DM*s*s*s!  ~#fo͐ ~#fo)* s#r*6**s#r! 6#6`i6#6͐͐ ~#foE w}l E ! ~#fo͐)~#fon}<ʙ |M + > . ! ~#fo͐)~#fo#n}· *! ~#fo͐)~#fo##| ! ~#fo͐)~#fo#!N !*6!] ! ~#fo͐)~#fo|J *n&|g}os} *4! ~#fo͐)~#fo#* s#r! ~#fo͐)~#fo#n} ! ~#fo͐)!i s#r! ~#fo͐)* s#r *n&|g}os! ~#fo͐)~#fo#n} !v !! ~#fo͐)~#fo#*! ~#fo͐)~#fo##|u ! ~#fo͐)~#fo#! !*4w} ͐! s#r͐͐ ~#fo ! ~#fo͐)! ~#fo͐#)~#fos#r! ^#Vr+sÒ ͐ ^#Vr+s`i^#Vr+s* ^#Vr+s+ ͐ ͐s#r! ~#fo͐ ~#fo)w#w9 ! ^#Vr+s`i^#Vr+sL !9Can't open %s ¢>>®>>º>>>(! n&v! n&!y! n&!y! n} ! !y! n&!y͐##^#Vr+s|‡!͐͐~#fo||f!͐##6#6͐͐s#r͐^#Vr+s! ns&óWè!9DM͐!͐##~#fo|!͐##~#fo`is#r͐͐͐~#foͪ͐2!͐+?`is#r͐##~#fo|!͐͐͐ͭ͐##~#fo͐s#r͐~#fo͐s#r!!͐~#foͰ͐##6#6͐͐s#r!!9 f!9DM͐|͐+++|,!͐##^#Vr+s|ª!͐͐~#fo`is#r!|}͐##^#Vr+s͐##͐?+s#r͐͐s#r͐^#Vr+sn&!9!9DM`iw#w! ^#Vr+sn}`i^#Vr+s͐!9È÷!h9DM! ^#Vr+s~#fo! s#r͐! s#r! ^#Vr+sn`is{g`in}%Q! ! s#r! 6#6! s! s! s͐n}-¦! ^#Vr+s! 4͐n}0¶! 4͐n& }! !! s#r! ^#Vr+sn`is{.! ! s#r! 4! ^#Vr+sn`is`in&}DJUʆXʏOʘCS;͐~#fo|҆! ^#Vr+s6-͐͐~#fos#r! ^#Vr+s! 6 Þ! 6Þ! 6! ~#fo! n&! ^#Vr+s~#fo! ѯgs#rÇ! ^#Vr+s! ^#Vr+s~#fos! ^#Vr+sÇ! n}"! 6#6! ^#Vr+s~#fo! s#r͐n}ʇ͐|ʇ! ^#Vr+s! ^#Vr+sns! ^#Vr+s! ^#Vr+s=͐6! ! s#r! n}! ^#Vr+s!|! ^#Vr+s! n}!0! sã͐! ^#Vr+sns{! ^#Vr+s! n}8! ^#Vr+s!|8! ^#Vr+s6 N! ^#Vr+s`insd! ^#Vr+s`insE͐6!9|s!9DM! ^#Vr+sn`is{`in} ²͐! y͐`in&y#|!Ä!!9!9DM͐͐ 4͐^#Vr+s͐!͐0)͐7s!&͐ ͐͐ ͉͐`is͐ ͐͐ )͐`in&#&!9!9DM! n&|ͯڳ! n&|ͩýÈ!9DM`iw#w͐~#fon&ͺ} ͐ ?͐^#Vr+snѯg`is#r͐!9 T!9DM! n&|G! n&N! n&&!9DM! n&|ͯ! n&|ͩ  !\&!7*!&*!&!&="&! BL<"e=L=É7*^#V#zx24+V+^+*:4o&9! !j96  #F#xa~#T7:O*7,2q*&:q):ʳ=ʳ=r:qo&Æw7*;\!*#7:)~:,"s!"u*|*uU*~#,"*s*uU#"u*+"7*|DM**چ><~+ x–|}îä7:,*ͫ:*}|2q :qw!! {w7:)~:,"s!"u*|i**sn! ~i6*u*+"*"*u#"u57*!9& 6C#6O#6M¸*|!\&!\&*|!!l&!9~#fo> +q#~##xS:" óEXECL: Too much text $!pz!*w#F*:1`*i!i!a{ ѷ! , FNxg>Goy$7*^#V#zx24+V+^+*:4o&9! !j96  #F#xa~#T7:O*7,2q*&:q):ʳ=ʳ=r:qo&Æw7*;\!*#7:)~:,"s!"u*|*uU*~#,"*s*uU#"u*+"7*|DM**چ><~+ x–|}îä7:,*ͫ:*}|2q :qw/* wc.c -- UTOOL. Count lines, words and characters in standard input. Can handle Wordstar doc files. author: David H. Wolen last change: 9/9/82 usage: wc a:prep a:prep a:cat file1.dat file2.dat file3.dat |a:sort -fu |a:lpr 5 Sorte lis o al word i WordSta do file On wor pe line Distinguis betwee uppe an lowe cas alpha Sho only one occurrence of each word. B>a:cat outfile a:cat outfile a:cat outfile -w k Wher UTOO a tak regula fil a inpu (withou th < an ha option (-xyz) consul th manua pag t se whethe th option mus b give befor o afte th fil name Th optio usuall preceed th fil nam bu ɠ wasn' perfectl consistent. E.g. a:cal file -g 01/01/83 (option follows file name) a:cat -w file (option preceeds file name) a:comm -12 file (option preceeds file name) a:crt -n file (option preceeds file name) l Th followin ar registere trademarks Osborn b Osborn Computer CP/ b Digita Research Z80 b Zilog UNI b Bel Labs, WordStar by MicroPro.  or -abc. j Option an redirecte inpu an outpu ca appea i an order. E.g. all of the following are o.k. a:cat -w outfile a:cat outfile a:cat outfile -w k Wher UTOO a tak regula fil a inpu (withou th < an ha option (-xyz) consul th manua pag t se whethe th option mus b give befor o afte th fil name Th optio usuall preceed th fil nam bu ɠ wasn' perfectl consistent. E.g. a:cal file -g 01/01/83 (option follows file name) a:cat -w file (option preceeds file name) a:comm -12 file (option preceeds file name) a:crt -n file (option preceeds file name) l Th followin ar registere trademarks Osborn b Osborn Computer CP/ b Digita Research Z80 b Zilog UNIat only do words on file -i list.dat ignore words on file -d preface output words with input sequence numbers input: STDIN output: STDOUT notes: (a) files for -o and -i must be prepared by prep and sort (-f and -u) (b) can't use both -o and -i (c) output is lower case (d) max file size for -o or -i is 1000 lines or about 30K. */ /* sort.c -- UTOOL. (ver. 2) Incore sort of ascii lines. Max file size 2000 lines or about 30K. author: David H. Wolen last change: 5/5/83 usage: sort outfile sort 0 && (*++argv)[0] == '-') for(s=argv[0]+1; *s != '\0'; s++) switch (*s) {case 'E': eq=TRUE; break; case 'G': gt=TRUE; break; case 'L': lt=TRUE; break; case 'R': range=TRUE; break; default: error("cal: invalid option"); } if(convdate(*argv++,&argdate1)==ERROR) error("cal: invalid date1"); if(range) {if(convdate(*argv,&argdate2)==ERROR) error("cal: invalid date2"); if(eq || gt || lt) error("cal: no other options allowed with -r"); } if(!eq && !gt && !lt && !range) /* default -e if no options */ eq=TRUE; while(isstdin ? fgets(line,STDIN) : fgets(line,ibuf)) {if(!finddate(line,cdate)) continue; else convdate(cdate,&linedate); if(eq && datecmp(&linedate,&argdate1)==0) fputs(line,STDOUT); if(gt && datecmp(&linedate,&argdate1) > 0) fputs(line,STDOUT); if(lt && datecmp(&linedate,&argdate1) < 0) fputs(line,STDOUT); if(range && datecmp(&linedate,&argdate1) >= 0 && datecmp(&linedate,&argdate2) <= 0) fputs(line,STDOUT); } dioflush(); } /* convdate -- convert mm/dd/yy to structure date */ convdate(mmddyy,pd) char *mmddyy; struct date *pd; { int tmonth, tday, tyear; char mm[3], dd[3], yy[3]; mm[0]=mmddyy[0]; mm[1]=mmddyy[1]; dd[0]=mmddyy[3]; dd[1]=mmddyy[4]; yy[0]=mmddyy[6]; yy[1]=mmddyy[7]; mm[2]=dd[2]=yy[2]='\0'; tmonth=atoi(mm); tday=atoi(dd); tyear=atoi(yy); if(tyear < BASEYR) tyear += 2000; else tyear += 1900; if(tmonth < 1 || tmonth > 12) return(ERROR); if(tday < 1 || tday > 31) return(ERROR); switch(tmonth) {case 1: case 3: case 5: case 7: case 8: case 10: case 12: if(tday > 31) return(ERROR); break; case 4: case 6: case 9: case 11: if(tday > 30) return(ERROR); break; case 2: if(tyear % 4 == 0 && tyear % 100 != 0 || tyear % 400 == 0) {if(tday > 29) /* leap year */ % return(ERROR); break; } else {if(tday > 28) /* not leap year */ return(ERROR); break; } default: error("in convdate -- can't happen"); } pd->day=tday; pd->month=tmonth; pd->year=tyear; return(OK); } /* finddate -- find mm/dd/yy in line */ finddate(line,mmddyy) char *line, *mmddyy; { struct date dtest; char ctemp[9]; int i, len, start; if((start=index(line,"/")) < 0) return(FALSE); start=max(start-2,0); len=strlen(line); for(i=start; i0 if first is <,==,> second. */ datecmp(pd1,pd2) struct date *pd1, *pd2; { if(pd1->year > pd2->year) return(1); if(pd1->year < pd2->year) return(-1); if(pd1->month > pd2->month) return(1); if(pd1->month < pd2->month) return(-1); if(pd1->day > pd2->day) return(1); if(pd1->day < pd2->day) return(-1); return(0); } j)); if(k >= 0) /* matched rest of pattern */ done=TRUE; else i--; } offset2=k; done=TRUE; } else if(!omatch(lin,&offset2,pat,j)) {offset2=-1; done=TRUE; } else j += patsize(pat,j); } return(offset2); } /* patsize -- return size of pattern entry at pat[n] usage: j += patsize(pat,j); */ patsize(pat,n) char *pat; int n; { switch(pat[n]) {case LITCHAR: return(2); case BOL: case EOL: case ANY: return(1); case CCL: case NCCL: return(pat[n+1]+2); case CLOSURE: return(CLOSIZE); default: error("in patsize: can't happen"); } } /* omatch -- match one pattern element at pat[j] usage: if(!omatch(lin,&i,pat,j)) ... */ omatch(lin,i,pat,j) char *lin, *pat; int *i, j; { int advance, retval; advance=-1; if(lin[*i] == '\0') retval=FALSE; else switch(pat[j]) {case LITCHAR: if(lin[*i] == pat[j+1]) advance=1; break; case BOL: if(*i == 0) advance=0; break; case ANY: if(lin[*i] != '\n') advance=1; break; case EOL: if(lin[*i] == '\n') advance=0; break; case CCL: if(locate(lin[*i],pat,j+1)) advance=1; break; case NCCL: if(lin[*i] != '\n' && !locate(lin[*i],pat,j+1))  advance=1; break; default: error("in omatch: can't happen"); } if(advance >= 0) {(*i) += advance; retval=TRUE; } else retval=FALSE; return(retval); } /* locate -- look for c in character class at pat[offset] usage: if(locate(lin[i],pat,j+1)) ... */ locate(c,pat,offset) char c, *pat; int offset; { int i; i=offset+pat[offset]; while(i > offset) if(c == pat[i]) return(TRUE); else i--; return(FALSE); } /* getpat -- convert argument into pattern usage: if(!getpat(arg,pat)) ... */ getpat(arg,pat) char *arg, *pat; { return(makepat(arg,0,'\0',pat) >= 0); } /* makepat -- make pattern from arg[i], terminate at delim. returns i>=0 if ok, else ERROR (-1). usage: if(makepat(arg,0,'\0',pat) == ERROR) ... */ makepat(arg,start,&delim,pat) char *arg, delim, *pat; int start; { int i, j, lastj, lj, done; j=0; /* pat index */ i=start; /* arg index */ lastj=0; done=FALSE; while(!done && arg[i] != delim && arg[i] != '\0') {lj=j; if(arg[i] == ANY) addstr(ANY,pat,&j,MAXLINE); else if(arg[i] == BOL && i == start) addstr(BOL,pat,&j,MAXLINE); else if(arg[i] == EOL && arg[i+1] == delim) addstr(EOL,pat,&j,MAXLINE); else if(arg[i] == CCL) done=(getccl(arg,&i,pat,&j) == FALSE); else if(arg[i] == CLOSURE && i > start) {lj=lastj; if(pat[lj] == BOL || pat[lj] == EOL || pat[lj] == CLOSURE) done=TRUE; else stclose(pat,&j,lastj); } else {addstr(LITCHAR,pat,&j,MAXLINE); addstr(esc(arg,&i),pat,&j,MAXLINE); }  lastj=lj; if(!done) i++; } if(done || arg[i] != delim) return(ERROR); else if(!addstr('\0',pat,&j,MAXLINE)) return(ERROR); else return(i); } /* getccl -- expand char class at arg[i] into pat[j]. Return TRUE if find CCLEND, else FALSE. usage: if(!getccl(arg,&i,pat,&j)) ... */ getccl(arg,i,pat,j) char *arg, *pat; int *i, *j; { int jstart; (*i)++; /* skip over [ */ if(arg[*i] == NEGATE) {addstr(NCCL,pat,j,MAXLINE); (*i)++; } else addstr(CCL,pat,j,MAXLINE); jstart=*j; addstr(0,pat,j,MAXLINE); /* room for count */ dodash(CCLEND,arg,i,pat,j,MAXLINE); pat[jstart]=*j -jstart -1; return(arg[*i] == CCLEND); } /* stclose -- insert closure entry at pat[j] usage: stclose(pat,&j,lastj); */ stclose(pat,j,lastj) char *pat; int *j, lastj; { int jp, jt; for(jp=*j -1; jp >= lastj; jp--) {jt=jp +CLOSIZE; addstr(pat[jp],pat,&jt,MAXLINE); } (*j) += CLOSIZE; pat[lastj] = CLOSURE; /* where orig pattern began */ } /* undoc -- zero hi bit & replace strange chars by blanks (WS doc files) usage: putchar(undoc(c)); */ char undoc(c) char(c); { c &= 0177; /* zero hi bit */ if(c == '\0' || c == '\n' || c == '\r') /* leave as is */ return(c); else if(c < ' ' || c == 0x7f) /* replace by blank */ return(' '); else return(c); } j,MAXLINE); jstart=*j; addstr(0,pat,j,MAXLINE); /* room for count */ dodash(CCLEND,arg,i,pat,j,MAXLINE); pat[jstart]=*j -jstart -1; return(arg[*i] == CCLEND); } /* stclose -- insert closure entry at pat[j] usage: stclose(pat,&j,lastj); */ stclose(pat,j,lastj) char *pat; int *j, lastj; { int jp, jt; for(jp=*j -1. author: David H. Wolen last change: 12/2/82 option: -c prefixes each output line with count usage: sort outfile -c input: STDIN output: STDOUT */ /* unrot.c -- UTOOL. Unrotate lines rotated by kwic. Last step in making keyword-in-context index. author: David H. Wolen last change: 12/2/82 usage: kwic outfile input: STDIN output: STDOUT */ /* utdir.c -- UTOOL. Sorted file directory. author: David H. Wolen last change: 6/5/83 usage: utdir *.* all files on current drive utdir !*.com all files on current drive except .com utdir b:*.* !b:*.c all files on b: except .c utdir ?.com all .com files with single letter file name on current drive options: none input: command line only output: STDOUT notes: 1. max of 200 files after expansion 2. metacharacters in filename: ! except ? wildcard match a single character * wildcard match 1 or more characters */ /* vsplit.c -- UTOOL. Vertically split a text file. author: David H. Wolen last change: 2/20/83 usage: vsplit cc col vsplit ll 80 (output first 80 cols of each line) vsplit lr 10 (delete first 10 cols, output rest) vsplit rl 10 (delete last 10 cols, output rest) vsplit rr 15 (output last 15 cols) options: ll split from left, output left part lr split from left, output right part rl split from right, output left part rr split from right, output right part input: STDIN output: STDOUT notes: 1. If input line contains only , so will output 2. If ll and col '> line length, output will be whole line 3. If lr and col > line length, output will be 4. If ll and col <= 0, output will be 5. If lr and col <= 0, output will be whole line 6. If rl and col > line length, output will be 7. If rr and col > line length, output will be whole line 8. If rl and col <= 0, output will be whole line 9. If rr and col <= 0, output will be */ /* wc.c -- UTOOL. Count lines, words and characters in standard input. Can handle Wordstar doc files. author: David H. Wolen last change: 9/9/82 usage: wc , so will output 2. If ll and col