270 likes | 427 Views
TPFDF Keylists in ISOC. Paul Stuyvesant. Agenda. The traditional approach - Assembler The traditional approach - ISOC Using parameters in ISOC Overview of Keylists Writing macros for C programs Some examples using Keylist macros. Traditional Approach.
E N D
TPFDF Keylists in ISOC Paul Stuyvesant
Agenda • The traditional approach - Assembler • The traditional approach - ISOC • Using parameters in ISOC • Overview of Keylists • Writing macros for C programs • Some examples using Keylist macros
Traditional Approach • Multiple calls in program with different parameters • DBOPN with HOLD/DETAC • DBOPN with NOHOLD • Keys set on individual commands • Keylists available but rarely used
Traditional Approach #IF EBSW01,EQ,X'04’ Updates to file? DBOPN REF=TR01PS,HOLD,DETAC, * ALG=MYORD#ELSE DBOPN REF=TR01PS,ALG=MYORD#EIF #IF CLI,OPTION,EQ,C’D’ DBRED REF=TR01PS,REG=R5,UP, * ERROR=DBERR, * KEY1=(PKY=#TR01K80), * KEY2=(R=TR01CAR,S=EBX000) #ELSE DBRED REF=TR01PS,REG=R5,UP, * ERROR=DBERR, * KEY1=(PKY=#TR01K80) #EIF
Traditional Approach • Simple rewrite in ‘Assembler-ish’ style • Does not use power of C/C++ parameter passing • Often caused by lack of design training • Assembler programmers used to ‘straight line’ coding techniques • Not advertising - no course available!
Traditional Approach dft_fil *tr01ptr = NULL; if(ecbptr()->ebsw01 == 0x04 ) Updates to file? tr01ptr = dfopn_acc(TR01NAM, TR01FID, DFOPN_ORD, DFOPN_HOLD | DFOPN_DETAC, MYORD); else tr01ptr = dfopn_acc(TR01NAM, TR01FID, DFOPN_ORD, 0, MYORD); if(option == ‘D’) df_setkey(keys, 1, offsetof(tr01k80, tr01key), member_size(tr01k80, tr01key), DF_EQ, 0, TR01K80, DF_UPORG, DF_CONST);
Using Parameters • Most function calls accept parameters • Parameters can be fixed values or variables • You all know this anyway!
Passing Parameters // Main program here { dft_opt opts = 0; // Set for default options dft_fil *fptr = NULL; if(ecbptr()->ebsw01 == 0x04 ) opts = DFOPN_HOLD | DFOPN_DETAC; fptr = Open_tr01(opts); } // User written function to open file using options passed dft_fil *Open_tr01( dft_opt tr01opt ) { dft_fil *tr01ptr = NULL; ptr = dfopn_acc(TR01NAM, TR01FID, DFOPN_ORD, tr01opt, MYORD); return tr01ptr; }
Keylist Overview • Build keylist in area of memory • Rarely seen - but can be useful • Uses SW01SR Dsect #SUBR KEY40_ROUTINE,R4 LA R1,EBX050 Basing key list - SW01SR XC EBX050(L'SW01NKY+5*L'SW01KIT),EBX050 clear it MVC EBX050(2),=H'1' Number of keys MVC SW01DIS,=H'2' Displacement in LREC MVC SW01LEN,=H'1' Length MVI SW01MSK,X'40' Mask to check MVI SW01CON,X'70' Indicate TM MVI SW01ID1,#BIT1+#BIT4 Up & CLI on Mask Value #ESUB
Macros Substitution • Create macros using #define directive • Compiler expands macro out at compile time. • Parenthesis required to ensure they are evaluated correctly • Can sometimes be obtuse
Macros Substitution #define MAX(A, B) ((A > B) ? A : B ) var = MAX(10, 20) // Becomes var = ((10 > 20) ? 10 : 20 ) // This example from cdferr.h #define DF_OK(file) ((file)->sw00rtn == 0) if(DF_OK(tr01ptr)) //becomes if(((tr01ptr)->sw00rtn == 0)) #define ecbptr() (*(struct eb0eb **)0x00000514ul)
Take Care // this line from header file - standard way to calculate size // of fixed length part of lrec. In this example imagine that // tr01k40 = 10 and tr01msg = 1. This means the fixed part of // the lrec is 9 #define TR01L40 sizeof(tr01k40) - member_size(tr01k40,tr01msg) // Read an lrec - it is 20 bytes long - 11 bytes variable field ptr = dfred( etc etc ); // calculate length of variable field a = ptr->tr01siz - TR01L40; // expands out to a = ptr->tr01siz - sizeof(tr01k40) - member_size(tr01k40,tr01msg); a = 20 - 10 - 1; // WRONG - this result is 9
Correct Version // this line from header file - standard way to calculate size // of fixed length part of lrec. In this example imagine that // tr01k40 = 10 and tr01msg = 1. This means the fixed part of // the lrec is 9 #define TR01L40 (sizeof(tr01k40) - member_size(tr01k40,tr01msg)) // Read an lrec - it is 20 bytes long - 11 bytes variable field ptr = dfred( etc etc ); // calculate length of variable field a = ptr->tr01siz - TR01L40; // expands out to a = ptr->tr01siz - (sizeof(tr01k40) - member_size(tr01k40,tr01msg)); a = 20 - (10 - 1); // CORRECT - this result is 11
Keylist Examples • Various ways of dealing with Keylists • Traditional approach • Pass parameters into functions • Write user defined macros • Or a combination of all/some of these
// Key 2 set up depending on value of parameter // key2: CARCODE = match Carrier Code in lrec // Else = Matching name for length of input void SetUpKeys(dft_fil *pTr01ps, dft_kyl *pKeys, char *Carcode, int key2setting ) { df_setkey(pKeys, 1, offsetof(tr01k80, tr01key), member_size(tr01k80, tr01key), DF_EQ, 0, TR01K80, DF_UPORG, DF_CONST);
if(key2 == CARCODE) { df_setkey(pKeys, 2, offsetof(tr01k80, tr01car), member_size(tr01k80, tr01car), DF_EQ, Carcode, 0, DF_UPORG, DF_CHAR); } else { df_setkey(pKeys, 2, offsetof(tr01k80, tr01nam), strlen(ecbptr()->ebw000), DF_EQ, Carcode, 0, DF_NOORG, DF_CHAR); } dfkey_nbr(pTr01ps, pKeys, 2); return; }
Conditional Operator df_setkey(pKeys, 1, offsetof(tr01k80, tr01key), member_size(tr01k80, tr01key), DF_EQ, 0, TR04K80, DF_UPORG, DF_CONST); df_setkey(pKeys, 2, ((key2 == CARCODE) ? offsetof(tr01k80, tr01car) : offsetof(tr01k80, tr01nam)), ((key2 == CARCODE) ? member_size(tr01k80, tr01car) : strlen(Carcode)), DF_EQ, Carcode, 0, ((key2 == CARCODE) ? DF_UPORG : DF_NOORG), DF_CHAR);
df_setkey() issues • General df_setkey() function • Equivalent of Assembler process • Mutually exclusive parameters • Always a recipe for disaster • No indication of problems at compile time only at run time • Nine parameters for each key
// This example will try to match the byte at address 0 // with the PKY field in the lrec - NOT GOOD df_setkey(pKeys, 1, offsetof(tr01k80, tr01key), member_size(tr01k80, tr01key), DF_EQ, 0, // For DF_CHAR or DF_PACKED TR04K80, // For DF_CONST or DF_MASK DF_UPORG, DF_CHAR); // WRONG - should be DF_CONST
Solutions? • Write some macros • Easy to do • Place macros in header file • Single point of change • Make sure people know about them! • Otherwise it’s a waste of time
// Set up our own setkey macros - allows us to cut // down parameters to 7 #define DF_CONST_KEY(A, B, C, D, E, F, G ) \ df_setkey(A, B, C, D, E, \ 0, \ F, G, \ DF_CONST) #define DF_MASK_KEY(A, B, C, D, E, F, G) \ df_setkey(A, B, C, D, E, \ 0, \ F, G, \ DF_MASK) #define DF_CHAR_KEY(A, B, C, D, E, F, G) \ df_setkey(A, B, C, D, E, F, \ 0, \ G , \ DF_CHAR)
// This Example is using the previously defined // macros and allows us to only worry about 7 // parameters and the name of the macro indicates // the type of parameter being used to set the key DF_CONST_KEY(pKeys, 1, offsetof(tr01k40, grctkey), member_size(tr01k40, grctkey), DF_EQ, GRCTK40, DF_UPORG); if(ptr != NULL) { DF_MASK_KEY(pKeys, 2, offsetof(tr01k40, grctind), member_size(tr01k40, grctind), DF_O, 0X21, DF_NOORG); }
Next Stage • In assembler we use PKY • KEY1=(PKY=#TR01K80) • Only for Primary Key • Is (normally) the first key set • Always length of 1 • Assumes displacement of 2 in lrec • So lets do the same in ISOC
// Set up our own PKY macros - allows us to cut // down parameters = 2 if we make some assumptions // about the position and size // The only parameters we need are the address of // key area and the organisation // These are generic macros and can be used // with ANY file #define SET_PKY40(A, B) \ df_setkey(A, 1, 2, 1, DF_EQ, \ 0, 0X40, B, \ DF_CONST) #define SET_PKY80(A, B) \ df_setkey(A, 1, 2, 1, DF_EQ, \ 0, 0X80, B, \ DF_CONST)
// This Example is using the previously defined // macros and allows us to only worry about 2 // parameters and the name of the macro indicates // the type of parameter being used to set the key SET_PKY40(pKeys, DF_UPORG); if(ptr != NULL) { DF_MASK_KEY(pKeys, 2, offsetof(tr01k40, grctind), member_size(tr01k40, grctind), DF_O, 0X21, DF_NOORG); }
// Take it another stage and create UP/DOWN/NOORG // versions of the macros // These are generic macros and can be used // with ANY file #define SET_PKY40_UP(A) \ df_setkey(A, 1, 2, 1, DF_EQ, \ 0, 0X40, DF_UPORG, \ DF_CONST) // And now use the macro in a program SET_PKY40_UP(pKeys);
Last thoughts • Thanks for listening • In the spirit of Open Source • All code samples available (and free) • www.pcs-training.co.uk/downloads • Any Questions?