Remove old version of awk.

This commit is contained in:
James Raynard 1997-10-14 18:29:32 +00:00
parent 9addf1c150
commit 60e8807fae
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=30416
32 changed files with 0 additions and 29563 deletions

View file

@ -1,25 +0,0 @@
The current developers of Gawk would like to thank and acknowledge the
many people who have contributed to the development through bug reports
and fixes and suggestions. Unfortunately, we have not been organized
enough to keep track of all the names -- for that we apologize.
Another group of people have assisted even more by porting Gawk to new
platforms and providing a great deal of feedback. They are:
Hal Peterson <hrp@pecan.cray.com> (Cray)
Pat Rankin <gawk.rankin@EQL.Caltech.Edu> (VMS)
Michal Jaegermann <michal@gortel.phys.UAlberta.CA> (Atari, NeXT, DEC 3100)
Mike Lijewski <mjlx@eagle.cnsf.cornell.edu> (IBM RS6000)
Scott Deifik <scottd@amgen.com> (MSDOS 2.14 and 2.15)
Kent Williams (MSDOS 2.11)
Conrad Kwok (MSDOS earlier versions)
Scott Garfinkle (MSDOS earlier versions)
Kai Uwe Rommel <rommel@ars.muc.de> (OS/2)
Darrel Hankerson <hankedr@mail.auburn.edu> (OS/2)
Mark Moraes <Mark-Moraes@deshaw.com> (Code Center, Purify)
Kaveh Ghazi <ghazi@noc.rutgers.edu> (Lots of Unix variants)
Last, but far from least, we would like to thank Brian Kernighan who
has helped to clear up many dark corners of the language and provided a
restraining touch when we have been overly tempted by "feeping
creaturism".

View file

@ -1,340 +0,0 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 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 licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU 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. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Library General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), 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 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 show them these terms so they know 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.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
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 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 derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
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 License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
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.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary 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
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 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 Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing 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 for copying, distributing or modifying
the Program or works based on it.
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.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. 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 this 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
this License, you may choose any version ever published by the Free Software
Foundation.
10. 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
11. 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.
12. 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 the public, 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 2 of the License, 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) 19yy 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 is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Library General
Public License instead of this License.

View file

