Part_1 | - demo uvcopy for All Purpose 'Text file' Manipulation |
- uvcopy can save a great amount of manual editing drudgery | |
- with a few lines of uvcopy code, you can do a complex job that | |
would require hundreds of lines of COBOL code. | |
repage1 - demo mass changes to documentation | |
codefix1 - demo mass changes to program code | |
codefix2 - cleanup scripts & C programs | |
scripts - ensure 1st line is '#!/bin/ksh' | |
C prgms - insert /* filename */ on first line as a /* comment */ | |
emailfix1 - cleanup email |
Part_2 | - demo uvcopy for All Purpose 'Data File' Utility jobs |
adrsfix1 - eliminate duplicate Names & Addresses by standardizing | |
street addresses (street to st., road to rd., etc) | |
- drop duplicates with uvsort unique key option | |
adrsfix2 - alternate version using search/replace tables | |
vs embedded code as in adrsfix1 | |
adrsfix3 - alternate version to combine amount fields into 1 remaining | |
record for duplicate key record group | |
splitprint1 - split large print file into multiple files | |
of specified number of pages each |
Goto: Begin this doc , End this doc , Index this doc , Contents this library , UVSI Home-Page
1A1. | 'repage1' - demo mass changes to documentation |
- replace common contents page 1 in all documents | |
- saves many hours of manual editing | |
- page 1 is contents for all Vancouver Utilities | |
& needs to be updated when any document title changed |
1B1. | repage1 problem illustration |
1C1. | problem solution - uvcopy job 'repage1' operating instructions |
1D1. | 'repage1' uvcopy job listing |
1E1. | 'repage1' vital instructions explained |
The Vancouver Utilities includes over 160,000 lines of 'C' in 55 programs. The code was developed over many years on various unix & linux systems.
HP compilers did not accept '/*' embedded in '/* ..code.. /* ..comments.. */'. uvcopy codefix1 made it easy to change it to '/* ..code.. |* ..comments.. */'.
1F1. | Fix embedded '/*' comments in all 'C' programs in source directory |
- demo uvcopy mass change to text files saving days of manual editing | |
1F2. | codefix1 Operating Instructions |
1F3. | alldiff - verify mass changes |
1F4. | codefix1 uvcopy job listing |
1F5. | codefix1 vital instructions explained |
1G1. | codefix2 - cleanup scripts & C programs |
- convert tabs to 3 spaces & reduce multiple blank lines to 1 | |
scripts - ensure 1st line is '#!/bin/ksh' | |
- insert #filename on 2nd line as a #comment | |
- insert '\' to split long lines exceeding column 80 | |
C prgms - insert /* filename */ on first line as a /* comment */ | |
- left adjust lines with leading blanks to a /* comment */ | |
- insert /*eject*/ prior to a /*----*/ if < 25 lines since last |
1G2. | sample script & C program BEFORE & AFTER codefix2 cleanup |
1G3. | codefix2 uvcopy job listing |
1H1. | emailfix1 - cleanup email |
- remove the '>' retransmitted indicators | |
- left justify lines & leave just 1 blank between words | |
- reformat lines to about 50 characters | |
- reduce multiple blank lines to 1 |
Goto: Begin this doc , End this doc , Index this doc , Contents this library , UVSI Home-Page
'repage1' is a 'uvcopy job' that UV Software uses to update the 1st page of any file in the doc directory (/home/uvadm/doc/...) that has the standard 'contents page'. There are over 100 files in the doc/... subdir & about 60 of them have the common page 1 contents that you see on the 1st page of this document uvcopy7.htm.
It was a very laborious job to make the updates when I needed to change page 1 in all those files, so I finally developed this 'repage1' uvcopy job to do it automatically (after I edited 1 master copy of the new page 1).
These files are all unix/linux text files maintained with the 'vi' editor ' (despite the .doc extension). Periodically the text files are automatically converted to HTML (with uvcopy jobs as described in 'HTMLjobs.doc) & FTP'd to the UV Software web site (www.uvsoftware.ca).
Note that the common page 1 contents is printed for the hard-copy manuals, but is usually dropped when we convert to HTML for the website, because the website has the home-page & many links for navigation. The common page 1 on the hard-copy manuals is intended to help the reader relate the current manual to the other manuals available. I set the option to retain page 1 on this uvcopy7.doc so you can see the subject under discussion.
'repage1' was developed as a UV Software internal aid, but it is a good illustration of the power of uvcopy - how to do a lot of complex data manipulation with very few instructions.
You may have similar problems with your data files that could be solved with similar techniques. If your files are in a database or WORD or Excel spread sheets, you could export them to text or delimited files, and re-import them after manipulating with uvcopy.
uvcopy also works with mainframe type files (fixed/variable length, sequential or indexed files compatible with Micro Focus COBOL), but this section is focused on general purpose solutions rather than the mainframe conversions.
If you study this example, you will realize that 'uvcopy' could save you hundreds of hours of manual editing. If you needed help to implement a solution to your problem, describe your problem in an email to UV Software, and if we are not too busy we will help you with the solution.
Goto: Begin this doc , End this doc , Index this doc , Contents this library , UVSI Home-Page
Here is a cut-down version of page 1 of this & most UV Software documents. I have chopped off the right side, so I could make comments
CNVaids.doc - Mainframe <-- Title on line 2 of all page 1's *********************************** - restored from input file to new page1 ** <--- this section is related to (vs replacement page 1)
** volume 1 - Installa install.doc - install guide fo versions.doc - update history f uvprices.doc - Prices & License ... etc (lines removed) ...
** volume 2 - P uvlist.doc - list text files uvhd.doc - file display/se uvsort.doc - parameter drive uvcopy7.doc - general purpose ... etc (lines removed) ...
** volume 3 - MVS ** CNVaids.doc - Mainframe Aids <-- '**' marks the current file ** - restored in new page1 by searching for document name ('CNVaids' here) MVSJCL.doc - Converting JCL MVSCOBOL.doc - Converting COBOL ... etc (lines removed) ...
Goto: Begin this doc , End this doc , Index this doc , Contents this library , UVSI Home-Page
#1a. vi xxxx.doc <-- edit any existing file with contents page =========== :1,55 w new/page1 <-- write page1 to a separate file (in subdir new/)
#1b. vi new/page1 <-- edit new page1 as desired ============ - also remove existing '**' markers ........
#2a. mv doc doc.old <-- rename existing doc dir to doc.old ==============
#2b. mkdir doc <-- make a new (empty) doc dir =========
#3. uvcopy repage1,fild1=doc.old,fild2=doc,fili3=new/page1 ====================================================== - execute job to replace the 1st page on existing files that have a 'contents page' (identified by unique words)
#3a. uvcopy repage1 <-- same as above, but easier ============== - files default as shown above
#4. vi doc/* <-- spot check results ======== OR (better) use alldiff2 below
#5a. alldiff2 doc.old doc <-- create diff report for all files in 2 subdirs ==================== - writes diff's to tmp/doc.dif - see alldiff2 script listed at scripts.htm#83H
#5b. vi tmp/doc.dif <-- verify changes, only on page 1's ============== & no changes beyond line 55 of any document
#6a. tar cvf /dev/st0 doc.old <-- backup to DAT tape (or other disc) ========================
#6b. rm -rf doc.old <-- remove old directory ==============
'repage1' is listed on the next 3 pages, with line #s inserted, for references from explanations that follow on page '1E1'+ Inserting sequence#s is performed with uvcopy job 'seqnum1' a pre-programmed job that accepts I/O filenames, a displacement (0 in this case),& a pattern for seq# '#999_' in this case).
Goto: Begin this doc , End this doc , Index this doc , Contents this library , UVSI Home-Page
#001 # repage1 - uvcopy Parameter File from UVSI stored in: /home/uvadm/pf/adm/ #002 # repage1 - replace page1 (contents) of most files in /home/uvadm/doc/... #003 # - by Owen Townsend, UV Software, Jan 12/2008 #004 # #005 # 1. mv doc doc.old <-- change name of existing doc dir #006 # 2. mkdir doc <-- make new empty doc dir #007 # 3. uvcopy repage1,fild1=doc.old,fild2=doc,fili3=new/page1 #008 # ====================================================== #009 # - copy all docs from doc.old/... to new doc/... #010 # - replacing page 1 if criteria met ("volume" & "install.doc" found) #011 # #012 # At program init: #013 # - load new page 1 into memory area 'm' #014 # (will copy to alt area 'n' for modify & output) #015 # For each file in direcctory: #016 # - read entire file into area 'a' #017 # - test for contents page (patterns "volume" & "install.doc" present) #018 # If contents page: #019 # - copy new page1 from area 'm' to altternate area 'n' for modify #020 # - modify page1, insert page hdr from curent file, restore the '**' markers #021 # - dump modified new page1 from area 'n' to output file #022 # - clear page 1 (to 1st '*Eject') to nulls (inhibits output) #023 # Common to all files (whether contents page present/replaced or not) #024 # - dump file data from area 'a' to output file #025 # - repeat for all files in directory #026 # #027 opr='$jobname - copy all doc files, replacing page 1 if contents' #028 was=a4000000m6000n6000 # increase sizes of areas a,m,n #029 # area 'a' 4 Meg (20,000 lines max * 200 per line max) #030 # area 'm' & 'n' 6K (60 lines max * 100 per line max) #031 fild1=?doc.old,typ=DIR,rcs=80 #input directory #032 fili1=xxxxxxxx,typ=LST,rcs=512 #current input file from directory #033 fild2=?doc,typ=DIR,rcs=80 #output directory #034 filo2=xxxxxxxx,typ=LSTt,rcs=512 #current output file #035 fili3=?new/page1,typ=LSTt,rcs=128 #new page1 contents #036 @run #037 opn fild1 open input directory #038 opn fild2 open output directory (must exist) #039 opn fili3 open the new page1 file #040 msgwy 'did you rename doc as doc.old & create new empty doc ?' #041 clr m0(6000),'~' ensure page area ends with tildes #042 rtb fili3,m0(100),m0(100) read new page1 into area 'm' #043 #
Goto: Begin this doc , End this doc , Index this doc , Contents this library , UVSI Home-Page
#045 # begin loop to read directory for next filename #046 man10 get fild1,f0(80) get next record (filename) in directory #047 skp> man90 (cc set > at EOF) #048 skp< man10 (cc set < if any subdirs) #049 # create I/O filenames for opens by concat dirname + '/' + filename #050 clr f100(200),' ' #051 mvu f100(80),$fild1,x'00' move dirname until ending null #052 cat f100(80),'/' concat the '/' #053 cata8 f100(80),f0(40) concat current filename (a8 null terms) #054 mvu f200(80),$fild2,x'00' move output dirname until null reached #055 cat f200(80),'/' concat the '/' #056 cata8 f200(80),f0(40) concat current filename (a8 null terms) #057 # store current pair of input/output files & open the files #058 mvc $fili1,f100 store input filename before open #059 mvc $filo2,f200 store output filename before open #060 opn fili1 #061 opn filo2 #062 # #063 # read current file into area 'a' & test for .doc page1 to be replaced ? #064 # - specify end table char x'EF' (vs dflt '~') since doc might have '~'s #065 man20 rtb fili1,a0(200),a0(200),x'EF',x'EF' read file into memory #066 scn f0(40),'.doc' UVSI ____.doc ? #067 skp! man50 #068 scni a0(4000),'volume' pattern1 known to be in 1st 20 lines #069 skp! man50 #070 scni a0(4000),'install.d' pattern2 known to be in 1st 20 lines #071 skp! man50 #072 lok a0(200),a0(6),'*eject' look for 1st end page pattern #073 skp! man50 #074 mvn $ra,$rx save length to '*eject' for clr #075 # #076 # contents page1 confirmed - copy new page1(area 'm') to area 'n' to modify/dump #077 # - copy current file Title (line 2) to new page1 #078 # - try to locate current doc name on new page1 & flag '**' before & after #079 # (avoid matching title line, load $rn with 400 to start search on line 5) #080 # - nullify old page1 to inhibit output on table dump (wtb) #081 man30 mvc n0(6000),m0 copy new page1 from 'm' to 'n' to modify #082 mvc n100(100),a200 move old page1 hdr to new page1 #083 rep f0(20),'.doc',' ' remove .doc to match name for ** insert #084 mvn $rn,400 set rgstr 'n' to start search on line 5 #085 stsg4 nn00(100),n0(100),f0(20) search table for current doc name #086 skp! man36 #087 mvc nn00(2),'**' flag ** at begin line #088 mvc nn77(2),'**' flag ** at end line #089 man36 clr a0($ra12000),x'00' clear page1 (length in $ra saved above) #090 man40 wtbe filo2,n0(100),n0(100) dump new page1 (area 'n') to outfile #091 # #092 # common point to write out doc file data from area 'a' #093 # - 1st page cleared if volume contents, otherwise not #094 man50 wtbe filo2,a0(200),a0(200),x'EF' dump file data to outfile #095 cls fili1 close current input file #096 cls filo2 close current output file #097 skp man10 return to process next file #098 # #099 # end input directory - close all files & end job #100 man90 cls all #101 eoj
Goto: Begin this doc , End this doc , Index this doc , Contents this library , UVSI Home-Page
I will explain here only the instructions I think you might not fully appreciate without some additional comments. You can see all uvcopy instructions documented in uvcopy3.htm which has an alphabetical index. Note that all uvcopy instrns are 3 characters (anything following is an option).
Please relate the sequence# here to the full listing above.
#031 fild1=?doc.old,typ=DIR,rcs=80 #input directory #032 fili1=xxxxxxxx,typ=LST,rcs=512 #current input file from directory #033 fild2=?doc,typ=DIR,rcs=80 #output directory #034 filo2=xxxxxxxx,typ=LSTt,rcs=512 #current output file #035 fili3=?new/page1,typ=LSTt,rcs=128 #new page1 contents
#042 rtb fili3,m0(100),m0(100) read new page1 into area 'm'
#046 man10 get fild1,f0(80) ............... #061 opn filo2
#065 man20 rtb fili1,a0(200),a0(200),x'EF',x'EF' read file into memory
#068 scni a0(4000),'volume' pattern1 known to be in 1st 20 lines .................. #074 mvn $ra,$rx save length to '*eject' for clr
#081 man30 mvc n0(6000),m0 copy new page1 for modify #082 mvc n100(100),a200 move old page1 hdr to new page1
Goto: Begin this doc , End this doc , Index this doc , Contents this library , UVSI Home-Page
#083 mvn $rn,400 #084 stsg4 nn0(100),n0(100),f0(20) search table for current name.doc #085 skp! man36 #086 mvc nn0(2),'**' flag ** at begin line #087 mvc nn77(2),'**' flag ** at end line
#089 man36 clr a0($ra12000),x'00' clear page1 (length in $ra saved above)
#090 man40 wtbe filo2,n0(100),n0(100) dump new page1 to outfile
#094 man50 wtbe filo2,a0(200),a0(200),x'EF' dump file data to outfile
#095 cls fili1 close current input file #096 cls filo2 close current output file #097 skp man10 return to process next file
I hope I have explained this clearly. Please see all instructions documented in uvcopy3.htm which has an alphabetical index.
'repage1' only replaces page 1 (if recognized as a contents page). I use repage1 whenever the contents pages needs to be updated for all documents.
I have a 'repage2' job that also inserts the filename/title on all page headings, but it was not as useful as repage1 since I did not necessarily want the title on all page headings.
Goto: Begin this doc , End this doc , Index this doc , Contents this library , UVSI Home-Page
The Vancouver Utilities includes over 160,000 lines of 'C' in 55 programs. The code was developed over many years on various unix & linux systems.
In April 2008, I had my first chance to compile the programs on an HP Itanium, and encountered a problem. The HP compiler did not accept '/*' embedded within '/* ...comments ...*/'. In C a comment must begin with '/*' & end with '*/', But other compilers did not complain about the 2nd embedded '/*'.
Here are 3 coding examples illustrating the problem:
#1. /* prepend with 'cat > ...' & append with '/*' */ =================================================
#2. /* fwrite((char*)fcip,1,100,fo2p); /* write FCD for DEBUG */ ================================================================
#3. gg = memcmp(recw,"//*",3); /* gg=0 if line has '//*' */ ================================================================
There were almost 500 lines of code similar to the above examples. As you can imagine it would be a monumental task to fix the problem via manual editing.
So I wrote the 'codefix1' job to copy all programs, scanning for the 2nd '/*' & changing it to '|*'.
#1. /* prepend with 'cat > ...' & append with '|*' */ =================================================
#2. /* fwrite((char*)fcip,1,100,fo2p); |* write FCD for DEBUG */ ================================================================
#3. gg = memcmp(recw,"//*",3); /* gg=0 if current line is '//*' */ ================================================================
Note that the 2nd '/*' in example #3 is not changed because the 1st '/*' is a legitimate use of a constant "//*". My first coding of codefix1 missed this, but compile errors quickly alerted me to this problem, which was fixed as explained below (see codefix1 listing lines #67 & #68).
Goto: Begin this doc , End this doc , Index this doc , Contents this library , UVSI Home-Page
#1. Login as uvadm --> /home/uvadm ==============
#2a. mv src src.old <-- change name of existing source code subdir ==============
#2b. mkdir src <-- make new source code subdir =========
#3. uvcopy codefix1,fild1=src.old,fild2=src ======================================= - execute codefix1 to copy all programs from src.old to src - scanning for 2nd '/*' & changing to '|*' - see the console log stats report below
#4. alldiff2 src.old src <-- create a 'difference report' ==================== - a great tool to verify mass changes to test files - see a few lines of the report on the next page
#5a. ccuvall LNX L32 P32 disamLNX ============================ - recompile all programs on my Linux machine - see 'ccuvall' script at install.htm#L3
#5b. ccuvall HP L32 P32 disamHPIA ============================ - recompile all programs on the HP Itanium
codefix1 - copy all files fixing embedded /* comments 78 fixed in 11159 total lines of file: src.old/jclunix51.c 080413:091642:codefix1: EOF fili01 rds=11159 size=475936: src.old/jclunix51.c 080413:091642:codefix1: EOF filo02 wrts=11159 size=475146: src/jclunix51.c 8 fixed in 17286 total lines of file: src.old/uvcopy.c 080413:091643:codefix1: EOF fili01 rds=17286 size=759457: src.old/uvcopy.c 080413:091643:codefix1: EOF filo02 wrts=17286 size=758537: src/uvcopy.c 3 fixed in 7979 total lines of file: src.old/uvhd.c 080413:091644:codefix1: EOF fili01 rds=7979 size=339701: src.old/uvhd.c 080413:091644:codefix1: EOF filo02 wrts=7979 size=331318: src/uvhd.c - - - stats shown for only 4 of 55 programs total - - - 080413:091650:codefix1: EOF fild02 size=4096: src 441 fixed in 161598 total lines of directory: src.old
Goto: Begin this doc , End this doc , Index this doc , Contents this library , UVSI Home-Page
1634c1634 < /* today[12] = '\0'; /* drop seconds <-- disabled Feb18/07 */ --- > /* today[12] = '\0'; |* drop seconds <-- disabled Feb18/07 */ 6394c6394 < /* fd1 = fileno(fp1); /* get filedes from fileptr <-- NOneed May2001 */ --- > /* fd1 = fileno(fp1); |* get filedes from fileptr <-- NOneed May2001 */ diff file# 43 - src.old/... vs src/uvhd.c
408c408 < /* "t!&l00004H", /* 05 PaperTRAY: &l4H=alt source (t2=tray#2) */ --- > /* "t!&l00004H", |* 05 PaperTRAY: &l4H=alt source (t2=tray#2) */ diff file# 45 - src.old/... vs src/uvlist.c
2335,2337c2335,2337 < /* fwrite((char*)fcip,1,100,fo2p); /* write FCD */ < /* fwrite((char*)fi1kdr,1,100,fo2p); /* write KDI retrieval */ < /* fwrite((char*)kdip,1,374,fo2p); /* write KDB */ --- > /* fwrite((char*)fcip,1,100,fo2p); |* write FCD */ > /* fwrite((char*)fi1kdr,1,100,fo2p); |* write KDI retrieval */ > /* fwrite((char*)kdip,1,374,fo2p); |* write KDB */ 2859,2860c2859,2860 < /* fwrite((char*)fcop,1,100,fo2p); /* write FCD */ < /* fwrite((char*)kdop,1,374,fo2p); /* write KDB */ --- > /* fwrite((char*)fcop,1,100,fo2p); |* write FCD */ > /* fwrite((char*)kdop,1,374,fo2p); |* write KDB */ diff file# 55 - src.old/... vs src/uxsort.c
20 different of 55 files compared src.old to src
Of course the best verification is 're-compiling' the programs & see if error free.
The 'alldiff2' script is most vital when masschanging text files such as documentation where you have no 're-compile' to verify.
Goto: Begin this doc , End this doc , Index this doc , Contents this library , UVSI Home-Page
#01 # codefix1 - uvcopy Parameter File from UVSI stored in: /home/uvadm/pf/adm/ #02 # codefix1 - remove/disable '/*' embedded in '/* code /* comments */' #03 # - by Owen Townsend, UV Software, April 2008 #04 # #05 # I used SCO unix & Red Hat Linux to write & compile the Vancouver Utilities #06 # - 160,000 lines of code in 55 programs (over may years) #07 # In April 2008, I had a problem when I compiled on HP Itanium #08 # - HP 'C' compiler would not accept a 2nd '/*' embedded in comments, example: #09 # #10 # /* ...code... /* ...comment... */ <-- common practise to cmt out code #11 # /* ...code... |* ...comment... */ <-- this job changes 2nd '/*' to '|*' #12 # #13 # There were _____ occurrences in 160,000 lines of code #14 # - a monumental job to fix by manual editing #15 # - I wrote this job in less than 1 hour & ran in 10 seconds #16 # #17 # 1. mv src src.old <-- rename source library #18 # ============== #19 # #20 # 2. uvcopy codefix1,fild1=src.old,fild2=src #21 # ======================================= #22 # - copy all files from src.old to src/... #23 # - fixing embedded /* comments as illustrated above #24 # #25 opr='$jobname - copy all files fixing embedded /* comments ' #26 fild1=?indir,typ=DIR,rcs=80 #input directory #27 fili1=xxxxxxxx,typ=LST,rcs=256 #current input file from directory #28 fild2=?outdir,typ=DIR,rcs=80 #output directory #29 filo2=xxxxxxxx,typ=LSTt,rcs=256 #current output file #30 @run #31 opn fild1 open input directory #32 msgwy 'did you create outdir (dflt tmp) ? (or remove files?)' #33 opn fild2 open output directory (must exist) #34 #
Goto: Begin this doc , End this doc , Index this doc , Contents this library , UVSI Home-Page
#36 # begin outer loop to read directory for next filename #37 man10 get fild1,a0(80) get next record (filename) in directory #38 skp> man90 (cc set > at EOD) #39 skp< man10 (cc set < on subdir vs file) #40 # #41 # create input filename by concat: indir/infile & open #42 clr f0(300),' ' #43 mvu f100(80),$fild1,x'00' move dirname until ending null #44 cat f100(80),'/' concat the '/' #45 cata8 f100(80),a0(80) concat current filename (a8 null terms) #46 mvc $fili1,f100 store input filename before open #47 opn fili1 open current input file #48 # #49 # create same filename in output subdir & open #50 mvu f200(80),$fild2,x'00' move output dirname until null reached #51 cat f200(80),'/' concat the '/' #52 cata8 f200(80),a0(80) concat current filename (a8 null terms) #53 mvc $filo2,f200 store output filename before open #54 opn filo2 open current output file #55 # #56 # clear counters for current files #57 mvn $ca1,0 clear count, lines in current file #58 mvn $ca3,0 clear count, fixes in current file #59 # #60 # begin inner loop: get/put records from/to current file until EOF #61 man20 get fili1,b0(256) get each record into area 'b' #62 skp> man40 #63 add $ca1,1 count lines for current infile #64 add $ca2,1 count total lines in directory #65 # #66 # scan for embedded cmts & disable any 2nd '/*' by changing to '|*' #67 scne1z1q2 bb0(80),'/*' scan to 1st '/*' not in "quotes" #68 skp! man30 #69 add $rb,1 rgstr 'b' +1 for scan to 2nd #70 scne1 bb0(100),'/*' continue scan for 2nd '/*' #71 skp! man30 #72 mvc bb0(1),'|' yes - change '/*' to '|*' #73 add $ca3,1 count lines modified in current file #74 add $ca4,1 count total lines modified in dir #75 # #76 # common point whether current line modified or not #77 man30 put filo2,b0(256) write current line #78 skp man20 return to get next line #79 # #80 # EOF current file - output counts, close files,& return for next file pair #81 man40 msgv1 '$ca3 fixed in $ca1 total lines of file: $fili1' #82 cls fili1 close current input file #83 cls filo2 close current output file #84 skp man10 #85 # #86 # end input directory - display stats, close all dirs & files, & eoj #87 man90 cls all #88 msgv1 '$ca4 fixed in $ca2 total lines of directory: $fild1' #89 eoj
Goto: Begin this doc , End this doc , Index this doc , Contents this library , UVSI Home-Page
I will explain here only the instructions I think you might not fully appreciate without some additional comments. You can see all uvcopy instructions documented in uvcopy3.htm which has an alphabetical index. Note that all uvcopy instrns are 3 characters (anything following is an option).
Please relate the sequence# here to the full listing above.
#26 fild1=?indir,typ=DIR,rcs=80 #input directory #27 fili1=xxxxxxxx,typ=LST,rcs=256 #current input file from directory #28 fild2=?outdir,typ=DIR,rcs=80 #output directory #29 filo2=xxxxxxxx,typ=LSTt,rcs=256 #current output file
#41 # create input filename by concat: indir/infile & open #42 clr f0(300),' ' #43 mvu f100(80),$fild1,x'00' move dirname until ending null #44 cat f100(80),'/' concat the '/' #45 cata8 f100(80),a0(80) concat current filename, a8 null terms #46 mvc $fili1,f100 store input filename before open #47 opn fili1 open current input file
#66 # scan for embedded cmts & disable any 2nd '/*' by changing to '|*' #67 scne1z1q2 bb0(80),'/*' scan to 1st '/*' not in "quotes" #68 skp! man30 #69 add $rb,1 rgstr 'b' +1 for scan to 2nd #70 scne1 bb0(100),'/*' continue scan for 2nd '/*' #71 skp! man30 #72 mvc bb0(1),'|' yes - change '/*' to '|*'
The op1 register is the 2nd 'b' of 'bb0(80)' (1st 'b' is area 'b') (the register could be any letter, but I like to make it same as area)
Goto: Begin this doc , End this doc , Index this doc , Contents this library , UVSI Home-Page
#70 scne1 bb0(100),'/*' continue scan for 2nd '/*'
Do you understand the index registers ?
#69 nop <-- replace 'add $rb,1' with 'nop' #70 scne1 bb1(100),'/*' continue scan for 2nd '/*' #71 skp! man30 #72 mvc bb1(1),'|' yes - change '/*' to '|*'
Do you see that we could have saved 1 instruction (line #69 add $rb,1) if we change op1 on lines #70 & #72 from 'bb0(1)' to 'bb1(1)' ?
#80 # EOF current file - output counts, close files,& return for next file pair #81 man40 msgv1 '$ca3 fixed in $ca1 total lines of file: $fili1' #82 cls fili1 close current input file #83 cls filo2 close current output file #84 skp man10 return to get next filename from dir
I hope I have explained this clearly. Please see all instructions documented in uvcopy3.htm which has an alphabetical index.
Goto: Begin this doc , End this doc , Index this doc , Contents this library , UVSI Home-Page
For scripts:
For C programs:
: # compile and/or link converted rpg programs
##### if [ "$RPGCDIR" = "" -o ! -f $xid/rpgtocfp.h -o ! -f $xid/rpgtoctd.h -o ! -f $xid/rpgtocex.h -o ! -f $xld/librc.a ]; then echo "ERROR - The environment variable RPGCDIR is not set" exit fi
#!/bin/ksh # tools/rpgcomp1 # compile and/or link converted rpg programs
##### if [ "$RPGCDIR" = "" -o ! -f $xid/rpgtocfp.h -o ! -f $xid/rpgtoctd.h -o ! -f\ $xid/rpgtocex.h -o ! -f $xld/librc.a ]; then echo "ERROR - The environment variable RPGCDIR is not set" exit fi
Goto: Begin this doc , End this doc , Index this doc , Contents this library , UVSI Home-Page
/* keyenter.c Enter key to Version Control File */
/* Get input */ static void get_input(char *argv1) { int x; char keywork[200];
for(;;) { for (x=0;keywork[x];x++) /* make it lower case */ { keywork[x] = (char)tolower((int)keywork[x]); if (!strchr("0123456789abcdef",(int)keywork[x])) { printf("\nError - Incorrect character in position %d",x+1); } } }
/*--------------------------------------*/ /* Write version control file */ static void write_vc(char *vcon) { ...etc...remaining code omitted...
/* tools/keyenter.c */ /* keyenter.c Enter key to Version Control File */
/* Get input */ static void get_input(char *argv1) { int x; char keywork[200];
for(;;) { for (x=0;keywork[x];x++) /* make it lower case */ { keywork[x] = (char)tolower((int)keywork[x]); if (!strchr("0123456789abcdef",(int)keywork[x])) { printf("\nError - Incorrect character in position %d",x+1); } } }
/*EJect*/ <-- changed to '*EJect' to prevent uvlist new page on '*eject' /*--------------------------------------*/ /* Write version control file */ static void write_vc(char *vcon) { ...etc...remaining code omitted...
Goto: Begin this doc , End this doc , Index this doc , Contents this library , UVSI Home-Page
# codefix2 - clean up C programs & scripts # - by Owen Townsend, UV Software, May 2008 # #May2008 - 1st used on Morada RPG libraries (libr,sort,tools,util) # # uvcopy codefix2,fili1=tools/mkurpg,filo1=tmp/mkurpg # =================================================== # - convert 1 file at a time (for test/debug) # - then convert All files in directories as follows: # # 1. mv libr libr.old; mv sort sort.old; mv tools tools.old; mv util util.old; # ========================================================================= # 2. mkdir libr sort tools util # ========================== # # 3a. uvcopyx codefix2 libr.old libr uop=q0i7 # ======================================= # 3a. uvcopyx codefix2 sort.old sort uop=q0i7 # ======================================= # 3a. uvcopyx codefix2 tools.old tools uop=q0i7 # ========================================= # 3a. uvcopyx codefix2 util.old util uop=q0i7 # ======================================= # # ** changes ** # # 1. Convert each tab to 3 blanks # # 2. Reduce multiple blank lines to 1 # # ** Only for C programs ** # # 3. Insert filename on 1st line /* subdir/filename */ # # 4. Left adjust lines with only leading blanks to /*---------*/ # # 5. Insert /*Eject*/ prior to /*---------*/ lines (with no code) # - if we have not inserted /*Eject*/ in last 25 lines # # ** Only for scripts ** # # 6. Insert filename on 2nd line: # subdir/filename # (since 1st line will be: #!/bin/ksh) # # 7. if 1st line ':' or '#!' change to: '#!/bin/ksh' # else insert '#!/bin/ksh' as 1st line # # 8. Insert '\' to split long lines # - insert prior to word exceeding col 80 # - line up part2 under 1st non-blank of part1 # but indent 3 columns to the right #
Goto: Begin this doc , End this doc , Index this doc , Contents this library , UVSI Home-Page
opr='$jobname - clean up C programs & scripts' fili1=?input,rcs=512,typ=LST filo1=?output,rcs=256,typ=LSTt @run opn fili1 open input file man01 mvu f0(80),$fili1,x'00' retrieve filename rep f0(80),'.old','' remove any '.old' suffix # # To help determine if file is script or C, we will read 1st 5 lines # - counting '# ' & '/*' in cols 1-2 man02 bal getr get next line skp> man06 cmc a0(2),'# ' probable script ? skp! 1 add $cb11,1 count '# ' in 1st 5 lines cmc a0(2),'/*' probable C code or hdr file ? skp! 1 add $cb12,2 count '/*' in 1st 5 lines cmn $ca1,5 reached 5 lines ? skp< man02 # # end 5 line test for #script vs C program # - close & re-open input file, so we can copy all lines below man06 cls fili1 opn fili1 opn filo1 mvn $ca1,0 reset total line ctr mvn $ca2,0 reset lines since last *Eject bal getr get 1st line for #! or : test skp> man90 (cc set > if EOF) # # set C $cb1=2 if: filename suffix .c or .h or '/*' in 1st 5 lines man10 scn f0(80),'.c ' C program ? skp= man30 scn f0(80),'.h ' C program ? skp= man30 cmn $cb12,1 found /* 1st 5 lines ? skp=> man30 # # set script $cb1=1 if: C not detected above and: # - 1st line '#!' or ':', or found '# ' in 1st 5 lines man14 cmc a0(2),'#!' shell spcfd on 1st line ? skp= man20 cmc a0(1),':' ':' col 1 of 1st line ? skp= man20 cmn $cb11,1 found '# ' 1st 5 lines ? skp=> man21 # # neither C nor script detected man18 skp man60 go write 1st line & return to loop #
Goto: Begin this doc , End this doc , Index this doc , Contents this library , UVSI Home-Page
# script detected by '#!' or ':' - ensure ksh spcfd man20 mvc a0(10),'#!/bin/ksh' yes - replace with Korn shell # # script detected by counting '# ' in 1st 5 lines (write 1st line unchanged) man21 put filo1,a0 write 1st line # # set script switch & insert line 2 as script name man22 mvn $cb1,1 set switch to ID scripts ins f0(80),'# ' insert '#' prior to filename put filo1,f0(80) write inserted line # file-name skp man40 goto record processing loop # # C program - set switch to ID C & insert program name on 1st line man30 mvn $cb1,2 set switch to ID C program/header ins f0(80),'/* ' insert comment ID begin cat f0(80),' */' append comment ID end put filo1,f0(80) write 1st line /* file-name */ skp man60 go write 1st line & return to loop #
Goto: Begin this doc , End this doc , Index this doc , Contents this library , UVSI Home-Page
# begin mainline loop to get,process,write lines until EOF man40 bal getr get next line skp> man90 # # reduce multiple blank lines to 1 # - getr subrtn counts blank lines in $cb3 & resets on non-blank man42 cmn $cb3,2 2nd+ blank line ? skp=> man40 ifso - bypass, return to get next # # insert /*Eject*/ on /*--------*/ (in not done in last 25 lines) # - getr subrtn sets switch $cb2 if /*-----*/ present man44 cmn $cb2,1 comment /*......*/ present ? skp< man50 getr45 cnt a0(80),'-' count '-'s cmn $ci1,15 15+ '_'s ? skp< man50 getr46 cmn $ca2,20 20 lines since last Eject ? skp< man50 put filo1,'/*eject*/' insert Eject mvn $ca2,0 reset 25 line ctr # # insert '\' to split long lines in scripts (not if C code) man50 cmn $cb1,1 script ? (vs C) skp! man60 man51 cmc a80(10),' ' col 80 exceeded ? skp= man60 man52 scnre1z1 aa0(80),' ' scan from right to begin word ### mvn $ra,$rx save ptr to blank at begin word cmn $ra,40 col 40+ ? skp< man60 scn aa0(80),'"' within quotes ? skp= man60 mvc aa0(1),'\' insert '\' continuation char mvc b0(256),aa1 save 2nd part in area 'b' clr aa1(256),' ' clear part2 from original put filo1,a0 write part 1 # # indent (by 3 columns) part2 under 1st non-blank of part1 man56 clr c0(256),' ' clear another work area scne1z1 bb0(80),>' ' scan to 1st non-blank in part1 ### mvn $rb,$rx save ptr to 1st non-blank mvc cb3(256),b0 indent part2 under part1 1st NB +3 put filo1,c0 write part2 skp man40 return to get next line # # common point to write current line # - unless it was split as above man60 put filo1,a0 write out current line skp man40 return to get next line # # EOF - close files & end job man90 cls all eoj #
Goto: Begin this doc , End this doc , Index this doc , Contents this library , UVSI Home-Page
# getr - subrtn to get next line of code # - convert tabs to 3 blanks # - left adjust lines with leading blanks to /*---------*/ # - count blank lines & clear on non-blank # - count all lines (in $ca1) # - count lines since last /*Eject*/ insert (in $ca2) # getr get fili1,a0 get next line skp> getr9 (cc set > at EOF) add $ca1,1 count total lines add $ca2,1 count lines since last Eject insert # rep a0(256),x'09',' ' replace each tab with 3 blanks # # test for all comment lines /*..........*/ (no C code) # - set switch to test in mainline for /*-------*/ & insert /*eject*/ # - if any leading blanks, remove them, left adjust squeeze out blanks getr2 mvn $cb2,0 presume not all cmt scn a0(80),>' ' scan to 1st non-blank mvn $ra,$rx save ptr to 1st NB cmc aa0(2),'/*' '/*' after leading blanks ? skp! getr6 scnr a0(80),>' ' scan from right to last non-blank mvn $rb,$rx save ptr to last NB sub $rb,1 -1 to pint to last 2 chars cmc ab0(2),'*/' '*/' ending data on line ? skp! getr6 getr4 mvn $cb2,1 set switch for /*.....*/ cmc a0(1),' ' leading blanks ? skp! getr6 sqzc1 a0(256),' ' squeeze left (drop leading blanks) # # count blank lines & clear ctr on non-blank line getr6 cmc a0(80),' ' blank line ? skp= getr7 mvn $cb3,0 clear blank line ctr skp getr8 getr7 add $cb3,1 count blank lines # # common exit with: cc = if not EOF, cc > if EOF getr8 ret= getr9 ret> #------------------------- end codefix2 --------------------------
Goto: Begin this doc , End this doc , Index this doc , Contents this library , UVSI Home-Page
Sometimes you get email that has been forwarded several times is very ugly (many '>>>' prior message indicators, long lines, bad spacing, etc).
'emailfix1' will cleanup the mess for important things (like good jokes) before you pass it on to your friends.
> >>> > >> Biscuit Recipe > >>> > >> > >>> > >> > >>> > >> THIS IS A TRUE STORY > >>> > >> > >>> > >> My daughter and I had just finished lunch at a Neiman-Marcus Cafe > >>> > >> in > >>> > >> Dallas. > >>> > >> Because both of us are such biscuit lovers, we decided to try the > >>> > >> 'Neiman-Marcus cookie'. It was so excellent that I asked if they > >>>would > >>> > >> give me the recipe. The waitress said with a small frown, 'I'm > >>>afraid > >>> > >> not, but you can BUY the recipe.' I asked how much, and she > >>>responded; > >>> > >> 'Only two fifty - it's a great deal!' I agreed to that, and told > >>> > >> her > >>> > >> to add it to my bill. > >>> > >> > >>> > >> Thirty days later, I got my VISA statement, and the Neiman-Marcus > >>> > >> charge was $285.00. I looked at it again, and I remembered I had > >>>only > >>> > >> spent $9.95 for two sandwiches and about $20.00 for a scarf. At the > >>> > >> bottom of the statement, it said, 'Cookie Recipe-$250.00'. That was > >>> > >> outrageous! > >>> > >> > >>> > >> I called Neiman's Accounting Department and told them the waitress > >>>had > >>> > >> said it was 'two fifty', which clearly does not mean 'two hundred > >>>and > >>> > >> fifty dollars' by any reasonable interpretation of the phrase. > >>> > >> Neiman-Marcus refused to budge. They would not refund my money > >>> > >> because, according to them; 'What the waitress told you is not our > >>> > >> problem. You have already seen the recipe. We absolutely will not > >>> > >> refund your money.' > >>> > >>
------- you can guess the rest -------
Goto: Begin this doc , End this doc , Index this doc , Contents this library , UVSI Home-Page
Biscuit Recipe
THIS IS A TRUE STORY
My daughter and I had just finished lunch at a Neiman-Marcus Cafe in Dallas. Because both of us are such biscuit lovers, we decided to try the 'Neiman-Marcus cookie'. It was so excellent that I asked if they would give me the recipe. The waitress said with a small frown, 'I'm afraid not, but you can BUY the recipe.' I asked how much, and she responded; 'Only two fifty - it's a great deal!' I agreed to that, and told her to add it to my bill.
Thirty days later, I got my VISA statement, and the Neiman-Marcus charge was $285.00. I looked at it again, and I remembered I had only spent $9.95 for two sandwiches and about $20.00 for a scarf. At the bottom of the statement, it said, 'Cookie Recipe-$250.00'. That was outrageous!
I called Neiman's Accounting Department and told them the waitress had said it was 'two fifty', which clearly does not mean 'two hundred and fifty dollars' by any reasonable interpretation of the phrase. Neiman-Marcus refused to budge. They would not refund my money because, according to them; 'What the waitress told you is not our problem. You have already seen the recipe. We absolutely will not refund your money.'
------- you can guess the rest -------
#2. uvcopy emailfix1,fili1=tmp/NeimanMarcus.txt,filo1=tmp/NeimanMarcus.fixed ========================================================================
Goto: Begin this doc , End this doc , Index this doc , Contents this library , UVSI Home-Page
# emailfix1 - cleanup email # # - remove the '>' retransmitted indicators # - left justify lines & leave just 1 blank between words # - reformat lines to about 60 characters # (split lines at 1st word break right of 60 chars) # - reduce multiple blank lines to 1 # rop=r1 # option to prompt oprtr for disposition of output opr='uop=q1l60 - option defaults' opr=' l60 - line length default 60 bytes' uop=q1l60 # set option defaults was=b20000 # increase area b paragraph storage area fili1=?input,typ=LST,rcs=1024 filo1=?output,typ=LSTtd3,rcs=128 @run opn all mvn $rl,$uopbl store line lth in rgstr 'l' # # begin paragraph # - bypass any blank lines til next data found man20 bal getr get next line skp> eof cmc a0(10),' ' blank line ? skp= man20 # # non-blank line reached # - get & store paragraph (til next blank line reached) man30 clr b0(10000),' ' clear para storage area mvn $rb,0 init para storage ctl rgstr # # begin loop to get lines & store para, til next blank line reached man32 mvc bb0($ra1024),a0 store current line by rgstrs add $rb,$ra up para store ctl rgstr by line lth bal getr get next line skp> man40 cmc a0(10),' ' blank line reached ? skp! man32 #
Goto: Begin this doc , End this doc , Index this doc , Contents this library , UVSI Home-Page
# blank line reached (ending para store) # - output stored para in $rl (dflt 60) byte lines man40 mvn $rb,0 init rgstr b back to begin para # begin loop to output lines of 60+ bytes til end para blanks reached man42 mvn $rc,$rb ptr to current line in para storage add $rc,$rl up by desired line lth scn bc0(20),' ' scan to end of word add $rc,$rx adjust line lth to end word mvn $rd,$rc pointer to end of current line sub $rd,$rb calc current line length clr c0(128),' ' clear output area mvc c0($rd128),bb0 move current line to out area sqzc1 c0(128),' ' ensure left justified put filo1,c0 write current line add $rb,$rd up para ctl rgstr by line length cmc c0(20),' ' reached blank line ending para ? skp! man42 no - repeat loop skp man20 yes - return to begin next para # # EOF - close files & end job eof cls all eoj # #----------------------------------------------------------- # getr - subrtn to get next line # - convert any '>'s to blanks # - left justify # - store data length in $ra getr get fili1,a0(1024) skp> getr9 rep a0(30),'>',' ' remove '>' indicators sqzc1 a0(1024),' ' left justify mvn $ra,$rx store data lth in $ra add $ra,1 +1 to leave blank btwn lines ret= getr9 ret>
Goto: Begin this doc , End this doc , Index this doc , Contents this library , UVSI Home-Page
2A1. | adrsfix1 - eliminate duplicate Names & Addresses by standardizing |
street addresses (street to st., road to rd., etc) | |
- drop duplicates with uvsort unique key option |
2B1. | adrsfix2 - alternate version using search/replace tables |
vs embedded code as in adrsfix1 |
2C1. | adrsfix3 - alternate version to combine amount fields into 1 remaining |
record for duplicate key record group |
2D1. | splitprint1 - split large print file into multiple files |
of specified number of pages each |
Goto: Begin this doc , End this doc , Index this doc , Contents this library , UVSI Home-Page
Thanks to Jack Stamy of Berks EIT, for suggesting this in April 2004. We think that other sites might benefit from these techniques.
duplicate Name & Address records is a common problem at many customer sites. New customer Name & Address records are often set up when personnel do not know that existing records are already onfile for the customer.
The application software may be checking for duplicates, but this check may fail due to minor differences in the new address. These failures are usually due to spelling differences in abbreviations (ST. vs STREET, RD. vs ROAD, N. vs North, etc).
Note that checks for duplicates must check both Name & Address fields since it is not unusual to have duplicate Company Names at the same Address.
We have provided sample test data, uvcopy jobs,& uvsort commands to illustrate our solutions & to help you to develop solutions for your own data files. First we will give you an overview of the steps involved.
To make it easier for you, we have supplied our test data file as a simple sequential file without packed fields & with LineFeeds in the last byte (so you can inspect with vi). Usually the customer master file would be a multi-key Indexed file & it would often contain packed fields (which makes it impossible to use vi).
001-006 - customer# - 1st key in Indexed file 011-035 - customer name - 2nd key in Indexed file 036-060 - address <-- address field to be modified 061-076 - city 078-079 - province 081-090 - postal code 091-102 - telephone# - 3rd key in Indexed file 103-120 - contact name
Note |
|
Goto: Begin this doc , End this doc , Index this doc , Contents this library , UVSI Home-Page
130140 EVERGREEN MOTORS LTD. 1815 BOWEN ROAD NANAIMO BC V9S1H1 132588 GEECOE GENERATOR SERVICE 2851 SIMPSON ST RICHMOND BC V6X2R2 139923 JOHNSTONE BOILER & TANKS 1250 EAST PENDER STREET VANCOUVER BC V5L1W1 140055 JOHNSTONE BOILER & TANKS 1250 EAST PENDER ST. VANCOUVER BC V5L1W1 142175 LILLY ELECTRIC LTD 16809 - 24TH AVENUE EAST SURREY BC V4B5E7 147615 O'CONNER R.V. CENTRE 44430 YALE ROAD WEST CHILLIWACK BC V2P6J1 148800 LILLY ELECTRIC LTD 16809 - 24TH AVE E SURREY BC V4B5E7 149304 POINT GREY GOLF&COUNTRY 3350 S.W. MARINE DRIVE VANCOUVER BC V6N3Y9 151500 LILLY ELECTRIC LTD 16809 - 24TH AVE. E. SURREY BC V4B5E7 152040 EVERGREEN MOTORS LTD. 1815 BOWEN RD NANAIMO BC V9S1H1
130140 EVERGREEN MOTORS LTD. 1815 BOWEN RD. NANAIMO BC V9S1H1 132588 GEECOE GENERATOR SERVICE 2851 SIMPSON ST. RICHMOND BC V6X2R2 139923 JOHNSTONE BOILER & TANKS 1250 E. PENDER ST. VANCOUVER BC V5L1W1 140055 JOHNSTONE BOILER & TANKS 1250 E. PENDER ST. VANCOUVER BC V5L1W1 142175 LILLY ELECTRIC LTD 16809 - 24TH AVE. E. SURREY BC V4B5E7 147615 O'CONNER R.V. CENTRE 44430 YALE RD. W. CHILLIWACK BC V2P6J1 148800 LILLY ELECTRIC LTD 16809 - 24TH AVE. E. SURREY BC V4B5E7 149304 POINT GREY GOLF&COUNTRY 3350 S.W. MARINE DR. VANCOUVER BC V6N3Y9 151500 LILLY ELECTRIC LTD 16809 - 24TH AVE. E. SURREY BC V4B5E7 152040 EVERGREEN MOTORS LTD. 1815 BOWEN RD. NANAIMO BC V9S1H1
152040 EVERGREEN MOTORS LTD. 1815 BOWEN RD. NANAIMO BC V9S1H1 132588 GEECOE GENERATOR SERVICE 2851 SIMPSON ST. RICHMOND BC V6X2R2 139923 JOHNSTONE BOILER & TANKS 1250 E. PENDER ST. VANCOUVER BC V5L1W1 151500 LILLY ELECTRIC LTD 16809 - 24TH AVE. E. SURREY BC V4B5E7 147615 O'CONNER R.V. CENTRE 44430 YALE RD. W. CHILLIWACK BC V2P6J1 149304 POINT GREY GOLF&COUNTRY 3350 S.W. MARINE DR. VANCOUVER BC V6N3Y9
132588 GEECOE GENERATOR SERVICE 2851 SIMPSON ST. RICHMOND BC V6X2R2 139923 JOHNSTONE BOILER & TANKS 1250 E. PENDER ST. VANCOUVER BC V5L1W1 147615 O'CONNER R.V. CENTRE 44430 YALE RD. W. CHILLIWACK BC V2P6J1 149304 POINT GREY GOLF&COUNTRY 3350 S.W. MARINE DR. VANCOUVER BC V6N3Y9 151500 LILLY ELECTRIC LTD 16809 - 24TH AVE. E. SURREY BC V4B5E7 152040 EVERGREEN MOTORS LTD. 1815 BOWEN RD. NANAIMO BC V9S1H1
Note that sample#3 is in Name & Address sequence, after duplicates dropped by the unique sortkey option, which is effective during the output phase of the sort. Sample#4 has been sorted back to customer# sequence to reload the customer master file (usually a multi-key Indexed file).
Goto: Begin this doc , End this doc , Index this doc , Contents this library , UVSI Home-Page
1. uvcopy adrsfix1,fili1=dat1/custmas4,filo1=tmp/custmas4a =======================================================
2. uvsort "fili1=tmp/custmas4a,typ=RSF,rcs=120,filo1=tmp/custmas4b\ ================================================================ ,key1=10(25),key2u1=35(25)" ===========================
3. uvsort "fili1=tmp/custmas4b,typ=RSF,rcs=120,filo1=tmp/custmas4c,typ=ISF ======================================================================= ,key1=0(6),isk1=0(6),isk2=10(25d),isk3=90(12d)"
Goto: Begin this doc , End this doc , Index this doc , Contents this library , UVSI Home-Page
# adrsfix1 - standardize Names & Addresses for duplicate elimination # - using search/replace table to change STREET to ST., ROAD to RD.,etc # - followed by uvsort to drop duplicate records # - demo based on supplied test file /home/uvadm/dat1/custmas4 # # uvcopy adrsfix1,fili1=dat1/custmas4,filo1=tmp/custmas4a # ======================================================= # was=c8000 - increase area c to 8000 bytes (allows 200 * 40 byte table entries) fili1=?dat1/custmas4,typ=RSF,rcs=120 #<-- would be typ=ISF in real life filo1=?tmp/custmas4a,typ=RSF,rcs=120 # # load table of search/replace addresses # - applied to address field b35(25) by 'rpt' instrn below # - 40 byte table entries, 01-20=search pattern, 21-40=replacement # - patterns preceded & followed with 1 blank to avoid matches within words # - table ended with a line of all tildes lod=c0(40) STREET ~~~~~~~~~~~~ ST. ~~~~~~~~~~~~~~~ ROAD ~~~~~~~~~~~~~~ RD. ~~~~~~~~~~~~~~~ AVENUE ~~~~~~~~~~~~ AVE. ~~~~~~~~~~~~~~ DRIVE ~~~~~~~~~~~~~ DR. ~~~~~~~~~~~~~~~ NORTH ~~~~~~~~~~~~~ N. ~~~~~~~~~~~~~~~~ SOUTH ~~~~~~~~~~~~~ S. ~~~~~~~~~~~~~~~~ EAST ~~~~~~~~~~~~~~ E. ~~~~~~~~~~~~~~~~ WEST ~~~~~~~~~~~~~~ W. ~~~~~~~~~~~~~~~~ ST ~~~~~~~~~~~~~~~~ ST. ~~~~~~~~~~~~~~~ RD ~~~~~~~~~~~~~~~~ RD. ~~~~~~~~~~~~~~~ AVE ~~~~~~~~~~~~~~~ AVE. ~~~~~~~~~~~~~~ DR ~~~~~~~~~~~~~~~~ DR. ~~~~~~~~~~~~~~~ N ~~~~~~~~~~~~~~~~~ N. ~~~~~~~~~~~~~~~~ S ~~~~~~~~~~~~~~~~~ S. ~~~~~~~~~~~~~~~~ E ~~~~~~~~~~~~~~~~~ E. ~~~~~~~~~~~~~~~~ W ~~~~~~~~~~~~~~~~~ W. ~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # - we need to repeat our patterns to ensure we get the '.' on abbreviations # in case the abbreviation already present but without '.' @run opn all # # begin loop to get/process/write records until EOF man20 get fili1,a0 get next record skp> eof (cc set > at EOF) mvc b0(120),a0 move to outarea 'b' from inarea 'a' rpta2 b35(25),c0(40),c0(20) search/replace address by table above put filo1,b0 write record to output skp man20 return to get next record # # EOF - close files & end job eof cls all eoj
Goto: Begin this doc , End this doc , Index this doc , Contents this library , UVSI Home-Page
Goto: Begin this doc , End this doc , Index this doc , Contents this library , UVSI Home-Page
Here is an alternate version that allows you to maintain the search/replace table as a separate file for easier maintenance (adding new entries). You can run the (previously illustrated) demo as shown below in adrsfix2.
# adrsfix.tbl - search/replace table to standardize N&A abbreviations # - separate file read by uvcopy job adrsfix1 on startup # - for easier maintenance & addition of new entries # - this demo file supplied in /home/uvadm/tf/adrsfix.tbl STREET ~~~~~~~~~~~~ ST. ~~~~~~~~~~~~~~~ ROAD ~~~~~~~~~~~~~~ RD. ~~~~~~~~~~~~~~~ AVENUE ~~~~~~~~~~~~ AVE. ~~~~~~~~~~~~~~ - - - - lines omitted - - - - S ~~~~~~~~~~~~~~~~~ S. ~~~~~~~~~~~~~~~~ E ~~~~~~~~~~~~~~~~~ E. ~~~~~~~~~~~~~~~~ W ~~~~~~~~~~~~~~~~~ W. ~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# adrsfix2 - standardize Names & Addresses for duplicate elimination # - alternate version of /home/uvadm/pf/demo/adrsfix1 # - loads the search/replace table from a file vs embedded as in adrsfix1 # - adrsfix1 & adrsfix2 are extensively documented in uvcopy7.htm # # uvcopy adrsfix2,fili1=dat1/custmas4,filo1=tmp/custmas4a,fili2=tf/adrsfix.tbl # ============================================================================ # uvcopy adrsfix2 <-- same as above (files default as above) # opr='$jobname - standardize Names & Addresses for duplicate elimination' fili1=?dat1/custmas4,typ=RSF,rcs=120 #<-- would be typ=ISF in real life filo1=?tmp/custmas4a,typ=RSF,rcs=120 #<-- output file default in tmp subdir fili2=?tf/adrsfix.tbl,typ=LST,rcs=80 #<-- search/replace table text file LST @run opn all rtb fili2,c0(40),c0(40) <-- read table into area c (40 byte entries) # # begin loop to get/process/write records until EOF man20 get fili1,a0 get next record skp> eof (cc set > at EOF) mvc b0(120),a0 move to outarea 'b' from inarea 'a' rpta2 b35(25),c0(40),c0(20) search/replace address by table above put filo1,b0 write record to output skp man20 return to get next record # # EOF - close files & end job eof cls all eoj
Goto: Begin this doc , End this doc , Index this doc , Contents this library , UVSI Home-Page
The previous pages illustrated techniques for eliminating duplicate Name & Address records, but those techniques did not allow for the possibility that the N&A records might also contain quantity or $amount fields that should be combined into the 1 remaining record.
Combining amount fields is made possible by the 'sum' feature of uvsort (which will be further explained on the next page).
Alternate test file 'dat1/custmas5' is provided to demonstrate the accumulation of amount fields into the 1 remaining record. The 1st 120 bytes of 'custmas5' is the same as the previously illustrated 'custmas4', but custmas5 also contains 24 * 6 byte packed fields in 121-240.
001-006 - customer# - 1st key in Indexed file 011-035 - customer name - 2nd key in Indexed file 036-060 - address <-- address field to be modified 061-076 - city 078-079 - province 081-090 - postal code 091-102 - telephone# - 3rd key in Indexed file 103-120 - contact name 121-180 - this year monthly sales (12 * 5 bytes packed) 181-240 - last year monthly sales (12 * 5 bytes packed) 241-256 - unused
We will show you the 1st record using the 'uvhd' utility (since the packed fields make it impossible to list the records as we did for custmas4).
uvhd dat1/custmas5 r256 <-- run uvhd to illustrate 1st record =======================
10 20 30 40 50 60 r# 1 0123456789012345678901234567890123456789012345678901234567890123 0 130140 EVERGREEN MOTORS LTD. 1815 BOWEN ROAD NANA 3333332222454545444244545524542222233332445442544422222222224444 130140000056527255E0DF4F230C44E0000181502F75E02F140000000000E1E1 64 IMO BC V9S1H1 ..4V|... 4442222222222442535343222222222222222222222222222222222201357000 9DF000000000023069318100000000000000000000000000000000000246C000 128 .........W0....`........)X}..f3.....\.................4V}...f... 0000000005300016000000002570063100095000000000000000013570016000 0C0000C0270D0540C0000C0098D0263C0444C0000C0000C0000C0246D0056C00 192 ...............................f.....<........f.C 19950531 0000008900000000880000000018000680001300000000694233333333222222 00C0026C0000C0023C0000C0083C0056D0012C0000C0016D3019950531000000
Packed fields can be identified by the ending sign bytes x'_C' or x'_D'.
Goto: Begin this doc , End this doc , Index this doc , Contents this library , UVSI Home-Page
We can demonstrate this technique using uvcopy job 'adrsfix3', which is similar to 'adrsfix2' (previously listed on page '2B1'), except that the input file record size is now 256 (vs 120).
1. uvcopy adrsfix3,fili1=dat1/custmas5,filo1=tmp/custmas5a =======================================================
2. uvsort "fili1=tmp/custmas5a,typ=RSF,rcs=256,filo1=tmp/custmas5b\ ================================================================ ,key1=10(25),key2u1=35(25),sum1x24=120(5p)" ===========================================
3. uvsort "fili1=tmp/custmas5b,typ=RSF,rcs=256,filo1=tmp/custmas5c,typ=ISF ======================================================================= ,key1=0(6),isk1=0(6),isk2=10(25d),isk3=90(12d)"
The most important difference (vs previous Op. Instrns on page '2A3' is the 'sum1x24=120(5p)' instruction on the uvsort that drops the duplicate records.
The 'x' option specifies 24 contiguous fields, all 5 bytes packed starting at byte 120 (zero relative). Without the 'x' option we would have had to specify:
sum1=120(5p),sum2=125(5p),sum3=130(5p),......,sum24=235(5p) ===========================================================
If you run this demo, you could use 'uvhd' to verify that the amount fields have been added together into the 1 remaining record for a duplicate set. It is easier to see this if you print out the input & output files using the immediate print instruction of uvhd.
uvhd dat1/custmas5 r256 <-- run uvhd on the input file ======================= ---> i10f2 <-- immediate print 10 recs, 2 per form(page) ---> q <-- quit
uvhd tmp/custmas5b r256 <-- run uvhd on the uvsort output file ======================= ---> i6f2 <-- immediate print 6 recs, 2 per form(page) ---> q <-- quit
Goto: Begin this doc , End this doc , Index this doc , Contents this library , UVSI Home-Page
Here is a job suggested by Gaetan Cadieux (City of Laval) in March 2009. We are listing the job here in case useful to other users. See the operating instructions example as #comments at begining of code below.
vi /home/uvadm/pf/util/splitprint1 ==================================
# splitprint1 - split print file into multi-files # of specified no of pages each (default 10,000) # - by Owen Townsend, UV Software, March 10, 2009 # # uvcopy splitprint1,fili1=rpts/filexx,fild2=tmp,uop=p10000 # ========================================================= # - split rpts/bigfile into multi-files (10000 pages each) # - writing output files to tmp/filexx_001, tmp/filexx_002, etc # # uvlp13L tmp/filexx_001 <-- print 1st file Landscape at 13 cpi & 8.5 lpi # ====================== (fits 132 columns & 66 lines on 8 1/2 x 11) # # uvlp13LD tmp/filexx_002 <-- print 2nd file Landscape & Duplex # ======================= # opr='$jobname - split print file into multi-files of specified no of pages' opr='- write outfiles to tmp/filexx_001, tmp/filexx_002, etc opr='uop=p10000 - option defaults' opr=' p10000 - desired pages in each output file' uop=q1p10000 # option defaults was=a9000 # allow 9000 bytes get area a (1 page 132 * 66 = 8712 max) fili1=?infile,rcs=9000,typ=LST fild2=?outdir,rcs=80,typ=DIR filo2=outdir/infile_###,rcs=9000,typ=LSTt
Goto: Begin this doc , End this doc , Index this doc , Contents this library , UVSI Home-Page
@run opn fili1 open input file opn fild2 open output subdir # # save input filename to construct output filenames # - output to subdir tmp/infilename + '_' separator + 3 digit seq# # tmp/infilename_001, tmp/infilename_002, etc mvu f1(80),$fili1,x'00' retrieve infilename scnr f0(80),'/' scan from Right side to any subdir mvc f200(80),fx1 save infile basename (w/o subdirs) cat f200(80),'_' concat separator (seq# will follow) # # begin outer loop for each split-file # - increment outfile# & clear page# man20 add $ca1,1 increment outfile# mvn $ca2,0 clear page# # # format outfilename = tmp/infilename_### clr f400(80),' ' clear output filename build area mvu f400(80),$fild2,x'00' setup output subdir cat f400(80),'/' append '/' separator cat f400(80),f200(80) append infilename scn f400(80),'_ ' scan to ending '_ ' mvn fx401(3),$ca1 insert outfile seq# (at dsplcmnt $rx+1) mvf $filo2,f400(80),x'00' store outfilename & null terminate opn filo2 open next output file # # begin inner loop to copy specified no of pages (option p) man30 getd0e0s8 fili1,a0(9000),' ',x'0C' skp> man80 puts8t8 filo2,a0($rv9000),' ',x'0C' add $ca2,1 count pages cmn $ca2,$uopbp reached page limit ? skp< man30 # # page count limit reached (or EOF) # - close output file, test EOF & return for next file if not EOF man80 cls filo2 cmc a0(4),'~EOF' EOF on infile ? skp! man20 man90 cls all eoj
Goto: Begin this doc , End this doc , Index this doc , Contents this library , UVSI Home-Page