Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Cherrypick [9b960af129], was supposed to have been checked into trunk in the first place |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
bbafc013aa7348f836ccdbfd0c8935da |
User & Date: | andygoth 2016-11-04 23:18:01 |
Context
2016-11-04
| ||
23:57 | Use linenoise for fossil shell. Do not bother with persistent history. check-in: 6327b026 user: andygoth tags: trunk | |
23:18 | Cherrypick [9b960af129], was supposed to have been checked into trunk in the first place check-in: bbafc013 user: andygoth tags: trunk | |
23:13 | Fix various typos in makeheaders.html. Use curly quotes instead of classic `` and '' quotes (ref: http://www.dwheeler.com/essays/quotes-in-html.html). Format most such quoted text in monospace print. check-in: 9b960af1 user: andygoth tags: andygoth-timeline-ms | |
22:37 | Consistently use the count(X) macro in place of sizeof(X)/sizeof(*X) throughout the Fossil core, excluding things that don't use makeheaders. Also use count(X) instead of ArraySize(X) which has the same definition. check-in: e5b62edb user: andygoth tags: trunk | |
Changes
Changes to src/makeheaders.html.
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 .. 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 .. 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 ... 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 ... 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 ... 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 ... 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 ... 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 ... 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 ... 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 ... 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 ... 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 ... 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 ... 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 ... 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 ... 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 ... 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 ... 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 ... 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 ... 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 ... 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 ... 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 ... 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 ... 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 ... 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 |
<head><title>The Makeheaders Program</title></head> <body bgcolor=white> <h1 align=center>The Makeheaders Program</h1> <p> This document describes <em>makeheaders</em>, a tool that automatically generates ``<code>.h</code>'' files for a C or C++ programming project. </p> <h2>Table Of Contents</h2> <ul> ................................................................................ <p> Declarations in C include things such as the following: <ul> <li> Typedefs. <li> Structure, union and enumeration declarations. <li> Function and procedure prototypes. <li> Preprocessor macros and #defines. <li> ``extern'' variable declarations. </ul> </p> <p> Definitions in C, on the other hand, include these kinds of things: <ul> <li> Variable definitions. ................................................................................ modern software engineering. Another way of looking at the difference is that the declaration is the <em>interface</em> and the definition is the <em>implementation</em>. </p> <p> In C programs, it has always been the tradition that declarations are put in files with the ``<code>.h</code>'' suffix and definitions are placed in ``<code>.c</code>'' files. The .c files contain ``<code>#include</code>'' preprocessor statements that cause the contents of .h files to be included as part of the source code when the .c file is compiled. In this way, the .h files define the interface to a subsystem and the .c files define how the subsystem is implemented. </p> <a name="H0003"></a> ................................................................................ into the file of your choice. </p> <p> A similar option is -H. Like the lower-case -h option, big -H generates a single include file on standard output. But unlike small -h, the big -H only emits prototypes and declarations that have been designated as ``exportable''. The idea is that -H will generate an include file that defines the interface to a library. More will be said about this in section 3.4. </p> <p> Sometimes you want the base name of the .c file and the .h file to ................................................................................ If you want a particular file to be scanned by makeheaders but you don't want makeheaders to generate a header file for that file, then you can supply an empty header filename, like this: <pre> makeheaders alpha.c beta.c gamma.c: </pre> In this example, makeheaders will scan the three files named ``alpha.c'', ``beta.c'' and ``gamma.c'' but because of the colon on the end of third filename it will only generate headers for the first two files. Unfortunately, it is not possible to get makeheaders to process any file whose name contains a colon. </p> <p> In a large project, the length of the command line for makeheaders can become very long. If the operating system doesn't support long command lines (example: DOS and Win32) you may not be able to list all of the input files in the space available. In that case, you can use the ``-f'' option followed by the name of a file to cause makeheaders to read command line options and filename from the file instead of from the command line. For example, you might prepare a file named ``mkhdr.dat'' that contains text like this: <pre> src/alpha.c:hdr/alpha.h src/beta.c:hdr/beta.h src/gamma.c:hdr/gamma.h ... </pre> ................................................................................ Then invoke makeheaders as follows: <pre> makeheaders -f mkhdr.dat </pre> </p> <p> The ``-local'' option causes makeheaders to generate of prototypes for ``static'' functions and procedures. Such prototypes are normally omitted. </p> <p> Finally, makeheaders also includes a ``-doc'' option. This command line option prevents makeheaders from generating any headers at all. Instead, makeheaders will write to standard output information about every definition and declaration that it encounters in its scan of source files. The information output includes the type of the definition or declaration and any comment that preceeds the definition or ................................................................................ documentation about the program. We'll talk more about this feature later. </p> <p> If you forget what command line options are available, or forget their exact name, you can invoke makeheaders using an unknown command line option (like ``--help'' or ``-?'') and it will print a summary of the available options on standard error. If you need to process a file whose name begins with ``-'', you can prepend a ``./'' to its name in order to get it accepted by the command line parser. Or, you can insert the special option ``--'' on the command line to cause all subsequent command line arguments to be treated as filenames even if their names beginn with ``-''. </p> <a name="H0006"></a> <h2>3.0 Preparing Source Files For Use With Makeheaders</h2> <p> Very little has to be done to prepare source files for use with ................................................................................ This section will describe several typical uses of makeheaders. </p> <a name="H0007"></a> <h3>3.1 The Basic Setup</h3> <p> The simpliest way to use makeheaders is to put all definitions in one or more .c files and all structure and type declarations in separate .h files. The only restriction is that you should take care to chose basenames for your .h files that are different from the basenames for you .c files. Recall that if your .c file is named (for example) ``alpha.c'' makeheaders will attempt to generate a corresponding header file named ``alpha.h''. For that reason, you don't want to use that name for any of the .h files you write since that will prevent makeheaders from generating the .h file automatically. </p> <p> The structure of a .c file intented for use with makeheaders is very simple. All you have to do is add a single ``#include'' to the top of the file that sources the header file that makeheaders will generate. Hence, the beginning of a source file named ``alpha.c'' might look something like this: </p> <pre> /* * Introductory comment... */ ................................................................................ /* The rest of your code... */ </pre> <p> Your manually generated header files require no special attention at all. Code them as you normally would. However, makeheaders will work better if you omit the ``#if'' statements people often put around the outside of header files that prevent the files from being included more than once. For example, to create a header file named ``beta.h'', many people will habitually write the following: <pre> #ifndef BETA_H #define BETA_H /* declarations for beta.h go here */ ................................................................................ You can forego this cleverness with makeheaders. Remember that the header files you write will never really be included by any C code. Instead, makeheaders will scan your header files to extract only those declarations that are needed by individual .c files and then copy those declarations to the .h files corresponding to the .c files. Hence, the ``#if'' wrapper serves no useful purpose. But it does make makeheaders work harder, forcing it to put the statements <pre> #if !defined(BETA_H) #endif </pre> ................................................................................ manually written .h files and then automatically generate .h files corresponding to all .c files. </p> <p> Note that the wildcard expression used in the above example, ``<code>*.[ch]</code>'', will expand to include all .h files in the current directory, both those entered manually be the programmer and others generated automatically by a prior run of makeheaders. But that is not a problem. The makeheaders program will recognize and ignore any files it has previously generated that show up on its input list. </p> ................................................................................ <ul> <p><li> When a function is defined in any .c file, a prototype of that function is placed in the generated .h file of every .c file that calls the function.</p> <P>If the ``static'' keyword of C appears at the beginning of the function definition, the prototype is suppressed. If you use the ``LOCAL'' keyword where you would normally say ``static'', then a prototype is generated, but it will only appear in the single header file that corresponds to the source file containing the function. For example, if the file <code>alpha.c</code> contains the following: <pre> LOCAL int testFunc(void){ return 0; } ................................................................................ <pre> #define LOCAL static LOCAL int testFunc(void); </pre> However, no other generated header files will contain a prototype for <code>testFunc()</code> since the function has only file scope.</p> <p>When the ``LOCAL'' keyword is used, makeheaders will also generate a #define for LOCAL, like this: <pre> #define LOCAL static </pre> so that the C compiler will know what it means.</p> <p>If you invoke makeheaders with a ``-local'' command-line option, then it treats the ``static'' keyword like ``LOCAL'' and generates prototypes in the header file that corresponds to the source file containing the function defintiion.</p> <p><li> When a global variable is defined in a .c file, an ``extern'' declaration of that variable is placed in the header of every .c file that uses the variable. </p> <p><li> When a structure, union or enumeration declaration or a function prototype or a C++ class declaration appears in a ................................................................................ those files and are not copied. </p> <p><li> When a structure, union or enumeration declaration appears in a .h file, makeheaders will automatically generate a typedef that allows the declaration to be referenced without the ``struct'', ``union'' or ``enum'' qualifier. In other words, if makeheaders sees the code: <pre> struct Examp { /* ... */ }; </pre> it will automatically generate a corresponding typedef like this: <pre> typedef struct Examp Examp; ................................................................................ The .h files are suppose to contain only interface, not implementation. C compilers will not enforce this convention, but makeheaders does. </ul> <p> As a final note, we observe that automatically generated declarations are ordered as required by the ANSI-C programming language. If the declaration of some structure ``X'' requires a prior declaration of another structure ``Y'', then Y will appear first in the generated headers. </p> <a name="H0009"></a> <h3>3.3 How To Avoid Having To Write Any Header Files</h3> <p> In my experience, large projects work better if all of the manually ................................................................................ You can instruct makeheaders to treat any part of a .c file as if it were a .h file by enclosing that part of the .c file within: <pre> #if INTERFACE #endif </pre> Thus any structure definitions that appear after the ``#if INTERFACE'' but before the corresponding ``#endif'' are eligable to be copied into the automatically generated .h files of other .c files. </p> <p> If you use the ``#if INTERFACE'' mechanism in a .c file, then the generated header for that .c file will contain a line like this: <pre> #define INTERFACE 0 </pre> In other words, the C compiler will never see any of the text that defines the interface. ................................................................................ putting the declarations in the correct ANSI-C order -- makeheaders will do that for you automatically. </p> <p> Note that you don't have to use this approach exclusively. You can put some declarations in .h files and others within the ``#if INTERFACE'' regions of .c files. Makeheaders treats all declarations alike, no matter where they come from. You should also note that a single .c file can contain as many ``#if INTERFACE'' regions as desired. </p> <a name="H0010"></a> <h3>3.4 Designating Declarations For Export</h3> <p> In a large project, one will often construct a hierarchy of ................................................................................ (The second interface is normally a subset of the first.) Ordinary C does not provide support for a tiered interface like this, but makeheaders does. </p> <p> Using makeheaders, it is possible to designate routines and data structures as being for ``export''. Exported objects are visible not only to other files within the same library or subassembly but also to other libraries and subassemblies in the larger program. By default, makeheaders only makes objects visible to other members of the same library. </p> ................................................................................ This is not a perfect solution, but it works well in practice. </p> <p> But trouble quickly arises when we attempt to devise a mechanism for telling makeheaders which prototypes it should export and which it should keep local. The built-in ``static'' keyword of C works well for prohibiting prototypes from leaving a single source file, but because C doesn't support a linkage hierarchy, there is nothing in the C language to help us. We'll have to invite our own keyword: ``EXPORT'' </p> <p> Makeheaders allows the EXPORT keyword to precede any function or procedure definition. The routine following the EXPORT keyword is then eligable to appear in the header file generated using the -H command line option. ................................................................................ are visible to all files within the library, any declarations or definitions within <pre> #if EXPORT_INTERFACE #endif </pre> will become part of the exported interface. The ``#if EXPORT_INTERFACE'' mechanism can be used in either .c or .h files. (The ``#if INTERFACE'' can also be used in both .h and .c files, but since it's use in a .h file would be redundant, we haven't mentioned it before.) </p> <a name="H0011"></a> <h3>3.5 Local declarations processed by makeheaders</h3> <p> Structure declarations and typedefs that appear in .c files are normally ignored by makeheaders. Such declarations are only intended for use by the source file in which they appear and so makeheaders doesn't need to copy them into any generated header files. We call such declarations ``private''. </p> <p> Sometimes it is convenient to have makeheaders sort a sequence of private declarations into the correct order for us automatically. Or, we could have static functions and procedures for which we would like makeheaders to generate prototypes, but the arguments to these ................................................................................ <p> When this situation arises, enclose the private declarations within <pre> #if LOCAL_INTERFACE #endif </pre> A ``LOCAL_INTERFACE'' block works very much like the ``INTERFACE'' and ``EXPORT_INTERFACE'' blocks described above, except that makeheaders insures that the objects declared in a LOCAL_INTERFACE are only visible to the file containing the LOCAL_INTERFACE. </p> <a name="H0012"></a> <h3>3.6 Using Makeheaders With C++ Code</h3> <p> You can use makeheaders to generate header files for C++ code, in addition to C. Makeheaders will recognize and copy both ``class'' declarations and inline function definitions, and it knows not to try to generate prototypes for methods. </p> <p> In fact, makeheaders is smart enough to be used in projects that employ a mixture of C and C++. ................................................................................ <p> No special command-line options are required to use makeheaders with C++ input. Makeheaders will recognize that its source code is C++ by the suffix on the source code filename. Simple ".c" or ".h" suffixes are assumed to be ANSI-C. Anything else, including ".cc", ".C" and ".cpp" is assumed to be C++. The name of the header file generated by makeheaders is derived from by the name of the source file by converting every "c" to "h" and every "C" to "H" in the suffix of the filename. Thus the C++ source file ``alpha.cpp'' will induce makeheaders to generate a header file named ``alpha.hpp''. </p> <p> Makeheaders augments class definitions by inserting prototypes to methods were appropriate. If a method definition begins with one of the special keywords <b>PUBLIC</b>, <b>PROTECTED</b>, or <b>PRIVATE</b> (in upper-case to distinguish them from the regular C++ keywords with the same meaning) then a prototype for that method will be inserted into the class definition. If none of these keywords appear, then the prototype is not inserted. For example, in the following code, the constructor is not explicitly declared in the class definition but makeheaders will add it there ................................................................................ </p> <h4>3.6.1 C++ Limitations</h4> <p> Makeheaders does not understand more recent C++ syntax such as templates and namespaces. Perhaps these issued will be addressed in future revisions. </p> <a name="H0013"></a> <h3>3.7 Conditional Compilation</h3> <p> The makeheaders program understands and tracks the conditional compilation constructs in the source code files it scans. Hence, if the following code appears in a source file <pre> #ifdef UNIX # define WORKS_WELL 1 #else # define WORKS_WELL 0 #endif </pre> then the next patch of code will appear in the generated header for every .c file that uses the WORKS_WELL constant: <pre> #if defined(UNIX) # define WORKS_WELL 1 ................................................................................ </p> <p> Makeheaders does not understand the old K&R style of function and procedure definitions. It only understands the modern ANSI-C style, and will probably become very confused if it encounters an old K&R function. You should take care to avoid putting K&R function defintions in your code, therefore. </p> <p> Makeheaders does not understand when you define more than one global variable with the same type separated by a comma. In other words, makeheaders does not understand this: <pre> ................................................................................ unrelated file in a different part of the source tree. <li> Information is kept in only one place. When a change occurs in the code, it is not necessary to make a corresponding change in a separate document. Just rerun the documentation generator. </ul> The makeheaders program does not generate program documentation itself. But you can use makeheaders to parse the program source code, extract the information that is relavant to the documentation and to pass this information to another tool to do the actual documentation preparation. </p> <p> When makeheaders is run with the ``-doc'' option, it emits no header files at all. Instead, it does a complete dump of its internal tables to standard outputs in a form that is easily parsed. This output can then be used by another program (the implementation of which is left as an exercise to the reader) that will use the information to prepare suitable documentation. </p> <p> The ``-doc'' option causes makeheaders to print information to standard output about all of the following objects: <ul> <li> C++ Class declarations <li> Structure and union declarations <li> Enumerations <li> Typedefs <li> Procedure and function definitions <li> Global variables <li> Preprocessor macros (ex: ``#define'') </ul> For each of these objects, the following information is output: <ul> <li> The name of the object. <li> The type of the object. (Structure, typedef, macro, etc.) <li> Flags to indicate if the declaration is exported (contained within an EXPORT_INTERFACE block) or local (contained with LOCAL_INTERFACE). <li> A flag to indicate if the object is declared in a C++ file. <li> The name of the file in which the object was declared. <li> The complete text of any block comment that preceeds the declarations. <li> If the declaration occurred inside a preprocessor conditional (``#if'') then the text of that conditional is provided. <li> The complete text of a declaration for the object. </ul> The exact output format will not be described here. It is simple to understand and parse and should be obvious to anyone who inspects some sample output. </p> <a name="H0016"></a> <h2>5.0 Compiling The Makeheaders Program</h2> <p> The source code for makeheaders is a single file of ANSI-C code, less than 3000 lines in length. The program makes only modest demands of the system and C library and should compile without alteration on most ANSI C compilers and on most operating systems. It is known to compile using several variations of GCC for Unix as well as Cygwin32 and MSVC 5.0 for Win32. </p> |
| | | | | | | | | | | | | | | > | > | | | | | | | > < > | | | | | | | | | | | | | | | | | | > | > | | | | | | | | | | | | | | | | | | | | | > | | > | | | | | | | | | | | | | | | | | | > | |
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 .. 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 .. 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 ... 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 ... 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 ... 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 ... 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 ... 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 ... 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 ... 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 ... 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 ... 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 ... 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 ... 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 ... 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 ... 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 ... 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 ... 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 ... 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 ... 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 ... 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 ... 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 ... 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 ... 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 ... 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 |
<head><title>The Makeheaders Program</title></head> <body bgcolor=white> <h1 align=center>The Makeheaders Program</h1> <p> This document describes <em>makeheaders</em>, a tool that automatically generates “<code>.h</code>” files for a C or C++ programming project. </p> <h2>Table Of Contents</h2> <ul> ................................................................................ <p> Declarations in C include things such as the following: <ul> <li> Typedefs. <li> Structure, union and enumeration declarations. <li> Function and procedure prototypes. <li> Preprocessor macros and #defines. <li> “<code>extern</code>” variable declarations. </ul> </p> <p> Definitions in C, on the other hand, include these kinds of things: <ul> <li> Variable definitions. ................................................................................ modern software engineering. Another way of looking at the difference is that the declaration is the <em>interface</em> and the definition is the <em>implementation</em>. </p> <p> In C programs, it has always been the tradition that declarations are put in files with the “<code>.h</code>” suffix and definitions are placed in “<code>.c</code>” files. The .c files contain “<code>#include</code>” preprocessor statements that cause the contents of .h files to be included as part of the source code when the .c file is compiled. In this way, the .h files define the interface to a subsystem and the .c files define how the subsystem is implemented. </p> <a name="H0003"></a> ................................................................................ into the file of your choice. </p> <p> A similar option is -H. Like the lower-case -h option, big -H generates a single include file on standard output. But unlike small -h, the big -H only emits prototypes and declarations that have been designated as “exportable”. The idea is that -H will generate an include file that defines the interface to a library. More will be said about this in section 3.4. </p> <p> Sometimes you want the base name of the .c file and the .h file to ................................................................................ If you want a particular file to be scanned by makeheaders but you don't want makeheaders to generate a header file for that file, then you can supply an empty header filename, like this: <pre> makeheaders alpha.c beta.c gamma.c: </pre> In this example, makeheaders will scan the three files named “<code>alpha.c</code>”, “<code>beta.c</code>” and “<code>gamma.c</code>” but because of the colon on the end of third filename it will only generate headers for the first two files. Unfortunately, it is not possible to get makeheaders to process any file whose name contains a colon. </p> <p> In a large project, the length of the command line for makeheaders can become very long. If the operating system doesn't support long command lines (example: DOS and Win32) you may not be able to list all of the input files in the space available. In that case, you can use the “<code>-f</code>” option followed by the name of a file to cause makeheaders to read command line options and filename from the file instead of from the command line. For example, you might prepare a file named “<code>mkhdr.dat</code>” that contains text like this: <pre> src/alpha.c:hdr/alpha.h src/beta.c:hdr/beta.h src/gamma.c:hdr/gamma.h ... </pre> ................................................................................ Then invoke makeheaders as follows: <pre> makeheaders -f mkhdr.dat </pre> </p> <p> The “<code>-local</code>” option causes makeheaders to generate of prototypes for “<code>static</code>” functions and procedures. Such prototypes are normally omitted. </p> <p> Finally, makeheaders also includes a “<code>-doc</code>” option. This command line option prevents makeheaders from generating any headers at all. Instead, makeheaders will write to standard output information about every definition and declaration that it encounters in its scan of source files. The information output includes the type of the definition or declaration and any comment that preceeds the definition or ................................................................................ documentation about the program. We'll talk more about this feature later. </p> <p> If you forget what command line options are available, or forget their exact name, you can invoke makeheaders using an unknown command line option (like “<code>--help</code>” or “<code>-?</code>”) and it will print a summary of the available options on standard error. If you need to process a file whose name begins with “<code>-</code>”, you can prepend a “<code>./</code>” to its name in order to get it accepted by the command line parser. Or, you can insert the special option “<code>--</code>” on the command line to cause all subsequent command line arguments to be treated as filenames even if their names begin with “<code>-</code>”. </p> <a name="H0006"></a> <h2>3.0 Preparing Source Files For Use With Makeheaders</h2> <p> Very little has to be done to prepare source files for use with ................................................................................ This section will describe several typical uses of makeheaders. </p> <a name="H0007"></a> <h3>3.1 The Basic Setup</h3> <p> The simplest way to use makeheaders is to put all definitions in one or more .c files and all structure and type declarations in separate .h files. The only restriction is that you should take care to chose basenames for your .h files that are different from the basenames for your .c files. Recall that if your .c file is named (for example) “<code>alpha.c</code>” makeheaders will attempt to generate a corresponding header file named “<code>alpha.h</code>”. For that reason, you don't want to use that name for any of the .h files you write since that will prevent makeheaders from generating the .h file automatically. </p> <p> The structure of a .c file intented for use with makeheaders is very simple. All you have to do is add a single “<code>#include</code>” to the top of the file that sources the header file that makeheaders will generate. Hence, the beginning of a source file named “<code>alpha.c</code>” might look something like this: </p> <pre> /* * Introductory comment... */ ................................................................................ /* The rest of your code... */ </pre> <p> Your manually generated header files require no special attention at all. Code them as you normally would. However, makeheaders will work better if you omit the “<code>#if</code>” statements people often put around the outside of header files that prevent the files from being included more than once. For example, to create a header file named “<code>beta.h</code>”, many people will habitually write the following: <pre> #ifndef BETA_H #define BETA_H /* declarations for beta.h go here */ ................................................................................ You can forego this cleverness with makeheaders. Remember that the header files you write will never really be included by any C code. Instead, makeheaders will scan your header files to extract only those declarations that are needed by individual .c files and then copy those declarations to the .h files corresponding to the .c files. Hence, the “<code>#if</code>” wrapper serves no useful purpose. But it does make makeheaders work harder, forcing it to put the statements <pre> #if !defined(BETA_H) #endif </pre> ................................................................................ manually written .h files and then automatically generate .h files corresponding to all .c files. </p> <p> Note that the wildcard expression used in the above example, “<code>*.[ch]</code>”, will expand to include all .h files in the current directory, both those entered manually be the programmer and others generated automatically by a prior run of makeheaders. But that is not a problem. The makeheaders program will recognize and ignore any files it has previously generated that show up on its input list. </p> ................................................................................ <ul> <p><li> When a function is defined in any .c file, a prototype of that function is placed in the generated .h file of every .c file that calls the function.</p> <P>If the “<code>static</code>” keyword of C appears at the beginning of the function definition, the prototype is suppressed. If you use the “<code>LOCAL</code>” keyword where you would normally say “<code>static</code>”, then a prototype is generated, but it will only appear in the single header file that corresponds to the source file containing the function. For example, if the file <code>alpha.c</code> contains the following: <pre> LOCAL int testFunc(void){ return 0; } ................................................................................ <pre> #define LOCAL static LOCAL int testFunc(void); </pre> However, no other generated header files will contain a prototype for <code>testFunc()</code> since the function has only file scope.</p> <p>When the “<code>LOCAL</code>” keyword is used, makeheaders will also generate a #define for LOCAL, like this: <pre> #define LOCAL static </pre> so that the C compiler will know what it means.</p> <p>If you invoke makeheaders with a “<code>-local</code>” command-line option, then it treats the “<code>static</code>” keyword like “<code>LOCAL</code>” and generates prototypes in the header file that corresponds to the source file containing the function definition.</p> <p><li> When a global variable is defined in a .c file, an “<code>extern</code>” declaration of that variable is placed in the header of every .c file that uses the variable. </p> <p><li> When a structure, union or enumeration declaration or a function prototype or a C++ class declaration appears in a ................................................................................ those files and are not copied. </p> <p><li> When a structure, union or enumeration declaration appears in a .h file, makeheaders will automatically generate a typedef that allows the declaration to be referenced without the “<code>struct</code>”, “<code>union</code>” or “<code>enum</code>” qualifier. In other words, if makeheaders sees the code: <pre> struct Examp { /* ... */ }; </pre> it will automatically generate a corresponding typedef like this: <pre> typedef struct Examp Examp; ................................................................................ The .h files are suppose to contain only interface, not implementation. C compilers will not enforce this convention, but makeheaders does. </ul> <p> As a final note, we observe that automatically generated declarations are ordered as required by the ANSI-C programming language. If the declaration of some structure “<code>X</code>” requires a prior declaration of another structure “<code>Y</code>”, then Y will appear first in the generated headers. </p> <a name="H0009"></a> <h3>3.3 How To Avoid Having To Write Any Header Files</h3> <p> In my experience, large projects work better if all of the manually ................................................................................ You can instruct makeheaders to treat any part of a .c file as if it were a .h file by enclosing that part of the .c file within: <pre> #if INTERFACE #endif </pre> Thus any structure definitions that appear after the “<code>#if INTERFACE</code>” but before the corresponding “<code>#endif</code>” are eligable to be copied into the automatically generated .h files of other .c files. </p> <p> If you use the “<code>#if INTERFACE</code>” mechanism in a .c file, then the generated header for that .c file will contain a line like this: <pre> #define INTERFACE 0 </pre> In other words, the C compiler will never see any of the text that defines the interface. ................................................................................ putting the declarations in the correct ANSI-C order -- makeheaders will do that for you automatically. </p> <p> Note that you don't have to use this approach exclusively. You can put some declarations in .h files and others within the “<code>#if INTERFACE</code>” regions of .c files. Makeheaders treats all declarations alike, no matter where they come from. You should also note that a single .c file can contain as many “<code>#if INTERFACE</code>” regions as desired. </p> <a name="H0010"></a> <h3>3.4 Designating Declarations For Export</h3> <p> In a large project, one will often construct a hierarchy of ................................................................................ (The second interface is normally a subset of the first.) Ordinary C does not provide support for a tiered interface like this, but makeheaders does. </p> <p> Using makeheaders, it is possible to designate routines and data structures as being for “<code>export</code>”. Exported objects are visible not only to other files within the same library or subassembly but also to other libraries and subassemblies in the larger program. By default, makeheaders only makes objects visible to other members of the same library. </p> ................................................................................ This is not a perfect solution, but it works well in practice. </p> <p> But trouble quickly arises when we attempt to devise a mechanism for telling makeheaders which prototypes it should export and which it should keep local. The built-in “<code>static</code>” keyword of C works well for prohibiting prototypes from leaving a single source file, but because C doesn't support a linkage hierarchy, there is nothing in the C language to help us. We'll have to invite our own keyword: “<code>EXPORT</code>” </p> <p> Makeheaders allows the EXPORT keyword to precede any function or procedure definition. The routine following the EXPORT keyword is then eligable to appear in the header file generated using the -H command line option. ................................................................................ are visible to all files within the library, any declarations or definitions within <pre> #if EXPORT_INTERFACE #endif </pre> will become part of the exported interface. The “<code>#if EXPORT_INTERFACE</code>” mechanism can be used in either .c or .h files. (The “<code>#if INTERFACE</code>” can also be used in both .h and .c files, but since it's use in a .h file would be redundant, we haven't mentioned it before.) </p> <a name="H0011"></a> <h3>3.5 Local declarations processed by makeheaders</h3> <p> Structure declarations and typedefs that appear in .c files are normally ignored by makeheaders. Such declarations are only intended for use by the source file in which they appear and so makeheaders doesn't need to copy them into any generated header files. We call such declarations “<code>private</code>”. </p> <p> Sometimes it is convenient to have makeheaders sort a sequence of private declarations into the correct order for us automatically. Or, we could have static functions and procedures for which we would like makeheaders to generate prototypes, but the arguments to these ................................................................................ <p> When this situation arises, enclose the private declarations within <pre> #if LOCAL_INTERFACE #endif </pre> A “<code>LOCAL_INTERFACE</code>” block works very much like the “<code>INTERFACE</code>” and “<code>EXPORT_INTERFACE</code>” blocks described above, except that makeheaders insures that the objects declared in a LOCAL_INTERFACE are only visible to the file containing the LOCAL_INTERFACE. </p> <a name="H0012"></a> <h3>3.6 Using Makeheaders With C++ Code</h3> <p> You can use makeheaders to generate header files for C++ code, in addition to C. Makeheaders will recognize and copy both “<code>class</code>” declarations and inline function definitions, and it knows not to try to generate prototypes for methods. </p> <p> In fact, makeheaders is smart enough to be used in projects that employ a mixture of C and C++. ................................................................................ <p> No special command-line options are required to use makeheaders with C++ input. Makeheaders will recognize that its source code is C++ by the suffix on the source code filename. Simple ".c" or ".h" suffixes are assumed to be ANSI-C. Anything else, including ".cc", ".C" and ".cpp" is assumed to be C++. The name of the header file generated by makeheaders is derived from the name of the source file by converting every "c" to "h" and every "C" to "H" in the suffix of the filename. Thus the C++ source file “<code>alpha.cpp</code>” will induce makeheaders to generate a header file named “<code>alpha.hpp</code>”. </p> <p> Makeheaders augments class definitions by inserting prototypes to methods where appropriate. If a method definition begins with one of the special keywords <b>PUBLIC</b>, <b>PROTECTED</b>, or <b>PRIVATE</b> (in upper-case to distinguish them from the regular C++ keywords with the same meaning) then a prototype for that method will be inserted into the class definition. If none of these keywords appear, then the prototype is not inserted. For example, in the following code, the constructor is not explicitly declared in the class definition but makeheaders will add it there ................................................................................ </p> <h4>3.6.1 C++ Limitations</h4> <p> Makeheaders does not understand more recent C++ syntax such as templates and namespaces. Perhaps these issues will be addressed in future revisions. </p> <a name="H0013"></a> <h3>3.7 Conditional Compilation</h3> <p> The makeheaders program understands and tracks the conditional compilation constructs in the source code files it scans. Hence, if the following code appears in a source file <pre> #ifdef UNIX # define WORKS_WELL 1 #else # define WORKS_WELL 0 #endif </pre> then the next patch of code will appear in the generated header for every .c file that uses the WORKS_WELL constant: <pre> #if defined(UNIX) # define WORKS_WELL 1 ................................................................................ </p> <p> Makeheaders does not understand the old K&R style of function and procedure definitions. It only understands the modern ANSI-C style, and will probably become very confused if it encounters an old K&R function. Therefore you should take care to avoid putting K&R function definitions in your code. </p> <p> Makeheaders does not understand when you define more than one global variable with the same type separated by a comma. In other words, makeheaders does not understand this: <pre> ................................................................................ unrelated file in a different part of the source tree. <li> Information is kept in only one place. When a change occurs in the code, it is not necessary to make a corresponding change in a separate document. Just rerun the documentation generator. </ul> The makeheaders program does not generate program documentation itself. But you can use makeheaders to parse the program source code, extract the information that is relevant to the documentation and to pass this information to another tool to do the actual documentation preparation. </p> <p> When makeheaders is run with the “<code>-doc</code>” option, it emits no header files at all. Instead, it does a complete dump of its internal tables to standard output in a form that is easily parsed. This output can then be used by another program (the implementation of which is left as an exercise to the reader) that will use the information to prepare suitable documentation. </p> <p> The “<code>-doc</code>” option causes makeheaders to print information to standard output about all of the following objects: <ul> <li> C++ class declarations <li> Structure and union declarations <li> Enumerations <li> Typedefs <li> Procedure and function definitions <li> Global variables <li> Preprocessor macros (ex: “<code>#define</code>”) </ul> For each of these objects, the following information is output: <ul> <li> The name of the object. <li> The type of the object. (Structure, typedef, macro, etc.) <li> Flags to indicate if the declaration is exported (contained within an EXPORT_INTERFACE block) or local (contained with LOCAL_INTERFACE). <li> A flag to indicate if the object is declared in a C++ file. <li> The name of the file in which the object was declared. <li> The complete text of any block comment that preceeds the declarations. <li> If the declaration occurred inside a preprocessor conditional (“<code>#if</code>”) then the text of that conditional is provided. <li> The complete text of a declaration for the object. </ul> The exact output format will not be described here. It is simple to understand and parse and should be obvious to anyone who inspects some sample output. </p> <a name="H0016"></a> <h2>5.0 Compiling The Makeheaders Program</h2> <p> The source code for makeheaders is a single file of ANSI-C code, approximately 3000 lines in length. The program makes only modest demands of the system and C library and should compile without alteration on most ANSI C compilers and on most operating systems. It is known to compile using several variations of GCC for Unix as well as Cygwin32 and MSVC 5.0 for Win32. </p> |