@ -1,117 +0,0 @@
This file lists future projects and enhancements for gawk. Items are listed
in roughly the order they will be done for a given release. This file is
mainly for use by the developer(s) to help keep themselves on track, please
don't bug us too much about schedules or what all this really means.
(An `x' indicates that some progress has been made, but that the feature is
not complete yet.)
For 2.16
========
x Move to autoconf-based configure system.
x Research awk `fflush' function.
x Generalize IGNORECASE
any value makes it work, not just numeric non-zero
make it apply to *all* string comparisons
x Fix FILENAME to have an initial value of "", not "-"
In 2.17
=======
x Allow RS to be a regexp.
RT variable to hold text of record terminator
RECLEN variable for fixed length records
Feedback alloca.s changes to FSF
x Split() with null string as third arg to split up strings
x Analogously, setting FS="" would split the input record into individual
characters.
x Clean up code by isolating system-specific functions in separate files.
Undertake significant directory reorganization.
x Extensive manual cleanup:
Use of texinfo 2.0 features
Lots more examples
Document all of the above.
x Go to POSIX regexps
Make regex + dfa less dependant on gawk header file includes
Additional manual features:
Document posix regexps
Document use of dbm arrays
? Add an error messages section to the manual
? A section on where gawk is bounded
regex
i/o
sun fp conversions
For 2.18
========
DBM storage of awk arrays. Try to allow multiple dbm packages
General sub functions:
edit(line, pat, sub) and gedit(line, pat, sub)
that return the substituted strings and allow \1 etc. in the sub
string.
? Have strftime() pay attention to the value of ENVIRON["TZ"]
For 2.19
========
Add chdir and stat built-in functions.
Add function pointers as valid variable types.
Add an `ftw' built-in function that takes a function pointer.
Do an optimization pass over parse tree?
For 2.20 or later:
==================
Add variables similar to C's __FILE__ and __LINE__ for better diagnostics
from within awk programs.
Add an explicit concatenation operator and assignment version.
? Add a switch statement
Add the ability to seek on an open file and retrieve the current file position.
Add lint checking everywhere, including check for use of builtin vars.
only in new awk.
"restart" keyword
Add |&
Make awk '/foo/' files... run at egrep speeds
Do a reference card
Allow OFMT and CONVFMT to be other than a floating point format.
Allow redefining of builtin functions?
Make it faster and smaller.
For 3.x:
========
Create a gawk compiler?
Create a gawk-to-C translator? (or C++??)
Provide awk profiling and debugging.

View file

@ -1,16 +0,0 @@
This file describes limits of gawk on a Unix system (although it
is variable even then). Non-Unix systems may have other limits.
# of fields in a record: MAX_INT
Length of input record: MAX_INT
Length of output record: unlimited
Size of a field: MAX_INT
Size of a printf string: MAX_INT
Size of a literal string: MAX_INT
Characters in a character class: 2^(# of bits per byte)
# of file redirections: unlimited
# of pipe redirections: min(# of processes per user, # of open files)
double-precision floating point
Length of source line: unlimited
Number of input records in one file: MAX_LONG
Number of input records total: MAX_LONG

File diff suppressed because it is too large Load diff

View file

@ -1,35 +0,0 @@
A recent version of gawk has been successfully compiled and run "make test"
on the following:
Sun 4/490 running 4.1
NeXT running 2.0
DECstation 3100 running Ultrix 4.0 or Ultrix 3.1 (different config)
AtariST (16-bit ints, gcc compiler, byacc, running under TOS)
ESIX V.3.2 Rev D (== System V Release 3.2), the 386. compiler was gcc + bison
IBM RS/6000 (see README.rs6000)
486 running SVR4, using cc and bison
SGI running IRIX 3.3 using gcc (fails with cc)
Sequent Balance running Dynix V3.1
Cray Y-MP8 running Unicos 6.0.11
Cray 2 running Unicos 6.1 (modulo trailing zeroes in chem)
VAX/VMS V5.x (should also work on 4.6 and 4.7)
VMS POSIX V1.0, V1.1
OpenVMS AXP V1.0
MSDOS - Microsoft C 5.1, compiles and runs very simple testing
BSD 4.4alpha
From: ghazi@noc.rutgers.edu (Kaveh R. Ghazi):
arch configured as:
---- --------------
Dec Alpha OSF 1.3 osf1
Hpux 9.0 hpux8x
NeXTStep 2.0 next20
Sgi Irix 4.0.5 (/bin/cc) sgi405.cc
Stardent Titan 1500 OSv2.5 sysv3
Stardent Vistra (i860) SVR4 sysv4
Solaris 2.3 solaris2.cc
SunOS 4.1.3 sunos41
Tektronix XD88 (UTekV 3.2e) sysv3
Tektronix 4300 (UTek 4.0) utek
Ultrix 4.2 ultrix41

View file

@ -1,95 +0,0 @@
Right now, the numeric vs. string comparisons are screwed up in draft
11.2. What prompted me to check it out was the note in gnu.bug.utils
which observed that gawk was doing the comparison $1 == "000"
numerically. I think that we can agree that intuitively, this should
be done as a string comparison. Version 2.13.2 of gawk follows the
current POSIX draft. Following is how I (now) think this
stuff should be done.
1. A numeric literal or the result of a numeric operation has the NUMERIC
attribute.
2. A string literal or the result of a string operation has the STRING
attribute.
3. Fields, getline input, FILENAME, ARGV elements, ENVIRON elements and the
elements of an array created by split() that are numeric strings
have the STRNUM attribute. Otherwise, they have the STRING attribute.
Uninitialized variables also have the STRNUM attribute.
4. Attributes propagate across assignments, but are not changed by
any use. (Although a use may cause the entity to acquire an additional
value such that it has both a numeric and string value -- this leaves the
attribute unchanged.)
When two operands are compared, either string comparison or numeric comparison
may be used, depending on the attributes of the operands, according to the
following (symmetric) matrix:
+----------------------------------------------
| STRING NUMERIC STRNUM
--------+----------------------------------------------
|
STRING | string string string
|
NUMERIC | string numeric numeric
|
STRNUM | string numeric numeric
--------+----------------------------------------------
So, the following program should print all OKs.
echo '0e2 0a 0 0b
0e2 0a 0 0b' |
$AWK '
NR == 1 {
num = 0
str = "0e2"
print ++test ": " ( (str == "0e2") ? "OK" : "OOPS" )
print ++test ": " ( ("0e2" != 0) ? "OK" : "OOPS" )
print ++test ": " ( ("0" != $2) ? "OK" : "OOPS" )
print ++test ": " ( ("0e2" == $1) ? "OK" : "OOPS" )
print ++test ": " ( (0 == "0") ? "OK" : "OOPS" )
print ++test ": " ( (0 == num) ? "OK" : "OOPS" )
print ++test ": " ( (0 != $2) ? "OK" : "OOPS" )
print ++test ": " ( (0 == $1) ? "OK" : "OOPS" )
print ++test ": " ( ($1 != "0") ? "OK" : "OOPS" )
print ++test ": " ( ($1 == num) ? "OK" : "OOPS" )
print ++test ": " ( ($2 != 0) ? "OK" : "OOPS" )
print ++test ": " ( ($2 != $1) ? "OK" : "OOPS" )
print ++test ": " ( ($3 == 0) ? "OK" : "OOPS" )
print ++test ": " ( ($3 == $1) ? "OK" : "OOPS" )
print ++test ": " ( ($2 != $4) ? "OK" : "OOPS" ) # 15
}
{
a = "+2"
b = 2
if (NR % 2)
c = a + b
print ++test ": " ( (a != b) ? "OK" : "OOPS" ) # 16 and 22
d = "2a"
b = 2
if (NR % 2)
c = d + b
print ++test ": " ( (d != b) ? "OK" : "OOPS" )
print ++test ": " ( (d + 0 == b) ? "OK" : "OOPS" )
e = "2"
print ++test ": " ( (e == b "") ? "OK" : "OOPS" )
a = "2.13"
print ++test ": " ( (a == 2.13) ? "OK" : "OOPS" )
a = "2.130000"
print ++test ": " ( (a != 2.13) ? "OK" : "OOPS" )
if (NR == 2) {
CONVFMT = "%.6f"
print ++test ": " ( (a == 2.13) ? "OK" : "OOPS" )
}
}'

View file

@ -1,10 +0,0 @@
This is a list of known problems in gawk 2.15.
Hopefully they will all be fixed in the next major release of gawk.
Please keep in mind that the code is still undergoing significant evolution.
1. The interactions with the lexer and yyerror need reworking. It is possible
to get line numbers that are one line off if --compat or --posix is
true and either `next file' or `delete array' are used.
Really the whole lexical analysis stuff needs reworking.

View file

@ -1,125 +0,0 @@
README:
This is GNU Awk 2.15. It should be upwardly compatible with the System
V Release 4 awk. It is almost completely compliant with POSIX 1003.2.
This release adds new features -- see NEWS for details.
See the installation instructions, below.
Known problems are given in the PROBLEMS file. Work to be done is
described briefly in the FUTURES file. Verified ports are listed in
the PORTS file. Changes in this version are summarized in the NEWS file.
Please read the LIMITATIONS and ACKNOWLEDGMENT files.
Read the file POSIX for a discussion of how the standard says comparisons
should be done vs. how they really should be done and how gawk does them.
To format the documentation with TeX, you must use texinfo.tex 2.53
or later. Otherwise footnotes look unacceptable.
If you wish to remake the Info files, you should use makeinfo. The 2.15
version of makeinfo works with no errors.
The man page is up to date.
INSTALLATION:
Check whether there is a system-specific README file for your system.
A quick overview of the installation process is in the file INSTALL.
Makefile.in may need some tailoring. The only changes necessary should
be to change installation targets or to change compiler flags.
The changes to make in Makefile.in are commented and should be obvious.
All other changes should be made in a config file. Samples for
various systems are included in the config directory. Starting with
2.11, our intent has been to make the code conform to standards (ANSI,
POSIX, SVID, in that order) whenever possible, and to not penalize
standard conforming systems. We have included substitute versions of
routines not universally available. Simply add the appropriate define
for the missing feature(s) on your system.
If you have neither bison nor yacc, use the awktab.c file here. It was
generated with bison, and should have no AT&T code in it. (Note that
modifying awk.y without bison or yacc will be difficult, at best. You might
want to get a copy of bison from the FSF too.)
If no config file is included for your system, start by copying one
for a similar system. One way of determining the defines needed is to
try to load gawk with nothing defined and see what routines are
unresolved by the loader. This should give you a good idea of how to
proceed.
The next release will use the FSF autoconfig program, so we are no longer
soliciting new config files.
If you have an MS-DOS or OS/2 system, use the stuff in the pc directory.
For an Atari there is an atari directory and similarly one for VMS.
Chapter 16 of The GAWK Manual discusses configuration in detail.
(However, it does not discuss OS/2 configuration, see README.pc for
the details. The manual is being massively revised for 2.16.)
After successful compilation, do 'make test' to run a small test
suite. There should be no output from the 'cmp' invocations except in
the cases where there are small differences in floating point values.
If there are other differences, please investigate and report the
problem.
PRINTING THE MANUAL
The 'support' directory contains texinfo.tex 2.115, which will be necessary
for printing the manual, and the texindex.c program from the texinfo
distribution which is also necessary. See the makefile for the steps needed
to get a DVI file from the manual.
CAVEATS
The existence of a patchlevel.h file does *N*O*T* imply a commitment on
our part to issue bug fixes or patches. It is there in case we should
decide to do so.
BUG REPORTS AND FIXES (Un*x systems):
Please coordinate changes through David Trueman and/or Arnold Robbins.
David Trueman
Department of Mathematics, Statistics and Computing Science,
Dalhousie University, Halifax, Nova Scotia, Canada
UUCP: {uunet utai watmath}!dalcs!david
INTERNET: david@cs.dal.ca
Arnold Robbins
1736 Reindeer Drive
Atlanta, GA, 30329-3528, USA
INTERNET: arnold@skeeve.atl.ga.us
UUCP: { gatech, emory, emoryu1 }!skeeve!arnold
BUG REPORTS AND FIXES (non-Unix ports):
MS-DOS:
Scott Deifik
AMGEN Inc.
Amgen Center, Bldg.17-Dept.393
Thousand Oaks, CA 91320-1789
Tel-805-499-5725 ext.4677
Fax-805-498-0358
scottd@amgen.com
VMS:
Pat Rankin
rankin@eql.caltech.edu (e-mail only)
Atari ST:
Michal Jaegermann
michal@gortel.phys.ualberta.ca (e-mail only)
OS/2:
Kai Uwe Rommel
rommel@ars.muc.de (e-mail only)
Darrel Hankerson
hankedr@mail.auburn.edu (e-mail only)

View file

@ -1,515 +0,0 @@
/*
* array.c - routines for associative arrays.
*/
/*
* Copyright (C) 1986, 1988, 1989, 1991, 1992, 1993 the Free Software Foundation, Inc.
*
* This file is part of GAWK, the GNU implementation of the
* AWK Progamming Language.
*
* GAWK 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 2 of the License, or
* (at your option) any later version.
*
* GAWK 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 GAWK; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*
* Tree walks (``for (iggy in foo)'') and array deletions use expensive
* linear searching. So what we do is start out with small arrays and
* grow them as needed, so that our arrays are hopefully small enough,
* most of the time, that they're pretty full and we're not looking at
* wasted space.
*
* The decision is made to grow the array if the average chain length is
* ``too big''. This is defined as the total number of entries in the table
* divided by the size of the array being greater than some constant.
*/
#define AVG_CHAIN_MAX 10 /* don't want to linear search more than this */
#include "awk.h"
static NODE *assoc_find P((NODE *symbol, NODE *subs, int hash1));
static void grow_table P((NODE *symbol));
NODE *
concat_exp(tree)
register NODE *tree;
{
register NODE *r;
char *str;
char *s;
size_t len;
int offset;
size_t subseplen;
char *subsep;
if (tree->type != Node_expression_list)
return force_string(tree_eval(tree));
r = force_string(tree_eval(tree->lnode));
if (tree->rnode == NULL)
return r;
subseplen = SUBSEP_node->lnode->stlen;
subsep = SUBSEP_node->lnode->stptr;
len = r->stlen + subseplen + 2;
emalloc(str, char *, len, "concat_exp");
memcpy(str, r->stptr, r->stlen+1);
s = str + r->stlen;
free_temp(r);
tree = tree->rnode;
while (tree) {
if (subseplen == 1)
*s++ = *subsep;
else {
memcpy(s, subsep, subseplen+1);
s += subseplen;
}
r = force_string(tree_eval(tree->lnode));
len += r->stlen + subseplen;
offset = s - str;
erealloc(str, char *, len, "concat_exp");
s = str + offset;
memcpy(s, r->stptr, r->stlen+1);
s += r->stlen;
free_temp(r);
tree = tree->rnode;
}
r = make_str_node(str, s - str, ALREADY_MALLOCED);
r->flags |= TEMP;
return r;
}
/* Flush all the values in symbol[] before doing a split() */
void
assoc_clear(symbol)
NODE *symbol;
{
int i;
NODE *bucket, *next;
if (symbol->var_array == 0)
return;
for (i = 0; i < symbol->array_size; i++) {
for (bucket = symbol->var_array[i]; bucket; bucket = next) {
next = bucket->ahnext;
unref(bucket->ahname);
unref(bucket->ahvalue);
freenode(bucket);
}
symbol->var_array[i] = 0;
}
free(symbol->var_array);
symbol->var_array = NULL;
symbol->array_size = symbol->table_size = 0;
symbol->flags &= ~ARRAYMAXED;
}
/*
* calculate the hash function of the string in subs
*/
unsigned int
hash(s, len, hsize)
register const char *s;
register size_t len;
unsigned long hsize;
{
register unsigned long h = 0;
#ifdef this_is_really_slow
register unsigned long g;
while (len--) {
h = (h << 4) + *s++;
g = (h & 0xf0000000);
if (g) {
h = h ^ (g >> 24);
h = h ^ g;
}
}
#else /* this_is_really_slow */
/*
* This is INCREDIBLY ugly, but fast. We break the string up into 8 byte
* units. On the first time through the loop we get the "leftover bytes"
* (strlen % 8). On every other iteration, we perform 8 HASHC's so we handle
* all 8 bytes. Essentially, this saves us 7 cmp & branch instructions. If
* this routine is heavily used enough, it's worth the ugly coding.
*
* OZ's original sdbm hash, copied from Margo Seltzers db package.
*
*/
/* Even more speed: */
/* #define HASHC h = *s++ + 65599 * h */
/* Because 65599 = pow(2,6) + pow(2,16) - 1 we multiply by shifts */
#define HASHC htmp = (h << 6); \
h = *s++ + htmp + (htmp << 10) - h
unsigned long htmp;
h = 0;
#if defined(VAXC)
/*
* [This was an implementation of "Duff's Device", but it has been
* redone, separating the switch for extra iterations from the loop.
* This is necessary because the DEC VAX-C compiler is STOOPID.]
*/
switch (len & (8 - 1)) {
case 7: HASHC;
case 6: HASHC;
case 5: HASHC;
case 4: HASHC;
case 3: HASHC;
case 2: HASHC;
case 1: HASHC;
default: break;
}
if (len > (8 - 1)) {
register size_t loop = len >> 3;
do {
HASHC;
HASHC;
HASHC;
HASHC;
HASHC;
HASHC;
HASHC;
HASHC;
} while (--loop);
}
#else /* !VAXC */
/* "Duff's Device" for those who can handle it */
if (len > 0) {
register size_t loop = (len + 8 - 1) >> 3;
switch (len & (8 - 1)) {
case 0:
do { /* All fall throughs */
HASHC;
case 7: HASHC;
case 6: HASHC;
case 5: HASHC;
case 4: HASHC;
case 3: HASHC;
case 2: HASHC;
case 1: HASHC;
} while (--loop);
}
}
#endif /* !VAXC */
#endif /* this_is_really_slow - not */
if (h >= hsize)
h %= hsize;
return h;
}
/*
* locate symbol[subs]
*/
static NODE * /* NULL if not found */
assoc_find(symbol, subs, hash1)
NODE *symbol;
register NODE *subs;
int hash1;
{
register NODE *bucket, *prev = 0;
for (bucket = symbol->var_array[hash1]; bucket; bucket = bucket->ahnext) {
if (cmp_nodes(bucket->ahname, subs) == 0) {
#if 0
/*
* Disable this code for now. It screws things up if we have
* a ``for (iggy in foo)'' in progress. Interestingly enough,
* this was not a problem in 2.15.3, only in 2.15.4. I'm not
* sure why it works in 2.15.3.
*/
if (prev) { /* move found to front of chain */
prev->ahnext = bucket->ahnext;
bucket->ahnext = symbol->var_array[hash1];
symbol->var_array[hash1] = bucket;
}
#endif
return bucket;
} else
prev = bucket; /* save previous list entry */
}
return NULL;
}
/*
* test whether the array element symbol[subs] exists or not
*/
int
in_array(symbol, subs)
NODE *symbol, *subs;
{
register int hash1;
if (symbol->type == Node_param_list)
symbol = stack_ptr[symbol->param_cnt];
if (symbol->var_array == 0)
return 0;
subs = concat_exp(subs); /* concat_exp returns a string node */
hash1 = hash(subs->stptr, subs->stlen, (unsigned long) symbol->array_size);
if (assoc_find(symbol, subs, hash1) == NULL) {
free_temp(subs);
return 0;
} else {
free_temp(subs);
return 1;
}
}
/*
* SYMBOL is the address of the node (or other pointer) being dereferenced.
* SUBS is a number or string used as the subscript.
*
* Find SYMBOL[SUBS] in the assoc array. Install it with value "" if it
* isn't there. Returns a pointer ala get_lhs to where its value is stored
*/
NODE **
assoc_lookup(symbol, subs)
NODE *symbol, *subs;
{
register int hash1;
register NODE *bucket;
(void) force_string(subs);
if (symbol->var_array == 0) {
symbol->type = Node_var_array;
symbol->array_size = symbol->table_size = 0; /* sanity */
symbol->flags &= ~ARRAYMAXED;
grow_table(symbol);
hash1 = hash(subs->stptr, subs->stlen,
(unsigned long) symbol->array_size);
} else {
hash1 = hash(subs->stptr, subs->stlen,
(unsigned long) symbol->array_size);
bucket = assoc_find(symbol, subs, hash1);
if (bucket != NULL) {
free_temp(subs);
return &(bucket->ahvalue);
}
}
/* It's not there, install it. */
if (do_lint && subs->stlen == 0)
warning("subscript of array `%s' is null string",
symbol->vname);
/* first see if we would need to grow the array, before installing */
symbol->table_size++;
if ((symbol->flags & ARRAYMAXED) == 0
&& symbol->table_size/symbol->array_size > AVG_CHAIN_MAX) {
grow_table(symbol);
/* have to recompute hash value for new size */
hash1 = hash(subs->stptr, subs->stlen,
(unsigned long) symbol->array_size);
}
getnode(bucket);
bucket->type = Node_ahash;
if (subs->flags & TEMP)
bucket->ahname = dupnode(subs);
else {
unsigned int saveflags = subs->flags;
subs->flags &= ~MALLOC;
bucket->ahname = dupnode(subs);
subs->flags = saveflags;
}
free_temp(subs);
/* array subscripts are strings */
bucket->ahname->flags &= ~NUMBER;
bucket->ahname->flags |= STRING;
bucket->ahvalue = Nnull_string;
bucket->ahnext = symbol->var_array[hash1];
symbol->var_array[hash1] = bucket;
return &(bucket->ahvalue);
}
void
do_delete(symbol, tree)
NODE *symbol, *tree;
{
register int hash1;
register NODE *bucket, *last;
NODE *subs;
if (symbol->type == Node_param_list)
symbol = stack_ptr[symbol->param_cnt];
if (symbol->var_array == 0)
return;
subs = concat_exp(tree); /* concat_exp returns string node */
hash1 = hash(subs->stptr, subs->stlen, (unsigned long) symbol->array_size);
last = NULL;
for (bucket = symbol->var_array[hash1]; bucket; last = bucket, bucket = bucket->ahnext)
if (cmp_nodes(bucket->ahname, subs) == 0)
break;
free_temp(subs);
if (bucket == NULL)
return;
if (last)
last->ahnext = bucket->ahnext;
else
symbol->var_array[hash1] = bucket->ahnext;
unref(bucket->ahname);
unref(bucket->ahvalue);
freenode(bucket);
symbol->table_size--;
if (symbol->table_size <= 0) {
memset(symbol->var_array, '\0',
sizeof(NODE *) * symbol->array_size);
symbol->table_size = symbol->array_size = 0;
symbol->flags &= ~ARRAYMAXED;
free((char *) symbol->var_array);
symbol->var_array = NULL;
}
}
void
assoc_scan(symbol, lookat)
NODE *symbol;
struct search *lookat;
{
lookat->sym = symbol;
lookat->idx = 0;
lookat->bucket = NULL;
lookat->retval = NULL;
if (symbol->var_array != NULL)
assoc_next(lookat);
}
void
assoc_next(lookat)
struct search *lookat;
{
register NODE *symbol = lookat->sym;
if (symbol == NULL)
fatal("null symbol in assoc_next");
if (symbol->var_array == NULL || lookat->idx > symbol->array_size) {
lookat->retval = NULL;
return;
}
/*
* This is theoretically unsafe. The element bucket might have
* been freed if the body of the scan did a delete on the next
* element of the bucket. The only way to do that is by array
* reference, which is unlikely. Basically, if the user is doing
* anything other than an operation on the current element of an
* assoc array while walking through it sequentially, all bets are
* off. (The safe way is to register all search structs on an
* array with the array, and update all of them on a delete or
* insert)
*/
if (lookat->bucket != NULL) {
lookat->retval = lookat->bucket->ahname;
lookat->bucket = lookat->bucket->ahnext;
return;
}
for (; lookat->idx < symbol->array_size; lookat->idx++) {
NODE *bucket;
if ((bucket = symbol->var_array[lookat->idx]) != NULL) {
lookat->retval = bucket->ahname;
lookat->bucket = bucket->ahnext;
lookat->idx++;
return;
}
}
lookat->retval = NULL;
lookat->bucket = NULL;
return;
}
/* grow_table --- grow a hash table */
static void
grow_table(symbol)
NODE *symbol;
{
NODE **old, **new, *chain, *next;
int i, j;
unsigned long hash1;
unsigned long oldsize, newsize;
/*
* This is an array of primes. We grow the table by an order of
* magnitude each time (not just doubling) so that growing is a
* rare operation. We expect, on average, that it won't happen
* more than twice. The final size is also chosen to be small
* enough so that MS-DOG mallocs can handle it. When things are
* very large (> 8K), we just double more or less, instead of
* just jumping from 8K to 64K.
*/
static long sizes[] = { 13, 127, 1021, 8191, 16381, 32749, 65497 };
/* find next biggest hash size */
oldsize = symbol->array_size;
newsize = 0;
for (i = 0, j = sizeof(sizes)/sizeof(sizes[0]); i < j; i++) {
if (oldsize < sizes[i]) {
newsize = sizes[i];
break;
}
}
if (newsize == oldsize) { /* table already at max (!) */
symbol->flags |= ARRAYMAXED;
return;
}
/* allocate new table */
emalloc(new, NODE **, newsize * sizeof(NODE *), "grow_table");
memset(new, '\0', newsize * sizeof(NODE *));
/* brand new hash table, set things up and return */
if (symbol->var_array == NULL) {
symbol->table_size = 0;
goto done;
}
/* old hash table there, move stuff to new, free old */
old = symbol->var_array;
for (i = 0; i < oldsize; i++) {
if (old[i] == NULL)
continue;
for (chain = old[i]; chain != NULL; chain = next) {
next = chain->ahnext;
hash1 = hash(chain->ahname->stptr,
chain->ahname->stlen, newsize);
/* remove from old list, add to new */
chain->ahnext = new[hash1];
new[hash1] = chain;
}
}
free(old);
done:
/*
* note that symbol->table_size does not change if an old array,
* and is explicitly set to 0 if a new one.
*/
symbol->var_array = new;
symbol->array_size = newsize;
}

File diff suppressed because it is too large Load diff

View file

@ -1,790 +0,0 @@
/*
* awk.h -- Definitions for gawk.
*/
/*
* Copyright (C) 1986, 1988, 1989, 1991, 1992, 1993 the Free Software Foundation, Inc.
*
* This file is part of GAWK, the GNU implementation of the
* AWK Progamming Language.
*
* GAWK 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 2 of the License, or
* (at your option) any later version.
*
* GAWK 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 GAWK; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* ------------------------------ Includes ------------------------------ */
#include "config.h"
#include <stdio.h>
#ifndef LIMITS_H_MISSING
#include <limits.h>
#endif
#include <ctype.h>
#include <setjmp.h>
#include <varargs.h>
#include <time.h>
#include <errno.h>
#if !defined(errno) && !defined(MSDOS) && !defined(OS2)
extern int errno;
#endif
#ifdef __GNU_LIBRARY__
#ifndef linux
#include <signum.h>
#endif
#endif
/* ----------------- System dependencies (with more includes) -----------*/
#if defined(__FreeBSD__)
# include <floatingpoint.h>
#endif
#if !defined(VMS) || (!defined(VAXC) && !defined(__DECC))
#include <sys/types.h>
#include <sys/stat.h>
#else /* VMS w/ VAXC or DECC */
#include <types.h>
#include <stat.h>
#include <file.h> /* avoid <fcntl.h> in io.c */
#endif
#include <signal.h>
#ifdef __STDC__
#define P(s) s
#define MALLOC_ARG_T size_t
#else
#define P(s) ()
#define MALLOC_ARG_T unsigned
#define volatile
#define const
#endif
#ifndef SIGTYPE
#define SIGTYPE void
#endif
#ifdef SIZE_T_MISSING
typedef unsigned int size_t;
#endif
#ifndef SZTC
#define SZTC
#define INTC
#endif
#ifdef STDC_HEADERS
#include <stdlib.h>
#include <string.h>
#ifdef NeXT
#include <libc.h>
#undef atof
#else
#if defined(atarist) || defined(VMS)
#include <unixlib.h>
#else /* atarist || VMS */
#if !defined(MSDOS) && !defined(_MSC_VER)
#include <unistd.h>
#endif /* MSDOS */
#endif /* atarist || VMS */
#endif /* Next */
#else /* STDC_HEADERS */
#include "protos.h"
#endif /* STDC_HEADERS */
#if defined(ultrix) && !defined(Ultrix41)
extern char * getenv P((char *name));
extern double atof P((char *s));
#endif
#ifndef __GNUC__
#ifdef sparc
/* nasty nasty SunOS-ism */
#include <alloca.h>
#ifdef lint
extern char *alloca();
#endif
#else /* not sparc */
#if !defined(alloca) && !defined(ALLOCA_PROTO)
#if defined(_MSC_VER)
#include <malloc.h>
#else
extern char *alloca();
#endif /* _MSC_VER */
#endif
#endif /* sparc */
#endif /* __GNUC__ */
#ifdef HAVE_UNDERSCORE_SETJMP
/* nasty nasty berkelixm */
#define setjmp _setjmp
#define longjmp _longjmp
#endif
/*
* if you don't have vprintf, try this and cross your fingers.
*/
#if defined(VPRINTF_MISSING)
#define vfprintf(fp,fmt,arg) _doprnt((fmt), (arg), (fp))
#endif
#ifdef VMS
/* some macros to redirect to code in vms/vms_misc.c */
#define exit vms_exit
#define open vms_open
#define strerror vms_strerror
#define strdup vms_strdup
extern void exit P((int));
extern int open P((const char *,int,...));
extern char *strerror P((int));
extern char *strdup P((const char *str));
extern int vms_devopen P((const char *,int));
# ifndef NO_TTY_FWRITE
#define fwrite tty_fwrite
#define fclose tty_fclose
extern size_t fwrite P((const void *,size_t,size_t,FILE *));
extern int fclose P((FILE *));
# endif
extern FILE *popen P((const char *,const char *));
extern int pclose P((FILE *));
extern void vms_arg_fixup P((int *,char ***));
/* some things not in STDC_HEADERS */
extern size_t gnu_strftime P((char *,size_t,const char *,const struct tm *));
extern int unlink P((const char *));
extern int getopt P((int,char **,char *));
extern int isatty P((int));
#ifndef fileno
extern int fileno P((FILE *));
#endif
extern int close(), dup(), dup2(), fstat(), read(), stat();
extern int getpgrp P((void));
#endif /*VMS*/
#define GNU_REGEX
#ifdef GNU_REGEX
#include "gnuregex.h"
#include "dfa.h"
typedef struct Regexp {
struct re_pattern_buffer pat;
struct re_registers regs;
struct dfa dfareg;
int dfa;
} Regexp;
#define RESTART(rp,s) (rp)->regs.start[0]
#define REEND(rp,s) (rp)->regs.end[0]
#else /* GNU_REGEX */
#endif /* GNU_REGEX */
#ifdef atarist
#define read _text_read /* we do not want all these CR's to mess our input */
extern int _text_read (int, char *, int);
#ifndef __MINT__
#undef NGROUPS_MAX
#endif /* __MINT__ */
#endif
#ifndef DEFPATH
#define DEFPATH ".:/usr/local/lib/awk:/usr/lib/awk"
#endif
#ifndef ENVSEP
#define ENVSEP ':'
#endif
extern double double_to_int P((double d));
/* ------------------ Constants, Structures, Typedefs ------------------ */
#define AWKNUM double
typedef enum {
/* illegal entry == 0 */
Node_illegal,
/* binary operators lnode and rnode are the expressions to work on */
Node_times,
Node_quotient,
Node_mod,
Node_plus,
Node_minus,
Node_cond_pair, /* conditional pair (see Node_line_range) */
Node_subscript,
Node_concat,
Node_exp,
/* unary operators subnode is the expression to work on */
/*10*/ Node_preincrement,
Node_predecrement,
Node_postincrement,
Node_postdecrement,
Node_unary_minus,
Node_field_spec,
/* assignments lnode is the var to assign to, rnode is the exp */
Node_assign,
Node_assign_times,
Node_assign_quotient,
Node_assign_mod,
/*20*/ Node_assign_plus,
Node_assign_minus,
Node_assign_exp,
/* boolean binaries lnode and rnode are expressions */
Node_and,
Node_or,
/* binary relationals compares lnode and rnode */
Node_equal,
Node_notequal,
Node_less,
Node_greater,
Node_leq,
/*30*/ Node_geq,
Node_match,
Node_nomatch,
/* unary relationals works on subnode */
Node_not,
/* program structures */
Node_rule_list, /* lnode is a rule, rnode is rest of list */
Node_rule_node, /* lnode is pattern, rnode is statement */
Node_statement_list, /* lnode is statement, rnode is more list */
Node_if_branches, /* lnode is to run on true, rnode on false */
Node_expression_list, /* lnode is an exp, rnode is more list */
Node_param_list, /* lnode is a variable, rnode is more list */
/* keywords */
/*40*/ Node_K_if, /* lnode is conditonal, rnode is if_branches */
Node_K_while, /* lnode is condtional, rnode is stuff to run */
Node_K_for, /* lnode is for_struct, rnode is stuff to run */
Node_K_arrayfor, /* lnode is for_struct, rnode is stuff to run */
Node_K_break, /* no subs */
Node_K_continue, /* no stuff */
Node_K_print, /* lnode is exp_list, rnode is redirect */
Node_K_printf, /* lnode is exp_list, rnode is redirect */
Node_K_next, /* no subs */
Node_K_exit, /* subnode is return value, or NULL */
/*50*/ Node_K_do, /* lnode is conditional, rnode stuff to run */
Node_K_return,
Node_K_delete,
Node_K_getline,
Node_K_function, /* lnode is statement list, rnode is params */
/* I/O redirection for print statements */
Node_redirect_output, /* subnode is where to redirect */
Node_redirect_append, /* subnode is where to redirect */
Node_redirect_pipe, /* subnode is where to redirect */
Node_redirect_pipein, /* subnode is where to redirect */
Node_redirect_input, /* subnode is where to redirect */
/* Variables */
/*60*/ Node_var, /* rnode is value, lnode is array stuff */
Node_var_array, /* array is ptr to elements, asize num of
* eles */
Node_val, /* node is a value - type in flags */
/* Builtins subnode is explist to work on, proc is func to call */
Node_builtin,
/*
* pattern: conditional ',' conditional ; lnode of Node_line_range
* is the two conditionals (Node_cond_pair), other word (rnode place)
* is a flag indicating whether or not this range has been entered.
*/
Node_line_range,
/*
* boolean test of membership in array lnode is string-valued
* expression rnode is array name
*/
Node_in_array,
Node_func, /* lnode is param. list, rnode is body */
Node_func_call, /* lnode is name, rnode is argument list */
Node_cond_exp, /* lnode is conditonal, rnode is if_branches */
Node_regex,
/*70*/ Node_hashnode,
Node_ahash,
Node_NF,
Node_NR,
Node_FNR,
Node_FS,
Node_RS,
Node_FIELDWIDTHS,
Node_IGNORECASE,
Node_OFS,
Node_ORS,
Node_OFMT,
Node_CONVFMT,
Node_K_nextfile
} NODETYPE;
/*
* NOTE - this struct is a rather kludgey -- it is packed to minimize
* space usage, at the expense of cleanliness. Alter at own risk.
*/
typedef struct exp_node {
union {
struct {
union {
struct exp_node *lptr;
char *param_name;
long ll;
} l;
union {
struct exp_node *rptr;
struct exp_node *(*pptr) ();
Regexp *preg;
struct for_loop_header *hd;
struct exp_node **av;
int r_ent; /* range entered */
} r;
union {
char *name;
struct exp_node *extra;
long xl;
} x;
short number;
unsigned char reflags;
# define CASE 1
# define CONST 2
# define FS_DFLT 4
} nodep;
struct {
AWKNUM fltnum; /* this is here for optimal packing of
* the structure on many machines
*/
char *sp;
size_t slen;
unsigned char sref;
char idx;
} val;
struct {
struct exp_node *next;
char *name;
size_t length;
struct exp_node *value;
} hash;
#define hnext sub.hash.next
#define hname sub.hash.name
#define hlength sub.hash.length
#define hvalue sub.hash.value
struct {
struct exp_node *next;
struct exp_node *name;
struct exp_node *value;
} ahash;
#define ahnext sub.ahash.next
#define ahname sub.ahash.name
#define ahvalue sub.ahash.value
} sub;
NODETYPE type;
unsigned short flags;
# define MALLOC 1 /* can be free'd */
# define TEMP 2 /* should be free'd */
# define PERM 4 /* can't be free'd */
# define STRING 8 /* assigned as string */
# define STR 16 /* string value is current */
# define NUM 32 /* numeric value is current */
# define NUMBER 64 /* assigned as number */
# define MAYBE_NUM 128 /* user input: if NUMERIC then
* a NUMBER */
# define ARRAYMAXED 256 /* array is at max size */
char *vname; /* variable's name */
} NODE;
#define lnode sub.nodep.l.lptr
#define nextp sub.nodep.l.lptr
#define rnode sub.nodep.r.rptr
#define source_file sub.nodep.x.name
#define source_line sub.nodep.number
#define param_cnt sub.nodep.number
#define param sub.nodep.l.param_name
#define subnode lnode
#define proc sub.nodep.r.pptr
#define re_reg sub.nodep.r.preg
#define re_flags sub.nodep.reflags
#define re_text lnode
#define re_exp sub.nodep.x.extra
#define re_cnt sub.nodep.number
#define forsub lnode
#define forloop rnode->sub.nodep.r.hd
#define stptr sub.val.sp
#define stlen sub.val.slen
#define stref sub.val.sref
#define stfmt sub.val.idx
#define numbr sub.val.fltnum
#define var_value lnode
#define var_array sub.nodep.r.av
#define array_size sub.nodep.l.ll
#define table_size sub.nodep.x.xl
#define condpair lnode
#define triggered sub.nodep.r.r_ent
#ifdef DONTDEF
int primes[] = {31, 61, 127, 257, 509, 1021, 2053, 4099, 8191, 16381};
#endif
typedef struct for_loop_header {
NODE *init;
NODE *cond;
NODE *incr;
} FOR_LOOP_HEADER;
/* for "for(iggy in foo) {" */
struct search {
NODE *sym;
size_t idx;
NODE *bucket;
NODE *retval;
};
/* for faster input, bypass stdio */
typedef struct iobuf {
int fd;
char *buf;
char *off;
char *end;
size_t size; /* this will be determined by an fstat() call */
int cnt;
long secsiz;
int flag;
# define IOP_IS_TTY 1
# define IOP_IS_INTERNAL 2
# define IOP_NO_FREE 4
} IOBUF;
typedef void (*Func_ptr)();
/*
* structure used to dynamically maintain a linked-list of open files/pipes
*/
struct redirect {
unsigned int flag;
# define RED_FILE 1
# define RED_PIPE 2
# define RED_READ 4
# define RED_WRITE 8
# define RED_APPEND 16
# define RED_NOBUF 32
# define RED_USED 64
# define RED_EOF 128
char *value;
FILE *fp;
IOBUF *iop;
int pid;
int status;
struct redirect *prev;
struct redirect *next;
};
/* structure for our source, either a command line string or a source file */
struct src {
enum srctype { CMDLINE = 1, SOURCEFILE } stype;
char *val;
};
/* longjmp return codes, must be nonzero */
/* Continue means either for loop/while continue, or next input record */
#define TAG_CONTINUE 1
/* Break means either for/while break, or stop reading input */
#define TAG_BREAK 2
/* Return means return from a function call; leave value in ret_node */
#define TAG_RETURN 3
#ifndef INT_MAX
#define INT_MAX (~(1 << (sizeof (int) * 8 - 1)))
#endif
#ifndef LONG_MAX
#define LONG_MAX (~(1 << (sizeof (long) * 8 - 1)))
#endif
#ifndef ULONG_MAX
#define ULONG_MAX (~(unsigned long)0)
#endif
#ifndef LONG_MIN
#define LONG_MIN (-LONG_MAX - 1)
#endif
#define HUGE INT_MAX
/* -------------------------- External variables -------------------------- */
/* gawk builtin variables */
extern long NF;
extern long NR;
extern long FNR;
extern int IGNORECASE;
extern char *RS;
extern char *OFS;
extern int OFSlen;
extern char *ORS;
extern int ORSlen;
extern char *OFMT;
extern char *CONVFMT;
extern int CONVFMTidx;
extern int OFMTidx;
extern NODE *FS_node, *NF_node, *RS_node, *NR_node;
extern NODE *FILENAME_node, *OFS_node, *ORS_node, *OFMT_node;
extern NODE *CONVFMT_node;
extern NODE *FNR_node, *RLENGTH_node, *RSTART_node, *SUBSEP_node;
extern NODE *IGNORECASE_node;
extern NODE *FIELDWIDTHS_node;
extern NODE **stack_ptr;
extern NODE *Nnull_string;
extern NODE **fields_arr;
extern int sourceline;
extern char *source;
extern NODE *expression_value;
extern NODE *_t; /* used as temporary in tree_eval */
extern const char *myname;
extern NODE *nextfree;
extern int field0_valid;
extern int do_unix;
extern int do_posix;
extern int do_lint;
extern int in_begin_rule;
extern int in_end_rule;
/* ------------------------- Pseudo-functions ------------------------- */
#define is_identchar(c) (isalnum(c) || (c) == '_')
#ifndef MPROF
#define getnode(n) if (nextfree) n = nextfree, nextfree = nextfree->nextp;\
else n = more_nodes()
#define freenode(n) ((n)->nextp = nextfree, nextfree = (n))
#else
#define getnode(n) emalloc(n, NODE *, sizeof(NODE), "getnode")
#define freenode(n) free(n)
#endif
#ifdef DEBUG
#define tree_eval(t) r_tree_eval(t)
#define get_lhs(p, a) r_get_lhs((p), (a))
#undef freenode
#else
#define get_lhs(p, a) ((p)->type == Node_var ? (&(p)->var_value) : \
r_get_lhs((p), (a)))
#define tree_eval(t) (_t = (t),_t == NULL ? Nnull_string : \
(_t->type == Node_param_list ? r_tree_eval(_t) : \
(_t->type == Node_val ? _t : \
(_t->type == Node_var ? _t->var_value : \
r_tree_eval(_t)))))
#endif
#define make_number(x) mk_number((x), (unsigned int)(MALLOC|NUM|NUMBER))
#define tmp_number(x) mk_number((x), (unsigned int)(MALLOC|TEMP|NUM|NUMBER))
#define free_temp(n) do {if ((n)->flags&TEMP) { unref(n); }} while (0)
#define make_string(s,l) make_str_node((s), SZTC (l),0)
#define SCAN 1
#define ALREADY_MALLOCED 2
#define cant_happen() fatal("internal error line %d, file: %s", \
__LINE__, __FILE__);
#if defined(__STDC__) && !defined(NO_TOKEN_PASTING)
#define emalloc(var,ty,x,str) (void)((var=(ty)malloc((MALLOC_ARG_T)(x))) ||\
(fatal("%s: %s: can't allocate memory (%s)",\
(str), #var, strerror(errno)),0))
#define erealloc(var,ty,x,str) (void)((var=(ty)realloc((char *)var,\
(MALLOC_ARG_T)(x))) ||\
(fatal("%s: %s: can't allocate memory (%s)",\
(str), #var, strerror(errno)),0))
#else /* __STDC__ */
#define emalloc(var,ty,x,str) (void)((var=(ty)malloc((MALLOC_ARG_T)(x))) ||\
(fatal("%s: %s: can't allocate memory (%s)",\
(str), "var", strerror(errno)),0))
#define erealloc(var,ty,x,str) (void)((var=(ty)realloc((char *)var,\
(MALLOC_ARG_T)(x))) ||\
(fatal("%s: %s: can't allocate memory (%s)",\
(str), "var", strerror(errno)),0))
#endif /* __STDC__ */
#ifdef DEBUG
#define force_number r_force_number
#define force_string r_force_string
#else /* not DEBUG */
#ifdef lint
extern AWKNUM force_number();
#endif
#ifdef MSDOS
extern double _msc51bug;
#define force_number(n) (_msc51bug=(_t = (n),(_t->flags & NUM) ? _t->numbr : r_force_number(_t)))
#else /* not MSDOS */
#define force_number(n) (_t = (n),(_t->flags & NUM) ? _t->numbr : r_force_number(_t))
#endif /* MSDOS */
#define force_string(s) (_t = (s),(_t->flags & STR) ? _t : r_force_string(_t))
#endif /* not DEBUG */
#define STREQ(a,b) (*(a) == *(b) && strcmp((a), (b)) == 0)
#define STREQN(a,b,n) ((n)&& *(a)== *(b) && strncmp((a), (b), SZTC (n)) == 0)
/* ------------- Function prototypes or defs (as appropriate) ------------- */
/* array.c */
extern NODE *concat_exp P((NODE *tree));
extern void assoc_clear P((NODE *symbol));
extern unsigned int hash P((const char *s, size_t len, unsigned long hsize));
extern int in_array P((NODE *symbol, NODE *subs));
extern NODE **assoc_lookup P((NODE *symbol, NODE *subs));
extern void do_delete P((NODE *symbol, NODE *tree));
extern void assoc_scan P((NODE *symbol, struct search *lookat));
extern void assoc_next P((struct search *lookat));
/* awk.tab.c */
extern char *tokexpand P((void));
extern char nextc P((void));
extern NODE *node P((NODE *left, NODETYPE op, NODE *right));
extern NODE *install P((char *name, NODE *value));
extern NODE *lookup P((const char *name));
extern NODE *variable P((char *name, int can_free));
extern int yyparse P((void));
/* builtin.c */
extern NODE *do_exp P((NODE *tree));
extern NODE *do_index P((NODE *tree));
extern NODE *do_int P((NODE *tree));
extern NODE *do_length P((NODE *tree));
extern NODE *do_log P((NODE *tree));
extern NODE *do_sprintf P((NODE *tree));
extern void do_printf P((NODE *tree));
extern void print_simple P((NODE *tree, FILE *fp));
extern NODE *do_sqrt P((NODE *tree));
extern NODE *do_substr P((NODE *tree));
extern NODE *do_strftime P((NODE *tree));
extern NODE *do_systime P((NODE *tree));
extern NODE *do_system P((NODE *tree));
extern void do_print P((NODE *tree));
extern NODE *do_tolower P((NODE *tree));
extern NODE *do_toupper P((NODE *tree));
extern NODE *do_atan2 P((NODE *tree));
extern NODE *do_sin P((NODE *tree));
extern NODE *do_cos P((NODE *tree));
extern NODE *do_rand P((NODE *tree));
extern NODE *do_srand P((NODE *tree));
extern NODE *do_match P((NODE *tree));
extern NODE *do_gsub P((NODE *tree));
extern NODE *do_sub P((NODE *tree));
/* eval.c */
extern int interpret P((NODE *volatile tree));
extern NODE *r_tree_eval P((NODE *tree));
extern int cmp_nodes P((NODE *t1, NODE *t2));
extern NODE **r_get_lhs P((NODE *ptr, Func_ptr *assign));
extern void set_IGNORECASE P((void));
void set_OFS P((void));
void set_ORS P((void));
void set_OFMT P((void));
void set_CONVFMT P((void));
/* field.c */
extern void init_fields P((void));
extern void set_record P((char *buf, int cnt, int freeold));
extern void reset_record P((void));
extern void set_NF P((void));
extern NODE **get_field P((int num, Func_ptr *assign));
extern NODE *do_split P((NODE *tree));
extern void set_FS P((void));
extern void set_RS P((void));
extern void set_FIELDWIDTHS P((void));
/* io.c */
extern void set_FNR P((void));
extern void set_NR P((void));
extern void do_input P((void));
extern struct redirect *redirect P((NODE *tree, int *errflg));
extern NODE *do_close P((NODE *tree));
extern int flush_io P((void));
extern int close_io P((void));
extern int devopen P((const char *name, const char *mode));
extern int pathopen P((const char *file));
extern NODE *do_getline P((NODE *tree));
extern void do_nextfile P((void));
/* iop.c */
extern int optimal_bufsize P((int fd));
extern IOBUF *iop_alloc P((int fd));
extern int get_a_record P((char **out, IOBUF *iop, int rs, int *errcode));
/* main.c */
extern int main P((int argc, char **argv));
extern Regexp *mk_re_parse P((char *s, int ignorecase));
extern void load_environ P((void));
extern char *arg_assign P((char *arg));
extern SIGTYPE catchsig P((int sig, int code));
/* msg.c */
extern void err P((const char *s, const char *emsg, va_list argp));
#if _MSC_VER == 510
extern void msg P((va_list va_alist, ...));
extern void warning P((va_list va_alist, ...));
extern void fatal P((va_list va_alist, ...));
#else
extern void msg ();
extern void warning ();
extern void fatal ();
#endif
/* node.c */
extern AWKNUM r_force_number P((NODE *n));
extern NODE *r_force_string P((NODE *s));
extern NODE *dupnode P((NODE *n));
extern NODE *mk_number P((AWKNUM x, unsigned int flags));
extern NODE *make_str_node P((char *s, size_t len, int scan ));
extern NODE *tmp_string P((char *s, size_t len ));
extern NODE *more_nodes P((void));
#ifdef DEBUG
extern void freenode P((NODE *it));
#endif
extern void unref P((NODE *tmp));
extern int parse_escape P((char **string_ptr));
/* re.c */
extern Regexp *make_regexp P((char *s, size_t len, int ignorecase, int dfa));
extern int research P((Regexp *rp, char *str, int start,
size_t len, int need_start));
extern void refree P((Regexp *rp));
extern void reg_error P((const char *s));
extern Regexp *re_update P((NODE *t));
extern void resyntax P((int syntax));
extern void resetup P((void));
/* strcase.c */
extern int strcasecmp P((const char *s1, const char *s2));
extern int strncasecmp P((const char *s1, const char *s2, register size_t n));
#ifdef atarist
/* atari/tmpnam.c */
extern char *tmpnam P((char *buf));
extern char *tempnam P((const char *path, const char *base));
#endif
/* Figure out what '\a' really is. */
#ifdef __STDC__
#define BELL '\a' /* sure makes life easy, don't it? */
#else
# if 'z' - 'a' == 25 /* ascii */
# if 'a' != 97 /* machine is dumb enough to use mark parity */
# define BELL '\207'
# else
# define BELL '\07'
# endif
# else
# define BELL '\057'
# endif
#endif
extern char casetable[]; /* for case-independent regexp matching */

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,306 +0,0 @@
/*
* config.h -- configuration definitions for gawk.
*
* For generic 4.4 alpha
*/
/*
* Copyright (C) 1991, 1992, 1993 the Free Software Foundation, Inc.
*
* This file is part of GAWK, the GNU implementation of the
* AWK Progamming Language.
*
* GAWK 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 2, or (at your option)
* any later version.
*
* GAWK 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 GAWK; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*
* This file isolates configuration dependencies for gnu awk.
* You should know something about your system, perhaps by having
* a manual handy, when you edit this file. You should copy config.h-dist
* to config.h, and edit config.h. Do not modify config.h-dist, so that
* it will be easy to apply any patches that may be distributed.
*
* The general idea is that systems conforming to the various standards
* should need to do the least amount of changing. Definining the various
* items in ths file usually means that your system is missing that
* particular feature.
*
* The order of preference in standard conformance is ANSI C, POSIX,
* and the SVID.
*
* If you have no clue as to what's going on with your system, try
* compiling gawk without editing this file and see what shows up
* missing in the link stage. From there, you can probably figure out
* which defines to turn on.
*/
/**************************/
/* Miscellanious features */
/**************************/
/*
* BLKSIZE_MISSING
*
* Check your /usr/include/sys/stat.h file. If the stat structure
* does not have a member named st_blksize, define this. (This will
* most likely be the case on most System V systems prior to V.4.)
*/
/* #define BLKSIZE_MISSING 1 */
/*
* SIGTYPE
*
* The return type of the routines passed to the signal function.
* Modern systems use `void', older systems use `int'.
* If left undefined, it will default to void.
*/
/* #define SIGTYPE int */
/*
* SIZE_T_MISSING
*
* If your system has no typedef for size_t, define this to get a default
*/
/* #define SIZE_T_MISSING 1 */
/*
* CHAR_UNSIGNED
*
* If your machine uses unsigned characters (IBM RT and RS/6000 and others)
* then define this for use in regex.c
*/
/* #define CHAR_UNSIGNED 1 */
/*
* HAVE_UNDERSCORE_SETJMP
*
* Check in your /usr/include/setjmp.h file. If there are routines
* there named _setjmp and _longjmp, then you should define this.
* Typically only systems derived from Berkeley Unix have this.
*/
#define HAVE_UNDERSCORE_SETJMP 1
/*
* LIMITS_H_MISSING
*
* You don't have a <limits.h> include file.
*/
/* #define LIMITS_H_MISSING 1 */
/***********************************************/
/* Missing library subroutines or system calls */
/***********************************************/
/*
* MEMCMP_MISSING
* MEMCPY_MISSING
* MEMSET_MISSING
*
* These three routines are for manipulating blocks of memory. Most
* likely they will either all three be present or all three be missing,
* so they're grouped together.
*/
/* #define MEMCMP_MISSING 1 */
/* #define MEMCPY_MISSING 1 */
/* #define MEMSET_MISSING 1 */
/*
* RANDOM_MISSING
*
* Your system does not have the random(3) suite of random number
* generating routines. These are different than the old rand(3)
* routines!
*/
/* #define RANDOM_MISSING 1 */
/*
* STRCASE_MISSING
*
* Your system does not have the strcasemp() and strncasecmp()
* routines that originated in Berkeley Unix.
*/
/* #define STRCASE_MISSING 1 */
/*
* STRCHR_MISSING
*
* Your system does not have the strchr() and strrchr() functions.
*/
/* #define STRCHR_MISSING 1 */
/*
* STRERROR_MISSING
*
* Your system lacks the ANSI C strerror() routine for returning the
* strings associated with errno values.
*/
/* #define STRERROR_MISSING 1 */
/*
* STRTOD_MISSING
*
* Your system does not have the strtod() routine for converting
* strings to double precision floating point values.
*/
/* #define STRTOD_MISSING 1 */
/*
* STRFTIME_MISSING
*
* Your system lacks the ANSI C strftime() routine for formatting
* broken down time values.
*/
/* #define STRFTIME_MISSING 1 */
/*
* TZSET_MISSING
*
* If you have a 4.2 BSD vintage system, then the strftime() routine
* supplied in the missing directory won't be enough, because it relies on the
* tzset() routine from System V / Posix. Fortunately, there is an
* emulation for tzset() too that should do the trick. If you don't
* have tzset(), define this.
*/
/* #define TZSET_MISSING 1 */
/*
* TZNAME_MISSING
*
* Some systems do not support the external variables tzname and daylight.
* If this is the case *and* strftime() is missing, define this.
*/
/* #define TZNAME_MISSING 1 */
/*
* TM_ZONE_MISSING
*
* Your "struct tm" is missing the tm_zone field.
* If this is the case *and* strftime() is missing *and* tzname is missing,
* define this.
*/
/* #define TM_ZONE_MISSING 1 */
/*
* STDC_HEADERS
*
* If your system does have ANSI compliant header files that
* provide prototypes for library routines, then define this.
*/
#define STDC_HEADERS 1
/*
* NO_TOKEN_PASTING
*
* If your compiler define's __STDC__ but does not support token
* pasting (tok##tok), then define this.
*/
/* #define NO_TOKEN_PASTING 1 */
/*****************************************************************/
/* Stuff related to the Standard I/O Library. */
/*****************************************************************/
/* Much of this is (still, unfortunately) black magic in nature. */
/* You may have to use some or all of these together to get gawk */
/* to work correctly. */
/*****************************************************************/
/*
* NON_STD_SPRINTF
*
* Look in your /usr/include/stdio.h file. If the return type of the
* sprintf() function is NOT `int', define this.
*/
/* #define NON_STD_SPRINTF 1 */
/*
* VPRINTF_MISSING
*
* Define this if your system lacks vprintf() and the other routines
* that go with it. This will trigger an attempt to use _doprnt().
* If you don't have that, this attempt will fail and you are on your own.
*/
/* #define VPRINTF_MISSING 1 */
/*
* Casts from size_t to int and back. These will become unnecessary
* at some point in the future, but for now are required where the
* two types are a different representation.
*/
/* #define SZTC */
/* #define INTC */
/*
* SYSTEM_MISSING
*
* Define this if your library does not provide a system function
* or you are not entirely happy with it and would rather use
* a provided replacement (atari only).
*/
/* #define SYSTEM_MISSING 1 */
/*
* FMOD_MISSING
*
* Define this if your system lacks the fmod() function and modf() will
* be used instead.
*/
/* #define FMOD_MISSING 1 */
/*******************************/
/* Gawk configuration options. */
/*******************************/
/*
* DEFPATH
*
* The default search path for the -f option of gawk. It is used
* if the AWKPATH environment variable is undefined. The default
* definition is provided here. Most likely you should not change
* this.
*/
/* #define DEFPATH ".:/usr/lib/awk:/usr/local/lib/awk" */
/* #define ENVSEP ':' */
/*
* alloca already has a prototype defined - don't redefine it
*/
#define ALLOCA_PROTO 1
/*
* srandom already has a prototype defined - don't redefine it
*/
#define SRANDOM_PROTO 1
/*
* getpgrp() in sysvr4 and POSIX takes no argument
*/
/* #define GETPGRP_NOARG 0 */
/*
* define const to nothing if not __STDC__
*/
#ifndef __STDC__
#define const
#endif
/* If svr4 and not gcc */
/* #define SVR4 0 */
#ifdef SVR4
#define __svr4__ 1
#endif
/* anything that follows is for system-specific short-term kludges */

