home *** CD-ROM | disk | FTP | other *** search
/ Power GUI Programming with VisualAge C++ / powergui.iso / powergui / shipapp / genprags / genprags.cmd next >
OS/2 REXX Batch file  |  1996-10-29  |  10KB  |  314 lines

  1. /*-----------------------------------------------------------------------
  2.    genprags.lx  - The primary purpose of this macro is to
  3.       generate the alloc_text pragmas for initialization,
  4.       termination, and static functions.   If you have a command line
  5.       REXX interpreter available, you can copy this file to genprags.cmd
  6.       and run it from the command line.   If this option is available it
  7.       is recommended since this program can take a while and will lock
  8.       up the edit session while it is running as a macro.
  9.  
  10.       The macro functions by generating and parsing the
  11.       assembler code (-Fa) for all specified files. Static
  12.       functions are identified because they have a PROC
  13.       statement with no cooresponding PUBLIC statement.
  14.       The static functions identified in this manner are
  15.       searched for various tokens to determine the segment
  16.       they should be placed in and the appropriate
  17.       alloc_text pragmas generated.
  18.  
  19.    Requires as inout:
  20.     wildCardFileName   - files to process of the form '*.cpp'
  21.  
  22.    Generates as output:
  23.     initprag.h
  24.  
  25.  
  26.   Copyright (C) 1994, Law, Leong, Love, Olson, Tsuji.
  27.   Copyright (c) 1997 John Wiley & Sons, Inc. 
  28. -----------------------------------------------------------------------*/
  29.  
  30. call RxFuncAdd 'SysLoadFuncs', 'RexxUtil', 'SysLoadFuncs'
  31. call SysLoadFuncs
  32.  
  33. /* set up to run as either a macro or a command file */
  34. parse upper source osname . me
  35. me = strip(me)
  36. lastDot = lastPos('.', me)
  37. if substr(me, lastDot) = ".LX" then do
  38.    isMacro = 1
  39. end
  40. else do
  41.    isMacro = 0
  42. end
  43. if isMacro = 1 then do
  44.   /* insure that message and messageline are on */
  45.   'extract messageLine into messageLineSetting'
  46.   'extract messages    into messagesSetting'
  47.   'set messages    on'
  48.   'set messageLine on'
  49. end
  50.  
  51. /*
  52.   Read and parse arguments
  53. */
  54. PARSE UPPER ARG wildCardFileName  '(' optionsUpper
  55.  
  56.  
  57. kDebug = 0     /* set to 1 for debug info */
  58. if pos("DEBUG", optionsUpper) > 0 then kDebug = 1
  59.  
  60. wildCardFileName = strip(wildCardFileName)
  61. if wildCardFileName = "" then
  62.   wildCardFileName = "*.CPP"
  63.  
  64. /*
  65.   Initialize constants
  66. */
  67. publicString = "public"
  68. procString   = "proc"
  69. extrnString  = "extrn"
  70. kStaticWord  = "static"
  71.  
  72.  
  73. rootDirectory      = directory()
  74. assemblerFile      = rootDirectory"\genprag$.asm"
  75. objectFile         = rootDirectory"\genprag$.obj"
  76. OutFile            = rootDirectory"\genprag$.out"
  77. pragmaFile         = rootDirectory"\genprag$.h"
  78. filteredPragmaFile = rootDirectory"\initprag.h"
  79.  
  80. InitSegment      = "InitSegment"
  81. TermSegment      = "TermSegment"
  82. StaticSegment    = "StaticSegment"
  83.  
  84. /*
  85.  check for file already in ring
  86. */
  87. if isMacro = 1 then do
  88.   'EXTRACT DOCLIST'
  89.   if doclist \= '' then
  90.      'EXTRACT DOCNUM INTO SAVEDOCNUM'
  91.   else
  92.      savedocnum = 0
  93.   do while doclist \= ''
  94.      parse var doclist docnum doclist
  95.      'GODOC DOCNUM 'docnum
  96.      if rc <= 1 then do
  97.        'EXTRACT NAME into currentDocName'
  98.        if translate(currentDocName) = translate(filteredPragmaFile) then
  99.           'qquit'
  100.      end
  101.   end
  102.   if savedocnum \= 0 then
  103.      'GODOC DOCNUM 'savedocnum
  104. end
  105.  
  106. if stream(pragmaFile,'C','QUERY EXIST')<>'' then
  107.    call osCmd '@DEL 'pragmaFile
  108.  
  109.  
  110. /*
  111.   Write a prolog to the output file
  112. */
  113. rc = lineOut(pragmaFile, "// Generated by "me )
  114. rc = lineOut(pragmaFile, "// Arguments were "wildCardFileName  )
  115. rc = lineOut(pragmaFile, " " )
  116.  
  117.  
  118. /*
  119.   Collect a list of the files to process
  120. */
  121. cppFiles. = 0
  122. if kDebug = 1 then
  123.   call sayErr 'wildCardFileName='wildCardFileName
  124. rc=SysFileTree(wildCardFileName,'cppFiles','FO','*****')
  125.  
  126. /*
  127.   Process each CPP file
  128. */
  129. do fileNumber=1 TO cppFiles.0
  130.   call refreshDisplay
  131.   call sayErr "Processing file "fileNumber" of "cppFiles.0" ("cppFiles.fileNumber")"
  132.   /* Erase the assembler file and create the next one */
  133.   if stream(assemblerFile,'C','QUERY EXIST')<>'' then
  134.      call osCmd '@DEL 'assemblerFile
  135.   iccOptions = "-c -Ft- -O+ -W2 -Q+ -Gm+ -Gd+"
  136.   if 0 \= osCmd( '@ICC' iccOptions '-Fa'assemblerFile '-Fo'objectFile  cppFiles.fileNumber' > 'outFile ) then do
  137.      call sayErr "ICC failed"
  138.      if isMacro = 1 then
  139.         'lx 'outFile
  140.      else
  141.         call osCmd 'type 'outFile
  142.      exit 1
  143.   end
  144.  
  145.   /*
  146.      Build a table of public symbols from the assembler file.
  147.   */
  148.   filePublics. = 0
  149.   call SysFileSearch publicString, assemblerFile, 'filePublics', 'C'
  150.   if kDebug = 1 then do
  151.      call sayErr "FilePublics.0 = "filePublics.0
  152.      call refreshDisplay
  153.   end
  154.   publicList. = 0
  155.   do j=1 to filePublics.0
  156.      filePublics.j = translate(filePublics.j, ' ', '09'x)   /* remove tabs */
  157.      parse var  filePublics.j publicKeyword function
  158.      if kDebug = 1 then
  159.        call sayErr "PUBLIC: " publicKeyword function
  160.      /* We want the statements of the form                        */
  161.      /* public  __functionName                                    */
  162.      /* but not segment declarations and such.                    */
  163.      if strip(publicKeyword) = publicString  then do
  164.         publicList.0 = publicList.0 + 1
  165.         currentPublic = publicList.0
  166.         publicList.currentPublic = strip(function)
  167.      end  /* if */
  168.   end  /* do */
  169.  
  170.  
  171.   /*
  172.      Build a table of procedures ("proc", both public & static).
  173.   */
  174.   fileProcs. = 0
  175.   call SysFileSearch procString, assemblerFile, 'fileProcs', 'C'
  176.   procList.  = 0
  177.   do j=1 to fileProcs.0
  178.      fileProcs.j = translate(fileProcs.j, ' ', '09'x)
  179.      parse value fileProcs.j with fileProcs.j ";" comment
  180.      /* The following logic attempts to eliminate lines that get
  181.         included that are not "proc" statements (e.g. lines with
  182.         words like "process").
  183.      */
  184.      if words(fileProcs.j) = 2 & word(fileProcs.j,2) = procString then do
  185.         procList.0 = procList.0 + 1
  186.         currentProc = procList.0
  187.         procList.currentProc = strip(word(fileProcs.j,1))
  188.         if kDebug = 1 then
  189.           call sayErr "PROC: "fileProcs.j
  190.      end  /* if */
  191.   end /* do */
  192.  
  193.   /*
  194.      Flag the functions in the procList as being PUBLIC or
  195.      STATIC (STATICS are in the procList but not the publicList).
  196.   */
  197.   staticsFound = 0
  198.   do j=1 to procList.0
  199.      found = 0
  200.      do k=1 to publicList.0 while found = 0
  201.         if procList.j = publicList.k then do
  202.            found = 1
  203.            procList.j.scope = publicString
  204.         end
  205.      end  /* do */
  206.      /* Not found in public list so must be a static */
  207.      if found = 0 then do
  208.        procList.j.scope = kStaticWord
  209.        staticsFound = 1
  210.      end /* if */
  211.   end /* do */
  212.  
  213.   /*
  214.      Determine the alloc_text pragmas for functions meeting
  215.      one of the criteria.
  216.   */
  217.   if staticsFound = 1 then do
  218.     /* Determine the File Name and write an #ifdef for it */
  219.     cppOffset = pos('.', cppFiles.fileNumber)
  220.     lastSlash = lastPos('\', cppFiles.fileNumber)
  221.     cppNameLength = cppOffset - lastSlash -1
  222.     cppFileName = substr(cppFiles.fileNumber, lastSlash+1, cppNameLength)
  223.     rc = lineOut(pragmaFile, "#ifdef _"||translate(cppFileName)||"_CPP_")
  224.  
  225.     /* Now dump out the segment definitions for Statics  */
  226.     do procNumber=1 to procList.0
  227.       if procList.procNumber.scope = kStaticWord then do
  228.          writePragma = 1
  229.          outBuffer = "#pragma alloc_text("
  230.          /* Do not write out Exception Functions because  */
  231.          /* they are in EH_CODE already.                  */
  232.          if pos("__dftdt", procList.procNumber) > 0   | ,
  233.             pos("__dftbdt", procList.procNumber) > 0  then
  234.            writePragma = 0
  235.          if pos("__dftct", procList.procNumber) > 0 then
  236.            outBuffer = outbuffer||StaticSegment
  237.          /* Write out Initialization functions */
  238.          else if pos("__sinit", procList.procNumber) > 0  then
  239.            outBuffer = outbuffer||InitSegment
  240.          /* Write out termination functions */
  241.          else if pos("__sterm", procList.procNumber) > 0 then
  242.            outBuffer = outbuffer||TermSegment
  243.          else
  244.            outBuffer = outbuffer||StaticSegment
  245.  
  246.          outBuffer = outBuffer||"," procList.procNumber||")"
  247.          if writePragma = 1 then
  248.            rc = lineOut(pragmaFile, outBuffer)
  249.       end
  250.     end /* do procNumber */
  251.  
  252.     rc = lineOut(pragmaFile, "#endif")
  253.     rc = lineOut(pragmaFile, "")
  254.   end /* do staticsExist */
  255. end /* do fileNumber */
  256. rc = stream(pragmaFile, 'C', 'close')
  257.  
  258. /*
  259.   Use CPPFILT on the pragma file
  260. */
  261. call oscmd '@CPPFILT /q' pragmaFile ' > ' filteredPragmaFile
  262.  
  263. /* cleanup temporary files */
  264. if kDebug = 0 then do
  265.   if stream(assemblerFile,'C','QUERY EXIST')<>'' then
  266.      call osCmd '@DEL 'assemblerFile
  267.   if stream(objectFile,'C','QUERY EXIST')<>'' then
  268.      call osCmd '@DEL 'objectFile
  269.   if stream(outFile,'C','QUERY EXIST')<>'' then
  270.      call osCmd '@DEL 'OutFile
  271.   if stream(pragmaFile,'C','QUERY EXIST')<>'' then
  272.      call osCmd '@DEL 'pragmaFile
  273. end
  274.  
  275. /* restore previous settings and view the results if a macro */
  276. if isMacro = 1 then do
  277.   'set messageLine 'messageLineSetting
  278.   'set messages    'messagesSetting
  279.   'lx 'filteredPragmaFile
  280. end
  281.  
  282. exit 0
  283.  
  284. /* Utility function to call a system function */
  285. oscmd:
  286.   parse arg theCmd
  287.  
  288.   if pos('@', theCmd) \= 1 | kDebug \= 0 then
  289.     call sayErr theCmd
  290.   if pos('@', theCmd) = 1 then
  291.     Address 'CMD' substr(theCmd, 2)
  292.   else
  293.     Address 'CMD' theCmd
  294.   return rc
  295.  
  296. /* Utility function to write error message    */
  297. sayErr:
  298. procedure expose isMacro
  299. parse arg theString
  300. if isMacro = 1 then
  301.    'msg 'theString
  302. else
  303.    say theString
  304. call refreshDisplay
  305. return
  306.  
  307. /* Utility function to update the display     */
  308. refreshDisplay:
  309. procedure expose isMacro
  310. if isMacro = 1 then
  311.    'sshow'
  312. return
  313.  
  314.