; Copyright (c) 2000, Perforce Software, All rights reserved. ; ; This software was originally developed by Silicon Graphics, Inc (SGI). ; ; Redistribution and use in source and binary forms, with or ; without modification, are permitted provided that the following ; conditions are met: ; ; Redistributions of source code must retain the above copyright notice, ; this list of conditions and the following disclaimer. ; ; Redistributions in binary form must reproduce the above copyright ; notice, this list of conditions and the following disclaimer in the ; documentation and/or other materials provided with the distribution. ; ; Neither name of Perforce Software nor SGI nor the names of its ; contributors may be used to endorse or promote products derived from ; this software without specific prior written permission. ; ; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ; ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR ; CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, ; EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, ; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR ; PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF ; LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING ; NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. procedure(CDS_P4IntWiz() ;_Oct 18 00 sikand 1475 ; Integrate wizard for 4.4 let(( o1 actions libchoices intwiz liblist intchoices libchoice selbutton deselbutton) ;; design the GUI ;; actions libchoice = ddGetLibList()~>name liblist = cons("All" libchoice) intchoices = hiCreateCyclicField(?name 'intchoices ?choices list("Update this branch" "Update the MAINLINE") ?prompt "Integration direction" ?value "Update this branch" ) actions = hiCreateRadioField(?name 'actions ?choices '("Show pending" "Describe change" "Integrate") ?value "Show pending" ) libchoices = hiCreateCyclicField(?name 'libchoices ?choices liblist ?prompt "Library" ?value "All" ) o1 = hiCreateListBoxField(?name 'o1 ?choices list() ?multipleSelect t ) intwiz = hiCreateAppForm(?name 'intwiz ?fields list(list(intchoices 10:0 50:10 0) list(actions 0:40 10:10 0) list(libchoices 0:70 60:30 50) list(o1 0:120 700:400 0) ) ?formTitle "Update Changes" ?callback 'CDS_P4IntWizCB() ?buttonLayout 'ApplyCancel ) hiDisplayForm(intwiz) ) ; ** let ** ) ; ** procedure CDS_P4IntWiz ** procedure(CDS_P4IntWizCB(form) ;_Nov 13 00 sikand 0 prog(( action libname intoption choices lel changenum status refint cont cmd openfile direction bname singleint) action = form->actions->value libname = form->libchoices->value direction = form->intchoices->value CDS_P4IntTable = makeTable("CDS_P4IntTable" list()) if( direction == "Update the MAINLINE" then when( libname != "All" hiGetAttention() singleint = t status = CDS_WarnDialogBox("P4 Interface" strcat("Your library selection is not set to ALL.\nAre you sure you want to selectively integrate the\n" form->libchoices->value " library ?")) unless( status warn("Library list overriden to All") form->libchoices->value = "All" libname = "All" singleint = nil ) ; ** unless status ** ) ; ** when libname ** ;; cond( ((action == "Show pending") intoption = "-n" CDS_P4Integrate(libname intoption form t) return(t) ) ((action == "Describe change") CDS_ErrorDialogBox("P4 Interface" "Use the Show Versions form instead") error("Describe changes is not active for reverse integrates") ) ((action == "Integrate") ;; make sure the user has no pending integrates to ;; this branch CDS_P4Integrate(libname "-n" form) when( CDS_P4IntTable~>? CDS_ErrorDialogBox("P4 Interface" "You have pending integrates to this branch !") error("Integrate aborted") ) ;; make sure the user knows what this entails unless(CDS_WarnDialogBox("P4 Interface" "This procedure will modify the main tree.\n\nAll files in the display will be integrated.\n\nNo de-selections are possible.\n\nAre you sure you want to continue ?\n") error("Integrate aborted by user request\n") ) ;; make sure that there are no checkouts bname = getShellEnvVar(CDS_P4ProjectBranchEnvVar) openfile = strcat("/tmp/p4bopen." CDS_P4UserFileName ) if( singleint then cmd = sprintf(nil "opened -a //depot/%s/... | grep %s: > %s" bname libname openfile) else cmd = sprintf(nil "opened -a //depot/%s/... > %s" bname openfile) ) status = CDS_P4IPCDirectCommand(cmd) ;; if no files are opened, opened returns a 1 ;; so don't bother checking it ;; I hate this aspect if( fileLength(openfile) != 0 then CDS_ErrorDialogBox("P4 Interface" "Please check-in all your open files first.\nThe list will pop up next...\n") view(openfile) error("Integrate aborted") ) ;; force a show pending ;; to check the status CDS_P4Integrate(libname "-n" form t) if( ddGetObj(libname)~>p4CheckinType == "Bulk" then ;; check for bulk mode bulkcont = CDS_WarnDialogBox("P4 Interface" strcat(libname " is a bulk mode library. Normal checks will not be performed. Do you know what you are doing ?")) unless( bulkcont error("Integrate aborted by user request") ) CDS_P4Integrate(libname "" form t) return(t) else unless( form->o1->choices error("Nothing to integrate !\n") ) ) ; ** if ddGetObj ** unless(CDS_WarnDialogBox("P4 Interface" "Please review the file names in the form.\nReady to continue ?\n") error("Integrate aborted by user request\n") ) ;; make sure that if a ref library is involved ;; the user either has permissions and/or knows the ;; implication foreach( lib CDS_P4IntTable["..."] when( lib == "P4INTFAIL" CDS_ErrorDialogBox("P4 Interface" "Target files in the mainline are opened for edit.\nCheck the CIW for the list.\n") error("Integrate aborted") ) when( ddGetObj(lib)~>p4type == "Reference" when( CDS_P4RefLibControl status = CDS_P4CheckProtect(lib CDS_P4User) unless( status message = strcat("You do not have permission to integrate " ddGetObj(lib)~>name " Reference library data.\nPlease revert your Reference library cells back to a valid state\nor wait for a new release.") CDS_ErrorDialogBox("P4 Interface" message) error("Integrate aborted!\n") ) ) ; ** when CDS_P4RefLibControl ** ) ; ** when ddGetObj ** ) ; ** foreach lib ** when( refint cont = CDS_WarnDialogBox("P4 Interface" "You have Reference library changes that will be integrated.\nAre you sure that you want to do this?") unless( cont error("Integrate aborted!\n") ) ) ; ** when refint ** CDS_P4Integrate(libname "" form t) ) ) ; ** cond action ** ) ; ** if direction ** if( direction == "Update this branch" then cond( ((action == "Show pending") intoption = "-n" CDS_P4Integrate(libname intoption form) return(t) ) ((action == "Integrate") intoption = "" CDS_P4Integrate(libname intoption form) return(t) ) ) ; ** cond action ** when( action == "Describe change" choices = form->o1->value foreach( el choices lel = parseString(el) changenum = nthelem(3 lel) printf("Getting description for change %s, please wait....\n" changenum) ;;status = CDS_P4IPCCommand(strcat("describe -s " changenum ">/tmp/p4des." CDS_P4UserFileName)) status = CDS_P4IPCCommand(strcat("-o /tmp/p4des." CDS_P4UserFileName " describe -s " changenum)) when( status == 0 view(strcat("/tmp/p4des." CDS_P4UserFileName)) ) ) ; ** foreach el ** ) ; ** when action ** ) ; ** if direction ** ) ; ** prog ** ) ; ** procedure CDS_P4IntWizCB ** procedure(CDS_P4Integrate(lib option form @optional reverse) ;_Dec 7 01 sikand 1926 prog( (liblist bname libclient cmd filename user clist ilist ichange ochange status cddata xlist cnameprefix message odes idata) liblist = nil clist = nil if( lib == "All" then liblist = ddGetLibList()~>name else liblist = cons(lib liblist) ) user = CDS_P4User bname = getShellEnvVar(CDS_P4ProjectBranchEnvVar) unless( bname error("No branch detected") ) when( option != "" foreach( el liblist if( ddGetObjDMSys(ddGetObj(el)) == "p4" then ;; fix bname maybe if( reverse then ;; xxx libclient = CDS_P4GetClient(ddGetObj(el)) ;; need the name of the main line client cnameprefix = car(parseString(libclient ":")) if(boundp('CDS_SiteName) then libclient = strcat(cnameprefix ":" CDS_Project "_" CDS_ProjectRev "_" CDS_SiteName) else libclient = strcat(cnameprefix ":" CDS_Project "_" CDS_ProjectRev) ) printf("Checking reverse updates for %s\n" el) filename = strcat("/tmp/p4int." CDS_P4UserFileName) sprintf(cmd "-o %s -c %s integrate -i -d %s -b %s -r" filename libclient option bname) ;;println(cmd) else ;;libclient = strcat(el ":" bname) libclient = CDS_P4GetClient(ddGetObj(el)) printf("Checking updates for %s\n" el) filename = strcat("/tmp/p4int." CDS_P4UserFileName) sprintf(cmd "-o %s -c %s integrate -i -d %s -b %s" filename libclient option bname) ) ; ** if reverse ** status = CDS_P4IPCCommand(cmd) ;;unless( zerop(status) ;;error(CDS_IPCBuffer) ;;) if( reverse then if( ddGetObj(el)~>p4CheckinType == "Bulk" then ;; check for bulk mode warn("Library %s is a bulk mode object\n" el) warn("Changes will not be displayed\n") ;;view("/tmp/p4int.sikand") else CDS_P4BuildRevIntTable(el bname) ;; don't forget to reject the ... cookie form->o1->choices=remove("..." sort(CDS_P4IntTable~>? 'alphalessp)) ) else CDS_P4BuildIntTable(el bname) foreach( key CDS_P4IntTable ;; reject the magic ... field that we use ;; as a cookie unless( key == "..." unless( member(car(CDS_P4IntTable[key]) clist) clist = cons(car(CDS_P4IntTable[key]) clist) ) ) ) ; ** foreach key ** form->o1->choices=clist ) ; ** if reverse ** ) ; ** if ddGetObjDMSys ** ) ; ** foreach el ** printf("Done...\n") return(t) ) ; ** when option ** if( reverse && option == "" then ;; get a change description message = CDS_P4IntegrateMessage() foreach( el liblist if( ddGetObjDMSys(ddGetObj(el)) == "p4" then ;; xxx libclient = CDS_P4GetClient(ddGetObj(el)) ;; need the name of the main line client cnameprefix = car(parseString(libclient ":")) if(boundp('CDS_SiteName) then libclient = strcat(cnameprefix ":" CDS_Project "_" CDS_ProjectRev "_" CDS_SiteName) else libclient = strcat(cnameprefix ":" CDS_Project "_" CDS_ProjectRev) ) filename = strcat("/tmp/p4int." CDS_P4UserFileName) ;; avoid creating empty changes ;; so do a trial run first sprintf(cmd "-o %s -c %s integrate -i -d -n -b %s -r" filename libclient bname) status = CDS_P4IPCCommand(cmd) ;;unless( zerop(status) ;;error(CDS_IPCBuffer) ;;) ;;println(fileLength(filename)) when( fileLength(filename) > 0 ;; create the change printf("Integrating mainline lib %s\n" el) ichange = CDS_P4CreateChange(libclient strcat("cds:auto-r-int " message)) sprintf(cmd "-o %s -c %s integrate -i -d -b %s -r -c %s" filename libclient bname ichange) status = CDS_P4IPCCommand(cmd) ;;unless( zerop(status) ;; error(CDS_IPCBuffer) ;) if( rexMatchp("denied" CDS_IPCBuffer) then warn("Permission errors, get help\n"); warn("Manual revert of files required\n") error(CDS_IPCBuffer) ) ;; first resolve, then submit sprintf(cmd "-o /dev/null -c %s resolve -at" libclient) status = CDS_P4IPCCommand(cmd) ;;unless( zerop(status) ;; error(CDS_IPCBuffer) ;;) printf("Integrating changes to mainline...") sprintf(cmd "-c %s submit -c %s" libclient ichange) status = CDS_P4IPCCommand(cmd) ;;unless( zerop(status) ;; error(CDS_IPCBuffer) ;;) printf("done\n"); ;; update the int wiz form ??? hiFormCancel(form) ) ; ** when fileLength ** ) ; ** if ddGetObjDMSys ** ) ; ** foreach el ** else ;; check status CDS_P4Integrate(lib "-n" form) foreach( lib CDS_P4IntTable["..."] when( lib == "P4INTFAIL" CDS_ErrorDialogBox("P4 Interface" "Target files in the branch are opened for edit.\nCheck the CIW for the list.\n") error("Integrate aborted") ) ) ; ** foreach lib ** ;; user is not allowed to make selections ;; it's lock stock and barrel ;; since otherwise they can break dependencies ;; and that's true for both directions ! ;; make sure the user knows what this entails unless(CDS_WarnDialogBox("P4 Interface" "This procedure will modify the branch.\n\nAll files in the display will be integrated.\n\nNo de-selections are possible.\n\nAre you sure you want to continue ?\n") error("Integrate aborted by user request\n") ) ilist = form->o1->choices if( ilist then filename = strcat("/tmp/p4auto." CDS_P4UserFileName) foreach( el ilist ;; create a change cddata = parseString(el) ochange = nthelem(3 cddata) libclient = CDS_P4GetClient(ddGetObj(nthelem(1 cddata))) ichange = CDS_P4CreateChange(libclient strcat("cds:auto-int " "(" ochange ")")) ;; every change is separately integrated for undo purposes sprintf( cmd "-o %s -c %s integrate -i -d -c %s -b %s //depot/...@%s,@%s" filename libclient ichange bname ochange ochange) printf("Integrating change %s\n", ochange) status = CDS_P4IPCCommand(cmd) ;;unless( zerop(status) ;;error(CDS_IPCBuffer) ;;) ;; first resolve, then submit sprintf(cmd "-o /dev/null -c %s resolve -at" libclient) status = CDS_P4IPCCommand(cmd) ;;unless( zerop(status) ;; error(CDS_IPCBuffer) ;;) sprintf(cmd "-c %s submit -c %s" libclient ichange) status = CDS_P4IPCCommand(cmd) ;; p4 return status stuff drives me crazy ; unless( zerop(status) ; error(CDS_IPCBuffer) ; ) ) ; ** foreach el ** ) ; ** if ilist ** ) ; ** if reverse ** ;; clear the form form->o1->choices = nil ;; update the cellviews from disk ddsHiRefresh() ) ; ** prog ** ) ; ** procedure CDS_P4Integrate ** procedure(CDS_P4GetCdsSpec(fullspec lib) ;_Nov 5 99 sikand 0 ; return the cds component of a depot spec let(( client odspec odspecl dspecrex) client = CDS_P4GetClient(ddGetObj(lib)) CDS_P4IPCBufferProcess(sprintf(nil "-c %s client -o" client)) odspec = parseString(CDS_IPCBuffer) odspecl = nthelem(length(odspec)-1 odspec) dspecrex= substring(odspecl 1 strlen(odspecl)-3-strlen(lib)-1) rexCompile(dspecrex) rexReplace(fullspec "" 0) ) ; ** let ** ) ; ** procedure CDS_P4GetCdsSpec ** procedure(CDS_P4GetDdid(dfile lib) ;_Dec 6 99 sikand 1083 let(( cdsspec data cmd res) ;; cadence are total monkeys for not providing a consistent ;; access method for all files in a library ;; instead, we have to resort to this nonsense to detect ;; the number of entries in a path and then pad them out ;; with null "", just so that we can get a valid ddid. ;; earth calling polar lander...anybody there ???? cmd = "ddGetObj(" cdsspec = CDS_P4GetCdsSpec(dfile lib) data = parseString(cdsspec "/") ;; handle lib files if( length(data) == 2 then sprintf(cmd "%s\"%s\" \"\" \"\" \"%s\")" cmd car(data) cadr(data)) else if( length(data) == 3 then sprintf(cmd "%s\"%s\" \"%s\" \"\" \"%s\")" cmd car(data) cadr(data) caddr(data)) else foreach( el data sprintf(cmd "%s\"%s\" " cmd el) ) sprintf(cmd "%s)" cmd) ) ; ** if length ** ) ; ** if length ** unless(res = evalstring(cmd) ;; brutal thread of execution failure ;; as it should be for null ddGetObj calls error("CDS_P4GetDdid failed for %s" cmd) ) res ) ; ** let ** ) ; ** procedure CDS_P4GetDdid ** procedure(CDS_P4CreateChange(client des) ;_Jun 29 01 sikand 0 prog(( dfile fname cnum cdata ) fname = strcat("/tmp/p4scratch." CDS_P4UserFileName) dfile = outfile(fname) fprintf(dfile "Change: new\nDescription:%s" des) close(dfile) CDS_P4IPCBufferProcess(sprintf(nil "-i %s -c %s change -i" fname client)) when( rexMatchp("Change [0-9]+ created" CDS_IPCBuffer) cdata = parseString(CDS_IPCBuffer) cnum = cadr(cdata) return(cnum) ) error("Abort" "Failed to create change") ) ; ** prog ** ) ; ** procedure CDS_P4CreateChange ** procedure(CDS_P4BuildRevIntTable(lib bname) ;_Jun 29 01 sikand 251 prog(( openfile opfile pline dfile cdsspec cdata itype version cdes undo tfile lin xlin dspec matchcount reject dspecrex odspec odspecl cofile catdata tspec isopen efile ) CDS_P4IPCBufferProcess(sprintf(nil "-c %s client -o" CDS_P4GetClient(ddGetObj(lib)))) odspec = parseString(CDS_IPCBuffer) odspecl = nthelem(length(odspec)-1 odspec) dspecrex= substring(odspecl 1 strlen(odspecl)-3-strlen(lib)-1) openfile = strcat("/tmp/p4int." CDS_P4UserFileName) opfile = infile(openfile) while( gets(lin opfile) reject = nil xlin = parseString(lin) dspec = nthelem(5 xlin) tspec = nthelem(1 xlin) ;; should use the getcdspec routine here rexCompile(dspecrex) cofile = rexReplace(dspec "" 0) if( cofile == "opened" then isopen = t else isopen = nil ) matchcount = length(parseString(cofile "/")) catdata = "" when( matchcount == 2 && rexMatchp("Cat" lin) catdata = "(category)" ) when( matchcount == 2 && rexMatchp("prop.xx" lin) catdata = "(library property)" ) when( matchcount == 3 && rexMatchp("prop.xx" lin) catdata = "(cell property)" ) when( matchcount == 4 ;; only show the cdb objects in a view file when( !rexMatchp("\\.cdb" lin) reject = t ) catdata = "(cellview)" ) ; ** when matchcount ** unless( reject ;; make sure it's not opened ;;printf("running fstat for %s\n",tspec) ;; what's the easiest quietest way of checking to see ;; if a file exists efile = strcat("/tmp/p4exists." CDS_P4UserFileName) CDS_P4IPCDirectCommand(strcat("filelog " tspec " 2>&1 | grep -v 'no such file(s)' >/tmp/p4exists." CDS_P4UserFileName)) when( isFile(efile) when( fileLength(efile) > 0 deleteFile(efile) fstat = CDS_P4Fstat(tspec) when( fstat~>otherOpen0 != 'unbound hiGetAttention() warn("%s is opened for %s by %s\n", tspec fstat~>otherAction0 fstat~>otherOpen0) ;; mark the table CDS_P4IntTable["..."] = cons("P4INTFAIL" CDS_P4IntTable["..."]) ) ; ** when fstat ** ) ; ** when fileLength ** ) ; ** when isFile ** ;;println("Finished") ;; need to know more about these files ;; dspecrex is client dependent ;; need to get the client name ;; and then find it's mapping ;; on a file by file basis pline = parseString(lin) ;;tfile = car(parseString(car(pline) "#")) ;;tfile = car(parseString(nthelem(5 pline) "#")) tfile = nthelem(5 pline) ;; make sure that this is not part of an undo spec dfile = car(parseString(tfile "#")) version = car(reverse(parseString(tfile "#"))) itype = nthelem(3 pline) ;; build the data in lib format unless( isopen cdsspec = CDS_P4GetCdsSpec(tfile lib) rexCompile("/") cdata = sprintf(nil "(%s) %s %s" itype rexReplace(cdsspec " " 0) catdata) CDS_P4IntTable[cdata] = 1 unless( member(lib CDS_P4IntTable["..."]) CDS_P4IntTable["..."] = cons(lib CDS_P4IntTable["..."]) ) ) ; ** unless isopen ** ) ; ** unless reject ** ) ; ** while gets ** ) ; ** prog ** ) ; ** procedure CDS_P4BuildRevIntTable ** procedure(CDS_P4BuildIntTable(lib bname) ;_Nov 13 00 sikand 2896 prog(( openfile opfile pline intfile dfile defile change cnum version cdata lin reject xlin dspec odspec odspecl dspecrex cofile matchcount fstat status cdbcount viewcount) openfile = strcat("/tmp/p4int." CDS_P4UserFileName) CDS_P4IPCBufferProcess(sprintf(nil "-c %s client -o" CDS_P4GetClient(ddGetObj(lib)))) odspec = parseString(CDS_IPCBuffer) odspecl = nthelem(length(odspec)-1 odspec) dspecrex= substring(odspecl 1 strlen(odspecl)-3-strlen(lib)-1) viewcount = 0 cdbcount = 0 opfile = infile(openfile) while( gets(lin opfile) reject = nil xlin = parseString(lin) dspec = nthelem(1 xlin) rexCompile(dspecrex) cofile = rexReplace(dspec "" 0) matchcount = length(parseString(cofile "/")) when( matchcount == 4 ;; make sure atomics are consistent ;; also detect victims of old baseless merge bug ;; where integrate -i wasn't the default viewcount++ ;; only show the cdb objects in a view file when( !rexMatchp("\\.cdb" lin) reject = t ) when( rexMatchp("\\.cdb" lin) cdbcount++ ) ) ; ** when matchcount ** unless( reject fstat = CDS_P4Fstat(dspec) if( (fstat~>action != 'unbound || fstat~>otherAction0 != 'unbound || rexMatchp("already opened" lin)) then hiGetAttention() warn("%s is opened!\n" cofile) status = "FAIL" ;; mark the table CDS_P4IntTable["..."] = cons("P4INTFAIL" CDS_P4IntTable["..."]) else ;; dspecrex is client dependent ;; need to get the client name ;; and then find it's mapping ;; on a file by file basis pline = parseString(lin) ;;tfile = car(parseString(car(pline) "#")) intfile = nthelem(5 pline) dfile = parseString(intfile "#") defile = car(dfile) version = car(reverse(dfile)) ;; build the data in lib format ;;cdsspec = CDS_P4GetCdsSpec(tfile lib) ;; get the change ;; may be overkill change = CDS_P4GetChangeFromVersion(defile version t) unless( change error("Something went wrong in BuildIntTable\n") ) rexCompile("... #[0-9]+ c") cdata = rexReplace(change "C" 0) cdata = strcat(lib " :" cdata) cnum = nthelem(4 parseString(change)) CDS_P4IntTable[cnum] = cons(cdata CDS_P4IntTable[cnum]) unless( member(lib CDS_P4IntTable["..."]) CDS_P4IntTable["..."] = cons(lib CDS_P4IntTable["..."]) ) ) ; ** if fstat ** ) ; ** unless reject ** ) ; ** while gets ** when( cdbcount == 0 && viewcount > 0 CDS_ErrorDialogBox("P4 Interface" "Error: You are a victim of the baseless merge bug, call the doctor for a shot!\n") error("Call the doctor!") ) when( status == "FAIL" CDS_ErrorDialogBox("P4 Interface" "Error: Target files in the branch are opened for edit.\nCheck the CIW for the list.\n") ) ) ; ** prog ** ) ; ** procedure CDS_P4BuildIntTable ** procedure(CDS_P4IntegrateMessage() ;_Apr 19 00 sikand 500 ; get a message let((ckmessageform ckmessage) ckmessage = hiCreateStringField(?name 'ckmessage ?prompt "Description" ?value "" ) ckmessageform = hiCreateAppForm(?name 'ckmessageform ?fields '(ckmessage) ?formTitle "Integrate Description" ?buttonLayout 'OKCancel ) hiDisplayForm(ckmessageform) ckmessageform->ckmessage->value ) ; ** let ** ) ; ** procedure CDS_P4IntegrateMessage **