File diff suppressed because it is too large Load diff

View file

@ -1,360 +0,0 @@
/* dfa.h - declarations for GNU deterministic regexp compiler
Copyright (C) 1988 Free Software Foundation, Inc.
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 2, 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. */
/* Written June, 1988 by Mike Haertel */
/* FIXME:
2. We should not export so much of the DFA internals.
In addition to clobbering modularity, we eat up valuable
name space. */
/* Number of bits in an unsigned char. */
#define CHARBITS 8
/* First integer value that is greater than any character code. */
#define NOTCHAR (1 << CHARBITS)
/* INTBITS need not be exact, just a lower bound. */
#define INTBITS (CHARBITS * sizeof (int))
/* Number of ints required to hold a bit for every character. */
#define CHARCLASS_INTS ((NOTCHAR + INTBITS - 1) / INTBITS)
/* Sets of unsigned characters are stored as bit vectors in arrays of ints. */
typedef int charclass[CHARCLASS_INTS];
/* The regexp is parsed into an array of tokens in postfix form. Some tokens
are operators and others are terminal symbols. Most (but not all) of these
codes are returned by the lexical analyzer. */
typedef enum
{
END = -1, /* END is a terminal symbol that matches the
end of input; any value of END or less in
the parse tree is such a symbol. Accepting
states of the DFA are those that would have
a transition on END. */
/* Ordinary character values are terminal symbols that match themselves. */
EMPTY = NOTCHAR, /* EMPTY is a terminal symbol that matches
the empty string. */
BACKREF, /* BACKREF is generated by \<digit>; it
it not completely handled. If the scanner
detects a transition on backref, it returns
a kind of "semi-success" indicating that
the match will have to be verified with
a backtracking matcher. */
BEGLINE, /* BEGLINE is a terminal symbol that matches
the empty string if it is at the beginning
of a line. */
ENDLINE, /* ENDLINE is a terminal symbol that matches
the empty string if it is at the end of
a line. */
BEGWORD, /* BEGWORD is a terminal symbol that matches
the empty string if it is at the beginning
of a word. */
ENDWORD, /* ENDWORD is a terminal symbol that matches
the empty string if it is at the end of
a word. */
LIMWORD, /* LIMWORD is a terminal symbol that matches
the empty string if it is at the beginning
or the end of a word. */
NOTLIMWORD, /* NOTLIMWORD is a terminal symbol that
matches the empty string if it is not at
the beginning or end of a word. */
QMARK, /* QMARK is an operator of one argument that
matches zero or one occurences of its
argument. */
STAR, /* STAR is an operator of one argument that
matches the Kleene closure (zero or more
occurrences) of its argument. */
PLUS, /* PLUS is an operator of one argument that
matches the positive closure (one or more
occurrences) of its argument. */
REPMN, /* REPMN is a lexical token corresponding
to the {m,n} construct. REPMN never
appears in the compiled token vector. */
CAT, /* CAT is an operator of two arguments that
matches the concatenation of its
arguments. CAT is never returned by the
lexical analyzer. */
OR, /* OR is an operator of two arguments that
matches either of its arguments. */
ORTOP, /* OR at the toplevel in the parse tree.
This is used for a boyer-moore heuristic. */
LPAREN, /* LPAREN never appears in the parse tree,
it is only a lexeme. */
RPAREN, /* RPAREN never appears in the parse tree. */
CSET /* CSET and (and any value greater) is a
terminal symbol that matches any of a
class of characters. */
} token;
/* Sets are stored in an array in the compiled dfa; the index of the
array corresponding to a given set token is given by SET_INDEX(t). */
#define SET_INDEX(t) ((t) - CSET)
/* Sometimes characters can only be matched depending on the surrounding
context. Such context decisions depend on what the previous character
was, and the value of the current (lookahead) character. Context
dependent constraints are encoded as 8 bit integers. Each bit that
is set indicates that the constraint succeeds in the corresponding
context.
bit 7 - previous and current are newlines
bit 6 - previous was newline, current isn't
bit 5 - previous wasn't newline, current is
bit 4 - neither previous nor current is a newline
bit 3 - previous and current are word-constituents
bit 2 - previous was word-constituent, current isn't
bit 1 - previous wasn't word-constituent, current is
bit 0 - neither previous nor current is word-constituent
Word-constituent characters are those that satisfy isalnum().
The macro SUCCEEDS_IN_CONTEXT determines whether a a given constraint
succeeds in a particular context. Prevn is true if the previous character
was a newline, currn is true if the lookahead character is a newline.
Prevl and currl similarly depend upon whether the previous and current
characters are word-constituent letters. */
#define MATCHES_NEWLINE_CONTEXT(constraint, prevn, currn) \
((constraint) & 1 << (((prevn) ? 2 : 0) + ((currn) ? 1 : 0) + 4))
#define MATCHES_LETTER_CONTEXT(constraint, prevl, currl) \
((constraint) & 1 << (((prevl) ? 2 : 0) + ((currl) ? 1 : 0)))
#define SUCCEEDS_IN_CONTEXT(constraint, prevn, currn, prevl, currl) \
(MATCHES_NEWLINE_CONTEXT(constraint, prevn, currn) \
&& MATCHES_LETTER_CONTEXT(constraint, prevl, currl))
/* The following macros give information about what a constraint depends on. */
#define PREV_NEWLINE_DEPENDENT(constraint) \
(((constraint) & 0xc0) >> 2 != ((constraint) & 0x30))
#define PREV_LETTER_DEPENDENT(constraint) \
(((constraint) & 0x0c) >> 2 != ((constraint) & 0x03))
/* Tokens that match the empty string subject to some constraint actually
work by applying that constraint to determine what may follow them,
taking into account what has gone before. The following values are
the constraints corresponding to the special tokens previously defined. */
#define NO_CONSTRAINT 0xff
#define BEGLINE_CONSTRAINT 0xcf
#define ENDLINE_CONSTRAINT 0xaf
#define BEGWORD_CONSTRAINT 0xf2
#define ENDWORD_CONSTRAINT 0xf4
#define LIMWORD_CONSTRAINT 0xf6
#define NOTLIMWORD_CONSTRAINT 0xf9
/* States of the recognizer correspond to sets of positions in the parse
tree, together with the constraints under which they may be matched.
So a position is encoded as an index into the parse tree together with
a constraint. */
typedef struct
{
unsigned index; /* Index into the parse array. */
unsigned constraint; /* Constraint for matching this position. */
} position;
/* Sets of positions are stored as arrays. */
typedef struct
{
position *elems; /* Elements of this position set. */
int nelem; /* Number of elements in this set. */
} position_set;
/* A state of the dfa consists of a set of positions, some flags,
and the token value of the lowest-numbered position of the state that
contains an END token. */
typedef struct
{
int hash; /* Hash of the positions of this state. */
position_set elems; /* Positions this state could match. */
char newline; /* True if previous state matched newline. */
char letter; /* True if previous state matched a letter. */
char backref; /* True if this state matches a \<digit>. */
unsigned char constraint; /* Constraint for this state to accept. */
int first_end; /* Token value of the first END in elems. */
} dfa_state;
/* Element of a list of strings, at least one of which is known to
appear in any R.E. matching the DFA. */
struct dfamust
{
int exact;
char *must;
struct dfamust *next;
};
/* A compiled regular expression. */
struct dfa
{
/* Stuff built by the scanner. */
charclass *charclasses; /* Array of character sets for CSET tokens. */
int cindex; /* Index for adding new charclasses. */
int calloc; /* Number of charclasses currently allocated. */
/* Stuff built by the parser. */
token *tokens; /* Postfix parse array. */
int tindex; /* Index for adding new tokens. */
int talloc; /* Number of tokens currently allocated. */
int depth; /* Depth required of an evaluation stack
used for depth-first traversal of the
parse tree. */
int nleaves; /* Number of leaves on the parse tree. */
int nregexps; /* Count of parallel regexps being built
with dfaparse(). */
/* Stuff owned by the state builder. */
dfa_state *states; /* States of the dfa. */
int sindex; /* Index for adding new states. */
int salloc; /* Number of states currently allocated. */
/* Stuff built by the structure analyzer. */
position_set *follows; /* Array of follow sets, indexed by position
index. The follow of a position is the set
of positions containing characters that
could conceivably follow a character
matching the given position in a string
matching the regexp. Allocated to the
maximum possible position index. */
int searchflag; /* True if we are supposed to build a searching
as opposed to an exact matcher. A searching
matcher finds the first and shortest string
matching a regexp anywhere in the buffer,
whereas an exact matcher finds the longest
string matching, but anchored to the
beginning of the buffer. */
/* Stuff owned by the executor. */
int tralloc; /* Number of transition tables that have
slots so far. */
int trcount; /* Number of transition tables that have
actually been built. */
int **trans; /* Transition tables for states that can
never accept. If the transitions for a
state have not yet been computed, or the
state could possibly accept, its entry in
this table is NULL. */
int **realtrans; /* Trans always points to realtrans + 1; this
is so trans[-1] can contain NULL. */
int **fails; /* Transition tables after failing to accept
on a state that potentially could do so. */
int *success; /* Table of acceptance conditions used in
dfaexec and computed in build_state. */
int *newlines; /* Transitions on newlines. The entry for a
newline in any transition table is always
-1 so we can count lines without wasting
too many cycles. The transition for a
newline is stored separately and handled
as a special case. Newline is also used
as a sentinel at the end of the buffer. */
struct dfamust *musts; /* List of strings, at least one of which
is known to appear in any r.e. matching
the dfa. */
};
/* Some macros for user access to dfa internals. */
/* ACCEPTING returns true if s could possibly be an accepting state of r. */
#define ACCEPTING(s, r) ((r).states[s].constraint)
/* ACCEPTS_IN_CONTEXT returns true if the given state accepts in the
specified context. */
#define ACCEPTS_IN_CONTEXT(prevn, currn, prevl, currl, state, dfa) \
SUCCEEDS_IN_CONTEXT((dfa).states[state].constraint, \
prevn, currn, prevl, currl)
/* FIRST_MATCHING_REGEXP returns the index number of the first of parallel
regexps that a given state could accept. Parallel regexps are numbered
starting at 1. */
#define FIRST_MATCHING_REGEXP(state, dfa) (-(dfa).states[state].first_end)
/* Entry points. */
#ifdef __STDC__
/* dfasyntax() takes two arguments; the first sets the syntax bits described
earlier in this file, and the second sets the case-folding flag. */
extern void dfasyntax(reg_syntax_t, int);
/* Compile the given string of the given length into the given struct dfa.
Final argument is a flag specifying whether to build a searching or an
exact matcher. */
extern void dfacomp(char *, size_t, struct dfa *, int);
/* Execute the given struct dfa on the buffer of characters. The
first char * points to the beginning, and the second points to the
first character after the end of the buffer, which must be a writable
place so a sentinel end-of-buffer marker can be stored there. The
second-to-last argument is a flag telling whether to allow newlines to
be part of a string matching the regexp. The next-to-last argument,
if non-NULL, points to a place to increment every time we see a
newline. The final argument, if non-NULL, points to a flag that will
be set if further examination by a backtracking matcher is needed in
order to verify backreferencing; otherwise the flag will be cleared.
Returns NULL if no match is found, or a pointer to the first
character after the first & shortest matching string in the buffer. */
extern char *dfaexec(struct dfa *, char *, char *, int, int *, int *);
/* Free the storage held by the components of a struct dfa. */
extern void dfafree(struct dfa *);
/* Entry points for people who know what they're doing. */
/* Initialize the components of a struct dfa. */
extern void dfainit(struct dfa *);
/* Incrementally parse a string of given length into a struct dfa. */
extern void dfaparse(char *, size_t, struct dfa *);
/* Analyze a parsed regexp; second argument tells whether to build a searching
or an exact matcher. */
extern void dfaanalyze(struct dfa *, int);
/* Compute, for each possible character, the transitions out of a given
state, storing them in an array of integers. */
extern void dfastate(int, struct dfa *, int []);
/* Error handling. */
/* dfaerror() is called by the regexp routines whenever an error occurs. It
takes a single argument, a NUL-terminated string describing the error.
The default dfaerror() prints the error message to stderr and exits.
The user can provide a different dfafree() if so desired. */
extern void dfaerror(const char *);
#else /* ! __STDC__ */
extern void dfasyntax(), dfacomp(), dfafree(), dfainit(), dfaparse();
extern void dfaanalyze(), dfastate(), dfaerror();
extern char *dfaexec();
#endif /* ! __STDC__ */

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,678 +0,0 @@
/*
* field.c - routines for dealing with fields and record parsing
*/
/*
* Copyright (C) 1986, 1988, 1989, 1991, 1992, 1993 the Free Software Foundation, Inc.
*
* This file is part of GAWK, the GNU implementation of the
* AWK Progamming Language.
*
* GAWK 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 2 of the License, or
* (at your option) any later version.
*
* GAWK 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 GAWK; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "awk.h"
typedef void (* Setfunc) P((int, char*, int, NODE *));
static long (*parse_field) P((int, char **, int, NODE *,
Regexp *, Setfunc, NODE *));
static void rebuild_record P((void));
static long re_parse_field P((int, char **, int, NODE *,
Regexp *, Setfunc, NODE *));
static long def_parse_field P((int, char **, int, NODE *,
Regexp *, Setfunc, NODE *));
static long sc_parse_field P((int, char **, int, NODE *,
Regexp *, Setfunc, NODE *));
static long fw_parse_field P((int, char **, int, NODE *,
Regexp *, Setfunc, NODE *));
static void set_element P((int, char *, int, NODE *));
static void grow_fields_arr P((long num));
static void set_field P((int num, char *str, int len, NODE *dummy));
static Regexp *FS_regexp = NULL;
static char *parse_extent; /* marks where to restart parse of record */
static long parse_high_water=0; /* field number that we have parsed so far */
static long nf_high_water = 0; /* size of fields_arr */
static int resave_fs;
static NODE *save_FS; /* save current value of FS when line is read,
* to be used in deferred parsing
*/
NODE **fields_arr; /* array of pointers to the field nodes */
int field0_valid; /* $(>0) has not been changed yet */
int default_FS;
static NODE **nodes; /* permanent repository of field nodes */
static int *FIELDWIDTHS = NULL;
void
init_fields()
{
NODE *n;
emalloc(fields_arr, NODE **, sizeof(NODE *), "init_fields");
emalloc(nodes, NODE **, sizeof(NODE *), "init_fields");
getnode(n);
*n = *Nnull_string;
fields_arr[0] = nodes[0] = n;
parse_extent = fields_arr[0]->stptr;
save_FS = dupnode(FS_node->var_value);
field0_valid = 1;
}
static void
grow_fields_arr(num)
long num;
{
register int t;
register NODE *n;
erealloc(fields_arr, NODE **, (num + 1) * sizeof(NODE *), "set_field");
erealloc(nodes, NODE **, (num+1) * sizeof(NODE *), "set_field");
for (t = nf_high_water+1; t <= num; t++) {
getnode(n);
*n = *Nnull_string;
fields_arr[t] = nodes[t] = n;
}
nf_high_water = num;
}
/*ARGSUSED*/
static void
set_field(num, str, len, dummy)
int num;
char *str;
int len;
NODE *dummy; /* not used -- just to make interface same as set_element */
{
register NODE *n;
if (num > nf_high_water)
grow_fields_arr(num);
n = nodes[num];
n->stptr = str;
n->stlen = len;
n->flags = (PERM|STR|STRING|MAYBE_NUM);
fields_arr[num] = n;
}
/* Someone assigned a value to $(something). Fix up $0 to be right */
static void
rebuild_record()
{
register size_t tlen;
register NODE *tmp;
NODE *ofs;
char *ops;
register char *cops;
register NODE **ptr;
register size_t ofslen;
tlen = 0;
ofs = force_string(OFS_node->var_value);
ofslen = ofs->stlen;
ptr = &fields_arr[NF];
while (ptr > &fields_arr[0]) {
tmp = force_string(*ptr);
tlen += tmp->stlen;
ptr--;
}
tlen += (NF - 1) * ofslen;
if ((long)tlen < 0)
tlen = 0;
emalloc(ops, char *, tlen + 2, "rebuild_record");
cops = ops;
ops[0] = '\0';
for (ptr = &fields_arr[1]; ptr <= &fields_arr[NF]; ptr++) {
tmp = *ptr;
if (tmp->stlen == 1)
*cops++ = tmp->stptr[0];
else if (tmp->stlen != 0) {
memcpy(cops, tmp->stptr, tmp->stlen);
cops += tmp->stlen;
}
if (ptr != &fields_arr[NF]) {
if (ofslen == 1)
*cops++ = ofs->stptr[0];
else if (ofslen != 0) {
memcpy(cops, ofs->stptr, ofslen);
cops += ofslen;
}
}
}
tmp = make_str_node(ops, tlen, ALREADY_MALLOCED);
unref(fields_arr[0]);
fields_arr[0] = tmp;
field0_valid = 1;
}
/*
* setup $0, but defer parsing rest of line until reference is made to $(>0)
* or to NF. At that point, parse only as much as necessary.
*/
void
set_record(buf, cnt, freeold)
char *buf;
int cnt;
int freeold;
{
register int i;
NF = -1;
for (i = 1; i <= parse_high_water; i++) {
unref(fields_arr[i]);
}
parse_high_water = 0;
if (freeold) {
unref(fields_arr[0]);
if (resave_fs) {
resave_fs = 0;
unref(save_FS);
save_FS = dupnode(FS_node->var_value);
}
nodes[0]->stptr = buf;
nodes[0]->stlen = cnt;
nodes[0]->stref = 1;
nodes[0]->flags = (STRING|STR|PERM|MAYBE_NUM);
fields_arr[0] = nodes[0];
}
fields_arr[0]->flags |= MAYBE_NUM;
field0_valid = 1;
}
void
reset_record()
{
(void) force_string(fields_arr[0]);
set_record(fields_arr[0]->stptr, fields_arr[0]->stlen, 0);
}
void
set_NF()
{
register int i;
NF = (long) force_number(NF_node->var_value);
if (NF > nf_high_water)
grow_fields_arr(NF);
for (i = parse_high_water + 1; i <= NF; i++) {
unref(fields_arr[i]);
fields_arr[i] = Nnull_string;
}
field0_valid = 0;
}
/*
* this is called both from get_field() and from do_split()
* via (*parse_field)(). This variation is for when FS is a regular
* expression -- either user-defined or because RS=="" and FS==" "
*/
static long
re_parse_field(up_to, buf, len, fs, rp, set, n)
int up_to; /* parse only up to this field number */
char **buf; /* on input: string to parse; on output: point to start next */
int len;
NODE *fs;
Regexp *rp;
Setfunc set; /* routine to set the value of the parsed field */
NODE *n;
{
register char *scan = *buf;
register int nf = parse_high_water;
register char *field;
register char *end = scan + len;
if (up_to == HUGE)
nf = 0;
if (len == 0)
return nf;
if (*RS == 0 && default_FS)
while (scan < end && (*scan == ' ' || *scan == '\t' || *scan == '\n'))
scan++;
field = scan;
while (scan < end
&& research(rp, scan, 0, (end - scan), 1) != -1
&& nf < up_to) {
if (REEND(rp, scan) == RESTART(rp, scan)) { /* null match */
scan++;
if (scan == end) {
(*set)(++nf, field, (int)(scan - field), n);
up_to = nf;
break;
}
continue;
}
(*set)(++nf, field,
(int)(scan + RESTART(rp, scan) - field), n);
scan += REEND(rp, scan);
field = scan;
if (scan == end) /* FS at end of record */
(*set)(++nf, field, 0, n);
}
if (nf != up_to && scan < end) {
(*set)(++nf, scan, (int)(end - scan), n);
scan = end;
}
*buf = scan;
return (nf);
}
/*
* this is called both from get_field() and from do_split()
* via (*parse_field)(). This variation is for when FS is a single space
* character.
*/
static long
def_parse_field(up_to, buf, len, fs, rp, set, n)
int up_to; /* parse only up to this field number */
char **buf; /* on input: string to parse; on output: point to start next */
int len;
NODE *fs;
Regexp *rp;
Setfunc set; /* routine to set the value of the parsed field */
NODE *n;
{
register char *scan = *buf;
register int nf = parse_high_water;
register char *field;
register char *end = scan + len;
char sav;
if (up_to == HUGE)
nf = 0;
if (len == 0)
return nf;
/* before doing anything save the char at *end */
sav = *end;
/* because it will be destroyed now: */
*end = ' '; /* sentinel character */
for (; nf < up_to; scan++) {
/*
* special case: fs is single space, strip leading whitespace
*/
while (scan < end && (*scan == ' ' || *scan == '\t'))
scan++;
if (scan >= end)
break;
field = scan;
while (*scan != ' ' && *scan != '\t')
scan++;
(*set)(++nf, field, (int)(scan - field), n);
if (scan == end)
break;
}
/* everything done, restore original char at *end */
*end = sav;
*buf = scan;
return nf;
}
/*
* this is called both from get_field() and from do_split()
* via (*parse_field)(). This variation is for when FS is a single character
* other than space.
*/
static long
sc_parse_field(up_to, buf, len, fs, rp, set, n)
int up_to; /* parse only up to this field number */
char **buf; /* on input: string to parse; on output: point to start next */
int len;
NODE *fs;
Regexp *rp;
Setfunc set; /* routine to set the value of the parsed field */
NODE *n;
{
register char *scan = *buf;
register char fschar;
register int nf = parse_high_water;
register char *field;
register char *end = scan + len;
char sav;
if (up_to == HUGE)
nf = 0;
if (len == 0)
return nf;
if (*RS == 0 && fs->stlen == 0)
fschar = '\n';
else
fschar = fs->stptr[0];
/* before doing anything save the char at *end */
sav = *end;
/* because it will be destroyed now: */
*end = fschar; /* sentinel character */
for (; nf < up_to;) {
field = scan;
while (*scan != fschar)
scan++;
(*set)(++nf, field, (int)(scan - field), n);
if (scan == end)
break;
scan++;
if (scan == end) { /* FS at end of record */
(*set)(++nf, field, 0, n);
break;
}
}
/* everything done, restore original char at *end */
*end = sav;
*buf = scan;
return nf;
}
/*
* this is called both from get_field() and from do_split()
* via (*parse_field)(). This variation is for fields are fixed widths.
*/
static long
fw_parse_field(up_to, buf, len, fs, rp, set, n)
int up_to; /* parse only up to this field number */
char **buf; /* on input: string to parse; on output: point to start next */
int len;
NODE *fs;
Regexp *rp;
Setfunc set; /* routine to set the value of the parsed field */
NODE *n;
{
register char *scan = *buf;
register long nf = parse_high_water;
register char *end = scan + len;
if (up_to == HUGE)
nf = 0;
if (len == 0)
return nf;
for (; nf < up_to && (len = FIELDWIDTHS[nf+1]) != -1; ) {
if (len > end - scan)
len = end - scan;
(*set)(++nf, scan, len, n);
scan += len;
}
if (len == -1)
*buf = end;
else
*buf = scan;
return nf;
}
NODE **
get_field(requested, assign)
register int requested;
Func_ptr *assign; /* this field is on the LHS of an assign */
{
/*
* if requesting whole line but some other field has been altered,
* then the whole line must be rebuilt
*/
if (requested == 0) {
if (!field0_valid) {
/* first, parse remainder of input record */
if (NF == -1) {
NF = (*parse_field)(HUGE-1, &parse_extent,
fields_arr[0]->stlen -
(parse_extent - fields_arr[0]->stptr),
save_FS, FS_regexp, set_field,
(NODE *)NULL);
parse_high_water = NF;
}
rebuild_record();
}
if (assign)
*assign = reset_record;
return &fields_arr[0];
}
/* assert(requested > 0); */
if (assign)
field0_valid = 0; /* $0 needs reconstruction */
if (requested <= parse_high_water) /* already parsed this field */
return &fields_arr[requested];
if (NF == -1) { /* have not yet parsed to end of record */
/*
* parse up to requested fields, calling set_field() for each,
* saving in parse_extent the point where the parse left off
*/
if (parse_high_water == 0) /* starting at the beginning */
parse_extent = fields_arr[0]->stptr;
parse_high_water = (*parse_field)(requested, &parse_extent,
fields_arr[0]->stlen - (parse_extent-fields_arr[0]->stptr),
save_FS, FS_regexp, set_field, (NODE *)NULL);
/*
* if we reached the end of the record, set NF to the number of
* fields so far. Note that requested might actually refer to
* a field that is beyond the end of the record, but we won't
* set NF to that value at this point, since this is only a
* reference to the field and NF only gets set if the field
* is assigned to -- this case is handled below
*/
if (parse_extent == fields_arr[0]->stptr + fields_arr[0]->stlen)
NF = parse_high_water;
if (requested == HUGE-1) /* HUGE-1 means set NF */
requested = parse_high_water;
}
if (parse_high_water < requested) { /* requested beyond end of record */
if (assign) { /* expand record */
register int i;
if (requested > nf_high_water)
grow_fields_arr(requested);
/* fill in fields that don't exist */
for (i = parse_high_water + 1; i <= requested; i++)
fields_arr[i] = Nnull_string;
NF = requested;
parse_high_water = requested;
} else
return &Nnull_string;
}
return &fields_arr[requested];
}
static void
set_element(num, s, len, n)
int num;
char *s;
int len;
NODE *n;
{
register NODE *it;
it = make_string(s, len);
it->flags |= MAYBE_NUM;
*assoc_lookup(n, tmp_number((AWKNUM) (num))) = it;
}
NODE *
do_split(tree)
NODE *tree;
{
NODE *t1, *t2, *t3, *tmp;
NODE *fs;
char *s;
long (*parseit)P((int, char **, int, NODE *,
Regexp *, Setfunc, NODE *));
Regexp *rp = NULL;
/*
* do dupnode(), to avoid problems like
* x = split(a[1], a, "blah")
* since we assoc_clear the array. gack.
* this also gives up complete call by value semantics.
*/
tmp = tree_eval(tree->lnode);
t1 = dupnode(tmp);
free_temp(tmp);
t2 = tree->rnode->lnode;
t3 = tree->rnode->rnode->lnode;
(void) force_string(t1);
if (t2->type == Node_param_list)
t2 = stack_ptr[t2->param_cnt];
if (t2->type != Node_var && t2->type != Node_var_array)
fatal("second argument of split is not a variable");
assoc_clear(t2);
if (t3->re_flags & FS_DFLT) {
parseit = parse_field;
fs = force_string(FS_node->var_value);
rp = FS_regexp;
} else {
tmp = force_string(tree_eval(t3->re_exp));
if (tmp->stlen == 1) {
if (tmp->stptr[0] == ' ')
parseit = def_parse_field;
else
parseit = sc_parse_field;
} else {
parseit = re_parse_field;
rp = re_update(t3);
}
fs = tmp;
}
s = t1->stptr;
tmp = tmp_number((AWKNUM) (*parseit)(HUGE, &s, (int)t1->stlen,
fs, rp, set_element, t2));
unref(t1);
free_temp(t3);
return tmp;
}
void
set_FS()
{
char buf[10];
NODE *fs;
/*
* If changing the way fields are split, obey least-suprise
* semantics, and force $0 to be split totally.
*/
if (fields_arr != NULL)
(void) get_field(HUGE - 1, 0);
buf[0] = '\0';
default_FS = 0;
if (FS_regexp) {
refree(FS_regexp);
FS_regexp = NULL;
}
fs = force_string(FS_node->var_value);
if (fs->stlen > 1)
parse_field = re_parse_field;
else if (*RS == 0) {
parse_field = sc_parse_field;
if (fs->stlen == 1) {
if (fs->stptr[0] == ' ') {
default_FS = 1;
strcpy(buf, "[ \t\n]+");
} else if (fs->stptr[0] != '\n')
sprintf(buf, "[%c\n]", fs->stptr[0]);
}
} else {
parse_field = def_parse_field;
if (fs->stptr[0] == ' ' && fs->stlen == 1)
default_FS = 1;
else if (fs->stptr[0] != ' ' && fs->stlen == 1) {
if (IGNORECASE == 0)
parse_field = sc_parse_field;
else if (fs->stptr[0] == '\\')
/* yet another special case */
strcpy(buf, "[\\\\]");
else
sprintf(buf, "[%c]", fs->stptr[0]);
}
}
if (buf[0]) {
FS_regexp = make_regexp(buf, strlen(buf), IGNORECASE, 1);
parse_field = re_parse_field;
} else if (parse_field == re_parse_field) {
FS_regexp = make_regexp(fs->stptr, fs->stlen, IGNORECASE, 1);
} else
FS_regexp = NULL;
resave_fs = 1;
}
void
set_RS()
{
(void) force_string(RS_node->var_value);
RS = RS_node->var_value->stptr;
set_FS();
}
void
set_FIELDWIDTHS()
{
register char *scan;
char *end;
register int i;
static int fw_alloc = 1;
static int warned = 0;
extern double strtod();
if (do_lint && ! warned) {
warned = 1;
warning("use of FIELDWIDTHS is a gawk extension");
}
if (do_unix) /* quick and dirty, does the trick */
return;
/*
* If changing the way fields are split, obey least-suprise
* semantics, and force $0 to be split totally.
*/
if (fields_arr != NULL)
(void) get_field(HUGE - 1, 0);
parse_field = fw_parse_field;
scan = force_string(FIELDWIDTHS_node->var_value)->stptr;
end = scan + 1;
if (FIELDWIDTHS == NULL)
emalloc(FIELDWIDTHS, int *, fw_alloc * sizeof(int), "set_FIELDWIDTHS");
FIELDWIDTHS[0] = 0;
for (i = 1; ; i++) {
if (i >= fw_alloc) {
fw_alloc *= 2;
erealloc(FIELDWIDTHS, int *, fw_alloc * sizeof(int), "set_FIELDWIDTHS");
}
FIELDWIDTHS[i] = (int) strtod(scan, &end);
if (end == scan)
break;
scan = end;
}
FIELDWIDTHS[i] = -1;
}

