This example uses the IEDTCMD
interface and IEDTGET
-interface to read and process the records in a file:
/********************************************************************/ /* */ /* Example 2 */ /* */ /* This example uses the IEDTCMD interface */ /* to execute EDT statements and the IEDGET */ /* interface to read lines. All the records in a */ /* file which contains accounting data are output */ /* if they have an invoice date more than a */ /* predefined number of days before the current date. */ /* */ /* */ /* The example program performs the following individual */ /* actions: */ /* */ /* 1) Determine the current date. */ /* 2) Use the @COPY statement (Format 1) to read all the lines of */ /* the file together with their invoice dates into work area $0. */ /* 3) Execute a loop in which all the lines in work area */ /* $0 are read one after the other and calculate the time */ /* difference between the current date and the invoice date. */ /* If this time difference is greater than the predefined */ /* limit, then the customer number, invoice number and invoiced */ /* amount specified in this line are output. */ /* 4) Once this loop has terminated, EDT is terminated with the */ /* @HALT statement and the example program is then exited. */ /* */ /********************************************************************/ #include <string.h> #include <stdlib.h> #include <stdio.h> #include <time.h> /* Include files of the EDT subroutine interface */ #define EDT_V17 #include <iedtgle.h> /* Create and initialize the EDT subroutine interface data */ /* structures required for this example. */
static iedglcb glcb = IEDGLCB_INIT; static iedupcb upcb = IEDUPCB_INIT; static iedamcb amcb = IEDAMCB_INIT; static iedbuff *command = NULL; static iedbuff *message1 = NULL; static iedbuff *message2 = NULL; /* Definition of an output line */ typedef struct line { char kdnr[8]; /* Customer number */ char free1[2]; char renr[8]; /* Invoice number */ char free2[2]; char betr[10]; /* Invoice amount */ char free3[2]; char day[2]; /* Day of invoicing */ char mon[2]; /* Month of invoicing */ char trenn2[1]; char year[4]; /* Year of invoicing */ char rest[215]; } LINE; /********************************************************************/ /* Function: printrc */ /* */ /* Task: */ /* If EDT has returned an error message, then the error message */ /* is output by this function. */ /* */ /* Parameter: errmsg (IN) Pointer to the additional error */ /* message to be output if an error occurs*/ /* */ /* Return value: none */ /********************************************************************/ static void printrc(char *errmsg) { char message[81]; if (glcb.IEDGLCB_RC_MAINCODE != 0) { printf("%s: %08x\n",errmsg, glcb.IEDGLCB_RC_NBR);/* Output passed error message */ if (glcb.return_message.structured_msg.rmsgl > 0) { strncpy(message,(char*)glcb.return_message.structured_msg.rmsgf,
glcb.return_message.structured_msg.rmsgl); message[glcb.return_message.structured_msg.rmsgl] = 0x00; printf("Meldungstext: %s\n",message); /* Output EDT message */ } exit(1); } } /********************************************************************/ /* Function: fill_buff */ /* */ /* Task: */ /* This function enters content and the record length field in a */ /* record of variable length. */ /* */ /* Parameter: p: (IN) Pointer to a structure of type */ /* iedbuff, which contains the variable */ /* length record to be set. */ /* textp: (IN) Points to a string which contains the */ /* text to be entered. The length */ /* of the string implicitly defines the */ /* record length (length of string + 4) */ /* */ /* Return value: none */ /********************************************************************/ static void fill_buff(iedbuff *p,char *textp) { size_t l_text; /* Length of string */ if ((l_text = strlen(textp)) > 2044) l_text = 2044; /* Restrict length to 2044 characters */ strncpy((char *)p->text,textp,l_text); /* Enter text */ p->length = l_text + 4; /* Enter record length */ } /********************************************************************/ /* Function: edtcmd */ /* */ /* Task: */ /* This function enters the passed strings in records of */ /* variable lengths (DMS format) and then calls the EDT's */ /* CMD interface. */ /* */ /* Parameter: cmd: (IN) Pointer to a string which contains */ /* the EDT statement(s) that are to be */ /* executed. The length of the string */ /* implicitly defines the record length */
/* (String length + 4). */ /* msg1: (IN) Pointer to a string which contains the */ /* text to be entered. The length */ /* of the string implicitly defines the */ /* record length (length of string + 4). */ /* msg2: (IN) Pointer to a string which contains the */ /* text to be entered. The length */ /* of the string implicitly defines the */ /* record length (length of string + 4). */ /* */ /* Return value: none */ /********************************************************************/ static void edtcmd(char *cmd,char *msg1,char *msg2) { fill_buff(command,cmd); fill_buff(message1,msg1); fill_buff(message2,msg2); IEDTCMD(&glcb,&upcb,command,message1,message2); } /********************************************************************/ /* Function: edtget */ /* */ /* Task: */ /* This function uses the subroutine interface's GET function */ /* to read a line from work file $0. The read operation is always */ /* performed relative to the record with line number 0. */ /* */ /* Parameter: rec: (IN) Pointer to a data area in which */ /* the line read by the GET function */ /* is stored. */ /* disp: (IN) Specifies the displacement of the */ /* line to be read from line number 0. */ /* Return value: none */ /********************************************************************/ static void edtget(char *rec,int disp) { char localfile[9] = "$0 "; iedbyte key1[8] = {0,0,0,0,0,0,0,0}; iedbyte key[8] = {0,0,0,0,0,0,0,0}; /* Enter values in IEDAMCB control block */ IEDAMCB_SET_NO_MARKS(amcb); amcb.length_key_outbuffer = 8; amcb.length_rec_outbuffer = 256; amcb.length_key1 = 8; /* -------------------------- (1) */
amcb.displacement = disp; /* read <disp> records after 0 */ strncpy((char *)amcb.filename,localfile,8); /* Work file $0 */ IEDTGET(&glcb,&amcb,key1,key,rec); } /********************************************************************/ /* Main program */ /********************************************************************/ int main(void) { char filename[] = "edt.rechnung2"; char cmd[257]; LINE zeile; int disp; int days = 20; int time_diff; time_t zeit1; time_t zeit2; struct tm t; printf("\nStart Beispiel2\n\n"); /* Provide buffer */ command = (iedbuff *)malloc(2048); message1 = (iedbuff *)malloc(2048); message2 = (iedbuff *)malloc(2048); /* Determine current date */ zeit1 = time((time_t *) 0); /* For the conversion of the date in the line */ /* the time is set to 00.00 */ t.tm_sec = 0; t.tm_min = 0; t.tm_hour = 0; /* Read the file to be processed using */ /* the @COPY statement (format 1) */ sprintf(cmd,"COPY FILE=%s",filename); edtcmd(cmd,"",""); printrc("Fehler bei der @COPY-Anweisung!"); /* The following loop processes all the lines */ /* in work file $0. */ for (disp = 1; disp < 99999999; disp++) /*-------------------- (2) */
{ /* Read next line */ edtget((char *)&zeile,disp); printrc("Fehler bei der Funktion GET!"); /* If reading goes beyond the last line number then */ /* IEDTGET returns "last record" */ if (glcb.IEDGLCB_RC_SUBCODE1 == IEDGLCBlast_record) break; /* Exit loop */ t.tm_mday = atoi(zeile.day); /* Fetch date from */ t.tm_mon = atoi(zeile.mon) - 1; /* the read-in */ t.tm_year = atoi(zeile.year) - 1900; /* line */ zeit2 = mktime(&t); /* Conv. date to */ /* time value */ /* Determine time difference in days */ time_diff = difftime(zeit1,zeit2)/86400; /* If the predefined period has expired, output the */ /* customer number, invoice number and invoiced amount */ /* for the current line. */ if (time_diff > days) { zeile.free1[0] = '\0'; /* ---------------------------- (3) */ zeile.free2[0] = '\0'; zeile.free3[0] = '\0'; printf("Kdnr.: %s, Rechn.nr.: %s, Betrag: %s Euro\n", zeile.kdnr,zeile.renr,zeile.betr); } } /* Terminate EDT and program */ edtcmd("HALT","",""); printrc("Fehler bei der @HALT-Anweisung!"); printf("\n\nEnde Beispiel2\n\n"); return 0; }
Explanations
(1) | In the IEDTGET function it is only necessary to enter values for length_key1 and length_key_outbuffer. |
(2) | The method for the sequential reading of the work file implemented here is not particularly effective since it is always necessary to restart the read operation from the beginning again. Readers should consider how it might be possible to develop a more effective algorithm by using the key returned in key with a constant amcb.displacement = +1. |
(3) | The end character for C strings is used here to permit direct output without conversion. |
If the procedure explained in the section “Producing main programs in C” is stored in a file named CC.DO
in BS2000 and the source file is stored as the S element BEISPIEL2.C
in the library EDT.BEISPIELE
then the above program can be compiled and linked with
/CALL-PROC CC.DO,(2).
The generated program can then be executed using
/START-EXECUTABLE-PROGRAM (E=BSP2C,L=EDT.BEISPIELE)
When CC.DO
runs, the following or similar output is generated by the system or the compiler:
% BLS0524 LLM 'SDFCC', VERSION '03.1A40' OF '2005-02-03 16:16:36' LOADED % BLS0551 COPYRIGHT (C) Fujitsu Siemens Computers GmbH 2005. ALL RIGHTS RESERVED % CDR9992 : BEGIN C/C++(BS2000/OSD) VERSION 03.1A40 % CDR9907 : NOTES: 0 WARNINGS: 0 ERRORS: 0 FATALS: 0 % CDR9937 : MODULES GENERATED, CPU TIME USED = 2.6000 SEC % BND3102 SOME WEAK EXTERNS UNRESOLVED % BND1501 LLM FORMAT: '1' % BND1101 BINDER NORMALLY TERMINATED. SEVERITY CLASS: 'UNRESOLVED EXTERNAL' % CDR9936 : END; SUMMARY: NOTES: 0 WARNINGS: 0 ERRORS: 0 FATALS: 0 % CCM0998 CPU TIME USED: 3.6403 SECONDS
Let us assume that the file to be processed by this example program EDT.RECHNUNG2
resembles the following:
00347563 00028654 1378.89 21.05.2007 00345781 00027349 21500.00 07.04.2007 00375863 00028937 248.23 19.05.2007 00242365 00012358 4577.54 23.03.2007 00416467 00046687 6776.31 10.05.2007 00576373 00015463 578.00 19.04.2007 00785214 00053417 65465.00 13.12.2006 00265432 00065743 6534.67 16.05.2007
00546315 00035476 656.34 29.05.2007 00675436 00015334 7878.45 04.05.2007 00353466 00087227 654.24 11.11.2006 00534267 00067854 52346.00 15.05.2007 00243535 00078921 4532.54 22.04.2007 00783432 00063223 548.19 17.05.2007 00623556 00054342 5346.32 17.03.2007 00234354 00065233 4534.65 08.05.2007
When /START-EXECUTABLE-PROGRAM (E=BSP2C,L=EDT.BEISPIELE)
is called (on 4.5.2007), the following or similar output is displayed:
% BLS0523 ELEMENT 'BSP2C', VERSION '@', TYPE 'L' FROM LIBRARY ':A:$USER.EDT .BEISPIELE' IN PROCESS % BLS0524 LLM '$LIB-ELEM$EDT$BEISPIELE$$BSP2C$$', VERSION ' ' OF '2007-05-04 12 :22:24' LOADED Start Beispiel2 Kdnr.: 00345781, Rechn.nr.: 00027349, Betrag: 21500.00 Euro Kdnr.: 00242365, Rechn.nr.: 00012358, Betrag: 4577.54 Euro Kdnr.: 00785214, Rechn.nr.: 00053417, Betrag: 65465.00 Euro Kdnr.: 00353466, Rechn.nr.: 00087227, Betrag: 654.24 Euro Kdnr.: 00623556, Rechn.nr.: 00054342, Betrag: 5346.32 Euro Ende Beispiel 2 % CCM0998 CPU TIME USED: 0.3276 SECONDS