home *** CD-ROM | disk | FTP | other *** search
/ Fish 'n' More 2 / fishmore-publicdomainlibraryvol.ii1991xetec.iso / dirs / libtool_393.lzh / LibTool / LibTool.DOC < prev    next >
Text File  |  1990-10-28  |  19KB  |  398 lines

  1. LibTool:
  2.  
  3.  This is a program which takes an fd file (the calling specifications for a
  4. shared library) and outputs PRAGMA statements for the Manx or Lattice C
  5. compilers, the C glue code (instead of PRAGMAS), BMAP files for Basic
  6. programs, an asm or C INCLUDE file, and an asm module which can turn any C or
  7. asm code into a shared library. It allows you to develop and test functions in
  8. a stand alone program, and then easily and quickly convert the functions into
  9. a shared library, plus make all support files for your library. It also can
  10. aid the development of devices in C or asm.
  11.  
  12.   It is written entirely in 68000 for speed and small size (about 9.5K). It's
  13. a necessary tool for anyone writing a shared library as it generates code
  14. necessary to make the library, as well as all support files needed by
  15. applications using the library.
  16.  
  17.  
  18. «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
  19. 1) Usage:
  20.  
  21.  LibTool is meant to be used from the CLI. The args are as follows:
  22.  
  23. LibTool [-ibpschalmd] [-e extension] [-o out] fdname1...
  24.  
  25.  -i = include ##private functions within the fd file
  26.  -b = generate a Basic BMAP file instead of Glue, PRAGMAS, or INCLUDE files
  27.  -p = generate PRAGMAS instead of the C glue modules or BMAP
  28.  -s = scratch reg a6 in the C glue code (default = SAVE reg a6)
  29.  -c = setup glue, PRAGMAS, and libstartup code for a lib made of C functions
  30.  -l = generate Lattice style pragmas (default = MANX Pragmas)
  31.  -o = PRAGMA, BMAP, or combined glue filename
  32.  -m = generate lib startup code (.src asm module)
  33.  -a = generate asm INCLUDE file instead of PRAGMAS, glue, or BMAP
  34.  -h = generate C INCLUDE file
  35.  -d = make device startup code instead of library
  36.  -e = use an extension other than ".asm" for the C glue modules
  37.  
  38.  
  39. «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
  40. 2). Glue Modules
  41.  
  42.   By default, LibTool generates the C glue modules with which a C application
  43. must be linked in order to access functions in a shared library. It generates
  44. a 68000 asm code file for each function in the library. These files should each
  45. be assembled (with your C compiler's assembler), and the resulting objects
  46. should be linked with your C application. You only need link with those files
  47. with the same name as functions that you intend to call within the library.
  48. For example, if you made the glue modules from an fd file for Exec, you would
  49. end up with several dozen 68000 asm files. Among them would be such files as
  50. AllocMem.asm, FreeMem.asm, WaitPort.asm, etc. You need assemble and link only
  51. those Exec functions which you call in your application. The -e option allows
  52. you to specify a different extension than ".asm". For example,
  53.  
  54. LibTool -e 68K exec_lib.fd
  55.  
  56. would take the fd file, exec_lib.fd, and create files with such names as
  57. AllocMem.68K, FreeMem.68K, etc.
  58.   By default, register a6 is saved upon entry to the glue code, and restored
  59. upon exit. If your compiler generates code where a6 is not considered scratch,
  60. you'll want this feature. The later versions of both Manx and Lattice treat
  61. a6 as scratch across calls, so you can make for more efficient and smaller C
  62. glue code by using the -s option. For example, the glue code for AllocMem.asm
  63. without the -s option is:
  64.  
  65. _AllocMem
  66.     move.l   a6,-(sp)
  67.     movea.l  _SysBase,a6
  68.     movem.l  4(sp),d0/d1
  69.     jsr      _LVOAllocMem(a6)
  70.     movea.l  (sp)+,a6
  71.     rts
  72.  
  73. With the -s option:
  74.  
  75. _AllocMem
  76.     movea.l  _SysBase,a6
  77.     movem.l  4(sp),d0/d1
  78.     jmp      _LVOAllocMem(a6)
  79.  
  80.  
  81.   Besides eliminating 3 of the 6 instructions, it eliminates 1 level of rts
  82. (which otherwise incurs some processor overhead). You should experiment to
  83. see if your compiler won't choke on glue code made with the -s option.
  84.   The -o option should be followed by a filename. If you supply this filename,
  85. then instead of making separate files for each function in the library, one
  86. complete file will be made. If you intend upon using all the functions in a
  87. library, then this option can save you from dealing with dozens of separate
  88. modules. The separate modules are always written to the current directory,
  89. whereas the -o option allows for choosing the directory to write the glue file.
  90.  
  91.  
  92. «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
  93. 3). Pragmas
  94.  
  95.   LibTool will make PRAGMAS for Manx or Lattice compilers. Specifying the -p
  96. option causes the compiler to make one file with all the Pragma statements
  97. instead of any glue modules. The default style is for Manx PRAGMAS. Specifying
  98. the -l option causes Lattice style Pragmas to be output instead. This file
  99. should be INCLUDED in any C source that references functions in the library.
  100.   The -o option allows you to specify a filename for the Pragma file.
  101. Otherwise, a default filename is made from stripping the .fd extension from the
  102. source fd filename and appending ".pragma". For example,
  103.  
  104. LibTool -plo df0:MyPragmas exec_lib.fd
  105.  
  106. will make a Lattice Pragma file for the Exec library and place it on df0: as
  107. "MyPragmas".
  108.  
  109.  
  110. ««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
  111. 4). ##private functions
  112.  
  113.   The -i option allows glue modules and PRAGMA statements for any library
  114. functions that are flagged as private in the fd file. Otherwise, private
  115. functions are ignored (as they should be), except in the construction of BMAPS.
  116.  
  117.  
  118. ««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
  119. 5). Bmap files
  120.  
  121.   BMAP files allow basic programmers to use the library. Specifying the -b
  122. option causes LibTool to generate a BMAP file instead of PRAGMAS or glue
  123. modules. For example,
  124.  
  125. LibTool -b -o MyBmap exec_lib.fd
  126.  
  127. will generate a BMAP file of Exec called "MyBmap" in the current directory.
  128.   The program checks for the following known collisions between library names
  129. and AmigaBasic keywords:
  130.  
  131. abs, Close, Exit, Input, Open, Output, Read, tan, Translate, Wait, Write
  132.  
  133. If found, it prepends an x to the function name (i.e. "xRead" instead of
  134. "Read"), and posts a msg to the CLI.
  135.   Since AmigaBasic labels cannot have underscores, any underscores in a
  136. library function name are replaced by a period. An error msg will appear if
  137. this is the case, indicating the change.
  138.   Since AmigaBasic also cannot support a function which needs an argument
  139. passed in a5, an error msg will appear if this is the case. There is no way
  140. to call such a function from AmigaBasic.
  141.   The BMAP file always includes any ##private functions in the fd file.
  142.   The -o option allows the bmap file to be saved under any name. Otherwise,
  143. the .fd will be stripped from the source fd filename and ".bmap" appended.
  144.   Note that AmigaBasic requires the name of a BMAP file to be the name of the
  145. shared library minus its ".library" extension.
  146.   Also note that a library written in C (where args are expected on the stack)
  147. cannot be used by AmigaBasic.
  148.  
  149.  
  150. ««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
  151. 6). Calling a C shared library
  152.  
  153.   If you are developing a library whose functions are written in C, then your
  154. functions normally expect arguments on the stack. You have 2 choices for
  155. interfacing between a C application and such a library.
  156.  
  157.  1). Make reverse glue functions inside of your library that push args back
  158.      onto the stack and call the "real" C functions.
  159.  
  160.  2). Make glue routines for your application which do not pull args off of
  161.      the stack. (i.e. args are left on the stack and the lib function is
  162.      called).
  163.  
  164.   By specifying the -c option, LibTool will make pragmas or glue modules
  165. which implement the second method. Therefore, you can develop libraries
  166. written in C and not have to worry about passing args in registers at all.
  167. Your fd file will simply contain the names of the functions as they appear
  168. in the lib's function table. For example, assume we made a C library called
  169. "mylib.library" which has 2 functions in its function table:
  170.  
  171. void Func1();
  172. BYTE Func2();
  173.  
  174. Func2() expects 2 args.
  175.  
  176. An excerpt of your my_lib.fd file looks like this:
  177.  
  178. ##base MyBase  * this is the name of our lib base returned by OpenLibrary()
  179. ##bias 30
  180. ##public
  181. ##ret void
  182. Func1()
  183. ##ret BYTE
  184. Func2(arg1,arg2)
  185.  
  186. These would be C functions in your library which expect their arguments as
  187. usual (on the stack). 
  188.  
  189. You would create your c glue module, and lib startup code as so:
  190.  
  191. LibTool -cm -o mylib.asm my_lib.fd
  192.  
  193. Assemble the resulting file, mylib.asm and link this with your C application.
  194. Your C application would open the lib as so:
  195.  
  196.  MyBase = OpenLibrary("mylib.library",0L);
  197.  
  198. And you might call Func2() as so:
  199.  
  200.   returnval = Func2( arg1, arg2 );
  201.  
  202. Please note that the glue routines treat a6 as a scratch register.
  203.  
  204.   The -h option makes a C INCLUDE file for an application which simplifies
  205. opening and closing the library as well as declaring the returns of the lib
  206. functions. See the CSimple.DOC file for an explanation of how to make a C
  207. library and use these features. A default filename is made from stripping the
  208. .fd extension from the source fd filename and appending ".h".
  209.  
  210.  
  211. «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
  212. 7). Generating a library startup
  213.  
  214.  The -m option will generate an assembly module which when assembled and linked
  215. with any C or asm routines, will turn those routines into a shared library.
  216. You need to make an fd file describing the functions which you wish to make
  217. callable by any application. See the example library and instructions.
  218.   If your library is written in C (args on the stack), also specify -c option.
  219.   A default filename is made from stripping the .fd extension from the
  220. source fd filename and appending ".src".
  221.  
  222.  
  223. «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
  224. 8). Making an Asm INCLUDE file
  225.  
  226.  The -a option will make an INCLUDE file for asm language applications which
  227. wish to use the library. This file will contain _LVO labels for all of the
  228. callable functions in the library. Also, it will make an equate for the
  229. version number. The name of this symbol will be the library name (minus
  230. .library extention) plus the string VERSION. For example, if you had the
  231. following fd file, test.fd
  232.  
  233. ##name test.library
  234. ##bias 30
  235. ##vers 2
  236. Func1()
  237. ##end
  238.  
  239. and invoked LibTool as so
  240.  
  241. LibTool -a test.fd
  242.  
  243. then a file called "test.i" would be produced and it would contain
  244.  
  245. _LVOFunc1   equ -30
  246. testVERSION equ  2
  247.  
  248. A default filename is made from stripping the .fd extension from the
  249. source fd filename and appending ".i".
  250.  
  251.  
  252. «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
  253. 9). Devices
  254.  
  255.   Devices are very similiar to libraries with the following exceptions:
  256. Devices have only two functions in the function table, a BeginIO and an
  257. AbortIO function. These two functions are always passed just 1 argument; an
  258. initialized I/O block (a special structure allocated and initialized by the
  259. application). One of the fields in the IOB is the Command. The BeginIO and
  260. AbortIO functions must decipher the Command and dispatch to appropriate
  261. functions. These other functions will do various things with the other fields
  262. in the IOB. Essentially, all of your functions operate on this IOB. BeginIO is
  263. meant to initiate or control IO, and AbortIO deals with stopping IO previously
  264. begun. The only good reason for writing a device instead of a library is if you
  265. wish to spawn a task within your device to handle IO. Then, you can allow an
  266. application to "give" its IOB to that task (via the BeginIO function), and
  267. return immediately. The application does not have to wait for the IO to
  268. complete. An example of this is the trackdisk device. Often, after performing
  269. a Write(), your task will return before all of the data has been written to the
  270. disk. A task inside the trackdisk device is doing the work, not your
  271. application. Of course, you didn't have to deal with IO Blocks and the
  272. trackdisk device because AmigaDOS handled that for you.
  273.   One of the IOB fields is for Flags, and one flag is IO_QUICK. If IO_QUICK is
  274. set, this means that the application wants to return as quickly as possible. If
  275. quick IO is not possible, this means that "someone else" must take care of the
  276. IO so that the application can return immediately. The way that an application
  277. knows whether its IO was handled quickly (i.e. all done) or not quickly (i.e.
  278. somebody else is handling it and it isn't done yet), is by whether the IO_QUICK
  279. flag IS STILL SET UPON RETURN. If set, the IO was done. The application is now
  280. free to reuse the IOB or do something else. If clear, this means that the
  281. device's BeginIO function passed off the IOB to some other task. The appli-
  282. cation cannot use the IOB until it is returned. The device task returns the IOB
  283. by replying it to it's ReplyPort. The IOB's replyport address is obtained from
  284. the ReplyPort field of the IOB. It is up to the application to keep checking
  285. that replyport for the returned IOB if IO_QUICK did not occur.
  286.   So here is the interaction between a device and an application.
  287.  
  288.       APPLICATION                             DEVICE
  289.   1). Allocate an IOB, set up
  290.       a replyport for the IOB.
  291.   2). OpenDevice() with this IOB.        3). Device executes its Open routine.
  292.                                              Passed the IOB. Stuffs its base
  293.                                              address into the IOB's Device
  294.                                              field. May do other stuff. Clears
  295.                                              IOB's Error field if all went well.
  296.   4). If an OpenDevice error, goto #15.
  297.  
  298.   5). Setup the IOB's Command field, and
  299.       other fields as appropriate.
  300.  
  301.   6). Set IO_QUICK of Flags if you want to
  302.       return immediately. Call BeginIO.   7). Device's BeginIO recieves the
  303.                                               IOB. Check IO_QUICK. If set,
  304.                                               attempt to handle immediately. If
  305.                                               handled, return with IO_QUICK
  306.                                               still set and clear IOB's Error
  307.                                               field is all went well. If
  308.                                               IO_QUICK not set or not possible,
  309.                                               clear IO_QUICK and pass the IOB
  310.                                               to another task. Clear IOB's
  311.                                               Error if all went well and return.
  312.   8). Check IOB's Error. If not 0, then
  313.       an error. Skip to step #12. If clear,
  314.       all went well. Now, see if the
  315.       IO_QUICK flag is still set. If so,
  316.       all done. Skip to step #12. If
  317.       clear, no quick IO. Proceed.
  318.                                                
  319.  
  320.   9). Do something else if desired.         ->   The device's task is presently
  321.                                                  handling the IOB. When done,
  322.                                                  this task will ReplyMsg that
  323.                                                  IOB to its replyport. The IOB's
  324.                                                  Error field will be cleared if
  325.                                                  all went well.
  326.  
  327.   10). Check the IOB's replyport to
  328.       see if it is returned.
  329.       If nothing there, WaitPort.
  330.  
  331.  11). When you wake up, Remove() the IOB. (The
  332.       IOB has been returned). If its
  333.       Error field is zero, then all went well.
  334.  
  335.  12). The IOB can now be reused. If so, goto #5.
  336.  
  337.  13). CloseDevice()                         14). Device's Close routine called.
  338.                                                  Various things may be done.
  339.  
  340.  15). Free the IOB and its replyport.
  341.  
  342.   There are Exec functions (SendIO, DoIO, CheckIO) which an application can use
  343. to simplify calling a device's BeginIO function. Essentially, DoIO and SendIO
  344. both call the device's BeginIO. What these functions also do, is set up the
  345. IOB's Flags and Error field so that the app doesn't have to.
  346.   DoIO forces no quick IO. This is as if the app is telling the device:
  347.  
  348.  "Make sure that I don't return from BeginIO until that IOB is completely
  349.   taken care of. Put me to sleep if I have to wait for this to happen. I
  350.   don't have anything to do until that IOB is done. When I return from
  351.   DoIO, I expect either an error, or that IOB to be done successfully."
  352.  
  353.   Essentially DoIO() replaces steps 6,8,9,10 and 11 of the above procedure.
  354. DoIO returns the IOB's error field so that the app knows if all went well.
  355.  
  356. SendIO tries to do quick IO. This is like saying:
  357.  
  358.  "I want to return immediately whether that IO is done or not. Pass it off to
  359.   some other task if necessary and clear the IO_QUICK bit. I'm going to do
  360.   something else when I return, and later check if the IOB is done."
  361.  
  362. SendIO replaces step 6 of the above procedure. The Exec function CheckIO() is
  363. meant to be used in conjunction with SendIO(). CheckIO replaces step 10.
  364.  
  365.  DoIO is easier to use than SendIO, but doesn't allow the app to do something
  366. else while IO is in progress. An application will most likely never have to
  367. call a device's BeginIO directly. DoIO or SendIO are the proper vehicles. An
  368. exception to this is the audio device (which should have been a library
  369. anyway). Exec also has an AbortIO (which calls the device's actual AbortIO).
  370.  
  371.  By specifying the -d option, LibTool will make a startup code to be linked
  372. with your device code, turning it into a device. You must have two functions
  373. named BeginDev and AbortDev, which are the device's BeginIO and AbortIO
  374. vectors. These are passed the IOB (in a1 for asm programmers). For c code,
  375. also specify the -c option.
  376.  You'll definitely need to add ##open and ##clos vectors in order to initialize
  377. the IOB. These will be passed the IOB as above.
  378.  
  379.  LibTool makes no INCLUDE, pragma, or glue files for devices since you do not
  380. call the device's BeginIO and AbortIO directly.
  381.  
  382.  
  383. «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
  384. Final Notes
  385.  
  386.   You can do multiple fd conversions with LibTool at one invocation. Simply
  387. place the options before each filename. For example:
  388.  
  389. LibTool -po myPragma exec_lib.fd  -b dos_lib.fd  -a exec_lib.fd
  390.  
  391. will make a PRAGMA file from the Exec fd file called "MyPragma", then it will
  392. make a bmap file for the DOS fd file called "dos_lib.bmap", and finally make
  393. an asm INCLUDE file from the Exec fd file called "exec_lib.i"
  394.  
  395.   Do not do printf's within lib code. This is because there is no stdin or
  396. stdout handles for a library. Have your lib code return error values to the
  397. application instead, so that the application can do the printf.
  398.