View file

@ -1,757 +0,0 @@
/* Getopt for GNU.
NOTE: getopt is now part of the C library, so if you don't know what
"Keep this file name-space clean" means, talk to roland@gnu.ai.mit.edu
before changing it!
Copyright (C) 1987, 88, 89, 90, 91, 92, 93, 1994
Free Software Foundation, Inc.
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 2, 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, 675 Mass Ave, Cambridge, MA 02139, USA. */
#ifdef HAVE_CONFIG_H
#if defined (emacs) || defined (CONFIG_BROKETS)
/* We use <config.h> instead of "config.h" so that a compilation
using -I. -I$srcdir will use ./config.h rather than $srcdir/config.h
(which it would do because it found this file in $srcdir). */
#include <config.h>
#else
#include "config.h"
#endif
#endif
#ifndef __STDC__
/* This is a separate conditional since some stdc systems
reject `defined (const)'. */
#ifndef const
#define const
#endif
#endif
/* This tells Alpha OSF/1 not to define a getopt prototype in <stdio.h>. */
#ifndef _NO_PROTO
#define _NO_PROTO
#endif
#include <stdio.h>
/* Comment out all this code if we are using the GNU C Library, and are not
actually compiling the library itself. This code is part of the GNU C
Library, but also included in many other GNU distributions. Compiling
and linking in this code is a waste when using the GNU C library
(especially if it is a shared library). Rather than having every GNU
program understand `configure --with-gnu-libc' and omit the object files,
it is simpler to just do this in the source for each such file. */
#if defined (_LIBC) || !defined (__GNU_LIBRARY__)
/* This needs to come after some library #include
to get __GNU_LIBRARY__ defined. */
#if defined(__GNU_LIBRARY__) || defined(STDC_HEADERS)
/* Don't include stdlib.h for non-GNU C libraries because some of them
contain conflicting prototypes for getopt. */
#include <stdlib.h>
#else
extern char *getenv ();
#endif /* __GNU_LIBRARY || STDC_HEADERS */
/* If GETOPT_COMPAT is defined, `+' as well as `--' can introduce a
long-named option. Because this is not POSIX.2 compliant, it is
being phased out. */
/* #define GETOPT_COMPAT */
/* This version of `getopt' appears to the caller like standard Unix `getopt'
but it behaves differently for the user, since it allows the user
to intersperse the options with the other arguments.
As `getopt' works, it permutes the elements of ARGV so that,
when it is done, all the options precede everything else. Thus
all application programs are extended to handle flexible argument order.
Setting the environment variable POSIXLY_CORRECT disables permutation.
Then the behavior is completely standard.
GNU application programs can use a third alternative mode in which
they can distinguish the relative order of options and other arguments. */
#include "getopt.h"
/* For communication from `getopt' to the caller.
When `getopt' finds an option that takes an argument,
the argument value is returned here.
Also, when `ordering' is RETURN_IN_ORDER,
each non-option ARGV-element is returned here. */
char *optarg = 0;
/* Index in ARGV of the next element to be scanned.
This is used for communication to and from the caller
and for communication between successive calls to `getopt'.
On entry to `getopt', zero means this is the first call; initialize.
When `getopt' returns EOF, this is the index of the first of the
non-option elements that the caller should itself scan.
Otherwise, `optind' communicates from one call to the next
how much of ARGV has been scanned so far. */
/* XXX 1003.2 says this must be 1 before any call. */
int optind = 0;
/* The next char to be scanned in the option-element
in which the last option character we returned was found.
This allows us to pick up the scan where we left off.
If this is zero, or a null string, it means resume the scan
by advancing to the next ARGV-element. */
static char *nextchar;
/* Callers store zero here to inhibit the error message
for unrecognized options. */
int opterr = 1;
/* Set to an option character which was unrecognized.
This must be initialized on some systems to avoid linking in the
system's own getopt implementation. */
int optopt = '?';
/* Describe how to deal with options that follow non-option ARGV-elements.
If the caller did not specify anything,
the default is REQUIRE_ORDER if the environment variable
POSIXLY_CORRECT is defined, PERMUTE otherwise.
REQUIRE_ORDER means don't recognize them as options;
stop option processing when the first non-option is seen.
This is what Unix does.
This mode of operation is selected by either setting the environment
variable POSIXLY_CORRECT, or using `+' as the first character
of the list of option characters.
PERMUTE is the default. We permute the contents of ARGV as we scan,
so that eventually all the non-options are at the end. This allows options
to be given in any order, even with programs that were not written to
expect this.
RETURN_IN_ORDER is an option available to programs that were written
to expect options and other ARGV-elements in any order and that care about
the ordering of the two. We describe each non-option ARGV-element
as if it were the argument of an option with character code 1.
Using `-' as the first character of the list of option characters
selects this mode of operation.
The special argument `--' forces an end of option-scanning regardless
of the value of `ordering'. In the case of RETURN_IN_ORDER, only
`--' can cause `getopt' to return EOF with `optind' != ARGC. */
static enum
{
REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER
} ordering;
#if defined(__GNU_LIBRARY__) || defined(STDC_HEADERS)
/* We want to avoid inclusion of string.h with non-GNU libraries
because there are many ways it can cause trouble.
On some systems, it contains special magic macros that don't work
in GCC. */
#include <string.h>
#define my_index strchr
#else
/* Avoid depending on library functions or files
whose names are inconsistent. */
static char *
my_index (str, chr)
const char *str;
int chr;
{
while (*str)
{
if (*str == chr)
return (char *) str;
str++;
}
return 0;
}
/* If using GCC, we can safely declare strlen this way.
If not using GCC, it is ok not to declare it.
(Supposedly there are some machines where it might get a warning,
but changing this conditional to __STDC__ is too risky.) */
#ifdef __GNUC__
#ifdef IN_GCC
#include "gstddef.h"
#else
#include <stddef.h>
#endif
extern size_t strlen (const char *);
#endif
#endif /* __GNU_LIBRARY__ || STDC_HEADERS */
/* Handle permutation of arguments. */
/* Describe the part of ARGV that contains non-options that have
been skipped. `first_nonopt' is the index in ARGV of the first of them;
`last_nonopt' is the index after the last of them. */
static int first_nonopt;
static int last_nonopt;
/* Exchange two adjacent subsequences of ARGV.
One subsequence is elements [first_nonopt,last_nonopt)
which contains all the non-options that have been skipped so far.
The other is elements [last_nonopt,optind), which contains all
the options processed since those non-options were skipped.
`first_nonopt' and `last_nonopt' are relocated so that they describe
the new indices of the non-options in ARGV after they are moved. */
static void
exchange (argv)
char **argv;
{
int bottom = first_nonopt;
int middle = last_nonopt;
int top = optind;
char *tem;
/* Exchange the shorter segment with the far end of the longer segment.
That puts the shorter segment into the right place.
It leaves the longer segment in the right place overall,
but it consists of two parts that need to be swapped next. */
while (top > middle && middle > bottom)
{
if (top - middle > middle - bottom)
{
/* Bottom segment is the short one. */
int len = middle - bottom;
register int i;
/* Swap it with the top part of the top segment. */
for (i = 0; i < len; i++)
{
tem = argv[bottom + i];
argv[bottom + i] = argv[top - (middle - bottom) + i];
argv[top - (middle - bottom) + i] = tem;
}
/* Exclude the moved bottom segment from further swapping. */
top -= len;
}
else
{
/* Top segment is the short one. */
int len = top - middle;
register int i;
/* Swap it with the bottom part of the bottom segment. */
for (i = 0; i < len; i++)
{
tem = argv[bottom + i];
argv[bottom + i] = argv[middle + i];
argv[middle + i] = tem;
}
/* Exclude the moved top segment from further swapping. */
bottom += len;
}
}
/* Update records for the slots the non-options now occupy. */
first_nonopt += (optind - last_nonopt);
last_nonopt = optind;
}
/* Scan elements of ARGV (whose length is ARGC) for option characters
given in OPTSTRING.
If an element of ARGV starts with '-', and is not exactly "-" or "--",
then it is an option element. The characters of this element
(aside from the initial '-') are option characters. If `getopt'
is called repeatedly, it returns successively each of the option characters
from each of the option elements.
If `getopt' finds another option character, it returns that character,
updating `optind' and `nextchar' so that the next call to `getopt' can
resume the scan with the following option character or ARGV-element.
If there are no more option characters, `getopt' returns `EOF'.
Then `optind' is the index in ARGV of the first ARGV-element
that is not an option. (The ARGV-elements have been permuted
so that those that are not options now come last.)
OPTSTRING is a string containing the legitimate option characters.
If an option character is seen that is not listed in OPTSTRING,
return '?' after printing an error message. If you set `opterr' to
zero, the error message is suppressed but we still return '?'.
If a char in OPTSTRING is followed by a colon, that means it wants an arg,
so the following text in the same ARGV-element, or the text of the following
ARGV-element, is returned in `optarg'. Two colons mean an option that
wants an optional arg; if there is text in the current ARGV-element,
it is returned in `optarg', otherwise `optarg' is set to zero.
If OPTSTRING starts with `-' or `+', it requests different methods of
handling the non-option ARGV-elements.
See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above.
Long-named options begin with `--' instead of `-'.
Their names may be abbreviated as long as the abbreviation is unique
or is an exact match for some defined option. If they have an
argument, it follows the option name in the same ARGV-element, separated
from the option name by a `=', or else the in next ARGV-element.
When `getopt' finds a long-named option, it returns 0 if that option's
`flag' field is nonzero, the value of the option's `val' field
if the `flag' field is zero.
The elements of ARGV aren't really const, because we permute them.
But we pretend they're const in the prototype to be compatible
with other systems.
LONGOPTS is a vector of `struct option' terminated by an
element containing a name which is zero.
LONGIND returns the index in LONGOPT of the long-named option found.
It is only valid when a long-named option has been found by the most
recent call.
If LONG_ONLY is nonzero, '-' as well as '--' can introduce
long-named options. */
int
_getopt_internal (argc, argv, optstring, longopts, longind, long_only)
int argc;
char *const *argv;
const char *optstring;
const struct option *longopts;
int *longind;
int long_only;
{
int option_index;
optarg = 0;
/* Initialize the internal data when the first call is made.
Start processing options with ARGV-element 1 (since ARGV-element 0
is the program name); the sequence of previously skipped
non-option ARGV-elements is empty. */
if (optind == 0)
{
first_nonopt = last_nonopt = optind = 1;
nextchar = NULL;
/* Determine how to handle the ordering of options and nonoptions. */
if (optstring[0] == '-')
{
ordering = RETURN_IN_ORDER;
++optstring;
}
else if (optstring[0] == '+')
{
ordering = REQUIRE_ORDER;
++optstring;
}
else if (getenv ("POSIXLY_CORRECT") != NULL)
ordering = REQUIRE_ORDER;
else
ordering = PERMUTE;
}
if (nextchar == NULL || *nextchar == '\0')
{
if (ordering == PERMUTE)
{
/* If we have just processed some options following some non-options,
exchange them so that the options come first. */
if (first_nonopt != last_nonopt && last_nonopt != optind)
exchange ((char **) argv);
else if (last_nonopt != optind)
first_nonopt = optind;
/* Now skip any additional non-options
and extend the range of non-options previously skipped. */
while (optind < argc
&& (argv[optind][0] != '-' || argv[optind][1] == '\0')
#ifdef GETOPT_COMPAT
&& (longopts == NULL
|| argv[optind][0] != '+' || argv[optind][1] == '\0')
#endif /* GETOPT_COMPAT */
)
optind++;
last_nonopt = optind;
}
/* Special ARGV-element `--' means premature end of options.
Skip it like a null option,
then exchange with previous non-options as if it were an option,
then skip everything else like a non-option. */
if (optind != argc && !strcmp (argv[optind], "--"))
{
optind++;
if (first_nonopt != last_nonopt && last_nonopt != optind)
exchange ((char **) argv);
else if (first_nonopt == last_nonopt)
first_nonopt = optind;
last_nonopt = argc;
optind = argc;
}
/* If we have done all the ARGV-elements, stop the scan
and back over any non-options that we skipped and permuted. */
if (optind == argc)
{
/* Set the next-arg-index to point at the non-options
that we previously skipped, so the caller will digest them. */
if (first_nonopt != last_nonopt)
optind = first_nonopt;
return EOF;
}
/* If we have come to a non-option and did not permute it,
either stop the scan or describe it to the caller and pass it by. */
if ((argv[optind][0] != '-' || argv[optind][1] == '\0')
#ifdef GETOPT_COMPAT
&& (longopts == NULL
|| argv[optind][0] != '+' || argv[optind][1] == '\0')
#endif /* GETOPT_COMPAT */
)
{
if (ordering == REQUIRE_ORDER)
return EOF;
optarg = argv[optind++];
return 1;
}
/* We have found another option-ARGV-element.
Start decoding its characters. */
nextchar = (argv[optind] + 1
+ (longopts != NULL && argv[optind][1] == '-'));
}
if (longopts != NULL
&& ((argv[optind][0] == '-'
&& (argv[optind][1] == '-' || long_only))
#ifdef GETOPT_COMPAT
|| argv[optind][0] == '+'
#endif /* GETOPT_COMPAT */
))
{
const struct option *p;
char *s = nextchar;
int exact = 0;
int ambig = 0;
const struct option *pfound = NULL;
int indfound;
while (*s && *s != '=')
s++;
/* Test all options for either exact match or abbreviated matches. */
for (p = longopts, option_index = 0; p->name;
p++, option_index++)
if (!strncmp (p->name, nextchar, s - nextchar))
{
if (s - nextchar == strlen (p->name))
{
/* Exact match found. */
pfound = p;
indfound = option_index;
exact = 1;
break;
}
else if (pfound == NULL)
{
/* First nonexact match found. */
pfound = p;
indfound = option_index;
}
else
/* Second nonexact match found. */
ambig = 1;
}
if (ambig && !exact)
{
if (opterr)
fprintf (stderr, "%s: option `%s' is ambiguous\n",
argv[0], argv[optind]);
nextchar += strlen (nextchar);
optind++;
return '?';
}
if (pfound != NULL)
{
option_index = indfound;
optind++;
if (*s)
{
/* Don't test has_arg with >, because some C compilers don't
allow it to be used on enums. */
if (pfound->has_arg)
optarg = s + 1;
else
{
if (opterr)
{
if (argv[optind - 1][1] == '-')
/* --option */
fprintf (stderr,
"%s: option `--%s' doesn't allow an argument\n",
argv[0], pfound->name);
else
/* +option or -option */
fprintf (stderr,
"%s: option `%c%s' doesn't allow an argument\n",
argv[0], argv[optind - 1][0], pfound->name);
}
nextchar += strlen (nextchar);
return '?';
}
}
else if (pfound->has_arg == 1)
{
if (optind < argc)
optarg = argv[optind++];
else
{
if (opterr)
fprintf (stderr, "%s: option `%s' requires an argument\n",
argv[0], argv[optind - 1]);
nextchar += strlen (nextchar);
return optstring[0] == ':' ? ':' : '?';
}
}
nextchar += strlen (nextchar);
if (longind != NULL)
*longind = option_index;
if (pfound->flag)
{
*(pfound->flag) = pfound->val;
return 0;
}
return pfound->val;
}
/* Can't find it as a long option. If this is not getopt_long_only,
or the option starts with '--' or is not a valid short
option, then it's an error.
Otherwise interpret it as a short option. */
if (!long_only || argv[optind][1] == '-'
#ifdef GETOPT_COMPAT
|| argv[optind][0] == '+'
#endif /* GETOPT_COMPAT */
|| my_index (optstring, *nextchar) == NULL)
{
if (opterr)
{
if (argv[optind][1] == '-')
/* --option */
fprintf (stderr, "%s: unrecognized option `--%s'\n",
argv[0], nextchar);
else
/* +option or -option */
fprintf (stderr, "%s: unrecognized option `%c%s'\n",
argv[0], argv[optind][0], nextchar);
}
nextchar = (char *) "";
optind++;
return '?';
}
}
/* Look at and handle the next option-character. */
{
char c = *nextchar++;
char *temp = my_index (optstring, c);
/* Increment `optind' when we start to process its last character. */
if (*nextchar == '\0')
++optind;
if (temp == NULL || c == ':')
{
if (opterr)
{
#if 0
if (c < 040 || c >= 0177)
fprintf (stderr, "%s: unrecognized option, character code 0%o\n",
argv[0], c);
else
fprintf (stderr, "%s: unrecognized option `-%c'\n", argv[0], c);
#else
/* 1003.2 specifies the format of this message. */
fprintf (stderr, "%s: illegal option -- %c\n", argv[0], c);
#endif
}
optopt = c;
return '?';
}
if (temp[1] == ':')
{
if (temp[2] == ':')
{
/* This is an option that accepts an argument optionally. */
if (*nextchar != '\0')
{
optarg = nextchar;
optind++;
}
else
optarg = 0;
nextchar = NULL;
}
else
{
/* This is an option that requires an argument. */
if (*nextchar != '\0')
{
optarg = nextchar;
/* If we end this ARGV-element by taking the rest as an arg,
we must advance to the next element now. */
optind++;
}
else if (optind == argc)
{
if (opterr)
{
#if 0
fprintf (stderr, "%s: option `-%c' requires an argument\n",
argv[0], c);
#else
/* 1003.2 specifies the format of this message. */
fprintf (stderr, "%s: option requires an argument -- %c\n",
argv[0], c);
#endif
}
optopt = c;
if (optstring[0] == ':')
c = ':';
else
c = '?';
}
else
/* We already incremented `optind' once;
increment it again when taking next ARGV-elt as argument. */
optarg = argv[optind++];
nextchar = NULL;
}
}
return c;
}
}
int
getopt (argc, argv, optstring)
int argc;
char *const *argv;
const char *optstring;
{
return _getopt_internal (argc, argv, optstring,
(const struct option *) 0,
(int *) 0,
0);
}
#endif /* _LIBC or not __GNU_LIBRARY__. */
#ifdef TEST
/* Compile with -DTEST to make an executable for use in testing
the above definition of `getopt'. */
int
main (argc, argv)
int argc;
char **argv;
{
int c;
int digit_optind = 0;
while (1)
{
int this_option_optind = optind ? optind : 1;
c = getopt (argc, argv, "abc:d:0123456789");
if (c == EOF)
break;
switch (c)
{
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
if (digit_optind != 0 && digit_optind != this_option_optind)
printf ("digits occur in two different argv-elements.\n");
digit_optind = this_option_optind;
printf ("option %c\n", c);
break;
case 'a':
printf ("option a\n");
break;
case 'b':
printf ("option b\n");
break;
case 'c':
printf ("option c with value `%s'\n", optarg);
break;
case '?':
break;
default:
printf ("?? getopt returned character code 0%o ??\n", c);
}
}
if (optind < argc)
{
printf ("non-option ARGV-elements: ");
while (optind < argc)
printf ("%s ", argv[optind++]);
printf ("\n");
}
exit (0);
}
#endif /* TEST */

