GNO dmake 1.0.0 sources, converted to LF line endings.

This commit is contained in:
Stephen Heumann 2017-05-14 19:59:26 -05:00
commit 48f940a1d9
364 changed files with 57159 additions and 0 deletions

248
dmake/LICENSE Normal file
View File

@ -0,0 +1,248 @@
GNU GENERAL PUBLIC LICENSE
Version 1, February 1989
Copyright (C) 1989 Free Software Foundation, Inc.
675 Mass Ave, Cambridge, MA 02139, USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The license agreements of most software companies try to keep users
at the mercy of those companies. By contrast, our General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. The
General Public License applies to the Free Software Foundation's
software and to any other program whose authors commit to using it.
You can use it for your programs, too.
When we speak of free software, we are referring to freedom, not
price. Specifically, the General Public License is designed to make
sure that you have the freedom to give away or sell copies of free
software, that you receive source code or can get it if you want it,
that you can change the software or use pieces of it in new free
programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of a such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must tell them their rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License Agreement applies to any program or other work which
contains a notice placed by the copyright holder saying it may be
distributed under the terms of this General Public License. The
"Program", below, refers to any such program or work, and a "work based
on the Program" means either the Program or any work containing the
Program or a portion of it, either verbatim or with modifications. Each
licensee is addressed as "you".
1. You may copy and distribute verbatim copies of the Program's source
code as you receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice and
disclaimer of warranty; keep intact all the notices that refer to this
General Public License and to the absence of any warranty; and give any
other recipients of the Program a copy of this General Public License
along with the Program. You may charge a fee for the physical act of
transferring a copy.
2. You may modify your copy or copies of the Program or any portion of
it, and copy and distribute such modifications under the terms of Paragraph
1 above, provided that you also do the following:
a) cause the modified files to carry prominent notices stating that
you changed the files and the date of any change; and
b) cause the whole of any work that you distribute or publish, that
in whole or in part contains the Program or any part thereof, either
with or without modifications, to be licensed at no charge to all
third parties under the terms of this General Public License (except
that you may choose to grant warranty protection to some or all
third parties, at your option).
c) If the modified program normally reads commands interactively when
run, you must cause it, when started running for such interactive use
in the simplest and most usual way, to print or display an
announcement including an appropriate copyright notice and a notice
that there is no warranty (or else, saying that you provide a
warranty) and that users may redistribute the program under these
conditions, and telling the user how to view a copy of this General
Public License.
d) You may charge a fee for the physical act of transferring a
copy, and you may at your option offer warranty protection in
exchange for a fee.
Mere aggregation of another independent work with the Program (or its
derivative) on a volume of a storage or distribution medium does not bring
the other work under the scope of these terms.
3. You may copy and distribute the Program (or a portion or derivative of
it, under Paragraph 2) in object code or executable form under the terms of
Paragraphs 1 and 2 above provided that you also do one of the following:
a) accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of
Paragraphs 1 and 2 above; or,
b) accompany it with a written offer, valid for at least three
years, to give any third party free (except for a nominal charge
for the cost of distribution) a complete machine-readable copy of the
corresponding source code, to be distributed under the terms of
Paragraphs 1 and 2 above; or,
c) accompany it with the information you received as to where the
corresponding source code may be obtained. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form alone.)
Source code for a work means the preferred form of the work for making
modifications to it. For an executable file, complete source code means
all the source code for all modules it contains; but, as a special
exception, it need not include source code for modules which are standard
libraries that accompany the operating system on which the executable
file runs, or for standard header files or definitions files that
accompany that operating system.
4. You may not copy, modify, sublicense, distribute or transfer the
Program except as expressly provided under this General Public License.
Any attempt otherwise to copy, modify, sublicense, distribute or transfer
the Program is void, and will automatically terminate your rights to use
the Program under this License. However, parties who have received
copies, or rights to use copies, from you under this General Public
License will not have their licenses terminated so long as such parties
remain in full compliance.
5. By copying, distributing or modifying the Program (or any work based
on the Program) you indicate your acceptance of this license to do so,
and all its terms and conditions.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the original
licensor to copy, distribute or modify the Program subject to these
terms and conditions. You may not impose any further restrictions on the
recipients' exercise of the rights granted herein.
7. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of the license which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
the license, you may choose any version ever published by the Free Software
Foundation.
8. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
9. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
10. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
Appendix: How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to humanity, the best way to achieve this is to make it
free software which everyone can redistribute and change under these
terms.
To do so, attach the following notices to the program. It is safest to
attach them to the start of each source file to most effectively convey
the exclusion of warranty; and each file should have at least the
"copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) 19yy <name of author>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 1, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) 19xx name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the
appropriate parts of the General Public License. Of course, the
commands you use may be called something other than `show w' and `show
c'; they could even be mouse-clicks or menu items--whatever suits your
program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the
program `Gnomovision' (a program to direct compilers to make passes
at assemblers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
That's all there is to it!

219
dmake/_install Normal file
View File

@ -0,0 +1,219 @@
INSTALLATION INSTRUCTIONS
This file contains the instructions required to install and create the
appropriate version of dmake.
NOTE: If you use dmake to bootstrap a NEW DISTRIBUTED version or to remake
it after applying a PATCH, it may be NECESSARY to use the batch
script instead of dmake as a patch may incorporate changes to the
makefile.mk file and associated config.mk files that cannot be
handled by earlier versions of dmake. The use of the batch files
is the ONLY supported method of making a new release or update
version.
NOTE: If you do not plan to use the MAKESTARTUP variable in your
environment, change the value of the variable in the file
"./unix/startup.h" BEFORE you bootstrap this package.
NOTE: NAME_MAX is used in sysintf.c to limit the name of a file name
component before performing a stat operation. If you have problems
with file name lengths make certain that NAME_MAX is correctly set.
NAME_MAX is set either in limits.h or in unistd.h (for POSIX systems)
or in stdio.h. If it is not set anywhere then dmake's own "posix.h"
file will define a reasonable default value, this may or may not be
reasonable for your system. If you have trouble with long file names
then hunt down the NAME_MAX definition.
NOTE: This file should really be rewritten :-)
MAKING THE PROPER VERSION
The list of available versions of dmake has grown quite large. The best
method to determine what versions are available for your configuration is to
simply issue the command 'make' in the source root directory. Below is a
partial list of the available versions to give an idea of what is supported.
Note that this copy of the list is not maintained up to date.
bsd43 - Generic BSD 4.3 (eg, true BSD, apollo, Sun OS4, SGI etc)
bsd43uw - Generic BSD 4.3 at U of Waterloo
bsd43vf - Generic BSD with no vfprintf in its library (use this
target if you are missing the vfprintf function in your
C library)
sysvr3 - Generic SysV R3 UNIX
sysvr1 - Generic SysV R1 UNIX
386ix - 386/ix (SysV R3), not tested
dynix - Sequent Symmetry dynix
ultrix - Ultrix 3.0 system
mips - Any MIPS box
os2msc60 - OS/2 with MSC 6.0
tos - Atari-ST using GCC as compiler
tcc - DOS with tcc 2.0
tccswp - swapping DOS version with tcc 2.0
msc60 - DOS with MSC 6.0
msc60swp - swapping DOS version with MSC 6.0
The file 'makefile' understands these targets and runs the appropriate script
to create the correct version.
The source code is organized as follows:
dmake [source for all common functions]
|
|
----------------------------
| | | |
unix tos os2 msdos [source for OS specific functions]
| | |
-------------------- mscdos -------------------
| | | | | |
386ix bsd43 sysvr[134] tccdos bccdos mscdos [source for OSRELEASE
| specific functions]
--------
| |
uw vf [source for OSENVIRONMENT specific functions]
Each of the directories (eg. bsd43, mscdos, tccdos, and sysvr3) contain source
that is specific to that release of the OS (and possibly C-library)
To make the appropriate versions of dmake, simply type the command
'make system'
where system is one of the supplied possibilities. Note that if you are using
an earlier version of dmake to make a new version from scratch then you must
use the command:
'dmake -f makefile system'
as dmake by default first reads makefile.mk and would thus use the wrong
makefile for bootstrapping purposes.
The bootstrapping of dmake is accomplished by running a shell script with the
appropriate compile commands hard coded.
(NOTE: If you are using MSDOS then, you will actually be using the make.bat
scriptfile to make the correct version of dmake for MSDOS. If you
are running a SHELL other than command.com, you may have to perform
some extra work to invoke the batch file.
Make sure you read the readme/msdos file before attempting to make the
MSDOS version, as it contains important configuration and limitation
information.)
The making of dmake, echoes the commands being executed, and should proceed
relatively error free. Ignore ANY warnings produced by the compile
They have all be verified and are spurious noise.
UNIX SYSV R3 AND GETCWD
Some versions of UNIX SysV R3 and Xenix use the popen call to capture the
output of pwd when invoking the C library function getcwd(). These versions
of the function cause dmake to terminate with the "lost a child" message
due to the fact that the parent dmake process may catch the pwd and not
recognize it as a child. For systems that have this problem use the version
of dmake that supplies its own getcwd function. The settings are:
OS = unix
OSRELEASE = sysvr3
OSENVIRONMENT = pwd
It is directly available through the 'makefile' by typing one of:
make sysvr3pwd
make xenixpwd
both include the getcwd code but the xenixpwd target compiles for a Xenix
system.
UNIX and "limits.h"
Some compilers do not yet provide the "limits.h" file, if yours is one of
these then simply copy the file "namemax.h" in the source root directory to
"limits.h". Make sure the length of a file name is correctly set in
"limits.h" as it is processed prior to "namemax.h".
STARTUP FILE
dmake requires the loading of a startup file when it is invoked. The
path for the startup file is set in the file 'startup.h' found in the
appropriate system sub-directories. You may override the value of the
path variable compiled-in by creating a file at the root source directory
called startup.h and inserting into that file a definition that is like
the definition found in the supplied startup.h files. Alternatively you
can modify the MAKESTARTUP environment variable to point at the location
of your startup.mk file.
INSTALLATION
To install dmake you must copy the executable to where your system
locates executables, and you must place a copy of startup.mk (found in the
root source directory after the build is successfuly completed) into a location
corresponding to the value of the MAKESTARTUP macro or environment variable.
You are free to customize the contents of startup.mk.
To make dmake again, (using itself), you will have to set three environment
variables. See the files in readme/options for their names and their legal
values. Once set you can invoke dmake to make itself.
DOCUMENTATION
All documentation for dmake appears under the man directory.
The file dmake.tf included in this distribution contains the troff
source for the man page. You must typeset it using the -man macros.
If you cannot typeset it, the file dmake.p is a version that has been
typeset for a normal dumb terminal. The file dmake.p contains control
characters. The file dmake.nc is a version of the man page that has
all of the control characters stripped.
CREATING A NEW VERSION
To create yet another version of dmake you should follow the following steps.
The sysvr3 version as sent is the base version, all dmake versions must provide
the equivalent of the functions defined in the sysvr3 directory, and MUST
provide the same semantics (MSDOS archive lib searches are an exception since
we cannot search libraries for timestamps in MSDOS, Actually the MKS version
of dmake does this, I don't have the inclination to add this code though).
1. Create a new directory for the version you will be making at the level
that is appropriate. If it is a new OS then add the dir at the top level,
if it is a new version of UNIX then add it below the unix directory.
2. Copy the files from the unix and unix/sysvr3 directories to the new dir.
(Or from any other directory sub-tree that is more appropriate)
3. Not all OS/OSRELEASE combinations are compatible so in order to make
dmake on each, the particular directory may contain C-source for functions
present in the SVID SysV R3 distribution which are used by dmake but are
not supplied by the C-library in the target system. For example the bsd43
directory contains source for tempnam.c since it is not provided with
the BSD C-library. Before writing a new version of the source file
check the other directories to see if one already exists.
4. Under some systems the standard include files may be missing or incorrect.
eg. under BSD stdarg.h and string.h. If this is the case
you should create the proper .h file in the proper directory.
This works as expected as the compile line includes the flag -Idir
where dir is the configuration dir, (bsd43 for example) and any
standard include files will be searched for in dir before the compiler
looks in the normal places (if you have a sane compiler :-).
5. Modify dmake.sh to contain the appropriate C compiler flags and link command
and to include any specific C files that you have had to add for this
version of dmake, and run the result through the shell.
(make the same changes to config.mk so that once you have a working copy of
dmake you can use it to bring itself up to date)
6. Send me the changes :-) so that I can incorporate them into future
distributions.
7. This should be all that you require to create a new version of dmake.
If you have any questions send e-mail to dvadura@plg.uwaterloo.ca

71
dmake/alloc.h Normal file
View File

@ -0,0 +1,71 @@
/* RCS -- $Header: /u/dvadura/src/generic/dmake/src/RCS/alloc.h,v 1.2 1992/04/07 04:42:46 dvadura Exp $
-- SYNOPSIS -- macros for allocating memory.
--
-- DESCRIPTION
-- A somewhat nicer interface to malloc and calloc.
-- Here we standardise the calling convention with a common macro
-- interface.
--
-- AUTHOR
-- Dennis Vadura, dvadura@watdragon.uwaterloo.ca
-- CS DEPT, University of Waterloo, Waterloo, Ont., Canada
--
-- COPYRIGHT
-- Copyright (c) 1990 by Dennis Vadura. All rights reserved.
--
-- This program is free software; you can redistribute it and/or
-- modify it under the terms of the GNU General Public License
-- (version 1), as published by the Free Software Foundation, and
-- found in the file 'LICENSE' included with this distribution.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warrant of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program; if not, write to the Free Software
-- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
--
-- LOG
-- $Log: alloc.h,v $
* Revision 1.2 1992/04/07 04:42:46 dvadura
* Added a !defined(_SIZE_T_) to satisfy Silicon Graphics IRIX.
*
* Revision 1.1 1992/01/24 03:26:54 dvadura
* dmake Version 3.8, Initial revision
*
*/
#ifndef ALLOC_h
#define ALLOC_h
/* DO NOT CHANGE these! These are the definitions that the make source
* uses for allocating memory. They must be defined for make to compile
* properly.
*/
/* This is the only place that we define size_t now. This should be more
* than enough! */
#if __STDC__
#else
# if !defined(_TYPES_) && !defined(M_XENIX) && !defined(atarist) && !defined(_MPW) && !defined(_SIZE_T) && !defined(_SIZE_T_)
# if defined(MSDOS) || defined(__MSDOS__)
# undef size_t
typedef unsigned size_t;
# else
typedef long size_t;
# endif
# endif
#endif
#define usizeof(t) (size_t)sizeof(t)
#define FREE(p) free((char*)(p))
#define MALLOC(n, t) (t*) malloc((unsigned int)(n)*usizeof(t))
#define CALLOC(n, t) (t*) calloc((unsigned int)(n), usizeof(t))
#define TALLOC(p, n, t) if ((p = CALLOC(n, t)) == (t*)0) {No_ram();}
#endif

55
dmake/basename.c Normal file
View File

@ -0,0 +1,55 @@
/* RCS -- $Header: /u2/dvadura/src/generic/dmake/src/RCS/basename.c,v 1.1 1992/01/24 03:26:56 dvadura Exp $
-- SYNOPSIS -- return pointer to last pathname component
--
-- DESCRIPTION
-- take a file name like /fred/foo/hoe/mary.k, and return the 'mary.k'
-- portion
--
-- AUTHOR
-- Dennis Vadura, dvadura@watdragon.uwaterloo.ca
-- CS DEPT, University of Waterloo, Waterloo, Ont., Canada
--
-- COPYRIGHT
-- Copyright (c) 1990 by Dennis Vadura. All rights reserved.
--
-- This program is free software; you can redistribute it and/or
-- modify it under the terms of the GNU General Public License
-- (version 1), as published by the Free Software Foundation, and
-- found in the file 'LICENSE' included with this distribution.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warrant of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program; if not, write to the Free Software
-- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
--
-- LOG
-- $Log: basename.c,v $
* Revision 1.1 1992/01/24 03:26:56 dvadura
* dmake Version 3.8, Initial revision
*
*/
#include "extern.h"
PUBLIC char*
basename( path )
char *path;
{
char *p;
char *q;
if( *(q = path) ) {
for(; *(p=_strpbrk(q, DirBrkStr)) != '\0'; q = p+1 );
if( !*q ) {
for( p=q-1; p != path; --p )
if( strchr( DirBrkStr, *p ) == NIL(char) ) return( p+1 );
return( strchr(DirBrkStr, *p)?path:(p+1) );
}
path = q;
}
return( path );
}

497
dmake/dag.c Normal file
View File

@ -0,0 +1,497 @@
/* RCS -- $Header: /u2/dvadura/src/generic/dmake/src/RCS/dag.c,v 1.1 1992/01/24 03:26:55 dvadura Exp $
-- SYNOPSIS -- Routines to construct the internal dag.
--
-- DESCRIPTION
-- This file contains all the routines that are responsible for
-- defining and manipulating all objects used by the make facility.
--
-- AUTHOR
-- Dennis Vadura, dvadura@watdragon.uwaterloo.ca
-- CS DEPT, University of Waterloo, Waterloo, Ont., Canada
--
-- COPYRIGHT
-- Copyright (c) 1990 by Dennis Vadura. All rights reserved.
--
-- This program is free software; you can redistribute it and/or
-- modify it under the terms of the GNU General Public License
-- (version 1), as published by the Free Software Foundation, and
-- found in the file 'LICENSE' included with this distribution.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warrant of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program; if not, write to the Free Software
-- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
--
-- LOG
-- $Log: dag.c,v $
* Revision 1.1 1992/01/24 03:26:55 dvadura
* dmake Version 3.8, Initial revision
*
*/
#include "extern.h"
PUBLIC HASHPTR
Get_name( name, tab, define )/*
===============================
Look to see if the name is defined, if it is then return
a pointer to its node, if not return NIL(HASH).
If define is TRUE and the name is not found it will be added. */
char *name; /* name we are looking for */
HASHPTR *tab; /* the hash table to look in */
int define; /* TRUE => add to table */
{
register HASHPTR hp;
register char *p;
uint16 hv;
uint32 hash_key;
DB_ENTER( "Get_name" );
DB_PRINT( "name", ("Looking for %s", name) );
hp = Search_table( tab, name, &hv, &hash_key );
if( hp == NIL(HASH) && define ) {
/* Check to make sure that CELL name contains only printable chars */
for( p=name; *p; p++ )
if( !isprint(*p) && !iswhite(*p) && *p != '\n' )
Fatal( "Name contains non-printable character [0x%02x]", *p );
TALLOC( hp, 1, HASH ); /* allocate a cell and add it in */
hp->ht_name = _strdup( name );
hp->ht_hash = hash_key;
hp->ht_next = tab[ hv ];
tab[ hv ] = hp;
DB_PRINT( "name", ("Adding %s", name) );
}
DB_PRINT( "name",("Returning: [%s,%lu]",
(hp == NIL(HASH)) ? "":hp->ht_name, hv) );
DB_RETURN( hp );
}
PUBLIC HASHPTR
Search_table( tab, name, phv, phkey )
HASHPTR *tab;
char *name;
uint16 *phv;
uint32 *phkey;
{
HASHPTR hp;
*phv = Hash( name, phkey );
for( hp = tab[ *phv ]; hp != NIL(HASH); hp = hp->ht_next )
if( hp->ht_hash == *phkey
&& !strcmp(hp->ht_name, name) )
break;
return( hp );
}
PUBLIC HASHPTR
Def_macro( name, value, flags )/*
=================================
This routine is used to define a macro, and it's value.
The flags indicates if it is a permanent macro or if it's value
can be redefined. A flags of M_PRECIOUS means it is a precious
macro and cannot be further redefined. If the flags flag also
contains the M_MULTI bit it means that the macro can be redefined
multiple times and no warning of the redefinitions should be issued.
Once a macro's VAR flags are set they are preserved through all future
macro definitions.
Macro definitions that have one of the variable bits set are treated
specially. In each case the hash table entry var field points at the
global variable that can be set by assigning to the macro.
bit valued global vars must be computed when the macro value is changed.
char valued global vars must have the first char of ht_value copied to
them. string valued global vars have the same value as ht_value and should
just have the new value of ht_value copied to them. */
char *name; /* macro name to define */
char *value; /* macro value to set */
int flags; /* initial ht_flags */
{
register HASHPTR hp;
register char *p, *q;
DB_ENTER( "Def_macro" );
DB_PRINT( "mac", ("Defining macro %s = %s, %x", name, value, flags) );
/* check to see if name is in the table, if so then just overwrite
the previous definition. Otherwise allocate a new node, and
stuff it in the hash table, at the front of any linked list */
if( Readenv ) flags |= M_LITERAL|M_EXPANDED;
hp = Get_name( name, Macs, TRUE );
if( (hp->ht_flag & M_PRECIOUS) && !(flags & M_FORCE) ) {
Warning( "Macro `%s' cannot be redefined", name );
DB_RETURN( hp );
}
/* Make sure we don't export macros whose names contain legal macro
* assignment operators, since we can't do proper quoting in the
* environment. */
if( *_strpbrk(name, "*+:=") != '\0' ) flags |= M_NOEXPORT;
if( hp->ht_value != NIL(char) ) FREE( hp->ht_value );
if( (hp->ht_flag & M_USED) && !((flags | hp->ht_flag) & M_MULTI) )
Warning( "Macro `%s' redefined after use", name );
if( (value != NIL(char)) && (*value) ) {
/* strip out any \<nl> combinations where \ is the current CONTINUATION
* char */
for( p = value; (p = strchr(p, CONTINUATION_CHAR)) != NIL(char); )
if( p[1] == '\n' )
strcpy( p, p+2 );
else
p++;
if( !(flags & M_LITERAL) ) {
p = _strdup( _strspn( value, " \t" ) ); /* strip white space before */
/* ... and after value */
if( *p ) {
for(q=p+strlen(p)-1; ((*q == ' ')||(*q == '\t')); q--);
*++q = '\0';
}
flags &= ~M_LITERAL;
}
else
p = _strdup( value ); /* take string literally */
if( !*p ) { /* check if result is "" */
FREE( p );
p = NIL(char);
flags |= M_EXPANDED;
}
else if( *_strpbrk( p, "${}" ) == '\0' )
flags |= M_EXPANDED;
hp->ht_value = p;
}
else
hp->ht_value = NIL(char);
/* Assign the hash table flag less the M_MULTI flag, it is used only
* to silence the warning. But carry it over if it was previously
* defined in ht_flag, as this is a permanent M_MULTI variable. */
hp->ht_flag = (flags & ~(M_MULTI|M_FORCE)) |
(hp->ht_flag & (M_VAR_MASK | M_MULTI));
/* Check for macro variables and make the necessary adjustment in the
* corresponding global variables */
if( hp->ht_flag & M_VAR_MASK )
if( !(flags & M_EXPANDED) )
Error( "Macro variable '%s' must be assigned with :=", name );
else switch( hp->ht_flag & M_VAR_MASK ) /* only one var type per var */
{
case M_VAR_STRING:
*hp->MV_SVAR = hp->ht_value;
break;
case M_VAR_CHAR:
*hp->MV_CVAR = (hp->ht_value == NIL(char)) ? '\0':*hp->ht_value;
break;
case M_VAR_INT: {
int tvalue;
if( hp->MV_IVAR == NIL(int) ) break; /* first time */
tvalue = atoi(hp->ht_value);
if( hp->MV_IVAR == &Buffer_size ) {
/* If Buffer_size is modified then make sure you change the
* size of the real buffer as well. */
tvalue = (tvalue < (BUFSIZ-2)) ? BUFSIZ : tvalue+2;
if( Buffer_size == tvalue ) break;
if( Buffer ) FREE(Buffer);
if((Buffer=MALLOC(tvalue, char)) == NIL(char)) No_ram();
*Buffer = '\0';
}
*hp->MV_IVAR = tvalue;
if( hp->MV_IVAR == &Max_proc || hp->MV_IVAR == &Max_proclmt ) {
if( tvalue < 1 )
Fatal( "Process limit value must be > 1" );
if( Max_proc > Max_proclmt )
Fatal( "Specified # of processes exceeds limit of [%d]",
Max_proclmt );
}
} break;
case M_VAR_BIT:
/* Bit variables are set to 1 if ht_value is not NULL and 0
* otherwise */
if( hp->ht_value == NIL(char) )
*hp->MV_BVAR &= ~hp->MV_MASK;
else
*hp->MV_BVAR |= hp->MV_MASK;
break;
}
DB_RETURN( hp );
}
PUBLIC CELLPTR
Def_cell( name )/*
==================
Take a string passed in and define it as a cell
If the cell exists then return a pointer to it. */
char *name;
{
register HASHPTR hp;
register CELLPTR cp;
register CELLPTR lib;
char *member;
char *end;
DB_ENTER( "Def_cell" );
/* Check to see if the cell is a member of the form lib(member) or
* lib((symbol)) and handle the cases appropriately.
* What we do is we look at the target, if it is of the above two
* forms we get the lib, and add the member/symbol to the list of
* prerequisites for the library. If this is a symbol name def'n
* we additionally add the attribute A_SYMBOL, so that stat can
* try to do the right thing. */
if( ((member = strchr(name, '(')) != NIL(char)) &&
((end = strrchr(member, ')')) != NIL(char)) &&
(member > name) && (member[-1] != '$') &&
(end > member+1) && (end[1] == '\0') )
{
*member++ = *end = '\0';
if( (*member == '(') && (member[strlen(member)-1] == ')') ) {
member[ strlen(member)-1 ] = '\0';
cp = Def_cell( member+1 );
cp->ce_attr |= A_SYMBOL;
}
else
cp = Def_cell( member );
lib = Def_cell( name );
Add_prerequisite( lib, cp, FALSE, FALSE );
lib->ce_attr |= A_LIBRARY | A_COMPOSITE;
if( !Def_targets ) cp = lib;
}
else {
hp = Get_name( name, Defs, TRUE );/* get the name from hash table */
if( hp->CP_OWNR == NIL(CELL) ) /* was it previously defined */
{ /* NO, so define a new cell */
DB_PRINT( "cell", ("Defining cell [%s]", name) );
TALLOC( cp, 1, CELL );
hp->CP_OWNR = cp;
cp->ce_name = hp;
cp->ce_fname = hp->ht_name;
}
else /* YES, so return the old cell */
{
DB_PRINT( "cell", ("Getting cell [%s]", hp->ht_name) );
cp = hp->CP_OWNR;
}
}
DB_RETURN( cp );
}
PUBLIC LINKPTR
Add_prerequisite( cell, prq, head, force )/*
============================================
Add a dependency node to the dag. It adds it to the prerequisites,
if any, of the cell and makes certain they are in linear order.
If head == 1, then add to head of the prerequisite list, else
add to tail. */
CELLPTR cell;
CELLPTR prq;
int head;
int force;
{
register LINKPTR lp, tlp;
DB_ENTER( "Add_prerequisite" );
DB_PRINT( "cell", ("Defining prerequisite %s", prq->CE_NAME) );
if( (prq->ce_flag & (F_MAGIC | F_PERCENT)) && !force )
Fatal( "Special target [%s] cannot be a prerequisite",
prq->CE_NAME );
if( cell->ce_prq == NIL(LINK) ) { /* it's the first one */
TALLOC( lp, 1, LINK );
lp->cl_prq = prq;
cell->ce_prq = lp;
}
else { /* search the list, checking for duplicates */
for( lp = cell->ce_prq;
(lp->cl_next != NIL(LINK)) && (lp->cl_prq != prq);
lp = lp->cl_next );
/* If the prq is not found and we are at the last prq in the list,
* allocate a new prq and place it into the list, insert it at the
* head if head == 1, else we add it to the end. */
if( lp->cl_prq != prq ) {
TALLOC( tlp, 1, LINK );
tlp->cl_prq = prq;
if( head ) {
tlp->cl_next = cell->ce_prq;
cell->ce_prq = tlp;
}
else
lp->cl_next = tlp;
lp = tlp;
}
}
DB_RETURN( lp );
}
PUBLIC void
Clear_prerequisites( cell )/*
=============================
Clear out the list of prerequisites, freeing all of the LINK nodes,
and setting the list to NULL */
CELLPTR cell;
{
LINKPTR lp, tlp;
DB_ENTER( "Clear_prerequisites" );
DB_PRINT( "cell", ("Nuking prerequisites") );
if( cell == NIL(CELL) ) { DB_VOID_RETURN; }
for( lp=cell->ce_prq; lp != NIL(LINK); lp=tlp ) {
tlp=lp->cl_next;
FREE( lp );
}
cell->ce_prq = NIL(LINK);
DB_VOID_RETURN;
}
PUBLIC int
Test_circle( cp, fail )/*
=========================
Actually run through the graph */
CELLPTR cp;
int fail;
{
register LINKPTR lp;
int res = 0;
DB_ENTER( "Test_circle" );
DB_PRINT( "tc", ("checking [%s]", cp->CE_NAME) );
if( cp->ce_flag & F_MARK )
if( fail )
Fatal("Detected circular dependency in graph at [%s]", cp->CE_NAME);
else
DB_RETURN( 1 );
cp->ce_flag |= F_MARK;
for( lp = cp->ce_prq; !res && lp != NIL(LINK); lp = lp->cl_next )
res = Test_circle( lp->cl_prq, fail );
cp->ce_flag ^= F_MARK;
DB_RETURN( res );
}
PUBLIC STRINGPTR
Def_recipe( rcp, sp, white_too, no_check )/*
=============================================
Take the recipe and add it to the list of recipes
pointed to by sp. sp points to the last element.
return a pointer to the new recipe. If white_too == TRUE add the
recipe even if it contains only white space.
If no_check is true then don't look for -@ at the start of the
recipe line. */
char *rcp;
STRINGPTR sp;
int white_too;
int no_check;
{
register STRINGPTR nsp;
register char *rp;
DB_ENTER( "Def_recipe" );
DB_PRINT( "rul", ("Defining recipe %s", rcp) );
if( !white_too ) rcp = _strspn( rcp, " \t" );
if( (rcp == NIL(char)) || (*rcp == 0 && !white_too) )
DB_RETURN( sp ); /* return last recipe when new recipe not added */
rp = no_check ? rcp : _strspn( rcp, " \t@-+%" );
TALLOC( nsp, 1, STRING );
nsp->st_string = _strdup( rp );
if( sp != NIL(STRING) ) sp->st_next = nsp;
nsp->st_next = NIL(STRING);
if( !no_check ) nsp->st_attr |= Rcp_attribute( rcp );
DB_RETURN( nsp );
}
PUBLIC t_attr
Rcp_attribute( rp )/*
======================
Look at the recipe and return the set of attributes that it defines. */
char *rp;
{
t_attr flag = A_DEFAULT;
int done = FALSE;
while( !done )
switch( *rp++ )
{
case '@' : flag |= A_SILENT; break;
case '-' : flag |= A_IGNORE; break;
case '+' : flag |= A_SHELL; break;
case '%' : flag |= A_SWAP; break;
case ' ' :
case '\t': break;
default: done = TRUE; break;
}
return(flag);
}

75
dmake/db.h Normal file
View File

@ -0,0 +1,75 @@
/* RCS -- $Header: /u2/dvadura/src/generic/dmake/src/RCS/db.h,v 1.1 1992/01/24 03:29:35 dvadura Exp $
-- SYNOPSIS -- front end to DBUG macros.
--
-- DESCRIPTION
-- This is a front end to Fred Fish's DBUG macros. The intent was
-- to provide an interface so that if you don't have the DBUG code
-- you can still compile dmake, by undefining DBUG, if you do have
-- the code then you can use Fred Fish's DBUG package. Originally
-- the DBUG stuff was copyrighted, it is now in the public domain
-- so the need for this is not as apparent.
--
-- AUTHOR
-- Dennis Vadura, dvadura@watdragon.uwaterloo.ca
-- CS DEPT, University of Waterloo, Waterloo, Ont., Canada
--
-- COPYRIGHT
-- Copyright (c) 1990 by Dennis Vadura. All rights reserved.
--
-- This program is free software; you can redistribute it and/or
-- modify it under the terms of the GNU General Public License
-- (version 1), as published by the Free Software Foundation, and
-- found in the file 'LICENSE' included with this distribution.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warrant of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program; if not, write to the Free Software
-- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
--
-- LOG
-- $Log: db.h,v $
* Revision 1.1 1992/01/24 03:29:35 dvadura
* dmake Version 3.8, Initial revision
*
*/
#ifndef DB_h
#define DB_h
#ifdef DBUG
# include "dbug.h"
# define DB_ENTER(a1) DBUG_ENTER(a1)
# define DB_RETURN(a1) DBUG_RETURN(a1)
# define DB_VOID_RETURN DBUG_VOID_RETURN
# define DB_EXECUTE(keyword, a1) DBUG_EXECUTE(keyword,a1)
# define DB_PRINT(keyword,arglist) DBUG_PRINT(keyword,arglist)
# define DB_PUSH(a1) DBUG_PUSH(a1)
# define DB_POP() DBUG_POP()
# define DB_PROCESS(a1) DBUG_PROCESS(a1)
# define DB_FILE(file) DBUG_FILE(file)
# define DB_SETJMP DBUG_SETJMP
# define DB_LONGJMP DBUG_LONGJMP
#else
# define DB_ENTER(a1)
# define DB_RETURN(a1) return (a1)
# define DB_VOID_RETURN return
# define DB_EXECUTE(keyword, a1)
# define DB_PRINT(keyword,arglist)
# define DB_PUSH(a1)
# define DB_POP()
# define DB_PROCESS(a1)
# define DB_FILE(file)
# define DB_SETJMP setjmp
# define DB_LONGJMP longjmp
#endif
#endif

13
dmake/dbug/README Normal file
View File

@ -0,0 +1,13 @@
This directory contains two public domain debugging packages.
1. Fred Fishes DEBUG macros.
2. Connor P. Cahills malloc library.
Descriptions of both can be found in their respective sub-directories. dbug
for the DEBUG macros and malloc for the malloc library. I have left the
malloc distribution intact as it comes from the net except for the changes
noted in the _changes file.
I thank the authors for making them available for others to use.
-dennis

66
dmake/dbug/dbug.mk Normal file
View File

@ -0,0 +1,66 @@
# Set the proper macros based on whether we are making the debugging version
# or not. The valid parameters to this file are:
#
# DEBUG=1 ==> enable the making of the DBUG version
# DBMALLOC=1 ==> enable DBUG version with extensive MALLOC checking
#
# DB_CFLAGS ==> CFLAGS is set to this value at the end if DEBUG=1
# DB_LDFLAGS ==> LDFLAGS is set to this at the end if DEBUG=1
# DB_LDLIBS ==> LDLIBS is set to this at end if DEBUG=1
#
# The non debug versions of the above three macros are:
#
# NDB_CFLAGS
# NDB_LDFLAGS
# NDB_LDLIBS
#
# One of the set of three should have values set appropriately prior to
# sourcing this file.
.IF $(DEBUG)
DBUG_SRC += dbug.c
DB_CFLAGS += -Idbug/dbug
.SETDIR=dbug/dbug : $(DBUG_SRC)
# If DBMALLOC is requested (ie non-NULL) then include the sources for
# compilation. BSD 4.3 needs the getwd.c source compiled in due to a bug
# in the clib getwd routine.
.IF $(DBMALLOC)
# Serious bug in bsd43 getwd.c would free a string and then use its
# value. The DBMALLOC code clears a string when it is free'd so the
# value was no longer valid and the returned path for the current
# directory was now completely wrong.
.IF $(OSRELEASE) == bsd43
GETWD_SRC += getwd.c
.SETDIR=dbug : $(GETWD_SRC)
.END
MLC_SRC += malloc.c free.c realloc.c calloc.c string.c\
mlc_chk.c mlc_chn.c memory.c tostring.c m_perror.c\
m_init.c mallopt.c dump.c
.SETDIR=dbug/malloc : $(MLC_SRC)
DB_CFLAGS += -Idbug/malloc
.END
SRC += $(DBUG_SRC) $(MLC_SRC) $(GETWD_SRC)
HDR += db.h
LDFLAGS += $(DB_LDFLAGS)
LDLIBS += $(DB_LDLIBS)
SILENT := $(.SILENT)
.SILENT := yes
TARGET := db$(TARGET)
OBJDIR := $(OBJDIR).dbg
.SILENT := $(SILENT)
CFLAGS += $(DB_CFLAGS)
.KEEP_STATE := _dbstate.mk
.ELSE
CFLAGS += $(NDB_CFLAGS)
LDFLAGS += $(NDB_LDFLAGS)
LDLIBS += $(NDB_LDLIBS)
.END

6
dmake/dbug/dbug/README Normal file
View File

@ -0,0 +1,6 @@
To unpack the DBUG manual page please issue the following sequence of
commands:
uudecode dbug.uue
uncompress dbug.Z
mv dbug dbug.p

1832
dmake/dbug/dbug/dbug.c Normal file

File diff suppressed because it is too large Load Diff

164
dmake/dbug/dbug/dbug.h Normal file
View File

@ -0,0 +1,164 @@
/******************************************************************************
* *
* N O T I C E *
* *
* Copyright Abandoned, 1987, Fred Fish *
* *
* *
* This previously copyrighted work has been placed into the public *
* domain by the author and may be freely used for any purpose, *
* private or commercial. *
* *
* Because of the number of inquiries I was receiving about the use *
* of this product in commercially developed works I have decided to *
* simply make it public domain to further its unrestricted use. I *
* specifically would be most happy to see this material become a *
* part of the standard Unix distributions by AT&T and the Berkeley *
* Computer Science Research Group, and a standard part of the GNU *
* system from the Free Software Foundation. *
* *
* I would appreciate it, as a courtesy, if this notice is left in *
* all copies and derivative works. Thank you. *
* *
* The author makes no warranty of any kind with respect to this *
* product and explicitly disclaims any implied warranties of mer- *
* chantability or fitness for any particular purpose. *
* *
******************************************************************************
*/
/*
* FILE
*
* dbug.h user include file for programs using the dbug package
*
* SYNOPSIS
*
* #include <local/dbug.h>
*
* SCCS ID
*
* @(#)dbug.h 1.11 9/5/87
*
* DESCRIPTION
*
* Programs which use the dbug package must include this file.
* It contains the appropriate macros to call support routines
* in the dbug runtime library.
*
* To disable compilation of the macro expansions define the
* preprocessor symbol "DBUG_OFF". This will result in null
* macros expansions so that the resulting code will be smaller
* and faster. (The difference may be smaller than you think
* so this step is recommended only when absolutely necessary).
* In general, tradeoffs between space and efficiency are
* decided in favor of efficiency since space is seldom a
* problem on the new machines).
*
* All externally visible symbol names follow the pattern
* "_db_xxx..xx_" to minimize the possibility of a dbug package
* symbol colliding with a user defined symbol.
*
* The DBUG_<N> style macros are obsolete and should not be used
* in new code. Macros to map them to instances of DBUG_PRINT
* are provided for compatibility with older code. They may go
* away completely in subsequent releases.
*
* AUTHOR
*
* Fred Fish
* (Currently employed by Motorola Computer Division, Tempe, Az.)
* hao!noao!mcdsun!fnf
* (602) 438-3614
*
*/
/*
* Internally used dbug variables which must be global.
*/
#ifndef DBUG_OFF
extern int _db_on_; /* TRUE if debug currently enabled */
extern FILE *_db_fp_; /* Current debug output stream */
extern char *_db_process_; /* Name of current process */
extern int _db_keyword_ (); /* Accept/reject keyword */
extern void _db_push_ (); /* Push state, set up new state */
extern void _db_pop_ (); /* Pop previous debug state */
extern void _db_enter_ (); /* New user function entered */
extern void _db_return_ (); /* User function return */
extern void _db_pargs_ (); /* Remember args for line */
extern void _db_doprnt_ (); /* Print debug output */
extern void _db_setjmp_ (); /* Save debugger environment */
extern void _db_longjmp_ (); /* Restore debugger environment */
# endif
/*
* These macros provide a user interface into functions in the
* dbug runtime support library. They isolate users from changes
* in the MACROS and/or runtime support.
*
* The symbols "__LINE__" and "__FILE__" are expanded by the
* preprocessor to the current source file line number and file
* name respectively.
*
* WARNING --- Because the DBUG_ENTER macro allocates space on
* the user function's stack, it must precede any executable
* statements in the user function.
*
*/
# ifdef DBUG_OFF
# define DBUG_ENTER(a1)
# define DBUG_MALLOC(a1)
# define DBUG_RETURN(a1) return(a1)
# define DBUG_VOID_RETURN return
# define DBUG_EXECUTE(keyword,a1)
# define DBUG_PRINT(keyword,arglist)
# define DBUG_2(keyword,format) /* Obsolete */
# define DBUG_3(keyword,format,a1) /* Obsolete */
# define DBUG_4(keyword,format,a1,a2) /* Obsolete */
# define DBUG_5(keyword,format,a1,a2,a3) /* Obsolete */
# define DBUG_PUSH(a1)
# define DBUG_POP()
# define DBUG_PROCESS(a1)
# define DBUG_FILE (stderr)
# define DBUG_SETJMP setjmp
# define DBUG_LONGJMP longjmp
# else
# define DBUG_ENTER(a) \
auto char *_db_func_, *_db_file_; \
int _db_level_; \
_db_enter_ (a,__FILE__,__LINE__,&_db_func_,&_db_file_,&_db_level_)
# define DBUG_MALLOC(a) \
auto char *_db_func_, *_db_file_; \
int _db_level_; \
malloc_init();\
_db_enter_ (a,__FILE__,__LINE__,&_db_func_,&_db_file_,&_db_level_)
# define DBUG_LEAVE \
(_db_return_ (__LINE__, &_db_func_, &_db_file_, &_db_level_))
# define DBUG_RETURN(a1) return (DBUG_LEAVE, (a1))
/* define DBUG_RETURN(a1) {DBUG_LEAVE; return(a1);} Alternate form */
# define DBUG_VOID_RETURN DBUG_LEAVE; return
# define DBUG_EXECUTE(keyword,a1) \
{if (_db_on_) {if (_db_keyword_ (keyword)) { a1 }}}
# define DBUG_PRINT(keyword,arglist) \
{if (_db_on_) {_db_pargs_(__LINE__,keyword); _db_doprnt_ arglist;}}
# define DBUG_2(keyword,format) \
DBUG_PRINT(keyword,(format)) /* Obsolete */
# define DBUG_3(keyword,format,a1) \
DBUG_PRINT(keyword,(format,a1)) /* Obsolete */
# define DBUG_4(keyword,format,a1,a2) \
DBUG_PRINT(keyword,(format,a1,a2)) /* Obsolete */
# define DBUG_5(keyword,format,a1,a2,a3) \
DBUG_PRINT(keyword,(format,a1,a2,a3)) /* Obsolete */
# define DBUG_PUSH(a1) _db_push_ (a1)
# define DBUG_POP() _db_pop_ ()
# define DBUG_PROCESS(a1) (_db_process_ = a1)
# define DBUG_FILE (_db_fp_)
# define DBUG_SETJMP(a1) (_db_setjmp_ (), setjmp (a1))
# define DBUG_LONGJMP(a1,a2) (_db_longjmp_ (), longjmp (a1, a2))
# endif

368
dmake/dbug/dbug/dbug.uue Normal file
View File

@ -0,0 +1,368 @@
begin 650 dbug.Z
M'YV,"@*"&$BPH,&#" T2 2$$1!401P0FG&AP" @H<MZ<D1.F#0@B9<34.7,F
MC9LS%\.,61/F3!F)%&/*!"$F#\R9. <:D5.&# @C:>:@"4@481($1Y,Z0;"T
M*14$3Z-*03"UZA,$5[,20;"U:Q4$7\,.03"V;%2H4),B19H5*]:F3)D6C1F$
M39LW<^B *&.GC)P\(.!DW-@1!!F^9=B\@=.FC!N]CNVDR>BF\6,0=][(H8,&
M,(@W9A0@Y%QFH)N.I06_D7QX#H@Y;QJ_UJP7M.&0(TN>!&%&91HV:>CD<3&P
MRIPZ8=BPL3D:35 0=,*L*>.:]$ SFCU^-C,PS$#5A+7?<3X&S<#G(,:$@1-&
M#)O2VT4?'//F<4;E)E'NQ5-F3!TZ:=0WD&V?D29'8(-QU(9K8;CA4QEX=&12
M?M"A\1)")M'AUVELO!:=AML5:.&!$/;W'X7@*3@'<2!08>$<I0D'!W4#AH90
MBAVY=L=O'8I1&D]F^,633W2\ 4(8KD&HH1P<WB8227ZY-H=)8\1HH7P&'?:D
M2P<^Y\8;>K&W68C6E>@?@+OAV :+1438!ASON19?<^C)"!^!6N;FUWENC,%&
M'8<-9%T8"!!J*!D((*JH& @PZNB1#KZ&P!R33JIHHHDZVFBC3NHIQQQ8%J0:
M:SUA%IQYUH4%%EAP-:564E@@$.NL&^ 0 P*WYKI!#I_-R!&:*,V11UYEK#D7
M14^X49IMUJGF7K$,S@';&&F$H:%/.W)V6U^*P8%B@CF&2I!)W;DQ4&23U6>9
M7J9J"\(9;[SATWY+-MDIE)^"\!QGUHH[T&'<+E:JFG)J&"ET1H* 1AA]#00<
M'72\-^"!('S)9[W)^:NO&WG)4<>ZU@;H!HLM.B<G>G4<E]QRIH'9'8)O/.L1
M=@>2IC' B0E\X)1]EF:AOG.P\-F!UCI<!I+L"O5&'6S,ZZ/0&P/8AK6),7=0
M;VW\5BW%V9I7(7P9;IC<T&<TF(8>(=<G-!G6>M=Q'6/040=/06O<H$_TV?=&
MAV8H=@>9/ZM)4QD4WNL2&20GP2YZ86@,HQP!IDR0L^]IQYMF TT=]FD]?P=N
M&XU]"O5X"8?!D\9UN '<="P7J3##I1U7'F\2 F=Z<)YU+>C/,(<WD(_Y::SY
M8V&8U!/4=Y&1AAEI'#]T8+25ZGJ#8(ZXEQN24;8NBXIK_%QRL!T)L\Q"(V8N
MS5]OF[.O0H_G6/J]*^B]G'?U-:_KD%Z?O;J.Z:6[=X))0]8 U##,I0YK6C/=
MS7"#+Z%ASGP5,U*>\.6"8TTD6>FKWIX6YB"A?2%1'Q3#!^OP091\SUP0Z@B<
M[L2=_$5-;&Q8X);\PB(A]"<,*2M-<$# DSC483(T"AN3QF:2MX$,0 *R3>-N
M]#FAW4U?=)!3REH"'S*\@4819-=A9G0P 4'*,W.8$;4RAA#UL$<,6@,0%@ED
MG?V8"(GFTE^Z*M,_J.WP>VRX0QB&93<[%(\-[9'8$W>DG'/QYTQ@BV.#/(,N
M[?5O=T7[FL8$!T48L8$[A.R0F?ZCPY$-) GF"@,9E ='H?&L2E $VI$T1I\W
MO0=$@5$)2UPR$-V)[S5B7%X:QC"0'%),B+VI$M2.I)Q)?DY.F"&/UW)X'G9E
M\G?P&54:#C,O6TXI:X"4@PQS0R$SMB>-S5O10%STG'*:2RBF@T-ZZD,'CN0%
M80,RD 4)\H5ZVO.>-RE(#(A3!2<D 0NJ]$X[15DLTZTA1$&@@@FHP)#$=(@)
M[=&,M303S@H216,YD4D+0! #$+3@HA=%"!&$4(4C..1Q(&A"@Y#3H8S&Y EQ
MB]F>9) #H<4@!SBP04BOEAW7V$:(32IB.S_6O[29RWT\V8M*O(:S;NWI=:!J
M#N$H]H8[N$%H*6,IR^+D&F\^2V@T\\A/'P-#P]%08Z!\S<>F]A>A^4@]S/P@
M&4(XPA(&U%Q '=L$N91*:;:&E?69$K'Z!!B59$1:O?)+R';32/X])FB0\LE;
M<0BC5 :ECW\,9(R,M#+U.35?._0K%O,F6(.-P3.&Q4M4#])9@FTL?7- C1P=
M^1B+8K0@+BJ-7.F* !(B "7L60D5]?4FO-"H/BQS&W#.@ :]A+$, W-,<H3S
M&3=H;)/ BE^.A":C7:X,,&V FWFX6J$&<10&@?%+E1[C1 ?9#03)HXYSSY8:
MZ;)!.%#KKGJ4XYD8H!>>()#!?WVU7CJ03 A6RU(9F.>&PKDME\SCI44$4P;5
M5$E:F!-6&\2P-YI4#W#4*8UZK(L0'_&P)W"3GI'TX!<CZ<YBY6F02US3PQ\.
M25 ):R-LYE8EP![&MC+)[77VYK?" >>=JKRE#W=YT($<!W2F\TR(=G>A^:SG
MFP\+9XVH/)#=-JJNOXVE<%W"IJ6FY\IH?!A@1CPX[SDH#:S1*F"D^RR?8$YY
ML:WSD?1B':G!QSO:U<YE,82]-TQG7C21\G.I988\% Y^1X*#:@)(M8&T<FH'
M XZR[":',Q#UL1;-B9':]$:108<CJ'P-&JI:.#.D+FZF!L%[N&5I=M[GM@GI
M6U4+0JZ7.;E8:6@!8>! GN\2!-/*HA@(4A8\EYKD,,2#(SR?[5T0*2LO%-HB
M9T*-$R,]X3]P^$_Z_/BGXW)G90XDFAO 6 <QP(A=H(':=!*,D[QVR(^0T^R*
M\DD1(S%!@#L\$JP#BV-?+UJ7O/PUNZ9<,=20 =<(<76?X+AOB!?$WP#7B\0'
M;JZ!HG)ZN.R/+DMU[>QJ&PW<GHF_VY,8I<YN:70(MUXT71K=[5@.J&2>Q!HN
MF\A:W" TK]C'?"2'E,MDY3YJZ=%F]QEPBUO6QJOEJ4PCVRG[1PX\><S/1961
M"U=<U!=)F7DP!X?%7*RLABM<7BH-X)55=>L$P:ZI=2>2W^B%7'O-]H)Q>-^O
M=QL$4N@)$./&Y7L-R.E):^?1M(._M3O(= ]W*<QE/A 4Y,6*_TG!Q'Q]FL;,
M2^=E8)&0#],;IM$![H>/N;@[MO@D.YYM<IB7D# ' LO3X3!83P')<HOZ$RN/
M)QR';W\X&!2//*>5*]00RYY=8<= NS8VRNB7Y#"U#EWZB4$?TN"EW78[O&&:
MJ9=Y[_/6MUU&T;;S=*E& ^Q1D*;_(R0UJ7'VI%(WL%3]R(HIT0-<4X[B5*?O
M!P4((( $6!54016O@A1-@ +V( )F 1G$14/: 4(0($66 0(@($:^!%<T8%$
MH($9F(%"@ C6(*J$A9'@ IN((KJ((J^("MPA0MN((M@A91 8(:6!9D019(
M@ ]^(,QZ$]KD111@ !%>(0G"!8XF(%3@ !-^(3O9Q"@A#$=(E0><T2FAD<\
M(4J%13O8M#6UUC-P<'JC821W\4YJ$CJ0=4HZ='>ND57&9AW,\REZD7<GH3$:
M4AX-YD/P\1ZFHRR(@UMYX"W[M1S#) (!=!EKIR'K,@<B0!"F4V4&441^<2U\
M EM+@W,B)B^E431")%\H\GV/Q5T_0Q^',3\GAGR_42I/A%W.$UF%1S>F5SB3
M]W2#=A IE#6 ^%KF92V,.(;P=!A+HHLU-R)6DAH9(3- 8W0$(606AF))54Y+
M$C)],3I3YW)>$QR*Q7V.EAC*<X<(<1=)!8OPI1EW@GA0\T0*(S"NQE^%=W.H
MQ"Q7PD0Q4SFJA&?TT1<WYB,T<XQ-IWIZ\5:Q02-%8B391$M%LD!CTRY>0WL4
M)AE+,P<LLS&/8XD>0C6-:!K0121&XB,:PQ/UTQ,L A2>EE0==4+[H4(2(X_[
M,H@LY#D9!V>26!!VB!)YB 9[6 >AMU,Y,0)4\B>!P@.7%R N@ 8^P&\Q,3RU
M9SIG, 9.U&EVD *]ER%'TFECL /CMS 'H@),:0=;T 58Z5)[T'M<ER'<@0(B
MT)5; -= (] (E0 9<X 8B\)1GX)5LF0)AB7\@\ (J0)8%H0(#$7CO9!MJ
M I@$H0(O@)@(8I:U)P(]\)96I"QNV0-S*0)ZV7M]$(5\B1 D.3>E$0.,61 8
M$9,- Q);0B%4,'PY^1(@)1-%T!>/(6?I>#!PZ(Y'8@9+ HD+YX=(]AJ(P1$Q
MA"'32''YQ3N44RQ25TB#<SFIXQ-/1!]8UQ_7PB)!0(8'P1G/47890HJEH2QW
M,)&4N!FETIB7<9&,V#_TDS+LXI$(<1C3)77;1A#)LBQB )&2 QM_(FW[8B37
M!"> <1BO=(QM8#?*44-EH!O)]H8JXXY65"'?PQME\#=^]H:/\1M?XQD+TQ=X
MF# \,2.15"87FE3/B%C!"1A^)C[@21,C 3UP\(9P4$$((60PDC<^<8:U<9^1
M(R5[<R("TI^ST1BK]C>&$12:164:4XMT #6$8R"[DQ$CX34ZEHFH9(J;"#J/
M%$QIE <LP$I;*&U*9'CX5BW/ D\F-@?94AZEDD0' AIFD&Z)ACH\HQ]M9!$(
M4F%=1QVP470$\9E))0-WE9*NM"SG5DS-P1,QPIIIP(<5AY2=>1 ;-0/MYWX:
M,U(E=5+TMU(+^:@% 5-%LG\T95/_YWXNY9-] I2E(92W1Y1&Z:@30943Y)8@
M -8V7M*B0),Z915>9=2Z6R7D:M[F1,QMI5J"9:]-Y:=Z9?F20=GF990*:LE
M@ >7:9=1"0**R9C+4WL3I'F)R*R/J99L":UR29?4NI9=D)G)^I>/*IB )U\A
M<ICKNIBENCRD]Q%%$'^,V:W-&IF&41^E$9F7B:X9-0+.MSR:R9F<VJ=I4)*E
M(0.CJ1 ,]!%&6J:KJ8>+JI.@\IHQ401F=I.M"57-)">BY$?$,V/E,B]X-K(-
M$ATSIC&V1#=BQ"[X0P9YT'F[! )V("4?<K,J04!&94I4NHFGB!"KX1<6(DI"
M WRQX2V )&TU!D2-6#Y(0JB]!"-0 Z\'L85LDV:XPZ1T, 8D\P3ZR$Q3UD84
M5J)[.AO[*3(:LV0KL55'0P;5823)N2 ,.1L\)K3PH;58ACLG*SS%0SPFT;?4
ME4SO U^SN$(#,0((P+B.FP8( +F2:P8(0+F6>RF*4@8(H+F<:[F56[E.E@<;
MMC<B.XZNXYX'07K&8V<4\YP+MKJ_,[7SXD4'%V&"XI)R@B<,M$!3,B2B]S/P
MJ+=G9BXF-C6!(I$+VUPL(XX_$K>:I3$UH5;!<:3,%VVF)H^EX;B-V[B2&[F1
MZ[F7BRF9N[GDNV"?:[F[^FE1!$]3\[6H,H\'4;T[ZT5L5(J<Z%;B]B5ZT5D3
M]J%YBF'YXG9W@(<FLWN\@UR>\;0@^4B70S$Z%AV/%WO%L2IA$80/."NR(BL$
M,03&A*=OX'68\QSH8QTG, (GD!Y:V;-[,CV2=C1=TG$_,X=Y 5A_T@97]3M/
M!T$0*B<P BT.DP;3 8EQ5)5H-%!_(<21=Q"ILX6P<1IE>F(=8WXB0S)^"A^2
MBI*YJ+@LN5H&,45D1JD:F[ )L5$T,*FD>A"6*G\H57_W)\8#X:DR=2"AZG\Y
M=<8]^9. DJI#^09%>92V&KA+:974VJL9197 FI6F8ZW%&JPX@:P#.RYF4*\?
MB*^=J:_?"I7F*J[3NJMX>:Z,/!,C$'=O%GWXYY>CR:Z$"7V!=LKR^LCG$<D+
M9J^4S)>6C);\.IG_:IET*; ]*<K*0\HXL9FNZL95# (S\+!-8([M*DI'BA$>
M#,('8AQ4!,;47,UV[,8&L5$U8,9A7!!IC*D'PL:;*L9P#*K]=U-U_'Y&@ #K
MW,Y)V$]QT10Z:!8VF!9#R!9ND15!6(,1:(!5$00( - "/<]DL81% (&C<&S
M(M !'= -R( ,2( #.(!,@ 5?=$&C; #<04UQR,7.29N*FLNW&"[$5%/UT9>
M!4YK!,P$T49>)D*]95=B-DOP$;W+-J<O\Y\2HXO4%&C)M$M#449+RTG5$<,]
M2U%C$Z9"MV$T1!!I-32X5W"# S%^L4!WP3$#!4MMM''<YW&ET1@QUF!ST :D
MN)V? S3>,ZCK4BK -S=3PBW#H1,+"YH@4,;[\C-*R=6Q1C,$+,)'G6\=HB;H
M-Z^GFL<@H*K*P\>MZE+*.G\'XEI*PS0^P4P\H!C[]0)D\"1];*VM?,>%'2@B
MD-DC490B,,SA",BX*LB<3,@Y8<A6^<DR,:R*C,G&*I:,R1,E02POK!>R>%]"
MDP9X -LYH20;$C6T$U. 77LIX$1%D@;*7:N=F<9?4 1.0 5%( 6/.3R8*=PX
M(=U0( 5/, 1%, 53$,AW::Z\K'[H@P+ +:LQL /Z@@>'O:N\9 (FP,E; -Q=
MD,G\>@(M< +P#=PKL *:Y\B<BJ;!,3NI?=[ZO04Q<*X@8.!NK!Z55<(GH ,/
M2Q'>7053@ 2U9P(+[I4-+@/GFM[8_#M;N ;<[5*;V9DMSI?K'>#RS0/T+>,#
M7N 9#G\E]07?G035?<EGX(A"@Y9J&9=M^98E(.3Q7:[ZG0(FSI>]K1=O&4Q%
MDMRXVMSF+>)X4.(KGE&U+ )QN<E1_N0Y\>+X)]U24 144 52X 2U!P-D3A'"
MG.,44<PT0.=&\-?5TB$8H1$*DE*!2W/7G!!"U@8(8.B(;BB%4BC=*[EN@ "/
M'NF\\6K\*2<P&UAI\,3H S->YV#K!EA0=C!01YF]PGU,J;XB>S"D$4?(=R*[
MX7-,E"$4(H=ZGM3<L73F\25NT *+(6VGOCT\>>($L5$VP,W!3A#?[-B ;G_C
MG+#E/%/G/*H:_1.349B%R@9"H[^[9"5%TUG8:U8'HM>!Q6E@H];]4YZ2 6AG
M^[]I"U^I)4[C9#+]2B/ZNT >IW$9X1'6P;=<2UW?;J6P.#73X1HIZQ[-QEJ%
M%*NJV+2FUDYPMN=+^1KY(3'K_L%ZFF&BRV'87JD>R!4E2((D^,XSJ((?5/((
M\ 5MD17MS,[LO/+M#%::<6'I,S5CD!'[P1X<(S)SVYSVIQRZ9]H@4!?AH^T?
M]S-X/"5)U$)M=+11S1NK^"_BFRF;XBAUT%M6/Q*_E?5GX ((P/5>CP8( /9B
MKS%FD._I8]ECP_1[ GI%"GQ5'M>U)V3ZB/1X]=D]H3'&J$I]YJYSGX5QU$:B
MK1_!^R]!X? B 4<WLWV:D0>ZUXSRSO9Y$QU%1$P=8AVJVV 4U\"2])X,Q%<T
M?UCMHTR4_SH-(X?9P8%=X?$@;X(4#!8C?P0F7_(*+2NSCP5>W_5=?_M>K_M=
M7_NU#V0Q(62IWQ4?S_HG^/JQ?_(&'801"!4&[<]4X>XU;R0F$59%731[M<(+
MXS\^ SO7158WEC[B;BZ=5RJ(?NB'KNB&TNB1&^F0#NG<HQ?A]4XF9AWZ"!@R
MC)T&(0+8I5F/&'3DXAWC[T2ZN2>==1A^8CI&E>I);!#\J,R+)")[TO]E2G._
M6QK#K_K%+_(NN(+)S^,378 ':!7YC!4$+=XAJ(%/Z(1.^(1.Z(32;_.W:! N
MD6S&ED-VICJ 41^HY"L^[3K5?_J W_E5C1#C433EGSZ"HT>N81+>=V@,^;NE
M,?RJ7_PB[X(KF/P\/M$$^,Y/Z(1.^(,^Z(/2GQ'"(R\C5]0B-C=95X>=OR>+
M6!K1&UN2\>IFRQ/XR<4%L8A_=C#OEETJ.J'H61IB(+O5E3Z1?Q\> CG@>!#L
M(2VLZ!K!P2"=IKZ_6QK#K_K%+_(NN(+)S^,378 '6!4P&,],T?P,)?TVGV0Y
M=#]O8$Q4"3_DAK$A@NOINRZ:/QY +3Y4CM15R,4%<;I7*G,B&>^E,?RJ7_PB
M[X(KF/Q? /UI'H(:V/QKWOIL?H!5L<^?GV,.53"\D_W:U!PARCO.MV76<759
MIW&4;FH+XQH^\CY;J*;0Z5X(P1-RPR0,@K/)H9, AM(KTVJ4/L4$41<M5;\A
M!KC3KR,>;6+MR#(0 B>!6RKD<ASN5@9\J(C4J?/,.*-&PDR6W_E^X9W'7>40
M3TGH81+>=V@N.W7><7V1$G3?'E883N=4CM0=T@(C0 8ZH!<=!:C'K#%"!E_H
MG^B+OO[>Z^CO+^F3/G&QIK1GT& L5C"\(P(M, )DH -T\(@> CFOCB3=L4WX
M$H;MU&$> CDGT5X^P1[20I _D_U$TVFHKC%H208Z0 >8*=4N#4)?%M-AQD.I
MDZ)J)6FT,1!0BB98E.Y(*E(=/U*K'_*M7U(NN(+)S^,338#O_(1.Z(0_Z(,^
M*/T9\;O;:3H XA_9Y"&0PUA.'"?_2'EE'QL$7!K#K_K%+_(NN(+)S^,378 '
M6!4P&,],T?P,]?DN-G4D3 8GW#<M 8MT%B?70>EL.QJH5CBV1,)T<,)]TQ*_
M6QI4CM1\0^E96-2.P4HK(SUH@*C0(4#4T3Y3-RB=ANH@( (Q4)<#(0(R4)<G
M.Q B, ,B(*,'X01@ A_\(K,_X]U2X.,,%1T#GY)QTSH(0 <(0 <(0 =W@ !W
M@ !W@ "9@0!O@ !O@ "<U6FHWCZG0L"QTQ_U 9V=IKX1'U9%$\4E'2E'!F\M
MU*W/BQ#DAK&:YQA^8EP^02YBTC\O$A3,*%(1&_GWX2&0<Q)=A>G6?DMJ+P?'
M"1\BT (C4)=D3V1559XV#6CTH1CG5&&F0S4^<62JG/U$TVFH+J,'P;&SD_U$
MTVGJ&U 2?Q(2,ZPJ3#%]TQ)#IAQ5=?<E5ECFTNLB,S;7!YQB0C4^<62J_.OJ
M&7*,=K,)*57O(I/G TA;/Q!3,)""ND(,PA,8WLW"[E$@< /&_G[)OL::VE)N
M_.QR'.WI#/0XT0(C0 8Z0 <Z\ 9TW@(C0 8L8!(L ',Z\*;#HP-&H -,@)1.
M ";PP2_L\I [.I%T]AXHV_E/U;,Z;VGF!4V)GV?O(5DH:K]ZTR%1O!LBT (C
M( + 3Q&C][J8?[W<0>O(#?'C;TH9OS?T!9U<7! BX 0A4)>J5!*RF6@8GN-.
M$ *RZN:"Z00MT%&"Z0(N0!R *IBBJ3'%O,UW71I4CM0M-?ZU)/K$M4(9N<,&
M"B^0PQG:T=:?(I/+03). ";PP2]\)N]>XC+*XG6WLQP$7!H^\DYZA*()\Z#'
M7>5[GNJRAW6T9Z/!H?/=<3H8<@;35RK(-Z#+,=@#B\=!N<=]W'N-C5*0O6J2
M?=.IBO9L@-F:;92<W7NFZB>&'=J:C0:E/9670>5(W2$H0&XZR=HX@=N%OR=4
M26XZV>4((>$N)=W4;=W8C994CM1LL-V,Z=U2X.,,A98,1@9U^9@,YA-Q>=Q5
MON=UB;/)H9-.WN4QD:TH0&XZ"0(^P%$X+L;DII/6.N6UWB$H0&XZZ5$<%><S
M8>;JY]U2X.,,A9917I>/&>6J%)=UB;/)H9-.WN4Q@>9JSN9NC@+DII-Q/A%S
M+NP'4<PU0.<%D>?(#?%&0.ELV\T)49]'0@8DR[*E87D#Z>Z H;_KE/-1'7"P
MH7D QFS@F)V\\])@IA_!1=/G43#;WTQ.UD[U<083Z1CT,3=4Y!KMN!R.,U1Q
M YIX(R\4HCL(7%VET3]'_$3^NA^A)8J+0V*X:&:3/G%3/!!-D+@2 R&A)8I1
M9$KB=21)8CHLPQ-RPR1<7!"N0QUFU(FR%B]P(#13 Q@FED-D@+^086:R8Q[<
M>9X*3!T$#!]D2R"]*&D906D@,ORJ7_PB[X(KF/Q? /UI'H(:V/QKWOIL?H!5
ML<^8,_RJ7_PB[X(KF/Q?8($56($ICQ4/./Q<D?Q? /UI'H(:V/QKWOIL?H!5
M$82 ._WH1^=C# (X8.SOE^QKK*DMY<;/+L?1GLY 3P4=^4--4WA4CM0M14E>
M!&CO;,'W_$\9/"NA2RQD#>I,VXF1HFD'I3O6<7T.@N&H-P:\Q.O'7>40/SPN
MP$M4CM1LX *\U )-\R1(*60BT )-\R2/^.L,K'QL4#"\HQ@$Y< )HVE-UFLV
M@Q ><Z&R<1R21AOE2 9,0R,C_#,O#6; )4M4Q":'Y.HV";\&0>5('=AG_3_K
M%.IVQAVF3WT83N?'7>40WU& *JEE7 -(Z1+)1C5%O2R(IVI55?=.S[ @8 .#
MG5&BZ5(.ZU(ZY5(R<.<N%0,"-NV<6LPZ)>S'7>40WU& *JEE7 .#[IF4'FNS
MUG*GYANOCAYT]AY.XQGL(2V%8S.</T,U\S,G0 <GW#<M\5J6'[&1?Q\> CDG
M,9)SG50W@(KPHZ0#$>6M9O;P<WT'(P)4CM0=\E$(,0)TH -&(JDR( +H9\V4
M*NS9# *\\E&4*E+Q!\[+WL9N_.QR'.WI?.PRP0<$X0-4CM3#F5%\0!!\0! ^
M0.5(/9P9Q0<$P0<$P0-4CM3#F5%\0! \0.5(/9P9Y; NQ0<$X0-4CM3#F5%\
M0!!\0! ^0.5(/9P9Q0<$P0<$P0<$X0-4CM3#F5%\0!!\0!!\0! \0.5(/9P9
MQ0<$P0<$P0-4CM3#F5%\0! \0.5(/9P9I5,NQ0/#,^V<6LPW0.<%0>5(W2$M
M, )TH -&(JD.V\T)P;&STS]'[#J8PQ-RPR2\8?;>,?ZJ1&WJ88DUH3$GX ,G
MK/GPTS]'##U428XGP ,GK/GP R&A)8I+"EANH"QQ4RK1JX\ LE\T83H[+\#N
M[KZ%PYV/)=6H:Q!',R4L@QW/:;CG5&&F0S62!1@'61IX!L$7!OP404[5@6K+
M@G@;HSSJH2'7SV=YKT>ISB?!L>>LU%D 1N5(S3=F?ZNNT^H@(@,AL-R7HQQ5
M52K1NT0',:<2T]:?(I-G5DBN0^5(7?E&TNH@$@,A\+OP,3S&Y.>%\35QI*2Q
M2!VF-V04(P,A<+*6MC+2 [\&0>5(W5+CWQUETVNVI&/]41_S\NMU-! S(*,'
MD>?(#?%GIASE&1R6U$)M_2DRV3I&TNH@(@,A (LQ$ )=*E7FPA-RPR2E$OGW
MP;Z!&_I _8^49__)H9.:/P,A8#>1 B':B#C3[@1@PNU\EO=>8H;64AX4TC]'
MS)V7(0+#XP./V, $O+=E(#=, CU4*0(\H-V# U>5531])D#^./RJ7_PB[X(K
MF/S3'8(:R/SU;-TAJ('0+P6 ._V8@20GME2E0B[#PUVH1B%ZY!KZ>SV:Y1-Y
M4 8&YM3Z7Q!ZE+NJ@UJZ^51M]/D),_RJ7_PB[X(KF/P\/M$$^,Y/Z(1.^(,^
MZ(.UA"2&5&J[P2_Z7Q >1R&3)1MT]AZ!6#+EY$I:QB]\]C.__DA'IO\%$=E-
M TV>8_'24IY(<BZF,Y%( CW2DND2PX:C;Z4=7"7?2*>\D_^6UED -ORJ7_PB
M[X(KF/P\/M$$^,Y/Z(1.^(,^Z(/G@4QZVC][OAQN)AE3\L2N@[E2KRDB<?6]
M=09:'V8HH)U=95XFEAER<&A5N321$KWCF5U+E)W%4G8<<<0#,?RJ7_PB[X(K
MF/P\/M$$^,Y/Z(1.^(,^Z(,H@ H@ H@ "XNNB&(@<(( <(( <(T&E:_UMV
M@ !V@ !V@ !>B0!;@ !;@ .CBNX@BM=@ !=@ !=@ #GB@ I@ I@ ":=QY8
MJCQ4,Y'=H9M/A:0BU?$CM?HAW_HEY8(KF/S3'8(:R/SU;-TAJ('0+P4H@ H
M@ H@ !HB0 B@ B@ B</Z)ONCK[[V._OZ1+@((( ((( ((@)D(D ((D ((
MH'F?S\?=+.P>=5[&_G[)OL::VE)N_.QR'.WI#/3U*6M(DT5EX)VGIA++@G@1
M1'W&UDIK]'3U0<#P\7J0MQ=8IQDL,@54XH]4CM2!?=;=ZAK!P<4%$>75!5L0
M#'MVAHY?$XU%'4VJE>E;6B,$?(X .2!_SSO#.+@M!3RO/@<UWQ%ZIB_<T6>9
MX3B*ER-5^9TN(RQ]@@:405^!6#*28_F=OR?]V30XYK*0 R+!X5.(5UVP!<&P
M9V>(1Y$:@K0X6RWI<P)O< )D#T@H,:PJS*<#X01@ A_\PBX6 P(G\ 8G3%QP
MHF7P0WI\I_\%87MW WGG@G6:L=R^=@)O<,)W:S&_KI["UR Z>S>0EZ3H"(O>
M<0)O<,+_HTB=IKZ9<S0<4[7EV4;EG\0& 7J)XP)% #4B0.5(W2$M, )TH -O
MP **<09L+ZDR\(B8L31-@QF0 R(V,QJHMBR(]UHBH!AG 'HB@*!P55D$\LX6
M?,__E,&S<A[F;KWU8>]_!%F!QJ!RQD.I0SNZ;;A'!3G9Y3J7!W,?:2W6PR_G
M='M"0HI+PUP[K$KZ*SX!)!ND-4W;R+:$ML."ND+H9\W6;,W'+NP;%0,=]5&4
M*E+Q!\[+WL9N_.QR'.WIC)3O_(1.Z(0&#0(ICQ4NS\ZH[X'%'_*M7U(NN(+)
MS^,378 '6!4P&,],T?P,]= -R- #O8-E ?W@G<]8,>V%/GQF,]8WK6(P0P8I
M!@*("#F/80:/F!=YL)*(=QY<7!#6,?RJ7_PB[X(KF/P\/M$%>(!5 8/QS!3-
MSU"?S\?33@6<I1R[9DG4>;W<H:2\8?:U>[.?CQ?'.9,$D?_=T6GJ"T\GBOH>
M6/PAW_HEY8(KF/P\/M$%>(!5 8/QS!3-SU"?3_T, @(O#68H,6^9$7LR>A!7
M8"$P_!SSEAD2O!X@"EHPW(F=IKY0AV3U"Q\G0 8G0/: I!^7"(DT&;$$$?GW
M01!1?!+#A"3C,L0B\%$(,0)DP +SEAFQ%P,L,&^9$7LRP (NX (NH -T4)?_
M2'EE'QN%)YV7_F;@>!"?GS#/06?O$8@E4QJDQW?^8R$P[!<ZY!H6<P)D<,)]
MTQ(;0\";J#<=$L6[ :1TMI*(QQMF/_JH[X'%'_*M7U(NN(+)S^,378 '6!4P
M&,],T?Q4 +C3WZA!-HC>Q5].Y-//9&(>8R[U(4QW:S'SEAFQQ\4%4;O-0P;Y
ME3#"Z!?$6$O;#P+SEAFQQR!)-25GT& 1MK(-3, B-C=9%R;):(\H8!WSEAFQ
MQR D"CEDY1.]UD:?_P9)BG@_K"R-7S+OTRQG_4PFYC&A5#8FT3Y39S.<W[OE
M.6^9$7N0!6"Y&'75-9&U>[/=P<0$ 1INMB3R!?P40:/]41_0V6GJ"T_>,?RJ
M7_PB[X(KF/P\/M$%>(!5 8/QS!3-SU"?3_T,<I$1G,0&8<D>D@<[%U:1%,6O
MKH[^^CS,F[X9F9"QSEZC[QA^8EP^02YBTC\O\ASAPR]\9B%K1F34*9/+ ;W]
M,9 &-_'P\?FETVGJ:\#H@1Y#BK.W\[P(87],G2^&"3F/<6Z=ANI5&3MU(&G1
M$XA!SP;ADT7PP2_Z7Q 6<_/ 02WL IY!EV0*S(I\]C/.!V(-W+Z.X_ G89T,
MXNY4W:;<D1=Y\![<E1G/PQF(^AK5UR'#K_K%+_(NN(+)S^,378 '6!4P&,],
MT?Q4 +C37[K1!"2*5:8@-Z<[G5IWZQUH,!*E$5;]@A!1?!(C.==)A0.J5E5%
MO2R(I_FDQW<RBVJ>GL0*IMG63,W"GLT<!:@?1:DB%7_@O.QM[,;/+L?1GL['
M+A-\ (F=-@<Z@-\D+JO'[%)\0! ^0.5(/9P9Q0<$P0<$P6!DH -.'RF22N5(
M/9P9Q0<$P0<$X0-4CM3#F5%\0!!\0!!\0! ,1@8ZX/21 JA4CM3#F5%\0!!\
M0!!\0! ^0.5(/9P9Q0<$P0<$P0<$P0<$P6!DH -.'RD=1>5(/9P9Q0<$P0<$
MP0<$P0<$$>4Z ,6FITJBZ5)\0!!\0!!\0! \0.5(/9P9Q0<$P0<$P0<$$>4Z
M ,6FITH.ZU)\0!!\0! \0.5(/9P9Q0<$P0<$$>4Z ,6FITHZY5)\0! \0.5(
M/9P9I5,NQ0/#,^V<6LPX0.<%0>5(W2$M, )DH -TH -&<LS=3.@_HZ2\8?;6
M,?RJ7_PB[X(KF/P\/M$%>(!5 8/QS!3-SU#2;_-))K_EF9"G[;Z%Y]7_2'DC
M',.4[O<_/3O6\?EOD*1C<'7P?@468BXU>1YR0F?O0090<_@M([.H5@;'.9,$
MH:0?O;Y%8QWOH9ONWFDFT3ZG G,;\WQ&!?P400425"R!E=6QDQC4>;W<4;LW
M^_EXH?E*VJ41-]?CR"NJ5E4%PSM17DL6 L.E0>5('=AG?8N36&B'=K>6'[&1
M?Q\> CF[(0(M, )DP )1K@-O( *#G5%4CM1LH -0;'HZ ,6FITJBZ5)4CM1L
MH -0;'HZ ,6FITH.ZU)4CM1LH -0;'HZ ,6FITHZY5)4CM1LH -0;'HZ ,6F
MITHR<.<N)0-W#O2<6LPY0.?'7>40WP(C0 8L$.4Z8"1W3JG"GLT<):D?1:DB
M%7_@O.QM[,;/+L?1GLY KSBJ!!N-4:&WT;M'"F!TX_"$EW:O?C=XB&I_QG$%
MPUDAQV@W._[/<V2J//[[-J/R_CUC@'Q'9B'8,G5M= )F<,*\ 4CZ,:PJ_$M_
M#[\*]B1AV$X=YB&0<Q)4/-?CZ%_G43 'C'@@1O:U'MAG;;AQY#%Q9$LH;6L=
MYB&0\^HB\%$(,0)DH -O2N5(S08Z8 0ZP 0Z\ 8B\+NE<0)&<,)]TQ+7HV_+
M2B'8ZSA!Z_024_ZP2,),<,)]TQ+7HV\P>:&O7K\S21"#S_9!9W],773'GA-4
MCM1LX )CH ,&D0,Z<-Q5ON<ZX/0.H@-.'RF22N5(/9SX1^5(S08N, 8Z8! Y
MH /'7>5[K@-.[R ZX/21 JA4CM3#B7]4CM1LX )CH ,&D0,Z<-Q5ON<ZX/0.
MH@-.'RD=1>5(/9SX1^5(S08N, 8ZH$\SH /'7>5[K@-0;'HZ ,6FITJB">.U
MS@8N, 8ZH$\SH /'7>5[K@-0;'HZ ,6FITH."^.US@8N, 8ZH$\SH /'7>5[
MK@-0;'HZ ,6FITHZY5( 2.<34<S^];!4CM0=T@(C0 8Z\*94CM1LH -&H -,
MH -&<LS=3.@_HZ2OQ3P,>UZJ5E77SV<_(P(,1@:/^/D)<XN3&$=L#P(B0.5(
MS08N, :/N&=.%K0_3)DX (O6(0)17MJG/?VJ1"[6$5NRP?9%,_A!%P,R@'[6
M7,W"GLT<5<8?1:DB%7_@O.QM[,;/+L?1GLY(^81.Z(3O_- -^- -R- "#?U2
MD 4(D 4(D 4(D 4@D/)8X?+LG%(0W8 ,/= [6!;0#][YC!5/Z(1...WD)"74
M:6I/QE;T53"\X\4O.?KI,3=9%S'T1A"77YZ?CQ>O91TO#6; )4M4]+M?_>ZW
MP6#!H?/D[IR10B[6X4L;XR>&S?:8*_6:(A)7WUMGH/6_Q?M%&?9A'_:\8?8/
M?#>0YV9^8MB_1YV+/]C='7_37=W771PPPI'0X5#IXS$7*AO'(6FTD3GRPC0S
MR:EM5/X@-ND39VK PUC@+Y)T7C*=V&GJB[CT3[5V @*(*(J[F9#8/*PJ+ <B
M8,#P(=W4;=W8_?EFR)YT?J=5$BBC[T9G<J2CCD6]9C/8//X#H0;L>2[@_XKJ
M./]ZT4HSR:EAH)M/U5FR]L$+>1A^8CI&!>\#P;'E0><Z#OO4;=W8+?TVC[A(
MMJ&=Z.[N>_!BC.9JSN9NCCG2;05/D 1$\ 5ION9M+OTVWR_8O-64'FL0$G#<
M"6H#(=W4;=U20.?2?U@$D4.(UC4P5Q" ECG64AX'+\9HKN9L[N;/H^.P;P5/
MD 1$\ 5ION9MGCFI1>>F4DAP55F8\8>%TQC20D5R4O:Q@:38_-)@!ERR-%P>
M<Z&R<1R21AOE2 9,LY-TCM!8H ,Z#OO4;=W8C9;:G9E;A^9JSN9NCJG0"1EF
M!B&A)8KPUD* -OYTODZ"2]+Z 6C23=W6C=W2;_-[MOENW#]'S)VU%>^=V&GJ
MJ_>\0VXZ2>< QA-RPR143.DZ7TNBSQ-RPR011.<XFQPZ61 HX'W3I'D$$=E-
M4Q!DV]+P*\;2;05/D 1$\ 5ION9MGCFI%?^!.GO:A,WX0Q ;"A^0J!#Q]P5I
MON9M;A":0><Z#OM6\ 1)0 1?D.9KWN:9DUJ7>$OC3^<_/3L+XQH6T[[E02'2
M3=W6C=W2GQ%=BLWJB-)+NXI<X]'(!TCDDJTV@\V?CQ=5V8EQ(V<W72HH "$X
M3TT_3^<(C04ZH..PG^9KWN:U1VXZ&>?X5P18H ,Z#OM6\ 1)0 1?D.9KWN;0
M+1/>#=[B3=[% 2,<R7/^>'59QRYH"TT'+\:N&(@#$02W2XAC\^M9BCG:R<4)
M^_G4[QK.>MYL69<5LC3,U4S+V5*H*\:^$B1QPS(+(VF \3_K)B)[$L4GP8R/
M6@18H ,Z#OO?'=[C7=XACM[0G1,;WN$#,05EL+[>L:+9OS,?4AK1&VY",>OP
M*\97EW5:%/69/?6-4O557_58?P9:[V0?<B>/43IQ9&_'+NP;%0/;_%&4*E+Q
M!\[+WL9N_.QR'.WI#/0YL78K 8OOEEUUH$[6L:*+6!K,!HYN#/@1NTYZTR%1
MG"9( B/06=0SR:F?SUF=IKZ_^]5XP2Z7YD5>/).<"J3O!EL?$CL0UCR2U843
M1.?KI#<M%<6O?F(.CQB(5O:QT=+P*\:_SL!'9F $X01@ A_\PF<_XX??> 9T
M#@(BT (C\(CDXAT*;VL=%L6[4;O-D\1BC"2^=GV1$G2__DCSKQ?N'^EO@ !O
M@ !O@ !@@@!T@ !T@ !.9.<RA[2PHJN(2:J##^?7SJ=IKXRZL;.F!&^<M/#
M!:3L@5@ )(J[F9#8O-75SB[#JL(4H_Z% KZ52P<(0 <(0 <(H"'EN[ER@ !R
M@ !R@ .S#L@( (M, *EC<U1?!+,^*A%@ 4ZH..P#P4<[N$H$.+YO=\D[N1=
M[E)%@ 4ZH..P#P4<[N%H208Z0 ?;3><(C04ZH..P#P4<[N%HN=U KQ#QQ^-/
M 6#*5_F6-3(R!<["N[H6=/TQJEE)VF%8QV+&#O1L1+62=5ODET)B<UEIT[,
MZV0?@D7\$D?A)A3E^4QMALT+.WWEJ8X6@QE_2"'/9&(E(9LRZL;"'W\\_@10
M(/TVOS"N83&_KI[,^*A%@ 4ZH..P#P5/ 7/#?3>'']?8 1)P 0'73+P(=U&
MD 1,<-#2;_-)ED/WDS#]2N<W#QS4HA=)\ )/4%WI$ZM*ZB%;:"S8K#BJE$,^
M02XZ5G7(]E1(@J38K&$:+R<B<'DP]XCD* *7)R2/^%HV@\VO!WD@D 0O\ 0S
M347,^*A%@ 4ZP!NU+-U&D 1,4 1"(P)$((KZT0925E4DYL9)\ )/$ )P#MTR
M(=U%@ 5%, 158-WQ#A_270184 1#4 76G3FI=1[(E$.(EI#8[(I?1,3!P1%'
M;!%6^KNED?]TGK[KHO<_$ZOSEAFQ!S4Y=#]O0.>GMK!\Y49G<KW<81T 7[O-
MD\1BC"2PU1_U 9V=IKZ_^QR?;X;L2>?->=/E"5=(E#(3.5DY!#6K<XQTKN.P
MW^,__OEO8$>+([+_$1LA4XCT=N")09WE:=.DQW?.9"'*HH]<=@)D< )TSAN
MA!(+XQH6\^N/=&3L@@))X )%X +I.! B\%'8/ )DH -T\(B1?Q\> CDG\?-T
MCM!8H ,Z#OM%@ 5%, 158-W?RF&;49='PF%C@@).#MWJ)]UN7C(A)OV@;[A)
MY>;HT6MMQ!$G,9.<*@,M4 /IF%17EW41 Q@QHY]E "*#Y-&H*\8@6;0^02[>
MX6IR,XX\X9NA1Q#SAZ38O*+>+04^SE"?S\?'+NP;%0/%_E&4*E+Q!\[+WL9N
M_.QR'.WI#/3('G\\+@4^SE"8RI']NJR%D^Z%)P)FH*^EC<W (08<<<23/G&Q
MYD76<7595X>[B\VLUQ%"(]U&D 1,4 2_"Q_YWQV=IKYTGF2 %JL@,&^9$7O'
M"1\U6A\^\3UTWL#MZV0._^KJV$;K-)UA5!_?> 9TGK[K\L-Y03). ";PP2\R
M&\/9T2_8',4E'2F_SL!'QBZ1V!W,Z:]T+OTVG[[K<K+PA?Z(7O557_4I4RF4
MDA<(0 <(0 <($)"EX1A^8EP^81)T'DM91QJ"Q8R/6@18H ,Z#OL]_N-H60:@
M49>/Z7PAPO;8\9R8&>?X5P18H ,Z#OL]_N-H:2=U^9AVHDK16I=T#ATNZ>1=
M[E)%@ 4ZH..PW^,_CI9Y 0=U^9C1ZE$^ )=*GA=PT*78G!?JU (^P'-EX.30
M/1/2/05JK@1- 7% 2,^02YPHA)4JV-E0 =J\"8HH'F3/G%LB\VND_^O 3OI
M<W595X>=OR>+.).<^D2K;DAO!!\/?#>0IW!J\"9T?F8'ZOB,HQQ553!&8OF=
MO\)O0.=07.5M> (Z6VGN \.E(=U,\ 1.< 1*T 100.?2;_-)ED/WDS FX7U!
M;!VO!WET+FOU<09J\"8HH'F%R")#,#=9%S&%54A"U2 71N=3)MU3H.9*T 10
MD#GL.2!C<'7RZ1PP/),'+EOC#XM%HV-5-_YT7C&@N!NSEAC,^*A%@ 4ZH..P
M/P5JK@1- 6U%QF9^7/2S01/X 1'H 1- 7% 2,^02YPHA)4:QV*<1)J\"8H
MH'F3/G%LB\WXD_\#03=5[H\/N:/@3N?H^6<+UT;0(4#PP7!M)&M(0^<Z#OM3
MH.9*T 10@,0M;2%#[(HM#;]B_'J0YS#U<09J\"8HH'EG=J $X01@ A_EI?\)
M>W59%S%2-OH#(=U,\ 1.< 1*T 10<&SO3N=07.7^N(B=*+.\DZ)E"[]B#$A(
M)MU3H.9*T 10$/^8L31-TYQE)RV9_AYT#F##(_EQ!"-BPG;2/05JK@1- 5_
MB\W2S01/X 1'H 1- 634SSY\CM2MJ&/9C/8G/T'XC$7*AO'(6FT48YDP#2E
M0;8V@\WY#XF=IKY2_<M!DG4 PG8V@\WL4>W,^*A%@ 4ZH..PSP1/X 1'H 1-
M 6U%QDL0&Z96<W"GLT<=0/&_G[)OL::VE)N_.QR'.WIC)3#SQ4&7?PAW_HE
MY8(T2-!#D/)O$<],T?Q4 /W@G<]8<=$6;=$@\(1.Z(3-3P70+P4P&,\RZ((K
M..VC%[&1?Q\> CF[\1PYQ)' *;.\LX@L1,#P >X$D>Z%-_RJ7_PB[X(KF/P\
M/M$$^,Y/Z(1.^(,^Z(.9DUH&C!XUBO@(\61L15]%+6)SDW414UA^]!M'FOUM
M.H8Z3XXV$W& I!_#JL+Y\M-,1V<[1WL%+S&DL28#$02=IKX:<V3KZQA^8EP^
M02XGL 4G_$0GT 4G'(FE+C+) ?PX009;P +SEAFQ-P=M601.O'/_2'G78?:9
M\^X$T35T3A"UVSSS,F^9$7OP'O2FP30=<F301^<$,6^9$7NN(4!PHF7\LK^%
M-&^9$7L,<CK";DG4*9) GQ!$L 4LX&=M"1* A/\9!F'-<S\"]&>Z^52X3N<$
MH:0_K"SYE3"O%'Y/1P8<81(R>N)4($ ZY!HE(9NO93"<D;LM!&@U6A])C,TH
M0&XZN67^I4K^"IPVVO@?L7>F1^?CXAHLEA',2!%FL 4L,/YST);_-D $D?W*
MUK,ZW]()@Z3"7KO-,R]'!F_<,?[P'@1"9Z@G?F2J/.D3I_/GX4I:5E[LLC)T
M3A#CSR!)94G4*9) GQ-& .AR<%"X#N[A]W1!QY!TWM(_4_X@AK>:Z/02$_F!
M>_#8;!V?;R1PA=/6H:3,^*A, .AR<%"X#N[A]W1!QY!TWM*\,_A.OW-!M]3[
MA[UT?FRI=6;,MAO6H:3,^*CFHE)R<%"X#N[A]W1!QY!TWM*E.#=9IW&4;FHE
MIW=CB') GQ-N/@5EP(<7:FQ+O7_G8F;_TOE5+>Q*^L.DOG:;X6!ZL4_Q7DY<
M[,8YU(Y#1C% XA>.D6KA)@=E!R-RXCXD=N+93U6(=QZN(43/]2FETC5T/CEG
MK:3,*&I;P *@UY:!]WO4F3[9WZ:(YR%;J.]O0.<MS3LAQVC-@VB@9\!5M'>F
M1^<$H:1.IGB%X7JW)R0D$P0$T?/#>>*_SL!'QBYP!2.YBWA2C;K8K'UNKV(>
M@GD&!O23LP4L@+;4T9;_-D $D?W*UK,ZW]()@Z3"7KO-@VAH2QTD$P2FP30M
M=62G-^V/NE$Q@ /&_G[)OL::VE)N_.QR'.WI#/3.YDI:UEKL3AV_6TX,NF!,
M0^<$L>F>8_'2@D4_S70\E#H$41Z_D<38C+;4P2). ";PP2_L@NO_TOE5+>Q*
M^L.DSF;-Z>YR<&AW:S/"7OX@EAYSDW7L@K8#D>Y(*NPG 4GW#<M\;O(:/&(
M5?Z(^T[M6QYTWM*\TQV=IKZB@B0P@F@ AJ3"/ORJ7_PB[X(KF/P\/M$%>(!6
MD<]80=#B'8(:^(1.Z(1/Z(1.*/T9P8R/"@6 +@<'A>O@'GY/%W0,2><M_3/E
M#V+I,3=9%R;LSB+)/,/"GD/M:+CFDD/8,G4 Q.ZUI$QT3A >PS&6YAQ-XSD6
M+RU8Q"_L$HG$!!MT3A# LQO9'X@@X 1@PNU\AIR1J'7"CK:9PYY5R1$G41HC
M_#/9KTW"'OGWX2&0LQOX8V*Q)"WEB3\V(^SE\1L^@;;4P8R/&LTPXA/DDC=J
M0.ES-W76,?RJ7_PB[X(KF/P\/M$$^,Y/Z(1.^(,^Z(-T?FRI!4]T4P9\5HIS
MDW5WYR!%A?C"/FLM)P:R!$\LEA$LDLSOE$/M*)]!?>+#K_K%+_(NN(+)S^,3
M38#O_(1.Z(0_Z(,^F#GO7K4J!AW%4G8< 3G+0>>0>%_:7QK9OS,?LI,/2P=;
MP ).T)9%X,02,_[KI#=\XS>"@FKY(:,G7NAA@ <"]#$5 XJ[<7*J5+O-D\38
M'+U.T%X^07I\M[ZN(V P@'[6;,U _Z@;=5/&_G[)OL::VE)N_.QR'.WIC)0_
MZ(,^"(/QS!3-3P5/Z(1.&/0-+=!!./Q<D5(0[8#WG 1/Z(1.2-#B'8(:>-$6
M;=$7;=$6S= "'80&G?)8\<Y/Z(1...WU"6+E^$XYU(YG=D8J[5/<81TO#6;
M)4O3C"$%DS#(%XF%)W<$-V7>41*RZ=/D0@>9D?AF$"19!QG8,T>-^+OE5!V#
MZ%T.ZJ^)YD9G<O &T2QG32XBNC]T=!E(U8:#LZ$T,FE^D5SNA1"Q)1F[8?F=
MOR=*RHLG%B19EW.K^+O(Z.<=@8I?$T<><U13-TW]XUU5Z 8RYQKD(J+[0T>7
M@50S.2[LDC5SX",;BD7JV$9*>AXB6S:]9D9R$_Z]MD19NV!^X1BI!GH&#!]T
MD!D# 21^X1BI!GIRPF9?$T>HFR7+$R19!R#&AGR1R)&W,8Q1ET)QPS)(51IR
M5Q])RAU]EAF<KJ<THCSZ.&/ 3Q%!,! \T;3EZ<5@8^D)2C=T+RB@^.I(!1^;
MCXN'Y*-#3""WE!YSDW7LTO=>A![(%XGSTA*!.\,((7<$9Y@\@9^NT?>!];OE
MY!HX6K4+QC2U9"$DEIUY'XG5M;PF@3EA/6/ 3Q&*HTKZ6Z1F$&&FQ[[RLCR%
MA4)X4/B%L_!/E9 88N[G"1L]5[_P,?[)X;<@!@(O#6; )4O3C! X5"3MZUW\
MU3ZG G-XJXGK%"AA;;( 9K:? [V$LQO9'X@@D%94;DKBA<(R1B-WX!<Z9.YD
MY1/DLD0'T?=)GSY00!M':A%#L+2K>" VW48XQ!FTUVM<1<#F=4ML _<@@ 15
M%9QVY(8>0AEGP#*.01]S0T5$LOV4KS'@R3)-)3!XPXGK=*'VMUDW[8_9?R"?
MCQ<-3,#P 3V;0;A2QL0$ET7EZ<+ T=3Q#A_),W));! +OR>1W33-F4-VICKX
MCSD:@FV,A0>%_RU^GB/H9\W5+.S9'&#H]5&4*E+Q!\[+WL9N_.QR'.WIC)0$
M/00,+= 66($5:- ,+=#-3P5/Z(1...U"]M)@!ERR-%R9(0=KX!H^\DZVY%H_
MS70;.I,$(0)!1U'G3@:/^(\R!S6RXS5((BA*PND7+SKOXAB*-9P'$6YR4':5
M=2)91AWE\[7Q/[S-^4)R$$SE:4TU#UTD=A 4=>[SXEIJ-3M(@K-!<7^"5^6N
M$;U#\KHD;9/P:Q#K,6GY!B*?CQ?P5(@A-T9\0^DZK_E%&D: Y&C@F)V\D_T4
M$^7P#@)/T$+TX=9E<)SHH1Y]$4GH4>\(L1YPXEUEFJV6W_E[HJ2JI-.>008?
M,R/SDB&E0_9/CSYEEQ<M('<"DHN#"T? 3Q%]'AXZ(OK,U!CBB%K*\<%&=1V4
MKO/Q-"($;%[PA?Z)ONB&P@8(P 8(P 8(H!P(P 8(P 8(H!@(\ 8(\ 8(\,$(
M, 8(, 8(D'#/=--R1OK(6(\^S&R[81VO!WD:\])@!ERR1$6_^]5XH1>7)B!U
6JTKA=5]I *"4_\%4D\0&T1CB.!Q$ 1VO
end

6
dmake/dbug/getwd.c Normal file
View File

@ -0,0 +1,6 @@
char *
getwd(pathname)
char *pathname;
{
return("delete this code if your getwd.c works correctly");
}

View File

@ -0,0 +1,77 @@
#
# (c) Copyright 1990 Conor P. Cahill (uunet!virtech!cpcahil).
# You may copy, distribute, and use this software as long as this
# copyright statement is not removed.
#
#
# This is the Makefile for the malloc debugging library
#
# $Id: Makefile,v 1.5 90/08/29 22:34:27 cpcahil Exp $
#
CC=cc
# for System V systems use this CFLAGS
#CFLAGS=-g -DSYS5
# else for BSD use:
#CFLAGS=-g
LINT=lint
SHARCMD=shar -o mallocshar -l50 -x -a -n Malloclib
SHELL=/bin/sh
LIB=libmalloc.a
SRCS= malloc.c \
free.c \
realloc.c \
calloc.c \
string.c \
mlc_chk.c \
mlc_chn.c \
memory.c \
tostring.c \
m_perror.c \
m_init.c \
mallopt.c \
dump.c
OBJS= malloc.o \
free.o \
realloc.o \
calloc.o \
string.o \
mlc_chk.o \
mlc_chn.o \
memory.o \
tostring.o \
m_perror.o \
m_init.o \
mallopt.o \
dump.o
TESTS=testmlc testmem
all: $(LIB) $(TESTS)
clean:
rm -f $(TESTS) pgm $(LIB) *.o *.ln
sharfile:
$(SHARCMD) Makefile README patchlevel *.[ch3]
$(LIB): $(OBJS)
ar ru $(LIB) $(OBJS)
-if test -s /bin/ranlib; then /bin/ranlib $(LIB); else exit 0; fi
-if test -s /usr/bin/ranlib; then /usr/bin/ranlib $(LIB); else exit 0; fi
testmlc: $(LIB) testmlc.o
$(CC) -o $@ testmlc.o $(LIB)
testmem: $(LIB) testmem.o
$(CC) -o $@ testmem.o $(LIB)
lint:
$(LINT) $(CFLAGS) $(SRCS) testmlc.c testmem.c
$(OBJS): malloc.h
tostring.o malloc.o dump.o: tostring.h

View File

@ -0,0 +1,9 @@
I made the following changes to the malloc package as found in
comp.sources.unix:
1. created this file _changes.
2. moved README to _readme (facilitates transfer to DOS and back to
unix)
3. renamed testmalloc.c, malloc_chk.c, and malloc_chn.c to testmlc.c,
mlc_chk.c, and mlc_chn.c respectively. Again DOS has trouble with
long basenames in filenames.

133
dmake/dbug/malloc/_readme Normal file
View File

@ -0,0 +1,133 @@
# (c) Copyright 1990 Conor P. Cahill. (uunet!virtech!cpcahil)
# You may copy, distribute, and use this software as long as this
# copyright statement is not removed.
This package is a collection of routines which are a drop-in replacement
for the malloc(3), memory(3), string(3), and bstring(3) library functions.
The purpose of these programs is to aid the development and/or debugging
of programs using these functions by providing a high level of consistancy
checking whenever a malloc pointer is used. Due to this increased
level of consistancy checking, these functions have a considerably larger
overhead than the standard functions, but the extra checking should be
well worth it in a development environment.
To use these functions all you need to do is compile the library and
include it on your loader command line. You do not need to recompile
your code, only a relink is necessary.
Features of this library:
1. The malloced area returned from each call to malloc is filled with
non-null bytes. This should catch any use of uninitialized malloc
area. The fill pattern for malloced area is 0x01.
2. When free is called numerous validity checks are made on the
pointer it is passed. In addition, the data in the malloc block
beyound the size requested on the initial malloc is checked to
verify that it is still filled with the original fill characters.
This is usefull for catching things like:
ptr = malloc(5);
ptr[5] = '\0';
/*
* You should not that this will be caught when it is
* freed not when it is done
*/
And finally, the freed block is filled with a different fill pattern
so that you can easily determine if you are still using free'd space.
The fill pattern for free'd areas is 0x02.
This is usefull for catching things like:
ptr = malloc(20);
bptr = ptr+10;
/* do something usefule with bptr */
free(ptr);
/*
* now try to do something useful with bptr, it should
* be trashed enough that it would cause real problems
* and when you went to debug the problem it would be
* filled with 0x02's and you would then know to look
* for something free'ing what bptr points to.
*/
3. Whenever a bstring(3)/string(3)/memory(3) function is called, it's
parameters are checked as follows:
If they point somewhere in the malloc arena
If the operation goes beyond requested malloc space
call malloc_warning()
This is usefull for catching things like:
ptr = malloc(5);
strcpy(ptr,"abcde");
4. Malloc_warning() and malloc_fatal() are used when an error condition
is detected. If the error is severe, malloc_fatal is called.
Malloc_warning is used otherwise. The decision about what is fatal
and what is a warning was made somewhat arbitrarily.
Warning messages include:
Calling free with a bad pointer
Calling a bstring/string/memory (3) function which will go beyond
the end of a malloc block (Note that the library function is
not modified to refuse the operation. If malloc warnings are
in the default IGNORE case, the operation will continue and
at some point cause a real problem).
Fatal errors are:
Detectable corruption to the malloc chain.
5. The operations to perform when an error is detected are specified at
run time by the use of environment variables.
MALLOC_WARN - specifies the warning error message handling
MALLOC_FATAL - specifies the fatal error handling
When one of these error conditions occur you will get an error
message and the handler will execute based upon what setting
is in the environment variables. Currently understood settings
are as follows:
0 - continue operations
1 - drop core and exit
2 - just exit
3 - drop core, but continue executing. Core files will
be placed into core.[PID].[counter] i.e: core.00123.001
128 - dump malloc chain and continue
129 - dump malloc chain, dump core, and exit
130 - dump malloc chain, exit
131 - dump malloc chain, dump core, continue processing
There is an additional environment variable MALLOC_ERRFILE which
is used to indicate the name of the file for error message output.
For example, to set up the session to generate a core file for
every malloc warning, to drop core and exit on a malloc fatal, and
to log all messages to the file "malloc_log" do the following:
MALLOC_WARN=131
MALLOC_FATAL=1
MALLOC_ERRFILE=malloc_log
export MALLOC_WARN MALLOC_FATAL MALLOC_ERRFILE
6. The function malloc_dump() is available to dump the malloc chain whenever
you might want. It's only argument is a file descriptor to use to write
the data. Review the code if you need to know what data is printed.

View File

@ -0,0 +1,73 @@
/*
* (c) Copyright 1990 Conor P. Cahill (uunet!virtech!cpcahil).
* You may copy, distribute, and use this software as long as this
* copyright statement is not removed.
*/
#include <stdio.h>
/*
* Function: calloc()
*
* Purpose: to allocate and nullify a data area
*
* Arguments: nelem - number of elements
* elsize - size of each element
*
* Returns: NULL - if malloc fails
* or pointer to allocated space
*
* Narrative: determine size of area to malloc
* malloc area.
* if malloc succeeds
* fill area with nulls
* return ptr to malloc'd region
*/
#ifndef lint
static char rcs_header[] = "$Id: calloc.c,v 1.1 1992/01/24 03:28:58 dvadura Exp $";
#endif
char *
calloc(nelem,elsize)
unsigned int nelem;
unsigned int elsize;
{
char * malloc();
char * memset();
char * ptr;
unsigned int size;
size = elsize * nelem;
if( (ptr = malloc(size)) != NULL)
{
(void) memset(ptr,'\0',(int)size);
}
return(ptr);
}
/*
* $Log: calloc.c,v $
* Revision 1.1 1992/01/24 03:28:58 dvadura
* dmake Version 3.8, Initial revision
*
* Revision 1.6 90/05/11 00:13:07 cpcahil
* added copyright statment
*
* Revision 1.5 90/02/24 20:41:57 cpcahil
* lint changes.
*
* Revision 1.4 90/02/24 17:25:47 cpcahil
* changed $header to $id so full path isn't included.
*
* Revision 1.3 90/02/24 13:32:24 cpcahil
* added function header. moved log to end of file.
*
* Revision 1.2 90/02/22 23:08:26 cpcahil
* fixed rcs_header line
*
* Revision 1.1 90/02/22 23:07:38 cpcahil
* Initial revision
*
*/

111
dmake/dbug/malloc/debug.h Normal file
View File

@ -0,0 +1,111 @@
/*
* (c) Copyright 1990 Conor P. Cahill (uunet!virtech!cpcahil).
* You may copy, distribute, and use this software as long as this
* copyright statement is not removed.
*/
/************************************************************************/
/* */
/* this include sets up some macro functions which can be used while */
/* debugging the program, and then left in the code, but turned of by */
/* just not defining "DEBUG". This way your production version of */
/* the program will not be filled with bunches of debugging junk */
/* */
/************************************************************************/
/*
* $Id: debug.h,v 1.1 1992/01/24 03:28:59 dvadura Exp $
*/
#ifdef DEBUG
#if DEBUG == 1 /* if default level */
#undef DEBUG
#define DEBUG 100 /* use level 100 */
#endif
#include <stdio.h>
#define DEBUG0(val,str)\
{\
if( DEBUG > val ) \
fprintf(stderr,"%s(%d): %s\n",\
__FILE__,__LINE__,str);\
}
#define DEBUG1(val,str,a1)\
{\
char _debugbuf[100];\
if( DEBUG > val )\
{\
sprintf(_debugbuf,str,a1);\
fprintf(stderr,"%s(%d): %s\n",\
__FILE__,__LINE__,_debugbuf);\
}\
}
#define DEBUG2(val,str,a1,a2)\
{\
char _debugbuf[100];\
if( DEBUG > val )\
{\
sprintf(_debugbuf,str,a1,a2);\
fprintf(stderr,"%s(%d): %s\n",\
__FILE__,__LINE__,_debugbuf);\
}\
}
#define DEBUG3(val,str,a1,a2,a3)\
{\
char _debugbuf[100];\
if( DEBUG > val )\
{\
sprintf(_debugbuf,str,a1,a2,a3);\
fprintf(stderr,"%s(%d): %s\n",\
__FILE__,__LINE__,_debugbuf);\
}\
}
#define DEBUG4(val,str,a1,a2,a3,a4)\
{\
char _debugbuf[100];\
if( DEBUG > val )\
{\
sprintf(_debugbuf,str,a1,a2,a3,a4);\
fprintf(stderr,"%s(%d): %s\n",\
__FILE__,__LINE__,_debugbuf);\
}\
}
#define DEBUG5(val,str,a1,a2,a3,a4,a5)\
{\
char _debugbuf[100];\
if( DEBUG > val )\
{\
sprintf(_debugbuf,str,a1,a2,a3,a4,a5);\
fprintf(stderr,"%s(%d): %s\n",\
__FILE__,__LINE__,_debugbuf);\
}\
}
#else
#define DEBUG0(val,s)
#define DEBUG1(val,s,a1)
#define DEBUG2(val,s,a1,a2)
#define DEBUG3(val,s,a1,a2,a3)
#define DEBUG4(val,s,a1,a2,a3,a4)
#define DEBUG5(val,s,a1,a2,a3,a4,a5)
#endif /* DEBUG */
/*
* $Log: debug.h,v $
* Revision 1.1 1992/01/24 03:28:59 dvadura
* dmake Version 3.8, Initial revision
*
* Revision 1.2 90/05/11 00:13:08 cpcahil
* added copyright statment
*
* Revision 1.1 90/02/23 07:09:01 cpcahil
* Initial revision
*
*/

124
dmake/dbug/malloc/dump.c Normal file
View File

@ -0,0 +1,124 @@
/*
* (c) Copyright 1990 Conor P. Cahill (uunet!virtech!cpcahil).
* You may copy, distribute, and use this software as long as this
* copyright statement is not removed.
*/
#include <stdio.h>
#include "malloc.h"
#include "tostring.h"
/*
* Function: malloc_dump()
*
* Purpose: to dump a printed copy of the malloc chain and
* associated data elements
*
* Arguments: fd - file descriptor to write data to
*
* Returns: nothing of any use
*
* Narrative: Just print out all the junk
*
* Notes: This function is implemented using low level calls because
* of the likelyhood that the malloc tree is damaged when it
* is called. (Lots of things in the c library use malloc and
* we don't want to get into a catch-22).
*
*/
#ifndef lint
static
char rcs_hdr[] = "$Id: dump.c,v 1.1 1992/01/24 03:29:01 dvadura Exp $";
#endif
#define ERRSTR "I/O Error on malloc dump file descriptor\n"
#define WRITEOUT(fd,str,len) if( write(fd,str,(unsigned)len) != len ) \
{ \
(void) write(2,ERRSTR,\
(unsigned)strlen(ERRSTR));\
exit(120); \
}
void
malloc_dump(fd)
int fd;
{
char buffer[512];
void exit();
int i;
extern char * malloc_data_end;
extern char * malloc_data_start;
extern struct mlist * malloc_end;
extern struct mlist malloc_start;
struct mlist * ptr;
WRITEOUT(fd,"MALLOC CHAIN:\n",14);
WRITEOUT(fd,"-------------------- START ----------------\n",44);
for(i=0; i < 80; i++)
{
buffer[i] = ' ';
}
for(ptr = &malloc_start; ptr; ptr = ptr->next)
{
(void) tostring(buffer, (int)ptr, 8, B_HEX, '0');
(void) tostring(buffer+9, (int)ptr->next, 8, B_HEX, '0');
(void) tostring(buffer+18, (int)ptr->prev, 8, B_HEX, '0');
(void) tostring(buffer+27, (int)ptr->flag, 10, B_HEX, '0');
(void) tostring(buffer+38, (int)ptr->s.size, 8, B_DEC, ' ');
(void) tostring(buffer+47, (int)ptr->s.size, 8, B_HEX, '0');
(void) tostring(buffer+57, (int)ptr->data, 8, B_HEX, '0');
buffer[46] = '(';
buffer[55] = ')';
buffer[65] = '\n';
WRITEOUT(fd,buffer,66);
}
WRITEOUT(fd,"-------------------- DONE -----------------\n",44);
WRITEOUT(fd,"Malloc start: ",19);
(void) tostring(buffer, (int) &malloc_start, 8, B_HEX, '0');
buffer[8] = '\n';
WRITEOUT(fd,buffer,9);
WRITEOUT(fd,"Malloc end: ", 19);
(void) tostring(buffer, (int) malloc_end, 8, B_HEX, '0');
buffer[8] = '\n';
WRITEOUT(fd,buffer,9);
WRITEOUT(fd,"Malloc data start: ", 19);
(void) tostring(buffer, (int) malloc_data_start, 8, B_HEX, '0');
buffer[8] = '\n';
WRITEOUT(fd,buffer,9);
WRITEOUT(fd,"Malloc data end: ", 19);
(void) tostring(buffer, (int) malloc_data_end, 8, B_HEX, '0');
buffer[8] = '\n';
WRITEOUT(fd,buffer,9);
} /* malloc_dump(... */
/*
* $Log: dump.c,v $
* Revision 1.1 1992/01/24 03:29:01 dvadura
* dmake Version 3.8, Initial revision
*
* Revision 1.5 90/08/29 21:22:37 cpcahil
* miscellaneous lint fixes
*
* Revision 1.4 90/05/11 00:13:08 cpcahil
* added copyright statment
*
* Revision 1.3 90/02/24 21:50:07 cpcahil
* lots of lint fixes
*
* Revision 1.2 90/02/24 17:27:48 cpcahil
* changed $header to $Id to remove full path from rcs id string
*
* Revision 1.1 90/02/22 23:17:43 cpcahil
* Initial revision
*
*/

188
dmake/dbug/malloc/free.c Normal file
View File

@ -0,0 +1,188 @@
/*
* (c) Copyright 1990 Conor P. Cahill (uunet!virtech!cpcahil).
* You may copy, distribute, and use this software as long as this
* copyright statement is not removed.
*/
#include <stdio.h>
#include "malloc.h"
#include "debug.h"
/*
* Function: free()
*
* Purpose: to deallocate malloced data
*
* Arguments: ptr - pointer to data area to deallocate
*
* Returns: nothing of any value
*
* Narrative:
* verify pointer is within malloc region
* get mlist pointer from passed address
* verify magic number
* verify inuse flag
* verify pointer connections with surrounding segments
* turn off inuse flag
* verify no data overrun into non-malloced area at end of segment
* IF possible join segment with next segment
* IF possible join segment with previous segment
* Clear all data in segment (to make sure it isn't reused)
*
*/
#ifndef lint
static
char rcs_hdr[] = "$Id: free.c,v 1.1 1992/01/24 03:29:02 dvadura Exp $";
#endif
void
free(cptr)
char * cptr;
{
char * func = "free";
int i;
extern int malloc_checking;
extern struct mlist * malloc_end;
extern int malloc_errno;
extern char * malloc_data_end;
extern char * malloc_data_start;
void malloc_join();
void malloc_memset();
struct mlist * oldptr;
struct mlist * ptr;
/*
* IF malloc chain checking is on, go do it.
*/
if( malloc_checking )
{
(void) malloc_chain_check(1);
}
/*
* verify that cptr is within the malloc region...
*/
if( cptr < malloc_data_start || cptr > malloc_data_end )
{
malloc_errno = M_CODE_BAD_PTR;
malloc_warning(func);
return;
}
/*
* convert pointer to mlist struct pointer. To do this we must
* move the pointer backwards the correct number of bytes...
*/
ptr = (struct mlist *) (cptr - M_SIZE);
if( (ptr->flag&M_MAGIC) != M_MAGIC )
{
malloc_errno = M_CODE_BAD_MAGIC;
malloc_warning(func);
return;
}
if( ! (ptr->flag & M_INUSE) )
{
malloc_errno = M_CODE_NOT_INUSE;
malloc_warning(func);
return;
}
if( (ptr->prev && (ptr->prev->next != ptr) ) ||
(ptr->next && (ptr->next->prev != ptr) ) ||
((ptr->next == NULL) && (ptr->prev == NULL)) )
{
malloc_errno = M_CODE_BAD_CONNECT;
malloc_warning(func);
return;
}
ptr->flag &= ~M_INUSE;
/*
* verify that the user did not overrun the requested number of bytes.
*/
for(i=ptr->r_size; i < ptr->s.size; i++)
{
if( ptr->data[i] != M_FILL )
{
malloc_errno = M_CODE_OVERRUN;
malloc_warning(func);
break;
}
}
DEBUG3(10,"pointers: prev: 0x%.7x, ptr: 0x%.7x, next: 0x%.7x",
ptr->prev, ptr, ptr->next);
DEBUG3(10,"size: prev: %9d, ptr: %9d, next: %9d",
ptr->prev->s.size, ptr->s.size, ptr->next->s.size);
DEBUG3(10,"flags: prev: 0x%.7x, ptr: 0x%.7x, next: 0x%.7x",
ptr->prev->flag, ptr->flag, ptr->next->flag);
/*
* check to see if this block can be combined with the next and/or
* previous block. Since it may be joined with the previous block
* we will save a pointer to the previous block and test to verify
* if it is joined (it's next ptr will no longer point to ptr).
*/
malloc_join(ptr,ptr->next,0,0);
oldptr = ptr->prev;
malloc_join(ptr->prev, ptr,0,0);
if( oldptr->next != ptr )
{
DEBUG0(10,"Oldptr was changed");
ptr = oldptr;
}
/*
* fill this block with '\02's to ensure that nobody is using a
* pointer to already freed data...
*/
malloc_memset(ptr->data,M_FREE_FILL,(int)ptr->s.size);
}
/*
* $Log: free.c,v $
* Revision 1.1 1992/01/24 03:29:02 dvadura
* dmake Version 3.8, Initial revision
*
* Revision 1.9 90/08/29 21:22:48 cpcahil
* miscellaneous lint fixes
*
* Revision 1.8 90/05/11 00:13:08 cpcahil
* added copyright statment
*
* Revision 1.7 90/02/25 11:00:18 cpcahil
* added support for malloc chain checking.
*
* Revision 1.6 90/02/24 21:50:18 cpcahil
* lots of lint fixes
*
* Revision 1.5 90/02/24 17:29:13 cpcahil
* changed $Header to $Id so full path wouldnt be included as part of rcs
* id string
*
* Revision 1.4 90/02/24 15:15:32 cpcahil
* 1. changed ALREADY_FREE errno to NOT_INUSE so that the same errno could
* be used by both free and realloc (since it was the same error).
* 2. fixed coding bug
*
* Revision 1.3 90/02/24 14:23:45 cpcahil
* fixed malloc_warning calls
*
* Revision 1.2 90/02/24 13:59:10 cpcahil
* added function header.
* Modified calls to malloc_warning/malloc_fatal to use new code error messages
* Added support for malloc_errno setting of error codes.
*
* Revision 1.1 90/02/22 23:17:43 cpcahil
* Initial revision
*
*/

103
dmake/dbug/malloc/m_init.c Normal file
View File

@ -0,0 +1,103 @@
/*
* (c) Copyright 1990 Conor P. Cahill (uunet!virtech!cpcahil).
* You may copy, distribute, and use this software as long as this
* copyright statement is not removed.
*/
#include <stdio.h>
#include "malloc.h"
/*
* Function: malloc_init()
*
* Purpose: to initialize the pointers and variables use by the
* malloc() debugging library
*
* Arguments: none
*
* Returns: nothing of any value
*
* Narrative: Just initialize all the needed variables. Use mallopt
* to set options taken from the environment.
*
*/
#ifndef lint
static
char rcs_hdr[] = "$Id: m_init.c,v 1.1 1992/01/24 03:29:03 dvadura Exp $";
#endif
void
malloc_init()
{
char * cptr;
char * getenv();
union malloptarg m;
extern char * malloc_data_end;
extern char * malloc_data_start;
extern struct mlist * malloc_end;
extern struct mlist malloc_start;
char * sbrk();
/*
* If already initialized...
*/
if( malloc_data_start != (char *) 0)
{
return;
}
malloc_data_start = sbrk(0);
malloc_data_end = malloc_data_start;
malloc_start.s.size = 0;
malloc_end = &malloc_start;
if( (cptr=getenv("MALLOC_WARN")) != NULL )
{
m.i = atoi(cptr);
(void) mallopt(MALLOC_WARN,m);
}
if( (cptr=getenv("MALLOC_FATAL")) != NULL)
{
m.i = atoi(cptr);
(void) mallopt(MALLOC_FATAL,m);
}
if( (cptr=getenv("MALLOC_CKCHAIN")) != NULL)
{
m.i = atoi(cptr);
(void) mallopt(MALLOC_CKCHAIN,m);
}
if( (cptr=getenv("MALLOC_ERRFILE")) != NULL)
{
m.str = cptr;
(void) mallopt(MALLOC_ERRFILE,m);
}
}
/*
* $Log: m_init.c,v $
* Revision 1.1 1992/01/24 03:29:03 dvadura
* dmake Version 3.8, Initial revision
*
* Revision 1.6 90/08/29 22:23:21 cpcahil
* fixed mallopt to use a union as an argument.
*
* Revision 1.5 90/08/29 21:22:50 cpcahil
* miscellaneous lint fixes
*
* Revision 1.4 90/05/11 15:53:35 cpcahil
* fixed bug in initialization code.
*
* Revision 1.3 90/05/11 00:13:08 cpcahil
* added copyright statment
*
* Revision 1.2 90/02/24 21:50:20 cpcahil
* lots of lint fixes
*
* Revision 1.1 90/02/24 17:10:53 cpcahil
* Initial revision
*
*/

View File

@ -0,0 +1,93 @@
/*
* (c) Copyright 1990 Conor P. Cahill (uunet!virtech!cpcahil).
* You may copy, distribute, and use this software as long as this
* copyright statement is not removed.
*/
#ifndef lint
static
char rcsid[] = "$Id: m_perror.c,v 1.1 1992/01/24 03:29:04 dvadura Exp $";
#endif
/*
* malloc errno error strings...
*/
char *malloc_err_strings[] =
{
"No errors",
"Malloc chain is corrupted, pointers out of order",
"Malloc chain is corrupted, end before end pointer",
"Pointer is not within malloc area",
"Malloc region does not have valid magic number in header",
"Pointers between this segment and ajoining segments are invalid",
"Data has overrun beyond requested number of bytes",
"Data in free'd area has been modified",
"Data are is not in use (can't be freed or realloced)",
"Unable to get additional memory from the system",
"Pointer within malloc region, but outside of malloc data bounds",
(char *) 0
};
/*
* Function: malloc_perror()
*
* Purpose: to print malloc_errno error message
*
* Arguments: str - string to print with error message
*
* Returns: nothing of any value
*
* Narrative:
*/
void
malloc_perror(str)
char * str;
{
extern int malloc_errno;
register char * s;
register char * t;
if( str && *str)
{
for(s=str; *s; s++)
{
/* do nothing */;
}
(void) write(2,str,(unsigned)(s-str));
(void) write(2,": ",(unsigned)2);
}
t = malloc_err_strings[malloc_errno];
for(s=t; *s; s++)
{
/* do nothing */;
}
(void) write(2,t,(unsigned)(s-t));
(void) write(2,"\n",(unsigned)1);
}
/*
* $Log: m_perror.c,v $
* Revision 1.1 1992/01/24 03:29:04 dvadura
* dmake Version 3.8, Initial revision
*
* Revision 1.5 90/08/29 21:25:08 cpcahil
* added additional error message that was missing (and
* caused a core dump)
*
* Revision 1.4 90/05/11 00:13:08 cpcahil
* added copyright statment
*
* Revision 1.3 90/02/24 21:50:21 cpcahil
* lots of lint fixes
*
* Revision 1.2 90/02/24 17:39:55 cpcahil
* 1. added function header
* 2. added rcs id and log strings.
*
*/

223
dmake/dbug/malloc/malloc.3 Normal file
View File

@ -0,0 +1,223 @@
.TH MALLOC 3 "" "" "1.0"
.ds ]T
.\"/*
.\" * (c) Copyright 1990 Conor P. Cahill (uunet!virtech!cpcahil).
.\" * You may copy, distribute, and use this software as long as this
.\" * copyright statement is not removed.
.\" */
.\" $Id: malloc.3,v 1.3 90/08/29 22:24:44 cpcahil Exp $
.SH NAME
malloc \t- debugging malloc library
.SH SYNOPSIS
.ft B
.nf
#include <malloc.h>
char * calloc(nelem,elsize);
void free(ptr);
char * malloc(size);
int malloc_chain_check(flag);
void malloc_dump(fd);
int mallopt(cmd,val)
char * realloc(ptr,size);
int cmd,fd,flag;
unsigned elsize,nelem,size;
char * ptr;
union malloptarg val;
.fi
.ft R
.SH DESCRIPTION
This malloc library is a replacement for the standard library to be used
during software development/debugging. See the standard malloc(3) pages
for more information on the use of the following functions:
.nf
.in +.5i
calloc(), free(), malloc(), realloc()
.in -.5i
.fi
.sp
This library differs from the standard malloc library in the
following ways:
.P
1. Each malloc segment contains a magic number so that free can
verify that the pointer passed points to a valid malloc segment.
.P
2. Each malloc segment is filled with a non-zero pattern so that code that
depends upon malloc segments being null will fail.
.P
3. The size of each segment will be at least 1 byte larger than requested
and the extra bytes will be filled with a non-zero pattern. When free is
called, it will verify that you did not go beyond the number of bytes
you asked for.
.P
4. When a segment is freed, it will be filled with a different non-zero pattern
to ensure that the program doesn't depend upon the use of already freed data.
.P
5. Whenever any of the string or memory functions (str*, b*, mem*) are
called with a pointer that is within the malloc arena, the operation is
checked to verify that it does not overrun the malloced segment. A failure
of this check is considered a "warning level error" (described later) and
is handled accordingly.
.P
7. Run time checking can include verification of the malloc chain at each
and every call to one of the malloc functions or manually by calling the
malloc_chain_check function.
.P
6. When a problem is found, the action taken is specified at runtime by
environment variables or at compile time by the use of the mallopt()
function.
.P
There are two arbitrary levels of errors, warning and fatal, that this
library will detect. They are broken down as follows:
.P
.nf
.in +.25i
Warning messages include:
.sp
.in +.5i
.ti -.25i
Calling free with a bad pointer
.br
.ti -.25i
Calling a bstring/string/memory (3) function which will go beyond
the end of a malloc block. Note that the library function is
not modified to refuse the operation.
.sp
.in -.5i
Fatal errors are:
.in +.5i
.ti -.25i
Detectable corruption to the malloc chain.
.in -.5i
.in -.25i
.P
The error handling for each level (warning or fatal) are specified using
environment variables or mallopt(). The coding for the error handling is
as follows:
.sp
.nf
.in +.5i
.ti -.25i
0 - continue operations
.ti -.25i
1 - drop core and exit
.ti -.25i
2 - just exit
.ti -.25i
3 - drop core, but continue executing. Core files will
be placed into core.[PID].[counter] i.e: core.00123.001
.ti -.25i
128 - dump malloc chain and continue
.ti -.25i
129 - dump malloc chain, dump core, and exit
.ti -.25i
130 - dump malloc chain, exit
.ti -.25i
131 - dump malloc chain, dump core, continue processing
.in -.5i
.P
In addition error messages can be placed into an error file.
.P
\fBmalloc_opt\fP() is used to set the malloc debugging options. The
following options can be set:
.br
.sp
.in +.5i
MALLOC_WARN - set the error handling for warning level errors. \fBval.i\fP is
an integer that can contain any one of the following values:
.sp
.in +.5i
M_HANDLE_IGNORE - ignore error
.br
M_HANDLE_ABORT - drop core and exit
.br
M_HANDLE_EXIT - just exit (no core drop)
.br
M_HANDLE_CORE - drop core, but keep on going
.br
.in -.5i
.sp
In addition, M_HANDLE_DUMP may be or'd in to cause a dump of the current
malloc chain.
.br
.sp
MALLOC_FATAL - set the error handling for fatal level errors. \fBval.i\fP is
equivalent to \fBval.i\fP for MALLOC_WARN.
.br
.sp
MALLOC_ERRFILE - set the destination for malloc error messages. \fBval.str\fP
is a pointer to a character string containing the name of the file to be used
for error messages.
.br
.sp
MALLOC_CKCHAIN - set the malloc chain checking flag. If \fBval.i\fP is
non-zero, chain checking at every call to malloc is turned on.
.br
.sp
For example, to set up the session to generate a core file for
every malloc warning, to drop core and exit on a malloc fatal, and
to log all messages to the file "malloc_log" do the following:
.sp
.nf
.in +.5i
#include <malloc.h>
malloc_opt(MALLOC_WARN,131);
malloc_opt(MALLOC_FATAL,1);
malloc_opt(MALLOC_ERRFILE,"malloc_log");
.in -.5i
.fi
.in -.5i
.sp
\fBmalloc_opt\fP() can be used to set/alter the debugging options at any
time.
.P
\fBmalloc_dump\fP() will dump a table of the malloc arena showing all
allocated/freed segments and the first few bytes of data in each segment.
\fBfd\fP is the file descriptor to write the data to.
.P
\fBmalloc_chain_check\fP() will check the status of the malloc arena.
If \fBflag\fP is non-zero, an error found in the chain will cause a
fatal error. \fBmalloc_chain_check\fP() returns zero when there are no
problems found in the malloc chain, non-zero otherwise.
.SH "ENVIRONMENT VARIABLES"
Environment variables can be used to control error handling, error logging
and malloc chain checking at run time. The following environment variables
are used:
.P
MALLOC_WARN - specifies the error handling for warning errors
.br
MALLOC_FATAL - specifies the error handling for fatal errors
.br
MALLOC_ERRFILE - specifies the error log file for error messages.
.br
MALLOC_CKCHAIN - if 1, turns on malloc chain checking at every call to any
of the malloc functions.
.P
For example, to set up the session to generate a core file for
every malloc warning, to drop core and exit on a malloc fatal, and
to log all messages to the file "malloc_log" do the following:
.sp
.nf
.in +.5i
MALLOC_WARN=131
MALLOC_FATAL=1
MALLOC_ERRFILE=malloc_log
export MALLOC_WARN MALLOC_FATAL MALLOC_ERRFILE
.in -.5i
.fi
.SH WARNINGS
This malloc library and it's associated string and memory functions are
much less efficient than the standard functions due in part to the extra
error checking. You do not want to use this library when generating a
production (i.e. releasable) version of your software. It should only
be used during development and testing.
.SH SEE ALSO
stat(2)
.SH AUTHOR
Conor P. Cahill
Virtual Technologies Incorporated
.sp
uunet!virtech!cpcahil

654
dmake/dbug/malloc/malloc.c Normal file
View File

@ -0,0 +1,654 @@
/*
* (c) Copyright 1990 Conor P. Cahill (uunet!virtech!cpcahil).
* You may copy, distribute, and use this software as long as this
* copyright statement is not removed.
*/
#include <stdio.h>
#include <fcntl.h>
#include "malloc.h"
#include "tostring.h"
/*
* Function: malloc()
*
* Purpose: memory allocator
*
* Arguments: size - size of data area needed
*
* Returns: pointer to allocated area, or NULL if unable
* to allocate addtional data.
*
* Narrative:
*
*/
#ifndef lint
static
char rcs_hdr[] = "$Id: malloc.c,v 1.1 1992/01/24 03:29:05 dvadura Exp $";
#endif
extern int malloc_checking;
char * malloc_data_start;
char * malloc_data_end;
struct mlist * malloc_end;
int malloc_errfd = 2;
int malloc_errno;
int malloc_fatal_level = M_HANDLE_CORE;
struct mlist malloc_start;
int malloc_warn_level;
void malloc_memset();
char *
malloc(size)
unsigned int size;
{
char * func = "malloc";
char * getenv();
void malloc_fatal();
void malloc_init();
void malloc_split();
void malloc_warning();
unsigned int need;
struct mlist * oldptr;
struct mlist * ptr;
char * sbrk();
/*
* If this is the first call to malloc...
*/
if( malloc_data_start == (char *) 0 )
{
malloc_init();
}
/*
* If malloc chain checking is on, go do it.
*/
if( malloc_checking )
{
(void) malloc_chain_check(1);
}
/*
* always make sure there is at least on extra byte in the malloc
* area so that we can verify that the user does not overrun the
* data area.
*/
size++;
/*
* Now look for a free area of memory of size bytes...
*/
oldptr = NULL;
for(ptr = &malloc_start; ; ptr = ptr->next)
{
/*
* Since the malloc chain is a forward only chain, any
* pointer that we get should always be positioned in
* memory following the previous pointer. If this is not
* so, we must have a corrupted chain.
*/
if( ptr )
{
if( IsLess(ptr,oldptr) )
{
malloc_errno = M_CODE_CHAIN_BROKE;
malloc_fatal(func);
return(NULL);
}
oldptr = ptr;
}
else if( oldptr != malloc_end )
{
/*
* This should never happen. If it does, then
* we got a real problem.
*/
malloc_errno = M_CODE_NO_END;
malloc_fatal(func);
return(NULL);
}
/*
* if this element is already in use...
*/
if( ptr && ((ptr->flag & M_INUSE) != 0) )
{
continue;
}
/*
* if there isn't room for this block..
*/
if( ptr && (ptr->s.size < size) )
{
continue;
}
/*
* If ptr is null, we have run out of memory and must sbrk more
*/
if( ptr == NULL )
{
need = (size + M_SIZE) * (size > 10*1024 ? 1:2);
if( need < M_BLOCKSIZE )
{
need = M_BLOCKSIZE;
}
else if( need & (M_BLOCKSIZE-1) )
{
need &= ~(M_BLOCKSIZE-1);
need += M_BLOCKSIZE;
}
ptr = (struct mlist *) sbrk((int)need);
if( ptr == (struct mlist *) -1 )
{
malloc_errno = M_CODE_NOMORE_MEM;
malloc_fatal(func);
}
malloc_data_end = sbrk((int)0);
ptr->prev = oldptr;
ptr->next = (struct mlist *) 0;
ptr->s.size = need - M_SIZE;
ptr->flag = M_MAGIC;
oldptr->next = ptr;
malloc_end = ptr;
} /* if( ptr ==... */
/*
* Now ptr points to a memory location that can store
* this data, so lets go to work.
*/
ptr->r_size = size; /* save requested size */
ptr->flag |= M_INUSE;
/*
* split off unneeded data area in this block, if possible...
*/
malloc_split(ptr);
/*
* re-adjust the requested size so that it is what the user
* actually requested...
*/
ptr->r_size--;
/*
* just to make sure that noone is misusing malloced
* memory without initializing it, lets set it to
* all '\01's. We call local_memset() because memset()
* may be checking for malloc'd ptrs and this isn't
* a malloc'd ptr yet.
*/
malloc_memset(ptr->data,M_FILL,(int)ptr->s.size);
return( ptr->data);
} /* for(... */
} /* malloc(... */
/*
* Function: malloc_split()
*
* Purpose: to split a malloc segment if there is enough room at the
* end of the segment that isn't being used
*
* Arguments: ptr - pointer to segment to split
*
* Returns: nothing of any use.
*
* Narrative:
* get the needed size of the module
* round the size up to appropriat boundry
* calculate amount of left over space
* if there is enough left over space
* create new malloc block out of remainder
* if next block is free
* join the two blocks together
* fill new empty block with free space filler
* re-adjust pointers and size of current malloc block
*
*
*
* Mod History:
* 90/01/27 cpcahil Initial revision.
*/
void
malloc_split(ptr)
struct mlist * ptr;
{
extern struct mlist * malloc_end;
void malloc_join();
int rest;
int size;
struct mlist * tptr;
size = ptr->r_size;
/*
* roundup size to the appropriate boundry
*/
M_ROUNDUP(size);
/*
* figure out how much room is left in the array.
* if there is enough room, create a new mlist
* structure there.
*/
if( ptr->s.size > size )
{
rest = ptr->s.size - size;
}
else
{
rest = 0;
}
if( rest > (M_SIZE+M_RND) )
{
tptr = (struct mlist *) (ptr->data+size);
tptr->prev = ptr;
tptr->next = ptr->next;
tptr->flag = M_MAGIC;
tptr->s.size = rest - M_SIZE;
/*
* If possible, join this segment with the next one
*/
malloc_join(tptr, tptr->next,0,0);
if( tptr->next )
{
tptr->next->prev = tptr;
}
malloc_memset(tptr->data,M_FREE_FILL, (int)tptr->s.size);
ptr->next = tptr;
ptr->s.size = size;
if( malloc_end == ptr )
{
malloc_end = tptr;
}
}
} /* malloc_split(... */
/*
* Function: malloc_join()
*
* Purpose: to join two malloc segments together (if possible)
*
* Arguments: ptr - pointer to segment to join to.
* nextptr - pointer to next segment to join to ptr.
*
* Returns: nothing of any values.
*
* Narrative:
*
* Mod History:
* 90/01/27 cpcahil Initial revision.
*/
void
malloc_join(ptr,nextptr, inuse_override, fill_flag)
struct mlist * ptr;
struct mlist * nextptr;
int inuse_override;
int fill_flag;
{
unsigned int newsize;
if( ptr && ! (inuse_override || (ptr->flag & M_INUSE)) &&
nextptr && ! (nextptr->flag & M_INUSE) &&
((ptr->data+ptr->s.size) == (char *) nextptr) )
{
if( malloc_end == nextptr )
{
malloc_end = ptr;
}
ptr->next = nextptr->next;
newsize = nextptr->s.size + M_SIZE;
/*
* if we are to fill and this segment is in use,
* fill in with M_FILL newly added space...
*/
if(fill_flag && (ptr->flag & M_INUSE) )
{
malloc_memset(ptr->data+ptr->s.size,
M_FILL, (int)(nextptr->s.size + M_SIZE));
}
ptr->s.size += newsize;
if( ptr->next )
{
ptr->next->prev = ptr;
}
}
} /* malloc_join(... */
/*
* The following mess is just to ensure that the versions of these functions in
* the current library are included (to make sure that we don't accidentaly get
* the libc versions. (This is the lazy man's -u ld directive)
*/
void free();
int strcmp();
int memcmp();
char * realloc();
void (*malloc_void_funcs[])() =
{
free,
};
int (*malloc_int_funcs[])() =
{
strcmp,
memcmp,
};
char * (*malloc_char_star_funcs[])() =
{
realloc,
};
/*
* This is malloc's own memset which is used without checking the parameters.
*/
void
malloc_memset(ptr,byte,len)
char * ptr;
char byte;
int len;
{
while(len-- > 0)
{
*ptr++ = byte;
}
} /* malloc_memset(... */
/*
* Function: malloc_fatal()
*
* Purpose: to display fatal error message and take approrpriate action
*
* Arguments: funcname - name of function calling this routine
*
* Returns: nothing of any value
*
* Narrative:
*
* Notes: This routine does not make use of any libc functions to build
* and/or disply the error message. This is due to the fact that
* we are probably at a point where malloc is having a real problem
* and we don't want to call any function that may use malloc.
*/
void
malloc_fatal(funcname)
char * funcname;
{
char errbuf[128];
void exit();
void malloc_err_handler();
extern char * malloc_err_strings[];
extern int malloc_errno;
extern int malloc_fatal_level;
char * s;
char * t;
s = errbuf;
t = "Fatal error: ";
while( *s = *t++)
{
s++;
}
t = funcname;
while( *s = *t++)
{
s++;
}
t = "(): ";
while( *s = *t++)
{
s++;
}
t = malloc_err_strings[malloc_errno];
while( *s = *t++)
{
s++;
}
*(s++) = '\n';
if( write(malloc_errfd,errbuf,(unsigned)(s-errbuf)) != (s-errbuf))
{
(void) write(2,"I/O error to error file\n",(unsigned)24);
exit(110);
}
malloc_err_handler(malloc_fatal_level);
} /* malloc_fatal(... */
/*
* Function: malloc_warning()
*
* Purpose: to display warning error message and take approrpriate action
*
* Arguments: funcname - name of function calling this routine
*
* Returns: nothing of any value
*
* Narrative:
*
* Notes: This routine does not make use of any libc functions to build
* and/or disply the error message. This is due to the fact that
* we are probably at a point where malloc is having a real problem
* and we don't want to call any function that may use malloc.
*/
void
malloc_warning(funcname)
char * funcname;
{
char errbuf[128];
void exit();
void malloc_err_handler();
extern char * malloc_err_strings[];
extern int malloc_errno;
extern int malloc_warn_level;
char * s;
char * t;
s = errbuf;
t = "Warning: ";
while( *s = *t++)
{
s++;
}
t = funcname;
while( *s = *t++)
{
s++;
}
t = "(): ";
while( *s = *t++)
{
s++;
}
t = malloc_err_strings[malloc_errno];
while( *s = *t++)
{
s++;
}
*(s++) = '\n';
if( write(malloc_errfd,errbuf,(unsigned)(s-errbuf)) != (s-errbuf))
{
(void) write(2,"I/O error to error file\n",(unsigned)24);
exit(110);
}
malloc_err_handler(malloc_warn_level);
} /* malloc_warning(... */
/*
* Function: malloc_err_handler()
*
* Purpose: to take the appropriate action for warning and/or fatal
* error conditions.
*
* Arguments: level - error handling level
*
* Returns: nothing of any value
*
* Narrative:
*
* Notes: This routine does not make use of any libc functions to build
* and/or disply the error message. This is due to the fact that
* we are probably at a point where malloc is having a real problem
* and we don't want to call any function that may use malloc.
*/
void
malloc_err_handler(level)
{
void exit();
void malloc_dump();
extern int malloc_errfd;
if( level & M_HANDLE_DUMP )
{
malloc_dump(malloc_errfd);
}
switch( level & ~M_HANDLE_DUMP )
{
/*
* If we are to drop a core file and exit
*/
case M_HANDLE_ABORT:
(void) abort();
break;
/*
* If we are to exit..
*/
case M_HANDLE_EXIT:
exit(200);
break;
#ifndef __MSDOS__
/*
* If we are to dump a core, but keep going on our merry way
*/
case M_HANDLE_CORE:
{
int pid;
/*
* fork so child can abort (and dump core)
*/
if( (pid = fork()) == 0 )
{
(void) write(2,"Child dumping core\n",
(unsigned)9);
(void) abort();
}
/*
* wait for child to finish dumping core
*/
while( wait((int *)0) != pid)
{
}
/*
* Move core file to core.pid.cnt so
* multiple cores don't overwrite each
* other.
*/
if( access("core",0) == 0 )
{
static int corecnt;
char filenam[32];
filenam[0] = 'c';
filenam[1] = 'o';
filenam[2] = 'r';
filenam[3] = 'e';
filenam[4] = '.';
(void)tostring(filenam+5,getpid(),
5, B_DEC, '0');
filenam[10] = '.';
(void)tostring(filenam+11,corecnt++,
3, B_DEC, '0');
filenam[14] = '\0';
(void) unlink(filenam);
if( link("core",filenam) == 0)
{
(void) unlink("core");
}
}
}
#endif
/*
* If we are to just ignore the error and keep on processing
*/
case M_HANDLE_IGNORE:
break;
} /* switch(... */
} /* malloc_err_handler(... */
/*
* $Log: malloc.c,v $
* Revision 1.1 1992/01/24 03:29:05 dvadura
* dmake Version 3.8, Initial revision
*
* Revision 1.6 90/05/11 00:13:09 cpcahil
* added copyright statment
*
* Revision 1.5 90/02/25 11:01:18 cpcahil
* added support for malloc chain checking.
*
* Revision 1.4 90/02/24 21:50:21 cpcahil
* lots of lint fixes
*
* Revision 1.3 90/02/24 14:51:18 cpcahil
* 1. changed malloc_fatal and malloc_warn to use malloc_errno and be passed
* the function name as a parameter.
* 2. Added several function headers.
* 3. Changed uses of malloc_fatal/warning to conform to new usage.
*
* Revision 1.2 90/02/23 18:05:23 cpcahil
* fixed open of error log to use append mode.
*
* Revision 1.1 90/02/22 23:17:43 cpcahil
* Initial revision
*
*/

103
dmake/dbug/malloc/malloc.h Normal file
View File

@ -0,0 +1,103 @@
/*
* (c) Copyright 1990 Conor P. Cahill (uunet!virtech!cpcahil).
* You may copy, distribute, and use this software as long as this
* copyright statement is not removed.
*/
/*
* $Id: malloc.h,v 1.1 1992/01/24 03:29:06 dvadura Exp $
*/
struct mlist
{
struct mlist * next; /* next entry in chain */
struct mlist * prev; /* prev entry in chain */
int flag; /* inuse flag */
unsigned int r_size; /* requested size */
union
{
unsigned int size; /* actual size */
double unused_just_for_alignment;
} s;
char data[4];
};
#define M_SIZE ((int)(char *)((struct mlist *)0)->data)
#define M_RND 0x08
#define M_INUSE 0x01
#define M_MAGIC 0x03156100
#define M_BLOCKSIZE (1024*8)
#define M_FILL '\01'
#define M_FREE_FILL '\02'
#define M_ROUNDUP(size) {\
if( size & (M_RND-1) ) \
{ \
size &= ~(M_RND-1); \
size += M_RND; \
} \
}
/*
* Malloc warning/fatal error handler defines...
*/
#define M_HANDLE_DUMP 0x80 /* 128 */
#define M_HANDLE_IGNORE 0
#define M_HANDLE_ABORT 1
#define M_HANDLE_EXIT 2
#define M_HANDLE_CORE 3
/*
* Mallopt commands and defaults
*/
#define MALLOC_WARN 1 /* set malloc warning handling */
#define MALLOC_FATAL 2 /* set malloc fatal handling */
#define MALLOC_ERRFILE 3 /* specify malloc error file */
#define MALLOC_CKCHAIN 4 /* turn on chain checking */
union malloptarg
{
int i;
char * str;
};
/*
* Malloc warning/fatal error codes
*/
#define M_CODE_CHAIN_BROKE 1 /* malloc chain is broken */
#define M_CODE_NO_END 2 /* chain end != endptr */
#define M_CODE_BAD_PTR 3 /* pointer not in malloc area */
#define M_CODE_BAD_MAGIC 4 /* bad magic number in header */
#define M_CODE_BAD_CONNECT 5 /* chain poingers corrupt */
#define M_CODE_OVERRUN 6 /* data overrun in malloc seg */
#define M_CODE_REUSE 7 /* reuse of freed area */
#define M_CODE_NOT_INUSE 8 /* pointer is not in use */
#define M_CODE_NOMORE_MEM 9 /* no more memory available */
#define M_CODE_OUTOF_BOUNDS 10 /* gone beyound bounds */
void malloc_warning();
void malloc_fatal();
void malloc_check_data();
void malloc_check_str();
void malloc_verify();
/*
* $Log: malloc.h,v $
* Revision 1.1 1992/01/24 03:29:06 dvadura
* dmake Version 3.8, Initial revision
*
* Revision 1.4 90/08/29 22:23:38 cpcahil
* fixed mallopt to use a union as an argument.
*
* Revision 1.3 90/05/11 11:04:10 cpcahil
* took out some extraneous lines
*
* Revision 1.2 90/05/11 00:13:09 cpcahil
* added copyright statment
*
* Revision 1.1 90/02/23 07:09:03 cpcahil
* Initial revision
*
*/

125
dmake/dbug/malloc/mallopt.c Normal file
View File

@ -0,0 +1,125 @@
/*
* (c) Copyright 1990 Conor P. Cahill (uunet!virtech!cpcahil).
* You may copy, distribute, and use this software as long as this
* copyright statement is not removed.
*/
#include <stdio.h>
#include <fcntl.h>
#include "malloc.h"
/*
* Function: mallopt()
*
* Purpose: to set options for the malloc debugging library
*
* Arguments: none
*
* Returns: nothing of any value
*
* Narrative:
*
*/
#ifndef lint
static
char rcs_hdr[] = "$Id: mallopt.c,v 1.1 1992/01/24 03:29:07 dvadura Exp $";
#endif
int
mallopt(cmd,value)
int cmd;
union malloptarg value;
{
int i;
extern int malloc_checking;
extern char * malloc_data_start;
extern int malloc_errfd;
extern int malloc_fatal_level;
void malloc_init();
extern int malloc_warn_level;
register char * s;
/*
* If not initialized...
*/
if( malloc_data_start == (char *) 0)
{
malloc_init();
}
switch(cmd)
{
case MALLOC_WARN:
malloc_warn_level = value.i;
break;
case MALLOC_FATAL:
malloc_fatal_level = value.i;
break;
case MALLOC_CKCHAIN:
malloc_checking = value.i;
break;
case MALLOC_ERRFILE:
i = open(value.str,O_CREAT|O_APPEND|O_WRONLY,0666);
if( i == -1 )
{
(void) write(2,
"Unable to open malloc error file: ",
(unsigned) 34);
for(s=value.str; *s; s++)
{
/* do nothing */;
}
(void) write(2,value.str,
(unsigned)(s-value.str));
(void) write(2,"\n",(unsigned)1);
}
else
{
if( malloc_errfd != 2 )
{
(void) close(malloc_errfd);
}
malloc_errfd = i;
}
break;
default:
return(1);
}
return(0);
}
/*
* $Log: mallopt.c,v $
* Revision 1.1 1992/01/24 03:29:07 dvadura
* dmake Version 3.8, Initial revision
*
* Revision 1.6 90/08/29 22:23:36 cpcahil
* fixed mallopt to use a union as an argument.
*
* Revision 1.5 90/08/29 21:22:51 cpcahil
* miscellaneous lint fixes
*
* Revision 1.4 90/05/11 00:13:10 cpcahil
* added copyright statment
*
* Revision 1.3 90/02/25 11:03:26 cpcahil
* changed to return int so that it agrees with l libmalloc.a's mallopt()
*
* Revision 1.2 90/02/25 11:01:21 cpcahil
* added support for malloc chain checking.
*
* Revision 1.1 90/02/24 21:50:24 cpcahil
* Initial revision
*
* Revision 1.1 90/02/24 17:10:53 cpcahil
* Initial revision
*
*/

225
dmake/dbug/malloc/memory.c Normal file
View File

@ -0,0 +1,225 @@
/*
* (c) Copyright 1990 Conor P. Cahill (uunet!virtech!cpcahil).
* You may copy, distribute, and use this software as long as this
* copyright statement is not removed.
*/
#ifndef lint
static
char rcs_hdr[] = "$Id: memory.c,v 1.1 1992/01/24 03:29:08 dvadura Exp $";
#endif
void malloc_check_data();
char *
memccpy(ptr1, ptr2, ch, len)
register char * ptr1;
register char * ptr2;
int len;
int ch;
{
int check;
register int i;
char * rtn;
/*
* I know that the assignment could be done in the following, but
* I wanted to perform a check before any assignment, so first I
* determine the length, check the pointers and then do the assignment.
*/
for( i=0; (i < len) && (ptr2[i] != ch); i++)
{
}
if( ptr2[i] == ch )
{
check = i+1;
}
else
{
check = len;
}
malloc_check_data("memccpy", ptr1, check);
malloc_check_data("memccpy", ptr2, check);
/*
* if we found the character...
*/
if( i < len )
{
rtn = ptr1+i+1;
i++;
}
else
{
rtn = (char *) 0;
}
while( i-- )
{
*(ptr1++) = *(ptr2++);
}
return(rtn);
}
char *
memchr(ptr1,ch,len)
register char * ptr1;
register int ch;
int len;
{
int i;
for( i=0; (i < len) && (ptr1[i] != (char) ch); i++)
{
}
malloc_check_data("memchr", ptr1, i);
if( i < len )
{
return( ptr1+i );
}
else
{
return( (char *) 0);
}
}
char *
memcpy(ptr1, ptr2, len)
register char * ptr1;
register char * ptr2;
register int len;
{
char * rtn = ptr1;
malloc_check_data("memcpy", ptr1, len);
malloc_check_data("memcpy", ptr2, len);
/*
* while the normal memcpy does not guarrantee that it will
* handle overlapping memory correctly, we will try...
*/
if( ptr1 > ptr2 && ptr1 < (ptr2+len))
{
ptr1 += (len-1);
ptr2 += (len-1);
while( len-- > 0 )
{
*(ptr1--) = *(ptr2--);
}
}
else
{
while( len-- > 0 )
{
*(ptr1++) = *(ptr2++);
}
}
return(rtn);
}
int
memcmp(ptr1, ptr2, len)
register char * ptr1;
register char * ptr2;
register int len;
{
malloc_check_data("memcpy", ptr1, len);
malloc_check_data("memcpy", ptr2, len);
while( --len >= 0 && (*ptr1 == *ptr2) )
{
ptr1++;
ptr2++;
}
/*
* If stopped by len, return zero
*/
if( len < 0 )
{
return(0);
}
return( *ptr1 - *ptr2 );
}
char *
memset(ptr1, ch, len)
register char * ptr1;
register int ch;
register int len;
{
char * rtn = ptr1;
malloc_check_data("memcpy", ptr1, len);
while( len-- )
{
*(ptr1++) = ch;
}
return(rtn);
}
char *
bcopy(ptr2,ptr1,len)
char * ptr2;
char * ptr1;
int len;
{
return(memcpy(ptr1,ptr2,len));
}
char *
bzero(ptr1,len)
char * ptr1;
int len;
{
return(memset(ptr1,'\0',len));
}
int
bcmp(ptr2, ptr1, len)
char * ptr1;
char * ptr2;
int len;
{
return( memcmp(ptr1,ptr2,len) );
}
/*
* $Log: memory.c,v $
* Revision 1.1 1992/01/24 03:29:08 dvadura
* dmake Version 3.8, Initial revision
*
* Revision 1.7 90/08/29 21:27:58 cpcahil
* fixed value of check in memccpy when character was not found.
*
* Revision 1.6 90/07/16 20:06:26 cpcahil
* fixed several minor bugs found with Henry Spencer's string/mem tester
* program.
*
*
* Revision 1.5 90/05/11 15:39:36 cpcahil
* fixed bug in memccpy().
*
* Revision 1.4 90/05/11 00:13:10 cpcahil
* added copyright statment
*
* Revision 1.3 90/02/24 21:50:29 cpcahil
* lots of lint fixes
*
* Revision 1.2 90/02/24 17:29:41 cpcahil
* changed $Header to $Id so full path wouldnt be included as part of rcs
* id string
*
* Revision 1.1 90/02/22 23:17:43 cpcahil
* Initial revision
*
*/

279
dmake/dbug/malloc/mlc_chk.c Normal file
View File

@ -0,0 +1,279 @@
/*
* (c) Copyright 1990 Conor P. Cahill (uunet!virtech!cpcahil).
* You may copy, distribute, and use this software as long as this
* copyright statement is not removed.
*/
#include <stdio.h>
#include "malloc.h"
#include "debug.h"
#ifndef lint
static
char rcs_hdr[] = "$Id: mlc_chk.c,v 1.1 1992/01/24 03:29:09 dvadura Exp $";
#endif
extern struct mlist malloc_start;
extern struct mlist * malloc_end;
extern char * malloc_data_start;
extern char * malloc_data_end;
/*
* Function: malloc_in_arena()
*
* Purpose: to verify address is within malloc arena.
*
* Arguments: ptr - pointer to verify
*
* Returns: TRUE - if pointer is within malloc area
* FALSE - otherwise
*
* Narrative:
* IF pointer is >= malloc area start AND <= malloc area end
* return TRUE
* ELSE
* return FALSE
*
* Mod History:
* 90/01/24 cpcahil Initial revision.
*/
int
malloc_in_arena(ptr)
char * ptr;
{
extern char * malloc_data_start;
extern char * malloc_data_end;
int rtn = 0;
if( ptr >= malloc_data_start && ptr <= malloc_data_end )
{
rtn = 1;
}
return(rtn);
}
/*
* Function: malloc_check_str()
*
* Arguments: func - name of function calling this routine
* str - pointer to area to check
*
* Purpose: to verify that if str is within the malloc arena, the data
* it points to does not extend beyond the applicable region.
*
* Returns: Nothing of any use (function is void).
*
* Narrative:
* IF pointer is within malloc arena
* determin length of string
* call malloc_verify() to verify data is withing applicable region
* return
*
* Mod History:
* 90/01/24 cpcahil Initial revision.
* 90/01/29 cpcahil Added code to ignore recursive calls.
*/
void
malloc_check_str(func,str)
char * func;
char * str;
{
static int layers;
register char * s;
if( (layers++ == 0) && malloc_in_arena(str) )
{
for( s=str; *s; s++)
{
}
malloc_verify(func,str,s-str+1);
}
layers--;
}
/*
* Function: malloc_check_strn()
*
* Arguments: func - name of function calling this routine
* str - pointer to area to check
* len - max length of string
*
* Purpose: to verify that if str is within the malloc arena, the data
* it points to does not extend beyond the applicable region.
*
* Returns: Nothing of any use (function is void).
*
* Narrative:
* IF pointer is within malloc arena
* determin length of string
* call malloc_verify() to verify data is withing applicable region
* return
*
* Mod History:
* 90/01/24 cpcahil Initial revision.
* 90/01/29 cpcahil Added code to ignore recursive calls.
* 90/08/29 cpcahil added length (for strn* functions)
*/
void
malloc_check_strn(func,str,len)
char * func;
char * str;
int len;
{
register int i;
static int layers;
register char * s;
if( (layers++ == 0) && malloc_in_arena(str) )
{
for( s=str,i=0; (i < len) && *s; s++)
{
}
malloc_verify(func,str,s-str+1);
}
layers--;
}
/*
* Function: malloc_check_data()
*
* Arguments: func - name of function calling this routine
* ptr - pointer to area to check
* len - length to verify
*
* Purpose: to verify that if ptr is within the malloc arena, the data
* it points to does not extend beyond the applicable region.
*
* Returns: Nothing of any use (function is void).
*
* Narrative:
* IF pointer is within malloc arena
* call malloc_verify() to verify data is withing applicable region
* return
*
* Mod History:
* 90/01/24 cpcahil Initial revision.
* 90/01/29 cpcahil Added code to ignore recursive calls.
*/
void
malloc_check_data(func,ptr,len)
char * func;
char * ptr;
int len;
{
static int layers;
if( layers++ == 0 )
{
DEBUG3(40,"malloc_check_data(%s,0x%x,%d) called...",
func,ptr,len);
if( malloc_in_arena(ptr) )
{
DEBUG0(10,"pointer in malloc arena, verifying...");
malloc_verify(func,ptr,len);
}
}
layers--;
}
/*
* Function: malloc_verify()
*
* Arguments: func - name of function calling the malloc check routines
* ptr - pointer to area to check
* len - length to verify
*
* Purpose: to verify that the data ptr points to does not extend beyond
* the applicable malloc region. This function is only called
* if it has been determined that ptr points into the malloc arena.
*
* Returns: Nothing of any use (function is void).
*
* Narrative:
*
* Mod History:
* 90/01/24 cpcahil Initial revision.
*/
void
malloc_verify(func,ptr,len)
char * func;
char * ptr;
int len;
{
extern struct mlist * malloc_end;
extern int malloc_errno;
extern struct mlist malloc_start;
struct mlist * mptr;
DEBUG3(40,"malloc_verify(%s,0x%x,%d) called...", func,ptr,len);
/*
* Find the malloc block that includes this pointer
*/
mptr = &malloc_start;
while( mptr &&
! (((char *)mptr < ptr) && ((mptr->data+mptr->s.size) > ptr) ) )
{
mptr = mptr->next;
}
/*
* if ptr was not in a malloc block, it must be part of
* some direct sbrk() stuff, so just return.
*/
if( ! mptr )
{
DEBUG1(10,"ptr (0x%x) not found in malloc search", ptr);
return;
}
/*
* Now we have a valid malloc block that contains the indicated
* pointer. We must verify that it is withing the requested block
* size (as opposed to the real block size which is rounded up to
* allow for correct alignment).
*/
DEBUG4(60,"Checking 0x%x-0x%x, 0x%x-0x%x",
ptr, ptr+len, mptr->data, mptr->data+mptr->r_size);
if( (ptr < mptr->data) || ((ptr+len) > (mptr->data+mptr->r_size)) )
{
DEBUG4(0,"pointer not within region 0x%x-0x%x, 0x%x-0x%x",
ptr, ptr+len, mptr->data, mptr->data+mptr->r_size);
malloc_errno = M_CODE_OUTOF_BOUNDS;
malloc_warning(func);
}
return;
}
/*
* $Log: mlc_chk.c,v $
* Revision 1.1 1992/01/24 03:29:09 dvadura
* dmake Version 3.8, Initial revision
*
* Revision 1.5 90/08/29 22:23:48 cpcahil
* added new function to check on strings up to a specified length
* and used it within several strn* functions.
*
* Revision 1.4 90/05/11 00:13:09 cpcahil
* added copyright statment
*
* Revision 1.3 90/02/24 21:50:22 cpcahil
* lots of lint fixes
*
* Revision 1.2 90/02/24 17:29:38 cpcahil
* changed $Header to $Id so full path wouldnt be included as part of rcs
* id string
*
* Revision 1.1 90/02/24 14:57:03 cpcahil
* Initial revision
*
*/

188
dmake/dbug/malloc/mlc_chn.c Normal file
View File

@ -0,0 +1,188 @@
/*
* (c) Copyright 1990 Conor P. Cahill (uunet!virtech!cpcahil).
* You may copy, distribute, and use this software as long as this
* copyright statement is not removed.
*/
#include <stdio.h>
#include <fcntl.h>
#include "malloc.h"
/*
* Function: malloc_chain_check()
*
* Purpose: to verify malloc chain is intact
*
* Arguments: todo - 0 - just check and return status
* 1 - call malloc_warn if error detected
*
* Returns: 0 - malloc chain intact & no overflows
* other - problems detected in malloc chain
*
* Narrative:
*
* Notes: If todo is non-zero the malloc_warn function, when called
* may not return (i.e. it may exit)
*
*/
#ifndef lint
static
char rcs_hdr[] = "$Id: mlc_chn.c,v 1.1 1992/01/24 03:29:10 dvadura Exp $";
#endif
int
malloc_chain_check(todo)
int todo;
{
char * func = "malloc_chain_check";
int i;
extern char * malloc_data_start;
extern char * malloc_data_end;
extern struct mlist * malloc_end;
extern int malloc_errno;
extern struct mlist malloc_start;
struct mlist * oldptr;
struct mlist * ptr;
int rtn = 0;
oldptr = &malloc_start;
for(ptr = malloc_start.next; ; ptr = ptr->next)
{
/*
* Since the malloc chain is a forward only chain, any
* pointer that we get should always be positioned in
* memory following the previous pointer. If this is not
* so, we must have a corrupted chain.
*/
if( ptr )
{
if(ptr < oldptr )
{
malloc_errno = M_CODE_CHAIN_BROKE;
if( todo )
{
malloc_fatal(func);
}
rtn++;
break;
}
oldptr = ptr;
}
else
{
if( oldptr != malloc_end )
{
/*
* This should never happen. If it does, then
* we got a real problem.
*/
malloc_errno = M_CODE_NO_END;
if( todo )
{
malloc_fatal(func);
}
rtn++;
}
break;
}
/*
* verify that ptr is within the malloc region...
* since we started within the malloc chain this should never
* happen.
*/
if( ((char *)ptr < malloc_data_start) ||
((char *)ptr > malloc_data_end) )
{
malloc_errno = M_CODE_BAD_PTR;
if( todo )
{
malloc_fatal(func);
}
rtn++;
break;
}
/*
* verify magic flag is set
*/
if( (ptr->flag&M_MAGIC) != M_MAGIC )
{
malloc_errno = M_CODE_BAD_MAGIC;
if( todo )
{
malloc_warning(func);
}
rtn++;
continue;
}
/*
* verify segments are correctly linked together
*/
if( (ptr->prev && (ptr->prev->next != ptr) ) ||
(ptr->next && (ptr->next->prev != ptr) ) ||
((ptr->next == NULL) && (ptr->prev == NULL)) )
{
malloc_errno = M_CODE_BAD_CONNECT;
if( todo )
{
malloc_warning(func);
}
rtn++;
continue;
}
/*
* If this segment is allocated
*/
if( (ptr->flag & M_INUSE) != 0 )
{
/*
* verify no overflow of data area
*/
for(i=ptr->r_size; i < ptr->s.size; i++)
{
if( ptr->data[i] != M_FILL )
{
malloc_errno = M_CODE_OVERRUN;
if( todo )
{
malloc_warning(func);
}
rtn++;
break;
}
}
}
else /* it's not allocated so */
{
/*
* verify no reuse of freed data blocks
*/
for(i=0; i < ptr->s.size; i++)
{
if( ptr->data[i] != M_FREE_FILL )
{
malloc_errno = M_CODE_REUSE;
if( todo )
{
malloc_warning(func);
}
rtn++;
break;
}
}
}
} /* for(... */
return(rtn);
} /* malloc_chain_check(... */

View File

@ -0,0 +1 @@
3

215
dmake/dbug/malloc/realloc.c Normal file
View File

@ -0,0 +1,215 @@
/*
* (c) Copyright 1990 Conor P. Cahill (uunet!virtech!cpcahil).
* You may copy, distribute, and use this software as long as this
* copyright statement is not removed.
*/
#include <stdio.h>
#include "malloc.h"
/*
* Function: realloc()
*
* Purpose: to re-allocate a data area.
*
* Arguments: cptr - pointer to area to reallocate
* size - size to change area to
*
* Returns: pointer to new area (may be same area)
*
* Narrative: verify pointer is within malloc region
* obtain mlist pointer from cptr
* verify magic number is correct
* verify inuse flag is set
* verify connection to adjoining segments is correct
* save requested size
* round-up size to appropriate boundry
* IF size is bigger than what is in this segment
* try to join next segment to this segment
* IF size is less than what is is this segment
* determine leftover amount of space
* ELSE
* allocate new segment of size bites
* IF allocation failed
* return NULL
* copy previous data to new segment
* free previous segment
* return new pointer
* split of extra space in this segment (if any)
* clear bytes beyound what they had before
* return pointer to data
*/
#ifndef lint
static
char rcs_hdr[] = "$Id: realloc.c,v 1.1 1992/01/24 03:29:11 dvadura Exp $";
#endif
char *
realloc(cptr,size)
char * cptr;
unsigned int size;
{
void free();
char * func = "realloc";
int i;
char * malloc();
extern int malloc_checking;
extern struct mlist * malloc_end;
extern int malloc_errno;
extern char * malloc_data_end;
extern char * malloc_data_start;
void malloc_join();
void malloc_memset();
void malloc_split();
char * memcpy();
char * new_cptr;
struct mlist * ptr;
int r_size;
/*
* IF malloc chain checking is on, go do it.
*/
if( malloc_checking )
{
(void) malloc_chain_check(1);
}
/*
* verify that cptr is within the malloc region...
*/
if( cptr < malloc_data_start || cptr > malloc_data_end )
{
malloc_errno = M_CODE_BAD_PTR;
malloc_warning(func);
return (NULL);
}
/*
* convert pointer to mlist struct pointer. To do this we must
* move the pointer backwards the correct number of bytes...
*/
ptr = (struct mlist *) (cptr - M_SIZE);
if( (ptr->flag&M_MAGIC) != M_MAGIC )
{
malloc_errno = M_CODE_BAD_MAGIC;
malloc_warning(func);
return(NULL);
}
if( ! (ptr->flag & M_INUSE) )
{
malloc_errno = M_CODE_NOT_INUSE ;
malloc_warning(func);
return(NULL);
}
if( (ptr->prev && (ptr->prev->next != ptr) ) ||
(ptr->next && (ptr->next->prev != ptr) ) ||
((ptr->next == NULL) && (ptr->prev == NULL)) )
{
malloc_errno = M_CODE_BAD_CONNECT;
malloc_warning(func);
return(NULL);
}
r_size = ++size;
M_ROUNDUP(size);
if( size > ptr->s.size )
{
malloc_join(ptr,ptr->next,1,1);
}
if( size > ptr->s.size )
{
/*
* else we can't combine it, so lets allocate a new chunk,
* copy the data and free the old chunk...
*/
new_cptr = malloc(size);
if( new_cptr == (char *) 0)
{
return(new_cptr);
}
if( r_size < ptr->r_size )
{
i = r_size;
}
else
{
i = ptr->r_size;
}
(void)memcpy(new_cptr,ptr->data,i);
free(cptr);
return(new_cptr);
} /* else... */
/*
* save amount of real data in new segment (this will be used in the
* memset later) and then save requested size of this segment.
*/
if( ptr->r_size < r_size )
{
i = ptr->r_size;
}
else
{
i = r_size;
}
ptr->r_size = r_size;
/*
* split off extra free space at end of this segment, if possible...
*/
malloc_split(ptr);
malloc_memset( ptr->data+i, M_FILL, (int) (ptr->s.size - i));
return(ptr->data);
} /* realloc(... */
/*
* $Log: realloc.c,v $
* Revision 1.1 1992/01/24 03:29:11 dvadura
* dmake Version 3.8, Initial revision
*
* Revision 1.8 90/08/29 21:22:52 cpcahil
* miscellaneous lint fixes
*
* Revision 1.7 90/05/11 00:13:10 cpcahil
* added copyright statment
*
* Revision 1.6 90/02/25 11:01:20 cpcahil
* added support for malloc chain checking.
*
* Revision 1.5 90/02/24 21:50:31 cpcahil
* lots of lint fixes
*
* Revision 1.4 90/02/24 17:29:39 cpcahil
* changed $Header to $Id so full path wouldnt be included as part of rcs
* id string
*
* Revision 1.3 90/02/24 17:20:00 cpcahil
* attempt to get rid of full path in rcs header.
*
* Revision 1.2 90/02/24 15:14:20 cpcahil
* 1. added function header
* 2. changed calls to malloc_warning to conform to new usage
* 3. added setting of malloc_errno
* 4. broke up bad pointer determination so that errno's would be more
* descriptive
*
* Revision 1.1 90/02/22 23:17:43 cpcahil
* Initial revision
*
*/

563
dmake/dbug/malloc/string.c Normal file
View File

@ -0,0 +1,563 @@
/*
* (c) Copyright 1990 Conor P. Cahill (uunet!virtech!cpcahil).
* You may copy, distribute, and use this software as long as this
* copyright statement is not removed.
*/
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include "malloc.h"
#ifndef lint
static
char rcs_hdr[] = "$Id: string.c,v 1.1 1992/01/24 03:29:13 dvadura Exp $";
#endif
int malloc_checking = 0;
char *
strcat(str1,str2)
register char * str1;
register char * str2;
{
char * rtn;
int len;
/*
* check pointers agains malloc region. The malloc* functions
* will properly handle the case where a pointer does not
* point into malloc space.
*/
malloc_checking = 1;
len = strlen(str2);
malloc_check_str("strcat", str2);
len += strlen(str1) + 1;
malloc_checking = 0;
malloc_check_data("strcat", str1, len);
rtn = str1;
while( *str1 )
{
str1++;
}
while( (*str1 = *str2) != '\0' )
{
str1++;
str2++;
}
return(rtn);
}
char *
strdup(str1)
register char * str1;
{
char * malloc();
char * rtn;
register char * str2;
malloc_check_str("strdup", str1);
rtn = str2 = malloc((unsigned)strlen(str1)+1);
if( rtn != (char *) 0)
{
while( (*str2 = *str1) != '\0' )
{
str1++;
str2++;
}
}
return(rtn);
}
char *
strncat(str1,str2,len)
register char * str1;
register char * str2;
register int len;
{
int len1;
int len2;
char * rtn;
malloc_check_strn("strncat", str2, len);
malloc_checking = 1;
len2 = strlen(str2) + 1;
len1 = strlen(str1);
malloc_checking = 0;
if( (len+1) < len2 )
{
len1 += len + 1;
}
else
{
len1 += len2;
}
malloc_check_data("strncat", str1, len1);
rtn = str1;
while( *str1 )
{
str1++;
}
while( len-- && ((*str1++ = *str2++) != '\0') )
{
}
if( ! len )
{
*str1 = '\0';
}
return(rtn);
}
int
strcmp(str1,str2)
register char * str1;
register char * str2;
{
malloc_check_str("strcmp", str1);
malloc_check_str("strcmp", str2);
while( *str1 && (*str1 == *str2) )
{
str1++;
str2++;
}
/*
* in order to deal with the case of a negative last char of either
* string when the other string has a null
*/
if( (*str2 == '\0') && (*str1 == '\0') )
{
return(0);
}
else if( *str2 == '\0' )
{
return(1);
}
else if( *str1 == '\0' )
{
return(-1);
}
return( *str1 - *str2 );
}
int
strncmp(str1,str2,len)
register char * str1;
register char * str2;
register int len;
{
malloc_check_strn("strncmp", str1, len);
malloc_check_strn("strncmp", str2, len);
while( --len >= 0 && *str1 && (*str1 == *str2) )
{
str1++;
str2++;
}
if( len < 0 )
{
return(0);
}
/*
* in order to deal with the case of a negative last char of either
* string when the other string has a null
*/
if( (*str2 == '\0') && (*str1 == '\0') )
{
return(0);
}
else if( *str2 == '\0' )
{
return(1);
}
else if( *str1 == '\0' )
{
return(-1);
}
return( *str1 - *str2 );
}
char *
strcpy(str1,str2)
register char * str1;
register char * str2;
{
char * rtn;
int len;
malloc_checking = 1;
len = strlen(str2) + 1;
malloc_checking = 0;
malloc_check_data("strcpy", str1, len);
malloc_check_data("strcpy", str2, len);
rtn = str1;
while( (*str1++ = *str2++) != '\0')
{
}
return(rtn);
}
char *
strncpy(str1,str2,len)
register char * str1;
register char * str2;
register int len;
{
extern int malloc_checking;
char * rtn;
malloc_check_data("strncpy", str1, len);
malloc_check_strn("strncpy", str2, len);
rtn = str1;
while((len-- > 0) && (*str1++ = *str2++) != '\0')
{
}
while( (len-- > 0) )
{
*str1++ = '\0';
}
return(rtn);
}
int
strlen(str1)
register char * str1;
{
register char * s;
if(! malloc_checking )
{
malloc_check_str("strlen", str1);
}
for( s = str1; *s; s++)
{
}
return( s - str1 );
}
char *
strchr(str1,c)
register char * str1;
register int c;
{
malloc_check_str("strchr", str1);
while( *str1 && (*str1 != (char) c) )
{
str1++;
}
if(*str1 != (char) c)
{
str1 = (char *) 0;
}
return(str1);
}
char *
strrchr(str1,c)
register char * str1;
register int c;
{
register char * rtn = (char *) 0;
malloc_check_str("strrchr", str1);
while( *str1 )
{
if(*str1 == (char) c )
{
rtn = str1;
}
str1++;
}
if( *str1 == (char) c)
{
rtn = str1;
}
return(rtn);
}
char *
index(str1,c)
char * str1;
char c;
{
return( strchr(str1,c) );
}
char *
rindex(str1,c)
char * str1;
char c;
{
return( strrchr(str1,c) );
}
char *
strpbrk(str1,str2)
register char * str1;
register char * str2;
{
register char * tmp;
malloc_check_str("strpbrk", str1);
malloc_check_str("strpbrk", str2);
while(*str1)
{
for( tmp=str2; *tmp && *tmp != *str1; tmp++)
{
}
if( *tmp )
{
break;
}
str1++;
}
if( ! *str1 )
{
str1 = (char *) 0;
}
return(str1);
}
int
strspn(str1,str2)
register char * str1;
register char * str2;
{
register char * tmp;
char * orig = str1;
malloc_check_str("strspn", str1);
malloc_check_str("strspn", str2);
while(*str1)
{
for( tmp=str2; *tmp && *tmp != *str1; tmp++)
{
}
if(! *tmp )
{
break;
}
str1++;
}
return( (int) (str1 - orig) );
}
int
strcspn(str1,str2)
register char * str1;
register char * str2;
{
register char * tmp;
char * orig = str1;
malloc_check_str("strcspn", str1);
malloc_check_str("strcspn", str2);
while(*str1)
{
for( tmp=str2; *tmp && *tmp != *str1; tmp++)
{
}
if( *tmp )
{
break;
}
str1++;
}
return( (int) (str1 - orig) );
}
/*
* strtok() source taken from that posted to comp.lang.c by Chris Torek
* in Jan 1990.
*/
/*
* Copyright (c) 1989 The Regents of the University of California.
* All rights reserved.
*
* Redistribution and use in source and binary forms are permitted
* provided that the above copyright notice and this paragraph are
* duplicated in all such forms and that any documentation,
* advertising materials, and other materials related to such
* distribution and use acknowledge that the software was developed
* by the University of California, Berkeley. The name of the
* University may not be used to endorse or promote products derived
* from this software without specific prior written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
/*
* Get next token from string s (NULL on 2nd, 3rd, etc. calls),
* where tokens are nonempty strings separated by runs of
* chars from delim. Writes NULs into s to end tokens. delim need not
* remain constant from call to call.
*
* Modified by cpc: changed variable names to conform with naming
* conventions used in rest of code. Added malloc pointer
* check calls.
*/
char *
strtok(str1, str2)
char * str1;
char * str2;
{
static char * last;
char * strtoken();
if( str1 )
{
malloc_check_str("strtok", str1);
last = str1;
}
malloc_check_str("strtok", str2);
return (strtoken(&last, str2, 1));
}
/*
* Get next token from string *stringp, where tokens are (possibly empty)
* strings separated by characters from delim. Tokens are separated
* by exactly one delimiter iff the skip parameter is false; otherwise
* they are separated by runs of characters from delim, because we
* skip over any initial `delim' characters.
*
* Writes NULs into the string at *stringp to end tokens.
* delim will usually, but need not, remain constant from call to call.
* On return, *stringp points past the last NUL written (if there might
* be further tokens), or is NULL (if there are definitely no more tokens).
*
* If *stringp is NULL, strtoken returns NULL.
*/
char *
strtoken(stringp, delim, skip)
register char **stringp;
register char *delim;
int skip;
{
register char *s;
register char *spanp;
register int c, sc;
char *tok;
if ((s = *stringp) == NULL)
return (NULL);
if (skip) {
/*
* Skip (span) leading delimiters (s += strspn(s, delim)).
*/
cont:
c = *s;
for (spanp = delim; (sc = *spanp++) != 0;) {
if (c == sc) {
s++;
goto cont;
}
}
if (c == 0) { /* no token found */
*stringp = NULL;
return (NULL);
}
}
/*
* Scan token (scan for delimiters: s += strcspn(s, delim), sort of).
* Note that delim must have one NUL; we stop if we see that, too.
*/
for (tok = s;;) {
c = *s++;
spanp = delim;
do {
if ((sc = *spanp++) == c) {
if (c == 0)
s = NULL;
else
s[-1] = 0;
*stringp = s;
return (tok);
}
} while (sc != 0);
}
/* NOTREACHED */
}
/*
* $Log: string.c,v $
* Revision 1.1 1992/01/24 03:29:13 dvadura
* dmake Version 3.8, Initial revision
*
* Revision 1.7 90/08/29 22:24:19 cpcahil
* added new function to check on strings up to a specified length
* and used it within several strn* functions.
*
* Revision 1.6 90/07/16 20:06:56 cpcahil
* fixed several minor bugs found with Henry Spencer's string/mem function
* tester program.
*
* Revision 1.5 90/06/10 14:59:49 cpcahil
* Fixed a couple of bugs in strncpy & strdup
*
* Revision 1.4 90/05/11 00:13:10 cpcahil
* added copyright statment
*
* Revision 1.3 90/02/24 21:50:32 cpcahil
* lots of lint fixes
*
* Revision 1.2 90/02/24 17:29:40 cpcahil
* changed $Header to $Id so full path wouldnt be included as part of rcs
* id string
*
* Revision 1.1 90/02/22 23:17:44 cpcahil
* Initial revision
*
*/

646
dmake/dbug/malloc/testmem.c Normal file
View File

@ -0,0 +1,646 @@
/*
* This stuff is all stolen (with permission, since it was in the public
* domain) from Henry Spencer's string and memory library. Thanks Henry.
*/
/*
* Test program for string(3) routines.
*
* Note that at least one Bell Labs implementation of the string
* routines flunks a couple of these tests -- the ones which test
* behavior on "negative" characters.
*/
#include <stdio.h>
#include <string.h>
char * index();
char * rindex();
#define STREQ(a, b) (strcmp((a), (b)) == 0)
char *it = "<UNSET>"; /* Routine name for message routines. */
int waserror = 0; /* For exit status. */
char uctest[] = "\004\203"; /* For testing signedness of chars. */
int charsigned; /* Result. */
/*
- check - complain if condition is not true
*/
void
check(thing, number)
int thing;
int number; /* Test number for error message. */
{
if (!thing) {
printf("%s flunked test %d\n", it, number);
waserror = 1;
}
}
/*
- equal - complain if first two args don't strcmp as equal
*/
void
equal(a, b, number)
char *a;
char *b;
int number; /* Test number for error message. */
{
check(a != NULL && b != NULL && STREQ(a, b), number);
}
char one[50];
char two[50];
#ifdef UNIXERR
#define ERR 1
#endif
#ifdef BERKERR
#define ERR 1
#endif
#ifdef ERR
int f;
extern char *sys_errlist[];
extern int sys_nerr;
extern int errno;
#endif
/* ARGSUSED */
main(argc, argv)
int argc;
char *argv[];
{
/*
* First, establish whether chars are signed.
*/
if (uctest[0] < uctest[1])
charsigned = 0;
else
charsigned = 1;
/*
* Then, do the rest of the work. Split into two functions because
* some compilers get unhappy about a single immense function.
*/
first();
second();
exit((waserror) ? 1 : 0);
}
first()
{
/*
* Test strcmp first because we use it to test other things.
*/
it = "strcmp";
check(strcmp("", "") == 0, 1); /* Trivial case. */
check(strcmp("a", "a") == 0, 2); /* Identity. */
check(strcmp("abc", "abc") == 0, 3); /* Multicharacter. */
check(strcmp("abc", "abcd") < 0, 4); /* Length mismatches. */
check(strcmp("abcd", "abc") > 0, 5);
check(strcmp("abcd", "abce") < 0, 6); /* Honest miscompares. */
check(strcmp("abce", "abcd") > 0, 7);
check(strcmp("a\203", "a") > 0, 8); /* Tricky if char signed. */
if (charsigned) /* Sign-bit comparison. */
check(strcmp("a\203", "a\003") < 0, 9);
else
check(strcmp("a\203", "a\003") > 0, 9);
check(strcmp("a", "a\203") < 0, 10); /* Tricky if char signed. */
/*
* Test strcpy next because we need it to set up other tests.
*/
it = "strcpy";
check(strcpy(one, "abcd") == one, 1); /* Returned value. */
equal(one, "abcd", 2); /* Basic test. */
(void) strcpy(one, "x");
equal(one, "x", 3); /* Writeover. */
equal(one+2, "cd", 4); /* Wrote too much? */
(void) strcpy(two, "hi there");
(void) strcpy(one, two);
equal(one, "hi there", 5); /* Basic test encore. */
equal(two, "hi there", 6); /* Stomped on source? */
(void) strcpy(one, "");
equal(one, "", 7); /* Boundary condition. */
/*
* strcat
*/
it = "strcat";
(void) strcpy(one, "ijk");
check(strcat(one, "lmn") == one, 1); /* Returned value. */
equal(one, "ijklmn", 2); /* Basic test. */
(void) strcpy(one, "x");
(void) strcat(one, "yz");
equal(one, "xyz", 3); /* Writeover. */
equal(one+4, "mn", 4); /* Wrote too much? */
(void) strcpy(one, "gh");
(void) strcpy(two, "ef");
(void) strcat(one, two);
equal(one, "ghef", 5); /* Basic test encore. */
equal(two, "ef", 6); /* Stomped on source? */
(void) strcpy(one, "");
(void) strcat(one, "");
equal(one, "", 7); /* Boundary conditions. */
(void) strcpy(one, "ab");
(void) strcat(one, "");
equal(one, "ab", 8);
(void) strcpy(one, "");
(void) strcat(one, "cd");
equal(one, "cd", 9);
/*
* strncat - first test it as strcat, with big counts, then
* test the count mechanism.
*/
it = "strncat";
(void) strcpy(one, "ijk");
check(strncat(one, "lmn", 99) == one, 1); /* Returned value. */
equal(one, "ijklmn", 2); /* Basic test. */
(void) strcpy(one, "x");
(void) strncat(one, "yz", 99);
equal(one, "xyz", 3); /* Writeover. */
equal(one+4, "mn", 4); /* Wrote too much? */
(void) strcpy(one, "gh");
(void) strcpy(two, "ef");
(void) strncat(one, two, 99);
equal(one, "ghef", 5); /* Basic test encore. */
equal(two, "ef", 6); /* Stomped on source? */
(void) strcpy(one, "");
(void) strncat(one, "", 99);
equal(one, "", 7); /* Boundary conditions. */
(void) strcpy(one, "ab");
(void) strncat(one, "", 99);
equal(one, "ab", 8);
(void) strcpy(one, "");
(void) strncat(one, "cd", 99);
equal(one, "cd", 9);
(void) strcpy(one, "ab");
(void) strncat(one, "cdef", 2);
equal(one, "abcd", 10); /* Count-limited. */
(void) strncat(one, "gh", 0);
equal(one, "abcd", 11); /* Zero count. */
(void) strncat(one, "gh", 2);
equal(one, "abcdgh", 12); /* Count and length equal. */
/*
* strncmp - first test as strcmp with big counts, then test
* count code.
*/
it = "strncmp";
check(strncmp("", "", 99) == 0, 1); /* Trivial case. */
check(strncmp("a", "a", 99) == 0, 2); /* Identity. */
check(strncmp("abc", "abc", 99) == 0, 3); /* Multicharacter. */
check(strncmp("abc", "abcd", 99) < 0, 4); /* Length unequal. */
check(strncmp("abcd", "abc", 99) > 0, 5);
check(strncmp("abcd", "abce", 99) < 0, 6); /* Honestly unequal. */
check(strncmp("abce", "abcd", 99) > 0, 7);
check(strncmp("a\203", "a", 2) > 0, 8); /* Tricky if '\203' < 0 */
if (charsigned) /* Sign-bit comparison. */
check(strncmp("a\203", "a\003", 2) < 0, 9);
else
check(strncmp("a\203", "a\003", 2) > 0, 9);
check(strncmp("abce", "abcd", 3) == 0, 10); /* Count limited. */
check(strncmp("abce", "abc", 3) == 0, 11); /* Count == length. */
check(strncmp("abcd", "abce", 4) < 0, 12); /* Nudging limit. */
check(strncmp("abc", "def", 0) == 0, 13); /* Zero count. */
/*
* strncpy - testing is a bit different because of odd semantics
*/
it = "strncpy";
check(strncpy(one, "abc", 4) == one, 1); /* Returned value. */
equal(one, "abc", 2); /* Did the copy go right? */
(void) strcpy(one, "abcdefgh");
(void) strncpy(one, "xyz", 2);
equal(one, "xycdefgh", 3); /* Copy cut by count. */
(void) strcpy(one, "abcdefgh");
(void) strncpy(one, "xyz", 3); /* Copy cut just before NUL. */
equal(one, "xyzdefgh", 4);
(void) strcpy(one, "abcdefgh");
(void) strncpy(one, "xyz", 4); /* Copy just includes NUL. */
equal(one, "xyz", 5);
equal(one+4, "efgh", 6); /* Wrote too much? */
(void) strcpy(one, "abcdefgh");
(void) strncpy(one, "xyz", 5); /* Copy includes padding. */
equal(one, "xyz", 7);
equal(one+4, "", 8);
equal(one+5, "fgh", 9);
(void) strcpy(one, "abc");
(void) strncpy(one, "xyz", 0); /* Zero-length copy. */
equal(one, "abc", 10);
(void) strncpy(one, "", 2); /* Zero-length source. */
equal(one, "", 11);
equal(one+1, "", 12);
equal(one+2, "c", 13);
(void) strcpy(one, "hi there");
(void) strncpy(two, one, 9);
equal(two, "hi there", 14); /* Just paranoia. */
equal(one, "hi there", 15); /* Stomped on source? */
/*
* strlen
*/
it = "strlen";
check(strlen("") == 0, 1); /* Empty. */
check(strlen("a") == 1, 2); /* Single char. */
check(strlen("abcd") == 4, 3); /* Multiple chars. */
/*
* strchr
*/
it = "strchr";
check(strchr("abcd", 'z') == NULL, 1); /* Not found. */
(void) strcpy(one, "abcd");
check(strchr(one, 'c') == one+2, 2); /* Basic test. */
check(strchr(one, 'd') == one+3, 3); /* End of string. */
check(strchr(one, 'a') == one, 4); /* Beginning. */
check(strchr(one, '\0') == one+4, 5); /* Finding NUL. */
(void) strcpy(one, "ababa");
check(strchr(one, 'b') == one+1, 6); /* Finding first. */
(void) strcpy(one, "");
check(strchr(one, 'b') == NULL, 7); /* Empty string. */
check(strchr(one, '\0') == one, 8); /* NUL in empty string. */
/*
* index - just like strchr
*/
it = "index";
check(index("abcd", 'z') == NULL, 1); /* Not found. */
(void) strcpy(one, "abcd");
check(index(one, 'c') == one+2, 2); /* Basic test. */
check(index(one, 'd') == one+3, 3); /* End of string. */
check(index(one, 'a') == one, 4); /* Beginning. */
check(index(one, '\0') == one+4, 5); /* Finding NUL. */
(void) strcpy(one, "ababa");
check(index(one, 'b') == one+1, 6); /* Finding first. */
(void) strcpy(one, "");
check(index(one, 'b') == NULL, 7); /* Empty string. */
check(index(one, '\0') == one, 8); /* NUL in empty string. */
/*
* strrchr
*/
it = "strrchr";
check(strrchr("abcd", 'z') == NULL, 1); /* Not found. */
(void) strcpy(one, "abcd");
check(strrchr(one, 'c') == one+2, 2); /* Basic test. */
check(strrchr(one, 'd') == one+3, 3); /* End of string. */
check(strrchr(one, 'a') == one, 4); /* Beginning. */
check(strrchr(one, '\0') == one+4, 5); /* Finding NUL. */
(void) strcpy(one, "ababa");
check(strrchr(one, 'b') == one+3, 6); /* Finding last. */
(void) strcpy(one, "");
check(strrchr(one, 'b') == NULL, 7); /* Empty string. */
check(strrchr(one, '\0') == one, 8); /* NUL in empty string. */
/*
* rindex - just like strrchr
*/
it = "rindex";
check(rindex("abcd", 'z') == NULL, 1); /* Not found. */
(void) strcpy(one, "abcd");
check(rindex(one, 'c') == one+2, 2); /* Basic test. */
check(rindex(one, 'd') == one+3, 3); /* End of string. */
check(rindex(one, 'a') == one, 4); /* Beginning. */
check(rindex(one, '\0') == one+4, 5); /* Finding NUL. */
(void) strcpy(one, "ababa");
check(rindex(one, 'b') == one+3, 6); /* Finding last. */
(void) strcpy(one, "");
check(rindex(one, 'b') == NULL, 7); /* Empty string. */
check(rindex(one, '\0') == one, 8); /* NUL in empty string. */
}
second()
{
/*
* strpbrk - somewhat like strchr
*/
it = "strpbrk";
check(strpbrk("abcd", "z") == NULL, 1); /* Not found. */
(void) strcpy(one, "abcd");
check(strpbrk(one, "c") == one+2, 2); /* Basic test. */
check(strpbrk(one, "d") == one+3, 3); /* End of string. */
check(strpbrk(one, "a") == one, 4); /* Beginning. */
check(strpbrk(one, "") == NULL, 5); /* Empty search list. */
check(strpbrk(one, "cb") == one+1, 6); /* Multiple search. */
(void) strcpy(one, "abcabdea");
check(strpbrk(one, "b") == one+1, 7); /* Finding first. */
check(strpbrk(one, "cb") == one+1, 8); /* With multiple search. */
check(strpbrk(one, "db") == one+1, 9); /* Another variant. */
(void) strcpy(one, "");
check(strpbrk(one, "bc") == NULL, 10); /* Empty string. */
check(strpbrk(one, "") == NULL, 11); /* Both strings empty. */
#if 0
/*
* strstr - somewhat like strchr
*/
it = "strstr";
check(strstr("abcd", "z") == NULL, 1); /* Not found. */
check(strstr("abcd", "abx") == NULL, 2); /* Dead end. */
(void) strcpy(one, "abcd");
check(strstr(one, "c") == one+2, 3); /* Basic test. */
check(strstr(one, "bc") == one+1, 4); /* Multichar. */
check(strstr(one, "d") == one+3, 5); /* End of string. */
check(strstr(one, "cd") == one+2, 6); /* Tail of string. */
check(strstr(one, "abc") == one, 7); /* Beginning. */
check(strstr(one, "abcd") == one, 8); /* Exact match. */
check(strstr(one, "abcde") == NULL, 9); /* Too long. */
check(strstr(one, "de") == NULL, 10); /* Past end. */
check(strstr(one, "") == one+4, 11); /* Finding empty. */
(void) strcpy(one, "ababa");
check(strstr(one, "ba") == one+1, 12); /* Finding first. */
(void) strcpy(one, "");
check(strstr(one, "b") == NULL, 13); /* Empty string. */
check(strstr(one, "") == one, 14); /* Empty in empty string. */
(void) strcpy(one, "bcbca");
check(strstr(one, "bca") == one+2, 15); /* False start. */
(void) strcpy(one, "bbbcabbca");
check(strstr(one, "bbca") == one+1, 16); /* With overlap. */
#endif
/*
* strspn
*/
it = "strspn";
check(strspn("abcba", "abc") == 5, 1); /* Whole string. */
check(strspn("abcba", "ab") == 2, 2); /* Partial. */
check(strspn("abc", "qx") == 0, 3); /* None. */
check(strspn("", "ab") == 0, 4); /* Null string. */
check(strspn("abc", "") == 0, 5); /* Null search list. */
/*
* strcspn
*/
it = "strcspn";
check(strcspn("abcba", "qx") == 5, 1); /* Whole string. */
check(strcspn("abcba", "cx") == 2, 2); /* Partial. */
check(strcspn("abc", "abc") == 0, 3); /* None. */
check(strcspn("", "ab") == 0, 4); /* Null string. */
check(strcspn("abc", "") == 3, 5); /* Null search list. */
/*
* strtok - the hard one
*/
it = "strtok";
(void) strcpy(one, "first, second, third");
equal(strtok(one, ", "), "first", 1); /* Basic test. */
equal(one, "first", 2);
equal(strtok((char *)NULL, ", "), "second", 3);
equal(strtok((char *)NULL, ", "), "third", 4);
check(strtok((char *)NULL, ", ") == NULL, 5);
(void) strcpy(one, ", first, ");
equal(strtok(one, ", "), "first", 6); /* Extra delims, 1 tok. */
check(strtok((char *)NULL, ", ") == NULL, 7);
(void) strcpy(one, "1a, 1b; 2a, 2b");
equal(strtok(one, ", "), "1a", 8); /* Changing delim lists. */
equal(strtok((char *)NULL, "; "), "1b", 9);
equal(strtok((char *)NULL, ", "), "2a", 10);
(void) strcpy(two, "x-y");
equal(strtok(two, "-"), "x", 11); /* New string before done. */
equal(strtok((char *)NULL, "-"), "y", 12);
check(strtok((char *)NULL, "-") == NULL, 13);
(void) strcpy(one, "a,b, c,, ,d");
equal(strtok(one, ", "), "a", 14); /* Different separators. */
equal(strtok((char *)NULL, ", "), "b", 15);
equal(strtok((char *)NULL, " ,"), "c", 16); /* Permute list too. */
equal(strtok((char *)NULL, " ,"), "d", 17);
check(strtok((char *)NULL, ", ") == NULL, 18);
check(strtok((char *)NULL, ", ") == NULL, 19); /* Persistence. */
(void) strcpy(one, ", ");
check(strtok(one, ", ") == NULL, 20); /* No tokens. */
(void) strcpy(one, "");
check(strtok(one, ", ") == NULL, 21); /* Empty string. */
(void) strcpy(one, "abc");
equal(strtok(one, ", "), "abc", 22); /* No delimiters. */
check(strtok((char *)NULL, ", ") == NULL, 23);
(void) strcpy(one, "abc");
equal(strtok(one, ""), "abc", 24); /* Empty delimiter list. */
check(strtok((char *)NULL, "") == NULL, 25);
(void) strcpy(one, "abcdefgh");
(void) strcpy(one, "a,b,c");
equal(strtok(one, ","), "a", 26); /* Basics again... */
equal(strtok((char *)NULL, ","), "b", 27);
equal(strtok((char *)NULL, ","), "c", 28);
check(strtok((char *)NULL, ",") == NULL, 29);
equal(one+6, "gh", 30); /* Stomped past end? */
equal(one, "a", 31); /* Stomped old tokens? */
equal(one+2, "b", 32);
equal(one+4, "c", 33);
/*
* memcmp
*/
it = "memcmp";
check(memcmp("a", "a", 1) == 0, 1); /* Identity. */
check(memcmp("abc", "abc", 3) == 0, 2); /* Multicharacter. */
check(memcmp("abcd", "abce", 4) < 0, 3); /* Honestly unequal. */
check(memcmp("abce", "abcd", 4) > 0, 4);
check(memcmp("alph", "beta", 4) < 0, 5);
if (charsigned) /* Sign-bit comparison. */
check(memcmp("a\203", "a\003", 2) < 0, 6);
else
check(memcmp("a\203", "a\003", 2) > 0, 6);
check(memcmp("abce", "abcd", 3) == 0, 7); /* Count limited. */
check(memcmp("abc", "def", 0) == 0, 8); /* Zero count. */
/*
* memchr
*/
it = "memchr";
check(memchr("abcd", 'z', 4) == NULL, 1); /* Not found. */
(void) strcpy(one, "abcd");
check(memchr(one, 'c', 4) == one+2, 2); /* Basic test. */
check(memchr(one, 'd', 4) == one+3, 3); /* End of string. */
check(memchr(one, 'a', 4) == one, 4); /* Beginning. */
check(memchr(one, '\0', 5) == one+4, 5); /* Finding NUL. */
(void) strcpy(one, "ababa");
check(memchr(one, 'b', 5) == one+1, 6); /* Finding first. */
check(memchr(one, 'b', 0) == NULL, 7); /* Zero count. */
check(memchr(one, 'a', 1) == one, 8); /* Singleton case. */
(void) strcpy(one, "a\203b");
check(memchr(one, 0203, 3) == one+1, 9); /* Unsignedness. */
/*
* memcpy
*
* Note that X3J11 says memcpy must work regardless of overlap.
* The SVID says it might fail.
*/
it = "memcpy";
check(memcpy(one, "abc", 4) == one, 1); /* Returned value. */
equal(one, "abc", 2); /* Did the copy go right? */
(void) strcpy(one, "abcdefgh");
(void) memcpy(one+1, "xyz", 2);
equal(one, "axydefgh", 3); /* Basic test. */
(void) strcpy(one, "abc");
(void) memcpy(one, "xyz", 0);
equal(one, "abc", 4); /* Zero-length copy. */
(void) strcpy(one, "hi there");
(void) strcpy(two, "foo");
(void) memcpy(two, one, 9);
equal(two, "hi there", 5); /* Just paranoia. */
equal(one, "hi there", 6); /* Stomped on source? */
(void) strcpy(one, "abcdefgh");
(void) memcpy(one+1, one, 9);
equal(one, "aabcdefgh", 7); /* Overlap, right-to-left. */
(void) strcpy(one, "abcdefgh");
(void) memcpy(one+1, one+2, 7);
equal(one, "acdefgh", 8); /* Overlap, left-to-right. */
(void) strcpy(one, "abcdefgh");
(void) memcpy(one, one, 9);
equal(one, "abcdefgh", 9); /* 100% overlap. */
/*
* memccpy - first test like memcpy, then the search part
*
* The SVID, the only place where memccpy is mentioned, says
* overlap might fail, so we don't try it. Besides, it's hard
* to see the rationale for a non-left-to-right memccpy.
*/
it = "memccpy";
check(memccpy(one, "abc", 'q', 4) == NULL, 1); /* Returned value. */
equal(one, "abc", 2); /* Did the copy go right? */
(void) strcpy(one, "abcdefgh");
(void) memccpy(one+1, "xyz", 'q', 2);
equal(one, "axydefgh", 3); /* Basic test. */
(void) strcpy(one, "abc");
(void) memccpy(one, "xyz", 'q', 0);
equal(one, "abc", 4); /* Zero-length copy. */
(void) strcpy(one, "hi there");
(void) strcpy(two, "foo");
(void) memccpy(two, one, 'q', 9);
equal(two, "hi there", 5); /* Just paranoia. */
equal(one, "hi there", 6); /* Stomped on source? */
(void) strcpy(one, "abcdefgh");
(void) strcpy(two, "horsefeathers");
check(memccpy(two, one, 'f', 9) == two+6, 7); /* Returned value. */
equal(one, "abcdefgh", 8); /* Source intact? */
equal(two, "abcdefeathers", 9); /* Copy correct? */
(void) strcpy(one, "abcd");
(void) strcpy(two, "bumblebee");
check(memccpy(two, one, 'a', 4) == two+1, 10); /* First char. */
equal(two, "aumblebee", 11);
check(memccpy(two, one, 'd', 4) == two+4, 12); /* Last char. */
equal(two, "abcdlebee", 13);
(void) strcpy(one, "xyz");
check(memccpy(two, one, 'x', 1) == two+1, 14); /* Singleton. */
equal(two, "xbcdlebee", 15);
/*
* memset
*/
it = "memset";
(void) strcpy(one, "abcdefgh");
check(memset(one+1, 'x', 3) == one+1, 1); /* Return value. */
equal(one, "axxxefgh", 2); /* Basic test. */
(void) memset(one+2, 'y', 0);
equal(one, "axxxefgh", 3); /* Zero-length set. */
(void) memset(one+5, 0, 1);
equal(one, "axxxe", 4); /* Zero fill. */
equal(one+6, "gh", 5); /* And the leftover. */
(void) memset(one+2, 010045, 1);
equal(one, "ax\045xe", 6); /* Unsigned char convert. */
/*
* bcopy - much like memcpy
*
* Berklix manual is silent about overlap, so don't test it.
*/
it = "bcopy";
(void) bcopy("abc", one, 4);
equal(one, "abc", 1); /* Simple copy. */
(void) strcpy(one, "abcdefgh");
(void) bcopy("xyz", one+1, 2);
equal(one, "axydefgh", 2); /* Basic test. */
(void) strcpy(one, "abc");
(void) bcopy("xyz", one, 0);
equal(one, "abc", 3); /* Zero-length copy. */
(void) strcpy(one, "hi there");
(void) strcpy(two, "foo");
(void) bcopy(one, two, 9);
equal(two, "hi there", 4); /* Just paranoia. */
equal(one, "hi there", 5); /* Stomped on source? */
/*
* bzero
*/
it = "bzero";
(void) strcpy(one, "abcdef");
bzero(one+2, 2);
equal(one, "ab", 1); /* Basic test. */
equal(one+3, "", 2);
equal(one+4, "ef", 3);
(void) strcpy(one, "abcdef");
bzero(one+2, 0);
equal(one, "abcdef", 4); /* Zero-length copy. */
/*
* bcmp - somewhat like memcmp
*/
it = "bcmp";
check(bcmp("a", "a", 1) == 0, 1); /* Identity. */
check(bcmp("abc", "abc", 3) == 0, 2); /* Multicharacter. */
check(bcmp("abcd", "abce", 4) != 0, 3); /* Honestly unequal. */
check(bcmp("abce", "abcd", 4) != 0, 4);
check(bcmp("alph", "beta", 4) != 0, 5);
check(bcmp("abce", "abcd", 3) == 0, 6); /* Count limited. */
check(bcmp("abc", "def", 0) == 0, 8); /* Zero count. */
#ifdef ERR
/*
* strerror - VERY system-dependent
*/
it = "strerror";
f = open("/", 1); /* Should always fail. */
check(f < 0 && errno > 0 && errno < sys_nerr, 1);
equal(strerror(errno), sys_errlist[errno], 2);
#ifdef UNIXERR
equal(strerror(errno), "Is a directory", 3);
#endif
#ifdef BERKERR
equal(strerror(errno), "Permission denied", 3);
#endif
#endif
}

176
dmake/dbug/malloc/testmlc.c Normal file
View File

@ -0,0 +1,176 @@
/* NOT copyright by SoftQuad Inc. -- msb, 1988 */
#ifndef lint
static char *SQ_SccsId = "@(#)mtest3.c 1.2 88/08/25";
#endif
#include <stdio.h>
/*
** looptest.c -- intensive allocator tester
**
** Usage: looptest
**
** History:
** 4-Feb-1987 rtech!daveb
*/
# ifdef SYS5
# define random rand
# else
# include <sys/vadvise.h>
# endif
# include <stdio.h>
# include <signal.h>
# include <setjmp.h>
# define MAXITER 1000000 /* main loop iterations */
# define MAXOBJS 1000 /* objects in pool */
# define BIGOBJ 90000 /* max size of a big object */
# define TINYOBJ 80 /* max size of a small object */
# define BIGMOD 100 /* 1 in BIGMOD is a BIGOBJ */
# define STATMOD 10000 /* interation interval for status */
main( argc, argv )
int argc;
char **argv;
{
register int **objs; /* array of objects */
register int *sizes; /* array of object sizes */
register int n; /* iteration counter */
register int i; /* object index */
register int size; /* object size */
register int r; /* random number */
int objmax; /* max size this iteration */
int cnt; /* number of allocated objects */
int nm = 0; /* number of mallocs */
int nre = 0; /* number of reallocs */
int nal; /* number of allocated objects */
int nfre; /* number of free list objects */
long alm; /* memory in allocated objects */
long frem; /* memory in free list */
long startsize; /* size at loop start */
long endsize; /* size at loop exit */
long maxiter = 0; /* real max # iterations */
extern char end; /* memory before heap */
char *calloc();
char *malloc();
char *sbrk();
long atol();
# ifndef SYS5
/* your milage may vary... */
vadvise( VA_ANOM );
# endif
if (argc > 1)
maxiter = atol (argv[1]);
if (maxiter <= 0)
maxiter = MAXITER;
printf("MAXITER %d MAXOBJS %d ", maxiter, MAXOBJS );
printf("BIGOBJ %d, TINYOBJ %d, nbig/ntiny 1/%d\n",
BIGOBJ, TINYOBJ, BIGMOD );
fflush( stdout );
if( NULL == (objs = (int **)calloc( MAXOBJS, sizeof( *objs ) ) ) )
{
fprintf(stderr, "Can't allocate memory for objs array\n");
exit(1);
}
if( NULL == ( sizes = (int *)calloc( MAXOBJS, sizeof( *sizes ) ) ) )
{
fprintf(stderr, "Can't allocate memory for sizes array\n");
exit(1);
}
/* as per recent discussion on net.lang.c, calloc does not
** necessarily fill in NULL pointers...
*/
for( i = 0; i < MAXOBJS; i++ )
objs[ i ] = NULL;
startsize = sbrk(0) - &end;
printf( "Memory use at start: %d bytes\n", startsize );
fflush(stdout);
printf("Starting the test...\n");
fflush(stdout);
for( n = 0; n < maxiter ; n++ )
{
if( !(n % STATMOD) )
{
printf("%d iterations\n", n);
fflush(stdout);
}
/* determine object of interst and it's size */
r = random();
objmax = ( r % BIGMOD ) ? TINYOBJ : BIGOBJ;
size = r % objmax;
i = r % (MAXOBJS - 1);
/* either replace the object of get a new one */
if( objs[ i ] == NULL )
{
objs[ i ] = (int *)malloc( size );
nm++;
}
else
{
/* don't keep bigger objects around */
if( size > sizes[ i ] )
{
objs[ i ] = (int *)realloc( objs[ i ], size );
nre++;
}
else
{
free( objs[ i ] );
objs[ i ] = (int *)malloc( size );
nm++;
}
}
sizes[ i ] = size;
if( objs[ i ] == NULL )
{
printf("\nCouldn't allocate %d byte object!\n",
size );
break;
}
} /* for() */
printf( "\n" );
cnt = 0;
for( i = 0; i < MAXOBJS; i++ )
if( objs[ i ] )
cnt++;
printf( "Did %d iterations, %d objects, %d mallocs, %d reallocs\n",
n, cnt, nm, nre );
printf( "Memory use at end: %d bytes\n", sbrk(0) - &end );
fflush( stdout );
/* free all the objects */
for( i = 0; i < MAXOBJS; i++ )
if( objs[ i ] != NULL )
free( objs[ i ] );
endsize = sbrk(0) - &end;
printf( "Memory use after free: %d bytes\n", endsize );
fflush( stdout );
if( startsize != endsize )
printf("startsize %d != endsize %d\n", startsize, endsize );
free( objs );
free( sizes );
malloc_dump(2);
exit( 0 );
}

View File

@ -0,0 +1,151 @@
/*
* (c) Copyright 1990 Conor P. Cahill (uunet!virtech!cpcahil).
* You may copy, distribute, and use this software as long as this
* copyright statement is not removed.
*/
#include "tostring.h"
/*
* Function: tostring()
*
* Purpose: to convert an integer to an ascii display string
*
* Arguments: buf - place to put the
* val - integer to convert
* len - length of output field (0 if just enough to hold data)
* base - base for number conversion (only works for base <= 16)
* fill - fill char when len > # digits
*
* Returns: length of string
*
* Narrative: IF fill character is non-blank
* Determine base
* If base is HEX
* add "0x" to begining of string
* IF base is OCTAL
* add "0" to begining of string
*
* While value is greater than zero
* use val % base as index into xlation str to get cur char
* divide val by base
*
* Determine fill-in length
*
* Fill in fill chars
*
* Copy in number
*
*
* Mod History:
* 90/01/24 cpcahil Initial revision.
*/
#ifndef lint
static
char rcs_hdr[] = "$Id: tostring.c,v 1.1 1992/01/24 03:29:16 dvadura Exp $";
#endif
#define T_LEN 10
int
tostring(buf,val,len,base,fill)
int base;
char * buf;
char fill;
int len;
int val;
{
char * bufstart = buf;
int i = T_LEN;
char * xbuf = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
char tbuf[T_LEN];
/*
* if we are filling with non-blanks, make sure the
* proper start string is added
*/
if( fill != ' ' )
{
switch(base)
{
case B_HEX:
*(buf++) = '0';
*(buf++) = 'x';
if( len )
{
len -= 2;
}
break;
case B_OCTAL:
*(buf++) = fill;
if( len )
{
len--;
}
break;
default:
break;
}
}
while( val > 0 )
{
tbuf[--i] = xbuf[val % base];
val = val / base;
}
if( len )
{
len -= (T_LEN - i);
if( len > 0 )
{
while(len-- > 0)
{
*(buf++) = fill;
}
}
else
{
/*
* string is too long so we must truncate
* off some characters. We do this the easiest
* way by just incrementing i. This means the
* most significant digits are lost.
*/
while( len++ < 0 )
{
i++;
}
}
}
while( i < T_LEN )
{
*(buf++) = tbuf[i++];
}
return( (int) (buf - bufstart) );
} /* tostring(... */
/*
* $Log: tostring.c,v $
* Revision 1.1 1992/01/24 03:29:16 dvadura
* dmake Version 3.8, Initial revision
*
* Revision 1.4 90/05/11 00:13:11 cpcahil
* added copyright statment
*
* Revision 1.3 90/02/24 21:50:33 cpcahil
* lots of lint fixes
*
* Revision 1.2 90/02/24 17:29:42 cpcahil
* changed $Header to $Id so full path wouldnt be included as part of rcs
* id string
*
* Revision 1.1 90/02/22 23:17:44 cpcahil
* Initial revision
*
*/

View File

@ -0,0 +1,25 @@
/*
* (c) Copyright 1990 Conor P. Cahill (uunet!virtech!cpcahil).
* You may copy, distribute, and use this software as long as this
* copyright statement is not removed.
*/
/*
* $Id: tostring.h,v 1.1 1992/01/24 03:29:17 dvadura Exp $
*/
#define B_BIN 2
#define B_DEC 10
#define B_HEX 16
#define B_OCTAL 8
/*
* $Log: tostring.h,v $
* Revision 1.1 1992/01/24 03:29:17 dvadura
* dmake Version 3.8, Initial revision
*
* Revision 1.2 90/05/11 00:13:11 cpcahil
* added copyright statment
*
* Revision 1.1 90/02/23 07:09:05 cpcahil
* Initial revision
*
*/

818
dmake/dmake.c Normal file
View File

@ -0,0 +1,818 @@
/* RCS -- $Header: /u/dvadura/src/generic/dmake/src/RCS/dmake.c,v 1.3 1992/04/07 04:42:46 dvadura Exp $
-- SYNOPSIS -- The main program.
--
-- DESCRIPTION
--
-- dmake [-#dbug_string] [ options ]
-- [ macro definitions ] [ target ... ]
--
-- This file contains the main command line parser for the
-- make utility. The valid flags recognized are as follows:
--
-- -f file - use file as the makefile
-- -C file - duplicate console output to file (MSDOS only)
-- -K file - .KEEP_STATE file
-- -#dbug_string - dump out debugging info, see below
-- -v{dfimt} - verbose, print what we are doing, as we do it.
--
-- options: (can be catenated, ie -irn == -i -r -n)
--
-- -A - enable AUGMAKE special target mapping
-- -B - enable non-use of TABS to start recipe lines
-- -c - use non-standard comment scanning
-- -i - ignore errors
-- -n - trace and print, do not execute commands
-- -t - touch, update dates without executing commands
-- -T - do not apply transitive closure on inference rules
-- -r - don't use internal rules
-- -s - do your work silently
-- -S - force Sequential make, overrides -P
-- -q - check if target is up to date. Does not
-- do anything. Returns 0 if up to date, -1
-- otherwise.
-- -p - print out a version of the makefile
-- -P# - set value of MAXPROCESS
-- -E - define environment strings as macros
-- -e - as -E but done after parsing makefile
-- -u - force unconditional update of target
-- -k - make all independent targets even if errors
-- -V - print out this make version number
-- -M - Microsoft make compatibility, (* disabled *)
-- -h - print out usage info
-- -x - export macro defs to environment
-- -X - ignore #! lines found in makefile
--
-- NOTE: - #ddbug_string is only availabe for versions of dmake that
-- have been compiled with -DDBUG switch on. Not the case for
-- distributed versions. Any such versions must be linked
-- together with a version of Fred Fish's debug code.
--
-- NOTE: - in order to compile the code the include file stddef.h
-- must be shipped with the bundled code.
--
-- AUTHOR
-- Dennis Vadura, dvadura@watdragon.uwaterloo.ca
-- CS DEPT, University of Waterloo, Waterloo, Ont., Canada
--
-- COPYRIGHT
-- Copyright (c) 1990 by Dennis Vadura. All rights reserved.
--
-- This program is free software; you can redistribute it and/or
-- modify it under the terms of the GNU General Public License
-- (version 1), as published by the Free Software Foundation, and
-- found in the file 'LICENSE' included with this distribution.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warrant of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program; if not, write to the Free Software
-- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
--
-- LOG
-- $Log: dmake.c,v $
* Revision 1.3 1992/04/07 04:42:46 dvadura
* Gnuiffied the source, and prettied up some of the output for -h.
*
* Revision 1.2 1992/04/01 03:31:03 dvadura
* changed use of #elif to satisfy broken compilers.
*
* Revision 1.1 1992/01/24 03:26:58 dvadura
* dmake Version 3.8, Initial revision
*
*/
/* Set this flag to one, and the global variables in vextern.h will not
* be defined as 'extern', instead they will be defined as global vars
* when this module is compiled. */
#define _DEFINE_GLOBALS_ 1
#include "extern.h"
#include "patchlvl.h"
#include "version.h"
#ifndef MSDOS
#define USAGE \
"Usage:\n%s [-P#] [-{f|K} file] [-v{dfimt}] [-ABceEhiknpqrsStTuVxX]\n"
#define USAGE2 \
"%s [macro[*][+][:]=value ...] [target ...]\n"
#else
#define USAGE \
"Usage:\n%s [-P#] [-{f|C|K} file] [-v{dfimt}] [-ABceEhiknpqrsStTuVxX]\n"
#define USAGE2 \
"%s [macro[*][+][:]=value ...] [target ...]\n"
#endif
#if __STDC__ == 1 && !defined(__GNUC__)
void Fatal(char *fmt, ...);
void Warning(char *fmt, ...);
#endif
static char *sccid = "Copyright (c) 1990,1991 by Dennis Vadura";
static char _warn = TRUE; /* warnings on by default */
static void _do_VPATH();
static void _do_ReadEnvironment();
#if !defined(__GNUC__)
static void _do_f_flag ANSI((char, char *, char **));
#else
static void _do_f_flag ANSI((int, char *, char **));
#endif
PUBLIC void
main(argc, argv)
int argc;
char **argv;
{
#ifdef MSDOS
char* std_fil_name = NIL(char);
#endif
char* fil_name = NIL(char);
char* state_name = NIL(char);
char* cmdmacs;
char* targets;
FILE* mkfil;
int ex_val;
int m_export;
DB_ENTER("main");
/* Initialize Global variables to their default values */
Prolog(argc, argv);
Create_macro_vars();
Catch_signals(Quit);
Def_macro( "MAKECMD", Pname, M_PRECIOUS|M_NOEXPORT );
Pname = basename(Pname);
DB_PROCESS(Pname);
(void) setvbuf(stdout, NULL, _IOLBF, BUFSIZ); /* stdout line buffered */
Continue = FALSE;
Comment = FALSE;
Get_env = FALSE;
Force = FALSE;
Target = FALSE;
If_expand = FALSE;
Listing = FALSE;
Readenv = FALSE;
Rules = TRUE;
Trace = FALSE;
Touch = FALSE;
Check = FALSE;
Microsoft = FALSE;
Makemkf = FALSE;
No_exec = FALSE;
m_export = FALSE;
cmdmacs = NIL(char);
targets = NIL(char);
Verbose = V_NONE;
Transitive = TRUE;
Nest_level = 0;
Line_number = 0;
Suppress_temp_file = FALSE;
while( --argc > 0 ) {
register char *p;
char *q;
if( *(p = *++argv) == '-' ) {
if( p[1] == '\0' ) Fatal("Missing option letter");
/* copy options to Buffer for $(MFLAGS), strip 'f' and 'C'*/
q = strchr(Buffer, '\0');
while (*p != '\0') {
char c = (*q++ = *p++);
if( c == 'f' || c == 'C' ) q--;
}
if( *(q-1) == '-' )
q--;
else
*q++ = ' ';
*q = '\0';
for( p = *argv+1; *p; p++) switch (*p) {
case 'f':
_do_f_flag( 'f', *++argv, &fil_name ); argc--;
break;
#if defined(MSDOS) && !defined(OS2)
case 'C':
_do_f_flag( 'C', *++argv, &std_fil_name ); argc--;
Hook_std_writes( std_fil_name );
break;
#endif
case 'K':
_do_f_flag( 'K', *++argv, &state_name ); argc--;
Def_macro(".KEEP_STATE", state_name, M_EXPANDED|M_PRECIOUS);
break;
case 'k': Continue = TRUE; break;
case 'c': Comment = TRUE; break;
case 'p': Listing = TRUE; break;
case 'r': Rules = FALSE; break;
case 'n': Trace = TRUE; break;
case 't': Touch = TRUE; break;
case 'q': Check = TRUE; break;
case 'u': Force = TRUE; break;
case 'x': m_export = TRUE; break;
case 'X': No_exec = TRUE; break;
case 'T': Transitive = FALSE; break;
case 'e': Get_env = 'e'; break;
case 'E': Get_env = 'E'; break;
case 'V': Version(); Quit(NIL(CELL)); break;
case 'A': Def_macro("AUGMAKE", "y", M_EXPANDED); break;
case 'B': Def_macro(".NOTABS", "y", M_EXPANDED); break;
case 'i': Def_macro(".IGNORE", "y", M_EXPANDED); break;
case 's': Def_macro(".SILENT", "y", M_EXPANDED); break;
case 'S': Def_macro(".SEQUENTIAL", "y", M_EXPANDED); break;
case 'v':
if( p[-1] != '-' ) Usage(TRUE);
while( p[1] ) switch( *++p ) {
case 'd': Verbose |= V_PRINT_DIR; break;
case 'f': Verbose |= V_FILE_IO; break;
case 'i': Verbose |= V_INFER; break;
case 'm': Verbose |= V_MAKE; break;
case 't': Verbose |= V_LEAVE_TMP; break;
default: Usage(TRUE); break;
}
if( !Verbose ) Verbose = V_ALL;
break;
case 'P':
if( p[1] ) {
Def_macro( "MAXPROCESS", p+1, M_MULTI|M_EXPANDED );
p += strlen(p)-1;
}
else
Fatal( "Missing number for -P flag" );
break;
#ifdef DBUG
case '#':
DB_PUSH(p+1);
p += strlen(p)-1;
break;
#endif
case 'h': Usage(FALSE); break;
case 0: break; /* lone - */
default: Usage(TRUE); break;
}
}
else if( (q = strchr(p, '=')) != NIL(char) ) {
cmdmacs = _stradd( cmdmacs, _strdup2(p), TRUE );
Parse_macro( p, (q[-1]!='+')?M_PRECIOUS:M_DEFAULT );
}
else {
register CELLPTR cp;
targets = _stradd( targets, _strdup(p), TRUE );
Add_prerequisite(Root, cp = Def_cell(p), FALSE, FALSE);
cp->ce_flag |= F_TARGET;
cp->ce_attr |= A_FRINGE;
Target = TRUE;
}
}
Def_macro( "MAKEMACROS", cmdmacs, M_PRECIOUS|M_NOEXPORT );
Def_macro( "MAKETARGETS", targets, M_PRECIOUS|M_NOEXPORT );
if( cmdmacs != NIL(char) ) FREE(cmdmacs);
if( targets != NIL(char) ) FREE(targets);
Def_macro( "MFLAGS", Buffer, M_PRECIOUS|M_NOEXPORT );
Def_macro( "%", "$@", M_PRECIOUS|M_NOEXPORT );
if( *Buffer ) Def_macro( "MAKEFLAGS", Buffer+1, M_PRECIOUS|M_NOEXPORT );
_warn = FALSE; /* disable warnings for builtin rules */
ex_val = Target; /* make sure we don't mark any */
Target = TRUE; /* of the default rules as */
Make_rules(); /* potential targets */
_warn = TRUE;
if( Rules ) {
char *fname;
if( (mkfil=Search_file("MAKESTARTUP", &fname)) != NIL(FILE) ) {
Parse(mkfil);
Def_macro( "MAKESTARTUP", fname, M_EXPANDED|M_MULTI );
mkfil = NIL(FILE);
}
else
Fatal( "Configuration file `%s' not found", fname );
}
Target = ex_val;
if( Get_env == 'E' ) _do_ReadEnvironment();
if( fil_name != NIL(char) )
mkfil = Openfile( fil_name, FALSE, TRUE );
else {
/* Search .MAKEFILES dependent list looking for a makefile.
*/
register CELLPTR cp;
register LINKPTR lp;
cp = Def_cell( ".MAKEFILES" );
if( (lp = cp->CE_PRQ) != NIL(LINK) ) {
int s_n, s_t, s_q;
s_n = Trace;
s_t = Touch;
s_q = Check;
Trace = Touch = Check = FALSE;
Makemkf = Wait_for_completion = TRUE;
mkfil = NIL(FILE);
for(; lp != NIL(LINK) && mkfil == NIL(FILE); lp=lp->cl_next) {
if( lp->cl_prq->ce_attr & A_FRINGE ) continue;
mkfil = Openfile( lp->cl_prq->CE_NAME, FALSE, FALSE );
if( mkfil == NIL(FILE) &&
Make(lp->cl_prq, NIL(CELL)) != -1 )
mkfil = Openfile( lp->cl_prq->CE_NAME, FALSE, FALSE );
}
Trace = s_n;
Touch = s_t;
Check = s_q;
Makemkf = Wait_for_completion = FALSE;
}
}
if( mkfil != NIL(FILE) ) {
char *f = Filename();
char *p;
if( strcmp(f, "stdin") == 0 ) f = "-";
p = _stradd( "-f", f, FALSE );
Def_macro( "MAKEFILE", p, M_PRECIOUS|M_NOEXPORT );
Parse( mkfil );
}
else if( !Rules )
Fatal( "No `makefile' present" );
if( Nest_level ) Fatal( "Missing .END for .IF" );
if( Get_env == 'e' ) _do_ReadEnvironment();
_do_VPATH(); /* kludge it up with .SOURCE */
if( Listing ) Dump(); /* print out the structures */
if( Trace ) Glob_attr &= ~A_SILENT; /* make sure we see the trace */
if( !Target )
Fatal( "No target" );
else {
Test_circle( Root, TRUE );
Check_circle_dfa();
}
Push_dir( Start_dir, ".SETDIR", (int)(Glob_attr & A_IGNORE ));
if( m_export ) {
int i;
for( i=0; i<HASH_TABLE_SIZE; ++i ) {
HASHPTR hp = Macs[i];
while( hp ) {
if( !(hp->ht_flag & M_NOEXPORT) && hp->ht_value != NIL(char) )
if( Write_env_string(hp->ht_name, hp->ht_value) != 0 )
Warning( "Could not export %s", hp->ht_name );
hp = hp->ht_next;
}
}
}
if( Buffer != NIL(char) ) {FREE( Buffer ); Buffer = NIL(char);}
if( Trace ) Def_macro(".SEQUENTIAL", "y", M_EXPANDED);
if( Glob_attr & A_SEQ ) Def_macro( "MAXPROCESS", "1", M_EXPANDED|M_FORCE );
ex_val = Make_targets();
Pop_dir( (Glob_attr & A_IGNORE) != 0 );
Clear_signals();
Epilog(ex_val); /* Does not return -- EVER */
}
static void
_do_f_flag( flag, name, fname )
char flag;
char *name;
char **fname;
{
if( *fname == NIL(char) ) {
if( name != NIL(char) ) {
*fname = name;
} else
Fatal("No file name for -%c", flag);
} else
Fatal("Only one `-%c file' allowed", flag);
}
static void
_do_ReadEnvironment()
{
t_attr saveattr = Glob_attr;
Glob_attr |= A_SILENT;
ReadEnvironment();
Glob_attr = saveattr;
}
static void
_do_VPATH()
{
HASHPTR hp;
char *_rl[2];
extern char **Rule_tab;
hp = GET_MACRO("VPATH");
if( hp == NIL(HASH) ) return;
_rl[0] = ".SOURCE :^ $(VPATH:s/:/ /)";
_rl[1] = NIL(char);
Rule_tab = _rl;
Parse( NIL(FILE) );
}
/* The file table and pointer to the next FREE slot for use by both
Openfile and Closefile. Each open stacks the new file onto the open
file stack, and a corresponding close will close the passed file, and
return the next file on the stack. The maximum number of nested
include files is limited by the value of MAX_INC_DEPTH */
static struct {
FILE *file; /* file pointer */
char *name; /* name of file */
int numb; /* line number */
} ftab[ MAX_INC_DEPTH ];
static int next_file_slot = 0;
/* Set the proper macro value to reflect the depth of the .INCLUDE directives.
*/
static void
_set_inc_depth()
{
char buf[10];
sprintf( buf, "%d", next_file_slot );
Def_macro( "INCDEPTH", buf, M_MULTI|M_NOEXPORT );
}
PUBLIC FILE *
Openfile(name, mode, err)/*
===========================
This routine opens a file for input or output depending on mode.
If the file name is `-' then it returns standard input.
The file is pushed onto the open file stack. */
char *name;
int mode;
int err;
{
FILE *fil;
DB_ENTER("Openfile");
if( name == NIL(char) || !*name )
if( !err )
DB_RETURN(NIL(FILE));
else
Fatal( "Openfile: NIL filename" );
if( next_file_slot == MAX_INC_DEPTH )
Fatal( "Too many open files. Max nesting level is %d.", MAX_INC_DEPTH);
DB_PRINT( "io", ("Opening file [%s], in slot %d", name, next_file_slot) );
if( strcmp("-", name) == 0 ) {
name = "stdin";
fil = stdin;
}
else
fil = fopen( name, mode ? "w":"r" );
if( Verbose & V_FILE_IO )
printf( "%s: Openning [%s] for %s", Pname, name, mode?"write":"read" );
if( fil == NIL(FILE) ) {
if( Verbose & V_FILE_IO ) printf( " (fail)\n" );
if( err )
Fatal( mode ? "Cannot open file %s for write" : "File %s not found",
name );
}
else {
if( Verbose & V_FILE_IO ) printf( " (success)\n" );
ftab[next_file_slot].file = fil;
ftab[next_file_slot].numb = Line_number;
ftab[next_file_slot++].name = _strdup(name);
Line_number = 0;
_set_inc_depth();
}
DB_RETURN(fil);
}
PUBLIC FILE *
Closefile()/*
=============
This routine is used to close the last file opened. This forces make
to open files in a last open first close fashion. It returns the
file pointer to the next file on the stack, and NULL if the stack is empty.*/
{
DB_ENTER("Closefile");
if( !next_file_slot )
DB_RETURN( NIL(FILE) );
if( ftab[--next_file_slot].file != stdin ) {
DB_PRINT( "io", ("Closing file in slot %d", next_file_slot) );
if( Verbose & V_FILE_IO )
printf( "%s: Closing [%s]\n", Pname, ftab[next_file_slot].name );
fclose( ftab[next_file_slot].file );
FREE( ftab[next_file_slot].name );
}
_set_inc_depth();
if( next_file_slot > 0 ) {
Line_number = ftab[next_file_slot].numb;
DB_RETURN( ftab[next_file_slot-1].file );
}
else
Line_number = 0;
DB_RETURN( NIL(FILE) );
}
PUBLIC FILE *
Search_file( macname, rname )
char *macname;
char **rname;
{
HASHPTR hp;
FILE *fil = NIL(FILE);
char *fname;
char *ename = NIL(char);
/* order of precedence is:
*
* MACNAME from command line (precious is marked)
* ... via MACNAME:=filename definition.
* MACNAME from environment
* MACNAME from builtin rules (not precious)
*/
if( (hp = GET_MACRO(macname)) != NIL(HASH) )
ename = fname = Expand(hp->ht_value);
if( hp->ht_flag & M_PRECIOUS ) fil = Openfile(fname, FALSE, FALSE);
if( fil == NIL(FILE) ) {
fname=Expand(Read_env_string(macname));
if( fil = Openfile(fname, FALSE, FALSE) ) FREE(ename);
}
if( fil == NIL(FILE) && hp != NIL(HASH) )
fil = Openfile(fname=ename, FALSE, FALSE);
if( rname ) *rname = fname;
return(fil);
}
PUBLIC char *
Filename()/*
============
Return name of file on top of stack */
{
return( next_file_slot==0 ? NIL(char) : ftab[next_file_slot-1].name );
}
PUBLIC int
Nestlevel()/*
=============
Return the file nesting level */
{
return( next_file_slot );
}
/*
** print error message from variable arg list
*/
static int errflg = TRUE;
static int warnflg = FALSE;
static void
errargs(fmt, args)
char *fmt;
va_list args;
{
int warn = _warn && warnflg && !(Glob_attr & A_SILENT);
if( errflg || warn ) {
char *f = Filename();
fprintf( stderr, "%s: ", Pname );
if( f != NIL(char) ) fprintf(stderr, "%s: line %d: ", f, Line_number);
if( errflg )
fprintf(stderr, "Error -- ");
else if( warn )
fprintf(stderr, "Warning -- ");
vfprintf( stderr, fmt, args );
putc( '\n', stderr );
if( errflg && !Continue ) Quit( NIL(CELL) );
}
}
/*
** Print error message and abort
*/
#if __STDC__ == 1 && !defined(__GNUC__)
void
Fatal(char *fmt, ...)
#else
#if defined(_MPW)
Fatal(char *fmt, va_alist)
va_dcl
#else
int
Fatal(fmt, va_alist)
char *fmt;
va_dcl;
#endif
#endif
{
va_list args;
va_start(args, fmt);
Continue = FALSE;
errargs(fmt, args);
va_end(args);
}
/*
** error message and exit (unless -k)
*/
#if __STDC__ == 1 && !defined(__GNUC__)
void
Error (char *fmt, ...)
#else
#if defined(_MPW)
Error(char *fmt, va_alist)
va_dcl
#else
int
Error(fmt, va_alist)
char* fmt;
va_dcl;
#endif
#endif
{
va_list args;
va_start(args, fmt);
errargs(fmt, args);
va_end(args);
}
/*
** non-fatal message
*/
#if __STDC__ == 1 && !defined(__GNUC__)
void
Error(char *fmt, ...)
#else
#if defined(_MPW)
Error(char *fmt, va_alist)
va_dcl
#else
int
Warning(fmt, va_alist)
char *fmt;
va_dcl;
#endif
#endif
{
va_list args;
va_start(args, fmt);
warnflg = TRUE;
errflg = FALSE;
errargs(fmt, args);
errflg = TRUE;
warnflg = FALSE;
va_end(args);
}
PUBLIC void
No_ram()
{
Fatal( "No more memory" );
}
PUBLIC
Usage( eflag )
int eflag;
{
register char *p;
char *fill;
fill = _strdup(Pname);
for(p=fill; *p; p++) *p=' ';
if( eflag ) {
fprintf(stderr, USAGE, Pname);
fprintf(stderr, USAGE2, fill);
}
else {
printf(USAGE, Pname);
fprintf(stderr, USAGE2, fill);
puts(" -P# - set max number of child processes for parallel make");
puts(" -f file - use file as the makefile");
#ifdef MSDOS
puts(" -C [+]file - duplicate console output to file, ('+' => append)");
#endif
puts(" -K file - use file as the .KEEP_STATE file");
puts(" -v{dfimt} - verbose, indicate what we are doing, (-v => -vdimt)");
puts(" d => dump change of directory info only" );
puts(" f => dump file open/close info only" );
puts(" i => dump inference information only" );
puts(" m => dump make of target information only" );
puts(" t => keep temporary files when done\n" );
puts("Options: (can be catenated, ie -irn == -i -r -n)");
puts(" -A - enable AUGMAKE special target mapping");
puts(" -B - enable the use of spaces instead of tabs to start recipes");
puts(" -c - use non standard comment scanning");
puts(" -E - define environment strings as macros");
puts(" -e - same as -E but done after parsing makefile");
puts(" -h - print out usage info");
puts(" -i - ignore errors");
puts(" -k - make independent targets, even if errors");
puts(" -n - trace and print, do not execute commands");
puts(" -p - print out a version of the makefile");
puts(" -q - check if target is up to date. Does not do");
puts(" anything. Returns 0 if up to date, 1 otherwise");
puts(" -r - don't use internal rules");
puts(" -s - do your work silently");
puts(" -S - disable parallel (force sequential) make, overrides -P");
puts(" -t - touch, update time stamps without executing commands");
puts(" -T - do not apply transitive closure on inference rules");
puts(" -u - force unconditional update of target");
puts(" -V - print out version number");
puts(" -x - export macro values to environment");
puts(" -X - ignore #! lines at start of makefile");
}
Quit(NIL(CELL));
}
PUBLIC
Version()
{
extern char **Rule_tab;
char **p;
printf("%s - %s, ", Pname, sccid);
printf("Version %s, PL %d\n\n", VERSION, PATCHLEVEL);
puts("Default Configuration:");
for (p=Rule_tab; *p != NIL(char); p++)
printf("\t%s\n", *p);
}

183
dmake/dmake.h Normal file
View File

@ -0,0 +1,183 @@
/* RCS -- $Header: /u2/dvadura/src/generic/dmake/src/RCS/dmake.h,v 1.1 1992/01/24 03:26:50 dvadura Exp $
-- SYNOPSIS -- global defines for dmake.
--
-- DESCRIPTION
-- All the interesting bits and flags that dmake uses are defined here.
--
-- AUTHOR
-- Dennis Vadura, dvadura@watdragon.uwaterloo.ca
-- CS DEPT, University of Waterloo, Waterloo, Ont., Canada
--
-- COPYRIGHT
-- Copyright (c) 1990 by Dennis Vadura. All rights reserved.
--
-- This program is free software; you can redistribute it and/or
-- modify it under the terms of the GNU General Public License
-- (version 1), as published by the Free Software Foundation, and
-- found in the file 'LICENSE' included with this distribution.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warrant of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program; if not, write to the Free Software
-- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
--
-- LOG
-- $Log: dmake.h,v $
* Revision 1.1 1992/01/24 03:26:50 dvadura
* dmake Version 3.8, Initial revision
*
*/
#ifndef _DMAKE_INCLUDED_
#define _DMAKE_INCLUDED_
#define MAX_INC_DEPTH 10 /* max of ten nested include files */
#define MAX_COND_DEPTH 20 /* max nesting level of conditionals */
#define ERROR_EXIT_VALUE 255 /* return code of aborted make */
#define CONTINUATION_CHAR '\\' /* line continuation \<nl> */
#define DEF_ESCAPE_CHAR '\\' /* escape char for used chars */
#define ESCAPE_CHAR *Escape_char
#define COMMENT_CHAR '#' /* start of comment chars */
#define TGT_DEP_SEP ':' /* separator for targets and dependents */
#define CONDSTART '.' /* start of conditional token eg .IF */
#define DEF_MAKE_PNAME "dmake"/* default name to use as name of make */
/* ............... Hashing function constants ......................... */
#define HASH_TABLE_SIZE 200 /* See hash.c for description */
/* Bit flags for cells and macro definitions. */
#define M_DEFAULT 0x0000 /* default flag value */
#define M_MARK 0x0001 /* mark for circularity checks */
#define M_PRECIOUS 0x0002 /* keep macro, same as A_PRE... */
#define M_MULTI 0x0004 /* multiple redefinitions ok! */
#define M_EXPANDED 0x0008 /* macro has been assigned */
#define M_USED 0x0010 /* macro has been expanded */
#define M_LITERAL 0x0020 /* don't strip w/s on macro def */
#define M_NOEXPORT 0x0040 /* don't export macro for -x */
#define M_FORCE 0x0080 /* Force a macro redefinition */
#define M_VAR_BIT 0x1000 /* macro bit variable */
#define M_VAR_CHAR 0x2000 /* macro char variable */
#define M_VAR_STRING 0x4000 /* macro string variable */
#define M_VAR_INT 0x8000 /* macro integer variable */
#define M_VAR_MASK 0xf000 /* macro variable mask */
/* Global and target attribute flag definitions.
* If you change the values of these or re-order them make appropriate changes
* in dump.c so that the output of dmake -p matches the attribute info for a
* target. */
#define A_DEFAULT 0x00000 /* default flag value */
#define A_PRECIOUS 0x00001 /* object is precious */
#define A_SILENT 0x00002 /* don't echo commands */
#define A_LIBRARY 0x00004 /* target is an archive */
#define A_EPILOG 0x00008 /* insert shell epilog code */
#define A_PROLOG 0x00010 /* insert shell prolog code */
#define A_IGNORE 0x00020 /* ignore errors */
#define A_SYMBOL 0x00040 /* lib member is a symbol */
#define A_NOINFER 0x00080 /* no trans closure from cell */
#define A_UPDATEALL 0x00100 /* all targets of rule modified */
#define A_SEQ 0x00200 /* sequential make attribute */
#define A_SETDIR 0x00400 /* cd to dir when making target */
#define A_SHELL 0x00800 /* run the recipe using a shell */
#define A_SWAP 0x01000 /* swap on exec. */
#define A_MKSARGS 0x02000 /* use MKS argument swapping */
#define A_PHONY 0x04000 /* .PHONY attribute */
#define A_NOSTATE 0x08000 /* don't track state for me */
#define MAX_ATTR A_NOSTATE /* highest valid attribute */
#define A_LIBRARYM 0x10000 /* target is an archive member */
#define A_FRINGE 0x20000 /* cell is on the fringe */
#define A_COMPOSITE 0x40000 /* member of lib(targ) name */
#define A_FFNAME 0x80000 /* if set, free ce_fname in stat*/
#define A_UPDATED 0x100000 /* Used to mark cell as updated */
#define A_ROOT 0x200000 /* True if it is a root prereq */
/* Global and target bit flag definitions */
#define F_DEFAULT 0x0000 /* default flag value */
#define F_MARK 0x0001 /* circularity check mark */
#define F_MULTI 0x0002 /* multiple rules for target */
#define F_SINGLE 0x0004 /* exec rules one/prerequisite */
#define F_TARGET 0x0008 /* marks a target */
#define F_RULES 0x0010 /* indicates target has rules */
#define F_GROUP 0x0020 /* indicates that rules are to */
/* fed to the shell as a group */
#define F_TRANS 0x0040 /* same as F_STAT not used tgthr*/
#define F_STAT 0x0040 /* target already stated */
#define F_VISITED 0x0080 /* target scheduled for make */
#define F_USED 0x0080 /* used in releparse.c */
#define F_SPECIAL 0x0100 /* marks a special target */
#define F_DFA 0x0200 /* bit for marking added DFA */
#define F_EXPLICIT 0x0400 /* explicit target in makefile */
#define F_PERCENT 0x0800 /* marks a target as a % rule */
#define F_REMOVE 0x1000 /* marks an intermediate target */
#define F_MAGIC 0x2000 /* marks a magic target */
#define F_INFER 0x4000 /* target is result of inference*/
#define F_MADE 0x8000 /* target is manufactured */
/* Definitions for the Parser states */
#define NORMAL_SCAN 0 /* normal processing state */
#define RULE_SCAN 1 /* scan of rule text */
/* definitions for macro operator types */
#define M_OP_EQ 1 /* macro operation is '=' */
#define M_OP_CL 2 /* macro operation is ':=' */
#define M_OP_PL 3 /* macro operation is '+=' */
#define M_OP_PLCL 4 /* macro operation is '+:='*/
#define M_OP_DF 5 /* macro operation is '*=' */
#define M_OP_DFCL 6 /* macro operation is '*:='*/
/* definitions for rule operator types */
#define R_OP_CL 1 /* rule operation is ':' */
#define R_OP_DCL 2 /* rule operation is '::' */
#define R_OP_BG 4 /* rule operation is ':!' */
#define R_OP_UP 8 /* rule operation is ':^' */
#define R_OP_MI 16 /* rule operation is ':-' */
/* definitions for modifier application in Apply_modifiers in expand.c */
#define SUFFIX_FLAG 1 /* defines for macro modifier code */
#define DIRECTORY_FLAG 2
#define FILE_FLAG 4
/* special target definitions for use inside dmake */
#define ST_IF 1
#define ST_ELSE 2
#define ST_END 3
#define ST_REST 4 /* remaining special targets */
#define ST_INCLUDE 5
#define ST_SOURCE 7
#define ST_EXPORT 8
#define ST_IMPORT 9
#define ST_ELIF 10
#define ST_KEEP 11
/* Flags for controling use of -v switch */
#define V_NONE 0x00
#define V_LEAVE_TMP 0x01
#define V_PRINT_DIR 0x02
#define V_INFER 0x04
#define V_MAKE 0x08
#define V_FILE_IO 0x10
#define V_ALL (V_LEAVE_TMP | V_PRINT_DIR | V_INFER | V_MAKE |\
V_FILE_IO)
/* Macro definitions for use inside dmake */
#define SET_TOKEN(A, B) (A)->tk_str = (B); (A)->tk_cchar = *(B);\
(A)->tk_quote = 1;
#define CLEAR_TOKEN(A) *(A)->tk_str = (A)->tk_cchar
#define GET_MACRO(A) Get_name(A, Macs, FALSE)
#define iswhite(C) ((C == ' ') || (C == '\t'))
#endif

209
dmake/dmdump.c Normal file
View File

@ -0,0 +1,209 @@
/* RCS -- $Header: /u/dvadura/src/generic/dmake/src/RCS/dmdump.c,v 1.2 1992/04/07 04:42:46 dvadura Exp $
-- SYNOPSIS -- dump the internal dag to stdout.
--
-- DESCRIPTION
-- This file contains the routine that is called to dump a version of
-- the digested makefile to the standard output. May be useful perhaps
-- to the ordinary user, and invaluable for debugging make.
--
-- AUTHOR
-- Dennis Vadura, dvadura@watdragon.uwaterloo.ca
-- CS DEPT, University of Waterloo, Waterloo, Ont., Canada
--
-- COPYRIGHT
-- Copyright (c) 1990 by Dennis Vadura. All rights reserved.
--
-- This program is free software; you can redistribute it and/or
-- modify it under the terms of the GNU General Public License
-- (version 1), as published by the Free Software Foundation, and
-- found in the file 'LICENSE' included with this distribution.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warrant of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program; if not, write to the Free Software
-- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
--
-- LOG
-- $Log: dmdump.c,v $
* Revision 1.2 1992/04/07 04:42:46 dvadura
* Deleted define of unused variable.
*
* Revision 1.1 1992/01/24 03:28:51 dvadura
* dmake Version 3.8, Initial revision
*
*/
#include "extern.h"
#define M_TEST (M_PRECIOUS | M_VAR_MASK)
static void dump_name ANSI((HASHPTR, int));
static void dump_normal_target ANSI((CELLPTR, int));
static void dump_prerequisites ANSI((LINKPTR, int, int, int));
PUBLIC void
Dump()/*
======== Dump onto standard output the digested makefile. Note that
the form of the dump is not representative of the contents
of the original makefile contents at all */
{
HASHPTR hp;
int i;
DB_ENTER( "Dump" );
puts( "# Dump of dmake macro variables:" );
for( i=0; i<HASH_TABLE_SIZE; i++)
for( hp=Macs[i]; hp != NIL(HASH); hp = hp->ht_next ) {
int flag = hp->ht_flag;
printf( "%s ", hp->ht_name );
if( flag & M_EXPANDED ) putchar( ':' );
printf( "= " );
if( hp->ht_value != NIL(char) ) printf( "%s",hp->ht_value );
if( flag & M_PRECIOUS )
printf( "\t # PRECIOUS " );
putchar( '\n' );
}
puts( "\n#====================================" );
puts( "# Dump of targets:\n" );
for( i=0; i<HASH_TABLE_SIZE; i++ )
for( hp = Defs[i]; hp != NIL(HASH); hp = hp->ht_next )
if( !(hp->CP_OWNR->ce_flag & F_PERCENT) ) {
if( Root->ce_prq && hp->CP_OWNR == Root->ce_prq->cl_prq )
puts( "# ******* FIRST TARGET ********" );
dump_normal_target( hp->CP_OWNR, hp->CP_OWNR->ce_flag );
}
puts( "\n#====================================" );
puts( "# Dump of inference graph\n" );
for( i=0; i<HASH_TABLE_SIZE; i++ )
for( hp = Defs[i]; hp != NIL(HASH); hp = hp->ht_next )
if( (hp->CP_OWNR->ce_flag & F_PERCENT) &&
!(hp->CP_OWNR->ce_flag & F_MAGIC) )
dump_normal_target( hp->CP_OWNR, hp->CP_OWNR->ce_flag );
DB_VOID_RETURN;
}
PUBLIC void
Dump_recipe( sp )/*
===================
Given a string pointer print the recipe line out */
STRINGPTR sp;
{
char *st;
char *nl;
if( sp == NIL(STRING) ) return;
putchar( '\t' );
if( sp->st_attr & A_SILENT ) putchar( '@' );
if( sp->st_attr & A_IGNORE ) putchar( '-' );
if( sp->st_attr & A_SHELL ) putchar( '+' );
if( sp->st_attr & A_SWAP ) putchar( '%' );
st = sp->st_string;
for( nl=strchr(st,'\n'); nl != NIL( char); nl=strchr(st,'\n') ) {
*nl = '\0';
printf( "%s\\\n", st );
*nl = '\n';
st = nl+1;
}
printf( "%s\n", st );
}
static char *_attrs[] = { ".PRECIOUS", ".SILENT", ".LIBRARY",
".EPILOG", ".PROLOG", ".IGNORE", ".SYMBOL", ".NOINFER",
".UPDATEALL", ".SEQUENTIAL", ".SETDIR=", ".USESHELL", ".SWAP", ".MKSARGS",
".PHONY", ".NOSTATE" };
static void
dump_normal_target( cp, flag )/*
================================
Dump in makefile like format the dag information */
CELLPTR cp;
int flag;
{
register STRINGPTR sp;
t_attr attr;
unsigned int k;
DB_ENTER( "dump_normal_target" );
if( !(cp->ce_flag & F_TARGET) && !cp->ce_attr ) { DB_VOID_RETURN; }
if( cp->ce_flag & F_MULTI ) {
int tflag = cp->ce_prq->cl_prq->ce_flag;
if( !(cp->ce_flag & F_PERCENT) ) tflag |= F_MULTI;
dump_prerequisites(cp->ce_prq, FALSE, TRUE, tflag);
}
else {
dump_name( cp->ce_name, FALSE );
for( k=0, attr=1; attr <= MAX_ATTR; attr <<= 1, k++ )
if( cp->ce_attr & attr ) {
printf( "%s%s ", _attrs[k],
(attr != A_SETDIR) ? "" : (cp->ce_dir?cp->ce_dir:"") );
}
putchar( ':' );
if( flag & F_MULTI ) putchar( ':' );
if( flag & F_SINGLE ) putchar( '!' );
putchar( ' ' );
dump_prerequisites( cp->ce_prq, FALSE, FALSE, F_DEFAULT);
dump_prerequisites( cp->ce_indprq, TRUE, FALSE, F_DEFAULT);
putchar( '\n' );
if( cp->ce_flag & F_GROUP ) puts( "[" );
for( sp = cp->ce_recipe; sp != NIL(STRING); sp = sp->st_next )
Dump_recipe( sp );
if( cp->ce_flag & F_GROUP ) puts( "]" );
putchar( '\n' );
}
DB_VOID_RETURN;
}
static void
dump_prerequisites( lp, quote, recurse, flag )
LINKPTR lp;
int quote;
int recurse;
int flag;
{
for( ; lp; lp=lp->cl_next )
if( recurse )
dump_normal_target(lp->cl_prq, flag);
else if( lp->cl_prq )
dump_name(lp->cl_prq->ce_name, quote);
}
static void
dump_name( hp, quote )/*
========================
print out a name */
HASHPTR hp;
int quote;
{
if( quote ) putchar('\'');
printf( "%s", hp->ht_name );
if( quote ) putchar('\'');
putchar(' ');
}

302
dmake/dmstring.c Normal file
View File

@ -0,0 +1,302 @@
/* RCS -- $Header: /u2/dvadura/src/generic/dmake/src/RCS/dmstring.c,v 1.1 1992/01/24 03:29:38 dvadura Exp $
-- SYNOPSIS -- string handling code
--
-- DESCRIPTION
-- Routines to handle string manipulation. This code is not specific
-- to dmake and has/and will be used in other programs. The string
-- "" is considered the NULL string, if NIL(char) is received instead
-- undefined results may occurr. (In reality NIL(char) is checked for
-- but in general it is not safe to assume NIL(char) == NULL)
--
-- AUTHOR
-- Dennis Vadura, dvadura@watdragon.uwaterloo.ca
-- CS DEPT, University of Waterloo, Waterloo, Ont., Canada
--
-- COPYRIGHT
-- Copyright (c) 1990 by Dennis Vadura. All rights reserved.
--
-- This program is free software; you can redistribute it and/or
-- modify it under the terms of the GNU General Public License
-- (version 1), as published by the Free Software Foundation, and
-- found in the file 'LICENSE' included with this distribution.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warrant of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program; if not, write to the Free Software
-- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
--
-- LOG
-- $Log: dmstring.c,v $
* Revision 1.1 1992/01/24 03:29:38 dvadura
* dmake Version 3.8, Initial revision
*
*/
#include "extern.h"
PUBLIC char *
_strjoin( src, data, n, fr )/*
==============================
Join data to src according to value of n.
n = -1 - return strcat( src, data )
n >= 0 - return strncat( src, data, n )
FREE original src if fr == TRUE, else leave it alone */
char *src;
char *data;
int n;
int fr;
{
char *t;
int l;
int flag = FALSE;
DB_ENTER( "_strjoin" );
if( src == NIL(char) ) { src = ""; flag = TRUE; }
if( data == NIL(char) ) data = "";
DB_PRINT( "str", ("Joining [%s] [%s] %d", src, data, n) );
if( n == -1 ) n = strlen( data );
l = strlen( src ) + n + 1;
if( (t = MALLOC( l, char )) == NIL(char) ) No_ram();
strcpy( t, src );
if (n) strncat( t, data, n );
t[ l-1 ] = '\0';
if( !flag && fr ) FREE( src );
DB_PRINT( "str", ("Result [%s]", t) );
DB_RETURN( t );
}
PUBLIC char *
_stradd( src, data, fr )/*
==========================
append data to src with space in between if src is not NIL(char) or ""
and free both src and data if fr == TRUE, otherwise leave them be */
char *src;
char *data;
int fr;
{
char *t;
int l;
int sflag;
int dflag;
DB_ENTER( "_stradd" );
sflag = dflag = fr;
if( src == NIL(char) ) { src = ""; sflag = FALSE; }
if( data == NIL(char) ) { data = ""; dflag = FALSE; }
DB_PRINT( "str", ("Adding [%s] [%s] %d", src, data, fr) );
l = strlen(src) + strlen(data) + 1;
if( *src ) l++;
if( (t = MALLOC( l, char )) == NIL(char) ) No_ram();
strcpy( t, src );
if( *data )
{
if( *src ) strcat( t, " " );
strcat( t, data );
}
if( sflag ) FREE( src );
if( dflag ) FREE( data );
DB_PRINT( "str", ("Result [%s]", t) );
DB_RETURN( t );
}
PUBLIC char *
_strapp( src1, src2 )/*
=======================
Append two strings together, and return the result with a space between
the two strings. FREE the first string if it is not NIL and always
leave the second string be. */
char *src1;
char *src2;
{
src2 = _stradd( src1, src2, FALSE );
if( src1 != NIL(char) ) FREE( src1 );
return( src2 );
}
#ifdef DBUG
#ifdef _strdup
#undef _strdup
#endif
#endif
PUBLIC char *
_strdup( str )/*
================ Duplicate the contents of a string, by using malloc */
char *str;
{
char *t;
if( str == NIL(char) ) return( NIL(char) );
if( (t = MALLOC( strlen( str )+1, char )) == NIL(char) ) No_ram();
strcpy( t, str );
return( t );
}
PUBLIC char *
_strdup2( str )/*
=================
This function is used solely to properly quote command line arguments when
they are reinserted int MAKEMACROS so that they can be used further in
a processing line. */
char *str;
{
char *t;
size_t size;
size_t alloced;
char *tmp;
char *dest;
int seen_equal = 0;
if(str == NIL(char)) return(NIL(char));
size = strlen(str) + 1;
alloced = size + 2; /* for two quotes */
for(tmp = str; *tmp; tmp++)
if(*tmp == '"')
alloced++;
if((t = MALLOC(alloced, char)) == NIL(char)) No_ram();
for(tmp = str, dest = t; *tmp; tmp++, dest++) {
if(*tmp == '=' && !seen_equal) {
seen_equal = 1;
*dest++ = *tmp;
*dest = '"';
continue;
}
if(*tmp == '"')
*dest++ = '\\';
*dest = *tmp;
}
if(!seen_equal)
Fatal("_strdup2 invoked without argument of form x=y\n");
*dest++ = '"';
*dest = 0;
return t;
}
PUBLIC char *
_strpbrk( s1, s2 )/*
====================
find first occurence of char in s2 in string s1.
Returns a pointer to the first occurrence. NOTE '\0' is considered part
of s2 and a pointer to it is returned if no other chars match. */
char *s1;
char *s2;
{
register char *t;
if( s1 == NIL(char) || s2 == NIL(char) ) return( "" );
for( t=s1; *t && (strchr( s2, *t ) == NIL(char)); t++ );
return( t );
}
PUBLIC char *
_strspn( s1, s2 )/*
===================
return pointer to first char in s1 that does not belong to s2.
Returns the pointer if match found, else returns pointer to null char
in s1. (ie. "" ) */
char *s1;
char *s2;
{
register char *t;
if( s1 == NIL(char) || s2 == NIL(char) ) return( "" );
for( t=s1; *t && (strchr( s2, *t ) != NIL(char)); t++ );
return( t );
}
PUBLIC char *
_strstr( s1, s2 )/*
================== find first occurrence in s1 of s2 */
char *s1;
char *s2;
{
register char *s;
register char *p;
register char *r;
if( s1 != NIL(char) && s2 != NIL(char) )
for( s=s1; *s; s++ )
if( *s == *s2 )
{
for( r=s+1, p = s2+1; *p && (*r == *p); r++, p++ );
if( !*p ) return( s );
}
return( NIL(char) );
}
PUBLIC char *
_substr( s, e )/*
=================
Return the string between the two pointers s and e, not including the
char that e points to. NOTE: This routine assumes that s and e point
into the same string. */
char *s;
char *e;
{
char save;
int len = e-s;
if( len < 0 || len > strlen(s) )
Fatal( "Internal Error: _substr fails consistency test" );
save = *e;
*e = '\0';
s = _strdup( s );
*e = save;
return( s );
}

921
dmake/expand.c Normal file
View File

@ -0,0 +1,921 @@
/* RCS -- $Header: /u2/dvadura/src/generic/dmake/src/RCS/expand.c,v 1.1 1992/01/24 03:27:03 dvadura Exp $
-- SYNOPSIS -- macro expansion code.
--
-- DESCRIPTION
--
-- This routine handles all the necessary junk that deals with macro
-- expansion. It understands the following syntax. If a macro is
-- not defined it expands to NULL, and {} are synonyms for ().
--
-- $$ - expands to $
-- {{ - expands to {
-- }} - expands to }
-- $A - expands to whatever the macro A is defined as
-- $(AA) - expands to whatever the macro AA is defined as
-- $($(A)) - represents macro indirection
-- <+...+> - get mapped to $(mktmp ...)
--
-- following macro is recognized
--
-- string1{ token_list }string2
--
-- and expands to string1 prepended to each element of token_list and
-- string2 appended to each of the resulting tokens from the first
-- operation. If string2 is of the form above then the result is
-- the cross product of the specified (possibly modified) token_lists.
--
-- The folowing macro modifiers are defined and expanded:
--
-- $(macro:modifier_list:modifier_list:...)
--
-- where modifier_list a combination of:
--
-- D or d - Directory portion of token including separator
-- F or f - File portion of token including suffix
-- B or b - basename portion of token not including suffix
-- T or t - for tokenization
--
-- or a single
-- S or s - pattern substitution (simple)
--
-- NOTE: Modifiers are applied once the macro value has been found.
-- Thus the construct $($(test):s/joe/mary/) is defined and
-- modifies the value of $($(test))
--
-- Also the construct $(m:d:f) is not the same as $(m:df)
-- the first applies d to the value of $(m) and then
-- applies f to the value of that whereas the second form
-- applies df to the value of $(m).
--
-- AUTHOR
-- Dennis Vadura, dvadura@watdragon.uwaterloo.ca
-- CS DEPT, University of Waterloo, Waterloo, Ont., Canada
--
-- COPYRIGHT
-- Copyright (c) 1990 by Dennis Vadura. All rights reserved.
--
-- This program is free software; you can redistribute it and/or
-- modify it under the terms of the GNU General Public License
-- (version 1), as published by the Free Software Foundation, and
-- found in the file 'LICENSE' included with this distribution.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warrant of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program; if not, write to the Free Software
-- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
--
-- LOG
-- $Log: expand.c,v $
* Revision 1.1 1992/01/24 03:27:03 dvadura
* dmake Version 3.8, Initial revision
*
*/
#include "extern.h"
/* Microsoft BRAINDAMAGE ALERT!!!!
* This #ifdef is here only to satisfy stupid bugs in MSC5.0 and MSC5.1
* it isn't needed for anything else. It turns loop optimization off. */
#if defined(_MSC_VER)
#include "optoff.h"
#endif
static char* _scan_token ANSI((char*, char**));
static char* _scan_macro ANSI((char*, char**));
static char* _scan_brace ANSI((char*, char**, int*));
static char* _cross_prod ANSI((char*, char*));
PUBLIC char *
Expand( src )/*
===============
This is the driver routine for the expansion, it identifies non-white
space tokens and gets the _scan_token routine to figure out if they should
be treated in a special way. */
char *src; /* pointer to source string */
{
char *tmp; /* pointer to temporary str */
char *res; /* pointer to result string */
char *start; /* pointer to start of token */
DB_ENTER( "Expand" );
DB_PRINT( "exp", ("Expanding [%s]", src) );
res = _strdup( "" );
if( src == NIL(char) ) DB_RETURN( res );
while( *src ) {
char *ks, *ke;
/* Here we find the next non white space token in the string
* and find it's end, with respect to non-significant white space. */
start = _strspn( src, " \t\n" );
res = _strjoin( res, src, start-src, TRUE );
if( !(*start) ) break;
/* START <+...+> KLUDGE */
if( (ks=_strstr(start,"<+")) && (ke=_strstr(ks,"+>")) ){
char *t1, *t2;
res = _strjoin( res, t2=Expand(t1=_substr(start,ks)), -1, TRUE);
FREE(t1); FREE(t2);
t1 = _substr(ks+2, ke+1); t1[ke-ks-2] = ')';
t2 = _strjoin( "$(mktmp ", t1, -1,FALSE);
FREE(t1);
res = _strjoin( res, t2=Expand(t2), -1, TRUE);
FREE(t2);
src = ke+2;
}
/* END <+...+> KLUDGE */
else {
res = _strjoin( res, tmp = _scan_token( start, &src ), -1, TRUE );
FREE( tmp );
}
}
DB_PRINT( "exp", ("Returning [%s]", res) );
DB_RETURN( res );
}
PUBLIC char *
Apply_edit( src, pat, subst, fr, anchor )/*
===========================================
Take the src string and apply the pattern substitution. ie. look for
occurrences of pat in src and replace each occurrence with subst. This is
NOT a regular expressions pattern substitution, it's just not worth it.
if anchor == TRUE then the src pattern match must be at the end of a token.
ie. this is for SYSV compatibility and is only used for substitutions of
the caused by $(macro:pat=sub). So if src = "fre.o.k june.o" then
$(src:.o=.a) results in "fre.o.k june.a", and $(src:s/.o/.a) results in
"fre.a.k june.a" */
char *src; /* the source string */
char *pat; /* pattern to find */
char *subst; /* substitute string */
int fr; /* if TRUE free src */
int anchor; /* if TRUE anchor */
{
char *res;
char *p;
char *s;
int l;
DB_ENTER( "Apply_edit" );
if( !*pat ) DB_RETURN( src ); /* do nothing if pat is NULL */
DB_PRINT( "mod", ("Source str: [%s]", src) );
DB_PRINT( "mod", ("Replacing [%s], with [%s]", pat, subst) );
s = src;
l = strlen( pat );
if( (p = _strstr( s, pat )) != NIL(char) ) {
res = _strdup( "" );
do {
if( anchor )
if( !*(p+l) || (strchr(" \t", *(p+l)) != NIL(char)) )
res = _strjoin( _strjoin( res, s, p-s, TRUE ), subst, -1, TRUE );
else
res = _strjoin( res, s, p+l-s, TRUE );
else
res = _strjoin( _strjoin( res, s, p-s, TRUE ), subst, -1, TRUE );
s = p + l;
}
while( (p = _strstr( s, pat )) != NIL(char) );
res = _strjoin( res, s, -1, TRUE );
if( fr ) FREE( src );
}
else
res = src;
DB_PRINT( "mod", ("Result [%s]", res) );
DB_RETURN( res );
}
PUBLIC void
Map_esc( tok )/*
================
Map an escape sequence and replace it by it's corresponding character
value. It is assumed that tok points at the initial \, the esc
sequence in the original string is replaced and the value of tok
is not modified. */
char *tok;
{
if( strchr( "\"\\vantbrf01234567", tok[1] ) ) {
switch( tok[1] ) {
case 'a' : *tok = 0x07; break;
case 'b' : *tok = '\b'; break;
case 'f' : *tok = '\f'; break;
case 'n' : *tok = '\n'; break;
case 'r' : *tok = '\r'; break;
case 't' : *tok = '\t'; break;
case 'v' : *tok = 0x0b; break;
case '\\': *tok = '\\'; break;
case '\"': *tok = '\"'; break;
default: {
register int i = 0;
register int j = 0;
for( ; i<2 && isdigit(tok[2]); i++ ) {
j = (j << 3) + (tok[1] - '0');
strcpy( tok+1, tok+2 );
}
j = (j << 3) + (tok[1] - '0');
*tok = j;
}
}
strcpy( tok+1, tok+2 );
}
}
PUBLIC char*
Apply_modifiers( mod, src )/*
=============================
This routine applies the appropriate modifiers to the string src
and returns the proper result string */
int mod;
char *src;
{
char *s;
char *e;
TKSTR str;
DB_ENTER( "Apply_modifiers" );
if( mod == (SUFFIX_FLAG | DIRECTORY_FLAG | FILE_FLAG) )
DB_RETURN( src );
SET_TOKEN( &str, src );
DB_PRINT( "mod", ("Source string [%s]", src) );
while( *(s = Get_token( &str, "", FALSE )) != '\0' ) {
/* search for the directory portion of the filename. If the
* DIRECTORY_FLAG is set, then we want to keep the directory portion
* othewise throw it away and blank out to the end of the token */
if( (e = basename(s)) != s)
if( !(mod & DIRECTORY_FLAG) ) {
strcpy(s, e);
e = s+(str.tk_str-e);
for(; e != str.tk_str; e++)
*e = ' ';
}
else
s = e;
/* search for the suffix, if there is none, treat it as a NULL suffix.
* if no file name treat it as a NULL file name. same copy op as
* for directory case above */
e = strrchr( s, '.' ); /* NULL suffix if e=0 */
if( e == NIL(char) ) e = s+strlen(s);
if( !(mod & FILE_FLAG) ) {
strcpy( s, e );
e = s+(str.tk_str-e);
for( ; e != str.tk_str; e++ ) *e = ' ';
}
else
s = e;
/* The last and final part. This is the suffix case, if we don't want
* it then just erase to the end of the token. */
if( s != NIL(char) )
if( !(mod & SUFFIX_FLAG) )
for( ; s != str.tk_str; s++ ) *s = ' ';
}
/* delete the extra white space, it looks ugly */
for( s = src, e = NIL(char); *s; s++ )
if( *s == ' ' || *s == '\t' || *s == '\n' ) {
if( e == NIL(char) )
e = s;
}
else {
if( e != NIL(char) ) {
if( e+1 < s ) {
strcpy( e+1, s );
s = e+1;
*e = ' ';
}
e = NIL(char);
}
}
if( e != NIL(char) )
if( e < s )
strcpy( e, s );
DB_PRINT( "mod", ("Result string [%s]", src) );
DB_RETURN( src );
}
PUBLIC char*
Tokenize( src, separator )/*
============================
Tokenize the input of src and join each token found together with
the next token separated by the separator string.
When doing the tokenization, <sp>, <tab>, <nl>, and \<nl> all
constitute white space. */
char *src;
char *separator;
{
TKSTR tokens;
char *tok;
char *res;
int first = TRUE;
DB_ENTER( "Tokenize" );
SET_TOKEN( &tokens, src );
/* map the escape codes in the separator string first */
for(tok=separator; (tok = strchr(tok,ESCAPE_CHAR)) != NIL(char); tok++)
Map_esc( tok );
DB_PRINT( "exp", ("Separator [%s]", separator) );
/* Build the token list */
res = _strdup( "" );
while( *(tok = Get_token( &tokens, "", FALSE )) != '\0' ) {
DB_PRINT( "exp", ("Tokenizing [%s]", tok) );
if( first ) {
FREE( res );
res = _strdup( tok );
first = FALSE;
}
else {
char *x;
res = _strjoin(res, x =_strjoin(separator, tok, -1, FALSE), -1, TRUE);
FREE( x );
}
}
FREE( src );
DB_RETURN( res );
}
static char*
_scan_token( s, ps )/*
======================
This routine scans the token characters one at a time and identifies
macros starting with $( and ${ and calls _scan_macro to expand their
value. the string1{ token_list }string2 expansion is also handled.
In this case a temporary result is maintained so that we can take it's
cross product with any other token_lists that may possibly appear. */
char *s; /* pointer to start of src string */
char **ps; /* pointer to start pointer */
{
char *res; /* pointer to result */
char *start; /* pointer to start of prefix */
int crossproduct = 0; /* if 1 then computing X-prod */
start = s;
res = _strdup( "" );
while( 1 )
switch( *s ) {
/* Termination, We halt at seeing a space or a tab or end of string.
* We return the value of the result with any new macro's we scanned
* or if we were computing cross_products then we return the new
* cross_product.
* NOTE: Once we start computing cross products it is impossible to
* stop. ie. the semantics are such that once a {} pair is
* seen we compute cross products until termination. */
case ' ':
case '\t':
case '\n':
case '\0':
{
char *tmp;
*ps = s;
if( !crossproduct )
tmp = _strjoin( res, start, (s-start), TRUE );
else
{
tmp = _substr( start, s );
tmp = _cross_prod( res, tmp );
}
return( tmp );
}
case '$':
case '{':
{
/* Handle if it's a macro or if it's a {} construct.
* The results of a macro expansion are handled differently based
* on whether we have seen a {} beforehand. */
char *tmp;
tmp = _substr( start, s ); /* save the prefix */
if( *s == '$' ) {
start = _scan_macro( s+1, &s );
if( crossproduct )
res = _cross_prod( res, _strjoin( tmp, start, -1, TRUE ) );
else {
res = _strjoin(res,tmp = _strjoin(tmp,start,-1,TRUE),-1,TRUE);
FREE( tmp );
}
FREE( start );
}
else if( strchr("{ \t",s[1]) == NIL(char) ){
int ok;
start = _scan_brace( s+1, &s, &ok );
if( ok ) {
res = _cross_prod( res, _cross_prod(tmp, start) );
crossproduct = TRUE;
}
else {
res =_strjoin(res,tmp=_strjoin(tmp,start,-1,TRUE),-1,TRUE);
FREE( start );
FREE( tmp );
}
}
else { /* handle the {{ case */
res = _strjoin( res, start, (s-start+1), TRUE );
s += (s[1]=='{')?2:1;
FREE( tmp );
}
start = s;
}
break;
case '}':
if( s[1] != '}' ) {
/* error malformed macro expansion */
s++;
}
else { /* handle the }} case */
res = _strjoin( res, start, (s-start+1), TRUE );
s += 2;
start = s;
}
break;
default: s++;
}
}
static char*
_scan_macro( s, ps )/*
======================
This routine scans a macro use and expands it to the value. It
returns the macro's expanded value and modifies the pointer into the
src string to point at the first character after the macro use.
The types of uses recognized are:
$$ - expands to $
$(name) - expands to value of name
${name} - same as above
$($(name)) - recurses on macro names (any level)
and
$(func[,args ...] [data])
and
$(name:modifier_list:modifier_list:...)
see comment for Expand for description of valid modifiers.
NOTE that once a macro name bounded by ( or { is found only
the appropriate terminator (ie. ( or } is searched for. */
char *s; /* pointer to start of src string */
char **ps; /* pointer to start pointer */
{
char sdelim; /* start of macro delimiter */
char edelim; /* corresponding end macro delim */
char *start; /* start of prefix */
char *macro_name; /* temporary macro name */
char *recurse_name; /* recursive macro name */
char *result; /* result for macro expansion */
int bflag = 0; /* brace flag, ==0 => $A type macro */
int done = 0; /* != 0 => done macro search */
int lev = 0; /* brace level */
int mflag = 0; /* != 0 => modifiers present in mac */
int fflag = 0; /* != 0 => GNU style function */
HASHPTR hp; /* hash table pointer for macros */
DB_ENTER( "_scan_macro" );
/* Check for the simple $ at end of line case */
if( !*s ) {
*ps = s;
DB_RETURN( _strdup("") );
}
if( *s == '$' ) { /* Take care of the simple $$ case. */
*ps = s+1;
DB_RETURN( _strdup("$") );
}
sdelim = *s; /* set and remember start/end delim */
if( sdelim == '(' )
edelim = ')';
else
edelim = '}';
start = s; /* build up macro name, find its end*/
while( !done ) {
switch( *s ) {
case '(': /* open macro brace */
case '{':
if( *s == sdelim ) {
lev++;
bflag++;
}
break;
case ':': /* halt at modifier */
if( lev == 1 ) {
done = TRUE;
mflag = 1;
}
break;
case ' ':
case '\t':
case '\n':
fflag = 1;
break;
case '\0': /* check for null */
*ps = s;
if( lev ) {
done = TRUE;
bflag = 0;
s = start;
}
break;
case ')': /* close macro brace */
case '}':
if( *s == edelim && lev ) --lev;
/*FALLTHROUGH*/
default:
done = !lev;
}
s++;
}
/* Check if this is a $A type macro. If so then we have to
* handle it a little differently. */
if( bflag )
macro_name = _substr( start+1, s-1 );
else
macro_name = _substr( start, s );
/* Check to see if the macro name contains spaces, if so then treat it
* as a GNU style function invocation and call the function mapper to
* deal with it. */
if( fflag )
result = Exec_function(macro_name);
else {
/* Check if the macro is a recursive macro name, if so then
* EXPAND the name before expanding the value */
if( strchr( macro_name, '$' ) != NIL(char) ) {
recurse_name = Expand( macro_name );
FREE( macro_name );
macro_name = recurse_name;
}
/* Code to do value expansion goes here, NOTE: macros whose assign bit
is one have been evaluated and assigned, they contain no further
expansions and thus do not need their values expanded again. */
if( (hp = GET_MACRO( macro_name )) != NIL(HASH) ) {
if( hp->ht_flag & M_MARK )
Fatal( "Detected circular macro [%s]", hp->ht_name );
/* for M_MULTI macro variable assignments */
If_multi = hp->ht_flag & M_MULTI;
if( !(hp->ht_flag & M_EXPANDED) ) {
hp->ht_flag |= M_MARK;
result = Expand( hp->ht_value );
hp->ht_flag ^= M_MARK;
}
else if( hp->ht_value != NIL(char) )
result = _strdup( hp->ht_value );
else
result = _strdup( "" );
/*
* Mark macros as used only if we are not expanding them for
* the purpose of a .IF test, so we can warn about redef after use*/
if( !If_expand ) hp->ht_flag |= M_USED;
}
else
result = _strdup( "" );
}
if( mflag ) {
char separator;
int modifier_list = 0;
int aug_mod = FALSE;
char *pat1;
char *pat2;
char *p;
/* Yet another brain damaged AUGMAKE kludge. We should accept the
* AUGMAKE bullshit of $(f:pat=sub) form of macro expansion. In
* order to do this we will forgo the normal processing if the
* AUGMAKE solution pans out, otherwise we will try to process the
* modifiers ala dmake.
*
* So we look for = in modifier string.
* If found we process it and not do the normal stuff */
for( p=s; *p && *p != '=' && *p != edelim; p++ );
if( *p == '=' ) {
pat1 = _substr( s, p );
for( s=p=p+1; (*p != edelim); p++ );
pat2 = _substr( s, p );
if( !Augmake ) {
char *tmp = pat2;
pat2 = Expand(pat2);
FREE(tmp);
}
result = Apply_edit( result, pat1, pat2, TRUE, TRUE );
FREE( pat1 );
FREE( pat2 );
s = p;
aug_mod = TRUE;
}
if( !aug_mod )
while( *s && *s != edelim ) { /* while not at end of macro */
switch( *s++ ) {
case 'b':
case 'B': modifier_list |= FILE_FLAG; break;
case 'd':
case 'D': modifier_list |= DIRECTORY_FLAG; break;
case 'f':
case 'F': modifier_list |= FILE_FLAG | SUFFIX_FLAG; break;
case 'S':
case 's':
if( modifier_list ) {
Warning( "Edit modifier must appear alone, ignored");
modifier_list = 0;
}
else {
separator = *s++;
for( p=s; *p != separator && *p != edelim; p++ );
if( *p == edelim )
Warning("Syntax error in edit pattern, ignored");
else {
char *t1, *t2;
pat1 = _substr( s, p );
for(s=p=p+1; (*p != separator) && (*p != edelim); p++ );
pat2 = _substr( s, p );
t1 = Expand(pat1); FREE(pat1);
t2 = Expand(pat2); FREE(pat2);
result = Apply_edit( result, t1, t2, TRUE, FALSE );
FREE( t1 );
FREE( t2 );
}
s = p;
}
/* find the end of the macro spec, or the start of a new
* modifier list for further processing of the result */
for( ; (*s != edelim) && (*s != ':'); s++ );
if( *s == ':' ) s++;
break;
case 'T':
case 't':
if( modifier_list ) {
Warning( "Tokenize modifier must appear alone, ignored");
modifier_list = 0;
}
else {
char *msg = "Separator string must be quoted";
separator = *s++;
if( separator != '\"' )
Warning( msg );
else {
/* we change the semantics to allow $(v:t")") */
for (p = s; *p && *p != separator; p++)
if (*p == '\\')
if (p[1] == '\\' || p[1] == '"')
p++;
if( *p == 0 )
Fatal( "Unterminated separator string" );
else {
pat1 = _substr( s, p );
result = Tokenize( result, pat1 );
FREE( pat1 );
}
s = p;
}
/* find the end of the macro spec, or the start of a new
* modifier list for further processing of the result */
for( ; (*s != edelim) && (*s != ':'); s++ );
if( *s == ':' ) s++;
}
break;
case ':':
if( modifier_list ) {
result = Apply_modifiers( modifier_list, result );
modifier_list = 0;
}
break;
default:
Warning( "Illegal modifier in macro, ignored" );
break;
}
}
if( modifier_list ) /* apply modifier */
result = Apply_modifiers( modifier_list, result );
s++;
}
*ps = s;
FREE( macro_name );
DB_RETURN( result );
}
static char*
_scan_brace( s, ps, flag )/*
============================
This routine scans for { token_list } pairs. It expands the value of
token_list by calling Expand on it. Token_list may be anything at all.
Note that the routine count's ballanced parentheses. This means you
cannot have something like { fred { joe }, if that is what you really
need the write it as { fred {{ joe }, flag is set to 1 if all ok
and to 0 if the braces were unballanced. */
char *s;
char **ps;
int *flag;
{
char *t;
char *start;
char *res;
int lev = 1;
int done = 0;
DB_ENTER( "_scan_brace" );
start = s;
while( !done )
switch( *s++ ) {
case '{':
if( *s == '{' ) break; /* ignore {{ */
lev++;
break;
case '}':
if( *s == '}' ) break; /* ignore }} */
if( lev )
if( --lev == 0 ) done = TRUE;
break;
case '$':
if( *s == '{' || *s == '}' ) {
if( (t = strchr(s,'}')) != NIL(char) )
s = t;
s++;
}
break;
case '\0':
if( lev ) {
done = TRUE;
s--;
/* error malformed macro expansion */
}
break;
}
start = _substr( start, (lev) ? s : s-1 );
if( lev ) {
/* Braces were not ballanced so just return the string.
* Do not expand it. */
res = _strjoin( "{", start, -1, FALSE );
*flag = 0;
}
else {
*flag = 1;
res = Expand( start );
if( (t = _strspn( res, " \t" )) != res ) strcpy( res, t );
}
FREE( start ); /* this is ok! start is assigned a _substr above */
*ps = s;
DB_RETURN( res );
}
static char*
_cross_prod( x, y )/*
=====================
Given two strings x and y compute the cross-product of the tokens found
in each string. ie. if x = "a b" and y = "c d" return "ac ad bc bd".
NOTE: buf will continue to grow until it is big enough to handle
all cross product requests. It is never freed! (maybe I
will fix this someday) */
char *x;
char *y;
{
static char *buf;
static int buf_siz = 0;
char *brkx;
char *brky;
char *cy;
char *cx;
char *res;
int i;
if( *x && *y ) {
res = _strdup( "" ); cx = x;
while( *cx ) {
cy = y;
brkx = _strpbrk( cx, " \t\n" );
if( (brkx-cx == 2) && *cx == '\"' && *(cx+1) == '\"' ) cx = brkx;
while( *cy ) {
brky = _strpbrk( cy, " \t\n" );
if( (brky-cy == 2) && *cy == '\"' && *(cy+1) == '\"' ) cy = brky;
i = brkx-cx + brky-cy + 2;
if( i > buf_siz ) { /* grow buf to the correct size */
if( buf != NIL(char) ) FREE( buf );
if( (buf = MALLOC( i, char )) == NIL(char)) No_ram();
buf_siz = i;
}
strncpy( buf, cx, (i = brkx-cx) );
buf[i] = '\0';
if (brky-cy > 0) strncat( buf, cy, brky-cy );
buf[i+(brky-cy)] = '\0';
strcat( buf, " " );
res = _strjoin( res, buf, -1, TRUE );
cy = _strspn( brky, " \t\n" );
}
cx = _strspn( brkx, " \t\n" );
}
FREE( x );
res[ strlen(res)-1 ] = '\0';
}
else
res = _strjoin( x, y, -1, TRUE );
FREE( y );
return( res );
}

78
dmake/extern.h Normal file
View File

@ -0,0 +1,78 @@
/* RCS -- $Header: /u/dvadura/src/generic/dmake/src/RCS/extern.h,v 1.2 1992/04/07 04:42:46 dvadura Exp $
-- SYNOPSIS -- external declarations for dmake functions.
--
-- DESCRIPTION
-- ANSI is a macro that allows the proper handling of ANSI style
-- function declarations.
--
-- AUTHOR
-- Dennis Vadura, dvadura@watdragon.uwaterloo.ca
-- CS DEPT, University of Waterloo, Waterloo, Ont., Canada
--
-- COPYRIGHT
-- Copyright (c) 1990 by Dennis Vadura. All rights reserved.
--
-- This program is free software; you can redistribute it and/or
-- modify it under the terms of the GNU General Public License
-- (version 1), as published by the Free Software Foundation, and
-- found in the file 'LICENSE' included with this distribution.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warrant of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program; if not, write to the Free Software
-- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
--
-- LOG
-- $Log: extern.h,v $
* Revision 1.2 1992/04/07 04:42:46 dvadura
* Changed namemax.h to posix.h.
*
* Revision 1.1 1992/01/24 03:26:52 dvadura
* dmake Version 3.8, Initial revision
*
*/
#ifndef EXTERN_h
#define EXTERN_h
/* Define this for the RS/6000 if it breaks something then we have to put a
* #ifdef around it. */
#if defined(rs6000)
#define _POSIX_SOURCE
#endif
#include <limits.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
#include <stdarg.h>
#if defined (_MPW)
# include <types.h>
# include <time.h>
#else
# include <sys/types.h>
# include <sys/stat.h>
#endif
#include <signal.h>
#include "itypes.h"
#include "stdmacs.h"
#include "alloc.h"
#include "db.h"
#include "dmake.h"
#include "struct.h"
#include "vextern.h"
#include "public.h"
/* Include this last as it invalidates some functions that are defined
* externally above and turns them into no-ops. Have to do this after
* the extern declarations however. */
#include "config.h"
#include "posix.h"
#endif

356
dmake/function.c Normal file
View File

@ -0,0 +1,356 @@
/* RCS -- $Header: /u2/dvadura/src/generic/dmake/src/RCS/function.c,v 1.1 1992/01/24 03:27:00 dvadura Exp $
-- SYNOPSIS -- GNU style functions for dmake.
--
-- DESCRIPTION
-- All GNU stule functions understood by dmake are implemented in this
-- file. Currently the only such function is $(mktmp ...) which is
-- not part of GNU-make is an extension provided by dmake.
--
-- AUTHOR
-- Dennis Vadura, dvadura@watdragon.uwaterloo.ca
-- CS DEPT, University of Waterloo, Waterloo, Ont., Canada
--
-- COPYRIGHT
-- Copyright (c) 1990 by Dennis Vadura. All rights reserved.
--
-- This program is free software; you can redistribute it and/or
-- modify it under the terms of the GNU General Public License
-- (version 1), as published by the Free Software Foundation, and
-- found in the file 'LICENSE' included with this distribution.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warrant of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program; if not, write to the Free Software
-- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
--
-- LOG
-- $Log: function.c,v $
* Revision 1.1 1992/01/24 03:27:00 dvadura
* dmake Version 3.8, Initial revision
*
*/
#include "extern.h"
static char *_exec_mktmp ANSI((char *, char *, char *));
static char *_exec_subst ANSI((char *, char *, char *));
static char *_exec_iseq ANSI((char *, char *, char *, int));
static char *_exec_sort ANSI((char *));
static char *_exec_shell ANSI((char *));
static int _mystrcmp ANSI((CONST PVOID, CONST PVOID));
PUBLIC char *
Exec_function(buf)/*
====================
Execute the function given by the value of args.
So far mktmp is the only valid function, anything else elicits and error
message. It is my hope to support the GNU style functions in this portion
of the code at some time in the future. */
char *buf;
{
char *fname;
char *args;
char *mod1;
char *mod2 = NIL(char);
char *res = NIL(char);
/* This must succeed since the presence of ' ', \t or \n is what
* determines if this functions is called in the first place. */
fname = _substr(buf, args=_strpbrk(buf," \t\n"));
if( (mod1 = strchr(fname,',')) != NIL(char) ){
*mod1 = '\0';
mod1++;
if( (mod2 = strchr(mod1,',')) != NIL(char) ){
*mod2 = '\0';
mod2++;
}
}
switch( *fname ) {
case 'e':
if(strncmp(fname,"eq",2) == 0) res = _exec_iseq(mod1,mod2,args,TRUE);
break;
case 'm':
if( strncmp(fname,"mktmp", 5) == 0 ) res = _exec_mktmp(mod1,mod2,args);
break;
case 'n':
if( strncmp(fname,"null", 4) == 0 )
res = _exec_iseq(mod1,NIL(char),args,TRUE);
break;
case '!':
if(strncmp(fname,"!null",5) == 0)
res = _exec_iseq(mod1,NIL(char),args,FALSE);
if(strncmp(fname,"!eq",3) == 0) res = _exec_iseq(mod1,mod2,args,FALSE);
break;
case 's':
if(strncmp(fname,"sort",4) == 0) res = _exec_sort(args);
else if(strncmp(fname,"shell",5)==0) res = _exec_shell(args);
else if(strncmp(fname,"strip",5)==0) res = Tokenize(Expand(args)," ");
else if(strncmp(fname,"subst",5)==0) res = _exec_subst(mod1,mod2,args);
break;
default:
Warning( "Function '%s' not implemented at this time", fname );
}
if( res == NIL(char) ) res = _strdup("");
FREE(fname);
return(res);
}
static char *
_exec_mktmp( file, text, data )
char *file;
char *text;
char *data;
{
register char *p;
char *tmpname;
char *name;
FILE *tmpfile = NIL(FILE);
/* This is only a test of the recipe line so prevent the tempfile side
* effects. */
if( Suppress_temp_file ) return(NIL(char));
name = Current_target ? Current_target->CE_NAME:"makefile text";
if( file && *file ) {
char *newtmp;
/* This call to Get_temp sets TMPFILE for subsequent expansion of file.
* DO NOT DELETE IT! */
Get_temp( &newtmp, "", FALSE ); FREE(newtmp);
tmpname = Expand(file);
if( *tmpname ) {
if( (tmpfile = fopen(tmpname, "w")) == NIL(FILE) )
Open_temp_error( tmpname, name );
Def_macro("TMPFILE", tmpname, M_EXPANDED|M_MULTI);
Link_temp( Current_target, tmpfile, tmpname );
}
else
FREE(tmpname);
}
if( !tmpfile )
tmpfile = Start_temp( "", Current_target, &tmpname );
if( !text || !*text ) text = tmpname;
data = Expand(_strspn(data, " \t\n"));
for(p=strchr(data,'\n'); p; p=strchr(p,'\n')) {
char *q = _strspn(++p," \t");
strcpy(p,q);
}
Append_line( data, FALSE, tmpfile, name, FALSE, TRUE );
Close_temp( Current_target, tmpfile );
FREE(data);
return( Expand(text) );
}
static char *
_exec_iseq( lhs, rhs, data, eq )
char *lhs;
char *rhs;
char *data;
int eq;
{
char *l = Expand(lhs);
char *r = Expand(rhs);
char *i = _strspn(data, " \t\n");
char *e = strchr(i, ' ');
char *res = NIL(char);
int val = strcmp(l,r);
if( (!val && eq) || (val && !eq) ) {
if( e != NIL(char) ) *e = '\0';
res = Expand(i);
}
else if( e != NIL(char) ) {
e = _strspn(e," \t\n");
if( *e ) res = Expand(e);
}
FREE(l);
FREE(r);
return(res);
}
static char *
_exec_sort( args )
char *args;
{
char *res = NIL(char);
char *data = Expand(args);
char **tokens = NIL(char *);
char *p;
char *white = " \t\n";
int j;
int i = 0;
for( i=0,p=_strspn(data,white); *p; p=_strspn(_strpbrk(p,white),white),i++);
if( i != 0 ) {
TALLOC(tokens, i, char *);
for( i=0,p=_strspn(data,white); *p; p=_strspn(p,white),i++){
tokens[i] = p;
p = _strpbrk(p,white);
if( *p ) *p++ = '\0';
}
qsort( tokens, i, sizeof(char *), _mystrcmp );
for( j=0; j<i; j++ ) res = _strapp(res, tokens[j]);
FREE(data);
FREE(tokens);
}
return(res);
}
static int
_mystrcmp( p, q )
CONST PVOID p;
CONST PVOID q;
{
return(strcmp(*((CONST char **)p),*((CONST char **)q)));
}
static char *
_exec_subst( pat, subst, data )
char *pat;
char *subst;
char *data;
{
char *res;
pat = Expand(pat);
subst = Expand(subst);
res = Apply_edit( Expand(data), pat, subst, TRUE, FALSE );
FREE(pat);
FREE(subst);
return(res);
}
static char *
_exec_shell( data )
char *data;
{
extern char *tempnam();
static int nestlevel = 0;
static int org_out;
static int bsize;
static char *buffer;
static char *tmpnm;
static FILE *tmp;
int wait = Wait_for_completion;
uint16 vflag = Verbose;
int tflag = Trace;
char *res = NIL(char);
CELL cell;
STRING rcp;
HASH cname;
if( Suppress_temp_file ) return(NIL(char));
/* Set the temp CELL used for building prerequisite candidates to
* all zero so that we don't have to keep initializing all the
* fields. */
{
register char *s = (char *) &cell;
register int n = sizeof(CELL);
while( n ) { *s++ = '\0'; n--; }
}
rcp.st_string = _strspn(data, " \t+-%@");
rcp.st_attr = Rcp_attribute( data );
rcp.st_next = NIL(STRING);
cname.ht_name = "Shell escape";
cell.ce_name = &cname;
cell.ce_fname = cname.ht_name;
cell.ce_recipe = &rcp;
cell.ce_flag = F_TARGET|F_RULES;
cell.ce_attr = A_PHONY|A_SILENT;
if( nestlevel == 0 ) {
tmpnm = tempnam(NIL(char),"mk");
org_out = dup(1);
if( (tmp = fopen(tmpnm, "w+")) == NIL(FILE) )
Open_temp_error( tmpnm, cname.ht_name );
close(1);
dup( fileno(tmp) );
bsize = (Buffer_size < BUFSIZ)?BUFSIZ:Buffer_size;
buffer = MALLOC(bsize,char);
}
Wait_for_completion = TRUE;
Verbose = V_NONE;
Trace = FALSE;
nestlevel++;
Exec_commands( &cell );
nestlevel--;
Trace = tflag;
Verbose = vflag;
Wait_for_completion = wait;
/* Now we have to read the temporary file, get the tokens and return them
* as a string. */
rewind(tmp);
while( fgets(buffer, bsize, tmp) ) {
char *p = strchr(buffer, '\n');
if( p == NIL(char) )
res = _strjoin(res,buffer,-1,TRUE);
else {
*p = '\0';
res = _strapp(res,buffer);
}
}
fclose(tmp);
if( nestlevel == 0 ) {
Remove_file(tmpnm);
close(1);
dup(org_out);
close(org_out);
FREE(tmpnm);
FREE(buffer);
}
else {
if( (tmp = fopen(tmpnm, "w+")) == NIL(FILE) )
Open_temp_error( tmpnm, cname.ht_name );
close(1);
dup( fileno(tmp) );
}
return(res);
}

531
dmake/getinp.c Normal file
View File

@ -0,0 +1,531 @@
/* RCS -- $Header: /u/dvadura/src/generic/dmake/src/RCS/getinp.c,v 1.2 1992/04/07 04:42:46 dvadura Exp $
-- SYNOPSIS -- handle reading of input.
--
-- DESCRIPTION
-- The code in this file reads the input from the specified stream
-- into the provided buffer of size Buffer_size. In doing so it deletes
-- comments. Comments are delimited by the #, and
-- <nl> character sequences. An exception is \# which
-- is replaced by # in the input. Line continuations are signalled
-- at the end of a line and are recognized inside comments.
-- The line continuation is always <\><nl>.
--
-- If the file to read is NIL(FILE) then the Get_line routine returns the
-- next rule from the builtin rule table if there is one.
--
-- AUTHOR
-- Dennis Vadura, dvadura@watdragon.uwaterloo.ca
-- CS DEPT, University of Waterloo, Waterloo, Ont., Canada
--
-- COPYRIGHT
-- Copyright (c) 1990 by Dennis Vadura. All rights reserved.
--
-- This program is free software; you can redistribute it and/or
-- modify it under the terms of the GNU General Public License
-- (version 1), as published by the Free Software Foundation, and
-- found in the file 'LICENSE' included with this distribution.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warrant of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program; if not, write to the Free Software
-- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
--
-- LOG
-- $Log: getinp.c,v $
* Revision 1.2 1992/04/07 04:42:46 dvadura
* Minor clean up and a check for -X flag on the execution of #! lines.
*
* Revision 1.1 1992/01/24 03:27:56 dvadura
* dmake Version 3.8, Initial revision
*
*/
#include "extern.h"
#define IS_WHITE(A) ((A == ' ') || (A == '\t') || (A == '\n') || (A == '\r'))
#define SCAN_WHITE(A) \
while( IS_WHITE(*A) ) A++;
static int _is_conditional ANSI((char*));
static int _handle_conditional ANSI((int, TKSTRPTR));
static int rule_ind = 0; /* index of rule when reading Rule_tab */
static int skip = FALSE; /* if true the skip input */
PUBLIC int
Get_line( buf, fil )/*
======================
Read a line of input from the file stripping
off comments. The routine returns TRUE if EOF */
char *buf;
FILE *fil;
{
extern char **Rule_tab;
register char *p;
register char *c;
char *q;
char *buf_org;
static int ignore = FALSE;
int cont = FALSE;
int pos = 0;
int res;
DB_ENTER( "Get_line" );
if( fil == NIL(FILE) ) {
/* Reading the internal rule table. Set the rule_index to zero.
* This way ReadEnvironment works as expected every time. */
while( (p = Rule_tab[ rule_ind++ ]) != NIL(char) )
/* The last test in this if '*p != '~', handles the environment
* passing conventions used by MKS to pass arguments. We want to
* skip those environment entries. */
if( !Readenv || (Readenv && (strchr(p,'=') != NIL(char)) && *p!='~')){
strcpy( buf, p );
DB_PRINT( "io", ("Returning [%s]", buf) );
DB_RETURN( FALSE );
}
rule_ind = 0;
DB_PRINT( "io", ("Done Ruletab") );
DB_RETURN( TRUE );
}
buf_org = buf;
do_again:
do {
p = buf+pos;
if(feof( fil ) || (fgets( p, Buffer_size-pos, fil ) == NIL(char)))
DB_RETURN( TRUE );
Line_number++;
/* ignore input if ignore flag set and line ends in a continuation
character. */
q = p+strlen(p)-2;
if( q<p ) q=p;
/* ignore each RETURN at the end of a line before any further
* processing */
if( q[0] == '\r' && q[1] == '\n' ) {
q[0] = '\n';
q[1] = '\0';
q--;
}
/* you also have to deal with END_OF_FILE chars to process raw
* DOS-Files. Normally they are the last chars in file, but after
* working on these file with vi, there is an additional NEWLINE
* after the last END_OF_FILE. So if the second last char in the
* actual line is END_OF_FILE, you can skip the last char. Then
* you can search the line back until you find no more END_OF_FILE
* and nuke each you found by string termination. */
if( q[0] == '\032' )
q--;
while( q[1] == '\032' ) {
q[1] = '\0';
q--;
}
if( ignore ) {
if( q[0] != CONTINUATION_CHAR || q[1] != '\n' ) ignore = FALSE;
*p = '\0';
continue;
}
c = Do_comment(p, &q, Group || (*buf == '\t'));
/* Does the end of the line end in a continuation sequence? */
if( (q[0] == CONTINUATION_CHAR) && (q[1] == '\n')) {
/* If the continuation was at the end of a comment then ignore the
* next input line, (or lines until we get one ending in just <nl>)
* else it's a continuation, so build the input line from several
* text lines on input. The maximum size of this is governened by
* Buffer_size */
if( q != p && q[-1] == CONTINUATION_CHAR ) {
strcpy( q, q+1 );
q--;
cont = FALSE;
}
else if( c != NIL(char) )
ignore = TRUE;
else
cont = TRUE;
}
else {
cont = FALSE;
}
q = ( c == NIL(char) ) ? q+2 : c;
pos += q-p;
}
while( (cont || !*buf) && (pos <= Buffer_size) );
if( buf[ pos-1 ] == '\n' )
buf[ --pos ] = '\0';
else
if( pos == Buffer_size-1 )
Fatal( "Input line too long, increase MAXLINELENGTH" );
/* Now that we have the next line of input to make, we should check to
* see if it is a conditional expression. If it is then process it,
* otherwise pass it on to the parser. */
if( *(p = _strspn(buf, " \t\r\n")) == CONDSTART ) {
TKSTR token;
SET_TOKEN( &token, p );
p = Get_token( &token, "", FALSE );
if( (res = _is_conditional( p )) ) /* ignore non control special */
{ /* targets */
res = _handle_conditional( res, &token );
skip = TRUE;
}
else {
CLEAR_TOKEN( &token );
res = TRUE;
}
}
if( skip ) {
buf = buf_org; /* ignore line just read in */
pos = 0;
skip = res;
goto do_again;
}
DB_PRINT( "io", ("Returning [%s]", buf) );
DB_RETURN( FALSE );
}
PUBLIC char *
Do_comment(str, pend, keep)/*
=============================
Search the input string looking for comment chars. If it contains
comment chars then NUKE the remainder of the line, if the comment
char is preceeded by \ then shift the remainder of the line left
by one char. */
char *str;
char **pend;
int keep;
{
char *c = str;
while( (c = strchr(c, COMMENT_CHAR)) != NIL(char) ) {
if( Comment || State == NORMAL_SCAN )
if( c != str && c[-1] == ESCAPE_CHAR ) {
strcpy( c-1, c ); /* copy it left, due to \# */
if( pend ) (*pend)--; /* shift tail pointer left */
}
else {
if( !No_exec
&& c == str
&& c[1] == '!'
&& Line_number == 1
&& Nestlevel() == 1 ) {
char *cmnd;
cmnd = Expand(c+2);
cmnd[strlen(cmnd)-1] = '\0'; /* strip last newline */
Current_target = Root;
Swap_on_exec = TRUE;
Wait_for_completion = TRUE;
Do_cmnd(cmnd, FALSE, TRUE, Current_target, FALSE, FALSE, TRUE);
}
*c = '\0'; /* a true comment so break */
break;
}
else {
if( keep )
c = NIL(char);
else
*c = '\0';
break;
}
}
return(c);
}
PUBLIC char *
Get_token( string, brk, anchor )/*
==================================
Return the next token in string.
Returns empty string when no more tokens in string.
brk is a list of chars that also cause breaks in addition to space and
tab, but are themselves returned as tokens. if brk is NULL then the
remainder of the line is returned as a single token.
anchor if 1, says break on chars in the brk list, but only if
the entire token begins with the first char of the brk list, if
0 then any char of brk will cause a break to occurr.
If anchor is 2, then break only seeing the first char in the break
list allowing only chars in the break list to form the prefix. */
TKSTRPTR string;
char *brk;
int anchor;
{
register char *s;
register char *curp;
register char *t;
int done = FALSE;
char space[10];
DB_ENTER( "Get_token" );
s = string->tk_str; /* Get string parameters */
*s = string->tk_cchar; /* ... and strip leading w/s */
SCAN_WHITE( s );
DB_PRINT( "tok", ("What's left [%s]", s) );
if( !*s ) {
DB_PRINT( "tok", ("Returning NULL token") );
DB_RETURN( "" );
}
/* Build the space list. space contains all those chars that may possibly
* cause breaks. This includes the brk list as well as white space. */
if( brk != NIL(char) ) {
strcpy( space, " \t\r\n" );
strcat( space, brk );
}
else {
space[0] = 0xff; /* a char we know will not show up */
space[1] = 0;
}
/* Handle processing of quoted tokens. Note that this is disabled if
* brk is equal to NIL */
while( *s == '\"' && ((brk != NIL(char)) || !string->tk_quote) ) {
s++;
if( string->tk_quote ) {
curp = s-1;
do { curp = strchr( curp+1, '\"' ); }
while( (curp != NIL(char)) && (*(curp+1) == '\"'));
if( curp == NIL(char) ) Fatal( "Unmatched quote in token" );
string->tk_quote = !string->tk_quote;
/* Check for "" case, and if found ignore it */
if( curp == s ) continue;
goto found_token;
}
else
SCAN_WHITE( s );
string->tk_quote = !string->tk_quote;
}
/* Check for a token break character at the beginning of the token.
* If found return the next set of break chars as a token. */
if( anchor == 2 && brk != NIL(char) ) {
curp = s;
while( *curp && (strchr(brk,*curp)!=NIL(char)) && (*curp!=*brk) ) curp++;
done = (*brk == *curp++);
}
else if( (brk != NIL(char)) && (strchr( brk, *s ) != NIL(char)) ) {
curp = _strspn( s, brk );
done = (anchor == 0) ? TRUE :
((anchor == 1)?(*s == *brk) : (*brk == curp[-1]));
}
/* Scan for the next token in the list and return it less the break char
* that was used to terminate the token. It will possibly be returned in
* the next call to Get_token */
if( !done ) {
SCAN_WHITE( s );
t = s;
do {
done = TRUE;
curp = _strpbrk(t, space);
if( anchor && *curp && !IS_WHITE( *curp ) )
if( ((anchor == 1)?*curp:_strspn(curp,brk)[-1]) != *brk ) {
t++;
done = FALSE;
}
}
while( !done );
if( (curp == s) && (strchr(brk, *curp) != NIL(char)) ) curp++;
}
found_token:
string->tk_str = curp;
string->tk_cchar = *curp;
*curp = '\0';
DB_PRINT( "tok", ("Returning [%s]", s) );
DB_RETURN( s );
}
static int
_is_conditional( tg )/*
=======================
Look at tg and return it's value if it is a conditional identifier
otherwise return 0. */
char *tg;
{
DB_ENTER( "_is_conditional" );
tg++;
switch( *tg ) {
case 'I': if( !strcmp( tg, "IF" )) DB_RETURN( ST_IF ); break;
case 'E':
if( !strcmp( tg, "END" )) DB_RETURN( ST_END );
else if( !strcmp( tg, "ENDIF")) DB_RETURN( ST_END );
else if( !strcmp( tg, "ELSE" )) DB_RETURN( ST_ELSE );
else if( !strcmp( tg, "ELIF" )) DB_RETURN( ST_ELIF );
break;
}
DB_RETURN( 0 );
}
#define SEEN_END 0x00
#define SEEN_IF 0x01
#define SEEN_ELSE 0x02
#define SEEN_ELIF 0x04
#define ACCEPT_IF 0x10
#define ACCEPT_ELIF 0x20
static int
_handle_conditional( opcode, tg )/*
===================================
Perform the necessary processing for .IF conditinal targets.
Someday this should be modified to do bracketted expressions ala
CPP... sigh */
int opcode;
TKSTRPTR tg;
{
static short action[MAX_COND_DEPTH];
static char ifcntl[MAX_COND_DEPTH];
char *tok, *lhs, *rhs, *op, *expr;
int result;
DB_ENTER( "_handle_conditional" );
switch( opcode ) {
case ST_ELIF:
if( !(ifcntl[Nest_level] & SEEN_IF) || (ifcntl[Nest_level]&SEEN_ELSE) )
Fatal(".ELIF without a preceeding .IF" );
/* FALLTHROUGH */
case ST_IF:
if( opcode == ST_IF && (Nest_level+1) == MAX_COND_DEPTH )
Fatal( ".IF .ELSE ... .END nesting too deep" );
If_expand = TRUE;
expr = Expand( Get_token( tg, NIL(char), FALSE ));
If_expand = FALSE;
lhs = _strspn( expr, " \t" );
if( !*lhs ) lhs = NIL(char);
if( (op = _strstr( lhs, "==" )) == NIL(char) )
op = _strstr( lhs, "!=" );
if( op == NIL(char) )
result = (lhs != NIL(char));
else {
op[1] = op[0];
if( lhs != op ) {
for( tok = op-1; (tok != lhs) && ((*tok == ' ')||(*tok == '\t'));
tok-- );
tok[1] = '\0';
}
else
lhs = NIL(char);
op++;
rhs = _strspn( op+1, " \t" );
if( !*rhs ) rhs = NIL(char);
if( (rhs == NIL(char)) || (lhs == NIL(char)) )
result = (rhs == lhs) ? TRUE : FALSE;
else {
tok = rhs + strlen( rhs );
for( tok=tok-1; (tok != lhs) && ((*tok == ' ')||(*tok == '\t'));
tok--);
tok[1] = '\0';
result = (strcmp( lhs, rhs ) == 0) ? TRUE : FALSE;
}
if( *op == '!' ) result = !result;
}
if( expr != NIL(char) ) FREE( expr );
if( opcode == ST_IF ) {
Nest_level++;
action[Nest_level] = 1;
}
ifcntl[Nest_level] |= (opcode==ST_IF)?SEEN_IF:SEEN_ELIF;
if( result ) {
if( !(ifcntl[Nest_level] & (ACCEPT_IF|ACCEPT_ELIF)) ) {
action[ Nest_level ] = action[ Nest_level-1 ];
ifcntl[Nest_level] |= (opcode==ST_IF)?ACCEPT_IF:ACCEPT_ELIF;
}
else
action[Nest_level] = 1;
}
else
action[Nest_level] = 1;
break;
case ST_ELSE:
if( Nest_level <= 0 ) Fatal( ".ELSE without .IF" );
if( ifcntl[Nest_level] & SEEN_ELSE )
Fatal( "Missing .IF or .ELIF before .ELSE" );
if( ifcntl[Nest_level] & (ACCEPT_IF|ACCEPT_ELIF) )
action[Nest_level] = 1;
else if( action[ Nest_level-1 ] != 1 )
action[ Nest_level ] ^= 0x1; /* flip between 0 and 1 */
ifcntl[Nest_level] |= SEEN_ELSE;
break;
case ST_END:
ifcntl[Nest_level] = SEEN_END;
Nest_level--;
if( Nest_level < 0 ) Fatal( "Unmatched .END[IF]" );
break;
}
DB_RETURN( action[ Nest_level ] );
}

61
dmake/hash.c Normal file
View File

@ -0,0 +1,61 @@
/* RCS -- $Header: /u2/dvadura/src/generic/dmake/src/RCS/hash.c,v 1.1 1992/01/24 03:27:06 dvadura Exp $
-- SYNOPSIS -- hashing function for hash tables.
--
-- DESCRIPTION
-- Hash an identifier. The hashing function works by computing the sum
-- of each char and the previous hash value multiplied by 129. Finally the
-- length of the identifier is added in. This way the hash depends on the
-- chars as well as the length, and appears to be sufficiently unique,
-- and is FAST to COMPUTE, unlike the previous hash function...
--
-- AUTHOR
-- Dennis Vadura, dvadura@watdragon.uwaterloo.ca
-- CS DEPT, University of Waterloo, Waterloo, Ont., Canada
--
-- COPYRIGHT
-- Copyright (c) 1990 by Dennis Vadura. All rights reserved.
--
-- This program is free software; you can redistribute it and/or
-- modify it under the terms of the GNU General Public License
-- (version 1), as published by the Free Software Foundation, and
-- found in the file 'LICENSE' included with this distribution.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warrant of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program; if not, write to the Free Software
-- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
--
-- LOG
-- $Log: hash.c,v $
* Revision 1.1 1992/01/24 03:27:06 dvadura
* dmake Version 3.8, Initial revision
*
*/
#include "extern.h"
PUBLIC uint16
Hash( id, phv )/*
=================
This function computes the identifier's hash value and returns the hash
value modulo the key size as well as the full hash value. The reason
for returning both is so that hash table searches can be sped up. You
compare hash keys instead and compare strings only for those whose 32-bit
hash keys match. (not many) */
char *id;
uint32 *phv;
{
register char *p = id;
register uint32 hash = (uint32) 0;
while( *p ) hash = (hash << 7) + hash + (uint32) (*p++);
*phv = hash = hash + (uint32) (p-id);
return( (uint16) (hash % HASH_TABLE_SIZE) );
}

172
dmake/imacs.c Normal file
View File

@ -0,0 +1,172 @@
/* RCS -- $Header: /u2/dvadura/src/generic/dmake/src/RCS/imacs.c,v 1.1 1992/01/24 03:29:55 dvadura Exp $
-- SYNOPSIS -- define default internal macros.
--
-- DESCRIPTION
-- This file adds to the internal macro tables the set of default
-- internal macros, and for those that are accessible internally via
-- variables creates these variables, and initializes them to point
-- at the default values of these macros.
--
-- AUTHOR
-- Dennis Vadura, dvadura@watdragon.uwaterloo.ca
-- CS DEPT, University of Waterloo, Waterloo, Ont., Canada
--
-- COPYRIGHT
-- Copyright (c) 1990 by Dennis Vadura. All rights reserved.
--
-- This program is free software; you can redistribute it and/or
-- modify it under the terms of the GNU General Public License
-- (version 1), as published by the Free Software Foundation, and
-- found in the file 'LICENSE' included with this distribution.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warrant of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program; if not, write to the Free Software
-- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
--
-- LOG
-- $Log: imacs.c,v $
* Revision 1.1 1992/01/24 03:29:55 dvadura
* dmake Version 3.8, Initial revision
*
*/
#include "extern.h"
static void _set_int_var ANSI((char *, char *, int, int *));
static void _set_string_var ANSI((char *, char *, int, char **));
static void _set_bit_var ANSI((char *, char *, int));
/*
** Arrange to parse the strings stored in Rules[]
*/
PUBLIC void
Make_rules()
{
Parse(NIL(FILE));
}
#define M_FLAG M_DEFAULT | M_EXPANDED
/*
** Add to the macro table all of the internal macro variables plus
** create secondary variables which will give access to their values
** easily, both when needed and when the macro value is modified.
** The latter is accomplished by providing a flag in the macro and a field
** which gives a pointer to the value if it is a char or string macro value
** and a mask representing the bit of the global flag register that is affected
** by this macro's value.
*/
PUBLIC void
Create_macro_vars()
{
static char* switchar;
char swchar[2];
swchar[0] = Get_switch_char(), swchar[1] = '\0';
_set_string_var("SWITCHAR", swchar, M_PRECIOUS, &switchar);
_set_string_var("DIRSEPSTR", (*swchar=='/')?"\\":"/",M_PRECIOUS,&DirSepStr);
_set_string_var("DIRBRKSTR", DirBrkStr, M_PRECIOUS, &DirBrkStr);
swchar[0] = DEF_ESCAPE_CHAR, swchar[1] = '\0';
_set_string_var(".ESCAPE_PREFIX", swchar, M_FLAG, &Escape_char);
_set_bit_var(".SILENT", "", A_SILENT );
_set_bit_var(".IGNORE", "", A_IGNORE );
_set_bit_var(".PRECIOUS", "", A_PRECIOUS);
_set_bit_var(".EPILOG", "", A_EPILOG );
_set_bit_var(".PROLOG", "", A_PROLOG );
_set_bit_var(".NOINFER", "", A_NOINFER );
_set_bit_var(".SEQUENTIAL","",A_SEQ );
_set_bit_var(".USESHELL", "", A_SHELL );
_set_bit_var(".SWAP", "", A_SWAP );
_set_bit_var(".MKSARGS", "", A_MKSARGS );
Glob_attr = A_DEFAULT; /* set all flags to NULL */
_set_string_var("SHELL", "", M_DEFAULT, &Shell );
_set_string_var("SHELLFLAGS", " ", M_DEFAULT, &Shell_flags );
_set_string_var("GROUPSHELL", "", M_DEFAULT, &GShell );
_set_string_var("GROUPFLAGS", " ", M_DEFAULT, &GShell_flags);
_set_string_var("SHELLMETAS", "", M_DEFAULT, &Shell_metas );
_set_string_var("GROUPSUFFIX", "", M_DEFAULT, &Grp_suff );
_set_string_var("PREP", "0", M_DEFAULT, &Prep );
_set_string_var("AUGMAKE",NIL(char), M_DEFAULT, &Augmake );
_set_string_var(".KEEP_STATE", "", M_DEFAULT, &Keep_state );
_set_string_var(".NOTABS", "", M_MULTI, &Notabs );
_set_string_var(".SETDIR", "", M_DEFAULT|M_NOEXPORT, &Start_dir );
_set_string_var("MAKEDIR",Get_current_dir(),M_PRECIOUS|M_NOEXPORT,&Makedir);
_set_string_var("PWD", Makedir, M_DEFAULT|M_NOEXPORT, &Pwd);
_set_string_var("TMD", "", M_DEFAULT|M_NOEXPORT, &Tmd);
Def_macro("NULL", "", M_PRECIOUS|M_NOEXPORT|M_FLAG);
_set_int_var( "MAXLINELENGTH", "0", M_DEFAULT|M_NOEXPORT, &Buffer_size );
(void) Def_macro("MAXLINELENGTH", "0", M_FLAG | M_DEFAULT);
/* set MAXPROCESSLIMIT high initially so that it allows MAXPROCESS to
* change from command line. */
_set_int_var( "MAXPROCESSLIMIT", "100", M_DEFAULT|M_NOEXPORT, &Max_proclmt );
_set_int_var( "MAXPROCESS", "1", M_DEFAULT|M_NOEXPORT, &Max_proc );
}
/*
** Define an integer variable value, and set up the macro.
*/
static void
_set_int_var(name, val, flag, var)
char *name;
char *val;
int flag;
int *var;
{
HASHPTR hp;
hp = Def_macro(name, val, M_FLAG | flag);
hp->ht_flag |= M_VAR_INT | M_MULTI;
hp->MV_IVAR = var;
*var = atoi(val);
}
/*
** Define a string variables value, and set up the macro.
*/
static void
_set_string_var(name, val, flag, var)
char *name;
char *val;
int flag;
char **var;
{
HASHPTR hp;
hp = Def_macro(name, val, M_FLAG | flag);
hp->ht_flag |= M_VAR_STRING | M_MULTI;
hp->MV_SVAR = var;
*var = hp->ht_value;
}
/*
** Define a bit variable value, and set up the macro.
*/
static void
_set_bit_var(name, val, mask)
char *name;
char *val;
int mask;
{
HASHPTR hp;
hp = Def_macro(name, val, M_FLAG);
hp->ht_flag |= M_VAR_BIT | M_MULTI;
hp->MV_MASK = mask;
hp->MV_BVAR = &Glob_attr;
}

822
dmake/infer.c Normal file
View File

@ -0,0 +1,822 @@
/* RCS -- $Header: /u2/dvadura/src/generic/dmake/src/RCS/infer.c,v 1.1 1992/01/24 03:27:21 dvadura Exp $
-- SYNOPSIS -- infer how to make a target.
--
-- DESCRIPTION
-- This file contains the code to infer a recipe, and possibly some new
-- prerequisites for a target which dmake does not know how to make, or
-- has no explicit recipe.
--
-- The inference fails if no path through the inference graph can be
-- found by which we can make the target.
--
-- AUTHOR
-- Dennis Vadura, dvadura@watdragon.uwaterloo.ca
-- CS DEPT, University of Waterloo, Waterloo, Ont., Canada
--
-- COPYRIGHT
-- Copyright (c) 1990 by Dennis Vadura. All rights reserved.
--
-- This program is free software; you can redistribute it and/or
-- modify it under the terms of the GNU General Public License
-- (version 1), as published by the Free Software Foundation, and
-- found in the file 'LICENSE' included with this distribution.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warrant of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program; if not, write to the Free Software
-- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
--
-- LOG
-- $Log: infer.c,v $
* Revision 1.1 1992/01/24 03:27:21 dvadura
* dmake Version 3.8, Initial revision
*
*/
#include "extern.h"
/* attributes that get transfered from the % start cell to the inferred
* cells. */
#define A_TRANSFER (A_EPILOG | A_PRECIOUS | A_SILENT | A_SHELL | A_SETDIR |\
A_SEQ | A_LIBRARY | A_IGNORE | A_PROLOG | A_SWAP |\
A_NOSTATE )
/* Define local static functions */
static DFALINKPTR _dfa_subset ANSI((DFALINKPTR, DFASETPTR));
static void _free_dfas ANSI((DFALINKPTR));
static int _count_dots ANSI((char *));
static char * _build_name ANSI((char *, char *, char *));
static void _free_icells ANSI(());
static ICELLPTR _union_iset ANSI((ICELLPTR, ICELLPTR));
static ICELLPTR _add_iset ANSI((ICELLPTR,ICELLPTR,CELLPTR,DFALINKPTR,
CELLPTR,int,int,char *,char *, int));
static ICELLPTR _derive_prerequisites ANSI((ICELLPTR, ICELLPTR *));
static char * _dump_inf_chain ANSI((ICELLPTR, int, int));
static int _prep = -1; /* Integer value of Prep variable */
PUBLIC void
Infer_recipe( cp, setdirroot )/*
================================
Perform a breadth-first search of the inference graph and return if
possible an inferred set of prerequisites for making the current target.
*/
CELLPTR cp;
CELLPTR setdirroot;
{
ICELLPTR nomatch, match;
DB_ENTER("Infer_recipe");
if( cp->ce_attr & A_NOINFER ) {DB_VOID_RETURN;}
if( _prep == -1 ) _prep = atoi(Prep); /* _dfa_subset needs _prep */
match = NIL(ICELL);
nomatch = _add_iset( NIL(ICELL), NIL(ICELL), NIL(CELL), NIL(DFALINK),
setdirroot, _prep+_count_dots(cp->CE_NAME), 0,
_strdup(cp->CE_NAME), NIL(char),
cp->ce_time != (time_t)0L);
/* Make sure we try whole heartedly to infer at least one suffix */
if( nomatch->ic_dmax == 0 ) ++nomatch->ic_dmax;
DB_EXECUTE( "inf", _dump_iset("nomatch",nomatch); );
while( nomatch != NIL(ICELL) ) {
ICELLPTR new_nomatch = NIL(ICELL);
ICELLPTR ic, pmatch, mmatch;
CELLPTR prereq;
int first;
for( ic=nomatch; ic != NIL(ICELL); ic=ic->ic_next ) {
int ipush = FALSE;
if( ic->ic_dir ) ipush = Push_dir(ic->ic_dir, ic->ic_name, FALSE);
match = _union_iset(match, _derive_prerequisites(ic, &new_nomatch));
if( ipush ) Pop_dir(FALSE);
}
DB_EXECUTE( "inf", _dump_iset("match",match); );
DB_EXECUTE( "inf", _dump_iset("nomatch",new_nomatch); );
/* We have now deduced the two sets MATCH and NOMATCH. MATCH holds the
* set of edges that we encountered that matched. If this set is empty
* then we can apply transitive closure (if enabled) to the elements of
* NOMATCH to see if we can find some other method to make the target.
*
* If MATCH is non-empty, we have found a method for making the target.
* It is the shortest method for doing so (ie. uses fewest number of
* steps). If MATCH contains more than one element then we have a
* possible ambiguity.
*/
if( match == NIL(ICELL) ) {
nomatch = new_nomatch;
if( Transitive ) continue;
goto all_done;
}
/* Ok, we have a set of possible matches in MATCH, we should check the
* set for ambiguity. If more than one inference path exists of the
* same depth, then we may issue an ambigous inference error message.
*
* The message is suppressed if MATCH contains two elements and one of
* them is the empty-prerequisite-rule. In this case we ignore the
* ambiguity and take the rule that infers the prerequisite.
*
* Also if there are any chains that rely on a non-existant prerequisite
* that may get made because it has a recipe then we prefer any that
* rely on existing final prerequisites over those that we have to make.
*
* NOTE: May turn this around at some point.
*/
/* Split out those that have to be made from those that end in
* prerequisites that already exist. */
pmatch = mmatch = NIL(ICELL);
for(; match; match = ic ) {
ic = match->ic_next;
match->ic_next = NIL(ICELL);
if( match->ic_exists )
pmatch = _union_iset(pmatch, match);
else
mmatch = _union_iset(mmatch, match);
}
if( pmatch )
match = pmatch;
else
match = mmatch;
/* Make sure it is unique */
if( match->ic_next != NIL(ICELL) ) {
int dump = (match->ic_next->ic_next != NIL(ICELL));
/* Check for definite ambiguity */
if( !dump )
if( (match->ic_meta->ce_prq && match->ic_next->ic_meta->ce_prq) ||
(!match->ic_meta->ce_prq && !match->ic_next->ic_meta->ce_prq) )
dump = TRUE;
else if(!match->ic_meta->ce_prq && match->ic_next->ic_meta->ce_prq )
match = match->ic_next;
if( dump ) {
int count = 1;
Continue = TRUE;
Error( "Ambiguous inference chains for target '%s'", cp->CE_NAME );
for( ic=match; ic; ic=ic->ic_next )
(void) _dump_inf_chain(ic, TRUE, count++);
Fatal( "resolve ambiguity before proceeding.");
/*NOTREACHED*/
}
}
/* MATCH now points at the derived recipe. We must now take cp, and
* construct the correct graph so that the make may proceed. */
if( Verbose & V_INFER ) {
char *tmp = _dump_inf_chain(match, TRUE, FALSE);
printf("%s: Inferring prerequistes and recipes using:\n%s: ... %s\n",
Pname, Pname, tmp );
FREE(tmp);
}
pmatch = NIL(ICELL);
prereq = NIL(CELL);
first = TRUE;
while( match ) {
CELLPTR infcell=NIL(CELL);
/* Compute the inferred prerequisite first. */
if( match->ic_name ) {
if( match->ic_meta )
infcell = Def_cell( match->ic_name );
else
infcell = cp;
infcell->ce_flag |= F_TARGET;
if( infcell != cp ) {
infcell->ce_flag |= F_INFER;
if( !first ) infcell->ce_flag |= F_REMOVE;
}
if( !match->ic_flag )
infcell->ce_attr |= A_NOINFER;
first = FALSE;
}
/* Add global prerequisites from previous rule if there are any and
* the recipe. */
if( pmatch ) {
CELLPTR imeta = pmatch->ic_meta;
LINKPTR lp;
infcell->ce_per = pmatch->ic_dfa->dl_per;
infcell->ce_attr |= (imeta->ce_attr & A_TRANSFER);
if( !(infcell->ce_flag & F_RULES) ) {
infcell->ce_flag |= (imeta->ce_flag&(F_SINGLE|F_GROUP))|F_RULES;
infcell->ce_recipe = imeta->ce_recipe;
}
pmatch->ic_dfa->dl_per = NIL(char);
/* If infcell already had a directory set then modify it based on
* whether it was the original cell or some intermediary. */
if( imeta->ce_dir )
if( infcell->ce_dir && infcell == cp ) {
/* cp->ce_dir was set and we have pushed the directory prior
* to calling this routine. We should therefore pop it and
* push the new concatenated directory required by the
* inference. */
infcell->ce_dir=_strdup(Build_path(infcell->ce_dir,
imeta->ce_dir));
}
else
infcell->ce_dir = imeta->ce_dir;
for( lp=imeta->ce_indprq; lp != NIL(LINK); lp=lp->cl_next ) {
char *name = lp->cl_prq->CE_NAME;
CELLPTR tcp;
name = _build_name( cp->CE_NAME, name, infcell->ce_per );
tcp = Def_cell( name );
tcp->ce_flag |= F_REMOVE;
Add_prerequisite( infcell, tcp, FALSE, FALSE );
if( Verbose & V_INFER )
printf( "%s: Inferred indirect prerequisite [%s]\n",
Pname, name );
FREE(name);
}
}
/* Add the previous cell as the prerequisite */
if( prereq )
(Add_prerequisite(infcell,prereq,FALSE,FALSE))->cl_flag |= F_TARGET;
pmatch = match;
prereq = infcell;
match = match->ic_parent;
}
DB_PRINT("inf", ("Terminated due to a match"));
break;
}
all_done:
_free_icells();
DB_VOID_RETURN;
}
static ICELLPTR
_derive_prerequisites( ic, nnmp )/*
===================================
Take a cell and derive a set of prerequisites from the cell. Categorize
them into those that MATCH (ie. those that we found in the file system),
and those that do not match NOMATCH that we may possibly have a look at
later. When we process the next level of the breadth-first search.
Once MATCH is non-empty we will stop inserting elements into NOMATCH
since we know that either MATCH is successful and unique or it will
issue an ambiguity error. We will never go on to look at elements
in NOMATCH after wards. */
ICELLPTR ic;
ICELLPTR *nnmp;
{
ICELLPTR match = NIL(ICELL);
DFALINKPTR pdfa;
DFALINKPTR dfas;
DB_ENTER("_derive_prerequisites");
/* If none of the inference nodes match then forget about the inference.
* The user did not tell us how to make such a target. We also stop the
* Inference if the new set of DFA's is a proper subset of a previous
* subset and it's PREP counts exceed the value of Prep.
*/
dfas = _dfa_subset( Match_dfa(ic->ic_name), &ic->ic_dfastack );
DB_EXECUTE("inf", _dump_dfa_stack(dfas, &ic->ic_dfastack); );
/* Ok, we have nothing here to work with so return an empty cell. */
if( dfas == NIL(DFALINK) ) {
DB_PRINT( "mem", ("%s:<- mem %ld",ic->ic_name, (long)coreleft()));
DB_PRINT( "inf", ("<<< Exit, no dfas, cp = %04x", NIL(CELL)) );
DB_RETURN( NIL(ICELL) );
}
/* Save the dfas, we are going to use on the stack for this cell. */
ic->ic_dfastack.df_set = dfas;
/* Run through the %-meta cells, build the prerequisite cells. For each
* %-meta go through it's list of edges and try to use each in turn to
* decuce a likely prerequisite. We perform a breadth-first search
* matching the first path that results in a unique method for making the
* target. */
for( pdfa = dfas; pdfa != NIL(DFALINK); pdfa = pdfa->dl_next ) {
LINK tl;
LINKPTR edge;
CELLPTR pmeta;
pmeta = pdfa->dl_meta;
DB_PRINT( "inf", ("Using dfa: [%s]", pmeta->CE_NAME) );
/* If the %-meta is a singleton meta then deal with it differently from
* the case when it is a bunch of %-meta's found on the original entries
* prerequisite list. */
if( pmeta->ce_flag & F_MULTI )
edge = pmeta->ce_prq;
else {
tl.cl_prq = pmeta;
tl.cl_next = NIL(LINK);
edge = &tl;
}
/* Now run through the list of prerequisite edge's for the %-meta. */
for( ; edge != NIL(LINK); edge = edge->cl_next ) {
HASHPTR thp; /* temporary hash table pointer */
HASH iprqh; /* hash cell for new prerequisite */
CELL iprq; /* inferred prerequisite to look for */
CELLPTR idirroot; /* Inferred prerequisite root */
CELLPTR nidirroot; /* Inferred prerequisite root */
STRINGPTR ircp; /* Inferred prerequisites recipe */
char *idir; /* directory to CD to. */
int ipush = 0; /* flag for push on inferred prereq */
char *name = NIL(char); /* prerequisite name */
CELLPTR meta = edge->cl_prq;
int dmax_fix;
int trans;
int noinf;
int exists;
if( meta->ce_prq ) name = meta->ce_prq->cl_prq->CE_NAME;
DB_PRINT( "inf", ("Trying edge from [%s] to [%s] for [%s]",
meta->CE_NAME, name?name:"(nil)", ic->ic_name) );
/* Set the temp CELL used for building prerequisite candidates to
* all zero so that we don't have to keep initializing all the
* fields. */
{
register char *s = (char *) &iprq;
register int n = sizeof(CELL);
while( n ) { *s++ = '\0'; n--; }
}
nidirroot = idirroot = ic->ic_setdirroot;
iprq.ce_name = &iprqh;
if( name ) {
/* Build the prerequisite name from the %-meta prerequisite given
* for the %-meta rule. */
iprqh.ht_name = _build_name( ic->ic_name, name, pdfa->dl_per );
if((dmax_fix = (_count_dots(name)-_count_dots(meta->CE_NAME))) < 0)
dmax_fix = 0;
if( !strcmp(ic->ic_name, iprqh.ht_name) ||
(_count_dots(iprqh.ht_name) > ic->ic_dmax + dmax_fix) ) {
FREE( iprqh.ht_name );
continue;
}
DB_PRINT( "inf", ("Checking prerequisite [%s]", iprqh.ht_name) );
/* See if the prerequisite CELL has been previously defined. If
* it has, then make a copy of it into iprq, and use it to try
* the inference. We make the copy so that we don't modify the
* stat of the inferred cell if the inference fails.
*/
thp = Get_name( iprqh.ht_name, Defs, FALSE );
if(thp != NIL(HASH)) {
iprq = *thp->CP_OWNR;
ircp = iprq.ce_recipe;
}
else
ircp = NIL(STRING);
}
else
iprqh.ht_name = NIL(char);
/* If the %-meta has a .SETDIR set then we change to the new
* directory prior to performing the stat of the new prerequisite.
* If the change of directory fails then the rule is droped from
* further consideration.
*/
if( iprq.ce_dir ) {
if( ipush = Push_dir(iprq.ce_dir, iprqh.ht_name, TRUE) ) {
nidirroot = thp->CP_OWNR;
idir = Pwd;
}
else {
if( iprqh.ht_name ) FREE( iprqh.ht_name );
continue;
}
}
else
idir = NIL(char);
/* Stat the inferred prerequisite.
*/
if( name ) {
if( Verbose & V_INFER )
printf( "%s: Trying prerequisite [%s] for [%s]\n", Pname,
iprqh.ht_name, ic->ic_name );
if( !(iprq.ce_flag & F_STAT) ) Stat_target(&iprq, FALSE);
}
/* If the STAT succeeded or if the prerequisite has a recipe for
* making it then it's a match and a candidate for getting infered.
* Otherwise it is not a match, and we cannot yet tell if it is
* going to be a successful path to follow, so we save it for
* later consideration.
*/
noinf = ((Glob_attr)&A_NOINFER);
if( meta->ce_prq )
noinf |= ((meta->ce_prq->cl_prq->ce_attr)&A_NOINFER);
trans = Transitive || !noinf;
exists = (iprq.ce_time != (time_t)0L);
if( exists || (ircp != NIL(STRING)) || !name ) {
match = _add_iset( match, ic, meta, pdfa, idirroot, ic->ic_dmax,
trans, iprq.ce_name->ht_name, idir, exists );
DB_PRINT("inf",("Added to MATCH %s",iprq.ce_name->ht_name));
}
else if( !noinf && match == NIL(ICELL) ) {
*nnmp = _add_iset( *nnmp, ic, meta, pdfa, nidirroot, ic->ic_dmax,
trans, iprq.ce_name->ht_name, idir, exists );
DB_PRINT("inf",("Added to NOMATCH %s",iprq.ce_name->ht_name));
}
/* If we pushed a directory for the inferred prerequisite then
* pop it.
*/
if( ipush ) Pop_dir(FALSE);
if( iprqh.ht_name ) FREE(iprqh.ht_name);
}
}
DB_RETURN(match);
}
static char *
_build_name( tg, meta, per )
char *tg;
char *meta;
char *per;
{
char *name;
name = Apply_edit( meta, "%", per, FALSE, FALSE );
if( strchr(name, '$') ) {
HASHPTR m_at;
char *tmp;
m_at = Def_macro( "@", tg, M_MULTI );
tmp = Expand( name );
if( m_at->ht_value != NIL(char) ) {
FREE( m_at->ht_value );
m_at->ht_value = NIL(char);
}
if( name != meta ) FREE( name );
name = tmp;
}
else if( name == meta )
name = _strdup( name );
return(name);
}
static DFALINKPTR
_dfa_subset( pdfa, stack )/*
============================
This is the valid DFA subset computation. Whenever a CELL has a Match_dfa
subset computed this algorithm is run to see if any of the previously
computed sets on the DFA stack are proper subsets of the new set. If they
are, then any elements of the matching subset whose Prep counts exceed
the allowed maximum given by Prep are removed from the computed DFA set,
and hence from consideration, thereby cutting off the cycle in the
inference graph. */
DFALINKPTR pdfa;
register DFASETPTR stack;
{
register DFALINKPTR element;
DFALINKPTR nelement;
DB_ENTER( "_dfa_subset" );
for(; pdfa != NIL(DFALINK) && stack != NIL(DFASET); stack = stack->df_next) {
int subset = TRUE;
for( element=stack->df_set; subset && element != NIL(DFALINK);
element=element->dl_next ) {
register DFALINKPTR subel;
for( subel = pdfa;
subel != NIL(DFALINK) && (subel->dl_meta != element->dl_meta);
subel = subel->dl_next );
if( subset = (subel != NIL(DFALINK)) ) element->dl_member = subel;
}
if( subset )
for( element=stack->df_set; element != NIL(DFALINK);
element=element->dl_next ) {
DFALINKPTR mem = element->dl_member;
int npr = element->dl_prep + 1;
if( npr > _prep )
mem->dl_delete++;
else
mem->dl_prep = npr;
}
}
for( element = pdfa; element != NIL(DFALINK); element = nelement ) {
nelement = element->dl_next;
if( element->dl_delete ) {
/* A member of the subset has a PREP count equal to PREP, so
* it should not be considered further in the inference, hence
* we remove it from the doubly linked set list */
if( element == pdfa )
pdfa = element->dl_next;
else
element->dl_prev->dl_next = element->dl_next;
if( element->dl_next != NIL(DFALINK) )
element->dl_next->dl_prev = element->dl_prev;
DB_PRINT("inf", ("deleting dfa [%s]", element->dl_meta->CE_NAME));
FREE( element->dl_per );
FREE( element );
}
}
DB_RETURN( pdfa );
}
static void
_free_dfas( chain )/*
=====================
Free the list of DFA's constructed by Match_dfa, and linked together by
LINK cells. FREE the % value as well, as long as it isn't NIL. */
DFALINKPTR chain;
{
register DFALINKPTR tl;
DB_ENTER( "_free_dfas" );
for( tl=chain; tl != NIL(DFALINK); chain = tl ) {
tl = tl->dl_next;
DB_PRINT( "inf", ("Freeing DFA [%s], %% = [%s]", chain->dl_meta->CE_NAME,
chain->dl_per) );
if( chain->dl_per != NIL(char) ) FREE( chain->dl_per );
FREE( chain );
}
DB_VOID_RETURN;
}
static int
_count_dots( name )/*
=====================*/
char *name;
{
register char *p;
register int i = 0;
for( p = name; *p; p++ ) if(*p == '.') i++;
return( i );
}
static ICELLPTR _icells = NIL(ICELL);
#ifdef DBUG
static int _icell_cost = 0;
#endif
static ICELLPTR
_add_iset( iset, parent, meta, dfa, setdirroot, dmax, noinf, name, dir, exists)
ICELLPTR iset;
ICELLPTR parent;
CELLPTR meta;
DFALINKPTR dfa;
CELLPTR setdirroot;
int dmax;
int noinf;
char *name;
char *dir;
int exists;
{
ICELLPTR icell;
DB_ENTER("_add_iset");
TALLOC(icell, 1, ICELL);
DB_EXECUTE("inf", _icell_cost+=(sizeof(ICELL)+strlen(dir?dir:"")+strlen(name?name:"")+2););
icell->ic_meta = meta;
icell->ic_dfa = dfa;
icell->ic_setdirroot = setdirroot;
if( parent ) icell->ic_dfastack.df_next = &parent->ic_dfastack;
icell->ic_dmax = dmax;
icell->ic_dir = _strdup(dir);
icell->ic_name = _strdup(name);
icell->ic_parent = parent;
icell->ic_next = iset;
icell->ic_flag = noinf;
icell->ic_exists = exists;
icell->ic_link = _icells;
_icells = icell;
DB_RETURN(icell);
}
static void
_free_icells()
{
register ICELLPTR ic;
DB_ENTER("_free_icells");
for( ; _icells; _icells = ic ) {
ic = _icells->ic_link;
_free_dfas(_icells->ic_dfastack.df_set);
if( _icells->ic_dir ) FREE(_icells->ic_dir);
if( _icells->ic_name) FREE(_icells->ic_name);
FREE(_icells);
}
DB_PRINT("inf",("Used %d memory for icells",_icell_cost));
DB_EXECUTE("inf", _icell_cost=0; );
DB_VOID_RETURN;
}
static ICELLPTR
_union_iset( iset, uset )
ICELLPTR iset;
ICELLPTR uset;
{
register ICELLPTR ic;
if( iset == NIL(ICELL) ) return(uset);
for( ic=iset; ic->ic_next != NIL(ICELL); ic=ic->ic_next );
ic->ic_next = uset;
return(iset);
}
static char *
_dump_inf_chain( ip, flag, print )/*
====================================*/
ICELLPTR ip;
int flag;
int print;
{
char *tmp;
if( ip == NIL(ICELL) ) return(NIL(char));
tmp = _dump_inf_chain(ip->ic_parent, FALSE, FALSE);
if( ip->ic_meta ) {
tmp = _strjoin(tmp, "(", -1, TRUE);
tmp = _strjoin(tmp, ip->ic_meta->CE_NAME, -1, TRUE);
if( ip->ic_dir && !*ip->ic_dir ) {
tmp = _strjoin(tmp, "[", -1, TRUE);
if( strncmp(Makedir,ip->ic_dir, strlen(Makedir)) )
tmp = _strjoin(tmp, ip->ic_dir, -1, TRUE);
else
tmp = _strjoin(tmp, ip->ic_dir+strlen(Makedir)+1, -1, TRUE);
tmp = _strjoin(tmp, "]", -1, TRUE);
}
tmp = _strjoin(tmp, (ip->ic_name)?") -->":")", -1, TRUE);
}
if( ip->ic_name ) tmp = _strapp( tmp, ip->ic_name );
if( flag && ip->ic_meta->ce_prq) {
tmp = _strjoin(tmp, "(", -1, TRUE);
tmp = _strjoin(tmp, ip->ic_meta->ce_prq->cl_prq->CE_NAME, -1, TRUE);
tmp = _strjoin(tmp, ")", -1, TRUE);
}
if( print ) {
fprintf( stderr, "%s: %2d. %s\n", Pname, print, tmp );
FREE(tmp);
tmp = NIL(char);
}
return(tmp);
}
#ifdef DBUG
_dump_dfa_stack(dfas, dfa_stack)
DFALINKPTR dfas;
DFASETPTR dfa_stack;
{
register DFALINKPTR pdfa;
char *tmp = NIL(char);
DFASETPTR ds;
for( pdfa = dfas; pdfa != NIL(DFALINK); pdfa = pdfa->dl_next )
tmp = _strapp( tmp, pdfa->dl_meta->CE_NAME );
tmp = _strapp( tmp, ":: {" );
for( ds = dfa_stack; ds != NIL(DFASET); ds = ds->df_next ) {
tmp = _strapp( tmp, "[" );
for( pdfa = ds->df_set; pdfa != NIL(DFALINK); pdfa = pdfa->dl_next )
tmp = _strapp( tmp, pdfa->dl_meta->CE_NAME );
tmp = _strapp( tmp, "]" );
}
tmp = _strapp( tmp, "}" );
printf( "DFA set and stack contents:\n%s\n", tmp );
FREE(tmp);
}
_dump_iset( name, iset )
char *name;
ICELLPTR iset;
{
int cell = 0;
printf( "**** ISET for %s\n", name );
for( ; iset != NIL(ICELL); iset = iset->ic_next ){
printf( "cell %d\n", cell++ );
if( iset->ic_meta )
printf( "edge: %s --> %s\n", iset->ic_meta->CE_NAME,
iset->ic_meta->ce_prq ?
iset->ic_meta->ce_prq->cl_prq->CE_NAME :
"(nil)" );
else
printf( "edge: (nil)\n" );
if( iset->ic_dfa )
printf( "dfa: %s\n", iset->ic_dfa->dl_meta->CE_NAME );
else
printf( "dfa: (nil)\n" );
printf( "sdr: %04x\n", iset->ic_setdirroot );
_dump_dfa_stack(iset->ic_dfastack.df_set, &iset->ic_dfastack);
printf( "dmax: %d\n", iset->ic_dmax );
printf( "name: %s\n", iset->ic_name );
printf( "dir: %s\n", iset->ic_dir?iset->ic_dir:"(nil)" );
printf( "parent: " );
if( iset->ic_parent )
if( iset->ic_parent->ic_meta )
printf( "%s --> %s\n",
iset->ic_parent->ic_meta->CE_NAME,
iset->ic_parent->ic_meta->ce_prq ?
iset->ic_parent->ic_meta->ce_prq->cl_prq->CE_NAME :
"(nil)" );
else
printf( "(nil)\n" );
else
printf( "(nil)\n" );
}
printf( "==================================\n" );
}
#endif

56
dmake/itypes.h Normal file
View File

@ -0,0 +1,56 @@
/* RCS -- $Header: /u2/dvadura/src/generic/dmake/src/RCS/itypes.h,v 1.1 1992/01/24 03:29:40 dvadura Exp $
-- SYNOPSIS -- type declarations for common types
--
-- DESCRIPTION
-- portable type declarations.
--
-- AUTHOR
-- Dennis Vadura, dvadura@watdragon.uwaterloo.ca
-- CS DEPT, University of Waterloo, Waterloo, Ont., Canada
--
-- COPYRIGHT
-- Copyright (c) 1990 by Dennis Vadura. All rights reserved.
--
-- This program is free software; you can redistribute it and/or
-- modify it under the terms of the GNU General Public License
-- (version 1), as published by the Free Software Foundation, and
-- found in the file 'LICENSE' included with this distribution.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warrant of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program; if not, write to the Free Software
-- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
--
-- LOG
-- $Log: itypes.h,v $
* Revision 1.1 1992/01/24 03:29:40 dvadura
* dmake Version 3.8, Initial revision
*
*/
#ifndef ITYPES_h
#define ITYPES_h
#if defined(M_I86) || defined(MC68000)
typedef char int8; /* typedefs for right size ints */
typedef int int16;
typedef long int32;
typedef unsigned char uint8;
typedef unsigned int uint16;
typedef unsigned long uint32;
#else
typedef char int8; /* typedefs for right size ints */
typedef short int16;
typedef long int32;
typedef unsigned char uint8;
typedef unsigned short uint16;
typedef unsigned long uint32;
#endif
#endif

58
dmake/mac/arlib.c Normal file
View File

@ -0,0 +1,58 @@
/* RCS -- $Header: /u2/dvadura/src/generic/dmake/src/mac/arlib.c,v 1.1 1992/01/24 03:29:41 dvadura Exp $
-- SYNOPSIS -- Library access code.
--
-- DESCRIPTION
-- This implementation uses the library timestamp inplace of the
-- library member timestamp.
--
-- AUTHOR
-- Dennis Vadura, dvadura@watdragon.uwaterloo.ca
-- CS DEPT, University of Waterloo, Waterloo, Ont., Canada
--
-- COPYRIGHT
-- Copyright (c) 1990 by Dennis Vadura. All rights reserved.
--
-- This program is free software; you can redistribute it and/or
-- modify it under the terms of the GNU General Public License
-- (version 1), as published by the Free Software Foundation, and
-- found in the file 'LICENSE' included with this distribution.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warrant of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program; if not, write to the Free Software
-- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
--
-- LOG
-- $Log: arlib.c,v $
* Revision 1.1 1992/01/24 03:29:41 dvadura
* dmake Version 3.8, Initial revision
*
*/
#include "extern.h"
PUBLIC time_t
seek_arch(char * /* name */, char *lib) {
static int warned = FALSE;
if (!warned && !(Glob_attr&A_SILENT))
warned = TRUE,
Warning("Can't extract library member timestamp;\n\
using library timestamp instead.");
return (Do_stat(lib, NULL, NULL));
}
PUBLIC int
touch_arch(char * /* name */, char *lib) {
static int warned = FALSE;
if (!warned && !(Glob_attr&A_SILENT))
warned = TRUE,
Warning("Can't update library member timestamp;\n\
touching library instead.");
return (Do_touch(lib, NULL, NULL));
}

92
dmake/mac/bogus.c Normal file
View File

@ -0,0 +1,92 @@
/* RCS -- $Header: /u2/dvadura/src/generic/dmake/src/mac/bogus.c,v 1.1 1992/01/24 03:29:42 dvadura Exp $
-- SYNOPSIS -- Write the shell of subroutines we can't or don't
-- need to implement
--
-- DESCRIPTION
-- dmake uses a couple of functions which I am either unable to figure out
-- how to implement or which are not needed. The shells of these routines
-- are in this file.
--
-- AUTHOR
-- Dennis Vadura, dvadura@watdragon.uwaterloo.ca
-- CS DEPT, University of Waterloo, Waterloo, Ont., Canada
--
--
-- COPYRIGHT
-- Copyright (c) 1990 by Dennis Vadura. All rights reserved.
--
-- This program is free software; you can redistribute it and/or
-- modify it under the terms of the GNU General Public License
-- (version 1), as published by the Free Software Foundation, and
-- found in the file 'LICENSE' included with this distribution.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warrant of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program; if not, write to the Free Software
-- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
--
-- LOG
-- $Log: bogus.c,v $
* Revision 1.1 1992/01/24 03:29:42 dvadura
* dmake Version 3.8, Initial revision
*
*/
#include "extern.h"
/*
* tzset() is a Microsoft "extension" to ANSI C. It sets global
* variables telling if we are in dayling savings time, the time
* zone, and difference between the current time and GMT.
* None of these globals are used by dmake, so this routine is
* not needed
*/
PUBLIC void tzset () {}
/*
* Add an environmental variable that child processes can use.
* Since MPW currently doesn't allow child processes, this isn't
* needed.
*/
PUBLIC int putenv (char * /* pEnvString */) {return (0);}
/*
* Execute a child process. This may be able to be done with
* the MPW system() call someday, but cannot be done currently.
*/
PUBLIC int runargv (CELLPTR /* target */, int /* ignore */, int /* group */,
int /* last */, int /* shell */, char * /* pCmd */) {
static int warned = FALSE;
if (!warned && !(Glob_attr & A_SILENT)) {
warned = TRUE;
Fatal ("Can't execute any targets: use '-n' option.");
} /* if */
return (0);
} /* int runargv () */
/*
* Wait for the child process to complete. Only needed to be implemented
* if we could executing multiple processes at once.
*/
PUBLIC int Wait_for_child(int /* abort_flg */, int /* pid */) {return (1);}
/*
* Do any cleanup for any processes when we quit.
*/
PUBLIC void Clean_up_processes() {}

87
dmake/mac/config.h Normal file
View File

@ -0,0 +1,87 @@
/* RCS -- $Header: /u2/dvadura/src/generic/dmake/src/mac/config.h,v 1.1 1992/01/24 03:29:43 dvadura Exp $
-- SYNOPSIS -- Configurarion include file for the Macintosh.
--
-- DESCRIPTION
-- There is one of these for each specific machine configuration.
-- It can be used to further tweek the machine specific sources
-- so that they compile.
--
-- AUTHOR
-- Dennis Vadura, dvadura@watdragon.uwaterloo.ca
-- CS DEPT, University of Waterloo, Waterloo, Ont., Canada
--
-- COPYRIGHT
-- Copyright (c) 1990 by Dennis Vadura. All rights reserved.
--
-- This program is free software; you can redistribute it and/or
-- modify it under the terms of the GNU General Public License
-- (version 1), as published by the Free Software Foundation, and
-- found in the file 'LICENSE' included with this distribution.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warrant of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program; if not, write to the Free Software
-- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
--
-- LOG
-- $Log: config.h,v $
* Revision 1.1 1992/01/24 03:29:43 dvadura
* dmake Version 3.8, Initial revision
*
*/
/* Definitions left out of StdArg.h */
#define va_alist ...
#define va_dcl
#define CONST const
#define FALSE 0
#define TRUE 1
/* signal extensions */
#define SIGQUIT SIGTERM
/* Mac doesn't have a stat function or structure so we have to add one in. */
typedef long off_t;
struct stat {
unsigned short st_mode;
off_t st_size;
time_t st_mtime;
time_t st_ctime;
/* struct stat has lots of other fields, but we don't need them for dmake */
}; /* struct stat */
#define S_IFDIR 0040000 /* directory */
#define S_IFREG 0100000 /* regular */
#define S_IFMT (S_IFDIR | S_IFREG) /* Format */
#define S_IREAD 0000400 /* read owner permission */
#define S_IWRITE 0000200 /* write owner permission */
#define S_IEXEC 0000100 /* execute owner permission */
/* Global for environmental variables */
extern char **environ;
/* We really want main to be in the mac directory
so that we get the envp argument */
#define main(argc, argv) dmakemain(argc, argv)
/* Directory/file info. and directory moving */
int stat (char *pPath, struct stat *pStat);
char *getcwd (char *pPath, size_t pathSize);
int chdir (char *pPath);
int utime (char *pPath, time_t *pTimes);
/* Routines to handle conversion from Unix file names to Mac file names */
char *Unix2MacFName(char *pUnixName);
FILE *MacFOpen (char *pName, char *pMode);
#define fopen(pFName, pMode) MacFOpen(pFName, pMode)
/* a small problem with pointer to voids on some unix machines needs this */
#define PVOID void *

44
dmake/mac/config.mk Normal file
View File

@ -0,0 +1,44 @@
# This is an OS Mac specific configuration file
# It assumes that OBJDIR, TARGET and DEBUG are previously defined.
# It defines CFLAGS, LDARGS, CPPFLAGS, STARTUPFILE, LDOBJS
# It augments SRC, OBJDIR, TARGET, CFLAGS, LDLIBS
#
STARTUPFILE = :$(OS):startup.mk
CPPFLAGS = $(CFLAGS)
LDOBJS = $(CSTARTUP) :$(OBJDIR):{$(<:f)}
LDARGS = $(LDFLAGS) -o $@ $(LDOBJS) $(LDLIBS)
# Debug flags
DB_CFLAGS = -sym on
DB_LDFLAGS = -sym on
DB_LDLIBS =
# NO Debug flags
NDB_CFLAGS = -sym off
NDB_LDFLAGS = -sym off
NDB_LDLIBS =
# Local configuration modifications for CFLAGS.
CFLAGS += -I :$(OS) -d _MPW -s $(<:b)
LDFLAGS += -w -c 'MPS ' -t MPST
# Since we writing out what files we want to execute, we can't use .SETDIR
# to specify the files to compile in the Mac directory.
# Instead, we copy the files to the (top-level) current directory and compile
# them there.
%.c : ":$(OS):%.c"
duplicate -y $< $@
# Common Mac source files.
OS_SRC = arlib.c bogus.c dirbrk.c directry.c environ.c main.c rmprq.c \
ruletab.c tempnam.c tomacfil.c
.IF $(SHELL) != mwp
.SETDIR=$(OS) : $(OS_SRC)
.ENDIF
SRC += $(OS_SRC)
# Set source dirs so that we can find files named in this
# config file.
.SOURCE.h : $(OS)

52
dmake/mac/dirbrk.c Normal file
View File

@ -0,0 +1,52 @@
/* RCS -- $Header: /u2/dvadura/src/generic/dmake/src/mac/dirbrk.c,v 1.1 1992/01/24 03:29:44 dvadura Exp $
-- SYNOPSIS -- define the directory separator string.
--
-- DESCRIPTION
-- Define this string for any character that may appear in a path name
-- and can be used as a directory separator.
--
-- AUTHOR
-- Dennis Vadura, dvadura@watdragon.uwaterloo.ca
-- CS DEPT, University of Waterloo, Waterloo, Ont., Canada
--
-- COPYRIGHT
-- Copyright (c) 1990 by Dennis Vadura. All rights reserved.
--
-- This program is free software; you can redistribute it and/or
-- modify it under the terms of the GNU General Public License
-- (version 1), as published by the Free Software Foundation, and
-- found in the file 'LICENSE' included with this distribution.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warrant of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program; if not, write to the Free Software
-- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
--
-- LOG
-- $Log: dirbrk.c,v $
* Revision 1.1 1992/01/24 03:29:44 dvadura
* dmake Version 3.8, Initial revision
*
*/
#include "extern.h"
/* mac only uses ':' */
char* DirBrkStr = ":";
/*
** Return TRUE if the name is the full specification of a path name to a file
** starting at the root of the file system, otherwise return FALSE
*/
PUBLIC int
If_root_path(name)
char *name;
{
name = Unix2MacFName (name);
return( (strchr(name, ':') != NIL(char)) &&
(name[0] != ':') );
}

270
dmake/mac/directry.c Normal file
View File

@ -0,0 +1,270 @@
/* RCS -- $Header: /u2/dvadura/src/generic/dmake/src/mac/directry.c,v 1.1 1992/01/24 03:29:45 dvadura Exp $
-- SYNOPSIS -- Fake directory and file functions for the Mac
--
-- DESCRIPTION
-- This file contains implementations for some ANSI standard routines dmake
-- uses which are not otherwise available for the mac.
--
-- Assume we are using at least 128K ROMS.
--
-- AUTHOR
-- Dennis Vadura, dvadura@watdragon.uwaterloo.ca
-- CS DEPT, University of Waterloo, Waterloo, Ont., Canada
--
--
-- COPYRIGHT
-- Copyright (c) 1990 by Dennis Vadura. All rights reserved.
--
-- This program is free software; you can redistribute it and/or
-- modify it under the terms of the GNU General Public License
-- (version 1), as published by the Free Software Foundation, and
-- found in the file 'LICENSE' included with this distribution.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warrant of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program; if not, write to the Free Software
-- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
--
-- LOG
-- $Log: directry.c,v $
* Revision 1.1 1992/01/24 03:29:45 dvadura
* dmake Version 3.8, Initial revision
*
*/
#include <Errors.h>
#include <Files.h>
#include <OSUtils.h>
#include <StdLib.h>
#include <Strings.h>
#include <SysEqu.h>
#include "extern.h"
/*
* Implementation of stat function for dmake on the mac.
*
* Many fields aren't filled in, and the times are seconds from 1/1//1904,
* but it should be enough for dmake (I think we only need st_mtime and
* st_mode's S_IFDIR set correctly).
*/
PUBLIC int stat(pPath, pStat)
char *pPath;
struct stat *pStat;
{
CInfoPBRec infoPB;
OSErr err;
int retVal;
pPath = Unix2MacFName (pPath);
infoPB.hFileInfo.ioCompletion = NULL;
infoPB.hFileInfo.ioNamePtr = c2pstr (pPath);
infoPB.hFileInfo.ioVRefNum = 0;
infoPB.hFileInfo.ioFDirIndex = 0;
infoPB.hFileInfo.ioDirID = 0;
err = PBGetCatInfo(&infoPB, FALSE);
p2cstr ((StringPtr) pPath);
if (err == noErr) {
pStat->st_mtime = (time_t) infoPB.hFileInfo.ioFlMdDat;
pStat->st_ctime = (time_t) infoPB.hFileInfo.ioFlCrDat;
pStat->st_mode = S_IREAD | S_IEXEC;
/* If it is a directory ... */
if (infoPB.hFileInfo.ioFlAttrib & 0x10) {
pStat->st_size = infoPB.dirInfo.ioDrNmFls;
pStat->st_mode |= S_IFDIR;
} else {
pStat->st_size = infoPB.hFileInfo.ioFlLgLen;
pStat->st_mode |= S_IFREG;
} /* if ... else */
/* If it is writeable */
if ((infoPB.hFileInfo.ioFlAttrib & 0x1) == 0) {
pStat->st_mode |= S_IWRITE;
} /* if */
retVal = 0;
} else {
retVal = -1;
} /* if ... else */
return (retVal);
} /* PUBLIC int stat () */
/*
* Return the current working directory, or NULL if there is an error.
*/
PUBLIC char *getcwd (char *pPath, size_t pathSize) {
DirInfo dirInfo;
OSErr err;
Str255 dirName;
char *pBeginName;
char *pC;
size_t len;
size_t spaceForColon;
pPath = Unix2MacFName (pPath);
/* Set up the info for the PBGetCatInfo() calls */
dirInfo.ioCompletion = NULL;
dirInfo.ioNamePtr = dirName;
dirInfo.ioVRefNum = 0;
dirInfo.ioFDirIndex = -1;
dirInfo.ioDrDirID = 0;
pBeginName = pPath + pathSize - 1;
spaceForColon = 0; /* Make sure we don't have an end colon on the name */
/*
* Keep going up the directory path until the end is reached or an error
* occurs. Ideally, we would check for errors at every level and stop
* when we received an fnfErr (File Not Found), but it appears that there
* are some problems with network volumes. (During testing, I received
* a paramErr (No Default Volume) beyond the top level.) Thus, to keep it
* simple, I assume any error past the first directory indicates we have
* seen all directories.
*/
while (TRUE) {
err = PBGetCatInfo ((CInfoPBPtr) &dirInfo, FALSE);
len = ((size_t)(unsigned char) dirName[0]);
if ((err == noErr) && (len < pBeginName - pPath)) {
p2cstr (dirName);
pBeginName -= len + spaceForColon;
strcpy (pBeginName, dirName);
/* Note that strcpy() adds the '\0' at the end of
the first directory for us */
if (spaceForColon == 1) {
pBeginName[len] = ':';
} else {
/* The end of the string shouldn't have a ':' */
spaceForColon = 1;
} /* if */
/* Set up for the next call to PBGetCatInfo() with
the parent's directory ID */
dirInfo.ioDrDirID = dirInfo.ioDrParID;
} else if (spaceForColon == 1) {
/* We got past the top-level directory */
break;
} else {
/* We either have an error when looking at the first directory
or have run out of room. */
return (NULL);
} /* if ... elses */
} /* while */
/* Now copy the directory string to the beginning of the path string.
(It's possible the directory already starts at the beginning of the
string, but this is unlikely and doesn't hurt anything if it does,
so we don't bother to check for it.) */
pC = pPath;
while ((*(pC++) = *(pBeginName++)) != '\0')
;
return (pPath);
} /* PUBLIC char *getcwd () */
/*
* Change the directory to a new default directory.
*
* Return 0 if successful, or -1 if there is an error.
*/
PUBLIC int chdir (char *pPath) {
WDPBRec WDPB;
VolumeParam vParam;
OSErr err;
int result;
char *pC;
char c;
pPath = Unix2MacFName (pPath);
/* Set up the directory */
c2pstr (pPath);
WDPB.ioCompletion = NULL;
WDPB.ioNamePtr = pPath;
WDPB.ioVRefNum = 0;
WDPB.ioWDProcID = 0;
WDPB.ioWDDirID = 0;
err = PBOpenWD (&WDPB, FALSE);
/* Restore path to a C-type string in case the caller wants
to use it after this call. */
p2cstr (pPath);
if (err != noErr) {
return (-1);
} /* if */
/* Set up the volume if necessary */
if (*pPath != ':') {
for (pC = pPath + 1; (*pC != ':') && (*pC != '\0'); ++pC)
;
c = *pC;
*pC = '\0';
vParam.ioCompletion = NULL;
vParam.ioNamePtr = c2pstr (pPath);
vParam.ioVRefNum = WDPB.ioVRefNum;
err = PBSetVol ((ParmBlkPtr) &vParam, FALSE);
p2cstr (pPath);
*pC = c;
result = ((err == noErr) ? 0 : -1);
} else {
result = 0;
} /* if ... else */
return (result);
} /* PUBLIC int chdir () */
/*
* Change the modification time for the file to the current time.
*
* The normal version of utime can set the modification time to any
* time, this function aborts the function if this is tried.
*
* We return 0 if the modification time was updated and -1 if there
* was an error.
*/
PUBLIC int utime (char *pPath, time_t *pTimes) {
CInfoPBRec infoPB;
OSErr err;
pPath = Unix2MacFName (pPath);
if (pTimes != NULL) {
Fatal ("SUBROUTINE SHORTCOMING: utime cannot take a utimbuf struct");
} /* if */
/* Get the old info */
infoPB.hFileInfo.ioCompletion = NULL;
infoPB.hFileInfo.ioNamePtr = c2pstr (pPath);
infoPB.hFileInfo.ioVRefNum = 0;
infoPB.hFileInfo.ioFDirIndex = 0;
infoPB.hFileInfo.ioDirID = 0;
err = PBGetCatInfo (&infoPB, FALSE);
if (err != noErr) {
p2cstr ((StringPtr) pPath);
return (-1);
} /* if */
/* Change the modification time and set the new info */
GetDateTime (&(infoPB.hFileInfo.ioFlMdDat));
infoPB.hFileInfo.ioDirID = 0;
err = PBSetCatInfo (&infoPB, FALSE);
p2cstr ((StringPtr) pPath);
return ((err == noErr) ? 0 : -1);
} /* PUBLIC int utime () */

54
dmake/mac/dompwmak Normal file
View File

@ -0,0 +1,54 @@
newfolder objects
c -I. -I :mac -d _MPW -s infer -sym off -o :objects:infer.c.o infer.c
c -I. -I :mac -d _MPW -s make -sym off -o :objects:make.c.o make.c
c -I. -I :mac -d _MPW -s stat -sym off -o :objects:stat.c.o stat.c
c -I. -I :mac -d _MPW -s expand -sym off -o :objects:expand.c.o expand.c
c -I. -I :mac -d _MPW -s dmstring -sym off -o :objects:dmstring.c.o dmstring.c
c -I. -I :mac -d _MPW -s hash -sym off -o :objects:hash.c.o hash.c
c -I. -I :mac -d _MPW -s dag -sym off -o :objects:dag.c.o dag.c
c -I. -I :mac -d _MPW -s dmake -sym off -o :objects:dmake.c.o dmake.c
c -I. -I :mac -d _MPW -s path -sym off -o :objects:path.c.o path.c
c -I. -I :mac -d _MPW -s imacs -sym off -o :objects:imacs.c.o imacs.c
c -I. -I :mac -d _MPW -s sysintf -sym off -o :objects:sysintf.c.o sysintf.c
c -I. -I :mac -d _MPW -s parse -sym off -o :objects:parse.c.o parse.c
c -I. -I :mac -d _MPW -s getinp -sym off -o :objects:getinp.c.o getinp.c
c -I. -I :mac -d _MPW -s quit -sym off -o :objects:quit.c.o quit.c
c -I. -I :mac -d _MPW -s state -sym off -o :objects:state.c.o state.c
c -I. -I :mac -d _MPW -s basename -sym off -o :objects:basename.c.o basename.c
c -I. -I :mac -d _MPW -s dmdump -sym off -o :objects:dmdump.c.o dmdump.c
c -I. -I :mac -d _MPW -s macparse -sym off -o :objects:macparse.c.o macparse.c
c -I. -I :mac -d _MPW -s rulparse -sym off -o :objects:rulparse.c.o rulparse.c
c -I. -I :mac -d _MPW -s percent -sym off -o :objects:percent.c.o percent.c
c -I. -I :mac -d _MPW -s function -sym off -o :objects:function.c.o function.c
duplicate -y :mac:arlib.c arlib.c
c -I. -I :mac -d _MPW -s arlib -sym off -o :objects:arlib.c.o arlib.c
delete arlib.c
duplicate -y :mac:bogus.c bogus.c
c -I. -I :mac -d _MPW -s bogus -sym off -o :objects:bogus.c.o bogus.c
delete bogus.c
duplicate -y :mac:dirbrk.c dirbrk.c
c -I. -I :mac -d _MPW -s dirbrk -sym off -o :objects:dirbrk.c.o dirbrk.c
delete dirbrk.c
duplicate -y :mac:directry.c directry.c
c -I. -I :mac -d _MPW -s directry -sym off -o :objects:directry.c.o directry.c
delete directry.c
duplicate -y :mac:environ.c environ.c
c -I. -I :mac -d _MPW -s environ -sym off -o :objects:environ.c.o environ.c
delete environ.c
duplicate -y :mac:main.c main.c
c -I. -I :mac -d _MPW -s main -sym off -o :objects:main.c.o main.c
delete main.c
duplicate -y :mac:rmprq.c rmprq.c
c -I. -I :mac -d _MPW -s rmprq -sym off -o :objects:rmprq.c.o rmprq.c
delete rmprq.c
duplicate -y :mac:ruletab.c ruletab.c
c -I. -I :mac -d _MPW -s ruletab -sym off -o :objects:ruletab.c.o ruletab.c
delete ruletab.c
duplicate -y :mac:tempnam.c tempnam.c
c -I. -I :mac -d _MPW -s tempnam -sym off -o :objects:tempnam.c.o tempnam.c
delete tempnam.c
duplicate -y :mac:tomacfil.c tomacfil.c
c -I. -I :mac -d _MPW -s tomacfil -sym off -o :objects:tomacfil.c.o tomacfil.c
delete tomacfil.c
link -w -c 'MPS ' -t MPST -sym off -o dmake :objects:infer.c.o :objects:make.c.o :objects:stat.c.o :objects:expand.c.o :objects:dmstring.c.o :objects:hash.c.o :objects:dag.c.o :objects:dmake.c.o :objects:path.c.o :objects:imacs.c.o :objects:sysintf.c.o :objects:parse.c.o :objects:getinp.c.o :objects:quit.c.o :objects:state.c.o :objects:basename.c.o :objects:dmdump.c.o :objects:macparse.c.o :objects:rulparse.c.o :objects:percent.c.o :objects:function.c.o :objects:arlib.c.o :objects:bogus.c.o :objects:dirbrk.c.o :objects:directry.c.o :objects:environ.c.o :objects:main.c.o :objects:rmprq.c.o :objects:ruletab.c.o :objects:tempnam.c.o :objects:tomacfil.c.o "Micah:MPW:Libraries:CLibraries:CSANELib.o" "Micah:MPW:Libraries:CLibraries:Math.o" "Micah:MPW:Libraries:CLibraries:StdCLib.o" "Micah:MPW:Libraries:Libraries:Runtime.o" "Micah:MPW:Libraries:Libraries:Interface.o" "Micah:MPW:Libraries:Libraries:Toollibs.o"
duplicate :mac:startup.mk startup.mk

236
dmake/mac/environ.c Normal file
View File

@ -0,0 +1,236 @@
/* RCS -- $Header: /u2/dvadura/src/generic/dmake/src/mac/environ.c,v 1.1 1992/01/24 03:29:46 dvadura Exp $
-- SYNOPSIS -- Set up and free for environ
--
-- DESCRIPTION
-- This file contains routines that will fill in and dispose of the
-- list of environmental variables in the environ global variable.
--
-- AUTHOR
-- Dennis Vadura, dvadura@watdragon.uwaterloo.ca
-- CS DEPT, University of Waterloo, Waterloo, Ont., Canada
--
--
-- COPYRIGHT
-- Copyright (c) 1990 by Dennis Vadura. All rights reserved.
--
-- This program is free software; you can redistribute it and/or
-- modify it under the terms of the GNU General Public License
-- (version 1), as published by the Free Software Foundation, and
-- found in the file 'LICENSE' included with this distribution.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warrant of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program; if not, write to the Free Software
-- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
--
-- LOG
-- $Log: environ.c,v $
* Revision 1.1 1992/01/24 03:29:46 dvadura
* dmake Version 3.8, Initial revision
*
*/
#include "extern.h"
/* The char used to replace the equal signs in environmental variable names. */
const char kEqualReplace = '_';
/* Maximum size of a "name=value" environmental string, including the ending '\0'.
Larger environmental variables will be clipped before dmake sees them.
(Caution: When I tested the program, the Mac or dmake trashed memory
when environmental variables of >4K were read in. I looked around a bit
and couldn't find out the exact cause, so I simply made this variable.
The memory trashing may be related to the value for MAXLINELENGTH.) */
const int kMaxEnvLen = 1024;
/* The list of environmental variables in the form "name=value".
(Once make_env() has been called.) */
char **environ = NULL;
/* Characters replaced during make_env() */
struct ReplaceChar {
char *fpPos;
char fC;
struct ReplaceChar *fpNext;
}; /* struct ReplaceChar */
struct ReplaceChar *gpReplaceList = NULL;
void AddReplace (char *pReplacePos);
/*
* Set up the environmental variables in a format used by
* the environ global variable.
*
* environ has already been set to main's envp argument when
* this suboroutine is called. We assume that envp is a copy
* MPW makes for this process' use alone, so we can modify it
* below.
*/
PUBLIC void make_env () {
char **ppCurEnv;
char *pCurPos;
#if 0
char **ppMacEnv;
char *pMacPos;
if (!gMECalled) {
gMECalled = TRUE;
environ = MALLOC (1, char *);
*environ = NULL;
#endif
#if 0
{
int numenv;
int len;
int firstnil;
numenv = 1;
ppMacEnv = environ;
while (*(ppMacEnv++) != NULL) {
++numenv;
} /* while */
ppMacEnv = environ;
if ((environ = MALLOC (numenv, char *)) == NULL) {
No_ram ();
} /* if */
numenv = 80;
for (ppCurEnv = environ; (numenv-- > 0) && (*ppMacEnv != NULL); ++ppCurEnv, ++ppMacEnv) {
pMacPos = *ppMacEnv;
len = strlen (pMacPos) + 1;
len += strlen (pMacPos + len) + 1;
#define MAXLEN 4098
if (len > MAXLEN) len = MAXLEN;
if ((*ppCurEnv = MALLOC (len, char)) == NULL) {
No_ram ();
} /* if */
firstnil = TRUE;
for (pCurPos = *ppCurEnv; ((pCurPos - *ppCurEnv) < MAXLEN - 1); ++pCurPos, ++pMacPos) {
if (*pMacPos == '=') {
*pCurPos = gEqualReplace;
} else if (*pMacPos == '\0') {
if (firstnil) {
*pCurPos = '=';
firstnil = FALSE;
} else {
*pCurPos = *pMacPos;
break;
} /* if ... else */
} else {
*pCurPos = *pMacPos;
} /* if ... elses */
} /* for */
firstnil = FALSE;
} /* for */
*ppCurEnv = NULL;
}
#endif
{
int firstnil;
/* Get rid of any equal signs in any environmental name, and put
equal signs between the names and their values */
for (ppCurEnv = environ; *ppCurEnv != NULL; ++ppCurEnv) {
firstnil = TRUE;
for (pCurPos = *ppCurEnv;
((pCurPos - *ppCurEnv < kMaxEnvLen - 1) &&
((*pCurPos != '\0') || !firstnil));
++pCurPos) {
if (*pCurPos == '=') {
AddReplace (pCurPos);
*pCurPos = kEqualReplace;
} else if (*pCurPos == '\0') {
AddReplace (pCurPos);
*pCurPos = '=';
firstnil = FALSE;
} /* if ... else if */
} /* for */
/* If the environtmental variable was too large ... */
if (*pCurPos != '\0') {
AddReplace (pCurPos);
*pCurPos = '\0';
if (firstnil) {
AddReplace (--pCurPos);
*pCurPos = '=';
} /* if */
} /* if */
} /* for */
}
#if 0
} /* if */
#endif
} /* PUBLIC void make_env () */
/*
* The character at pReplacePos is about to be replaced. Remember the
* old value so we can restore it when we're done.
*/
void AddReplace (char *pReplacePos) {
struct ReplaceChar *pReplaceChar;
if ((pReplaceChar = MALLOC (1, struct ReplaceChar)) == NULL) {
No_ram ();
} /* if */
pReplaceChar->fpPos = pReplacePos;
pReplaceChar->fC = *pReplacePos;
pReplaceChar->fpNext = gpReplaceList;
gpReplaceList = pReplaceChar;
} /* void AddReplace () */
/*
* Restore the old environmental variables to the way they looked before
* the make_env() call, on the unlikely chance that something else will look
* at our copy of the environmental variables during the program execution.
*
*/
PUBLIC void free_env () {
struct ReplaceChar *pReplaceChar;
while (gpReplaceList != NULL) {
pReplaceChar = gpReplaceList;
gpReplaceList = pReplaceChar->fpNext;
*(pReplaceChar->fpPos) = pReplaceChar->fC;
FREE (pReplaceChar);
} /* while */
#if 0
char **ppCurEnv;
char *pCurPos;
if (!gFECalled) {
gFECalled = TRUE;
//FREE (environ);
environ = NULL;
#endif
#if 0
/* Restore the environment list to what it was before we
read it in. */
for (ppCurEnv = environ; *ppCurEnv != NULL; ++ppCurEnv) {
for (pCurPos = *ppCurEnv; *pCurPos != '='; ++pCurPos)
;
*pCurPos = '\0';
} /* for */
} /* if */
#endif
} /* PUBLIC void free_env () */

128
dmake/mac/eold.c Normal file
View File

@ -0,0 +1,128 @@
/* RCS -- $Header: /u2/dvadura/src/generic/dmake/src/mac/eold.c,v 1.1 1992/01/24 03:29:47 dvadura Exp $
-- SYNOPSIS -- Set up and free for environ
--
-- DESCRIPTION
-- This file contains routines that will fill in and dispose of the
-- list of environmental variables in the environ global variable.
--
-- AUTHOR
-- Dennis Vadura, dvadura@watdragon.uwaterloo.ca
-- CS DEPT, University of Waterloo, Waterloo, Ont., Canada
--
--
-- COPYRIGHT
-- Copyright (c) 1990 by Dennis Vadura. All rights reserved.
--
-- This program is free software; you can redistribute it and/or
-- modify it under the terms of the GNU General Public License
-- (version 1), as published by the Free Software Foundation, and
-- found in the file 'LICENSE' included with this distribution.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warrant of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program; if not, write to the Free Software
-- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
--
-- LOG
-- $Log: eold.c,v $
* Revision 1.1 1992/01/24 03:29:47 dvadura
* dmake Version 3.8, Initial revision
*
*/
#include "extern.h"
/*
* Keep track of any environmental variables that have '='s in their
* name.
*/
struct EqualPos {
char *fpPos;
struct equalsign *fpNext;
} /* struct EqualPos */
struct EqualPos *gpEqualList;
/*
* The character used to replae the equal signs.
*/
const char gEqualReplace = '_';
/*
* Set up the environmental variables in a format used by
* the environ global variable.
*
* environ has already been set to main's envp argument when
* this suboroutine is called.
*/
void main_env () {
char **ppCurEnv;
char *pCurPos;
struct equalpos *pNewEqual;
gpEqualList = NULL;
for (ppCurEnv = environ; *ppCurEnv != NULL; ++ppCurEnv) {
for (pCurPos = *ppCurEnv; *pCurPos != '\0'; ++pCurPos) {
if (*pCurPos == '=') {
if ((pNewEqual =
(struct EqualPos *) malloc (sizeof (struct EqualPos))) ==
NULL) {
fputs ("Out of Memory", stderr);
exit (EXIT_FAILURE);
} /* if */
pNewEqual->fpPos = pCurPos;
pNewEqual->fpNext = gpEqualList;
gpEqualList = pNewEqual;
*pCurPos = gEqualReplace;
} /* if */
} /* for */
*pCurPos = '=';
} /* for */
} /* void main_env () */
/*
* Reset the environmental variables so they look like they did
* before the main_env() call.
*
* environ has already been set to main's envp argument when
* this suboroutine is called.
*/
void main_env () {
char **ppCurEnv;
char *pCurPos;
struct equalpos *pNewEqual;
gpEqualList = NULL;
for (ppCurEnv = environ; *ppCurEnv != NULL; ++ppCurEnv) {
for (pCurPos = *ppCurEnv; *pCurPos != '\0'; ++pCurPos) {
if (*pCurPos == '=') {
if ((pNewEqual =
(struct EqualPos *) malloc (sizeof (struct EqualPos))) ==
NULL) {
fputs ("Out of Memory", stderr);
exit (EXIT_FAILURE);
} /* if */
pNewEqual->fpPos = pCurPos;
pNewEqual->fpNext = gpEqualList;
gpEqualList = pNewEqual;
*pCurPos = gEqualReplace;
} /* if */
} /* for */
*pCurPos = '=';
} /* for */
} /* void main_env () */

52
dmake/mac/main.c Normal file
View File

@ -0,0 +1,52 @@
/* RCS -- $Header: /u2/dvadura/src/generic/dmake/src/mac/main.c,v 1.1 1992/01/24 03:29:48 dvadura Exp $
-- SYNOPSIS -- The real main function
--
-- DESCRIPTION
-- In order to get the third argument to main(), which is a list of
-- environmental variables, we have #defined main to dmakemain,
-- and put the real main here.
--
-- The environmental variables are placed in the environ global variable
-- and set up for processing by dmake in make_env().
--
-- AUTHOR
-- Dennis Vadura, dvadura@watdragon.uwaterloo.ca
-- CS DEPT, University of Waterloo, Waterloo, Ont., Canada
--
--
-- COPYRIGHT
-- Copyright (c) 1990 by Dennis Vadura. All rights reserved.
--
-- This program is free software; you can redistribute it and/or
-- modify it under the terms of the GNU General Public License
-- (version 1), as published by the Free Software Foundation, and
-- found in the file 'LICENSE' included with this distribution.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warrant of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program; if not, write to the Free Software
-- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
--
-- LOG
-- $Log: main.c,v $
* Revision 1.1 1992/01/24 03:29:48 dvadura
* dmake Version 3.8, Initial revision
*
*/
#include "extern.h"
/*
* Put envp in environ and call dmake's main().
*/
#undef main
void main (int argc, char *argv[], char *envp[]) {
environ = envp;
dmakemain (argc, argv);
} /* void main () */

43
dmake/mac/make.sh Normal file
View File

@ -0,0 +1,43 @@
newfolder objects
c -I. -I :mac -d _MPW -s infer -sym off -o :objects:infer.c.o infer.c
c -I. -I :mac -d _MPW -s make -sym off -o :objects:make.c.o make.c
c -I. -I :mac -d _MPW -s stat -sym off -o :objects:stat.c.o stat.c
c -I. -I :mac -d _MPW -s expand -sym off -o :objects:expand.c.o expand.c
c -I. -I :mac -d _MPW -s dmstring -sym off -o :objects:dmstring.c.o dmstring.c
c -I. -I :mac -d _MPW -s hash -sym off -o :objects:hash.c.o hash.c
c -I. -I :mac -d _MPW -s dag -sym off -o :objects:dag.c.o dag.c
c -I. -I :mac -d _MPW -s dmake -sym off -o :objects:dmake.c.o dmake.c
c -I. -I :mac -d _MPW -s path -sym off -o :objects:path.c.o path.c
c -I. -I :mac -d _MPW -s imacs -sym off -o :objects:imacs.c.o imacs.c
c -I. -I :mac -d _MPW -s sysintf -sym off -o :objects:sysintf.c.o sysintf.c
c -I. -I :mac -d _MPW -s parse -sym off -o :objects:parse.c.o parse.c
c -I. -I :mac -d _MPW -s getinp -sym off -o :objects:getinp.c.o getinp.c
c -I. -I :mac -d _MPW -s quit -sym off -o :objects:quit.c.o quit.c
c -I. -I :mac -d _MPW -s state -sym off -o :objects:state.c.o state.c
c -I. -I :mac -d _MPW -s basename -sym off -o :objects:basename.c.o basename.c
c -I. -I :mac -d _MPW -s dmdump -sym off -o :objects:dmdump.c.o dmdump.c
c -I. -I :mac -d _MPW -s macparse -sym off -o :objects:macparse.c.o macparse.c
c -I. -I :mac -d _MPW -s rulparse -sym off -o :objects:rulparse.c.o rulparse.c
c -I. -I :mac -d _MPW -s percent -sym off -o :objects:percent.c.o percent.c
c -I. -I :mac -d _MPW -s function -sym off -o :objects:function.c.o function.c
c -I. -I :mac -d _MPW -s arlib -sym off -o :objects:arlib.c.o :mac:arlib.c
c -I. -I :mac -d _MPW -s bogus -sym off -o :objects:bogus.c.o :mac:bogus.c
c -I. -I :mac -d _MPW -s dirbrk -sym off -o :objects:dirbrk.c.o :mac:dirbrk.c
c -I. -I :mac -d _MPW -s directry -sym off -o :objects:directry.c.o :mac:directry.c
c -I. -I :mac -d _MPW -s environ -sym off -o :objects:environ.c.o :mac:environ.c
c -I. -I :mac -d _MPW -s main -sym off -o :objects:main.c.o :mac:main.c
c -I. -I :mac -d _MPW -s rmprq -sym off -o :objects:rmprq.c.o :mac:rmprq.c
c -I. -I :mac -d _MPW -s ruletab -sym off -o :objects:ruletab.c.o :mac:ruletab.c
c -I. -I :mac -d _MPW -s tempnam -sym off -o :objects:tempnam.c.o :mac:tempnam.c
c -I. -I :mac -d _MPW -s tomacfil -sym off -o :objects:tomacfil.c.o :mac:tomacfil.c
link -w -c 'MPS ' -t MPST -sym off -o dmake :objects:infer.c.o \
:objects:make.c.o :objects:stat.c.o :objects:expand.c.o :objects:dmstring.c.o \
:objects:hash.c.o :objects:dag.c.o :objects:dmake.c.o :objects:path.c.o \
:objects:imacs.c.o :objects:sysintf.c.o :objects:parse.c.o :objects:getinp.c.o \
:objects:quit.c.o :objects:state.c.o :objects:basename.c.o :objects:dmdump.c.o \
:objects:macparse.c.o :objects:rulparse.c.o :objects:percent.c.o \
:objects:function.c.o :objects:arlib.c.o :objects:bogus.c.o :objects:dirbrk.c.o \
:objects:directry.c.o :objects:environ.c.o :objects:main.c.o :objects:rmprq.c.o \
:objects:ruletab.c.o :objects:tempnam.c.o :objects:tomacfil.c.o "CSANELib.o" \
"Math.o" "StdCLib.o" "Runtime.o" "Interface.o" "Toollibs.o"
duplicate :mac:startup.mk startup.mk

152
dmake/mac/public.h Normal file
View File

@ -0,0 +1,152 @@
/* RCS -- $Header$
-- WARNING -- This file is AUTOMATICALLY GENERATED DO NOT EDIT IT
--
-- SYNOPSIS -- Local functions exported to be visible by others.
--
-- DESCRIPTION
-- This file is generated by 'genpub'. Function declarations
-- that appear in this file are extracted by 'genpub' from
-- source files. Any function in the source file whose definition
-- appears like:
--
-- PUBLIC return_type
-- function( arg_list );
-- type_expr1 arg1;
-- ...
--
-- has its definition extracted and a line of the form:
--
-- return_type function ANSI((type_expr1,type_expr2,...));
--
-- entered into the output file.
--
-- AUTHOR
-- Dennis Vadura, dvadura@watdragon.uwaterloo.ca
-- CS DEPT, University of Waterloo, Waterloo, Ont., Canada
--
-- COPYRIGHT
-- Copyright (c) 1990 by Dennis Vadura. All rights reserved.
--
-- This program is free software; you can redistribute it and/or
-- modify it under the terms of the GNU General Public License
-- (version 1), as published by the Free Software Foundation, and
-- found in the file 'LICENSE' included with this distribution.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warrant of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program; if not, write to the Free Software
-- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
--
-- LOG
-- $Log$
*/
#ifndef _DMAKE_PUBLIC_h
#define _DMAKE_PUBLIC_h
void Infer_recipe ANSI((CELLPTR, CELLPTR));
int Make_targets ANSI(());
int Exec_commands ANSI((CELLPTR));
void Print_cmnd ANSI((char *, int, int));
void Pop_dir ANSI((int));
void Append_line ANSI((char *, int, FILE *, char *, int, int));
void Stat_target ANSI((CELLPTR, int));
char * Expand ANSI((char *));
char * Apply_edit ANSI((char *, char *, char *, int, int));
void Map_esc ANSI((char *));
char* Apply_modifiers ANSI((int, char *));
char* Tokenize ANSI((char *, char *));
char * _strjoin ANSI((char *, char *, int, int));
char * _stradd ANSI((char *, char *, int));
char * _strapp ANSI((char *, char *));
char * _strdup ANSI((char *));
char * _strdup2 ANSI((char *));
char * _strpbrk ANSI((char *, char *));
char * _strspn ANSI((char *, char *));
char * _strstr ANSI((char *, char *));
char * _substr ANSI((char *, char *));
uint16 Hash ANSI((char *, uint32 *));
HASHPTR Get_name ANSI((char *, HASHPTR *, int));
HASHPTR Search_table ANSI((HASHPTR *, char *, uint16 *, uint32 *));
HASHPTR Def_macro ANSI((char *, char *, int));
CELLPTR Def_cell ANSI((char *));
LINKPTR Add_prerequisite ANSI((CELLPTR, CELLPTR, int, int));
void Clear_prerequisites ANSI((CELLPTR));
int Test_circle ANSI((CELLPTR, int));
STRINGPTR Def_recipe ANSI((char *, STRINGPTR, int, int));
t_attr Rcp_attribute ANSI((char *));
void main ANSI((int, char **));
FILE * Openfile ANSI((char *, int, int));
FILE * Closefile ANSI(());
FILE * Search_file ANSI((char *, char **));
char * Filename ANSI(());
int Nestlevel ANSI(());
void No_ram ANSI(());
int Usage ANSI((int));
int Version ANSI(());
char * Get_suffix ANSI((char *));
char * Build_path ANSI((char *, char *));
void Make_rules ANSI(());
void Create_macro_vars ANSI(());
time_t Do_stat ANSI((char *, char *, char **));
int Do_touch ANSI((char *, char *, char **));
void Void_lib_cache ANSI((char *, char *));
time_t Do_time ANSI(());
int Do_cmnd ANSI((char *, int, int, CELLPTR, int, int, int));
char ** Pack_argv ANSI((int, int, char *));
char * Read_env_string ANSI((char *));
int Write_env_string ANSI((char *, char *));
void ReadEnvironment ANSI(());
void Catch_signals ANSI((void (*)()));
void Clear_signals ANSI(());
void Prolog ANSI((int, char* []));
void Epilog ANSI((int));
char * Get_current_dir ANSI(());
int Set_dir ANSI((char*));
char Get_switch_char ANSI(());
FILE* Get_temp ANSI((char **, char *, int));
FILE * Start_temp ANSI((char *, CELLPTR, char **));
void Open_temp_error ANSI((char *, char *));
void Link_temp ANSI((CELLPTR, FILE *, char *));
void Close_temp ANSI((CELLPTR, FILE *));
void Unlink_temp_files ANSI((CELLPTR));
void Handle_result ANSI((int, int, int, CELLPTR));
void Update_time_stamp ANSI((CELLPTR));
int Remove_file ANSI((char *));
void Parse ANSI((FILE *));
int Get_line ANSI((char *, FILE *));
char * Do_comment ANSI((char *, char **, int));
char * Get_token ANSI((TKSTRPTR, char *, int));
void Quit ANSI(());
void Read_state ANSI(());
void Write_state ANSI(());
int Check_state ANSI((CELLPTR, STRINGPTR *, int));
char* basename ANSI((char *));
void Dump ANSI(());
void Dump_recipe ANSI((STRINGPTR));
int Parse_macro ANSI((char *, int));
int Macro_op ANSI((char *));
int Parse_rule_def ANSI((int *));
int Rule_op ANSI((char *));
void Add_recipe_to_list ANSI((char *, int, int));
void Bind_rules_to_targets ANSI((int));
int Set_group_attributes ANSI((char *));
DFALINKPTR Match_dfa ANSI((char *));
void Check_circle_dfa ANSI(());
void Add_nfa ANSI((char *));
char * Exec_function ANSI((char *));
time_t seek_arch ANSI(());
void tzset () {} PUBLIC int putenv ANSI((PUBLIC int Wait_for_child(int /* abort_flg */, int /* pid */) {return (1)));
int If_root_path ANSI((char *));
int stat(pPath, pStat) pPath = Unix2MacFName ANSI(());
void make_env () { if ANSI((environ = MALLOC (1, char *), *environ = NULL));
void free_env () { while ANSI((//FREE (environ), environ = NULL));
void Remove_prq ANSI((CELLPTR));
char *tempnam (char * /* pDir */, char * pPrefix) { pName = tmpnam ANSI(());
char *Unix2MacFName(char *pUnixName) { if ANSI(());
#endif

47
dmake/mac/rmprq.c Normal file
View File

@ -0,0 +1,47 @@
/* RCS -- $Header: /u2/dvadura/src/generic/dmake/src/mac/rmprq.c,v 1.1 1992/01/24 03:29:48 dvadura Exp $
-- SYNOPSIS -- remove prerequisites code.
--
-- DESCRIPTION
-- This code is different for The Mac and for UNIX and parallel make
-- architectures since the parallel case requires the rm's to be
-- run in parallel, whereas The Mac guarantees to run them sequentially.
--
-- AUTHOR
-- Dennis Vadura, dvadura@watdragon.uwaterloo.ca
-- CS DEPT, University of Waterloo, Waterloo, Ont., Canada
--
-- COPYRIGHT
-- Copyright (c) 1990 by Dennis Vadura. All rights reserved.
--
-- This program is free software; you can redistribute it and/or
-- modify it under the terms of the GNU General Public License
-- (version 1), as published by the Free Software Foundation, and
-- found in the file 'LICENSE' included with this distribution.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warrant of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program; if not, write to the Free Software
-- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
--
-- LOG
-- $Log: rmprq.c,v $
* Revision 1.1 1992/01/24 03:29:48 dvadura
* dmake Version 3.8, Initial revision
*
*/
#include "extern.h"
PUBLIC void
Remove_prq( tcp )
CELLPTR tcp;
{
tcp->ce_flag &= ~(F_MADE|F_VISITED);
tcp->ce_time = 0L;
Make( tcp, NIL(LINK), NIL(CELL) );
}

52
dmake/mac/ruletab.c Normal file
View File

@ -0,0 +1,52 @@
/* RCS -- $Header: /u2/dvadura/src/generic/dmake/src/mac/ruletab.c,v 1.1 1992/01/24 03:29:49 dvadura Exp $
-- SYNOPSIS -- Default initial configuration of dmake.
--
-- DESCRIPTION
-- Define here the initial set of rules that are defined before
-- dmake performs any processing.
--
-- AUTHOR
-- Dennis Vadura, dvadura@watdragon.uwaterloo.ca
-- CS DEPT, University of Waterloo, Waterloo, Ont., Canada
--
-- COPYRIGHT
-- Copyright (c) 1990 by Dennis Vadura. All rights reserved.
--
-- This program is free software; you can redistribute it and/or
-- modify it under the terms of the GNU General Public License
-- (version 1), as published by the Free Software Foundation, and
-- found in the file 'LICENSE' included with this distribution.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warrant of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program; if not, write to the Free Software
-- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
--
-- LOG
-- $Log: ruletab.c,v $
* Revision 1.1 1992/01/24 03:29:49 dvadura
* dmake Version 3.8, Initial revision
*
*/
/* These are control macros for dmake that MUST be defined at some point
* if they are NOT dmake will not work! These are default definitions. They
* may be overridden inside the .STARTUP makefile, they are here
* strictly so that dmake can parse the STARTUP makefile */
static char *_rules[] = {
"MAXLINELENGTH := 4094",
"MAXPROCESSLIMIT := 1",
"MAXPROCESS := 1",
".IMPORT .IGNORE: MPW DMSTARTUPDIR",
".MAKEFILES : makefile.mk makefile",
".SOURCE : .NULL",
#include "startup.h"
0 };
char **Rule_tab = _rules; /* for sundry reasons in Get_environment() */

7
dmake/mac/startup.h Normal file
View File

@ -0,0 +1,7 @@
/* This file contains the default value of the DMMAKESTARTUP variable.
* You must set the quoted string below to the default path to the startup
* variable, so that it gets compiled in. LEAVE DMSTARTUPDIR in
* the path. This allows the user to customize his environment for dmake
* by setting up a new DMSTARTUPDIR environment variable. */
"MAKESTARTUP := $(MPW)tools:$(DMSTARTUPDIR)startup.mk",

126
dmake/mac/startup.mk Normal file
View File

@ -0,0 +1,126 @@
# MPW Mac startup file. Customize to suit your needs.
# Assumes MPW C. Change as req'd.
# See the documentation for a description of internally defined macros.
#
# Disable warnings for macros redefined here that were given
# on the command line.
__.SILENT := $(.SILENT)
.SILENT := yes
# Configuration parameters for DMAKE startup.mk file
# Set these to NON-NULL if you wish to turn the parameter on.
_HAVE_RCS := yes # yes => RCS is installed.
_HAVE_SCCS := # yes => SCCS is installed.
# Applicable suffix definitions
A := .lib # Libraries
C := .c # C
E := # Executables
F := .f # Fortran
O := .c.o # Object files: Assume they are created from C files
P := .p # Pascal
S := .a # Assembler sources
V := v # RCS suffix
# See if these are defined
TMPDIR := $(MPW)/tmp
.IMPORT .IGNORE : TMPDIR
.IMPORT .IGNORE : CLibraries Libraries
# Set arguments for the SHELL. Since we can't execute sub-processes,
# these variables are not important, except for some makefiles that check
# for some values to determine the platform.
SHELL := mpw
SHELLFLAGS :=
GROUPFLAGS :=
SHELLMETAS :=
GROUPSUFFIX :=
DIVFILE = $(TMPFILE)
# Standard C-language command names and flags
CC := c # C-compiler and flags
CFLAGS +=
AS := asm # Assembler and flags
ASFLAGS +=
LD = link # Loader and flags
LDFLAGS +=
LDLIBS = "$(CLibraries)CSANELib.o" "$(CLibraries)Math.o" \
"$(CLibraries)StdCLib.o" "$(Libraries)Runtime.o" \
"$(Libraries)Interface.o" "$(Libraries)Toollibs.o"
# Definition of $(MAKE) macro for recursive makes.
MAKE = $(MAKECMD) $(MFLAGS)
# Language and Parser generation Tools and their flags
YACC := yacc # standard yacc
YFLAGS +=
YTAB := ytab # yacc output files name stem.
LEX := lex # standard lex
LFLAGS +=
LEXYY := lex_yy # lex output file
# Other Compilers, Tools and their flags
PC := any_pc # pascal compiler
RC := anyf77 # ratfor compiler
FC := anyf77 # fortran compiler
CO := co # check out for RCS
COFLAGS += -q
RM := delete # remove a file command
RMFLAGS +=
# Implicit generation rules for making inferences.
# We don't provide .yr or .ye rules here. They're obsolete.
# Rules for making *$O
%$C.o : %$C ; $(CC) $(CFLAGS) -c $<
%$P.o : %$P ; $(PC) $(PFLAGS) -c $<
%$S.o : %$S ; $(AS) $(ASFLAGS) $(<:s,/,\);
%$F.o : %$F ; $(FC) $(RFLAGS) $(EFLAGS) $(FFLAGS) -c $<
# Executables rules should go here. However, on the Mac, there is not
# executable suffix (such as ".exe") and thus we end up with rules like
# "% : %.c.o", which cause circular-dependency errors. Thus, it's easier
# just to avoid specifiying any default rule for executables.
# lex and yacc rules
%.c : %.y ; $(YACC) $(YFLAGS) $<; mv $(YTAB).c $@
%.c : %.l ; $(LEX) $(LFLAGS) $<; mv $(LEXYY).c $@
# RCS support
.IF $(_HAVE_RCS)
% : $$(@:d)RCS$$(DIRSEPSTR)$$(@:f)$V;- $(CO) $(COFLAGS) $@
.NOINFER : $$(@:d)RCS$$(DIRSEPSTR)$$(@:f)$V
.END
# SCCS support
.IF $(_HAVE_SCCS)
% : s.% ; get $@
.NOINFER : s.%
.END
# DMAKE uses this recipe to remove intermediate targets
.REMOVE :; $(RM) $<
# AUGMAKE extensions for SYSV compatibility
@B = $(@:b)
@D = $(@:d)
@F = $(@:f)
"*B" = $(*:b)
"*D" = $(*:d)
"*F" = $(*:f)
<B = $(<:b)
<D = $(<:d)
<F = $(<:f)
?B = $(?:b)
?F = $(?:f)
?D = $(?:d)
# Turn warnings back to previous setting.
.SILENT := $(__.SILENT)
# Local init file if any, gets parsed before user makefile
.INCLUDE .IGNORE: "_startup.mk"

23
dmake/mac/sysintf.h Normal file
View File

@ -0,0 +1,23 @@
/*
** assorted bits of system interface, for common routines inside dmake.
** System specific code can be found in the config.h files for each
** of the system specifications.
*/
#define STAT stat
#define VOID_LCACHE(l,m)
#define Hook_std_writes(A)
#define GETPID 1
/*
** standard C items
*/
/*
** Mac interface standard items
*/
#define getswitchar() '-'
/*
** make parameters
*/
#define MAX_PATH_LEN 1024

72
dmake/mac/tempnam.c Normal file
View File

@ -0,0 +1,72 @@
/* RCS -- $Header: /u2/dvadura/src/generic/dmake/src/mac/tempnam.c,v 1.1 1992/01/24 03:29:52 dvadura Exp $
-- SYNOPSIS -- Fake tempnam function for the mac
--
-- DESCRIPTION
-- Get a temporary file name.
--
-- AUTHOR
-- Dennis Vadura, dvadura@watdragon.uwaterloo.ca
-- CS DEPT, University of Waterloo, Waterloo, Ont., Canada
--
--
-- COPYRIGHT
-- Copyright (c) 1990 by Dennis Vadura. All rights reserved.
--
-- This program is free software; you can redistribute it and/or
-- modify it under the terms of the GNU General Public License
-- (version 1), as published by the Free Software Foundation, and
-- found in the file 'LICENSE' included with this distribution.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warrant of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program; if not, write to the Free Software
-- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
--
-- LOG
-- $Log: tempnam.c,v $
* Revision 1.1 1992/01/24 03:29:52 dvadura
* dmake Version 3.8, Initial revision
*
*/
#include "extern.h"
#include <StdIO.h>
#include <String.h>
/*
* Try to open a temporary file in the given directory (if non-NULL)
* with the given prefix (if non-NULL).
*
* We ignore the directory argument.
*/
PUBLIC char *tempnam (char * /* pDir */, char * pPrefix) {
char *pName;
char *pFullName;
pName = tmpnam ((char *) NULL);
/* Assume that if the name returned by tmpnam is not being used,
the name with the prefix is also not being used. */
pFullName = MALLOC (((pPrefix != NULL) ? strlen (pPrefix) : 0) +
strlen (pName) + 1, char);
/* Copy in the name if we successfully allocated space for it. */
if (pFullName != NULL) {
if (pPrefix != NULL) {
strcpy (pFullName, pPrefix);
} else {
*pFullName = '\0';
} /* if ... else */
strcat (pFullName, pName);
} /* if */
return (pFullName);
} /* PUBLIC char *tempnam () */

114
dmake/mac/tomacfil.c Normal file
View File

@ -0,0 +1,114 @@
/* RCS -- $Header: /u2/dvadura/src/generic/dmake/src/mac/tomacfil.c,v 1.1 1992/01/24 03:29:53 dvadura Exp $
-- SYNOPSIS -- Routines to change unix file names to mac file names
--
-- DESCRIPTION
-- Dmake sometimes assumes that files have '/' as a directory parameter in some makefiles.
-- This works, even on DOS, but not on the Mac. In fact, on the Mac, you can't even do a
-- a simple switch of ':' for '/' because all other the Mac has decided to reverse the use
-- of a first-character directory delimiter to mean a relative path rather than absolute path.
-- (i.e., ':test:b' means directory test is relative to the current directory, rather than
-- a top-level directory. Thus, this file attempts to do the directory conversion behind
-- the back of the rest of the program.
--
-- AUTHOR
-- Dennis Vadura, dvadura@watdragon.uwaterloo.ca
-- CS DEPT, University of Waterloo, Waterloo, Ont., Canada
--
--
-- COPYRIGHT
-- Copyright (c) 1990 by Dennis Vadura. All rights reserved.
--
-- This program is free software; you can redistribute it and/or
-- modify it under the terms of the GNU General Public License
-- (version 1), as published by the Free Software Foundation, and
-- found in the file 'LICENSE' included with this distribution.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warrant of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program; if not, write to the Free Software
-- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
--
-- LOG
-- $Log: tomacfil.c,v $
* Revision 1.1 1992/01/24 03:29:53 dvadura
* dmake Version 3.8, Initial revision
*
*/
#include "extern.h"
int IsUnixFName (char *pFileName);
/*
* Convert a file that may be in unix format to mac format.
*
* The returned name is either the untouched pUnixName, or a static buffer.
*/
PUBLIC char *Unix2MacFName(char *pUnixName) {
static char MacName[256];
char *pCurMac;
if (IsUnixFName (pUnixName)) {
if (strlen (pUnixName) + (*pUnixName == '/' ? -1 : 1) >= sizeof (MacName)) {
Fatal ("File name '%s' is too long and will cause a buffer overflow", pUnixName);
} /* if */
/* Set up relative or absolute path */
pCurMac = MacName;
if (*pUnixName == '/') {
++pUnixName;
} else {
*(pCurMac++) = ':';
} /* if ... else */
/* Convert the rest of the name */
while (*pUnixName != '\0') {
if (*pUnixName == '/') {
*(pCurMac++) = ':';
pUnixName++;
} else {
*(pCurMac++) = *(pUnixName++);
} /* if ... else */
} /* while */
*pCurMac = '\0';
return (MacName);
} else {
return (pUnixName);
} /* if ... else */
} /* PUBLIC char *Unix2MacFName() */
/*
* Is this file name in UNIX format?
* (We assume it is if there are any slashes in its name.)
*/
int IsUnixFName (char *pFileName) {
for ( ; *pFileName != '\0'; ++pFileName) {
if (*pFileName == '/') {
return (TRUE);
} /* if */
} /* while */
return (FALSE);
} /* int IsUnixFName () */
/*
* Call the real fopen() from this override of the function
* that the rest of the program uses.
*/
#undef fopen
PUBLIC FILE *MacFOpen (char *pFName, char *pMode) {
return (fopen (Unix2MacFName (pFName), pMode));
} /* PUBLIC FILE *MacFOpen () */

167
dmake/macparse.c Normal file
View File

@ -0,0 +1,167 @@
/* RCS -- $Header: /u2/dvadura/src/generic/dmake/src/RCS/macparse.c,v 1.1 1992/01/24 03:27:52 dvadura Exp $
-- SYNOPSIS -- parse a macro definition
--
-- DESCRIPTION
-- This file contains the code that parses a macro definition
-- stored in a buffer. If the string in buffer is not a valid
-- macro definition the routie Parse_macro returns 0, otherwise it
-- returns 1 to indicate success.
--
-- AUTHOR
-- Dennis Vadura, dvadura@watdragon.uwaterloo.ca
-- CS DEPT, University of Waterloo, Waterloo, Ont., Canada
--
-- COPYRIGHT
-- Copyright (c) 1990 by Dennis Vadura. All rights reserved.
--
-- This program is free software; you can redistribute it and/or
-- modify it under the terms of the GNU General Public License
-- (version 1), as published by the Free Software Foundation, and
-- found in the file 'LICENSE' included with this distribution.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warrant of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program; if not, write to the Free Software
-- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
--
-- LOG
-- $Log: macparse.c,v $
* Revision 1.1 1992/01/24 03:27:52 dvadura
* dmake Version 3.8, Initial revision
*
*/
#include "extern.h"
PUBLIC int
Parse_macro( buffer, flag )/*
=============================
Parse the string in buffer and define it as a macro if it is a valid macro.
Note especially the string .SETDIR= since it is an attribute, but looks a
lot like a macro definition. This would not be a problem if make used
white space as token separators, since this is not the case we must do
something about it. */
char *buffer;
int flag;
{
register char *tok1; /* temporary place to keep a token */
register char *tok2; /* temporary place to keep a token */
char *result; /* temporary pointer for strings */
TKSTR input; /* place to scan the buffer from */
HASHPTR hv; /* pointer to hash table value */
int operator; /* what macro operator do we have */
DB_ENTER( "Parse_macro" );
SET_TOKEN( &input, buffer );
tok1 = Get_token( &input, "=+:*", 0 );
if( Macro_op( tok1 ) ) {
Error( "No macro name" );
CLEAR_TOKEN( &input );
DB_RETURN( 1 );
}
tok1 = _strdup( tok1 );
tok2 = Get_token( &input, "=+:*", 2 );
if( !(operator = Macro_op(tok2)) ||
(!strcmp(tok1, ".SETDIR") &&
((operator != M_OP_CL) || (operator != M_OP_PLCL) ||
(operator != M_OP_DFCL))) ) {
CLEAR_TOKEN( &input );
FREE( tok1 );
DB_RETURN( 0 );
}
tok2 = Expand(tok1); FREE(tok1); tok1 = tok2;
tok2 = Get_token( &input, NIL( char ), FALSE );
switch( operator ) {
case M_OP_PLCL:
tok2 = Expand( tok2 );
/* Fall thru */
case M_OP_PL:
/* Add to an existing macro, if it is not defined, though, then
* just define a new macro */
if( (hv = GET_MACRO(tok1)) == NIL(HASH) || hv->ht_value == NIL(char) )
Def_macro( tok1, tok2, flag );
else {
result = _stradd( hv->ht_value, tok2, FALSE );
Def_macro( tok1, result, flag );
FREE( result );
}
if( operator == M_OP_PLCL ) FREE(tok2);
break;
case M_OP_DF:
if( (hv = GET_MACRO(tok1)) != NIL(HASH) )
break;
/* else FALLTHRU */
case M_OP_EQ:
Def_macro( tok1, tok2, flag );
break;
case M_OP_DFCL:
if( (hv = GET_MACRO(tok1)) != NIL(HASH) )
break;
/* else FALLTHRU */
case M_OP_CL:
/* If the macro we are assigning from is a single control
* macro with nothing else, then we propagate the M_MULTI
* flag to the macro we are assigning the value to so that
* the same macro can be used to do this over and over. */
If_multi = 0;
tok2 = Expand( tok2 );
Def_macro( tok1, tok2, M_EXPANDED | flag | If_multi );
FREE( tok2 );
break;
}
FREE( tok1 );
DB_RETURN( 1 );
}
PUBLIC int
Macro_op( op )/*
================
Check the passed in op string and map it to one of the macro operators */
char *op;
{
int ret = 0;
DB_ENTER( "macro_op" );
switch( *op ) {
case '=': ret = M_OP_EQ; break;
case ':': ret = M_OP_CL; op++; break;
case '+':
ret = M_OP_PL; op++;
if( *op == ':' ) { ret = M_OP_PLCL; op++; }
break;
case '*':
ret = M_OP_DF; op++;
if( *op == ':' ) { ret = M_OP_DFCL; op++; }
break;
}
if( *op++ != '=' )
ret = 0;
else if( *op != '\0' )
ret = 0;
DB_RETURN( ret );
}

165
dmake/make.bat Normal file
View File

@ -0,0 +1,165 @@
echo off
cls
rem *** This is the make batchfile that is used under MSDOS to make the
rem *** first version of dmake. It isn't pretty but it does work, assuming
rem *** the compilers have been correctly setup. See the warning below
rem *** concerning tlink, if you are making the Turbo C version.
rem
if %0%1 == %0 goto error
if %1 == tcc goto mktcc
if %1 == tccswp goto mktccswp
if %1 == bcc goto mkbcc
if %1 == bccswp goto mkbccswp
if %1 == msc40 goto mkmsc40
if %1 == msc40swp goto mkmsc40swp
if %1 == msc50 goto mkmsc50
if %1 == msc50swp goto mkmsc50swp
if %1 == msc51 goto mkmsc51
if %1 == msc51swp goto mkmsc51swp
if %1 == msc60 goto mkmsc60
if %1 == msc60swp goto mkmsc60swp
if %1 == ztc goto mkztc
if %1 == ztcswp goto mkztcswp
rem label the possible DOS variations for dmake here.
:error
echo MSDOS: You must specify 'make target' where target is one of:
echo -------------
echo tcc - Turbo C 2.0 compile.
echo tccswp - Turbo C 2.0 compile of swapping dmake.
echo bcc - Borland C++ 2.0,3.0 compile.
echo bccswp - Borland C++ 2.0,3.0 compile of swapping dmake.
echo msc40 - Microsoft C 4.0 compile.
echo msc50 - Microsoft C 5.0 compile.
echo msc51 - Microsoft C 5.1 compile.
echo msc60 - Microsoft C 6.0 compile.
echo msc40swp - Microsoft C 4.0, MASM 5.1 compile of swapping dmake.
echo msc50swp - Microsoft C 5.0, MASM 5.1 compile of swapping dmake.
echo msc51swp - Microsoft C 5.1, MASM 5.1 compile of swapping dmake.
echo msc60swp - Microsoft C 6.0, MASM 5.1 compile of swapping dmake.
echo ztc - Zortech C++ 2.1 compile.
echo ztcswp - Zortech C++ 2.1 compile of swapping dmake.
goto end
rem This is the script that makes dmake using Microsoft C 4.0
:mkmsc40
msdos\mscdos\mk40.bat
goto end
:mkmsc40swp
msdos\mscdos\mk40swp.bat
goto end
rem This is the script that makes dmake using Microsoft C 5.0
:mkmsc50
msdos\mscdos\mk50.bat
goto end
:mkmsc50swp
msdos\mscdos\mk50swp.bat
goto end
rem This is the script that makes dmake using Microsoft C 5.1
:mkmsc51
msdos\mscdos\mk51.bat
goto end
:mkmsc51swp
msdos\mscdos\mk51swp.bat
goto end
rem This is the script that makes dmake using Microsoft C 6.0
:mkmsc60
msdos\mscdos\mk60.bat
goto end
:mkmsc60swp
msdos\mscdos\mk60swp.bat
goto end
rem This is the script that makes dmake using Zortech C++ 2.1
:mkztc
msdos\ztcdos\mk.bat
goto end
:mkztcswp
msdos\ztcdos\mkswp.bat
goto end
rem This is the script that makes dmake using Turbo C 2.0 or higher.
:mktcc
cls
echo WARNING:
echo The default response files:
echo msdos\tccdos\obj.rsp
echo msdos\tccdos\lib.rsp
echo contain absolute paths to TURBO-C runtime startup objects, and to
echo the standard libraries. You should check that these files contain
echo the correct path names for your installation of Turbo-C before
echo proceeding further. Also check that the mkdir command at the start
echo of the response file and the copy command at the end of the response
echo file will work on your system.
echo --
echo Continue if ok, or abort and edit the response files.
pause
msdos\tccdos\mk.bat
goto end
:mktccswp
cls
echo WARNING:
echo The default response files:
echo msdos\tccdos\objswp.rsp
echo msdos\tccdos\libswp.rsp
echo contain absolute paths to TURBO-C runtime startup objects, and to
echo the standard libraries. You should check that these files contain
echo the correct path names for your installation of Turbo-C before
echo proceeding further. Also check that the mkdir command at the start
echo of the response file and the copy command at the end of the response
echo file will work on your system.
echo --
echo Continue if ok, or abort and edit the response files.
pause
msdos\tccdos\mkswp.bat
goto end
rem This is the script that makes dmake using Turbo C++ 2.0.
:mkbcc
cls
echo WARNING:
echo The default response files:
echo msdos\bccdos\obj.rsp
echo msdos\bccdos\lib.rsp
echo contain absolute paths to Borland C++ runtime startup objects, and to
echo the standard libraries. You should check that these files contain
echo the correct path names for your installation of Borland C++ before
echo proceeding further. Also check that the mkdir command at the start
echo of the response file and the copy command at the end of the response
echo file will work on your system.
echo --
echo Continue if ok, or abort and edit the response files.
pause
msdos\bccdos\mk.bat
goto end
:mkbccswp
cls
echo WARNING:
echo The default response files:
echo msdos\bccdos\objswp.rsp
echo msdos\bccdos\libswp.rsp
echo contain absolute paths to Borland C++ runtime startup objects, and to
echo the standard libraries. You should check that these files contain
echo the correct path names for your installation of Borland C++ before
echo proceeding further. Also check that the mkdir command at the start
echo of the response file and the copy command at the end of the response
echo file will work on your system.
echo --
echo Continue if ok, or abort and edit the response files.
pause
msdos\bccdos\mkswp.bat
goto end
rem All done!
:end

1028
dmake/make.c Normal file

File diff suppressed because it is too large Load Diff

53
dmake/make.cmd Normal file
View File

@ -0,0 +1,53 @@
echo off
cls
rem *** This is the make command file that is used under OS/2 to make the
rem *** first version of dmake. It isn't pretty but it does work, assuming
rem *** the compilers have been correctly setup.
rem
echo Running make.cmd script to make a %1 copy of dmake.
if %0%1 == %0 goto error
if %1 == msc40 goto mkmsc40
if %1 == msc50 goto mkmsc50
if %1 == msc51 goto mkmsc51
if %1 == msc60 goto mkmsc60
if %1 == ibm goto mkibm
rem label the possible DOS variations for dmake here.
:error
echo OS/2 INDEX: You must specify one of:
echo ------------------
echo msc40 - Microsoft C 4.0 compile.
echo msc50 - Microsoft C 5.0 compile.
echo msc51 - Microsoft C 5.1 compile.
echo msc60 - Microsoft C 6.0 compile.
3cho ibm - IBM C 2.0 compile.
goto end
rem This is the script that makes dmake using Microsoft C 4.0
:mkmsc40
os2\mscdos\mk40.cmd
goto end
rem This is the script that makes dmake using Microsoft C 5.0
:mkmsc50
os2\mscdos\mk50.cmd
goto end
rem This is the script that makes dmake using Microsoft C 5.1
:mkmsc51
os2\mscdos\mk51.cmd
goto end
rem This is the script that makes dmake using Microsoft C 6.0
:mkmsc60
os2\mscdos\mk60.cmd
goto end
rem This is the script that makes dmake using Microsoft C 6.0
:ibm
os2\ibm\mkc2.cmd
goto end
rem All done!
:end

73
dmake/makefile Normal file
View File

@ -0,0 +1,73 @@
# Default makefile for the various versions of dmake that we
# have available. This is a bootstrap version and uses /bin/sh to
# execute a script which compiles dmake.
#
# Note the DOS commands actually invoke command.com to run the .bat file
# to make the script.
all :
@-echo ""; clear; exit 0
@echo "INDEX: You must specify 'make target' where target is one of:"
@echo "-------------"
@echo " make bsd43 - Generic BSD 4.3 System"
@echo " make bsd43uw - Generic BSD 4.3 at U of Waterloo"
@echo " make bsd43vf - Generic BSD 4.3 that needs vfprintf"
@echo " make sysvr4 - Generic SysV R4 UNIX System"
@echo " make sysvr3 - Generic SysV R3 UNIX System"
@echo " make sysvr3pwd - Generic SysV R3 UNIX System, our PWD, (Any HP System)"
@echo " make sysvr1 - Generic SysV R1 UNIX System"
@echo " make dynix - Sequent DYNIX System"
@echo " make ultrix - Ultrix 3.0 System"
@echo " make mips - Any MIPS System"
@echo " make coherent - Any Coherent System"
@echo " make 386ix - 386/ix (SysV R3) System"
@echo " make xenix - 386 Xenix System"
@echo " make xenixpwd - 386 Xenix System, our PWD"
@echo " make aix - IBM RS6000/AIX System"
@echo " make os2msc40 - OS/2 using MSC 4.0 compiler"
@echo " make os2msc50 - OS/2 using MSC 5.0 compiler"
@echo " make os2msc51 - OS/2 using MSC 5.1 compiler"
@echo " make os2msc60 - OS/2 using MSC 6.0 compiler"
@echo " make os2ibm - OS/2 using IBM C 2.0 compiler"
@echo " make tos - Atari-ST TOS using GCC as compiler"
@echo " make tcc - DOS with Turbo C 2.0"
@echo " make bcc - DOS with Borland C++ 3.0"
@echo " make tccswp - swapping DOS version with Turbo C 2.0"
@echo " make bccswp - swapping DOS version with Borland C++ 3.0"
@echo " make msc40 - DOS with MSC 4.0"
@echo " make msc50 - DOS with MSC 5.0"
@echo " make msc51 - DOS with MSC 5.1"
@echo " make msc60 - DOS with MSC 6.0"
@echo " make msc40swp - swapping DOS version with MSC 4.0"
@echo " make msc50swp - swapping DOS version with MSC 5.0"
@echo " make msc51swp - swapping DOS version with MSC 5.1"
@echo " make msc60swp - swapping DOS version with MSC 6.0"
@echo " make ztc - DOS with Zortech C++ 2.1"
@echo " make ztcswp - swapping DOS version with Zortech C++ 2.1"
@echo " make mpwmac - Macintosh under MPW"
ultrix aix: sysvr3;
sysvr1 sysvr3 sysvr4 bsd43 386ix :; /bin/sh -x < unix/$@/make.sh
bsd43uw :; /bin/sh -x < unix/bsd43/uw/make.sh
bsd43vf dynix mips :; /bin/sh -x < unix/bsd43/vf/make.sh
coherent :; /bin/sh -x < unix/coherent/make.sh
xenix :; /bin/sh -x < unix/xenix/make.sh
xenixpwd :; /bin/sh -x < unix/xenix/pwd/make.sh
sysvr3pwd :; /bin/sh -x < unix/sysvr3/pwd/make.sh
tos :; sh -x tos/make.sh
mpwmac :; :mac:make.sh
# Various OS/2 targets.
OS2_VER = os2msc40 os2msc50 os2msc51 os2msc60 os2ibm
$(OS2_VER) :; make.cmd $(@:s/os2//)
# DOS with some form of make and sh
# Note if you do not have a 'make and/or sh' program under MSDOS then
# typing 'make' in the dmake distribution directory will invoke the make.bat
# batch file which will issue the appropriate instructions.
DOS_VER = tcc msc40 msc50 msc51 msc60 \
tccswp msc40swp msc50swp msc51swp msc60swp \
bcc bccswp ztc ztcswp
$(DOS_VER) :; make.bat $@

342
dmake/makefile.mk Normal file
View File

@ -0,0 +1,342 @@
# //// Makefile for DMAKE. \\\\
# The target system is characterized by the following macros imported from
# the environment.
#
# OS - gives the class of operating system
# OSRELEASE - optionally gives the particular release of the OS above.
# OSENVIRONMENT - optionally gives the environment under which the above
# OS is in use.
#
# For valid values for the above macros consult the readme/* files or type
# 'make' by itself to get a summary of what is available.
# First target in the makefile, do this so that targets declared in the
# included files are never marked as being the first *default* target.
first : all ;
#Enable keeping of state for future compiles
.KEEP_STATE := _state.mk
# Pull in the configuration macros, from the environment. OS is required,
# OSRELEASE, and OSENVIRONMENT are optional.
.IF $(OS) == $(NULL)
.IMPORT : OS
.END
.IMPORT .IGNORE : OSRELEASE OSENVIRONMENT TMPDIR
# Define $(PUBLIC)
_osenv := $(OSENVIRONMENT)$(DIRSEPSTR)
_osre := $(OSRELEASE)$(DIRSEPSTR)$(!null,$(OSENVIRONMENT) $(_osenv))
ENVDIR = $(OS)$(DIRSEPSTR)$(!null,$(OSRELEASE) $(_osre))
PUBLIC = $(ENVDIR)public.h
STARTUP := startup.mk
# Define the source files
SRC =\
infer.c make.c stat.c expand.c dmstring.c hash.c dag.c dmake.c\
path.c imacs.c sysintf.c parse.c getinp.c quit.c state.c\
basename.c dmdump.c macparse.c rulparse.c percent.c function.c
# Common Include files.
HDR = dmake.h extern.h struct.h vextern.h patchlvl.h version.h
# Define the TARGET we are making, and where the OBJECT files go.
OBJDIR := objects
TARGET = dmake$E
CFLAGS += -I.
# Meta rule for making .o's from .c's (give our own so we can move object
# to objects directory in a portable, compiler independent way)
# Define it before the .INCLUDE so that different OS combinations can redefine
# it.
%$O : %.c
.IF $(SHELL) == mpw
%$(CC) $(CFLAGS) -o :$(OBJDIR:s,/,:,):$@ $<
.ELSE
%$(CC) -c $(CFLAGS) $<
.IF $(SHELL) != $(COMSPEC)
mv $(@:f) $(OBJDIR)
.ELSE
+copy $(@:f) $(OBJDIR)
+del $(@:f)
.ENDIF
.ENDIF
# Pull in the proper configuration files, based on the value of OS.
.INCLUDE : $(OS)/config.mk
.INCLUDE : dbug/dbug.mk
# Set the .SOURCE targets so that we look for things in the right place.
.SOURCE.c :^ .NULL
.SOURCE.h :^ .NULL
.SOURCE$O :^ $(OBJDIR)
.PRECIOUS : $(HDR)
# Must come after the above INCLUDE so that it gets ALL objects.
OBJECTS := {$(ASRC:b) $(SRC:b)}$O
# The main target, make sure the objects directory exists first.
# LDARGS is defined in config.mk file of each OS/OSRELEASE combination.
all : $(TARGET) $(STARTUP);
$(TARGET) : $(OBJDIR)
$(TARGET) : $(OBJECTS);$(LD) $(LDARGS)
.IF $(SHELL) == mpw
$(STARTUP) : $(ENVDIR)$(STARTUP); duplicate :$(<:s,/,:,) $@
.ELSE
$(STARTUP) : $(ENVDIR)$(STARTUP); $(eq,$(SHELL),$(COMSPEC) +copy cp) $< $@
.ENDIF
# how to make public.h
public .PHONY : $(PUBLIC);
$(PUBLIC) .SHELL .NOSTATE: $(SRC)
genpub -n DMAKE $< >$@
rcsclean $@ > /dev/null
# Other obvious targets...
.IF $(SHELL) == mpw
$(OBJDIR):;-newfolder $@
.ELSE
$(OBJDIR):;-$(eq,$(SHELL),$(COMSPEC) +md mkdir) $@
.ENDIF
# remaining dependencies should be automatically generated
sysintf$O : $(OS)/sysintf.h
ruletab$O : $(OS)/startup.h #khc 01NOV90 - dependency was missing
$(OBJECTS) : $(HDR)
clean:;+- $(RM) -rf dmake$E dbdmake$E objects* $(STARTUP) _*state*.mk
# Rules for making the manual pages.
man .SETDIR=man : dmake.nc dmake.uue ;
dmake.nc : dmake.p ; scriptfix < $< > $@
dmake.p : dmake.tf; typeset -man -Tdumb $< > $@
dmake.uue : dmake.p
compress -b 12 dmake.p
mv dmake.p.Z dmake.Z
uuencode dmake.Z dmake.Z >dmake.uue
/bin/rm -f dmake.Z
#--------------------------------------------------------------------------
# Make the various archives for shipping the thing around.
#
archives : zoo tar shar;
zoo .PHONY : dmake.zoo ;
shar .PHONY : dmake.shar;
tar .PHONY : dmake.tar;
dmake.zoo : dir-copy
[
find dmake -type f -print | zoo aI $@
$(RM) -rf src-list dmake
]
dmake.shar : dir-copy
[
find dmake -type f -print >src-list
xshar -vc -o$@ -L40 `cat src-list`
$(RM) -rf src-list dmake
]
dmake.tar : dir-copy
[
tar cf $@ dmake
$(RM) -rf src-list dmake
]
dir-copy .PHONY : src-list
[
echo 'tmp.tar .SILENT :$$(ALLSRC) ;tar -cf tmp.tar $$(ALLSRC)' >> $<
$(MAKECMD) -f $< tmp.tar
mkdir dmake
cd dmake
tar xf ../tmp.tar; chmod -R u+rw .
cd ..
/bin/rm -f tmp.tar
]
src-list : clean man
echo 'ALLSRC = \' >$@
find . -type f -print |\
sed -e 's/RCS\///' -e 's/,v//' -e 's/$$/\\/' -e 's/^\.\// /'|\
sort -u |\
grep -v tst | grep -v $@ | grep -v LICENSE |\
grep -v '\.zoo' | grep -v '\.tar'| grep -v '\.shar' >> $@
echo ' LICENSE' >> $@
#--------------------------------------------------------------------------
# This section can be used to make the necessary script files so that dmake
# can be bootstrapped.
#
# dmake scripts -- makes all the script files at once.
#
SH_n = $(@:s/swp-/-/:s,-,/,:s/scripts/${SCRIPTFILE}/)
MS_n = MAKESTARTUP=$(@:s/swp-/-/:s,-,/,:s/scripts/startup.mk/)
SH = $(SH_n:s/c40d/cd/:s/c50d/cd/:s/c51d/cd/:s/c60d/cd/:s/ibmc2/ibm/)
MS = $(MS_n:s/c40d/cd/:s/c50d/cd/:s/c51d/cd/:s/c60d/cd/:s/ibmc2/ibm/)
FIX-SH = $(SH:s,fix/,,)
scripts: unix-scripts atari-tos-scripts msdos-scripts os2-scripts\
apple-mac-scripts
# To add a new environment for UNIX, simply create the appropriate entry
# in the style below for the macro which contains the OS, OSRELEASE and
# OSENVIRONMENT flags. Then add the entry as a recipe line for the target
# unix-scripts.
#
unix-bsd43-scripts-flags = OS=unix OSRELEASE=bsd43 OSENVIRONMENT=
unix-bsd43-uw-scripts-flags= OS=unix OSRELEASE=bsd43 OSENVIRONMENT=uw
unix-bsd43-vf-scripts-flags= OS=unix OSRELEASE=bsd43 OSENVIRONMENT=vf
unix-sysvr4-scripts-flags = OS=unix OSRELEASE=sysvr4 OSENVIRONMENT=
unix-sysvr3-scripts-flags = OS=unix OSRELEASE=sysvr3 OSENVIRONMENT=
unix-sysvr3-pwd-scripts-flags = OS=unix OSRELEASE=sysvr3 OSENVIRONMENT=pwd
unix-xenix-scripts-flags = OS=unix OSRELEASE=xenix OSENVIRONMENT=
unix-xenix-pwd-scripts-flags = OS=unix OSRELEASE=xenix OSENVIRONMENT=pwd
unix-sysvr1-scripts-flags = OS=unix OSRELEASE=sysvr1 OSENVIRONMENT=
unix-386ix-scripts-flags = OS=unix OSRELEASE=386ix OSENVIRONMENT=
unix-coherent-scripts-flags= OS=unix OSRELEASE=coherent OSENVIRONMENT=
unix-gno-scripts-flags = OS=unix OSRELEASE=gno OSENVIRONMENT=
tos--scripts-flags = OS=tos OSRELEASE= OSENVIRONMENT=
mac--scripts-flags = OS=mac OSRELEASE= OSENVIRONMENT=
unix-scripts .SWAP : clean
$(MAKE) SCRIPTFILE=make.sh unix-bsd43-scripts
$(MAKE) SCRIPTFILE=make.sh unix-bsd43-uw-scripts
$(MAKE) SCRIPTFILE=make.sh unix-bsd43-vf-scripts
$(MAKE) SCRIPTFILE=make.sh unix-sysvr4-scripts
$(MAKE) SCRIPTFILE=make.sh unix-sysvr3-scripts
$(MAKE) SCRIPTFILE=make.sh unix-sysvr3-pwd-scripts
$(MAKE) SCRIPTFILE=make.sh unix-xenix-scripts
$(MAKE) SCRIPTFILE=make.sh unix-xenix-pwd-scripts
$(MAKE) SCRIPTFILE=make.sh unix-sysvr1-scripts
$(MAKE) SCRIPTFILE=make.sh unix-386ix-scripts
$(MAKE) SCRIPTFILE=make.sh unix-coherent-scripts
$(MAKE) SCRIPTFILE=make.sh unix-gno-scripts
unix-%-scripts .SWAP :
$(MAKECMD) -s $($@-flags) .KEEP_STATE:= public
$(MAKECMD) -ns .KEEP_STATE:= $(MS) $($@-flags) >/tmp/dmscr
dfold </tmp/dmscr >$(SH)
tos-%-scripts .SWAP :
$(MAKECMD) -s $($@-flags) .KEEP_STATE:= public
$(MAKECMD) -ns .KEEP_STATE:= $(MS) $($@-flags) >/tmp/dmscr
dfold </tmp/dmscr >$(SH)
atari-tos-scripts .SWAP : clean
$(MAKE) SCRIPTFILE=make.sh tos--scripts
apple-mac-scripts .SWAP : clean
$(MAKE) SCRIPTFILE=make.sh mac--scripts
mac-%-scripts .SWAP :
$(MAKECMD) -s $($@-flags) .KEEP_STATE:= public
$(MAKECMD) -ns .KEEP_STATE:= $(MS) $($@-flags) >$(SH)
sed 's/ mac\/\(.*\)$$/ :mac:\1/' <$(SH) | dfold >/tmp/dmscr
/bin/mv /tmp/dmscr $(SH)
# We make the standard dos scripts here, but we have to go and fix up the
# mkXX.bat file since it contains names of temporary files for the response
# files required by the linker. We need to also construct the response file
# contents. These two functions are performed by the fix-msdos-%-scripts
# meta-target.
#
# To add a new DOS environment just do what is described for adding a new
# unix environment, and then make certain that the fix-msdos-%-scripts target
# performs the correct function for the new environment.
msdos-cf = OS=msdos OSENVIRONMENT=
msdos-tccdos-scripts-flags = $(msdos-cf) OSRELEASE=tccdos SWAP=n
msdos-tccdosswp-scripts-flags = $(msdos-cf) OSRELEASE=tccdos
msdos-bccdos-scripts-flags = $(msdos-cf) OSRELEASE=bccdos SWAP=n
msdos-bccdosswp-scripts-flags = $(msdos-cf) OSRELEASE=bccdos
msdos-msc40dos-scripts-flags= $(msdos-cf) OSRELEASE=mscdos SWAP=n MSC_VER=4.0
msdos-msc40dosswp-scripts-flags = $(msdos-cf) OSRELEASE=mscdos MSC_VER=4.0
msdos-msc50dos-scripts-flags= $(msdos-cf) OSRELEASE=mscdos SWAP=n MSC_VER=5.0
msdos-msc50dosswp-scripts-flags = $(msdos-cf) OSRELEASE=mscdos MSC_VER=5.0
msdos-msc51dos-scripts-flags= $(msdos-cf) OSRELEASE=mscdos SWAP=n MSC_VER=5.1
msdos-msc51dosswp-scripts-flags = $(msdos-cf) OSRELEASE=mscdos MSC_VER=5.1
msdos-msc60dos-scripts-flags= $(msdos-cf) OSRELEASE=mscdos SWAP=n MSC_VER=6.0
msdos-msc60dosswp-scripts-flags = $(msdos-cf) OSRELEASE=mscdos MSC_VER=6.0
msdos-ztcdos-scripts-flags= $(msdos-cf) OSRELEASE=ztcdos SWAP=n
msdos-ztcdosswp-scripts-flags= $(msdos-cf) OSRELEASE=ztcdos
msdos-scripts: clean\
msdos-tcc-scripts msdos-bcc-scripts\
msdos-msc-scripts msdos-ztc-scripts;
msdos-tcc-scripts .SWAP :
$(MAKE) SCRIPTFILE=mk.bat msdos-tccdos-scripts
$(MAKE) SCRIPTFILE=mkswp.bat msdos-tccdosswp-scripts
msdos-bcc-scripts .SWAP :
$(MAKE) SCRIPTFILE=mk.bat msdos-bccdos-scripts
$(MAKE) SCRIPTFILE=mkswp.bat msdos-bccdosswp-scripts
msdos-msc-scripts .SWAP :! 40 50 51 60
$(MAKE) SCRIPTFILE=mk$?.bat msdos-msc$?dos-scripts
$(MAKE) SCRIPTFILE=mk$?swp.bat msdos-msc$?dosswp-scripts
msdos-ztc-scripts .SWAP :
$(MAKE) SCRIPTFILE=mk.bat msdos-ztcdos-scripts
$(MAKE) SCRIPTFILE=mkswp.bat msdos-ztcdosswp-scripts
msdos-%-scripts .SWAP .SILENT:
$(MAKE) -s $($@-flags) .KEEP_STATE:= public
$(MAKE) -ns SHELL=command.com COMSPEC=command.com .KEEP_STATE:= $(MS) $($@-flags) >$(SH)
$(MAKE) -s $(MAKEMACROS) $(MS) $($@-flags) fix-msdos-$*-scripts
# We make the standard OS/2 scripts here, but we have to go and fix up the
# mkXX.cmd file since it contains names of temporary files for the response
# files required by the linker. We need to also construct the response file
# contents. These two functions are performed by the fix-msdos-%-scripts
# meta-target.
#
# To add a new OS/2 environment just do what is described for adding a new
# unix environment, and then make certain that the fix-msdos-%-scripts target
# performs the correct function for the new environment.
os2-cf = OS=os2 OSENVIRONMENT=
os2-msc40dos-scripts-flags= $(os2-cf) OSRELEASE=mscdos SWAP=n MSC_VER=4.0
os2-msc50dos-scripts-flags= $(os2-cf) OSRELEASE=mscdos SWAP=n MSC_VER=5.0
os2-msc51dos-scripts-flags= $(os2-cf) OSRELEASE=mscdos SWAP=n MSC_VER=5.1
os2-msc60dos-scripts-flags= $(os2-cf) OSRELEASE=mscdos SWAP=n MSC_VER=6.0
os2-ibmc2-scripts-flags= $(os2-cf) OSRELEASE=ibm SWAP=n MSC_VER=5.1
os2-scripts: clean os2-msc-scripts os2-ibm-scripts;
os2-msc-scripts .SWAP :! 40 50 51 60
$(MAKE) SCRIPTFILE=mk$?.cmd os2-msc$?dos-scripts
os2-ibm-scripts .SWAP :! c2
$(MAKE) SCRIPTFILE=mk$?.cmd os2-ibm$?-scripts
os2-%-scripts .SWAP :
$(MAKE) -s $($@-flags) .KEEP_STATE:= public
$(MAKE) -ns SHELL=cmd.exe COMSPEC=cmd.exe .KEEP_STATE:= $(MS) $($@-flags) >$(SH)
$(MAKE) -s $(MAKEMACROS) $(MS) $($@-flags) fix-os2-$*-scripts
# Signify NULL targets for the various MSC compiler versions.
c2 40 50 51 60:;
# Go over the created script file and make sure all the '/' that are in
# filenames are '\', and make sure the final link command line looks
# reasonable.
MAPOBJ = obj$(SWAP:s/y/swp/:s/n//).rsp
MAPLIB = lib$(SWAP:s/y/swp/:s/n//).rsp
OBJRSP = $(SH:s,fix/,,:s,${SCRIPTFILE},${MAPOBJ},)
LIBRSP = $(SH:s,fix/,,:s,${SCRIPTFILE},${MAPLIB},)
DOSOBJ = $(CSTARTUP) $(OBJDIR)/{$(OBJECTS)}
fix-%-scripts:
tail -r $(FIX-SH) >tmp-sh-r
tail +3 tmp-sh-r | sed -e 's,/,\\,g' >tmp-out
tail -r tmp-out >$(FIX-SH)
head -2 tmp-sh-r |\
sed -e 's,\\usr\\tmp\\mkA[a-zA-Z]*[0-9]*,$(OBJRSP),'\
-e 's,\\usr\\tmp\\mkB[a-zA-Z]*[0-9]*,$(LIBRSP),' |\
sed -e 's,$(OS)/,$(OS)\\,g'\
-e 's,$(OS)/$(OSRELEASE)/,$(OS)\\$(OSRELEASE)\\,g'\
-e 's,$(OS)\\$(OSRELEASE)/,$(OS)\\$(OSRELEASE)\\,g'\
-e 's,$(OS)/$(OSRELEASE)\\,$(OS)\\$(OSRELEASE)\\,g' >>$(FIX-SH)
rm -f tmp-sh-r tmp-out
mv <+$(DOSOBJ:s,/,\\,:t"+\n")\n+> $(OBJRSP)
mv <+$(LDLIBS:s,/,\\,:t"+\n")\n+> $(LIBRSP)

9
dmake/man/README Normal file
View File

@ -0,0 +1,9 @@
To unpack the DMAKE manual page please issue the following sequence of
commands:
uudecode dmake.uue
uncompress dmake.Z
mv dmake dmake.p
NOTE: You only need to do this if you cannot typeset the manual page
yourself.

3200
dmake/man/dmake.nc Normal file

File diff suppressed because it is too large Load Diff

2732
dmake/man/dmake.tf Normal file

File diff suppressed because it is too large Load Diff

1248
dmake/man/dmake.uue Normal file

File diff suppressed because it is too large Load Diff

67
dmake/msdos/_chdir.c Normal file
View File

@ -0,0 +1,67 @@
/* RCS -- $Header: /u2/dvadura/src/generic/dmake/src/msdos/_chdir.c,v 1.1 1992/01/24 03:27:24 dvadura Exp $
-- SYNOPSIS -- Change directory.
--
-- DESCRIPTION
-- Under DOS change the current drive as well as the current directory.
--
-- AUTHOR
-- Dennis Vadura, dvadura@watdragon.uwaterloo.ca
-- CS DEPT, University of Waterloo, Waterloo, Ont., Canada
--
-- COPYRIGHT
-- Copyright (c) 1990 by Dennis Vadura. All rights reserved.
--
-- This program is free software; you can redistribute it and/or
-- modify it under the terms of the GNU General Public License
-- (version 1), as published by the Free Software Foundation, and
-- found in the file 'LICENSE' included with this distribution.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warrant of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program; if not, write to the Free Software
-- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
--
-- LOG
-- $Log: _chdir.c,v $
* Revision 1.1 1992/01/24 03:27:24 dvadura
* dmake Version 3.8, Initial revision
*
*/
#include <dos.h>
#include "extern.h"
PUBLIC int
_chdir(path)
char *path;
{
int res;
res = chdir(path);
#if defined(OS2)
if (res != -1 && path[1] == ':') {
unsigned new_drive;
unsigned max_drives;
/* for OS2 we must change drive without using intdos() */
new_drive = (*path & ~0x20) - 'A' + 1;
_dos_setdrive(new_drive, &max_drives);
}
#else
if (res != -1 && path[1] == ':') {
union REGS reg;
/* we must change the logged drive, since the chdir worked. */
reg.h.ah = 0x0E;
reg.h.dl = (*path & ~0x20) - 'A';
intdos(&reg, &reg);
}
#endif /* OS2 */
return (res);
}

65
dmake/msdos/arlib.c Normal file
View File

@ -0,0 +1,65 @@
/* RCS -- $Header: /u2/dvadura/src/generic/dmake/src/msdos/arlib.c,v 1.1 1992/01/24 03:27:23 dvadura Exp $
-- SYNOPSIS -- Library access code.
--
-- DESCRIPTION
-- This implementation uses the library timestamp inplace of the
-- library member timestamp.
--
-- AUTHOR
-- Dennis Vadura, dvadura@watdragon.uwaterloo.ca
-- CS DEPT, University of Waterloo, Waterloo, Ont., Canada
--
-- COPYRIGHT
-- Copyright (c) 1990 by Dennis Vadura. All rights reserved.
--
-- This program is free software; you can redistribute it and/or
-- modify it under the terms of the GNU General Public License
-- (version 1), as published by the Free Software Foundation, and
-- found in the file 'LICENSE' included with this distribution.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warrant of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program; if not, write to the Free Software
-- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
--
-- LOG
-- $Log: arlib.c,v $
* Revision 1.1 1992/01/24 03:27:23 dvadura
* dmake Version 3.8, Initial revision
*
*/
#include "extern.h"
PUBLIC time_t
seek_arch(name, lib)
char* name;
char* lib;
{
static int warned = FALSE;
if (!warned && !(Glob_attr&A_SILENT))
warned = TRUE,
Warning("Can't extract library member timestamp;\n\
using library timestamp instead.");
return (Do_stat(lib, NULL, NULL));
}
PUBLIC int
touch_arch(name, lib)
char* name;
char* lib;
{
static int warned = FALSE;
if (!warned && !(Glob_attr&A_SILENT))
warned = TRUE,
Warning("Can't update library member timestamp;\n\
touching library instead.");
return (Do_touch(lib, NULL, NULL));
}

View File

@ -0,0 +1,54 @@
/* RCS -- $Header: /u2/dvadura/src/generic/dmake/src/msdos/bccdos/config.h,v 1.1 1992/01/24 03:27:46 dvadura Exp $
-- SYNOPSIS -- Configurarion include file.
--
-- DESCRIPTION
-- There is one of these for each specific machine configuration.
-- It can be used to further tweek the machine specific sources
-- so that they compile.
--
-- AUTHOR
-- Dennis Vadura, dvadura@watdragon.uwaterloo.ca
-- CS DEPT, University of Waterloo, Waterloo, Ont., Canada
--
-- COPYRIGHT
-- Copyright (c) 1990 by Dennis Vadura. All rights reserved.
--
-- This program is free software; you can redistribute it and/or
-- modify it under the terms of the GNU General Public License
-- (version 1), as published by the Free Software Foundation, and
-- found in the file 'LICENSE' included with this distribution.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warrant of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program; if not, write to the Free Software
-- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
--
-- LOG
-- $Log: config.h,v $
* Revision 1.1 1992/01/24 03:27:46 dvadura
* dmake Version 3.8, Initial revision
*
*/
/* define this for configurations that don't have the coreleft function
* so that the code compiles. To my knowledge coreleft exists only on
* Turbo C, but it is needed here since the function is used in many debug
* macros. */
/*#define coreleft() 0L*/
extern unsigned int coreleft();
#define SIGQUIT SIGTERM /* turbo C doesn't understand SIGQUIT */
/* Turbo-C understands const declarations. */
#define CONST const
#ifndef MSDOS
# define MSDOS 1
#endif
/* a small problem with pointer to voids on some unix machines needs this */
#define PVOID void *

View File

@ -0,0 +1,50 @@
# This is the Turbo C++ 2.0 DOS configuration file for DMAKE
# It simply modifies the values of SRC, and checks to see if
# OSENVIRONMENT is defined. If so it includes the appropriate
# config.mk file.
#
# It also sets the values of .SOURCE.c and .SOURCE.h to include the local
# directory.
#
osrdir := $(OS)$(DIRSEPSTR)$(OSRELEASE)
# Definition of macros for library, and C startup code.
LDLIBS = d:/cc/bcc/lib/c$(MODEL)
CSTARTUP = d:/cc/bcc/lib/c0$(MODEL).obj
# The following sources are required for TURBO C++ 2.0
OSR_SRC = tempnam.c utime.c
.SETDIR=$(osrdir) : $(OSR_SRC)
SRC += $(OSR_SRC)
.SOURCE.h : $(osrdir)
# Local configuration modifications for CFLAGS. Make sure your turboc.cfg
# file contains a -D__STDC__=1 and -DM_I86=1, if not then uncomment the line
# below!
#CFLAGS += -DM_I86=1 -D__STDC__=1
# You can get a smaller executable still, buy adding a -1 to the list of
# flags below, but then you can't run this on an 8086/88 cpu.
#CFLAGS += -1
CFLAGS += -I$(osrdir) -d -O -N- -w-nod $(C_$(MODEL))
ASFLAGS += -t -mx $(S_$(MODEL))
# Debugging information for Turbo-C
DB_CFLAGS += -v
DB_LDFLAGS += /v
# See if we modify anything in the lower levels.
.IF $(OSENVIRONMENT) != $(NULL)
.INCLUDE .IGNORE : $(osrdir)$(DIRSEPSTR)$(OSENVIRONMENT)$(DIRSEPSTR)config.mk
.END
C_s =
C_m = -mm
C_c = -mc
C_l = -ml
S_s = -dmsmall
S_m = -dmmedium
S_c = -dmcompact
S_l = -dmlarge

View File

@ -0,0 +1 @@
d:\cc\bcc\lib\cl

View File

@ -0,0 +1 @@
d:\cc\bcc\lib\cl

96
dmake/msdos/bccdos/mk.bat Normal file
View File

@ -0,0 +1,96 @@
md objects
bcc -c -I. -Imsdos -Imsdos\bccdos -d -O -N- -w-nod -ml infer.c
copy infer.obj objects
del infer.obj
bcc -c -I. -Imsdos -Imsdos\bccdos -d -O -N- -w-nod -ml make.c
copy make.obj objects
del make.obj
bcc -c -I. -Imsdos -Imsdos\bccdos -d -O -N- -w-nod -ml stat.c
copy stat.obj objects
del stat.obj
bcc -c -I. -Imsdos -Imsdos\bccdos -d -O -N- -w-nod -ml expand.c
copy expand.obj objects
del expand.obj
bcc -c -I. -Imsdos -Imsdos\bccdos -d -O -N- -w-nod -ml dmstring.c
copy dmstring.obj objects
del dmstring.obj
bcc -c -I. -Imsdos -Imsdos\bccdos -d -O -N- -w-nod -ml hash.c
copy hash.obj objects
del hash.obj
bcc -c -I. -Imsdos -Imsdos\bccdos -d -O -N- -w-nod -ml dag.c
copy dag.obj objects
del dag.obj
bcc -c -I. -Imsdos -Imsdos\bccdos -d -O -N- -w-nod -ml dmake.c
copy dmake.obj objects
del dmake.obj
bcc -c -I. -Imsdos -Imsdos\bccdos -d -O -N- -w-nod -ml path.c
copy path.obj objects
del path.obj
bcc -c -I. -Imsdos -Imsdos\bccdos -d -O -N- -w-nod -ml imacs.c
copy imacs.obj objects
del imacs.obj
bcc -c -I. -Imsdos -Imsdos\bccdos -d -O -N- -w-nod -ml sysintf.c
copy sysintf.obj objects
del sysintf.obj
bcc -c -I. -Imsdos -Imsdos\bccdos -d -O -N- -w-nod -ml parse.c
copy parse.obj objects
del parse.obj
bcc -c -I. -Imsdos -Imsdos\bccdos -d -O -N- -w-nod -ml getinp.c
copy getinp.obj objects
del getinp.obj
bcc -c -I. -Imsdos -Imsdos\bccdos -d -O -N- -w-nod -ml quit.c
copy quit.obj objects
del quit.obj
bcc -c -I. -Imsdos -Imsdos\bccdos -d -O -N- -w-nod -ml state.c
copy state.obj objects
del state.obj
bcc -c -I. -Imsdos -Imsdos\bccdos -d -O -N- -w-nod -ml basename.c
copy basename.obj objects
del basename.obj
bcc -c -I. -Imsdos -Imsdos\bccdos -d -O -N- -w-nod -ml dmdump.c
copy dmdump.obj objects
del dmdump.obj
bcc -c -I. -Imsdos -Imsdos\bccdos -d -O -N- -w-nod -ml macparse.c
copy macparse.obj objects
del macparse.obj
bcc -c -I. -Imsdos -Imsdos\bccdos -d -O -N- -w-nod -ml rulparse.c
copy rulparse.obj objects
del rulparse.obj
bcc -c -I. -Imsdos -Imsdos\bccdos -d -O -N- -w-nod -ml percent.c
copy percent.obj objects
del percent.obj
bcc -c -I. -Imsdos -Imsdos\bccdos -d -O -N- -w-nod -ml function.c
copy function.obj objects
del function.obj
bcc -c -I. -Imsdos -Imsdos\bccdos -d -O -N- -w-nod -ml msdos\ruletab.c
copy ruletab.obj objects
del ruletab.obj
bcc -c -I. -Imsdos -Imsdos\bccdos -d -O -N- -w-nod -ml msdos\dirbrk.c
copy dirbrk.obj objects
del dirbrk.obj
bcc -c -I. -Imsdos -Imsdos\bccdos -d -O -N- -w-nod -ml msdos\runargv.c
copy runargv.obj objects
del runargv.obj
bcc -c -I. -Imsdos -Imsdos\bccdos -d -O -N- -w-nod -ml msdos\arlib.c
copy arlib.obj objects
del arlib.obj
bcc -c -I. -Imsdos -Imsdos\bccdos -d -O -N- -w-nod -ml msdos\_chdir.c
copy _chdir.obj objects
del _chdir.obj
bcc -c -I. -Imsdos -Imsdos\bccdos -d -O -N- -w-nod -ml msdos\switchar.c
copy switchar.obj objects
del switchar.obj
bcc -c -I. -Imsdos -Imsdos\bccdos -d -O -N- -w-nod -ml msdos\rmprq.c
copy rmprq.obj objects
del rmprq.obj
bcc -c -I. -Imsdos -Imsdos\bccdos -d -O -N- -w-nod -ml msdos\tee.c
copy tee.obj objects
del tee.obj
bcc -c -I. -Imsdos -Imsdos\bccdos -d -O -N- -w-nod -ml msdos\bccdos\tempnam.c
copy tempnam.obj objects
del tempnam.obj
bcc -c -I. -Imsdos -Imsdos\bccdos -d -O -N- -w-nod -ml msdos\bccdos\utime.c
copy utime.obj objects
del utime.obj
copy msdos\bccdos\startup.mk startup.mk
tlink @msdos\bccdos\obj.rsp,dmake.exe,NUL.MAP,@msdos\bccdos\lib.rsp

View File

@ -0,0 +1,101 @@
md objects
tasm -t -mx -dmlarge msdos\exec.asm;
mv exec.obj objects
bcc -c -I. -Imsdos -Imsdos\bccdos -d -O -N- -w-nod -ml infer.c
copy infer.obj objects
del infer.obj
bcc -c -I. -Imsdos -Imsdos\bccdos -d -O -N- -w-nod -ml make.c
copy make.obj objects
del make.obj
bcc -c -I. -Imsdos -Imsdos\bccdos -d -O -N- -w-nod -ml stat.c
copy stat.obj objects
del stat.obj
bcc -c -I. -Imsdos -Imsdos\bccdos -d -O -N- -w-nod -ml expand.c
copy expand.obj objects
del expand.obj
bcc -c -I. -Imsdos -Imsdos\bccdos -d -O -N- -w-nod -ml dmstring.c
copy dmstring.obj objects
del dmstring.obj
bcc -c -I. -Imsdos -Imsdos\bccdos -d -O -N- -w-nod -ml hash.c
copy hash.obj objects
del hash.obj
bcc -c -I. -Imsdos -Imsdos\bccdos -d -O -N- -w-nod -ml dag.c
copy dag.obj objects
del dag.obj
bcc -c -I. -Imsdos -Imsdos\bccdos -d -O -N- -w-nod -ml dmake.c
copy dmake.obj objects
del dmake.obj
bcc -c -I. -Imsdos -Imsdos\bccdos -d -O -N- -w-nod -ml path.c
copy path.obj objects
del path.obj
bcc -c -I. -Imsdos -Imsdos\bccdos -d -O -N- -w-nod -ml imacs.c
copy imacs.obj objects
del imacs.obj
bcc -c -I. -Imsdos -Imsdos\bccdos -d -O -N- -w-nod -ml sysintf.c
copy sysintf.obj objects
del sysintf.obj
bcc -c -I. -Imsdos -Imsdos\bccdos -d -O -N- -w-nod -ml parse.c
copy parse.obj objects
del parse.obj
bcc -c -I. -Imsdos -Imsdos\bccdos -d -O -N- -w-nod -ml getinp.c
copy getinp.obj objects
del getinp.obj
bcc -c -I. -Imsdos -Imsdos\bccdos -d -O -N- -w-nod -ml quit.c
copy quit.obj objects
del quit.obj
bcc -c -I. -Imsdos -Imsdos\bccdos -d -O -N- -w-nod -ml state.c
copy state.obj objects
del state.obj
bcc -c -I. -Imsdos -Imsdos\bccdos -d -O -N- -w-nod -ml basename.c
copy basename.obj objects
del basename.obj
bcc -c -I. -Imsdos -Imsdos\bccdos -d -O -N- -w-nod -ml dmdump.c
copy dmdump.obj objects
del dmdump.obj
bcc -c -I. -Imsdos -Imsdos\bccdos -d -O -N- -w-nod -ml macparse.c
copy macparse.obj objects
del macparse.obj
bcc -c -I. -Imsdos -Imsdos\bccdos -d -O -N- -w-nod -ml rulparse.c
copy rulparse.obj objects
del rulparse.obj
bcc -c -I. -Imsdos -Imsdos\bccdos -d -O -N- -w-nod -ml percent.c
copy percent.obj objects
del percent.obj
bcc -c -I. -Imsdos -Imsdos\bccdos -d -O -N- -w-nod -ml function.c
copy function.obj objects
del function.obj
bcc -c -I. -Imsdos -Imsdos\bccdos -d -O -N- -w-nod -ml msdos\ruletab.c
copy ruletab.obj objects
del ruletab.obj
bcc -c -I. -Imsdos -Imsdos\bccdos -d -O -N- -w-nod -ml msdos\dirbrk.c
copy dirbrk.obj objects
del dirbrk.obj
bcc -c -I. -Imsdos -Imsdos\bccdos -d -O -N- -w-nod -ml msdos\runargv.c
copy runargv.obj objects
del runargv.obj
bcc -c -I. -Imsdos -Imsdos\bccdos -d -O -N- -w-nod -ml msdos\arlib.c
copy arlib.obj objects
del arlib.obj
bcc -c -I. -Imsdos -Imsdos\bccdos -d -O -N- -w-nod -ml msdos\_chdir.c
copy _chdir.obj objects
del _chdir.obj
bcc -c -I. -Imsdos -Imsdos\bccdos -d -O -N- -w-nod -ml msdos\switchar.c
copy switchar.obj objects
del switchar.obj
bcc -c -I. -Imsdos -Imsdos\bccdos -d -O -N- -w-nod -ml msdos\rmprq.c
copy rmprq.obj objects
del rmprq.obj
bcc -c -I. -Imsdos -Imsdos\bccdos -d -O -N- -w-nod -ml msdos\find.c
copy find.obj objects
del find.obj
bcc -c -I. -Imsdos -Imsdos\bccdos -d -O -N- -w-nod -ml msdos\spawn.c
copy spawn.obj objects
del spawn.obj
bcc -c -I. -Imsdos -Imsdos\bccdos -d -O -N- -w-nod -ml msdos\bccdos\tempnam.c
copy tempnam.obj objects
del tempnam.obj
bcc -c -I. -Imsdos -Imsdos\bccdos -d -O -N- -w-nod -ml msdos\bccdos\utime.c
copy utime.obj objects
del utime.obj
copy msdos\bccdos\startup.mk startup.mk
tlink @msdos\bccdos\objswp.rsp,dmake.exe,NUL.MAP,@msdos\bccdos\libswp.rsp

View File

@ -0,0 +1,32 @@
d:\cc\bcc\lib\c0l.obj+
objects\infer.obj+
objects\make.obj+
objects\stat.obj+
objects\expand.obj+
objects\dmstring.obj+
objects\hash.obj+
objects\dag.obj+
objects\dmake.obj+
objects\path.obj+
objects\imacs.obj+
objects\sysintf.obj+
objects\parse.obj+
objects\getinp.obj+
objects\quit.obj+
objects\state.obj+
objects\basename.obj+
objects\dmdump.obj+
objects\macparse.obj+
objects\rulparse.obj+
objects\percent.obj+
objects\function.obj+
objects\ruletab.obj+
objects\dirbrk.obj+
objects\runargv.obj+
objects\arlib.obj+
objects\_chdir.obj+
objects\switchar.obj+
objects\rmprq.obj+
objects\tee.obj+
objects\tempnam.obj+
objects\utime.obj

View File

@ -0,0 +1,34 @@
d:\cc\bcc\lib\c0l.obj+
objects\exec.obj+
objects\infer.obj+
objects\make.obj+
objects\stat.obj+
objects\expand.obj+
objects\dmstring.obj+
objects\hash.obj+
objects\dag.obj+
objects\dmake.obj+
objects\path.obj+
objects\imacs.obj+
objects\sysintf.obj+
objects\parse.obj+
objects\getinp.obj+
objects\quit.obj+
objects\state.obj+
objects\basename.obj+
objects\dmdump.obj+
objects\macparse.obj+
objects\rulparse.obj+
objects\percent.obj+
objects\function.obj+
objects\ruletab.obj+
objects\dirbrk.obj+
objects\runargv.obj+
objects\arlib.obj+
objects\_chdir.obj+
objects\switchar.obj+
objects\rmprq.obj+
objects\find.obj+
objects\spawn.obj+
objects\tempnam.obj+
objects\utime.obj

152
dmake/msdos/bccdos/public.h Normal file
View File

@ -0,0 +1,152 @@
/* RCS -- $Header$
-- WARNING -- This file is AUTOMATICALLY GENERATED DO NOT EDIT IT
--
-- SYNOPSIS -- Local functions exported to be visible by others.
--
-- DESCRIPTION
-- This file is generated by 'genpub'. Function declarations
-- that appear in this file are extracted by 'genpub' from
-- source files. Any function in the source file whose definition
-- appears like:
--
-- PUBLIC return_type
-- function( arg_list );
-- type_expr1 arg1;
-- ...
--
-- has its definition extracted and a line of the form:
--
-- return_type function ANSI((type_expr1,type_expr2,...));
--
-- entered into the output file.
--
-- AUTHOR
-- Dennis Vadura, dvadura@watdragon.uwaterloo.ca
-- CS DEPT, University of Waterloo, Waterloo, Ont., Canada
--
-- COPYRIGHT
-- Copyright (c) 1990 by Dennis Vadura. All rights reserved.
--
-- This program is free software; you can redistribute it and/or
-- modify it under the terms of the GNU General Public License
-- (version 1), as published by the Free Software Foundation, and
-- found in the file 'LICENSE' included with this distribution.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warrant of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program; if not, write to the Free Software
-- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
--
-- LOG
-- $Log$
*/
#ifndef _DMAKE_PUBLIC_h
#define _DMAKE_PUBLIC_h
void Infer_recipe ANSI((CELLPTR, CELLPTR));
int Make_targets ANSI(());
int Exec_commands ANSI((CELLPTR));
void Print_cmnd ANSI((char *, int, int));
void Pop_dir ANSI((int));
void Append_line ANSI((char *, int, FILE *, char *, int, int));
void Stat_target ANSI((CELLPTR, int));
char * Expand ANSI((char *));
char * Apply_edit ANSI((char *, char *, char *, int, int));
void Map_esc ANSI((char *));
char* Apply_modifiers ANSI((int, char *));
char* Tokenize ANSI((char *, char *));
char * _strjoin ANSI((char *, char *, int, int));
char * _stradd ANSI((char *, char *, int));
char * _strapp ANSI((char *, char *));
char * _strdup ANSI((char *));
char * _strdup2 ANSI((char *));
char * _strpbrk ANSI((char *, char *));
char * _strspn ANSI((char *, char *));
char * _strstr ANSI((char *, char *));
char * _substr ANSI((char *, char *));
uint16 Hash ANSI((char *, uint32 *));
HASHPTR Get_name ANSI((char *, HASHPTR *, int));
HASHPTR Search_table ANSI((HASHPTR *, char *, uint16 *, uint32 *));
HASHPTR Def_macro ANSI((char *, char *, int));
CELLPTR Def_cell ANSI((char *));
LINKPTR Add_prerequisite ANSI((CELLPTR, CELLPTR, int, int));
void Clear_prerequisites ANSI((CELLPTR));
int Test_circle ANSI((CELLPTR, int));
STRINGPTR Def_recipe ANSI((char *, STRINGPTR, int, int));
t_attr Rcp_attribute ANSI((char *));
void main ANSI((int, char **));
FILE * Openfile ANSI((char *, int, int));
FILE * Closefile ANSI(());
FILE * Search_file ANSI((char *, char **));
char * Filename ANSI(());
int Nestlevel ANSI(());
void No_ram ANSI(());
int Usage ANSI((int));
int Version ANSI(());
char * Get_suffix ANSI((char *));
char * Build_path ANSI((char *, char *));
void Make_rules ANSI(());
void Create_macro_vars ANSI(());
time_t Do_stat ANSI((char *, char *, char **));
int Do_touch ANSI((char *, char *, char **));
void Void_lib_cache ANSI((char *, char *));
time_t Do_time ANSI(());
int Do_cmnd ANSI((char *, int, int, CELLPTR, int, int, int));
char ** Pack_argv ANSI((int, int, char *));
char * Read_env_string ANSI((char *));
int Write_env_string ANSI((char *, char *));
void ReadEnvironment ANSI(());
void Catch_signals ANSI((void (*)()));
void Clear_signals ANSI(());
void Prolog ANSI((int, char* []));
void Epilog ANSI((int));
char * Get_current_dir ANSI(());
int Set_dir ANSI((char*));
char Get_switch_char ANSI(());
FILE* Get_temp ANSI((char **, char *, int));
FILE * Start_temp ANSI((char *, CELLPTR, char **));
void Open_temp_error ANSI((char *, char *));
void Link_temp ANSI((CELLPTR, FILE *, char *));
void Close_temp ANSI((CELLPTR, FILE *));
void Unlink_temp_files ANSI((CELLPTR));
void Handle_result ANSI((int, int, int, CELLPTR));
void Update_time_stamp ANSI((CELLPTR));
int Remove_file ANSI((char *));
void Parse ANSI((FILE *));
int Get_line ANSI((char *, FILE *));
char * Do_comment ANSI((char *, char **, int));
char * Get_token ANSI((TKSTRPTR, char *, int));
void Quit ANSI(());
void Read_state ANSI(());
void Write_state ANSI(());
int Check_state ANSI((CELLPTR, STRINGPTR *, int));
char* basename ANSI((char *));
void Dump ANSI(());
void Dump_recipe ANSI((STRINGPTR));
int Parse_macro ANSI((char *, int));
int Macro_op ANSI((char *));
int Parse_rule_def ANSI((int *));
int Rule_op ANSI((char *));
void Add_recipe_to_list ANSI((char *, int, int));
void Bind_rules_to_targets ANSI((int));
int Set_group_attributes ANSI((char *));
DFALINKPTR Match_dfa ANSI((char *));
void Check_circle_dfa ANSI(());
void Add_nfa ANSI((char *));
char * Exec_function ANSI((char *));
int If_root_path ANSI((char *));
int runargv ANSI((CELLPTR, int, int, int, int, char *));
void Clean_up_processes ANSI(());
int Wait_for_child ANSI((int, int));
time_t seek_arch ANSI((char*, char*));
int touch_arch ANSI((char*, char*));
int _chdir ANSI((char *));
void Remove_prq ANSI((CELLPTR));
void Hook_std_writes ANSI((char *));
#endif

View File

@ -0,0 +1,154 @@
# MSDOS DMAKE startup file. Customize to suit your needs.
# Assumes MKS toolkit for the tool commands, and Turbo-C. Change as req'd.
# See the documentation for a description of internally defined macros.
#
# Disable warnings for macros redefined here that were given
# on the command line.
__.SILENT := $(.SILENT)
.SILENT := yes
# Configuration parameters for DMAKE startup.mk file
# Set these to NON-NULL if you wish to turn the parameter on.
_HAVE_RCS := yes # yes => RCS is installed.
_HAVE_SCCS := # yes => SCCS is installed.
# Applicable suffix definitions
A := .lib # Libraries
E := .exe # Executables
F := .for # Fortran
O := .obj # Objects
P := .pas # Pascal
S := .asm # Assembler sources
V := # RCS suffix
# See if these are defined
TMPDIR := $(ROOTDIR)/tmp
.IMPORT .IGNORE : TMPDIR SHELL COMSPEC
# Recipe execution configurations
# First set SHELL, If it is not defined, use COMSPEC, otherwise
# it is assumed to be MKS Korn SHELL.
.IF $(SHELL) == $(NULL)
.IF $(COMSPEC) == $(NULL)
SHELL := $(ROOTDIR)/bin/sh$E
.ELSE
SHELL := $(COMSPEC)
.END
.END
GROUPSHELL := $(SHELL)
# Now set remaining arguments depending on which SHELL we
# are going to use. COMSPEC (assumed to be command.com) or
# MKS Korn Shell.
.IF $(SHELL)==$(COMSPEC)
SHELLFLAGS := $(SWITCHAR)c
GROUPFLAGS := $(SHELLFLAGS)
SHELLMETAS := *"?<>
GROUPSUFFIX := .bat
DIRSEPSTR := \\
DIVFILE = $(TMPFILE:s,/,\)
.ELSE
SHELLFLAGS := -c
GROUPFLAGS :=
SHELLMETAS := *"?<>|()&][$$\#`'
GROUPSUFFIX := .ksh
.MKSARGS := yes
DIVFILE = $(TMPFILE:s,/,${DIVSEP_shell_${USESHELL}})
DIVSEP_shell_yes := \\\
DIVSEP_shell_no := \\
.END
# Standard C-language command names and flags
CC := bcc # C-compiler and flags
CFLAGS +=
AS := tasm # Assembler and flags
ASFLAGS +=
LD = tlink # Loader and flags
LDFLAGS +=
LDLIBS =
# Definition of $(MAKE) macro for recursive makes.
MAKE = $(MAKECMD) $(MFLAGS)
# Language and Parser generation Tools and their flags
YACC := yacc # standard yacc
YFLAGS +=
YTAB := ytab # yacc output files name stem.
LEX := lex # standard lex
LFLAGS +=
LEXYY := lex_yy # lex output file
# Other Compilers, Tools and their flags
PC := tpc # pascal compiler
RC := anyf77 # ratfor compiler
FC := anyf77 # fortran compiler
CO := co # check out for RCS
COFLAGS += -q
AR := ar # archiver
ARFLAGS+= ruv
RM := rm # remove a file command
RMFLAGS +=
# Implicit generation rules for making inferences.
# We don't provide .yr or .ye rules here. They're obsolete.
# Rules for making *$O
%$O .SWAP: %.c ; $(CC) $(CFLAGS) -c $<
%$O .SWAP: %$P ; $(PC) $(PFLAGS) -c $<
%$O .SWAP: %$S ; $(AS) $(ASFLAGS) $(<:s,/,\);
%$O : %.cl ; class -c $<
%$O .SWAP: %.e %.r %.F %$F ; $(FC) $(RFLAGS) $(EFLAGS) $(FFLAGS) -c $<
# Executables
%$E .SWAP: %$O ; $(CC) $(LDFLAGS) -e$@ $<
# lex and yacc rules
%.c .SWAP: %.y ; $(YACC) $(YFLAGS) $<; mv $(YTAB).c $@
%.c .SWAP: %.l ; $(LEX) $(LFLAGS) $<; mv $(LEXYY).c $@
# RCS support
.IF $(_HAVE_RCS)
% : $$(@:d)RCS/$$(@:f)$V;- $(CO) $(COFLAGS) $@
.NOINFER : $$(@:d)RCS/$$(@:f)$V
.END
# SCCS support
.IF $(_HAVE_SCCS)
% : s.% ; get $<
.NOINFER : s.%
.END
# Recipe to make archive files.
%$A .SWAP:
[
$(AR) $(ARFLAGS) $@ $?
$(RM) $(RMFLAGS) $?
]
# DMAKE uses this recipe to remove intermediate targets
.REMOVE :; $(RM) -f $<
# AUGMAKE extensions for SYSV compatibility
@B = $(@:b)
@D = $(@:d)
@F = $(@:f)
"*B" = $(*:b)
"*D" = $(*:d)
"*F" = $(*:f)
<B = $(<:b)
<D = $(<:d)
<F = $(<:f)
?B = $(?:b)
?F = $(?:f)
?D = $(?:d)
# Turn warnings back to previous setting.
.SILENT := $(__.SILENT)
# Local init file if any, gets parsed before user makefile
.INCLUDE .IGNORE: "_startup.mk"

View File

@ -0,0 +1,82 @@
/*LINTLIBRARY*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <dos.h>
#if defined(max)
# undef max
#endif
#define max(A,B) (((A)<(B))?(B):(A))
extern char *mktemp();
extern int access();
int _access();
/* Turbo C stdio.h doesn't define P_tmpdir, so let's do it here */
/* Under DOS leave the default tmpdir pointing here! */
#ifndef P_tmpdir
static char *P_tmpdir = "";
#endif
char *
tempnam(dir, prefix)
char *dir; /* use this directory please (if non-NULL) */
char *prefix; /* use this (if non-NULL) as filename prefix */
{
static int count = 0;
register char *p, *q, *tmpdir;
int tl=0, dl=0, pl;
char buf[30];
pl = strlen(P_tmpdir);
if( (tmpdir = getenv("TMPDIR")) != NULL ) tl = strlen(tmpdir);
if( dir != NULL ) dl = strlen(dir);
if( (p = malloc((unsigned)(max(max(dl,tl),pl)+13))) == NULL )
return(NULL);
*p = '\0';
if( (tl == 0) || (_access( strcpy(p, tmpdir), 0) != 0) )
if( (dl == 0) || (_access( strcpy(p, dir), 0) != 0) )
if( _access( strcpy(p, P_tmpdir), 0) != 0 )
if( !prefix )
prefix = "tp";
if(prefix)
{
*(p+strlen(p)+2) = '\0';
(void)strncat(p, prefix, 2);
}
sprintf( buf, "%08x", _psp );
buf[6]='\0';
(void)strcat(p, buf );
sprintf( buf, "%04d", count++ );
q=p+strlen(p)-6;
*q++ = buf[0]; *q++ = buf[1];
*q++ = buf[2]; *q++ = buf[3];
if( (q = strrchr(p,'.')) != NULL ) *q = '\0';
return(p);
}
_access( name, flag )
char *name;
int flag;
{
char *p;
int r;
if( name == NULL || !*name ) return(1); /* NULL dir means current dir */
r = access( name, flag );
p = name+strlen(name)-1;
if(*p != '/' && *p != '\\') strcat( p, "/" );
return( r );
}

View File

@ -0,0 +1,42 @@
/*
** change access and modify times of file
*/
#include <sys/stat.h>
#include <fcntl.h>
#include <time.h>
int
utime(name, timep)/*
====================
Broken for turbo C it only sets the file time to the current time by
touching a character in the file */
char* name;
time_t timep[2];
{
struct stat buf;
int fil;
char data;
if (stat(name, &buf) != 0)
return (-1);
if (buf.st_size != 0) {
if ((fil = open(name, O_RDWR, S_IWRITE)) < 0)
return (-1);
if (read(fil, &data, 1) < 1) {
close(fil);
return (-1);
}
lseek(fil, 0L, 0);
if (write(fil, &data, 1) < 1) {
close(fil);
return (-1);
}
close(fil);
return (0);
} else if ((fil = creat(name, S_IWRITE)) < 0) {
return (-1);
} else {
close(fil);
return (0);
}
}

68
dmake/msdos/config.mk Normal file
View File

@ -0,0 +1,68 @@
# This is an OS specific configuration file
# It assumes that OBJDIR, TARGET and DEBUG are previously defined.
# It defines CFLAGS, LDARGS, CPPFLAGS, STARTUPFILE, LDOBJS
# It augments SRC, OBJDIR, TARGET, CFLAGS, LDLIBS
#
# Memory model to compile for
# set to s - small, m - medium, c - compact, l - large
# Need large model now, dmake has grown up :-)
MODEL = l
STARTUPFILE = $(OS)/startup.mk
CPPFLAGS = $(CFLAGS)
LDOBJS = $(CSTARTUP) $(OBJDIR)/{$(<:f)}
LDARGS = $(LDHEAD) @$(LDTMPOBJ),$(TARGET),NUL.MAP$(LDTAIL)
LDTAIL = $(_libs)$(LDFLAGS:s/ //)
_libs = $(!null,$(LDLIBS) ,@$(LDTMPLIB))
LDTMPOBJ = $(mktmp,,$(DIVFILE) $(LDOBJS:s,/,\\,:t"+\n")\n)
LDTMPLIB = $(mktmp,,$(DIVFILE) $(LDLIBS:s,/,\\,:t"+\n")\n)
# Debug flags
DB_CFLAGS = -DDBUG
DB_LDFLAGS =
DB_LDLIBS =
# NO Debug flags
NDB_CFLAGS =
NDB_LDFLAGS =
NDB_LDLIBS =
# Local configuration modifications for CFLAGS.
CFLAGS += -I$(OS)
# Common MSDOS source files.
# Define SWAP to anything but 'y' for the swap code to be excluded on making.
# Swapping for DOS versions is enabled by default.
# Note: swapping is handled specially for ZTC in msdos/ztcdos/config.mk.
SWAP *= y
.IF $(OSRELEASE) != ztcdos
.IF $(SWAP) == y
SWP_SRC = find.c spawn.c
ASRC += exec.asm
.ELSE
SWP_SRC = tee.c
.END
.ELSE
SWP_SRC = tee.c
.END
OS_SRC += ruletab.c dirbrk.c runargv.c arlib.c _chdir.c switchar.c rmprq.c\
$(SWP_SRC)
SRC += $(OS_SRC)
.SETDIR=$(OS) : $(ASRC) $(OS_SRC)
# Provide our own %$O : %$S rule.
%$O : %$S
$(AS) $(ASFLAGS) $(<:s,/,\,);
mv $(@:f) $(OBJDIR)
# Set source dirs so that we can find files named in this
# config file.
.SOURCE.h : $(OS)
# See if we modify anything in the lower levels.
.IF $(OSRELEASE) != $(NULL)
.INCLUDE : $(OS)$(DIRSEPSTR)$(OSRELEASE)$(DIRSEPSTR)config.mk
.END

51
dmake/msdos/dirbrk.c Normal file
View File

@ -0,0 +1,51 @@
/* RCS -- $Header: /u2/dvadura/src/generic/dmake/src/msdos/dirbrk.c,v 1.1 1992/01/24 03:27:29 dvadura Exp $
-- SYNOPSIS -- define the directory separator string.
--
-- DESCRIPTION
-- Define this string for any character that may appear in a path name
-- and can be used as a directory separator.
--
-- AUTHOR
-- Dennis Vadura, dvadura@watdragon.uwaterloo.ca
-- CS DEPT, University of Waterloo, Waterloo, Ont., Canada
--
-- COPYRIGHT
-- Copyright (c) 1990 by Dennis Vadura. All rights reserved.
--
-- This program is free software; you can redistribute it and/or
-- modify it under the terms of the GNU General Public License
-- (version 1), as published by the Free Software Foundation, and
-- found in the file 'LICENSE' included with this distribution.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warrant of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program; if not, write to the Free Software
-- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
--
-- LOG
-- $Log: dirbrk.c,v $
* Revision 1.1 1992/01/24 03:27:29 dvadura
* dmake Version 3.8, Initial revision
*
*/
#include "extern.h"
/* dos uses /, \, and : */
char* DirBrkStr = "/\\:";
/*
** Return TRUE if the name is the full specification of a path name to a file
** starting at the root of the file system, otherwise return FALSE
*/
PUBLIC int
If_root_path(name)
char *name;
{
return( (strchr(DirBrkStr, *name) != NIL(char)) ||
(isalpha(*name) && name[1] == ':') );
}

42
dmake/msdos/dirlib.h Normal file
View File

@ -0,0 +1,42 @@
/* DIRLIB.H by M. J. Weinstein Released to public domain 1-Jan-89 */
#ifndef _DIRLIB_h_
#define _DIRLIB_h_
#include <stdio.h>
#include "stdmacs.h"
#define MAXNAMLEN 15
struct direct {
long d_ino;
unsigned short d_reclen;
unsigned short d_namlen;
char d_name[MAXNAMLEN+1];
};
typedef struct {
char fcb[21];
char attr;
short time;
short date;
long size;
char name[13];
} DTA;
typedef struct {
DTA dd_dta; /* disk transfer area for this dir. */
short dd_stat; /* status return from last lookup */
char dd_name[1]; /* full name of file -- struct is extended */
} DIR;
extern DIR *opendir ANSI((char *));
extern struct direct *readdir ANSI((DIR *));
extern long telldir ANSI((DIR *));
extern void seekdir ANSI((DIR *, long));
extern void closedir ANSI((DIR *));
extern DTA *findfirst ANSI((char *, DTA *));
extern DTA *findnext ANSI((DTA *));
#define rewinddir(dirp) seekdir(dirp,0L)
#endif

1234
dmake/msdos/exec.asm Normal file

File diff suppressed because it is too large Load Diff

19
dmake/msdos/exec.h Normal file
View File

@ -0,0 +1,19 @@
#ifndef _EXEC_h_
#define _EXEC_h_
#ifndef ANSI
#if defined(__STDC__) || defined(__TURBOC__)
#define ANSI(x) x
#else
#define ANSI(x) ()
#endif
#endif
extern int exec ANSI((int, char far *, char far *, unsigned int, char far *));
#ifndef MK_FP
#define MK_FP(seg,ofs) \
((void far *) (((unsigned long)(seg) << 16) | (unsigned)(ofs)))
#endif
#endif

63
dmake/msdos/exec.uue Normal file
View File

@ -0,0 +1,63 @@
begin 600 exec.obj
M@! #DU31$]37&5X96,N87-M;(@@ '%1U<F)O($%S<V5M8FQE<B @5F5R
M<VEO;B S+C";B!8 0.FRO888#DU31$]37&5X96,N87-M*(@# $#I3)8" !H
MB , 0*&4EA "45814-?5$585 1#3T1%:9@' $@:" (# ?&6# %7T1!5$$$
M1$%40<*8!P!( @ $!0$-E@@ !D1'4D]54(N:! &_P);C D !E]E<G)N;P#@
MD!, 0(,7TEN=&5R<G5P=&5D 69 < !%5]D;U]U;FAO;VM?<W1D7W=R
M:71E<P,( &>0# 05?97AE8^$& '.0&@ 1-?9&]?:&]O:U]S=&1?=W)I
M=&5SN < FH@$ $"B 9&@!@ !F ,&B#@ !7 $E $ 0 $ RJ(. &(
M 4$ 0 ! 0""H@X <D! 0 ! $ ! (&@" !S $ BJ#' '4
M 65X96,Z($9A:6QU<F4@<F5A9&EN9R!H96%D97(@8FQO8VL-"B1E>&5C.B!&
M86EL=7)E(')E861I;F<@<V5G;65N="!D871A#0HD97AE8SH@1F%I;'5R92!O
M;B!R97-I>F4-"B1E>&5C.B!&86EL=7)E('1O(&9R964@82!B;&]C:PT*)&5X
M96,Z(%!R;V=R86T@<W=A<"!F86EL=7)E#0HD97AE8SH@365M;W)Y(&)L;V-K
M<R!D;VXG="!M871C: T*)+>B#@ !EP(! $ 0 $ LJ H &8 G(&=0:7
M!G,&=@:]!@,$!P0+! 0$" 0J! 8$"@1@! 4$"012! J<20#$ %0!Q )4 <0$
M5 '$!E0!Q A4 <0*5 '$#%0!Q Y4 <005 '$$E0!Q!14 <065 '$&%0!Q!I4
M <0<5 '$'E0!Q"!4 <0B5 $GH P <H"7 $ %P! #-G D S !4 <P$5 $5
MH,T# =8" "<@/Q =0J#^P%T"X/[ G0&G2[_+LP!4%%24U155E<>!HOL+HL^
MT &T49PN_Q[, 2X['HP =&R.PR;%'C0 BW8,B@ N.@;3 75CB@$N.@;2 71*
MN SG"[_'LP!B_(KTK@!,YPN_Q[, 2Z+'HP M%"<+O\>S &+WXY> HM6#K1
MG"[_'LP!C,.T4)PN_Q[, 8O6N $SG"[_'LP!ZQ".7@*+5@Z+W[1 G"[_'LP!
M!Q]?7EV#Q );6EE8G2[_+LP!@\0&6%M96EY?71\'58OLAT8&#0$ AT8&7;@%
M ,_X+O\&D@ N@SZ8 !T ?G/NM0!ZQR0NOD!ZQ:0NAX"ZQ"0NC@"ZPJ0NG4"
MZP20NE@"4HL>C@#_E[ "C,B.V%JT"<TAN/],S2'1Z7,!I/.EP\/#P\/#P\/#
MNH$!N0< BQ[* ;0_S2%S NNF/0< = <+P'0"ZYOYPQXNCAZ! 2Z+%H,!+HL.
MA0$NBQ[* ;0_S2$?<P+K@3L&A0%T ^EX_\.+'LH!,\F+T;@ 0LTAPXL>R@&T
M/LTANH@!M$'-(<.+'I8 N %8S2&+'HX _Y>V HX&C "+'H0 M$K-(7,#Z4__
MBQZ. /^7I )R**"' 3P =.\\ 743BQZ% ;1(S2%R!CL&@0%TV^DA_XL>C@#_
MEZH"Z\Z+'HX _Y>P L.X %C-(:.6 (L^C ",RRO?B\=(CL FBS8# (DVA "X
MYP71Z-'HT>C1Z /8*_,#^XD>A@")/H@ L #H'0%R,:&, $B.P+LD!NC+ '(C
MH8P 2([ NQT&Z+T <P/IJ_Z.!HP BQZ& +1*S2%S ^F4_L.+'HX _Y>P C/
MHXX ^<.#/HX '0(Z(, <@/H<_^#/I( '5FH8H "\!T"%".P+1)S2%8H8H
MH\0"C,G'!L8"VP")#L@"NIH CL&[Q (>B2;4 HP6T@+'!M8" #_!I@ N !+
MS2$NCA;2 BZ+)M0"'W,&H]8"ZQ.0M$W-(8#\ 74$_P:2 #+DHY @SZ. !T
M ^B?_L<&F ,/'!HX #HE@##)HLV P",QT<FH0$ +CL&C !U)BX[/HH
M=!DN.SZ, '025U93_]-;7E]R#R:@ \6G0& _Z.Q^O'^,..Q[1)S2'#L %7
M5C/2BQZ. /^7F )>7W(Z@_X =#6+SH'Y_P]^ [G_#U'1X='AT>'1X5=6B_$S
MTK "BQZ. %/_EY@"6_^7G@)>7UIR!@/Z*_+KQL/#P\/#P\.@B $*P'07NH@!
M,\FT/,TA<@RCR@''!HX ! #K I#YPXD^@0&)%H,!(YR1 <065 '$)U0!Q"]4
M <0T5 '$1U0!Q%!4 <1;5 '$:%0!Q&U4 <1U5 '$A50!Q(]4 <2:5 '$K%0!
MQ+Y4 <3A5 '$YE0!Q.Y4 <3T5 '$^E0!Q0!4 <4&5 '%#%0!Q1%4 <455 '%
M-E0!Q3U4 <585 '%750!Q6)4 <5G5 '%=%0!Q7Y4 <6,5 '%DU0!Q9Q4 <6E
M5 '%J50!Q:U4 <6Q5 '%OE0!Q<)4 <7'5 '%TU0!Q=U4 <865 '&/%0!QDI4
M <7F5 '%ZE0!Q?!4 <7T5 '%_50!Q@%4 <835 '&*%0!QBQ4 <8V5 '&1%0!
MQE94 <9:5 '&:%0!QFQ4 <9Q5 '&=U0!QH94 <:,5 '&FU0!QIY4 <:D5 '&
MIE0!QJI4 <:M5 '&LE0!QK=4 <:[5 '&OU0!QL54 <;/5 '&U%0!QMI4 <;J
M5 '&[U0!QO-4 <;]5 ''!%0!QQM4 <<B5 ''*50!QU94 <=:5 ''@U0!QXA4
M <>-5 ''HE0!QZE4 <>T5 ''N%0!Q\-4 <?'5 $%H'\! 9\&B3:% :*' ;J!
M ;D' (L>R@&T0,TA<@8]!P!T ?G#'BZ.'H$!+HL6@P$NBPZ% 2Z+'LH!M$#-
M(1]R!SL&A0%T ?G#58OL5E<>#@?\BT8&)J.. (M&$":CB@"_F@#%=@BY00#H
M]_R_VP#%=@RY@0#HZ_R_B '%=A*Y00#HW_R,T":C@ FB2:" (S(CMB.T+R
M ,<&D@ ,<&D +@C-<TA+HD>O (NC :^ KJS [@C)<TAN"0US2$NB1[
M BZ,!L("NI8#N"0ES2&T4<TA+HD>C #HU?TNQ1:\ K@C)<TA+L46P *X)"7-
M(2ZA@ ".T"Z+)H( '[@ ([ +J&2 ":C "X ".P"ZAU@(FHP +J&0 %]>
M7<M5B^Q7BWX&+HD^T &T4<TA+HD>C ".PR;$'C0 )HI' 2ZBTP$FB@$NHM(!
MN"$US2$NB1[, 2Z,!LX!'HS(CMBZV *X(27-(1]?7<L>+L46S &,V O"= FX
M(26<+O\>S $?RPJ<O0#$ E0!Q 54 <0(5 '$#U0!Q")4 <0G5 '$+%0!Q#%4
M <0\5 '$4%0!Q%=4 <1:5 '$9E0!Q')4 <2!5 '$AE0!Q(]4 <235 '$F50!
MQ*54 <2J5 '$K50!Q+Q4 <3!5 '$Q%0!Q-)4 <3:5 '$Y%0!Q.U4 <3T5 '(
M^!0! L3^5 '% A0! LD%%@$!Q0M4 <4/%@$!Q1-4 <4C5 '%+%0!Q3M4 <5"
E5 '%3%0!Q5%4 <595 '%:%0!Q7=4 ?6@!@ " %B* @ =%0!
end

130
dmake/msdos/find.c Normal file
View File

@ -0,0 +1,130 @@
/*
Directory Access Library
FIND.C taken from DIRLIB.C by M. J. Weinstein
Released to public domain 1-Jan-89
The author may be contacted at:
matt@cs.ucla.edu -or- POB 84524, L.A., CA 90073
Modified by dvadura@watdragon.edu to work with dmake.
(nuked the DOS version 2 code, since dmake needs version
3.0 or greater to function).
*/
/*
* revision history:
*
* VER MM/DD/YY COMMENTS
* ---- -------- --------
* 0.99 02/24/86 Beta release to INTERNET
*/
#include <stdlib.h>
#include <ctype.h>
#include <errno.h>
#include <string.h>
#include <alloc.h>
#include <dos.h>
#include "dirlib.h"
#ifndef MK_FP
#define MK_FP(seg,ofs) ((void far *) \
(((unsigned long)(seg) << 16) | (unsigned)(ofs)))
#endif
#ifndef FP_SEG
#define FP_SEG(fp) ((unsigned)((unsigned long)(fp) >> 16))
#endif
#ifndef FP_OFF
#define FP_OFF(fp) ((unsigned)(fp))
#endif
int _err;
static DTA far *_getsetdta ANSI((DTA far *));
/*
* get/set dta address
*/
static DTA far *
_getsetdta(newdta)
DTA far *newdta;
{
DTA far *olddta;
union REGS r;
struct SREGS s;
/* get old dta */
r.h.ah = 0x2f;
intdos(&r, &r);
segread(&s);
olddta = (DTA far *) MK_FP(s.es, r.x.bx);
/* conditionally set new dta */
if (newdta) {
r.h.ah = 0x1a;
s.ds = FP_SEG(newdta);
r.x.dx = FP_OFF(newdta);
intdosx(&r, &r, &s);
}
return olddta;
}
/*
* dos findfirst
*/
DTA *
findfirst(name, dta)
char *name;
DTA *dta;
{
union REGS r;
struct SREGS s;
DTA far *dtasave;
char far *nmp = (char far *)name;
dtasave = _getsetdta((DTA far *)dta);
/* do directory lookup */
segread(&s);
r.h.ah = 0x4e;
r.x.cx = 0x10;
r.x.dx = FP_OFF(nmp);
s.ds = FP_SEG(nmp);
intdosx(&r, &r, &s);
/* restore dta */
_getsetdta(dtasave);
_err = r.x.ax;
if (r.x.cflag)
return (DTA *) 0;
return dta;
}
/*
* dos findnext
*/
DTA *
findnext(dta)
DTA *dta;
{
union REGS r;
DTA far *dtasave;
dtasave = _getsetdta((DTA far *)dta);
/* do directory lookup */
r.h.ah = 0x4f;
intdos(&r, &r);
/* restore old dta */
_getsetdta(dtasave);
_err = r.x.ax;
if (r.x.cflag)
return (DTA *) 0;
return dta;
}

View File

@ -0,0 +1,83 @@
/* RCS -- $Header: /u2/dvadura/src/generic/dmake/src/msdos/mscdos/config.h,v 1.1 1992/01/24 03:27:25 dvadura Exp $
-- SYNOPSIS -- Configurarion include file.
--
-- DESCRIPTION
-- There is one of these for each specific machine configuration.
-- It can be used to further tweek the machine specific sources
-- so that they compile.
--
-- AUTHOR
-- Dennis Vadura, dvadura@watdragon.uwaterloo.ca
-- CS DEPT, University of Waterloo, Waterloo, Ont., Canada
--
-- COPYRIGHT
-- Copyright (c) 1990 by Dennis Vadura. All rights reserved.
--
-- This program is free software; you can redistribute it and/or
-- modify it under the terms of the GNU General Public License
-- (version 1), as published by the Free Software Foundation, and
-- found in the file 'LICENSE' included with this distribution.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warrant of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program; if not, write to the Free Software
-- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
--
-- LOG
-- $Log: config.h,v $
* Revision 1.1 1992/01/24 03:27:25 dvadura
* dmake Version 3.8, Initial revision
*
*/
#if defined (_MSC_VER)
# if _MSC_VER < 500
Force a compile-time blowup.
Do not define define _MSC_VER for MSC compilers ealier than 5.0.
# endif
#endif
/* define this for configurations that don't have the coreleft function
* so that the code compiles. To my knowledge coreleft exists only on
* Turbo C, but it is needed here since the function is used in many debug
* macros. */
#define coreleft() 0L
/* MSC Version 4.0 doesn't understand SIGTERM, later versions do. */
#ifndef SIGTERM
# define SIGTERM SIGINT
#endif
/* Fixes unimplemented line buffering for MSC 5.x and 6.0.
* MSC _IOLBF is the same as _IOFBF
*/
#if defined(MSDOS) && defined (_MSC_VER)
# undef _IOLBF
# define _IOLBF _IONBF
#endif
/* in alloc.h: size_t is redefined
* defined in stdio.h which is included by alloc.h
*/
#if defined(MSDOS) && defined (_MSC_VER)
# define _TYPES_
#endif
/* in sysintf.c: SIGQUIT is used, this is not defined in MSC */
#ifndef SIGQUIT
# define SIGQUIT SIGTERM
#endif
/* MSC doesn't seem to care about CONST */
#define CONST
#ifndef MSDOS
# define MSDOS 1
#endif
/* a small problem with pointer to voids on some unix machines needs this */
#define PVOID void *

View File

@ -0,0 +1,93 @@
# This is the MSC 4.0 and higher DOS configuration file for DMAKE
# It simply modifies the values of SRC, and checks to see if
# OSENVIRONMENT is defined. If so it includes the appropriate
# config.mk file.
#
# It also sets the values of .SOURCE.c and .SOURCE.h to include the local
# directory.
#
osrdir := $(OS)$(DIRSEPSTR)$(OSRELEASE)
TMPDIR :=
.EXPORT : TMPDIR
# Definition of macros for library, and C startup code.
# The following sources are required for MSC
OSR_SRC = tempnam.c
.SETDIR=$(osrdir) : $(OSR_SRC)
SRC += $(OSR_SRC)
.SOURCE.h : $(osrdir)
SET_STACK = /stack:4096
NDB_LDFLAGS += $(SET_STACK)
# Local configuration modifications for CFLAGS
# If you have a 286 or better, you can uncomment the following line.
#HAVE_286 = y
.IF $(HAVE_286)
CFLAGS += -G2
ASFLAGS += -Dhave286
.END
ASFLAGS += -t -mx $(S_$(MODEL))
# Microsoft C doesn't need tail but needs head
LDTAIL = ;
LDHEAD = $(LDFLAGS)
# Debugging libraries
DB_LDFLAGS += /co /li /map $(SET_STACK)
DB_LDLIBS +=
# NO Debug MSC flags:
# Set the environment variable MSC_VER to be one of 4.0, 5.0, 5.1, or 6.0
# to get these by default when you make dmake using 'dmake'.
#
# Setting MSC_VER to one of the above sets the variable _MSC_VER appropriately
# and sets the flags appropriately.
.IMPORT .IGNORE : MSC_VER
MSC_VER *= 6.0 # If unset, assume 6.0 by default.
.IF $(MSC_VER) == 4.0
CFLAGS += -I$(osrdir) $(C_$(MODEL):s/A/m/)
CFLAGS += -DM_I86=1 # 5.0+ define this automatically
# CFLAGS += -D__STDC__=1 # 5.0, 5.1, but not 6.0 do this automatically
NDB_CFLAGS +=
DB_CFLAGS += -Zi
.ELSE
DB_CFLAGS += -Zi
CFLAGS += -I$(osrdir) $(C_$(MODEL))
.IF $(MSC_VER) != 6.0
# For 5.0 and 5.1, we define _MSC_VER=500 or 510
CFLAGS += -D_MSC_VER=$(MSC_VER:s,.,,)0
NDB_CFLAGS += -Oscl -Gs
.ELSE
# Microsoft C 6.0 auto defines _MSC_VER=600, but not __STDC__
CFLAGS += -D__STDC__=1 # incredibly not auto done by 6.0
NDB_CFLAGS += -Osecgl -Gs
# Redefine rule for making our objects, we don't need mv
%$O : %.c ;% $(CC) -c $(CFLAGS) -Fo$@ $<
.END
NDB_LDFLAGS += /exe /packc /batch
NDB_LDLIBS +=
.END
# See if we modify anything in the lower levels.
.IF $(OSENVIRONMENT) != $(NULL)
.INCLUDE .IGNORE : $(osrdir)$(DIRSEPSTR)$(OSENVIRONMENT)$(DIRSEPSTR)config.mk
.END
C_s =
C_m = -AM
C_c = -AC
C_l = -AL
S_s = -Dmsmall
S_m = -Dmmedium
S_c = -Dmcompact
S_l = -Dmlarge

Some files were not shown because too many files have changed in this diff Show More