home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / INFO / C / DMAKE37S.ZIP / DMAKE / DMAKE.C < prev    next >
Encoding:
C/C++ Source or Header  |  1991-05-06  |  19.6 KB  |  742 lines

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