View file

@ -1,129 +0,0 @@
/* Declarations for getopt.
Copyright (C) 1989, 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
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 2, 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, 675 Mass Ave, Cambridge, MA 02139, USA. */
#ifndef _GETOPT_H
#define _GETOPT_H 1
#ifdef __cplusplus
extern "C" {
#endif
/* For communication from `getopt' to the caller.
When `getopt' finds an option that takes an argument,
the argument value is returned here.
Also, when `ordering' is RETURN_IN_ORDER,
each non-option ARGV-element is returned here. */
extern char *optarg;
/* Index in ARGV of the next element to be scanned.
This is used for communication to and from the caller
and for communication between successive calls to `getopt'.
On entry to `getopt', zero means this is the first call; initialize.
When `getopt' returns EOF, this is the index of the first of the
non-option elements that the caller should itself scan.
Otherwise, `optind' communicates from one call to the next
how much of ARGV has been scanned so far. */
extern int optind;
/* Callers store zero here to inhibit the error message `getopt' prints
for unrecognized options. */
extern int opterr;
/* Set to an option character which was unrecognized. */
extern int optopt;
/* Describe the long-named options requested by the application.
The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector
of `struct option' terminated by an element containing a name which is
zero.
The field `has_arg' is:
no_argument (or 0) if the option does not take an argument,
required_argument (or 1) if the option requires an argument,
optional_argument (or 2) if the option takes an optional argument.
If the field `flag' is not NULL, it points to a variable that is set
to the value given in the field `val' when the option is found, but
left unchanged if the option is not found.
To have a long-named option do something other than set an `int' to
a compiled-in constant, such as set a value from `optarg', set the
option's `flag' field to zero and its `val' field to a nonzero
value (the equivalent single-letter option character, if there is
one). For long options that have a zero `flag' field, `getopt'
returns the contents of the `val' field. */
struct option
{
#ifdef __STDC__
const char *name;
#else
char *name;
#endif
/* has_arg can't be an enum because some compilers complain about
type mismatches in all the code that assumes it is an int. */
int has_arg;
int *flag;
int val;
};
/* Names for the values of the `has_arg' field of `struct option'. */
#define no_argument 0
#define required_argument 1
#define optional_argument 2
#ifdef __STDC__
#if defined(__GNU_LIBRARY__)
/* Many other libraries have conflicting prototypes for getopt, with
differences in the consts, in stdlib.h. To avoid compilation
errors, only prototype getopt for the GNU C library. */
extern int getopt (int argc, char *const *argv, const char *shortopts);
#else /* not __GNU_LIBRARY__ */
extern int getopt ();
#endif /* not __GNU_LIBRARY__ */
extern int getopt_long (int argc, char *const *argv, const char *shortopts,
const struct option *longopts, int *longind);
extern int getopt_long_only (int argc, char *const *argv,
const char *shortopts,
const struct option *longopts, int *longind);
/* Internal only. Users should not call this directly. */
extern int _getopt_internal (int argc, char *const *argv,
const char *shortopts,
const struct option *longopts, int *longind,
int long_only);
#else /* not __STDC__ */
extern int getopt ();
extern int getopt_long ();
extern int getopt_long_only ();
extern int _getopt_internal ();
#endif /* not __STDC__ */
#ifdef __cplusplus
}
#endif
#endif /* _GETOPT_H */

