home *** CD-ROM | disk | FTP | other *** search
- /*-----------------------------------------------------------------------
- genprags.lx - The primary purpose of this macro is to
- generate the alloc_text pragmas for initialization,
- termination, and static functions. If you have a command line
- REXX interpreter available, you can copy this file to genprags.cmd
- and run it from the command line. If this option is available it
- is recommended since this program can take a while and will lock
- up the edit session while it is running as a macro.
-
- The macro functions by generating and parsing the
- assembler code (-Fa) for all specified files. Static
- functions are identified because they have a PROC
- statement with no cooresponding PUBLIC statement.
- The static functions identified in this manner are
- searched for various tokens to determine the segment
- they should be placed in and the appropriate
- alloc_text pragmas generated.
-
- Requires as inout:
- wildCardFileName - files to process of the form '*.cpp'
-
- Generates as output:
- initprag.h
-
- Copyright (C) 1994, Law, Leong, Love, Olson, Tsuji.
- Copyright (c) 1997 John Wiley & Sons, Inc.
- -----------------------------------------------------------------------*/
-
- call RxFuncAdd 'SysLoadFuncs', 'RexxUtil', 'SysLoadFuncs'
- call SysLoadFuncs
-
- /* set up to run as either a macro or a command file */
- parse upper source osname . me
- me = strip(me)
- lastDot = lastPos('.', me)
- if substr(me, lastDot) = ".LX" then do
- isMacro = 1
- end
- else do
- isMacro = 0
- end
- if isMacro = 1 then do
- /* insure that message and messageline are on */
- 'extract messageLine into messageLineSetting'
- 'extract messages into messagesSetting'
- 'set messages on'
- 'set messageLine on'
- end
-
- /*
- Read and parse arguments
- */
- PARSE UPPER ARG wildCardFileName '(' optionsUpper
-
-
- kDebug = 0 /* set to 1 for debug info */
- if pos("DEBUG", optionsUpper) > 0 then kDebug = 1
-
- wildCardFileName = strip(wildCardFileName)
- if wildCardFileName = "" then
- wildCardFileName = "*.CPP"
-
- /*
- Initialize constants
- */
- publicString = "public"
- procString = "proc"
- extrnString = "extrn"
- kStaticWord = "static"
-
-
- rootDirectory = directory()
- assemblerFile = rootDirectory"\genprag$.asm"
- objectFile = rootDirectory"\genprag$.obj"
- OutFile = rootDirectory"\genprag$.out"
- pragmaFile = rootDirectory"\genprag$.h"
- filteredPragmaFile = rootDirectory"\initprag.h"
-
- InitSegment = "InitSegment"
- TermSegment = "TermSegment"
- StaticSegment = "StaticSegment"
-
- /*
- check for file already in ring
- */
- if isMacro = 1 then do
- 'EXTRACT DOCLIST'
- if doclist \= '' then
- 'EXTRACT DOCNUM INTO SAVEDOCNUM'
- else
- savedocnum = 0
- do while doclist \= ''
- parse var doclist docnum doclist
- 'GODOC DOCNUM 'docnum
- if rc <= 1 then do
- 'EXTRACT NAME into currentDocName'
- if translate(currentDocName) = translate(filteredPragmaFile) then
- 'qquit'
- end
- end
- if savedocnum \= 0 then
- 'GODOC DOCNUM 'savedocnum
- end
-
- if stream(pragmaFile,'C','QUERY EXIST')<>'' then
- call osCmd '@DEL 'pragmaFile
-
-
- /*
- Write a prolog to the output file
- */
- rc = lineOut(pragmaFile, "// Generated by "me )
- rc = lineOut(pragmaFile, "// Arguments were "wildCardFileName )
- rc = lineOut(pragmaFile, " " )
-
-
- /*
- Collect a list of the files to process
- */
- cppFiles. = 0
- if kDebug = 1 then
- call sayErr 'wildCardFileName='wildCardFileName
- rc=SysFileTree(wildCardFileName,'cppFiles','FO','*****')
-
- /*
- Process each CPP file
- */
- do fileNumber=1 TO cppFiles.0
- call refreshDisplay
- call sayErr "Processing file "fileNumber" of "cppFiles.0" ("cppFiles.fileNumber")"
- /* Erase the assembler file and create the next one */
- if stream(assemblerFile,'C','QUERY EXIST')<>'' then
- call osCmd '@DEL 'assemblerFile
- iccOptions = "-c -Ft- -O+ -W2 -Q+ -Gm+ -Gd+"
- if 0 \= osCmd( '@ICC' iccOptions '-Fa'assemblerFile '-Fo'objectFile cppFiles.fileNumber' > 'outFile ) then do
- call sayErr "ICC failed"
- if isMacro = 1 then
- 'lx 'outFile
- else
- call osCmd 'type 'outFile
- exit 1
- end
-
- /*
- Build a table of public symbols from the assembler file.
- */
- filePublics. = 0
- call SysFileSearch publicString, assemblerFile, 'filePublics', 'C'
- if kDebug = 1 then do
- call sayErr "FilePublics.0 = "filePublics.0
- call refreshDisplay
- end
- publicList. = 0
- do j=1 to filePublics.0
- filePublics.j = translate(filePublics.j, ' ', '09'x) /* remove tabs */
- parse var filePublics.j publicKeyword function
- if kDebug = 1 then
- call sayErr "PUBLIC: " publicKeyword function
- /* We want the statements of the form */
- /* public __functionName */
- /* but not segment declarations and such. */
- if strip(publicKeyword) = publicString then do
- publicList.0 = publicList.0 + 1
- currentPublic = publicList.0
- publicList.currentPublic = strip(function)
- end /* if */
- end /* do */
-
-
- /*
- Build a table of procedures ("proc", both public & static).
- */
- fileProcs. = 0
- call SysFileSearch procString, assemblerFile, 'fileProcs', 'C'
- procList. = 0
- do j=1 to fileProcs.0
- fileProcs.j = translate(fileProcs.j, ' ', '09'x)
- parse value fileProcs.j with fileProcs.j ";" comment
- /* The following logic attempts to eliminate lines that get
- included that are not "proc" statements (e.g. lines with
- words like "process").
- */
- if words(fileProcs.j) = 2 & word(fileProcs.j,2) = procString then do
- procList.0 = procList.0 + 1
- currentProc = procList.0
- procList.currentProc = strip(word(fileProcs.j,1))
- if kDebug = 1 then
- call sayErr "PROC: "fileProcs.j
- end /* if */
- end /* do */
-
- /*
- Flag the functions in the procList as being PUBLIC or
- STATIC (STATICS are in the procList but not the publicList).
- */
- staticsFound = 0
- do j=1 to procList.0
- found = 0
- do k=1 to publicList.0 while found = 0
- if procList.j = publicList.k then do
- found = 1
- procList.j.scope = publicString
- end
- end /* do */
- /* Not found in public list so must be a static */
- if found = 0 then do
- procList.j.scope = kStaticWord
- staticsFound = 1
- end /* if */
- end /* do */
-
- /*
- Determine the alloc_text pragmas for functions meeting
- one of the criteria.
- */
- if staticsFound = 1 then do
- /* Determine the File Name and write an #ifdef for it */
- cppOffset = pos('.', cppFiles.fileNumber)
- lastSlash = lastPos('\', cppFiles.fileNumber)
- cppNameLength = cppOffset - lastSlash -1
- cppFileName = substr(cppFiles.fileNumber, lastSlash+1, cppNameLength)
- rc = lineOut(pragmaFile, "#ifdef _"||translate(cppFileName)||"_CPP_")
-
- /* Now dump out the segment definitions for Statics */
- do procNumber=1 to procList.0
- if procList.procNumber.scope = kStaticWord then do
- writePragma = 1
- outBuffer = "#pragma alloc_text("
- /* Do not write out Exception Functions because */
- /* they are in EH_CODE already. */
- if pos("__dftdt", procList.procNumber) > 0 | ,
- pos("__dftbdt", procList.procNumber) > 0 then
- writePragma = 0
- if pos("__dftct", procList.procNumber) > 0 then
- outBuffer = outbuffer||StaticSegment
- /* Write out Initialization functions */
- else if pos("__sinit", procList.procNumber) > 0 then
- outBuffer = outbuffer||InitSegment
- /* Write out termination functions */
- else if pos("__sterm", procList.procNumber) > 0 then
- outBuffer = outbuffer||TermSegment
- else
- outBuffer = outbuffer||StaticSegment
-
- outBuffer = outBuffer||"," procList.procNumber||")"
- if writePragma = 1 then
- rc = lineOut(pragmaFile, outBuffer)
- end
- end /* do procNumber */
-
- rc = lineOut(pragmaFile, "#endif")
- rc = lineOut(pragmaFile, "")
- end /* do staticsExist */
- end /* do fileNumber */
- rc = stream(pragmaFile, 'C', 'close')
-
- /*
- Use CPPFILT on the pragma file
- */
- call oscmd '@CPPFILT /q' pragmaFile ' > ' filteredPragmaFile
-
- /* cleanup temporary files */
- if kDebug = 0 then do
- if stream(assemblerFile,'C','QUERY EXIST')<>'' then
- call osCmd '@DEL 'assemblerFile
- if stream(objectFile,'C','QUERY EXIST')<>'' then
- call osCmd '@DEL 'objectFile
- if stream(outFile,'C','QUERY EXIST')<>'' then
- call osCmd '@DEL 'OutFile
- if stream(pragmaFile,'C','QUERY EXIST')<>'' then
- call osCmd '@DEL 'pragmaFile
- end
-
- /* restore previous settings and view the results if a macro */
- if isMacro = 1 then do
- 'set messageLine 'messageLineSetting
- 'set messages 'messagesSetting
- 'lx 'filteredPragmaFile
- end
-
- exit 0
-
- /* Utility function to call a system function */
- oscmd:
- parse arg theCmd
-
- if pos('@', theCmd) \= 1 | kDebug \= 0 then
- call sayErr theCmd
- if pos('@', theCmd) = 1 then
- Address 'CMD' substr(theCmd, 2)
- else
- Address 'CMD' theCmd
- return rc
-
- /* Utility function to write error message */
- sayErr:
- procedure expose isMacro
- parse arg theString
- if isMacro = 1 then
- 'msg 'theString
- else
- say theString
- call refreshDisplay
- return
-
- /* Utility function to update the display */
- refreshDisplay:
- procedure expose isMacro
- if isMacro = 1 then
- 'sshow'
- return
-