home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / dmake40.zip / dmake.c < prev    next >
C/C++ Source or Header  |  1994-10-23  |  24KB  |  859 lines

  1. /* RCS      -- $Header: /u5/dvadura/src/public/dmake/src/RCS/dmake.c,v 1.1 1994/10/06 17:41:23 dvadura Exp $
  2. -- SYNOPSIS -- The main program.
  3. -- 
  4. -- DESCRIPTION
  5. -- 
  6. --     dmake [-#dbug_string] [ options ]
  7. --             [ macro definitions ] [ target ... ]
  8. -- 
  9. --     This file contains the main command line parser for the
  10. --     make utility.  The valid flags recognized are as follows:
  11. -- 
  12. --     -f file         - use file as the makefile
  13. --    -C file        - duplicate console output to file (MSDOS only)
  14. --    -K file        - .KEEP_STATE file
  15. --     -#dbug_string   - dump out debugging info, see below
  16. --     -v{dfimt}    - verbose, print what we are doing, as we do it.
  17. -- 
  18. --      options: (can be catenated, ie -irn == -i -r -n)
  19. -- 
  20. --    -A        - enable AUGMAKE special target mapping
  21. --    -B        - enable non-use of TABS to start recipe lines
  22. --    -c        - use non-standard comment scanning
  23. --      -d              - do not use directory cache
  24. --     -i              - ignore errors
  25. --     -n              - trace and print, do not execute commands
  26. --     -t              - touch, update dates without executing commands
  27. --     -T              - do not apply transitive closure on inference rules
  28. --     -r              - don't use internal rules
  29. --     -s              - do your work silently
  30. --    -S        - force Sequential make, overrides -P
  31. --     -q              - check if target is up to date.  Does not
  32. --               do anything.  Returns 0 if up to date, -1
  33. --               otherwise.
  34. --     -p              - print out a version of the makefile
  35. --    -P#        - set value of MAXPROCESS
  36. --     -E              - define environment strings as macros
  37. --     -e              - as -E but done after parsing makefile
  38. --     -u              - force unconditional update of target
  39. --     -k              - make all independent targets even if errors
  40. --     -V              - print out this make version number
  41. --     -M        - Microsoft make compatibility, (* disabled *)
  42. --     -h              - print out usage info
  43. --     -x        - export macro defs to environment
  44. --      -X              - ignore #! lines found in makefile
  45. -- 
  46. --     NOTE:  - #ddbug_string is only availabe for versions of dmake that
  47. --         have been compiled with -DDBUG switch on.  Not the case for
  48. --         distributed versions.  Any such versions must be linked
  49. --         together with a version of Fred Fish's debug code.
  50. --              
  51. --     NOTE:  - in order to compile the code the include file stddef.h
  52. --         must be shipped with the bundled code.
  53. -- 
  54. -- AUTHOR
  55. --      Dennis Vadura, dvadura@watdragon.uwaterloo.ca
  56. --      CS DEPT, University of Waterloo, Waterloo, Ont., Canada
  57. --
  58. -- COPYRIGHT
  59. --      Copyright (c) 1992,1994 by Dennis Vadura.  All rights reserved.
  60. -- 
  61. --      This program is free software; you can redistribute it and/or
  62. --      modify it under the terms of the GNU General Public License
  63. --      (version 1), as published by the Free Software Foundation, and
  64. --      found in the file 'LICENSE' included with this distribution.
  65. -- 
  66. --      This program is distributed in the hope that it will be useful,
  67. --      but WITHOUT ANY WARRANTY; without even the implied warrant of
  68. --      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  69. --      GNU General Public License for more details.
  70. -- 
  71. --      You should have received a copy of the GNU General Public License
  72. --      along with this program;  if not, write to the Free Software
  73. --      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  74. --
  75. -- LOG
  76. --     $Log: dmake.c,v $
  77.  * Revision 1.1  1994/10/06  17:41:23  dvadura
  78.  * dmake Release Version 4.0, Initial revision
  79.  *
  80. */
  81.  
  82. /* Set this flag to one, and the global variables in vextern.h will not
  83.  * be defined as 'extern', instead they will be defined as global vars
  84.  * when this module is compiled. */
  85. #define _DEFINE_GLOBALS_ 1
  86.  
  87. #include "extern.h"
  88. #include "patchlvl.h"
  89. #include "version.h"
  90.  
  91. #ifndef MSDOS
  92. #define USAGE \
  93. "Usage:\n%s [-P#] [-{f|K} file] [-{w|W} target ...] [macro[!][[*][+][:]]=value ...]\n"
  94. #define USAGE2 \
  95. "%s [-v{cdfimt}] [-ABcdeEghiknpqrsStTuVxX] [target ...]\n"
  96. #else
  97. #define USAGE \
  98. "Usage:\n%s [-P#] [-{f|C|K} file] [-{w|W} target ...] [macro[!][[*][+][:]]=value ...]\n"
  99. #define USAGE2 \
  100. "%s [-v{cdfimt}] [-ABcdeEghiknpqrsStTuVxX] [target ...]\n"
  101. #endif
  102.  
  103. #if __STDC__ == 1 && !defined(__GNUC__) && !defined(_MSC_VER)
  104. void Fatal(char *fmt, ...);
  105. void Warning(char *fmt, ...);
  106. #endif
  107.  
  108. static char *sccid = "Copyright (c) 1990,...,1994 by Dennis Vadura";
  109. static char _warn  = TRUE;        /* warnings on by default */
  110.  
  111. static    void    _do_VPATH();
  112. static    void    _do_ReadEnvironment();
  113. #if !defined(__GNUC__)
  114. static  void    _do_f_flag ANSI((char, char *, char **));
  115. #else
  116. static  void    _do_f_flag ANSI((int, char *, char **));
  117. #endif
  118.  
  119. PUBLIC void
  120. main(argc, argv)
  121. int  argc;
  122. char **argv;
  123. {
  124. #ifdef MSDOS
  125.    char*   std_fil_name = NIL(char);
  126. #endif
  127.  
  128.    char*   fil_name = NIL(char);
  129.    char*   state_name = NIL(char);
  130.    char*   whatif = NIL(char);
  131.    char*   cmdmacs;
  132.    char*   targets;
  133.    FILE*   mkfil;
  134.    int     ex_val;
  135.    int     m_export;
  136.  
  137.    DB_ENTER("main");
  138.  
  139.    /* Initialize Global variables to their default values       */
  140.    Prolog(argc, argv);
  141.    Create_macro_vars();
  142.    Catch_signals(Quit);
  143.  
  144.    Def_macro( "MAKECMD", Pname, M_PRECIOUS|M_NOEXPORT );
  145.    Pname = Basename(Pname);
  146.  
  147.    DB_PROCESS(Pname);
  148.    (void) setvbuf(stdout, NULL, _IOLBF, BUFSIZ); /* stdout line buffered */
  149.  
  150.    Continue  = FALSE;
  151.    Comment   = FALSE;
  152.    Get_env   = FALSE;
  153.    Force     = FALSE;
  154.    Target    = FALSE;
  155.    If_expand = FALSE;
  156.    Listing   = FALSE;
  157.    Readenv   = FALSE;
  158.    Rules     = TRUE;
  159.    Trace     = FALSE;
  160.    Touch     = FALSE;
  161.    Check     = FALSE;
  162.    Microsoft = FALSE;
  163.    Makemkf   = FALSE;
  164.    No_exec   = FALSE;
  165.    m_export  = FALSE;
  166.    cmdmacs   = NIL(char);
  167.    targets   = NIL(char);
  168.  
  169.    Verbose     = V_NONE;
  170.    Transitive  = TRUE;
  171.    Nest_level  = 0;
  172.    Line_number = 0;
  173.    Suppress_temp_file = FALSE;
  174.    Skip_to_eof = FALSE;
  175.  
  176.    while( --argc > 0 ) {
  177.       register char *p;
  178.       char *q;
  179.  
  180.       if( *(p = *++argv) == '-' ) {
  181.          if( p[1] == '\0' ) Fatal("Missing option letter");
  182.  
  183.          /* copy options to Buffer for $(MFLAGS), strip 'f' and 'C'*/
  184.          q = strchr(Buffer, '\0');
  185.          while (*p != '\0') {
  186.         char c = (*q++ = *p++);
  187.             if( c == 'f' || c == 'C' ) q--;
  188.      }
  189.  
  190.      if( *(q-1) == '-' )
  191.         q--;
  192.      else
  193.             *q++ = ' ';
  194.  
  195.      *q = '\0';
  196.  
  197.          for( p = *argv+1; *p; p++) switch (*p) {
  198.         case 'f':
  199.            _do_f_flag( 'f', *++argv, &fil_name ); argc--;
  200.            break;
  201.  
  202. #if defined(MSDOS) && !defined(OS2)
  203.         case 'C':
  204.            _do_f_flag( 'C', *++argv, &std_fil_name ); argc--;
  205.            Hook_std_writes( std_fil_name );
  206.            break;
  207. #endif
  208.  
  209.         case 'K':
  210.            _do_f_flag( 'K', *++argv, &state_name ); argc--;
  211.            Def_macro(".KEEP_STATE", state_name, M_EXPANDED|M_PRECIOUS);
  212.            break;
  213.  
  214.         case 'W':
  215.         case 'w': {
  216.            CELLPTR wif;
  217.            _do_f_flag( 'w', *++argv, &whatif ); argc--;
  218.            wif = Def_cell(whatif);
  219.            wif->ce_attr |= A_WHATIF;
  220.            whatif = NIL(char);
  221.  
  222.            if ( *p == 'W') 
  223.           break;
  224.         }
  225.         /*FALLTHRU*/
  226.  
  227.         case 'n':
  228.            Trace = TRUE;
  229.            break;
  230.  
  231.         case 'k': Continue   = TRUE;  break;
  232.         case 'c': Comment    = TRUE;  break;
  233.         case 'p': Listing    = TRUE;  break;
  234.         case 'r': Rules      = FALSE; break;
  235.         case 't': Touch      = TRUE;  break;
  236.         case 'q': Check      = TRUE;  break;
  237.         case 'u': Force      = TRUE;  break;
  238.         case 'x': m_export   = TRUE;  break;
  239.         case 'X': No_exec    = TRUE;  break;
  240.         case 'T': Transitive = FALSE; break;
  241.         case 'e': Get_env    = 'e';   break;
  242.         case 'E': Get_env    = 'E';   break;
  243.  
  244.         case 'V': Version();  Quit(NIL(CELL));  break;
  245.         case 'A': Def_macro("AUGMAKE", "y", M_EXPANDED); break;
  246.         case 'B': Def_macro(".NOTABS", "y", M_EXPANDED); break;
  247.         case 'i': Def_macro(".IGNORE", "y", M_EXPANDED); break;
  248.         case 's': Def_macro(".SILENT", "y", M_EXPANDED); break;
  249.         case 'S': Def_macro(".SEQUENTIAL", "y", M_EXPANDED); break;
  250.         case 'g': Def_macro(".IGNOREGROUP","y", M_EXPANDED); break;
  251.         case 'd': Def_macro(".DIRCACHE",NIL(char),M_EXPANDED); break;
  252.  
  253.         case 'v':
  254.            if( p[-1] != '-' ) Usage(TRUE);
  255.            while( p[1] ) switch( *++p ) {
  256.           case 'c': Verbose |= V_DIR_CACHE; break;
  257.           case 'd': Verbose |= V_DIR_SET;   break;
  258.           case 'f': Verbose |= V_FILE_IO;   break;
  259.           case 'i': Verbose |= V_INFER;     break;
  260.           case 'm': Verbose |= V_MAKE;      break;
  261.           case 't': Verbose |= V_LEAVE_TMP; break;
  262.  
  263.           default: Usage(TRUE); break;
  264.            }
  265.            if( !Verbose ) Verbose = V_ALL;
  266.            break;
  267.  
  268.         case 'P':
  269.            if( p[1] ) {
  270.           Def_macro( "MAXPROCESS", p+1, M_MULTI|M_EXPANDED );
  271.           p += strlen(p)-1;
  272.            }
  273.            else
  274.           Fatal( "Missing number for -P flag" );
  275.            break;
  276.  
  277. #ifdef DBUG
  278.         case '#':
  279.            DB_PUSH(p+1);
  280.            p += strlen(p)-1;
  281.            break;
  282. #endif
  283.  
  284.         case 'h': Usage(FALSE); break;
  285.         case 0:   break;    /* lone - */
  286.         default:  Usage(TRUE);  break;
  287.      }
  288.       }
  289.       else if( (q = strchr(p, '=')) != NIL(char) ) {
  290.      cmdmacs = DmStrAdd( cmdmacs, DmStrDup2(p), TRUE );
  291.      Parse_macro( p, (q[-1]!='+')?M_PRECIOUS:M_DEFAULT );
  292.       }
  293.       else {
  294.      register CELLPTR cp;
  295.      targets = DmStrAdd( targets, DmStrDup(p), TRUE );
  296.      Add_prerequisite(Targets, cp = Def_cell(p), FALSE, FALSE);
  297.      cp->ce_flag |= F_TARGET;
  298.      cp->ce_attr |= A_FRINGE;
  299.      Target = TRUE;
  300.       }
  301.    }
  302.  
  303.    Def_macro( "MAKEMACROS",  cmdmacs, M_PRECIOUS|M_NOEXPORT );
  304.    Def_macro( "MAKETARGETS", targets, M_PRECIOUS|M_NOEXPORT );
  305.    if( cmdmacs != NIL(char) ) FREE(cmdmacs);
  306.    if( targets != NIL(char) ) FREE(targets);
  307.  
  308.    Def_macro( "MFLAGS", Buffer, M_PRECIOUS|M_NOEXPORT );
  309.    Def_macro( "%", "$@", M_PRECIOUS|M_NOEXPORT );
  310.  
  311.    if( *Buffer ) Def_macro( "MAKEFLAGS", Buffer+1, M_PRECIOUS|M_NOEXPORT );
  312.  
  313.    _warn  = FALSE;      /* disable warnings for builtin rules */
  314.    ex_val = Target;     /* make sure we don't mark any        */
  315.    Target = TRUE;       /* of the default rules as            */
  316.    Make_rules();        /* potential targets                  */
  317.    _warn = TRUE;
  318.  
  319.    if( Rules ) {
  320.       char *fname;
  321.  
  322.       if( (mkfil=Search_file("MAKESTARTUP", &fname)) != NIL(FILE) ) {
  323.          Parse(mkfil);
  324.      Def_macro( "MAKESTARTUP", fname, M_EXPANDED|M_MULTI|M_FORCE );
  325.          mkfil = NIL(FILE);
  326.       }
  327.       else
  328.          Fatal( "Configuration file `%s' not found", fname );
  329.    }
  330.  
  331.    Target = ex_val;
  332.  
  333.    if( Get_env == 'E' ) _do_ReadEnvironment();
  334.  
  335.    if( fil_name != NIL(char) )
  336.       mkfil = Openfile( fil_name, FALSE, TRUE );
  337.    else {
  338.       /* Search .MAKEFILES dependent list looking for a makefile.
  339.        */
  340.       register CELLPTR cp;
  341.  
  342.       cp = Def_cell( ".MAKEFILES" );
  343.       mkfil = TryFiles(cp->CE_PRQ);
  344.    }
  345.  
  346.    if( mkfil != NIL(FILE) ) {
  347.       char *f = Filename();
  348.       char *p;
  349.  
  350.       if( strcmp(f, "stdin") == 0 ) f = "-";
  351.       p = DmStrAdd( "-f", f, FALSE );
  352.       Def_macro( "MAKEFILE", p, M_PRECIOUS|M_NOEXPORT );
  353.       Parse( mkfil );
  354.    }
  355.    else if( !Rules )
  356.       Fatal( "No `makefile' present" );
  357.  
  358.    if( Nest_level     ) Fatal( "Missing .END for .IF" );
  359.    if( Get_env == 'e' ) _do_ReadEnvironment();
  360.  
  361.    _do_VPATH();                  /* kludge it up with .SOURCE    */
  362.  
  363.    if( Listing ) Dump();        /* print out the structures     */
  364.    if( Trace ) Glob_attr &= ~A_SILENT;    /* make sure we see the trace   */
  365.  
  366.    if( !Target )
  367.       Fatal( "No target" );
  368.    else {
  369.       Test_circle( Root, TRUE );
  370.       Check_circle_dfa();
  371.    }
  372.  
  373.    if( m_export ) {
  374.       int i;
  375.  
  376.       for( i=0; i<HASH_TABLE_SIZE; ++i ) {
  377.      HASHPTR hp = Macs[i];
  378.  
  379.      while( hp ) {
  380.         if( !(hp->ht_flag & M_NOEXPORT) && hp->ht_value != NIL(char) )
  381.            if( Write_env_string(hp->ht_name, hp->ht_value) != 0 )
  382.            Warning( "Could not export %s", hp->ht_name );
  383.         hp = hp->ht_next;
  384.      }
  385.       }
  386.    }
  387.  
  388.    if( Buffer != NIL(char) ) {FREE( Buffer ); Buffer = NIL(char);}
  389.    if( Trace ) Def_macro(".SEQUENTIAL", "y", M_EXPANDED);
  390.    if( Glob_attr & A_SEQ ) Def_macro( "MAXPROCESS", "1", M_EXPANDED|M_FORCE );
  391.  
  392.    ex_val = Make_targets();
  393.  
  394.    Clear_signals();
  395.    Epilog(ex_val);      /* Does not return -- EVER */
  396. }
  397.  
  398.  
  399. static void
  400. _do_f_flag( flag, name, fname )
  401. char  flag;
  402. char *name;
  403. char **fname;
  404. {
  405.    if( *fname == NIL(char) ) {
  406.       if( name != NIL(char) ) {
  407.      *fname = name;
  408.       } else
  409.      Fatal("No file name for -%c", flag);
  410.    } else
  411.       Fatal("Only one `-%c file' allowed", flag);
  412. }
  413.  
  414.  
  415. static void
  416. _do_ReadEnvironment()
  417. {
  418.    t_attr saveattr = Glob_attr;
  419.  
  420.    Glob_attr |= A_SILENT;
  421.    ReadEnvironment();
  422.    Glob_attr = saveattr;
  423. }
  424.  
  425.  
  426. static void
  427. _do_VPATH()
  428. {
  429.    HASHPTR hp;
  430.    char    *_rl[2];
  431.    extern char **Rule_tab;
  432.  
  433.    hp = GET_MACRO("VPATH");
  434.    if( hp == NIL(HASH) ) return;
  435.  
  436.    _rl[0] = ".SOURCE :^ $(VPATH:s/:/ /)";
  437.    _rl[1] = NIL(char);
  438.  
  439.    Rule_tab = _rl;
  440.    Parse( NIL(FILE) );
  441. }
  442.  
  443.  
  444. /*  The file table and pointer to the next FREE slot for use by both
  445.     Openfile and Closefile.  Each open stacks the new file onto the open
  446.     file stack, and a corresponding close will close the passed file, and
  447.     return the next file on the stack.  The maximum number of nested
  448.     include files is limited by the value of MAX_INC_DEPTH */
  449.  
  450. static struct {
  451.    FILE         *file;      /* file pointer                 */
  452.    char         *name;      /* name of file                 */
  453.    int          numb;       /* line number                  */
  454. } ftab[ MAX_INC_DEPTH ];
  455.  
  456. static int next_file_slot = 0;
  457.  
  458. /* Set the proper macro value to reflect the depth of the .INCLUDE directives
  459.  * and the name of the file we are reading.
  460.  */
  461. static void
  462. _set_inc_depth()
  463. {
  464.    char buf[10];
  465.    sprintf( buf, "%d", next_file_slot );
  466.    Def_macro( "INCDEPTH", buf, M_MULTI|M_NOEXPORT );
  467.    Def_macro( "INCFILENAME",
  468.               next_file_slot ? ftab[next_file_slot-1].name : "",
  469.               M_MULTI|M_NOEXPORT );
  470. }
  471.  
  472.  
  473. PUBLIC FILE *
  474. Openfile(name, mode, err)/*
  475. ===========================
  476.    This routine opens a file for input or output depending on mode.
  477.    If the file name is `-' then it returns standard input.
  478.    The file is pushed onto the open file stack.  */
  479. char *name;
  480. int  mode;
  481. int  err;
  482. {
  483.    FILE *fil;
  484.  
  485.    DB_ENTER("Openfile");
  486.  
  487.    if( name == NIL(char) || !*name )
  488.       if( !err )
  489.          DB_RETURN(NIL(FILE));
  490.       else
  491.          Fatal( "Openfile:  NIL filename" );
  492.    
  493.    if( next_file_slot == MAX_INC_DEPTH )
  494.       Fatal( "Too many open files. Max nesting level is %d.", MAX_INC_DEPTH);
  495.  
  496.    DB_PRINT( "io", ("Opening file [%s], in slot %d", name, next_file_slot) );
  497.  
  498.    if( strcmp("-", name) == 0 ) {
  499.       name = "stdin";
  500.       fil = stdin;
  501.    }
  502.    else
  503.       fil = fopen( name, mode ? "w":"r" );
  504.  
  505.    if( Verbose & V_FILE_IO )
  506.       printf( "%s:  Openning [%s] for %s", Pname, name, mode?"write":"read" );
  507.  
  508.    if( fil == NIL(FILE) ) {
  509.       if( Verbose & V_FILE_IO ) printf( " (fail)\n" );
  510.       if( err )
  511.          Fatal( mode ? "Cannot open file %s for write" : "File %s not found",
  512.         name );
  513.    }
  514.    else {
  515.       if( Verbose & V_FILE_IO ) printf( " (success)\n" );
  516.       ftab[next_file_slot].file   = fil;
  517.       ftab[next_file_slot].numb   = Line_number;
  518.       ftab[next_file_slot++].name = DmStrDup(name);
  519.       Line_number = 0;
  520.       _set_inc_depth();
  521.    }
  522.  
  523.    DB_RETURN(fil);
  524. }
  525.  
  526.  
  527. PUBLIC FILE *
  528. Closefile()/*
  529. =============
  530.    This routine is used to close the last file opened.  This forces make
  531.    to open files in a last open first close fashion.  It returns the
  532.    file pointer to the next file on the stack, and NULL if the stack is empty.*/
  533. {
  534.    DB_ENTER("Closefile");
  535.  
  536.    if( !next_file_slot )
  537.       DB_RETURN( NIL(FILE) );
  538.  
  539.    if( ftab[--next_file_slot].file != stdin ) {
  540.       DB_PRINT( "io", ("Closing file in slot %d", next_file_slot) );
  541.  
  542.       if( Verbose & V_FILE_IO )
  543.      printf( "%s:  Closing [%s]\n", Pname, ftab[next_file_slot].name );
  544.  
  545.       fclose( ftab[next_file_slot].file );
  546.       FREE( ftab[next_file_slot].name );
  547.    }
  548.  
  549.    _set_inc_depth();
  550.  
  551.    if( next_file_slot > 0 ) {
  552.       Line_number = ftab[next_file_slot].numb;
  553.       DB_RETURN( ftab[next_file_slot-1].file );
  554.    }
  555.    else
  556.       Line_number = 0;
  557.  
  558.    DB_RETURN( NIL(FILE) );
  559. }
  560.  
  561.  
  562. PUBLIC FILE *
  563. Search_file( macname, rname )
  564. char *macname;
  565. char **rname;
  566. {
  567.    HASHPTR hp;
  568.    FILE *fil = NIL(FILE);
  569.    char *fname;
  570.    char *ename = NIL(char);
  571.  
  572.    /* order of precedence is:
  573.     *
  574.     *   MACNAME  from command line (precious is marked)
  575.     *         ... via MACNAME:=filename definition.
  576.     *   MACNAME  from environment
  577.     *   MACNAME  from builtin rules (not precious)
  578.     */
  579.  
  580.    if( (hp = GET_MACRO(macname)) != NIL(HASH) )
  581.       ename = fname = Expand(hp->ht_value);
  582.  
  583.    if( hp->ht_flag & M_PRECIOUS ) fil = Openfile(fname, FALSE, FALSE);
  584.  
  585.    if( fil == NIL(FILE) ) {
  586.       fname=Expand(Read_env_string(macname));
  587.       if( (fil = Openfile(fname, FALSE, FALSE)) != NIL(FILE) ) FREE(ename);
  588.    }
  589.  
  590.    if( fil == NIL(FILE) && hp != NIL(HASH) )
  591.       fil = Openfile(fname=ename, FALSE, FALSE);
  592.  
  593.    if( rname ) *rname = fname;
  594.  
  595.    return(fil);
  596. }
  597.  
  598.  
  599. PUBLIC char *
  600. Filename()/*
  601. ============
  602.    Return name of file on top of stack */
  603. {
  604.    return( next_file_slot==0 ? NIL(char) : ftab[next_file_slot-1].name );
  605. }
  606.  
  607.  
  608. PUBLIC int
  609. Nestlevel()/*
  610. =============
  611.    Return the file nesting level */
  612. {
  613.    return( next_file_slot );
  614. }
  615.  
  616.  
  617. PUBLIC FILE *
  618. TryFiles(lp)
  619. LINKPTR lp;
  620. {
  621.    FILE *mkfil = NIL(FILE);
  622.  
  623.    if( lp != NIL(LINK) ) {
  624.       int s_n, s_t, s_q;
  625.  
  626.       s_n = Trace;
  627.       s_t = Touch;
  628.       s_q = Check;
  629.  
  630.       Trace = Touch = Check = FALSE;
  631.       Makemkf = Wait_for_completion = TRUE;
  632.       mkfil = NIL(FILE);
  633.  
  634.       for(;  lp != NIL(LINK) && mkfil == NIL(FILE); lp=lp->cl_next) {
  635.      if( lp->cl_prq->ce_attr & A_FRINGE ) continue;
  636.  
  637.      mkfil = Openfile( lp->cl_prq->CE_NAME, FALSE, FALSE );
  638.  
  639.      if( mkfil == NIL(FILE) &&
  640.          Make(lp->cl_prq, NIL(CELL)) != -1 )
  641.         mkfil = Openfile( lp->cl_prq->CE_NAME, FALSE, FALSE );
  642.       }
  643.  
  644.       Trace = s_n;
  645.       Touch = s_t;
  646.       Check = s_q;
  647.       Makemkf = Wait_for_completion = FALSE;
  648.    }
  649.  
  650.    return(mkfil);
  651. }
  652.  
  653.  
  654. /*
  655. ** print error message from variable arg list
  656. */
  657.  
  658. static int errflg = TRUE;
  659. static int warnflg = FALSE;
  660.  
  661. static void
  662. errargs(fmt, args)
  663. char    *fmt;
  664. va_list  args;
  665. {
  666.    int warn = _warn && warnflg && !(Glob_attr & A_SILENT);
  667.  
  668.    if( errflg || warn ) {
  669.       char *f = Filename();
  670.  
  671.       fprintf( stderr, "%s:  ", Pname );
  672.       if( f != NIL(char) ) fprintf(stderr, "%s:  line %d:  ", f, Line_number);
  673.  
  674.       if( errflg )
  675.          fprintf(stderr, "Error -- ");
  676.       else if( warn )
  677.          fprintf(stderr, "Warning -- ");
  678.  
  679.       vfprintf( stderr, fmt, args );
  680.       putc( '\n', stderr );
  681.       if( errflg && !Continue ) Quit( NIL(CELL) );
  682.    }
  683. }
  684.  
  685. /*
  686. ** Print error message and abort
  687. */
  688. #if __STDC__ == 1 && !defined(__GNUC__) && !defined(_MSC_VER)
  689. void
  690. Fatal(char *fmt, ...)
  691. #else
  692. #if defined(_MPW)
  693. Fatal(char *fmt, va_alist)
  694. va_dcl
  695. #else
  696. int
  697. Fatal(fmt, va_alist)
  698. char *fmt;
  699. va_dcl;
  700. #endif
  701. #endif
  702. {
  703.    va_list args;
  704.  
  705.    va_start(args, fmt);
  706.    Continue = FALSE;
  707.    errargs(fmt, args);
  708.    va_end(args);
  709. }
  710.  
  711. /*
  712. ** error message and exit (unless -k)
  713. */
  714. #if __STDC__ == 1 && !defined(__GNUC__) && !defined(_MSC_VER)
  715. void
  716. Error (char *fmt, ...)
  717. #else
  718. #if defined(_MPW)
  719. Error(char *fmt, va_alist)
  720. va_dcl
  721. #else
  722. int
  723. Error(fmt, va_alist)
  724. char*   fmt;
  725. va_dcl;
  726. #endif
  727. #endif
  728. {
  729.    va_list args;
  730.  
  731.    va_start(args, fmt);
  732.    errargs(fmt, args);
  733.    va_end(args);
  734. }
  735.  
  736.  
  737. /*
  738. ** non-fatal message
  739. */
  740. #if __STDC__ == 1 && !defined(__GNUC__) && !defined(_MSC_VER)
  741. void
  742. Warning(char *fmt, ...)
  743. #else
  744. #if defined(_MPW)
  745. Warning(char *fmt, va_alist)
  746. va_dcl
  747. #else
  748. int
  749. Warning(fmt, va_alist)
  750. char *fmt;
  751. va_dcl;
  752. #endif
  753. #endif
  754. {
  755.    va_list args;
  756.  
  757.    va_start(args, fmt);
  758.    warnflg = TRUE;
  759.    errflg = FALSE;
  760.    errargs(fmt, args);
  761.    errflg = TRUE;
  762.    warnflg = FALSE;
  763.    va_end(args);
  764. }
  765.  
  766.  
  767. PUBLIC void
  768. No_ram()
  769. {
  770.    Fatal( "No more memory" );
  771. }
  772.  
  773.  
  774. PUBLIC void
  775. Usage( eflag )
  776. int eflag;
  777. {
  778.    register char *p;
  779.    char *fill;
  780.  
  781.    fill = DmStrDup(Pname);
  782.    for(p=fill; *p; p++) *p=' ';
  783.  
  784.    if( eflag ) {
  785.       fprintf(stderr, USAGE, Pname);
  786.       fprintf(stderr, USAGE2, fill);
  787.    }
  788.    else {
  789.    printf(USAGE, Pname);
  790.    printf(USAGE2, fill);
  791.    puts("    -P#        - set max number of child processes for parallel make");
  792.    puts("    -f file    - use file as the makefile");
  793. #ifdef MSDOS
  794.    puts("    -C [+]file - duplicate console output to file, ('+' => append)");
  795. #endif
  796.    puts("    -K file    - use file as the .KEEP_STATE file");
  797.    puts("    -w target  - show what you would do if 'target' were out of date");
  798.    puts("    -W target  - rebuild pretending that 'target' is out of date");
  799.    puts("    -v{cdfimt} - verbose, indicate what we are doing, (-v => -vdimt)");
  800.    puts("                   c => dump directory cache info only" );
  801.    puts("                   d => dump change of directory info only" );
  802.    puts("                   f => dump file open/close info only" );
  803.    puts("                   i => dump inference information only" );
  804.    puts("                   m => dump make of target information only" );
  805.    puts("                   t => keep temporary files when done\n" );
  806.  
  807.    puts("Options: (can be catenated, ie -irn == -i -r -n)");
  808.    puts("    -A   - enable AUGMAKE special target mapping");
  809.    puts("    -B   - enable the use of spaces instead of tabs to start recipes");
  810.    puts("    -c   - use non standard comment scanning");
  811.    puts("    -d   - do not use directory cache");
  812.    puts("    -E   - define environment strings as macros");
  813.    puts("    -e   - same as -E but done after parsing makefile");
  814.    puts("    -g   - disable the special meaning of [ ... ] for group recipes");
  815.    puts("    -h   - print out usage info");
  816.    puts("    -i   - ignore errors");
  817.    puts("    -k   - make independent targets, even if errors");
  818.    puts("    -n   - trace and print, do not execute commands");
  819.    puts("    -p   - print out a version of the makefile");
  820.    puts("    -q   - check if target is up to date.  Does not do");
  821.    puts("           anything.  Returns 0 if up to date, 1 otherwise");
  822.    puts("    -r   - don't use internal rules");
  823.    puts("    -s   - do your work silently");
  824.    puts("    -S   - disable parallel (force sequential) make, overrides -P");
  825.    puts("    -t   - touch, update time stamps without executing commands");
  826.    puts("    -T   - do not apply transitive closure on inference rules");
  827.    puts("    -u   - force unconditional update of target");
  828.    puts("    -V   - print out version number");
  829.    puts("    -x   - export macro values to environment");
  830.    puts("    -X   - ignore #! lines at start of makefile");
  831.    }
  832.  
  833.    Quit(NIL(CELL));
  834. }
  835.  
  836.  
  837. PUBLIC void
  838. Version()
  839. {
  840.    extern char **Rule_tab;
  841.    char **p;
  842.    
  843.    printf("%s - %s, ", Pname, sccid);
  844.    printf("Version %s, PL %d\n\n", VERSION, PATCHLEVEL);
  845.  
  846.    puts("Default Configuration:");
  847.    for (p=Rule_tab;  *p != NIL(char);  p++)
  848.       printf("\t%s\n", *p);
  849.  
  850.    printf("\n");
  851. printf("Please read the file readme/release for the latest release notes.\n");
  852. printf("\n");
  853. printf("Please support the DMAKE Reference Manual project.  See the file\n");
  854. printf("readme/release for additional information on where to send contributions.\n");
  855. printf("Or, send mail to dvadura@plg.uwaterloo.ca for additional information if the\n");
  856. printf("above file is not readily available.\n");
  857.  
  858. }
  859.