View file

@ -1,187 +0,0 @@
/* getopt_long and getopt_long_only entry points for GNU getopt.
Copyright (C) 1987, 88, 89, 90, 91, 92, 1993
Free Software Foundation, Inc.
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 2, 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, 675 Mass Ave, Cambridge, MA 02139, USA. */
#ifdef HAVE_CONFIG_H
#if defined (emacs) || defined (CONFIG_BROKETS)
/* We use <config.h> instead of "config.h" so that a compilation
using -I. -I$srcdir will use ./config.h rather than $srcdir/config.h
(which it would do because it found this file in $srcdir). */
#include <config.h>
#else
#include "config.h"
#endif
#endif
#include "getopt.h"
#ifndef __STDC__
/* This is a separate conditional since some stdc systems
reject `defined (const)'. */
#ifndef const
#define const
#endif
#endif
#include <stdio.h>
/* Comment out all this code if we are using the GNU C Library, and are not
actually compiling the library itself. This code is part of the GNU C
Library, but also included in many other GNU distributions. Compiling
and linking in this code is a waste when using the GNU C library
(especially if it is a shared library). Rather than having every GNU
program understand `configure --with-gnu-libc' and omit the object files,
it is simpler to just do this in the source for each such file. */
#if defined (_LIBC) || !defined (__GNU_LIBRARY__)
/* This needs to come after some library #include
to get __GNU_LIBRARY__ defined. */
#if defined(__GNU_LIBRARY__) || defined(OS2) || defined(MSDOS) || defined(atarist)
#include <stdlib.h>
#else
char *getenv ();
#endif
#ifndef NULL
#define NULL 0
#endif
int
getopt_long (argc, argv, options, long_options, opt_index)
int argc;
char *const *argv;
const char *options;
const struct option *long_options;
int *opt_index;
{
return _getopt_internal (argc, argv, options, long_options, opt_index, 0);
}
/* Like getopt_long, but '-' as well as '--' can indicate a long option.
If an option that starts with '-' (not '--') doesn't match a long option,
but does match a short option, it is parsed as a short option
instead. */
int
getopt_long_only (argc, argv, options, long_options, opt_index)
int argc;
char *const *argv;
const char *options;
const struct option *long_options;
int *opt_index;
{
return _getopt_internal (argc, argv, options, long_options, opt_index, 1);
}
#endif /* _LIBC or not __GNU_LIBRARY__. */
#ifdef TEST
#include <stdio.h>
int
main (argc, argv)
int argc;
char **argv;
{
int c;
int digit_optind = 0;
while (1)
{
int this_option_optind = optind ? optind : 1;
int option_index = 0;
static struct option long_options[] =
{
{"add", 1, 0, 0},
{"append", 0, 0, 0},
{"delete", 1, 0, 0},
{"verbose", 0, 0, 0},
{"create", 0, 0, 0},
{"file", 1, 0, 0},
{0, 0, 0, 0}
};
c = getopt_long (argc, argv, "abc:d:0123456789",
long_options, &option_index);
if (c == EOF)
break;
switch (c)
{
case 0:
printf ("option %s", long_options[option_index].name);
if (optarg)
printf (" with arg %s", optarg);
printf ("\n");
break;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
if (digit_optind != 0 && digit_optind != this_option_optind)
printf ("digits occur in two different argv-elements.\n");
digit_optind = this_option_optind;
printf ("option %c\n", c);
break;
case 'a':
printf ("option a\n");
break;
case 'b':
printf ("option b\n");
break;
case 'c':
printf ("option c with value `%s'\n", optarg);
break;
case 'd':
printf ("option d with value `%s'\n", optarg);
break;
case '?':
break;
default:
printf ("?? getopt returned character code 0%o ??\n", c);
}
}
if (optind < argc)
{
printf ("non-option ARGV-elements: ");
while (optind < argc)
printf ("%s ", argv[optind++]);
printf ("\n");
}
exit (0);
}
#endif /* TEST */

File diff suppressed because it is too large Load diff

View file

@ -1,321 +0,0 @@
/*
* iop.c - do i/o related things.
*/
/*
* Copyright (C) 1986, 1988, 1989, 1991, 1992, 1993 the Free Software Foundation, Inc.
*
* This file is part of GAWK, the GNU implementation of the
* AWK Progamming Language.
*
* GAWK 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 2 of the License, or
* (at your option) any later version.
*
* GAWK 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 GAWK; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "awk.h"
#ifndef atarist
#define INVALID_HANDLE (-1)
#else
#include <stddef.h>
#include <fcntl.h>
#define INVALID_HANDLE (__SMALLEST_VALID_HANDLE - 1)
#endif /* atarist */
#ifdef TEST
int bufsize = 8192;
void
fatal(s)
char *s;
{
printf("%s\n", s);
exit(1);
}
#endif
int
optimal_bufsize(fd)
int fd;
{
struct stat stb;
#ifdef VMS
/*
* These values correspond with the RMS multi-block count used by
* vms_open() in vms/vms_misc.c.
*/
if (isatty(fd) > 0)
return BUFSIZ;
else if (fstat(fd, &stb) < 0)
return 8*512; /* conservative in case of DECnet access */
else
return 32*512;
#else
/*
* System V doesn't have the file system block size in the
* stat structure. So we have to make some sort of reasonable
* guess. We use stdio's BUFSIZ, since that is what it was
* meant for in the first place.
*/
#ifdef BLKSIZE_MISSING
#define DEFBLKSIZE BUFSIZ
#else
#define DEFBLKSIZE (stb.st_blksize ? stb.st_blksize : BUFSIZ)
#endif
#ifdef TEST
return bufsize;
#else
#ifndef atarist
if (isatty(fd))
#else
/*
* On ST redirected stdin does not have a name attached
* (this could be hard to do to) and fstat would fail
*/
if (0 == fd || isatty(fd))
#endif /*atarist */
return BUFSIZ;
#ifndef BLKSIZE_MISSING
/* VMS POSIX 1.0: st_blksize is never assigned a value, so zero it */
stb.st_blksize = 0;
#endif
if (fstat(fd, &stb) == -1)
fatal("can't stat fd %d (%s)", fd, strerror(errno));
if (lseek(fd, (off_t)0, 0) == -1)
return DEFBLKSIZE;
return ((int) (stb.st_size < DEFBLKSIZE ? stb.st_size : DEFBLKSIZE));
#endif /*! TEST */
#endif /*! VMS */
}
IOBUF *
iop_alloc(fd)
int fd;
{
IOBUF *iop;
if (fd == INVALID_HANDLE)
return NULL;
emalloc(iop, IOBUF *, sizeof(IOBUF), "iop_alloc");
iop->flag = 0;
if (isatty(fd))
iop->flag |= IOP_IS_TTY;
iop->size = optimal_bufsize(fd);
iop->secsiz = -2;
errno = 0;
iop->fd = fd;
iop->off = iop->buf = NULL;
iop->cnt = 0;
return iop;
}
/*
* Get the next record. Uses a "split buffer" where the latter part is
* the normal read buffer and the head part is an "overflow" area that is used
* when a record spans the end of the normal buffer, in which case the first
* part of the record is copied into the overflow area just before the
* normal buffer. Thus, the eventual full record can be returned as a
* contiguous area of memory with a minimum of copying. The overflow area
* is expanded as needed, so that records are unlimited in length.
* We also mark both the end of the buffer and the end of the read() with
* a sentinel character (the current record separator) so that the inside
* loop can run as a single test.
*/
int
get_a_record(out, iop, grRS, errcode)
char **out;
IOBUF *iop;
register int grRS;
int *errcode;
{
register char *bp = iop->off;
char *bufend;
char *start = iop->off; /* beginning of record */
char rs;
int saw_newline = 0, eat_whitespace = 0; /* used iff grRS==0 */
if (iop->cnt == EOF) { /* previous read hit EOF */
*out = NULL;
return EOF;
}
if (grRS == 0) { /* special case: grRS == "" */
rs = '\n';
} else
rs = (char) grRS;
/* set up sentinel */
if (iop->buf) {
bufend = iop->buf + iop->size + iop->secsiz;
*bufend = rs;
} else
bufend = NULL;
for (;;) { /* break on end of record, read error or EOF */
/* Following code is entered on the first call of this routine
* for a new iop, or when we scan to the end of the buffer.
* In the latter case, we copy the current partial record to
* the space preceding the normal read buffer. If necessary,
* we expand this space. This is done so that we can return
* the record as a contiguous area of memory.
*/
if ((iop->flag & IOP_IS_INTERNAL) == 0 && bp >= bufend) {
char *oldbuf = NULL;
char *oldsplit = iop->buf + iop->secsiz;
long len; /* record length so far */
len = bp - start;
if (len > iop->secsiz) {
/* expand secondary buffer */
if (iop->secsiz == -2)
iop->secsiz = 256;
while (len > iop->secsiz)
iop->secsiz *= 2;
oldbuf = iop->buf;
emalloc(iop->buf, char *,
iop->size+iop->secsiz+2, "get_a_record");
bufend = iop->buf + iop->size + iop->secsiz;
*bufend = rs;
}
if (len > 0) {
char *newsplit = iop->buf + iop->secsiz;
if (start < oldsplit) {
memcpy(newsplit - len, start,
oldsplit - start);
memcpy(newsplit - (bp - oldsplit),
oldsplit, bp - oldsplit);
} else
memcpy(newsplit - len, start, len);
}
bp = iop->end = iop->off = iop->buf + iop->secsiz;
start = bp - len;
if (oldbuf) {
free(oldbuf);
oldbuf = NULL;
}
}
/* Following code is entered whenever we have no more data to
* scan. In most cases this will read into the beginning of
* the main buffer, but in some cases (terminal, pipe etc.)
* we may be doing smallish reads into more advanced positions.
*/
if (bp >= iop->end) {
if ((iop->flag & IOP_IS_INTERNAL) != 0) {
iop->cnt = EOF;
break;
}
iop->cnt = read(iop->fd, iop->end, bufend - iop->end);
if (iop->cnt == -1) {
if (! do_unix && errcode != NULL) {
*errcode = errno;
iop->cnt = EOF;
break;
} else
fatal("error reading input: %s",
strerror(errno));
} else if (iop->cnt == 0) {
iop->cnt = EOF;
break;
}
iop->end += iop->cnt;
*iop->end = rs;
}
if (grRS == 0) {
extern int default_FS;
if (default_FS && (bp == start || eat_whitespace)) {
while (bp < iop->end
&& (*bp == ' ' || *bp == '\t' || *bp == '\n'))
bp++;
if (bp == iop->end) {
eat_whitespace = 1;
continue;
} else
eat_whitespace = 0;
}
if (saw_newline && *bp == rs) {
bp++;
break;
}
saw_newline = 0;
}
while (*bp++ != rs)
;
if (bp <= iop->end) {
if (grRS == 0)
saw_newline = 1;
else
break;
} else
bp--;
if ((iop->flag & IOP_IS_INTERNAL) != 0)
iop->cnt = bp - start;
}
if (iop->cnt == EOF
&& (((iop->flag & IOP_IS_INTERNAL) != 0) || start == bp)) {
*out = NULL;
return EOF;
}
iop->off = bp;
bp--;
if (*bp != rs)
bp++;
*bp = '\0';
if (grRS == 0) {
/* there could be more newlines left, clean 'em out now */
while (*(iop->off) == rs && iop->off <= iop->end)
(iop->off)++;
if (*--bp == rs)
*bp = '\0';
else
bp++;
}
*out = start;
return bp - start;
}
#ifdef TEST
main(argc, argv)
int argc;
char *argv[];
{
IOBUF *iop;
char *out;
int cnt;
char rs[2];
rs[0] = 0;
if (argc > 1)
bufsize = atoi(argv[1]);
if (argc > 2)
rs[0] = *argv[2];
iop = iop_alloc(0);
while ((cnt = get_a_record(&out, iop, rs[0], NULL)) > 0) {
fwrite(out, 1, cnt, stdout);
fwrite(rs, 1, 1, stdout);
}
}
#endif

View file

