Code:
- Include Files:
- cpsrc.cp1400h
- //--------------------------------------------------------------------------------------------------------------//
- // //
- // //
- // Regular Expression Server Include File //
- // //
- // //
- //--------------------------------------------------------------------------------------------------------------//
- //
- // compile regular expression, and return pointer
- //
- Dcl-PR cp1400_load Pointer ;
- *n Pointer Options(*String:*Trim) Value ;
- End-PR ;
- //
- // execute regular expression
- //
- Dcl-PR cp1400_process Ind ;
- *n Pointer ;
- *n Pointer Options(*String:*Trim) Value ;
- End-PR ;
- //
- // cleanup/housekeeping
- //
- Dcl-PR cp1400_cleanup ;
- *n Pointer ;
- End-PR ;
- cpsrc.cp1400h
- //--------------------------------------------------------------------------------------------------------------//
- // //
- // //
- // dynamic data structure array management include file //
- // //
- // //
- //--------------------------------------------------------------------------------------------------------------//
- //
- // parameter data structure
- //
- Dcl-DS cp1402_t Template ;
- @heap# Uns(10) Inz(0) ;// allocated size
- @heap$ Uns(10) Inz(0) ;// used size
- @heap@ Pointer Inz(*Null) ;// begining of @heap
- heap@@ Pointer Inz(*Null) ;// heap@@->heap@->heap
- heapSz Uns(10) Inz(0) ;// heap length
- End-DS ;
- //
- // allocate heap
- //
- Dcl-PR cp1402_alloc Pointer ;
- parms LikeDS(cp1402_t) ;
- End-PR ;
- //
- // deallocate heap
- //
- Dcl-PR cp1402_dealloc ;
- parms LikeDS(cp1402_t) ;
- End-PR ;
- Binding Source:
- cpsrc.cp1400b
- STRPGMEXP PGMLVL(*CURRENT)
- EXPORT SYMBOL(CP1400_LOAD)
- EXPORT SYMBOL(CP1400_PROCESS)
- EXPORT SYMBOL(CP1400_CLEANUP)
- ENDPGMEXP
- cpsrc.cp1402b
- STRPGMEXP PGMLVL(*CURRENT)
- EXPORT SYMBOL(CP1402_ALLOC)
- EXPORT SYMBOL(CP1402_DEALLOC)
- ENDPGMEXP
- Service Program Source:
- cpsrc.cp1400s
- //--------------------------------------------------------------------------------------------------------------//
- // //
- // //
- // CP1400S - Service Program - evaluate regular expression //
- // //
- // //
- //--------------------------------------------------------------------------------------------------------------//
- //
- // ... compilation notes ...
- //
- // CRTRPGMOD MODULE(CPANDO/CP1400S)
- // SRCFILE(CPANDO/CPSRC)
- //
- // CRTSRVPGM SRVPGM(CPANDO/CP1400S)
- // SRCFILE(CPANDO/CPSRC)
- // SRCMBR(CP1400B)
- // TEXT('Manage/Evaluate Regular Expressions')
- //
- Ctl-Opt debug(*Yes) option(*SrcStmt:*NoDebugIO) noMain ;
- //--------------------------------------------------------------------------------------------------------------//
- // //
- // ... procedure interfaces ... //
- // //
- //--------------------------------------------------------------------------------------------------------------//
- //
- // ... services (external) ...
- //
- Dcl-PR regcomp Int(10) ExtProc('regcomp') ;
- *n Pointer Value ;
- *n Pointer Value ;
- *n Int(10) Value ;
- End-PR ;
-
- Dcl-PR regexec Int(10) ExtProc('regexec') ;
- *n Pointer Value ;
- *n Pointer Value ;
- *n Uns(10) Value ;
- *n Pointer Value ;
- *n Int(10) Value ;
- End-PR ;
-
- Dcl-PR regerror Uns(10) ExtProc('regerror') ;
- *n Int(10) Value ;
- *n Pointer Value ;
- *n Pointer Value ;
- *n Int(10) Value ;
- End-PR ;
-
- Dcl-PR regfree ExtProc('regfree') ;
- *n Pointer Value ;
- End-PR ;
- //--------------------------------------------------------------------------------------------------------------//
- // //
- // ... data structures ... //
- // //
- //--------------------------------------------------------------------------------------------------------------//
- Dcl-DS regex_t Based(regex_t@) ;
- re_nsub Int(10) ;
- re_comp Pointer ;
- re_cflags Int(10) ;
- re_erroff Int(10) ;
- re_len Int(10) ;
- re_ucoll Int(10) Dim(2) ;
- re_lsub Pointer ;
- lsub Int(10) Dim(16) ;
- esub Int(10) Dim(16) ;
- *n Pointer ;// reserved
- re_esub Pointer ;
- re_specchar Pointer ;
- re_phdl Pointer ;
- comp_spc Char(1) Dim(112) ;
- re_map Char(1) Dim(256) ;
- re_shift Int(5) ;
- re_dbcs Int(5) ;
- *n Char(12) ;// forcing to 16 byte boundary
- End-DS ;
- //--------------------------------------------------------------------------------------------------------------//
- // //
- // ... standalone variables ... //
- // //
- //--------------------------------------------------------------------------------------------------------------//
- Dcl-S rc Int(10) ;
- Dcl-S buf Char(256) ;
- //--------------------------------------------------------------------------------------------------------------//
- // //
- // Procedures //
- // //
- //--------------------------------------------------------------------------------------------------------------//
- // load //
- //--------------------------------------------------------------------------------------------------------------//
- Dcl-Proc cp1400_load Export ;
- Dcl-PI *n Pointer ;
- regexp@ Pointer Options(*String:*Trim) Value ;
- End-PI ;
- //
- // compile regexp
- //
- regex_t@ = %Alloc(%Len(regex_t)) ;
- rc = regcomp(regex_t@:regexp@:0) ;
- If ( rc <> 0 ) ;// minimal error handling
- regerror(rc:regex_t@:%Addr(buf):%Len(buf)) ;
- regex_t@ = *Null ;
- EndIf ;
- Return regex_t@ ;
-
- End-Proc ;
- //--------------------------------------------------------------------------------------------------------------//
- // process //
- //--------------------------------------------------------------------------------------------------------------//
- Dcl-Proc cp1400_process Export ;
- Dcl-PI *n Ind ;
- regexp@ Pointer ;
- string@ Pointer Options(*String:*Trim) Value ;
- End-PI ;
- //
- // execute regular expression
- //
- Return ( 0 = regexec(regexp@:string@:0:*Null:0) ) ;
- End-Proc ;
- //--------------------------------------------------------------------------------------------------------------//
- // cleanup //
- //--------------------------------------------------------------------------------------------------------------//
- Dcl-Proc cp1400_cleanup Export ;
- Dcl-PI *n ;
- regex_t@ Pointer ;
- End-PI ;
- //
- // no memory leaks here!
- //
- regfree(regex_t@) ;
- DeAlloc regex_t@ ;
- Return ;
- End-Proc ;
- cpsrc.cp1402s
- //--------------------------------------------------------------------------------------------------------------//
- // //
- // //
- // dynamic array management //
- // //
- // //
- //--------------------------------------------------------------------------------------------------------------//
- // //
- // Instead of using array notation, where @heap($I) would be the Ith element of a data structure array, we //
- // are going to use pointer notation. //
- // //
- // For each element in the data structure array, we are going to allocate storage in the heap, and store //
- // the pointer to that storage in a contiguous section of memory. The first pointer points to the first //
- // array element, the second pointer to the second, and so on. When the number of pointers in contiguous //
- // memory fills the allocated area, we will double the allocated amount. //
- // //
- // //
- // @heap@ points to the first pointer. //
- // //
- // heap@@ -> heap@ -> heaprec //
- // //
- // Therefore, for the Ith element in the array: //
- // //
- // heap@@ = @heap@ + (I-1)*#POINTERSIZE //
- // //
- // This is almost like a Multiple Occurrence Data Structure, w/ the above statement replacing the OCUR //
- //--------------------------------------------------------------------------------------------------------------//
- //
- // ... compilation notes ...
- //
- // CRTRPGMOD MODULE(CPANDO/CP1402S)
- // SRCFILE(CPANDO/CPSRC)
- //
- // CRTSRVPGM SRVPGM(CPANDO/CP1402S)
- // SRCFILE(CPANDO/CPSRC)
- // SRCMBR(CP1402B)
- // TEXT('Dynamic Data Structure Array Management')
- //
- //--------------------------------------------------------------------------------------------------------------//
- Ctl-Opt debug(*Yes) option(*SrcStmt:*NoDebugIO:*NoUnRef) noMain ;
- //--------------------------------------------------------------------------------------------------------------//
- //
- // ... module include files ...
- //
- /copy cpsrc,cp1402h
- //--------------------------------------------------------------------------------------------------------------//
- Dcl-Proc cp1402_alloc Export ;
- Dcl-PI *n Pointer ;
- parms LikeDS(cp1402_t) ;
- End-PI ;
-
- parms.@heap$ += 1 ;
-
- Select ;
- //
- // initialization
- //
- When ( parms.@heap$ = 1 ) ;
- parms.@heap@ = %Alloc(parms.@heap#*16) ;
- parms.heap@@ = parms.@heap@ ;
- When ( parms.@heap$ <= parms.@heap# ) ;
- //
- // same as parms.heap@@ = parms.@heap@ + (parms.@heap$-1)*#POINTERSIZE
- //
- parms.heap@@ += 16 ;
- Other ;
- //
- // double allocated space
- //
- parms.@heap# *= 2 ;
- parms.@heap@ = %Realloc( parms.@heap@ : parms.@heap#*16 ) ;
- parms.heap@@ = parms.@heap@ + (parms.@heap$-1)*16 ;
- EndSl ;
-
- Return %Alloc(parms.heapSz) ;
- End-Proc ;
- //--------------------------------------------------------------------------------------------------------------//
- Dcl-Proc cp1402_dealloc Export ;
- Dcl-PI *n ;
- parms LikeDS(cp1402_t) ;
- End-PI ;
-
- Dcl-S heap@ Pointer Based(parms.heap@@) ;
- Dcl-S $I Uns(10) ;
-
- parms.heap@@ = parms.@heap@ ;
- For $I = 1 to parms.@heap$ ;
- DeAlloc heap@ ;
- parms.heap@@ += 16 ;
- EndFor ;
- DeAlloc parms.@heap@ ;
-
- Return ;
- End-Proc ;
- Program Source:
- RPG cpsrc.cp1402s
- //--------------------------------------------------------------------------------------------------------------//
- // //
- // //
- // Regular Expression Matching test program - match mailing address //
- // //
- // //
- //--------------------------------------------------------------------------------------------------------------//
- Ctl-Opt debug(*Yes) option(*SrcStmt:*NoDebugIO:*NoUnRef) main(cp1402r)
- dftActGrp(*No) actGrp(*New)
- bndDir('CP1400') ;
- //--------------------------------------------------------------------------------------------------------------//
- // //
- // ... files ... //
- // //
- //--------------------------------------------------------------------------------------------------------------//
- Dcl-F cp1400f Disk UsrOpn Prefix(inp_) ;
- Dcl-F qsysprt Printer(132) UsrOpn ;
- //--------------------------------------------------------------------------------------------------------------//
- // //
- // ... procedure interfaces ... //
- // //
- //--------------------------------------------------------------------------------------------------------------//
- //
- // ... service program include files ...
- //
- /copy cpsrc,cp1400h
- //
- // ... dynamic data structure array management module include files
- //
- /copy cpsrc,cp1402h
- //
- // ... from the C run-time library ...
- //
- Dcl-PR memcmp Int(10) ExtProc('memcmp') ;
- *n Pointer Value ;
- *n Pointer Value ;
- *n Uns(10) Value ;
- End-PR ;
-
- Dcl-PR qsort ExtProc('qsort') ;
- *n Pointer Value ;
- *n Uns(10) Value ;
- *n Uns(10) Value ;
- *n Pointer(*Proc) Value ;
- End-PR ;
- //--------------------------------------------------------------------------------------------------------------//
- // //
- // ... standalone variables/constants ... //
- // //
- //--------------------------------------------------------------------------------------------------------------//
-
- Dcl-DS *n ;// a routine for each sort
- *n Pointer(*Proc) Inz(%PAddr('QSORTCOMP1')) ;
- *n Pointer(*Proc) Inz(%PAddr('QSORTCOMP2')) ;
- @qsortcomp Pointer(*Proc) Dim(2) Pos(1) ;
- End-DS ;
-
- Dcl-DS addrCtl LikeDS(cp1402_t) ;// one control structure per array
-
- Dcl-S addr@ Pointer Based(addrCtl.heap@@) ;// addrCtl.heap@@->addr@->addrRec
- Dcl-DS addrRec Qualified Based(addr@) ;
- mType Uns(3) ;
- text Like(inp_TEXT) ;
- End-DS ;
-
- Dcl-S @regexp@ Pointer Dim(3) ;// an array of pointers
-
- Dcl-C #POINTERSIZE %Len(addr@) ;// in case pointer size ever changes
- Dcl-C #ADDRECSIZE 1024 ;// initial size of array
- //--------------------------------------------------------------------------------------------------------------//
- // //
- // ... What can I say? I still use 'O' specs ... //
- // //
- //--------------------------------------------------------------------------------------------------------------//
- oqsysprt e 1
- o addrRec.mType z
- o ' '
- o addrRec.text
- //--------------------------------------------------------------------------------------------------------------//
- // //
- // Procedures //
- // //
- //--------------------------------------------------------------------------------------------------------------//
- // ... MainLine ... //
- //--------------------------------------------------------------------------------------------------------------//
- Dcl-Proc cp1402r ;
-
- init() ;
- DoW ( reader() ) ;
- process() ;
- EndDo ;
- eoj() ;
-
- Return ;
- End-Proc ;
- //--------------------------------------------------------------------------------------------------------------//
- // ... reader ... //
- //--------------------------------------------------------------------------------------------------------------//
- Dcl-Proc reader ;
- Dcl-PI *n Ind End-PI ;
-
- Read cp1400f ;
-
- Return ( Not %Eof(cp1400f) ) ;
- End-Proc ;
- //--------------------------------------------------------------------------------------------------------------//
- // ... process ... //
- //--------------------------------------------------------------------------------------------------------------//
- Dcl-Proc process ;
-
- addr@ = cp1402_alloc( addrCtl ) ;// addrRec is based upon addr@
- addrRec.mType = getMatchType() ;
- addrRec.TEXT = inp_TEXT ;
-
- Return ;
- End-Proc ;
- //--------------------------------------------------------------------------------------------------------------//
- // ... get match Type ... //
- //--------------------------------------------------------------------------------------------------------------//
- Dcl-Proc getMatchType ;
- Dcl-PI *n Like(addrRec.mType) End-PI ;
-
- Dcl-S mType Like(addrRec.mType) Inz(0) ;
-
- DoU ( cp1400_process( @regexp@(mType) : inp_TEXT) ) ;// will always eventually return true
- mType += 1 ;
- EndDo ;
-
- Return mType ;
- End-Proc ;
- //--------------------------------------------------------------------------------------------------------------//
- // ... initialize ... //
- //--------------------------------------------------------------------------------------------------------------//
- Dcl-Proc init ;
- Open cp1400f ;
- //
- // 1815 Brunswick Court, Houston, TX, 77008
- //
- @regexp@(1) = cp1400_load('^[0-9]\{1,\}' //^1815\
- + ' [A-Za-z. ]*,' // Brunswick Court,\
- + ' [A-Za-z ]*,' // Houston,\
- + ' [A-Z]\{2\},' // TX,\
- + ' [0-9]\{5\}$') ;// 77008$
- //
- // 1815 Brunswick Court, Houston, TX, 77008-1242
- //
- @regexp@(2) = cp1400_load('^[0-9]\{1,\}' //^1815/
- + ' [A-Za-z. ]*,' // Brunswick Court,/
- + ' [A-Za-z ]*,' // Houston,/
- + ' [A-Z]\{2\},' // TX,/
- + ' [0-9]\{5\}-[0-9]\{4\}$') ;// 77008-1234$
- //
- // catch-all - leaving this out will cause an index error in getMatchType()
- //
- @regexp@(3) = cp1400_load('^.*$') ;
-
-
- //
- // initialization of dynamic data structure array @heap
- //
- addrCtl.@heap# = #ADDRECSIZE ;// intial allocation
- addrCtl.@heap$ = 0 ;// number of entries
- addrCtl.heapSz = %Len(addrRec) ;// length of array element
-
- Return ;
- End-Proc ;
- //--------------------------------------------------------------------------------------------------------------//
- // ... end of job - print out reports and house-keeping ... //
- //--------------------------------------------------------------------------------------------------------------//
- Dcl-Proc eoj ;
- Dcl-S $I Uns(10) ;// Utility variable
- Dcl-S $J Uns(10) ;// Utility variable
- Dcl-S svText Like(inp_TEXT) ;// only print once
- //
- // ... print reports ...
- //
- For $I = 1 to %Elem(@qsortcomp) ;
- qsort( addrCtl.@heap@
- : addrCtl.@heap$
- : #POINTERSIZE
- : @qsortcomp($I)
- ) ;
- Open qsysprt ;
- svTEXT = *Blanks ;
- addrCtl.heap@@ = addrCtl.@heap@ ;
- For $J = 1 to addrCtl.@heap$ ;
- If ( addrRec.text <> svTEXT ) ;// print if not duplicate
- Except ;
- svTEXT = addrRec.text ;
- EndIf ;
- addrCtl.heap@@ += #POINTERSIZE ;// @heap@ + ($I-1)*#POINTERSIZE
- EndFor ;
- Close qsysprt ;
- EndFor ;
-
- Close cp1400f ;
-
- cp1402_dealloc( addrCtl ) ;
-
- For $I = 1 to %Elem(@regexp@) ;
- cp1400_cleanup( @regexp@($I) ) ;
- EndFor ;
-
- Return ;
- End-Proc ;
- //--------------------------------------------------------------------------------------------------------------//
- // ... comparison for qsort ... //
- //--------------------------------------------------------------------------------------------------------------//
- Dcl-Proc qsortComp1 ;
- Dcl-PI *n Int(10) ;
- ds1@@ Pointer Value ;
- ds2@@ Pointer Value ;
- End-PI ;
-
- Dcl-DS ds1 LikeDS(addrRec) Based(ds1@) ;
- Dcl-DS ds2 LikeDS(addrRec) Based(ds2@) ;
- Dcl-S ds1@ Pointer Based(ds1@@) ;
- Dcl-S ds2@ Pointer Based(ds2@@) ;
-
- Select ;
- When ( ds1.TEXT < ds2.TEXT ) ;
- Return -1 ;
- When ( ds1.TEXT > ds2.TEXT ) ;
- Return 1 ;
- Other ;
- Return 0 ;
- EndSl ;
-
- End-Proc ;
- //--------------------------------------------------------------------------------------------------------------//
- Dcl-Proc qsortComp2 ;
- Dcl-PI *n Int(10) ;
- ds1@@ Pointer Value ;
- ds2@@ Pointer Value ;
- End-PI ;
-
- Dcl-S ds1@ Pointer Based(ds1@@) ;
- Dcl-S ds2@ Pointer Based(ds2@@) ;
-
- Return memcmp( ds1@ : ds2@ : addrCtl.heapSz ) ;
-
- End-Proc ;
- CLLE cpsrc.cp1402c
- PGM
-
- OVRPRTF FILE(QSYSPRT) MAXRCDS(*NOMAX)
- CALL PGM(CP1402R)
-
- ENDPGM
- File Source:
- CLLE cpsrc.cp1400f
- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- * *
- * regular expression (caching) - test data *
- * *
- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- A R CP1400
- A TEXT 128A
-
|
|