@ -1,823 +0,0 @@
/*
* main.c -- Expression tree constructors and main program for gawk.
*/
/*
* Copyright (C) 1986, 1988, 1989, 1991, 1992, 1993 the Free Software Foundation, Inc.
*
* This file is part of GAWK, the GNU implementation of the
* AWK Progamming Language.
*
* GAWK 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 2 of the License, or
* (at your option) any later version.
*
* GAWK 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 GAWK; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifdef __FreeBSD__
#include <locale.h>
#endif
#include "getopt.h"
#include "awk.h"
#include "patchlevel.h"
static void usage P((int exitval));
static void copyleft P((void));
static void cmdline_fs P((char *str));
static void init_args P((int argc0, int argc, char *argv0, char **argv));
static void init_vars P((void));
static void pre_assign P((char *v));
SIGTYPE catchsig P((int sig, int code));
static void gawk_option P((char *optstr));
static void nostalgia P((void));
static void version P((void));
char *gawk_name P((char *filespec));
#ifdef MSDOS
extern int isatty P((int));
#endif
extern void resetup P((void));
/* These nodes store all the special variables AWK uses */
NODE *FS_node, *NF_node, *RS_node, *NR_node;
NODE *FILENAME_node, *OFS_node, *ORS_node, *OFMT_node;
NODE *CONVFMT_node;
NODE *ERRNO_node;
NODE *FNR_node, *RLENGTH_node, *RSTART_node, *SUBSEP_node;
NODE *ENVIRON_node, *IGNORECASE_node;
NODE *ARGC_node, *ARGV_node, *ARGIND_node;
NODE *FIELDWIDTHS_node;
long NF;
long NR;
long FNR;
int IGNORECASE;
char *RS;
char *OFS;
char *ORS;
char *OFMT;
char *CONVFMT;
/*
* The parse tree and field nodes are stored here. Parse_end is a dummy item
* used to free up unneeded fields without freeing the program being run
*/
int errcount = 0; /* error counter, used by yyerror() */
/* The global null string */
NODE *Nnull_string;
/* The name the program was invoked under, for error messages */
const char *myname;
/* A block of AWK code to be run before running the program */
NODE *begin_block = 0;
/* A block of AWK code to be run after the last input file */
NODE *end_block = 0;
int exiting = 0; /* Was an "exit" statement executed? */
int exit_val = 0; /* optional exit value */
#if defined(YYDEBUG) || defined(DEBUG)
extern int yydebug;
#endif
struct src *srcfiles = NULL; /* source file name(s) */
int numfiles = -1; /* how many source files */
int do_unix = 0; /* turn off gnu extensions */
int do_posix = 0; /* turn off gnu and unix extensions */
int do_lint = 0; /* provide warnings about questionable stuff */
int do_nostalgia = 0; /* provide a blast from the past */
int in_begin_rule = 0; /* we're in a BEGIN rule */
int in_end_rule = 0; /* we're in a END rule */
int output_is_tty = 0; /* control flushing of output */
extern char *version_string; /* current version, for printing */
NODE *expression_value;
static struct option optab[] = {
{ "compat", no_argument, & do_unix, 1 },
{ "lint", no_argument, & do_lint, 1 },
{ "posix", no_argument, & do_posix, 1 },
{ "nostalgia", no_argument, & do_nostalgia, 1 },
{ "copyleft", no_argument, NULL, 'C' },
{ "copyright", no_argument, NULL, 'C' },
{ "field-separator", required_argument, NULL, 'F' },
{ "file", required_argument, NULL, 'f' },
{ "assign", required_argument, NULL, 'v' },
{ "version", no_argument, NULL, 'V' },
{ "usage", no_argument, NULL, 'u' },
{ "help", no_argument, NULL, 'u' },
{ "source", required_argument, NULL, 's' },
#ifdef DEBUG
{ "parsedebug", no_argument, NULL, 'D' },
#endif
{ 0, 0, 0, 0 }
};
int
main(argc, argv)
int argc;
char **argv;
{
int c;
char *scan;
/* the + on the front tells GNU getopt not to rearrange argv */
const char *optlist = "+F:f:v:W:m:";
int stopped_early = 0;
int old_optind;
extern int optind;
extern int opterr;
extern char *optarg;
#ifdef __FreeBSD__
(void) setlocale(LC_ALL, "");
#endif
#ifdef __EMX__
_response(&argc, &argv);
_wildcard(&argc, &argv);
setvbuf(stdout, NULL, _IOLBF, BUFSIZ);
#endif
(void) signal(SIGFPE, (SIGTYPE (*) P((int))) catchsig);
(void) signal(SIGSEGV, (SIGTYPE (*) P((int))) catchsig);
#ifdef SIGBUS
(void) signal(SIGBUS, (SIGTYPE (*) P((int))) catchsig);
#endif
myname = gawk_name(argv[0]);
argv[0] = (char *)myname;
#ifdef VMS
vms_arg_fixup(&argc, &argv); /* emulate redirection, expand wildcards */
#endif
/* remove sccs gunk */
if (strncmp(version_string, "@(#)", 4) == 0)
version_string += 4;
if (argc < 2)
usage(1);
/* initialize the null string */
Nnull_string = make_string("", 0);
Nnull_string->numbr = 0.0;
Nnull_string->type = Node_val;
Nnull_string->flags = (PERM|STR|STRING|NUM|NUMBER);
/* Set up the special variables */
/*
* Note that this must be done BEFORE arg parsing else -F
* breaks horribly
*/
init_vars();
/* worst case */
emalloc(srcfiles, struct src *, argc * sizeof(struct src), "main");
memset(srcfiles, '\0', argc * sizeof(struct src));
/* Tell the regex routines how they should work. . . */
resetup();
#ifdef fpsetmask
fpsetmask(~0xff);
#endif
/* we do error messages ourselves on invalid options */
opterr = 0;
/* option processing. ready, set, go! */
for (optopt = 0, old_optind = 1;
(c = getopt_long(argc, argv, optlist, optab, NULL)) != EOF;
optopt = 0, old_optind = optind) {
if (do_posix)
opterr = 1;
switch (c) {
case 'F':
cmdline_fs(optarg);
break;
case 'f':
/*
* a la MKS awk, allow multiple -f options.
* this makes function libraries real easy.
* most of the magic is in the scanner.
*/
/* The following is to allow for whitespace at the end
* of a #! /bin/gawk line in an executable file
*/
scan = optarg;
while (isspace(*scan))
scan++;
++numfiles;
srcfiles[numfiles].stype = SOURCEFILE;
if (*scan == '\0')
srcfiles[numfiles].val = argv[optind++];
else
srcfiles[numfiles].val = optarg;
break;
case 'v':
pre_assign(optarg);
break;
case 'm':
/*
* Research awk extension.
* -mf=nnn set # fields, gawk ignores
* -mr=nnn set record length, ditto
*/
if (do_lint)
warning("-m[fr] option irrelevant");
if ((optarg[0] != 'r' && optarg[0] != 'f')
|| optarg[1] != '=')
warning("-m option usage: -m[fn]=nnn");
break;
case 'W': /* gawk specific options */
gawk_option(optarg);
break;
/* These can only come from long form options */
case 'V':
version();
break;
case 'C':
copyleft();
break;
case 'u':
usage(0);
break;
case 's':
if (optarg[0] == '\0')
warning("empty argument to --source ignored");
else {
srcfiles[++numfiles].stype = CMDLINE;
srcfiles[numfiles].val = optarg;
}
break;
#ifdef DEBUG
case 'D':
yydebug = 2;
break;
#endif
case 0:
/*
* getopt_long found an option that sets a variable
* instead of returning a letter. Do nothing, just
* cycle around for the next one.
*/
break;
case '?':
default:
/*
* New behavior. If not posix, an unrecognized
* option stops argument processing so that it can
* go into ARGV for the awk program to see. This
* makes use of ``#! /bin/gawk -f'' easier.
*
* However, it's never simple. If optopt is set,
* an option that requires an argument didn't get the
* argument. We care because if opterr is 0, then
* getopt_long won't print the error message for us.
*/
if (! do_posix
&& (optopt == 0 || strchr(optlist, optopt) == NULL)) {
/*
* can't just do optind--. In case of an
* option with >=2 letters, getopt_long
* won't have incremented optind.
*/
optind = old_optind;
stopped_early = 1;
goto out;
} else if (optopt)
/* Use 1003.2 required message format */
fprintf (stderr,
"%s: option requires an argument -- %c\n",
myname, optopt);
/* else
let getopt print error message for us */
break;
}
}
out:
if (do_nostalgia)
nostalgia();
/* check for POSIXLY_CORRECT environment variable */
if (! do_posix && getenv("POSIXLY_CORRECT") != NULL) {
do_posix = 1;
if (do_lint)
warning(
"environment variable `POSIXLY_CORRECT' set: turning on --posix");
}
/* POSIX compliance also implies no Unix extensions either */
if (do_posix)
do_unix = 1;
#ifdef DEBUG
setbuf(stdout, (char *) NULL); /* make debugging easier */
#endif
if (isatty(fileno(stdout)))
output_is_tty = 1;
/* No -f or --source options, use next arg */
if (numfiles == -1) {
if (optind > argc - 1 || stopped_early) /* no args left or no program */
usage(1);
srcfiles[++numfiles].stype = CMDLINE;
srcfiles[numfiles].val = argv[optind];
optind++;
}
init_args(optind, argc, (char *) myname, argv);
(void) tokexpand();
/* Read in the program */
if (yyparse() || errcount)
exit(1);
/* Set up the field variables */
init_fields();
if (do_lint && begin_block == NULL && expression_value == NULL
&& end_block == NULL)
warning("no program");
if (begin_block) {
in_begin_rule = 1;
(void) interpret(begin_block);
}
in_begin_rule = 0;
if (!exiting && (expression_value || end_block))
do_input();
if (end_block) {
in_end_rule = 1;
(void) interpret(end_block);
}
in_end_rule = 0;
if (close_io() != 0 && exit_val == 0)
exit_val = 1;
exit(exit_val); /* more portable */
return exit_val; /* to suppress warnings */
}
/* usage --- print usage information and exit */
static void
usage(exitval)
int exitval;
{
const char *opt1 = " -f progfile [--]";
#if defined(MSDOS) || defined(OS2) || defined(VMS)
const char *opt2 = " [--] \"program\"";
#else
const char *opt2 = " [--] 'program'";
#endif
const char *regops = " [POSIX or GNU style options]";
fprintf(stderr, "Usage:\t%s%s%s file ...\n\t%s%s%s file ...\n",
myname, regops, opt1, myname, regops, opt2);
/* GNU long options info. Gack. */
fputs("POSIX options:\t\tGNU long options:\n", stderr);
fputs("\t-f progfile\t\t--file=progfile\n", stderr);
fputs("\t-F fs\t\t\t--field-separator=fs\n", stderr);
fputs("\t-v var=val\t\t--assign=var=val\n", stderr);
fputs("\t-m[fr]=val\n", stderr);
fputs("\t-W compat\t\t--compat\n", stderr);
fputs("\t-W copyleft\t\t--copyleft\n", stderr);
fputs("\t-W copyright\t\t--copyright\n", stderr);
fputs("\t-W help\t\t\t--help\n", stderr);
fputs("\t-W lint\t\t\t--lint\n", stderr);
#ifdef NOSTALGIA
fputs("\t-W nostalgia\t\t--nostalgia\n", stderr);
#endif
#ifdef DEBUG
fputs("\t-W parsedebug\t\t--parsedebug\n", stderr);
#endif
fputs("\t-W posix\t\t--posix\n", stderr);
fputs("\t-W source=program-text\t--source=program-text\n", stderr);
fputs("\t-W usage\t\t--usage\n", stderr);
fputs("\t-W version\t\t--version\n", stderr);
exit(exitval);
}
static void
copyleft ()
{
static char blurb_part1[] =
"Copyright (C) 1989, 1991, 1992, Free Software Foundation.\n\
\n\
This program is free software; you can redistribute it and/or modify\n\
it under the terms of the GNU General Public License as published by\n\
the Free Software Foundation; either version 2 of the License, or\n\
(at your option) any later version.\n\
\n";
static char blurb_part2[] =
"This program is distributed in the hope that it will be useful,\n\
but WITHOUT ANY WARRANTY; without even the implied warranty of\n\
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n\
GNU General Public License for more details.\n\
\n";
static char blurb_part3[] =
"You should have received a copy of the GNU General Public License\n\
along with this program; if not, write to the Free Software\n\
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.\n";
fputs(blurb_part1, stderr);
fputs(blurb_part2, stderr);
fputs(blurb_part3, stderr);
fflush(stderr);
}
static void
cmdline_fs(str)
char *str;
{
register NODE **tmp;
/* int len = strlen(str); *//* don't do that - we want to
avoid mismatched types */
tmp = get_lhs(FS_node, (Func_ptr *) 0);
unref(*tmp);
/*
* Only if in full compatibility mode check for the stupid special
* case so -F\t works as documented in awk even though the shell
* hands us -Ft. Bleah!
*
* Thankfully, Posix didn't propogate this "feature".
*/
if (str[0] == 't' && str[1] == '\0') {
if (do_lint)
warning("-Ft does not set FS to tab in POSIX awk");
if (do_unix && ! do_posix)
str[0] = '\t';
}
*tmp = make_str_node(str, strlen(str), SCAN); /* do process escapes */
set_FS();
}
static void
init_args(argc0, argc, argv0, argv)
int argc0, argc;
char *argv0;
char **argv;
{
int i, j;
NODE **aptr;
ARGV_node = install("ARGV", node(Nnull_string, Node_var, (NODE *)NULL));
aptr = assoc_lookup(ARGV_node, tmp_number(0.0));
*aptr = make_string(argv0, strlen(argv0));
(*aptr)->flags |= MAYBE_NUM;
for (i = argc0, j = 1; i < argc; i++) {
aptr = assoc_lookup(ARGV_node, tmp_number((AWKNUM) j));
*aptr = make_string(argv[i], strlen(argv[i]));
(*aptr)->flags |= MAYBE_NUM;
j++;
}
ARGC_node = install("ARGC",
node(make_number((AWKNUM) j), Node_var, (NODE *) NULL));
}
/*
* Set all the special variables to their initial values.
*/
struct varinit {
NODE **spec;
const char *name;
NODETYPE type;
const char *strval;
AWKNUM numval;
Func_ptr assign;
};
static struct varinit varinit[] = {
{&NF_node, "NF", Node_NF, 0, -1, set_NF },
{&FIELDWIDTHS_node, "FIELDWIDTHS", Node_FIELDWIDTHS, "", 0, 0 },
{&NR_node, "NR", Node_NR, 0, 0, set_NR },
{&FNR_node, "FNR", Node_FNR, 0, 0, set_FNR },
{&FS_node, "FS", Node_FS, " ", 0, 0 },
{&RS_node, "RS", Node_RS, "\n", 0, set_RS },
{&IGNORECASE_node, "IGNORECASE", Node_IGNORECASE, 0, 0, set_IGNORECASE },
{&FILENAME_node, "FILENAME", Node_var, "", 0, 0 },
{&OFS_node, "OFS", Node_OFS, " ", 0, set_OFS },
{&ORS_node, "ORS", Node_ORS, "\n", 0, set_ORS },
{&OFMT_node, "OFMT", Node_OFMT, "%.6g", 0, set_OFMT },
{&CONVFMT_node, "CONVFMT", Node_CONVFMT, "%.6g", 0, set_CONVFMT },
{&RLENGTH_node, "RLENGTH", Node_var, 0, 0, 0 },
{&RSTART_node, "RSTART", Node_var, 0, 0, 0 },
{&SUBSEP_node, "SUBSEP", Node_var, "\034", 0, 0 },
{&ARGIND_node, "ARGIND", Node_var, 0, 0, 0 },
{&ERRNO_node, "ERRNO", Node_var, 0, 0, 0 },
{0, 0, Node_illegal, 0, 0, 0 },
};
static void
init_vars()
{
register struct varinit *vp;
for (vp = varinit; vp->name; vp++) {
*(vp->spec) = install((char *) vp->name,
node(vp->strval == 0 ? make_number(vp->numval)
: make_string((char *) vp->strval,
strlen(vp->strval)),
vp->type, (NODE *) NULL));
if (vp->assign)
(*(vp->assign))();
}
}
void
load_environ()
{
#if !defined(MSDOS) && !defined(OS2) && !(defined(VMS) && defined(__DECC))
extern char **environ;
#endif
register char *var, *val;
NODE **aptr;
register int i;
ENVIRON_node = install("ENVIRON",
node(Nnull_string, Node_var, (NODE *) NULL));
for (i = 0; environ[i]; i++) {
static char nullstr[] = "";
var = environ[i];
val = strchr(var, '=');
if (val)
*val++ = '\0';
else
val = nullstr;
aptr = assoc_lookup(ENVIRON_node, tmp_string(var, strlen (var)));
*aptr = make_string(val, strlen (val));
(*aptr)->flags |= MAYBE_NUM;
/* restore '=' so that system() gets a valid environment */
if (val != nullstr)
*--val = '=';
}
}
/* Process a command-line assignment */
char *
arg_assign(arg)
char *arg;
{
char *cp, *cp2;
int badvar;
Func_ptr after_assign = NULL;
NODE *var;
NODE *it;
NODE **lhs;
cp = strchr(arg, '=');
if (cp != NULL) {
*cp++ = '\0';
/* first check that the variable name has valid syntax */
badvar = 0;
if (! isalpha(arg[0]) && arg[0] != '_')
badvar = 1;
else
for (cp2 = arg+1; *cp2; cp2++)
if (! isalnum(*cp2) && *cp2 != '_') {
badvar = 1;
break;
}
if (badvar)
fatal("illegal name `%s' in variable assignment", arg);
/*
* Recent versions of nawk expand escapes inside assignments.
* This makes sense, so we do it too.
*/
it = make_str_node(cp, strlen(cp), SCAN);
it->flags |= MAYBE_NUM;
var = variable(arg, 0);
lhs = get_lhs(var, &after_assign);
unref(*lhs);
*lhs = it;
if (after_assign)
(*after_assign)();
*--cp = '='; /* restore original text of ARGV */
}
return cp;
}
static void
pre_assign(v)
char *v;
{
if (!arg_assign(v)) {
fprintf (stderr,
"%s: '%s' argument to -v not in 'var=value' form\n",
myname, v);
usage(1);
}
}
SIGTYPE
catchsig(sig, code)
int sig, code;
{
#ifdef lint
code = 0; sig = code; code = sig;
#endif
if (sig == SIGFPE) {
fatal("floating point exception");
} else if (sig == SIGSEGV
#ifdef SIGBUS
|| sig == SIGBUS
#endif
) {
msg("fatal error: internal error");
/* fatal won't abort() if not compiled for debugging */
abort();
} else
cant_happen();
/* NOTREACHED */
}
/* gawk_option --- do gawk specific things */
static void
gawk_option(optstr)
char *optstr;
{
char *cp;
for (cp = optstr; *cp; cp++) {
switch (*cp) {
case ' ':
case '\t':
case ',':
break;
case 'v':
case 'V':
/* print version */
if (strncasecmp(cp, "version", 7) != 0)
goto unknown;
else
cp += 6;
version();
break;
case 'c':
case 'C':
if (strncasecmp(cp, "copyright", 9) == 0) {
cp += 8;
copyleft();
} else if (strncasecmp(cp, "copyleft", 8) == 0) {
cp += 7;
copyleft();
} else if (strncasecmp(cp, "compat", 6) == 0) {
cp += 5;
do_unix = 1;
} else
goto unknown;
break;
case 'n':
case 'N':
/*
* Undocumented feature,
* inspired by nostalgia, and a T-shirt
*/
if (strncasecmp(cp, "nostalgia", 9) != 0)
goto unknown;
nostalgia();
break;
case 'p':
case 'P':
#ifdef DEBUG
if (strncasecmp(cp, "parsedebug", 10) == 0) {
cp += 9;
yydebug = 2;
break;
}
#endif
if (strncasecmp(cp, "posix", 5) != 0)
goto unknown;
cp += 4;
do_posix = do_unix = 1;
break;
case 'l':
case 'L':
if (strncasecmp(cp, "lint", 4) != 0)
goto unknown;
cp += 3;
do_lint = 1;
break;
case 'H':
case 'h':
if (strncasecmp(cp, "help", 4) != 0)
goto unknown;
cp += 3;
usage(0);
break;
case 'U':
case 'u':
if (strncasecmp(cp, "usage", 5) != 0)
goto unknown;
cp += 4;
usage(0);
break;
case 's':
case 'S':
if (strncasecmp(cp, "source=", 7) != 0)
goto unknown;
cp += 7;
if (cp[0] == '\0')
warning("empty argument to -Wsource ignored");
else {
srcfiles[++numfiles].stype = CMDLINE;
srcfiles[numfiles].val = cp;
return;
}
break;
default:
unknown:
fprintf(stderr, "'%c' -- unknown option, ignored\n",
*cp);
break;
}
}
}
/* nostalgia --- print the famous error message and die */
static void
nostalgia()
{
fprintf(stderr, "awk: bailing out near line 1\n");
abort();
}
/* version --- print version message */
static void
version()
{
fprintf(stderr, "%s, patchlevel %d\n", version_string, PATCHLEVEL);
/* per GNU coding standards, exit successfully, do nothing else */
exit(0);
}
/* this mess will improve in 2.16 */
char *
gawk_name(filespec)
char *filespec;
{
char *p;
#ifdef VMS /* "device:[root.][directory.subdir]GAWK.EXE;n" -> "GAWK" */
char *q;
p = strrchr(filespec, ']'); /* directory punctuation */
q = strrchr(filespec, '>'); /* alternate <international> punct */
if (p == NULL || q > p) p = q;
p = strdup(p == NULL ? filespec : (p + 1));
if ((q = strrchr(p, '.')) != NULL) *q = '\0'; /* strip .typ;vers */
return p;
#endif /*VMS*/
#if defined(MSDOS) || defined(OS2) || defined(atarist)
char *q;
for (p = filespec; (p = strchr(p, '\\')); *p = '/')
;
p = filespec;
if ((q = strrchr(p, '/')))
p = q + 1;
if ((q = strchr(p, '.')))
*q = '\0';
strlwr(p);
return (p == NULL ? filespec : p);
#endif /* MSDOS || atarist */
/* "path/name" -> "name" */
p = strrchr(filespec, '/');
return (p == NULL ? filespec : p + 1);
}

View file

@ -1,107 +0,0 @@
/*
* msg.c - routines for error messages
*/
/*
* Copyright (C) 1986, 1988, 1989, 1991, 1992, 1993 the Free Software Foundation, Inc.
*
* This file is part of GAWK, the GNU implementation of the
* AWK Progamming Language.
*
* GAWK 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 2, or (at your option)
* any later version.
*
* GAWK 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 GAWK; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "awk.h"
int sourceline = 0;
char *source = NULL;
/* VARARGS2 */
void
err(s, emsg, argp)
const char *s;
const char *emsg;
va_list argp;
{
char *file;
(void) fflush(stdout);
(void) fprintf(stderr, "%s: ", myname);
if (sourceline) {
if (source)
(void) fprintf(stderr, "%s:", source);
else
(void) fprintf(stderr, "cmd. line:");
(void) fprintf(stderr, "%d: ", sourceline);
}
if (FNR) {
file = FILENAME_node->var_value->stptr;
(void) putc('(', stderr);
if (file)
(void) fprintf(stderr, "FILENAME=%s ", file);
(void) fprintf(stderr, "FNR=%ld) ", FNR);
}
(void) fprintf(stderr, s);
vfprintf(stderr, emsg, argp);
(void) fprintf(stderr, "\n");
(void) fflush(stderr);
}
/*VARARGS0*/
void
msg(va_alist)
va_dcl
{
va_list args;
char *mesg;
va_start(args);
mesg = va_arg(args, char *);
err("", mesg, args);
va_end(args);
}
/*VARARGS0*/
void
warning(va_alist)
va_dcl
{
va_list args;
char *mesg;
va_start(args);
mesg = va_arg(args, char *);
err("warning: ", mesg, args);
va_end(args);
}
/*VARARGS0*/
void
fatal(va_alist)
va_dcl
{
va_list args;
char *mesg;
va_start(args);
mesg = va_arg(args, char *);
err("fatal: ", mesg, args);
va_end(args);
#ifdef DEBUG
abort();
#endif
exit(2);
}

View file

@ -1,463 +0,0 @@
/*
* node.c -- routines for node management
*/
/*
* Copyright (C) 1986, 1988, 1989, 1991, 1992, 1993 the Free Software Foundation, Inc.
*
* This file is part of GAWK, the GNU implementation of the
* AWK Progamming Language.
*
* GAWK 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 2 of the License, or
* (at your option) any later version.
*
* GAWK 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 GAWK; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "awk.h"
extern double strtod();
AWKNUM
r_force_number(n)
register NODE *n;
{
register char *cp;
register char *cpend;
char save;
char *ptr;
unsigned int newflags;
#ifdef DEBUG
if (n == NULL)
cant_happen();
if (n->type != Node_val)
cant_happen();
if(n->flags == 0)
cant_happen();
if (n->flags & NUM)
return n->numbr;
#endif
/* all the conditionals are an attempt to avoid the expensive strtod */
n->numbr = 0.0;
n->flags |= NUM;
if (n->stlen == 0)
return 0.0;
cp = n->stptr;
if (isalpha(*cp))
return 0.0;
cpend = cp + n->stlen;
while (cp < cpend && isspace(*cp))
cp++;
if (cp == cpend || isalpha(*cp))
return 0.0;
if (n->flags & MAYBE_NUM) {
newflags = NUMBER;
n->flags &= ~MAYBE_NUM;
} else
newflags = 0;
if (cpend - cp == 1) {
if (isdigit(*cp)) {
n->numbr = (AWKNUM)(*cp - '0');
n->flags |= newflags;
}
return n->numbr;
}
errno = 0;
save = *cpend;
*cpend = '\0';
n->numbr = (AWKNUM) strtod((const char *)cp, &ptr);
/* POSIX says trailing space is OK for NUMBER */
while (isspace(*ptr))
ptr++;
*cpend = save;
/* the >= should be ==, but for SunOS 3.5 strtod() */
if (errno == 0 && ptr >= cpend)
n->flags |= newflags;
else
errno = 0;
return n->numbr;
}
/*
* the following lookup table is used as an optimization in force_string
* (more complicated) variations on this theme didn't seem to pay off, but
* systematic testing might be in order at some point
*/
static const char *values[] = {
"0",
"1",
"2",
"3",
"4",
"5",
"6",
"7",
"8",
"9",
};
#define NVAL (sizeof(values)/sizeof(values[0]))
NODE *
r_force_string(s)
register NODE *s;
{
char buf[128];
register char *sp = buf;
double val;
#ifdef DEBUG
if (s == NULL) cant_happen();
if (s->type != Node_val) cant_happen();
if (s->flags & STR) return s;
if (!(s->flags & NUM)) cant_happen();
if (s->stref != 0) ; /*cant_happen();*/
#endif
/* not an integral value, or out of range */
if ((val = double_to_int(s->numbr)) != s->numbr
|| val < LONG_MIN || val > LONG_MAX) {
#ifdef GFMT_WORKAROUND
NODE *dummy, *r;
unsigned short oflags;
extern NODE *format_tree P((const char *, int, NODE *));
extern NODE **fmt_list; /* declared in eval.c */
/* create dummy node for a sole use of format_tree */
getnode(dummy);
dummy->lnode = s;
dummy->rnode = NULL;
oflags = s->flags;
s->flags |= PERM; /* prevent from freeing by format_tree() */
r = format_tree(CONVFMT, fmt_list[CONVFMTidx]->stlen, dummy);
s->flags = oflags;
s->stfmt = (char)CONVFMTidx;
s->stlen = r->stlen;
s->stptr = r->stptr;
freenode(r); /* Do not free_temp(r)! We want */
freenode(dummy); /* to keep s->stptr == r->stpr. */
goto no_malloc;
#else
/*
* no need for a "replacement" formatting by gawk,
* just use sprintf
*/
sprintf(sp, CONVFMT, s->numbr);
s->stlen = strlen(sp);
s->stfmt = (char)CONVFMTidx;
#endif /* GFMT_WORKAROUND */
} else {
/* integral value */
/* force conversion to long only once */
register long num = (long) val;
if (num < NVAL && num >= 0) {
sp = (char *) values[num];
s->stlen = 1;
} else {
(void) sprintf(sp, "%ld", num);
s->stlen = strlen(sp);
}
s->stfmt = -1;
}
emalloc(s->stptr, char *, s->stlen + 2, "force_string");
memcpy(s->stptr, sp, s->stlen+1);
no_malloc:
s->stref = 1;
s->flags |= STR;
return s;
}
/*
* Duplicate a node. (For strings, "duplicate" means crank up the
* reference count.)
*/
NODE *
dupnode(n)
NODE *n;
{
register NODE *r;
if (n->flags & TEMP) {
n->flags &= ~TEMP;
n->flags |= MALLOC;
return n;
}
if ((n->flags & (MALLOC|STR)) == (MALLOC|STR)) {
if (n->stref < 255)
n->stref++;
return n;
}
getnode(r);
*r = *n;
r->flags &= ~(PERM|TEMP);
r->flags |= MALLOC;
if (n->type == Node_val && (n->flags & STR)) {
r->stref = 1;
emalloc(r->stptr, char *, r->stlen + 2, "dupnode");
memcpy(r->stptr, n->stptr, r->stlen);
r->stptr[r->stlen] = '\0';
}
return r;
}
/* this allocates a node with defined numbr */
NODE *
mk_number(x, flags)
AWKNUM x;
unsigned int flags;
{
register NODE *r;
getnode(r);
r->type = Node_val;
r->numbr = x;
r->flags = flags;
#ifdef DEBUG
r->stref = 1;
r->stptr = 0;
r->stlen = 0;
#endif
return r;
}
/*
* Make a string node.
*/
NODE *
make_str_node(s, len, flags)
char *s;
size_t len;
int flags;
{
register NODE *r;
getnode(r);
r->type = Node_val;
r->flags = (STRING|STR|MALLOC);
if (flags & ALREADY_MALLOCED)
r->stptr = s;
else {
emalloc(r->stptr, char *, len + 2, s);
memcpy(r->stptr, s, len);
}
r->stptr[len] = '\0';
if (flags & SCAN) { /* scan for escape sequences */
char *pf;
register char *ptm;
register int c;
register char *end;
end = &(r->stptr[len]);
for (pf = ptm = r->stptr; pf < end;) {
c = *pf++;
if (c == '\\') {
c = parse_escape(&pf);
if (c < 0) {
if (do_lint)
warning("backslash at end of string");
c = '\\';
}
*ptm++ = c;
} else
*ptm++ = c;
}
len = ptm - r->stptr;
erealloc(r->stptr, char *, len + 1, "make_str_node");
r->stptr[len] = '\0';
r->flags |= PERM;
}
r->stlen = len;
r->stref = 1;
r->stfmt = -1;
return r;
}
NODE *
tmp_string(s, len)
char *s;
size_t len;
{
register NODE *r;
r = make_string(s, len);
r->flags |= TEMP;
return r;
}
#define NODECHUNK 100
NODE *nextfree = NULL;
NODE *
more_nodes()
{
register NODE *np;
/* get more nodes and initialize list */
emalloc(nextfree, NODE *, NODECHUNK * sizeof(NODE), "newnode");
for (np = nextfree; np < &nextfree[NODECHUNK - 1]; np++) {
np->flags = 0;
np->nextp = np + 1;
}
np->nextp = NULL;
np = nextfree;
nextfree = nextfree->nextp;
return np;
}
#ifdef DEBUG
void
freenode(it)
NODE *it;
{
#ifdef MPROF
it->stref = 0;
free((char *) it);
#else /* not MPROF */
/* add it to head of freelist */
it->nextp = nextfree;
nextfree = it;
#endif /* not MPROF */
}
#endif /* DEBUG */
void
unref(tmp)
register NODE *tmp;
{
if (tmp == NULL)
return;
if (tmp->flags & PERM)
return;
if (tmp->flags & (MALLOC|TEMP)) {
tmp->flags &= ~TEMP;
if (tmp->flags & STR) {
if (tmp->stref > 1) {
if (tmp->stref != 255)
tmp->stref--;
return;
}
free(tmp->stptr);
}
freenode(tmp);
}
}
/*
* Parse a C escape sequence. STRING_PTR points to a variable containing a
* pointer to the string to parse. That pointer is updated past the
* characters we use. The value of the escape sequence is returned.
*
* A negative value means the sequence \ newline was seen, which is supposed to
* be equivalent to nothing at all.
*
* If \ is followed by a null character, we return a negative value and leave
* the string pointer pointing at the null character.
*
* If \ is followed by 000, we return 0 and leave the string pointer after the
* zeros. A value of 0 does not mean end of string.
*
* Posix doesn't allow \x.
*/
int
parse_escape(string_ptr)
char **string_ptr;
{
register int c = *(*string_ptr)++;
register int i;
register int count;
switch (c) {
case 'a':
return BELL;
case 'b':
return '\b';
case 'f':
return '\f';
case 'n':
return '\n';
case 'r':
return '\r';
case 't':
return '\t';
case 'v':
return '\v';
case '\n':
return -2;
case 0:
(*string_ptr)--;
return -1;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
i = c - '0';
count = 0;
while (++count < 3) {
if ((c = *(*string_ptr)++) >= '0' && c <= '7') {
i *= 8;
i += c - '0';
} else {
(*string_ptr)--;
break;
}
}
return i;
case 'x':
if (do_lint) {
static int didwarn;
if (! didwarn) {
didwarn = 1;
warning("Posix does not allow \"\\x\" escapes");
}
}
if (do_posix)
return ('x');
i = 0;
while (1) {
if (isxdigit((c = *(*string_ptr)++))) {
i *= 16;
if (isdigit(c))
i += c - '0';
else if (isupper(c))
i += c - 'A' + 10;
else
i += c - 'a' + 10;
} else {
(*string_ptr)--;
break;
}
}
return i;
default:
return c;
}
}

View file

@ -1 +0,0 @@
#define PATCHLEVEL 5

View file

@ -1,122 +0,0 @@
/*
* protos.h -- function prototypes for when the headers don't have them.
*/
/*
* Copyright (C) 1991, 1992, 1993 the Free Software Foundation, Inc.
*
* This file is part of GAWK, the GNU implementation of the
* AWK Progamming Language.
*
* GAWK 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 2 of the License, or
* (at your option) any later version.
*
* GAWK 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 GAWK; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifdef __STDC__
#define aptr_t void * /* arbitrary pointer type */
#else
#define aptr_t char *
#endif
extern aptr_t malloc P((MALLOC_ARG_T));
extern aptr_t realloc P((aptr_t, MALLOC_ARG_T));
extern aptr_t calloc P((MALLOC_ARG_T, MALLOC_ARG_T));
#if !defined(sun) && !defined(__sun__)
extern void free P((aptr_t));
#endif
extern char *getenv P((const char *));
extern char *strcpy P((char *, const char *));
extern char *strcat P((char *, const char *));
extern int strcmp P((const char *, const char *));
extern char *strncpy P((char *, const char *, size_t));
extern int strncmp P((const char *, const char *, size_t));
#ifndef VMS
extern char *strerror P((int));
#else
extern char *strerror P((int,...));
#endif
extern char *strchr P((const char *, int));
extern char *strrchr P((const char *, int));
extern char *strstr P((const char *s1, const char *s2));
extern size_t strlen P((const char *));
extern long strtol P((const char *, char **, int));
#if !defined(_MSC_VER) && !defined(__GNU_LIBRARY__)
extern size_t strftime P((char *, size_t, const char *, const struct tm *));
#endif
#ifdef __STDC__
extern time_t time P((time_t *));
#else
extern long time();
#endif
extern aptr_t memset P((aptr_t, int, size_t));
extern aptr_t memcpy P((aptr_t, const aptr_t, size_t));
extern aptr_t memmove P((aptr_t, const aptr_t, size_t));
extern aptr_t memchr P((const aptr_t, int, size_t));
extern int memcmp P((const aptr_t, const aptr_t, size_t));
extern int fprintf P((FILE *, const char *, ...));
#if !defined(MSDOS) && !defined(__GNU_LIBRARY__)
#ifdef __STDC__
extern size_t fwrite P((const aptr_t, size_t, size_t, FILE *));
#else
extern int fwrite();
#endif
extern int fputs P((const char *, FILE *));
extern int unlink P((const char *));
#endif
extern int fflush P((FILE *));
extern int fclose P((FILE *));
extern FILE *popen P((const char *, const char *));
extern int pclose P((FILE *));
extern void abort P(());
extern int isatty P((int));
extern void exit P((int));
extern int system P((const char *));
extern int sscanf P((const char *, const char *, ...));
#ifndef toupper
extern int toupper P((int));
#endif
#ifndef tolower
extern int tolower P((int));
#endif
extern double pow P((double x, double y));
extern double atof P((const char *));
extern double strtod P((const char *, char **));
extern int fstat P((int, struct stat *));
extern int stat P((const char *, struct stat *));
extern off_t lseek P((int, off_t, int));
extern int fseek P((FILE *, long, int));
extern int close P((int));
extern int creat P((const char *, mode_t));
extern int open P((const char *, int, ...));
extern int pipe P((int *));
extern int dup P((int));
extern int dup2 P((int,int));
extern int fork P(());
extern int execl P((/* char *, char *, ... */));
#ifndef __STDC__
extern int read P((int, char *, int));
#endif
extern int wait P((int *));
extern void _exit P((int));
#ifdef NON_STD_SPRINTF
extern char *sprintf P((char *, const char*, ...));
#else
extern int sprintf P((char *, const char*, ...));
#endif /* SPRINTF_INT */
#undef aptr_t

View file

@ -1,212 +0,0 @@
/*
* re.c - compile regular expressions.
*/
/*
* Copyright (C) 1991, 1992, 1993 the Free Software Foundation, Inc.
*
* This file is part of GAWK, the GNU implementation of the
* AWK Progamming Language.
*
* GAWK 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 2 of the License, or
* (at your option) any later version.
*
* GAWK 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 GAWK; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "awk.h"
/* Generate compiled regular expressions */
Regexp *
make_regexp(s, len, ignorecase, dfa)
char *s;
size_t len;
int ignorecase;
int dfa;
{
Regexp *rp;
const char *rerr;
char *src = s;
char *temp;
char *end = s + len;
register char *dest;
register int c;
/* Handle escaped characters first. */
/* Build a copy of the string (in dest) with the
escaped characters translated, and generate the regex
from that.
*/
emalloc(dest, char *, len + 2, "make_regexp");
temp = dest;
while (src < end) {
if (*src == '\\') {
c = *++src;
switch (c) {
case 'a':
case 'b':
case 'f':
case 'n':
case 'r':
case 't':
case 'v':
case 'x':
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
c = parse_escape(&src);
if (c < 0)
cant_happen();
*dest++ = (char)c;
break;
default:
*dest++ = '\\';
*dest++ = (char)c;
src++;
break;
} /* switch */
} else {
*dest++ = *src++; /* not '\\' */
}
} /* for */
*dest = '\0' ; /* Only necessary if we print dest ? */
emalloc(rp, Regexp *, sizeof(*rp), "make_regexp");
memset((char *) rp, 0, sizeof(*rp));
emalloc(rp->pat.buffer, unsigned char *, 16, "make_regexp");
rp->pat.allocated = 16;
emalloc(rp->pat.fastmap, char *, 256, "make_regexp");
if (ignorecase)
rp->pat.translate = casetable;
else
rp->pat.translate = NULL;
len = dest - temp;
if ((rerr = re_compile_pattern(temp, len, &(rp->pat))) != NULL)
fatal("%s: /%s/", rerr, temp);
if (dfa && !ignorecase) {
dfacomp(temp, len, &(rp->dfareg), 1);
rp->dfa = 1;
} else
rp->dfa = 0;
free(temp);
return rp;
}
int
research(rp, str, start, len, need_start)
Regexp *rp;
register char *str;
int start;
register size_t len;
int need_start;
{
char *ret = str;
if (rp->dfa) {
char save;
int count = 0;
int try_backref;
/*
* dfa likes to stick a '\n' right after the matched
* text. So we just save and restore the character.
*/
save = str[start+len];
ret = dfaexec(&(rp->dfareg), str+start, str+start+len, 1,
&count, &try_backref);
str[start+len] = save;
}
if (ret) {
if (need_start || rp->dfa == 0)
return re_search(&(rp->pat), str, start+len, start,
len, &(rp->regs));
else
return 1;
} else
return -1;
}
void
refree(rp)
Regexp *rp;
{
free(rp->pat.buffer);
free(rp->pat.fastmap);
if (rp->dfa)
dfafree(&(rp->dfareg));
free(rp);
}
void
dfaerror(s)
const char *s;
{
fatal(s);
}
Regexp *
re_update(t)
NODE *t;
{
NODE *t1;
# define CASE 1
if ((t->re_flags & CASE) == IGNORECASE) {
if (t->re_flags & CONST)
return t->re_reg;
t1 = force_string(tree_eval(t->re_exp));
if (t->re_text) {
if (cmp_nodes(t->re_text, t1) == 0) {
free_temp(t1);
return t->re_reg;
}
unref(t->re_text);
}
t->re_text = dupnode(t1);
free_temp(t1);
}
if (t->re_reg)
refree(t->re_reg);
if (t->re_cnt)
t->re_cnt++;
if (t->re_cnt > 10)
t->re_cnt = 0;
if (!t->re_text) {
t1 = force_string(tree_eval(t->re_exp));
t->re_text = dupnode(t1);
free_temp(t1);
}
t->re_reg = make_regexp(t->re_text->stptr, t->re_text->stlen,
IGNORECASE, t->re_cnt);
t->re_flags &= ~CASE;
t->re_flags |= IGNORECASE;
return t->re_reg;
}
void
resetup()
{
reg_syntax_t syn = RE_SYNTAX_AWK;
(void) re_set_syntax(syn);
dfasyntax(syn, 0);
}

View file

@ -1,47 +0,0 @@
char *version_string = "@(#)Gnu Awk (gawk) 2.15";
/* 1.02 fixed /= += *= etc to return the new Left Hand Side instead
of the Right Hand Side */
/* 1.03 Fixed split() to treat strings of space and tab as FS if
the split char is ' '.
Added -v option to print version number
Fixed bug that caused rounding when printing large numbers */
/* 2.00beta Incorporated the functionality of the "new" awk as described
the book (reference not handy). Extensively tested, but no
doubt still buggy. Badly needs tuning and cleanup, in
particular in memory management which is currently almost
non-existent. */
/* 2.01 JF: Modified to compile under GCC, and fixed a few
bugs while I was at it. I hope I didn't add any more.
I modified parse.y to reduce the number of reduce/reduce
conflicts. There are still a few left. */
/* 2.02 Fixed JF's bugs; improved memory management, still needs
lots of work. */
/* 2.10 Major grammar rework and lots of bug fixes from David.
Major changes for performance enhancements from David.
A number of minor bug fixes and new features from Arnold.
Changes for MSDOS from Conrad Kwok and Scott Garfinkle.
The gawk.texinfo and info files included! */
/* 2.11 Bug fix release to 2.10. Lots of changes for portability,
speed, and configurability. */
/* 2.12 Lots of changes for portability, speed, and configurability.
Several bugs fixed. POSIX compliance. Removal of last set
of hard-wired limits. Atari and VMS ports added. */
/* 2.13 Public release of 2.12 */
/* 2.14 Mostly bug fixes. */
/* 2.15 Bug fixes plus intermixing of command-line source and files,
GNU long options, ARGIND, ERRNO and Plan 9 style /dev/ files.
`delete array'. OS/2 port added. */