Add a test suite for etags

* test/etags/: New test suite, adapted from
http://fly.isti.cnr.it/pub/software/unix/etags-regression-test.tar.bz2,
whose original author is Francesco Potortì <pot@gnu.org>.
This commit is contained in:
Eli Zaretskii 2015-05-12 20:05:52 +03:00
parent c03c195a27
commit 000f5e0e43
96 changed files with 105938 additions and 1 deletions

10
.gitignore vendored
View file

@ -39,11 +39,13 @@ src/config.in
Info.plist
InfoPlist.strings
Makefile
makefile
!admin/charsets/Makefile
!etc/refcards/Makefile
!test/automated/data/flymake/Makefile
!test/indent/Makefile
makefile
!test/etags/Makefile
!test/etags/make-src/Makefile
/*.cache
/confdefs.h
/config.status
@ -145,6 +147,10 @@ src/*.map
# Tests.
test/indent/*.new
test/biditest.txt
test/etags/srclist
test/etags/regexfile
test/etags/ETAGS
test/etags/CTAGS
# ctags, etags.
TAGS
@ -200,6 +206,7 @@ lisp/international/uni-*.el
*.fn
*.fns
*.html
!test/etags/html-src/*.html
*.info
*.ky
*.kys
@ -215,6 +222,7 @@ lisp/international/uni-*.el
*.pj
*.pjs
*.ps
!test/etags/ps-src/*.ps
*.sc
*.scs
*.t2d/

6013
test/etags/CTAGS.good Normal file

File diff suppressed because it is too large Load diff

5214
test/etags/ETAGS.good_1 Normal file

File diff suppressed because it is too large Load diff

6440
test/etags/ETAGS.good_2 Normal file

File diff suppressed because it is too large Load diff

6118
test/etags/ETAGS.good_3 Normal file

File diff suppressed because it is too large Load diff

5378
test/etags/ETAGS.good_4 Normal file

File diff suppressed because it is too large Load diff

7508
test/etags/ETAGS.good_5 Normal file

File diff suppressed because it is too large Load diff

79
test/etags/Makefile Normal file
View file

@ -0,0 +1,79 @@
ADASRC=$(addprefix ./ada-src/,etags-test-for.ada 2ataspri.adb 2ataspri.ads waroquiers.ada)
ASRC=$(addprefix ./a-src/,empty.zz empty.zz.gz)
CSRC=$(addprefix ./c-src/,abbrev.c .//c.c torture.c getopt.h etags.c\
exit.c exit.strange_suffix sysdep.h tab.c dostorture.c\
emacs/src/gmalloc.c emacs/src/regex.h emacs/src/keyboard.c emacs/src/lisp.h\
machsyscalls.c machsyscalls.h fail.c a/b/b.c) ../etags/c-src/h.h
CPSRC=$(addprefix ./cp-src/,c.C abstract.C abstract.H cfront.H burton.cpp burton.cpp\
functions.cpp MDiagArray2.h Pctest.h Range.h\
screen.cpp screen.hpp conway.cpp conway.hpp clheir.cpp.gz clheir.hpp.gz fail.C)
ELSRC=$(addprefix ./el-src/,TAGTEST.EL emacs/lisp/progmodes/etags.el)
ERLSRC=$(addprefix ./erl-src/,gs_dialog.erl lines.erl lists.erl)
FORTHSRC=$(addprefix ./forth-src/,test-forth.fth)
FSRC=$(addprefix ./f-src/,entry.for entry.strange_suffix entry.strange)
HTMLSRC=$(addprefix ./html-src/,softwarelibero.html index.shtml algrthms.html software.html)
JAVASRC=$(addprefix ./java-src/,AWTEMul.java KeyEve.java SMan.java SysCol.java TG.java)
LUASRC=$(addprefix ./lua-src/,allegro.lua)
MAKESRC=$(addprefix ./make-src/,Makefile)
OBJCSRC=$(addprefix ./objc-src/,Subprocess.h Subprocess.m PackInsp.h PackInsp.m)
OBJCPPSRC=$(addprefix ./objcpp-src/,SimpleCalc.H SimpleCalc.M)
PASSRC=$(addprefix ./pas-src/,common.pas)
PERLSRC=$(addprefix ./perl-src/,htlmify-cystic yagrip.pl kai-test.pl mirror.pl)
PHPSRC=$(addprefix ./php-src/,lce_functions.php ptest.php sendmail.php)
PSSRC=$(addprefix ./ps-src/,rfc1245.ps)
PROLSRC=$(addprefix ./prol-src/,ordsets.prolog natded.prolog)
PYTSRC=$(addprefix ./pyt-src/,server.py)
TEXSRC=$(addprefix ./tex-src/,testenv.tex gzip.texi texinfo.tex nonewline.tex)
YSRC=$(addprefix ./y-src/,parse.y parse.c atest.y cccp.c cccp.y)
SRCS=Makefile ${ADASRC} ${ASRC} ${CSRC} ${CPSRC} ${ELSRC} ${ERLSRC} ${FSRC}\
${FORTHSRC} ${HTMLSRC} ${JAVASRC} ${LUASRC} ${MAKESRC} ${OBJCSRC}\
${OBJCPPSRC} ${PASSRC} ${PHPSRC} ${PERLSRC} ${PSSRC} ${PROLSRC} ${PYTSRC}\
${TEXSRC} ${YSRC}
NONSRCS=./f-src/entry.strange ./erl-src/lists.erl ./cp-src/clheir.hpp.gz
ETAGS_PROG=../../lib-src/etags
CTAGS_PROG=../../lib-src/ctags
REGEX=/[ \t]*DEFVAR_[A-Z_ \t\n(]+"\([^"]+\)"/
xx="this line is here because of a fontlock bug
RUN=
OPTIONS=--members --declarations --regex=@regexfile
ARGS=- < srclist
infiles = $(filter-out ${NONSRCS},${SRCS}) srclist regexfile
check:
@$(MAKE) OPTIONS='--no-members' ediff_1
@$(MAKE) OPTIONS='--declarations --no-members' ediff_2
@$(MAKE) OPTIONS='--members' ediff_3
@$(MAKE) OPTIONS='--regex=@regexfile --no-members' ediff_4
@$(MAKE) OPTIONS='nonexistent --members --declarations --regex=@regexfile' ediff_5
@$(MAKE) cdiff
ediff%: ETAGS.good% ETAGS ${infiles}
diff -u --suppress-common-lines --width=80 ETAGS.good$* ETAGS
cdiff: CTAGS.good CTAGS ${infiles}
diff -u --suppress-common-lines --width=80 CTAGS.good CTAGS
ETAGS: FRC ${infiles}
${RUN} ${ETAGS_PROG} ${OPTIONS} -o $@ ${ARGS}
CTAGS: FRC ${infiles}
${RUN} ${CTAGS_PROG} -o $@ --regex=@regexfile ${ARGS}
srclist: Makefile
@for i in $(SRCS); do echo $$i; done > srclist
@echo "srclist remade"
regexfile: Makefile
@echo ' -- This is for GNU Emacs source files' > regexfile
@echo '${REGEX}' >> regexfile
@echo '{c}${REGEX}\\1/m' >> regexfile
@echo "regexfile remade"
.PRECIOUS: ETAGS.good CTAGS.good
FRC:;

View file

View file

View file

@ -0,0 +1,665 @@
------------------------------------------------------------------------------
-- --
-- GNU ADA RUNTIME LIBRARY (GNARL) COMPONENTS --
-- --
-- S Y S T E M . T A S K _ P R I M I T I V E S --
-- --
-- B o d y --
-- --
-- $Revision: 1.1 $ --
-- --
-- Copyright (C) 1991,1992,1993,1994,1996 Florida State University --
-- --
-- GNARL is free software; you can redistribute it and/or modify it under --
-- terms of the GNU Library General Public License as published by the --
-- Free Software Foundation; either version 2, or (at your option) any --
-- later version. GNARL is distributed in the hope that it will be use- --
-- ful, but but WITHOUT ANY WARRANTY; without even the implied warranty of --
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Gen- --
-- eral Library Public License for more details. You should have received --
-- a copy of the GNU Library General Public License along with GNARL; see --
-- file COPYING.LIB. If not, write to the Free Software Foundation, 675 --
-- Mass Ave, Cambridge, MA 02139, USA. --
-- --
------------------------------------------------------------------------------
with GNAT.IO;
with Interfaces.C.POSIX_timers;
with Interfaces.C.POSIX_Error;
use Interfaces.C.POSIX_Error;
with Interfaces.C.POSIX_RTE;
use Interfaces.C.POSIX_RTE;
with Interfaces.C.Pthreads;
use Interfaces.C.Pthreads;
with Interfaces.C;
use Interfaces.C;
with System.Tasking;
use System.Tasking;
with System.Storage_Elements;
use System.Storage_Elements;
with System.Compiler_Exceptions;
use System.Compiler_Exceptions;
with System.Task_Specific_Data;
use System.Task_Specific_Data;
with System.Secondary_Stack;
use System.Secondary_Stack;
with System.Tasking_Soft_Links;
with System.Task_Clock;
use System.Task_Clock;
with Unchecked_Conversion;
with Interfaces.C.System_Constants;
package body System.Task_Primitives is
use Interfaces.C.Pthreads;
use Interfaces.C.System_Constants;
package RTE renames Interfaces.C.POSIX_RTE;
package TSL renames System.Tasking_Soft_Links;
Test_And_Set_Mutex : Lock;
Abort_Signal : constant := 6;
Abort_Handler : Abort_Handler_Pointer;
ATCB_Key : aliased pthread_key_t;
Unblocked_Signal_Mask : aliased RTE.Signal_Set;
-- The set of signals that should be unblocked in a task.
-- This is in general the signals that can be generated synchronously,
-- and which should therefore be converted into Ada exceptions.
-- It also includes the Abort_Signal, to allow asynchronous abortion.
function To_void_ptr is new
Unchecked_Conversion (TCB_Ptr, void_ptr);
function To_TCB_Ptr is new
Unchecked_Conversion (void_ptr, TCB_Ptr);
function pthread_mutexattr_setprotocol
(attr : access pthread_attr_t; priority : integer) return int;
pragma Import (C,
pthread_mutexattr_setprotocol,
"pthread_mutexattr_setprotocol",
"pthread_mutexattr_setprotocol");
function pthread_mutexattr_setprio_ceiling
(attr : access pthread_attr_t; priority : int) return int;
pragma Import (C,
pthread_mutexattr_setprio_ceiling,
"pthread_mutexattr_setprio_ceiling",
"pthread_mutexattr_setprio_ceiling");
pthread_mutexattr_default : pthread_mutexattr_t;
pragma Import (C, pthread_mutexattr_default,
"pthread_mutexattr_default",
"pthread_mutexattr_default");
-----------------------
-- Local Subprograms --
-----------------------
procedure Abort_Wrapper
(signo : Integer;
info : RTE.siginfo_ptr;
context : System.Address);
-- This is a signal handler procedure which calls the user-specified
-- abort handler procedure.
procedure LL_Wrapper (T : TCB_Ptr);
-- A wrapper procedure that is called from a new low-level task.
-- It performs initializations for the new task and calls the
-- user-specified startup procedure.
-------------------------
-- Initialize_LL_Tasks --
-------------------------
procedure Initialize_LL_Tasks (T : TCB_Ptr) is
Result : int;
begin
T.LL_Entry_Point := null;
T.Thread := pthread_self;
Result := pthread_key_create (ATCB_Key'Access, null);
if Result = FUNC_ERR then
raise Storage_Error; -- Insufficient resources.
end if;
T.Thread := pthread_self;
Result := pthread_setspecific (ATCB_Key, To_void_ptr (T));
if Result = FUNC_ERR then
GNAT.IO.Put_Line ("Get specific failed");
raise Storage_Error; -- Insufficient resources.
end if;
pragma Assert (Result /= FUNC_ERR,
"GNULLI failure---pthread_setspecific");
end Initialize_LL_Tasks;
----------
-- Self --
----------
function Self return TCB_Ptr is
Temp : aliased void_ptr;
Result : int;
begin
Result := pthread_getspecific (ATCB_Key, Temp'Access);
pragma Assert (Result /= FUNC_ERR,
"GNULLI failure---pthread_getspecific");
return To_TCB_Ptr (Temp);
end Self;
---------------------
-- Initialize_Lock --
---------------------
procedure Initialize_Lock
(Prio : System.Any_Priority;
L : in out Lock)
is
Attributes : aliased pthread_mutexattr_t;
Result : int;
MUTEX_NONRECURSIVE_NP : constant := 2;
begin
Result := pthread_mutexattr_init (Attributes'Access);
if Result = FUNC_ERR then
raise STORAGE_ERROR; -- should be ENOMEM
end if;
Result := pthread_mutexattr_setkind
(Attributes'Access, MUTEX_NONRECURSIVE_NP);
if Result = FUNC_ERR then
raise STORAGE_ERROR; -- should be ENOMEM
end if;
Result := pthread_mutex_init (L.mutex'Access, Attributes);
if Result = FUNC_ERR then
Result := pthread_mutexattr_destroy (Attributes'Access);
raise STORAGE_ERROR; -- should be ENOMEM ???
end if;
Result := pthread_mutexattr_destroy (Attributes'Access);
end Initialize_Lock;
-------------------
-- Finalize_Lock --
-------------------
procedure Finalize_Lock (L : in out Lock) is
Result : int;
begin
Result := pthread_mutex_destroy (L.mutex'Access);
pragma Assert
(Result /= FUNC_ERR, "GNULLI failure---pthread_mutex_destroy");
end Finalize_Lock;
----------------
-- Write_Lock --
----------------
--
-- The current pthreads implementation does not check for Ceiling
-- violations.
--
procedure Write_Lock (L : in out Lock; Ceiling_Violation : out Boolean) is
Result : int;
begin
Ceiling_Violation := False;
Result := pthread_mutex_lock (L.mutex'Access);
pragma Assert
(Result /= FUNC_ERR, "GNULLI FUNC_ERR---pthread_mutex_lock");
end Write_Lock;
---------------
-- Read_Lock --
---------------
procedure Read_Lock (L : in out Lock; Ceiling_Violation : out Boolean)
renames Write_Lock;
------------
-- Unlock --
------------
procedure Unlock (L : in out Lock) is
Result : int;
begin
Result := pthread_mutex_unlock (L.mutex'Access);
pragma Assert
(Result /= FUNC_ERR, "GNULLI FUNC_ERR---pthread_mutex_unlock");
end Unlock;
---------------------
-- Initialize_Cond --
---------------------
procedure Initialize_Cond (Cond : in out Condition_Variable) is
Attributes : aliased Pthreads.pthread_condattr_t;
Result : int;
begin
Result := pthread_condattr_init (Attributes'Access);
if Result = FUNC_ERR then
raise STORAGE_ERROR; -- should be ENOMEM ???
end if;
-- Result := pthread_cond_init (Cond.CV'Access, Attributes'Access);
Result := pthread_cond_init (Cond.CV'Access, Attributes);
if Result = FUNC_ERR then
raise STORAGE_ERROR; -- should be ENOMEM ???
end if;
Result := pthread_condattr_destroy (Attributes'Access);
pragma Assert
(Result /= FUNC_ERR, "GNULLI FUNC_ERR---pthread_condattr_destroy");
end Initialize_Cond;
-------------------
-- Finalize_Cond --
-------------------
procedure Finalize_Cond (Cond : in out Condition_Variable) is
Result : int;
begin
Result := pthread_cond_destroy (Cond.CV'Access);
pragma Assert
(Result /= FUNC_ERR, "GNULLI failure---pthread_cond_destroy");
end Finalize_Cond;
---------------
-- Cond_Wait --
---------------
procedure Cond_Wait (Cond : in out Condition_Variable; L : in out Lock) is
Result : int;
begin
Result := pthread_cond_wait (Cond.CV'Access, L.mutex'Access);
pragma Assert
(Result /= FUNC_ERR, "GNULLI failure---pthread_cond_wait");
end Cond_Wait;
---------------------
-- Cond_Timed_Wait --
---------------------
procedure Cond_Timed_Wait
(Cond : in out Condition_Variable;
L : in out Lock;
Abs_Time : System.Task_Clock.Stimespec;
Timed_Out : out Boolean) is
Result : int;
TV : aliased timespec;
use POSIX_Error;
begin
Timed_Out := False; -- Assume success until we know otherwise
TV.tv_sec := int (Interfaces.C.POSIX_timers.time_t
(Task_Clock.Stimespec_Seconds (Abs_Time)));
TV.tv_nsec := long (Interfaces.C.POSIX_timers.Nanoseconds
(Task_Clock.Stimespec_NSeconds (Abs_Time)));
Result := pthread_cond_timedwait
(Cond.CV'Access, L.mutex'Access, TV'Access);
pragma Assert
(Result /= FUNC_ERR, "GNULLI failure---pthread_cond_timedwait");
end Cond_Timed_Wait;
-----------------
-- Cond_Signal --
-----------------
procedure Cond_Signal (Cond : in out Condition_Variable) is
Result : int;
begin
Result := pthread_cond_signal (Cond.CV'Access);
pragma Assert
(Result /= FUNC_ERR, "GNULLI failure---pthread_cond_signal");
end Cond_Signal;
------------------
-- Set_Priority --
------------------
procedure Set_Priority
(T : TCB_Ptr;
Prio : System.Any_Priority) is
Result : int;
Thread : Pthreads.pthread_t renames T.Thread;
begin
Result := pthread_setprio (Thread, int (Prio));
pragma Assert
(Result /= FUNC_ERR, "GNULLI failure---pthread_setprio");
end Set_Priority;
----------------------
-- Set_Own_Priority --
----------------------
procedure Set_Own_Priority (Prio : System.Any_Priority) is
begin
null;
-- ENOSYS Result :=
-- pthread_setprio (pthread_self, int (Prio));
-- pragma Assert
-- (Result /= FUNC_ERR, "GNULLI failure---pthread_setprio");
end Set_Own_Priority;
------------------
-- Get_Priority --
------------------
function Get_Priority (T : TCB_Ptr) return System.Any_Priority is
Priority : aliased int := 0;
begin
-- ENOSYS Result := pthread_getprio (T.Thread, Priority'Access);
-- pragma Assert
-- (Result /= FUNC_ERR, "GNULLI failure---pthread_getprio");
return System.Priority (Priority);
end Get_Priority;
-----------------------
-- Get_Own_Priority --
-----------------------
function Get_Own_Priority return System.Any_Priority is
Result : int;
Priority : aliased int := 0;
begin
Result := pthread_getprio (pthread_self, Priority'Access);
pragma Assert
(Result /= FUNC_ERR, "GNULLI failure---pthread_getprio");
return System.Priority (Priority);
end Get_Own_Priority;
--------------------
-- Create_LL_Task --
--------------------
procedure Create_LL_Task
(Priority : System.Any_Priority;
Stack_Size : Task_Storage_Size;
Task_Info : System.Task_Info.Task_Info_Type;
LL_Entry_Point : LL_Task_Procedure_Access;
Arg : System.Address;
T : TCB_Ptr) is
use Pthreads;
Attributes : aliased pthread_attr_t;
Result : int;
L_Priority : System.Any_Priority := Priority;
function To_Start_Addr is new
Unchecked_Conversion (System.Address, start_addr);
begin
T.LL_Entry_Point := LL_Entry_Point;
T.LL_Arg := Arg;
T.Stack_Size := Stack_Size;
Result := pthread_attr_init (Attributes'Access);
pragma Assert (Result /= FUNC_ERR, "GNULLI failure---pthread_attr_init");
-- Result := pthread_attr_setdetachstate (Attributes'Access, 1);
-- pragma Assert
-- (Result /= FUNC_ERR, "GNULLI failure---pthread_setdetachstate");
Result := pthread_attr_setstacksize
(Attributes'Access, size_t (Stack_Size));
pragma Assert
(Result /= FUNC_ERR, "GNULLI failure---pthread_setstacksize");
Result := pthread_attr_setinheritsched
(Attributes'Access, PTHREAD_DEFAULT_SCHED);
pragma Assert
(Result /= FUNC_ERR, "GNULLI failure---pthread_setinheritsched");
Result := pthread_attr_setsched
(Attributes'Access, SCHED_FIFO);
pragma Assert
(Result /= FUNC_ERR, "GNULLI failure---pthread_setinheritsched");
-- The following priority adjustment is a kludge to get around needing
-- root privileges to run at higher than 18 for FIFO or 19 for OTHER.
if (L_Priority > 18) then
L_Priority := 18;
elsif (L_Priority < 14) then
L_Priority := 14;
end if;
Result := pthread_attr_setprio
(Attributes'Access, int (L_Priority));
pragma Assert
(Result /= FUNC_ERR, "GNULLI failure---pthread_attr_setprio");
Result := pthread_create
(T.Thread'Access,
Attributes,
To_Start_Addr (LL_Wrapper'Address),
T.all'Address);
if Result = FUNC_ERR then
GNAT.IO.Put_Line ("pthread create failed");
raise Storage_Error;
end if;
pragma Assert (Result /= FUNC_ERR, "GNULLI failure---pthread_create");
Result := pthread_attr_destroy (Attributes'Access);
pragma Assert
(Result /= FUNC_ERR, "GNULLI failure---pthread_attr_destroy");
end Create_LL_Task;
-----------------
-- Exit_LL_Task --
------------------
procedure Exit_LL_Task is
begin
pthread_exit (System.Null_Address);
end Exit_LL_Task;
----------------
-- Abort_Task --
----------------
procedure Abort_Task (T : TCB_Ptr) is
Result : int;
begin
-- Result := pthread_kill (T.Thread);
-- pragma Assert
-- (Result /= FUNC_ERR, "GNULLI failure---pthread_kill");
null;
end Abort_Task;
----------------
-- Test_Abort --
----------------
-- This procedure does nothing. It is intended for systems without
-- asynchronous abortion, where the runtime system would have to
-- synchronously poll for pending abortions. This should be done
-- at least at every synchronization point.
procedure Test_Abort is
begin
null;
end Test_Abort;
---------------------------
-- Install_Abort_Handler --
---------------------------
procedure Install_Abort_Handler (Handler : Abort_Handler_Pointer) is
act : aliased RTE.struct_sigaction;
old_act : aliased RTE.struct_sigaction;
Result : POSIX_Error.Return_Code;
SA_SIGINFO : constant := 64;
use type POSIX_Error.Return_Code;
begin
Abort_Handler := Handler;
act.sa_flags := SA_SIGINFO;
act.sa_handler := Abort_Wrapper'Address;
RTE.sigemptyset (act.sa_mask'Access, Result);
pragma Assert (Result /= FUNC_ERR, "GNULLI failure---sigemptyset");
RTE.sigaction (Abort_Signal, act'Access, old_act'Access, Result);
pragma Assert (Result /= FUNC_ERR, "GNULLI failure---sigaction");
end Install_Abort_Handler;
-------------------
-- Abort_Wrapper --
-------------------
-- This is the handler called by the OS when an abort signal is
-- received; it in turn calls the handler installed by the client.
-- This procedure serves to isolate the client from the
-- implementation-specific calling conventions of asynchronous
-- handlers.
procedure Abort_Wrapper
(signo : Integer;
info : RTE.siginfo_ptr;
context : System.Address)
is
function Address_To_Call_State is new
Unchecked_Conversion (System.Address, Pre_Call_State);
begin
Abort_Handler (Address_To_Call_State (context));
end Abort_Wrapper;
---------------------------
-- Install_Error_Handler --
---------------------------
procedure Install_Error_Handler (Handler : System.Address) is
Temp : Address;
use Pthreads;
begin
-- Set up the soft links to tasking services used in the absence of
-- tasking. These replace tasking-free defaults.
Temp := TSL.Get_Jmpbuf_Address.all;
-- pthread_set_jumpbuf_address (Temp);
Temp := TSL.Get_Sec_Stack_Addr.all;
-- pthread_set_sec_stack_addr (Temp);
-- TSL.Get_Jmpbuf_Address := pthread_get_jumpbuf_address'Access;
-- TSL.Set_Jmpbuf_Address := pthread_set_jumpbuf_address'Access;
-- TSL.Get_Gnat_Exception := pthread_get_exception'Access;
-- TSL.Set_Gnat_Exception := pthread_set_exception'Access;
end Install_Error_Handler;
---------------
-- LL_Assert --
---------------
procedure LL_Assert (B : Boolean; M : String) is
begin
null;
end LL_Assert;
----------------
-- LL_Wrapper --
----------------
procedure LL_Wrapper (T : TCB_Ptr) is
Result : POSIX_Error.Return_Code;
Result1 : int;
Exc_Stack : String (1 .. 256);
Exc_Base : Address := Exc_Stack (Exc_Stack'Last)'Address + 1;
Old_Set : aliased RTE.Signal_Set;
begin
Result1 := pthread_setspecific (ATCB_Key, T.all'Address);
RTE.sigprocmask (
RTE.SIG_UNBLOCK, Unblocked_Signal_Mask'Access, Old_Set'Access, Result);
pragma Assert (
Result /= Failure, "GNULLI failure---sigprocmask");
-- Note that the following call may not return!
T.LL_Entry_Point (T.LL_Arg);
end LL_Wrapper;
--------------------------
-- Test and Set support --
--------------------------
procedure Initialize_TAS_Cell (Cell : out TAS_Cell) is
begin
Cell.Value := 0;
end Initialize_TAS_Cell;
procedure Finalize_TAS_Cell (Cell : in out TAS_Cell) is
begin
null;
end Finalize_TAS_Cell;
procedure Clear (Cell : in out TAS_Cell) is
begin
Cell.Value := 1;
end Clear;
procedure Test_And_Set (Cell : in out TAS_Cell; Result : out Boolean) is
Error : Boolean;
begin
Write_Lock (Test_And_Set_Mutex, Error);
if Cell.Value = 1 then
Result := False;
else
Result := True;
Cell.Value := 1;
end if;
Unlock (Test_And_Set_Mutex);
end Test_And_Set;
function Is_Set (Cell : in TAS_Cell) return Boolean is
begin
return Cell.Value = 1;
end Is_Set;
begin
Initialize_Lock (System.Any_Priority'Last, Test_And_Set_Mutex);
end System.Task_Primitives;

View file

@ -0,0 +1,298 @@
------------------------------------------------------------------------------
-- --
-- GNU ADA RUNTIME LIBRARY (GNARL) COMPONENTS --
-- --
-- S Y S T E M . T A S K _ P R I M I T I V E S --
-- --
-- S p e c --
-- --
-- $Revision: 1.1 $ --
-- --
-- Copyright (C) 1991,1992,1993,1994,1995,1996 Florida State University --
-- --
-- GNARL is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
-- ware Foundation; either version 2, or (at your option) any later ver- --
-- sion. GNARL is distributed in the hope that it will be useful, but WITH- --
-- OUT 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 distributed with GNARL; see file COPYING. If not, write --
-- to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, --
-- MA 02111-1307, USA. --
-- --
-- As a special exception, if other files instantiate generics from this --
-- unit, or you link this unit with other files to produce an executable, --
-- this unit does not by itself cause the resulting executable to be --
-- covered by the GNU General Public License. This exception does not --
-- however invalidate any other reasons why the executable file might be --
-- covered by the GNU Public License. --
-- --
-- GNARL was developed by the GNARL team at Florida State University. It is --
-- now maintained by Ada Core Technologies Inc. in cooperation with Florida --
-- State University (http://www.gnat.com). --
-- --
------------------------------------------------------------------------------
with Interfaces.C;
-- Used for Size_t;
with Interfaces.C.Pthreads;
-- Used for, size_t,
-- pthread_mutex_t,
-- pthread_cond_t,
-- pthread_t
with Interfaces.C.POSIX_RTE;
-- Used for, Signal,
-- siginfo_ptr,
with System.Task_Clock;
-- Used for, Stimespec
with Unchecked_Conversion;
pragma Elaborate_All (Interfaces.C.Pthreads);
with System.Task_Info;
package System.Task_Primitives is
-- Low level Task size and state definition
type LL_Task_Procedure_Access is access procedure (Arg : System.Address);
type Pre_Call_State is new System.Address;
type Task_Storage_Size is new Interfaces.C.size_t;
type Machine_Exceptions is new Interfaces.C.POSIX_RTE.Signal;
type Error_Information is new Interfaces.C.POSIX_RTE.siginfo_ptr;
type Lock is private;
type Condition_Variable is private;
-- The above types should both be limited. They are not due to a hack in
-- ATCB allocation which allocates a block of the correct size and then
-- assigns an initialized ATCB to it. This won't work with limited types.
-- When allocation is done with new, these can become limited once again.
-- ???
type Task_Control_Block is record
LL_Entry_Point : LL_Task_Procedure_Access;
LL_Arg : System.Address;
Thread : aliased Interfaces.C.Pthreads.pthread_t;
Stack_Size : Task_Storage_Size;
Stack_Limit : System.Address;
end record;
type TCB_Ptr is access all Task_Control_Block;
-- Task ATCB related and variables.
function Address_To_TCB_Ptr is new
Unchecked_Conversion (System.Address, TCB_Ptr);
procedure Initialize_LL_Tasks (T : TCB_Ptr);
-- Initialize GNULLI. T points to the Task Control Block that should
-- be initialized for use by the environment task.
function Self return TCB_Ptr;
-- Return a pointer to the Task Control Block of the calling task.
procedure Initialize_Lock (Prio : System.Any_Priority; L : in out Lock);
-- Initialize a lock object. Prio is the ceiling priority associated
-- with the lock.
procedure Finalize_Lock (L : in out Lock);
-- Finalize a lock object, freeing any resources allocated by the
-- corresponding Initialize_Lock.
procedure Write_Lock (L : in out Lock; Ceiling_Violation : out Boolean);
pragma Inline (Write_Lock);
-- Lock a lock object for write access to a critical section. After
-- this operation returns, the calling task owns the lock, and
-- no other Write_Lock or Read_Lock operation on the same object will
-- return the owner executes an Unlock operation on the same object.
procedure Read_Lock (L : in out Lock; Ceiling_Violation : out Boolean);
pragma Inline (Read_Lock);
-- Lock a lock object for read access to a critical section. After
-- this operation returns, the calling task owns the lock, and
-- no other Write_Lock operation on the same object will return until
-- the owner(s) execute Unlock operation(s) on the same object.
-- A Read_Lock to an owned lock object may return while the lock is
-- still owned, though an implementation may also implement
-- Read_Lock to have the same semantics.
procedure Unlock (L : in out Lock);
pragma Inline (Unlock);
-- Unlock a locked lock object. The results are undefined if the
-- calling task does not own the lock. Lock/Unlock operations must
-- be nested, that is, the argument to Unlock must be the object
-- most recently locked.
procedure Initialize_Cond (Cond : in out Condition_Variable);
-- Initialize a condition variable object.
procedure Finalize_Cond (Cond : in out Condition_Variable);
-- Finalize a condition variable object, recovering any resources
-- allocated for it by Initialize_Cond.
procedure Cond_Wait (Cond : in out Condition_Variable; L : in out Lock);
pragma Inline (Cond_Wait);
-- Wait on a condition variable. The mutex object L is unlocked
-- atomically, such that another task that is able to lock the mutex
-- can be assured that the wait has actually commenced, and that
-- a Cond_Signal operation will cause the waiting task to become
-- eligible for execution once again. Before Cond_Wait returns,
-- the waiting task will again lock the mutex. The waiting task may become
-- eligible for execution at any time, but will become eligible for
-- execution when a Cond_Signal operation is performed on the
-- same condition variable object. The effect of more than one
-- task waiting on the same condition variable is unspecified.
procedure Cond_Timed_Wait
(Cond : in out Condition_Variable;
L : in out Lock; Abs_Time : System.Task_Clock.Stimespec;
Timed_Out : out Boolean);
pragma Inline (Cond_Timed_Wait);
-- Wait on a condition variable, as for Cond_Wait, above. In addition,
-- the waiting task will become eligible for execution again
-- when the absolute time specified by Timed_Out arrives.
procedure Cond_Signal (Cond : in out Condition_Variable);
pragma Inline (Cond_Signal);
-- Wake up a task waiting on the condition variable object specified
-- by Cond, making it eligible for execution once again.
procedure Set_Priority (T : TCB_Ptr; Prio : System.Any_Priority);
pragma Inline (Set_Priority);
-- Set the priority of the task specified by T to P.
procedure Set_Own_Priority (Prio : System.Any_Priority);
pragma Inline (Set_Own_Priority);
-- Set the priority of the calling task to P.
function Get_Priority (T : TCB_Ptr) return System.Any_Priority;
pragma Inline (Get_Priority);
-- Return the priority of the task specified by T.
function Get_Own_Priority return System.Any_Priority;
pragma Inline (Get_Own_Priority);
-- Return the priority of the calling task.
procedure Create_LL_Task
(Priority : System.Any_Priority;
Stack_Size : Task_Storage_Size;
Task_Info : System.Task_Info.Task_Info_Type;
LL_Entry_Point : LL_Task_Procedure_Access;
Arg : System.Address;
T : TCB_Ptr);
-- Create a new low-level task with priority Priority. A new thread
-- of control is created with a stack size of at least Stack_Size,
-- and the procedure LL_Entry_Point is called with the argument Arg
-- from this new thread of control. The Task Control Block pointed
-- to by T is initialized to refer to this new task.
procedure Exit_LL_Task;
-- Exit a low-level task. The resources allocated for the task
-- by Create_LL_Task are recovered. The task no longer executes, and
-- the effects of further operations on task are unspecified.
procedure Abort_Task (T : TCB_Ptr);
-- Abort the task specified by T (the target task). This causes
-- the target task to asynchronously execute the handler procedure
-- installed by the target task using Install_Abort_Handler. The
-- effect of this operation is unspecified if there is no abort
-- handler procedure for the target task.
procedure Test_Abort;
-- ??? Obsolete? This is intended to allow implementation of
-- abortion and ATC in the absence of an asynchronous Abort_Task,
-- but I think that we decided that GNARL can handle this on
-- its own by making sure that there is an Undefer_Abortion at
-- every abortion synchronization point.
type Abort_Handler_Pointer is access procedure (Context : Pre_Call_State);
procedure Install_Abort_Handler (Handler : Abort_Handler_Pointer);
-- Install an abort handler procedure. This procedure is called
-- asynchronously by the calling task whenever a call to Abort_Task
-- specifies the calling task as the target. If the abort handler
-- procedure is asynchronously executed during a GNULLI operation
-- and then calls some other GNULLI operation, the effect is unspecified.
procedure Install_Error_Handler (Handler : System.Address);
-- Install an error handler for the calling task. The handler will
-- be called synchronously if an error is encountered during the
-- execution of the calling task.
procedure LL_Assert (B : Boolean; M : String);
-- If B is False, print the string M to the console and halt the
-- program.
Task_Wrapper_Frame : constant Integer := 72;
-- This is the size of the frame for the Pthread_Wrapper procedure.
type Proc is access procedure (Addr : System.Address);
-- Test and Set support
type TAS_Cell is private;
-- On some systems we can not assume that an arbitrary memory location
-- can be used in an atomic test and set instruction (e.g. on some
-- multiprocessor machines, only memory regions are cache interlocked).
-- TAS_Cell is private to facilitate adaption to a variety of
-- implementations.
procedure Initialize_TAS_Cell (Cell : out TAS_Cell);
pragma Inline (Initialize_TAS_Cell);
-- Initialize a Test And Set Cell. On some targets this will allocate
-- a system-level lock object from a special pool. For most systems,
-- this is a nop.
procedure Finalize_TAS_Cell (Cell : in out TAS_Cell);
pragma Inline (Finalize_TAS_Cell);
-- Finalize a Test and Set cell, freeing any resources allocated by the
-- corresponding Initialize_TAS_Cell.
procedure Clear (Cell : in out TAS_Cell);
pragma Inline (Clear);
-- Set the state of the named TAS_Cell such that a subsequent call to
-- Is_Set will return False. This operation must be atomic with
-- respect to the Is_Set and Test_And_Set operations for the same
-- cell.
procedure Test_And_Set (Cell : in out TAS_Cell; Result : out Boolean);
pragma Inline (Test_And_Set);
-- Modify the state of the named TAS_Cell such that a subsequent call
-- to Is_Set will return True. Result is set to True if Is_Set
-- was False prior to the call, False otherwise. This operation must
-- be atomic with respect to the Clear and Is_Set operations for the
-- same cell.
function Is_Set (Cell : in TAS_Cell) return Boolean;
pragma Inline (Is_Set);
-- Returns the current value of the named TAS_Cell. This operation
-- must be atomic with respect to the Clear and Test_And_Set operations
-- for the same cell.
private
type Lock is
record
mutex : aliased Interfaces.C.Pthreads.pthread_mutex_t;
end record;
type Condition_Variable is
record
CV : aliased Interfaces.C.Pthreads.pthread_cond_t;
end record;
type TAS_Cell is
record
Value : aliased Interfaces.C.unsigned := 0;
end record;
end System.Task_Primitives;

View file

@ -0,0 +1,193 @@
type LL_Task_Procedure_Access is access procedure (Arg : System.Address);
function Body_Required
(N : Node_Id) return Boolean is
begin
pragma Assert (False
or else NT (N).Nkind = N_Compilation_Unit);
return Flag13 (N);
end Body_Required;
type Type_Specific_Data is record
Idepth : Natural;
Expanded_Name : Cstring_Ptr;
External_Tag : Cstring_Ptr;
HT_Link : Tag;
Ancestor_Tags : Tag_Table (Natural);
end record;
function "abs" (Right : Complex) return Real'Base renames Modulus;
type Barrier_Function_Pointer is access
function
(O : System.Address;
E : Protected_Entry_Index)
return Boolean;
function "=" (L, R : System.Address) return Boolean
renames System."=";
type usfreelock_ptr is access
procedure (lock : ulock_t; arena : usptr_t_ptr);
function p pragma Import (C,
"pthread_mutexattr_setprio_ceiling",
"pthread_mutexattr_setprio_ceiling");
pragma Import ()
procedure LL_Wrapper (T : TCB_Ptr);
function p ("p");
-- This file is an Ada file containing test data
-- for etags (Ada83 and Ada95 support).
package Pkg1 is
type Private_T is private;
package Inner1 is
procedure Private_T;
end Inner1;
package Inner2 is
task Private_T;
end Inner2;
type Public_T is
record
A : Integer;
B : Integer;
end record;
procedure Pkg1_Proc1;
procedure Pkg1_Proc2 (I : Integer);
function Pkg1_Func1 return Boolean;
function Pkg1_Func2 (Ijk : Integer; Z : Integer) return Natural;
package Pkg1_Pkg1 is
procedure Pkg1_Pkg1_Proc1;
end Pkg1_Pkg1;
task type Task_Type is
entry Entry1;
entry Entry2 (I : Integer);
end;
private
type Private_T is
record
Z : Integer;
W : Boolean;
end record;
end Pkg1;
package body Pkg1 is
procedure Pkg1_Proc1 is
begin
null;
end;
package body Inner1 is
procedure Private_T is
begin
null;
end;
end Inner1;
package body Inner2 is
task body Private_T is
begin
loop
null;
end loop;
end;
end Inner2;
task body Task_Type is
begin
select
accept Entry1 do
null;
end;
or
accept Entry2 (I : Integer) do
null;
end;
end select;
end;
procedure Pkg1_Proc2 (I : Integer) is
begin
null;
end Pkg1_Proc2;
function Pkg1_Func1 return Boolean is separate;
function Pkg1_Func2 (Ijk : Integer; Z : Integer) return Natural is
begin
return 1;
end;
package body Pkg1_Pkg1 is separate;
end Pkg1;
separate (Pkg1)
package body Pkg1_Pkg1 is
procedure Pkg1_Pkg1_Proc1 is
begin
null;
end;
end Pkg1_Pkg1;
separate (Pkg1)
function Pkg1_Func1 return Boolean is
begin
return False;
end;
-- from now on, this is Ada 95 specific.
package Truc is
I : Integer;
end Truc;
package Truc.Bidule is
protected Bidule is
entry Basar;
end Bidule;
protected type Machin_T is
entry Truc;
end Machin_T;
end Truc.Bidule;
package body Truc.Bidule is
protected body Bidule is
entry Basar is
begin
null;
end;
end Bidule;
protected Machin_T is
entry Truc is
begin
null;
end;
end Machin_T;
end Truc.Bidule;

View file

@ -0,0 +1,153 @@
-- This file is an Ada file containing test data
-- for etags (Ada83 and Ada95 support).
package Pkg1 is
type Private_T is private;
package Inner1 is
procedure Private_T;
end Inner1;
package Inner2 is
task Private_T;
end Inner2;
type Public_T is
record
A : Integer;
B : Integer;
end record;
procedure Pkg1_Proc1;
procedure Pkg1_Proc2 (I : Integer);
function Pkg1_Func1 return Boolean;
function Pkg1_Func2 (Ijk : Integer; Z : Integer) return Natural;
package Pkg1_Pkg1 is
procedure Pkg1_Pkg1_Proc1;
end Pkg1_Pkg1;
task type Task_Type is
entry Entry1;
entry Entry2 (I : Integer);
end;
private
type Private_T is
record
Z : Integer;
W : Boolean;
end record;
end Pkg1;
package body Pkg1 is
procedure Pkg1_Proc1 is
begin
null;
end;
package body Inner1 is
procedure Private_T is
begin
null;
end;
end Inner1;
package body Inner2 is
task body Private_T is
begin
loop
null;
end loop;
end;
end Inner2;
task body Task_Type is
begin
select
accept Entry1 do
null;
end;
or
accept Entry2 (I : Integer) do
null;
end;
end select;
end;
procedure Pkg1_Proc2 (I : Integer) is
begin
null;
end Pkg1_Proc2;
function Pkg1_Func1 return Boolean is separate;
function Pkg1_Func2 (Ijk : Integer; Z : Integer) return Natural is
begin
return 1;
end;
package body Pkg1_Pkg1 is separate;
end Pkg1;
separate (Pkg1)
package body Pkg1_Pkg1 is
procedure Pkg1_Pkg1_Proc1 is
begin
null;
end;
end Pkg1_Pkg1;
separate (Pkg1)
function Pkg1_Func1 return Boolean is
begin
return False;
end;
-- from now on, this is Ada 95 specific.
package Truc is
I : Integer;
end Truc;
with Pkg1;
package Truc.Bidule is
use type Pkg1.Public_T;
use Pkg1;
use
type Pkg1.Public_T;
use -- comment
type -- comment
Pkg1.Public_T;
protected Bidule is
entry Basar;
private
Ok : Boolean;
end Bidule;
protected type Machin_T is
entry Truc;
private
Ok : Boolean;
end Machin_T;
end Truc.Bidule;
package body Truc.Bidule is
protected body Bidule is
entry Basar when Ok is
begin
null;
end;
end Bidule;
protected body Machin_T is
entry Truc when Ok is
begin
null;
end;
end Machin_T;
end Truc.Bidule;

5
test/etags/c-src/a/b/b.c Normal file
View file

@ -0,0 +1,5 @@
#define this that
#line 33 "../c/c.web"
#define questo quello

616
test/etags/c-src/abbrev.c Normal file
View file

@ -0,0 +1,616 @@
/* Primitives for word-abbrev mode.
Copyright (C) 1985, 1986, 1993, 1996, 1998 Free Software Foundation, Inc.
This file is part of GNU Emacs.
GNU Emacs 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.
GNU Emacs 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 GNU Emacs; see the file COPYING. If not, write to
the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#include <config.h>
#include <stdio.h>
#include "lisp.h"
#include "commands.h"
#include "buffer.h"
#include "window.h"
#include "charset.h"
#include "syntax.h"
/* An abbrev table is an obarray.
Each defined abbrev is represented by a symbol in that obarray
whose print name is the abbreviation.
The symbol's value is a string which is the expansion.
If its function definition is non-nil, it is called
after the expansion is done.
The plist slot of the abbrev symbol is its usage count. */
/* List of all abbrev-table name symbols:
symbols whose values are abbrev tables. */
Lisp_Object Vabbrev_table_name_list;
/* The table of global abbrevs. These are in effect
in any buffer in which abbrev mode is turned on. */
Lisp_Object Vglobal_abbrev_table;
/* The local abbrev table used by default (in Fundamental Mode buffers) */
Lisp_Object Vfundamental_mode_abbrev_table;
/* Set nonzero when an abbrev definition is changed */
int abbrevs_changed;
int abbrev_all_caps;
/* Non-nil => use this location as the start of abbrev to expand
(rather than taking the word before point as the abbrev) */
Lisp_Object Vabbrev_start_location;
/* Buffer that Vabbrev_start_location applies to */
Lisp_Object Vabbrev_start_location_buffer;
/* The symbol representing the abbrev most recently expanded */
Lisp_Object Vlast_abbrev;
/* A string for the actual text of the abbrev most recently expanded.
This has more info than Vlast_abbrev since case is significant. */
Lisp_Object Vlast_abbrev_text;
/* Character address of start of last abbrev expanded */
int last_abbrev_point;
/* Hook to run before expanding any abbrev. */
Lisp_Object Vpre_abbrev_expand_hook, Qpre_abbrev_expand_hook;
DEFUN ("make-abbrev-table", Fmake_abbrev_table, Smake_abbrev_table, 0, 0, 0,
"Create a new, empty abbrev table object.")
()
{
return Fmake_vector (make_number (59), make_number (0));
}
DEFUN ("clear-abbrev-table", Fclear_abbrev_table, Sclear_abbrev_table, 1, 1, 0,
"Undefine all abbrevs in abbrev table TABLE, leaving it empty.")
(table)
Lisp_Object table;
{
int i, size;
CHECK_VECTOR (table, 0);
size = XVECTOR (table)->size;
abbrevs_changed = 1;
for (i = 0; i < size; i++)
XVECTOR (table)->contents[i] = make_number (0);
return Qnil;
}
DEFUN ("define-abbrev", Fdefine_abbrev, Sdefine_abbrev, 3, 5, 0,
"Define an abbrev in TABLE named NAME, to expand to EXPANSION and call HOOK.\n\
NAME must be a string.\n\
EXPANSION should usually be a string.\n\
To undefine an abbrev, define it with EXPANSION = nil.\n\
If HOOK is non-nil, it should be a function of no arguments;\n\
it is called after EXPANSION is inserted.\n\
If EXPANSION is not a string, the abbrev is a special one,\n\
which does not expand in the usual way but only runs HOOK.\n\
COUNT, if specified, initializes the abbrev's usage-count\n\
which is incremented each time the abbrev is used.")
(table, name, expansion, hook, count)
Lisp_Object table, name, expansion, hook, count;
{
Lisp_Object sym, oexp, ohook, tem;
CHECK_VECTOR (table, 0);
CHECK_STRING (name, 1);
if (NILP (count))
count = make_number (0);
else
CHECK_NUMBER (count, 0);
sym = Fintern (name, table);
oexp = XSYMBOL (sym)->value;
ohook = XSYMBOL (sym)->function;
if (!((EQ (oexp, expansion)
|| (STRINGP (oexp) && STRINGP (expansion)
&& (tem = Fstring_equal (oexp, expansion), !NILP (tem))))
&&
(EQ (ohook, hook)
|| (tem = Fequal (ohook, hook), !NILP (tem)))))
abbrevs_changed = 1;
Fset (sym, expansion);
Ffset (sym, hook);
Fsetplist (sym, count);
return name;
}
DEFUN ("define-global-abbrev", Fdefine_global_abbrev, Sdefine_global_abbrev, 2, 2,
"sDefine global abbrev: \nsExpansion for %s: ",
"Define ABBREV as a global abbreviation for EXPANSION.")
(abbrev, expansion)
Lisp_Object abbrev, expansion;
{
Fdefine_abbrev (Vglobal_abbrev_table, Fdowncase (abbrev),
expansion, Qnil, make_number (0));
return abbrev;
}
DEFUN ("define-mode-abbrev", Fdefine_mode_abbrev, Sdefine_mode_abbrev, 2, 2,
"sDefine mode abbrev: \nsExpansion for %s: ",
"Define ABBREV as a mode-specific abbreviation for EXPANSION.")
(abbrev, expansion)
Lisp_Object abbrev, expansion;
{
if (NILP (current_buffer->abbrev_table))
error ("Major mode has no abbrev table");
Fdefine_abbrev (current_buffer->abbrev_table, Fdowncase (abbrev),
expansion, Qnil, make_number (0));
return abbrev;
}
DEFUN ("abbrev-symbol", Fabbrev_symbol, Sabbrev_symbol, 1, 2, 0,
"Return the symbol representing abbrev named ABBREV.\n\
This symbol's name is ABBREV, but it is not the canonical symbol of that name;\n\
it is interned in an abbrev-table rather than the normal obarray.\n\
The value is nil if that abbrev is not defined.\n\
Optional second arg TABLE is abbrev table to look it up in.\n\
The default is to try buffer's mode-specific abbrev table, then global table.")
(abbrev, table)
Lisp_Object abbrev, table;
{
Lisp_Object sym;
CHECK_STRING (abbrev, 0);
if (!NILP (table))
sym = Fintern_soft (abbrev, table);
else
{
sym = Qnil;
if (!NILP (current_buffer->abbrev_table))
sym = Fintern_soft (abbrev, current_buffer->abbrev_table);
if (NILP (XSYMBOL (sym)->value))
sym = Qnil;
if (NILP (sym))
sym = Fintern_soft (abbrev, Vglobal_abbrev_table);
}
if (NILP (XSYMBOL (sym)->value)) return Qnil;
return sym;
}
DEFUN ("abbrev-expansion", Fabbrev_expansion, Sabbrev_expansion, 1, 2, 0,
"Return the string that ABBREV expands into in the current buffer.\n\
Optionally specify an abbrev table as second arg;\n\
then ABBREV is looked up in that table only.")
(abbrev, table)
Lisp_Object abbrev, table;
{
Lisp_Object sym;
sym = Fabbrev_symbol (abbrev, table);
if (NILP (sym)) return sym;
return Fsymbol_value (sym);
}
/* Expand the word before point, if it is an abbrev.
Returns 1 if an expansion is done. */
DEFUN ("expand-abbrev", Fexpand_abbrev, Sexpand_abbrev, 0, 0, "",
"Expand the abbrev before point, if there is an abbrev there.\n\
Effective when explicitly called even when `abbrev-mode' is nil.\n\
Returns the abbrev symbol, if expansion took place.")
()
{
register char *buffer, *p;
int wordstart, wordend;
register int wordstart_byte, wordend_byte, idx;
int whitecnt;
int uccount = 0, lccount = 0;
register Lisp_Object sym;
Lisp_Object expansion, hook, tem;
Lisp_Object value;
value = Qnil;
if (!NILP (Vrun_hooks))
call1 (Vrun_hooks, Qpre_abbrev_expand_hook);
wordstart = 0;
if (!(BUFFERP (Vabbrev_start_location_buffer)
&& XBUFFER (Vabbrev_start_location_buffer) == current_buffer))
Vabbrev_start_location = Qnil;
if (!NILP (Vabbrev_start_location))
{
tem = Vabbrev_start_location;
CHECK_NUMBER_COERCE_MARKER (tem, 0);
wordstart = XINT (tem);
Vabbrev_start_location = Qnil;
if (wordstart < BEGV || wordstart > ZV)
wordstart = 0;
if (wordstart && wordstart != ZV)
{
wordstart_byte = CHAR_TO_BYTE (wordstart);
if (FETCH_BYTE (wordstart_byte) == '-')
del_range (wordstart, wordstart + 1);
}
}
if (!wordstart)
wordstart = scan_words (PT, -1);
if (!wordstart)
return value;
wordstart_byte = CHAR_TO_BYTE (wordstart);
wordend = scan_words (wordstart, 1);
if (!wordend)
return value;
if (wordend > PT)
wordend = PT;
wordend_byte = CHAR_TO_BYTE (wordend);
whitecnt = PT - wordend;
if (wordend <= wordstart)
return value;
p = buffer = (char *) alloca (wordend_byte - wordstart_byte);
for (idx = wordstart_byte; idx < wordend_byte; idx++)
{
/* ??? This loop needs to go by characters! */
register int c = FETCH_BYTE (idx);
if (UPPERCASEP (c))
c = DOWNCASE (c), uccount++;
else if (! NOCASEP (c))
lccount++;
*p++ = c;
}
if (VECTORP (current_buffer->abbrev_table))
sym = oblookup (current_buffer->abbrev_table, buffer,
wordend - wordstart, wordend_byte - wordstart_byte);
else
XSETFASTINT (sym, 0);
if (INTEGERP (sym) || NILP (XSYMBOL (sym)->value))
sym = oblookup (Vglobal_abbrev_table, buffer,
wordend - wordstart, wordend_byte - wordstart_byte);
if (INTEGERP (sym) || NILP (XSYMBOL (sym)->value))
return value;
if (INTERACTIVE && !EQ (minibuf_window, selected_window))
{
/* Add an undo boundary, in case we are doing this for
a self-inserting command which has avoided making one so far. */
SET_PT (wordend);
Fundo_boundary ();
}
Vlast_abbrev_text
= Fbuffer_substring (make_number (wordstart), make_number (wordend));
/* Now sym is the abbrev symbol. */
Vlast_abbrev = sym;
value = sym;
last_abbrev_point = wordstart;
if (INTEGERP (XSYMBOL (sym)->plist))
XSETINT (XSYMBOL (sym)->plist,
XINT (XSYMBOL (sym)->plist) + 1); /* Increment use count */
/* If this abbrev has an expansion, delete the abbrev
and insert the expansion. */
expansion = XSYMBOL (sym)->value;
if (STRINGP (expansion))
{
SET_PT (wordstart);
del_range_both (wordstart, wordstart_byte, wordend, wordend_byte, 1);
insert_from_string (expansion, 0, 0, XSTRING (expansion)->size,
STRING_BYTES (XSTRING (expansion)), 1);
SET_PT (PT + whitecnt);
if (uccount && !lccount)
{
/* Abbrev was all caps */
/* If expansion is multiple words, normally capitalize each word */
/* This used to be if (!... && ... >= ...) Fcapitalize; else Fupcase
but Megatest 68000 compiler can't handle that */
if (!abbrev_all_caps)
if (scan_words (PT, -1) > scan_words (wordstart, 1))
{
Fupcase_initials_region (make_number (wordstart),
make_number (PT));
goto caped;
}
/* If expansion is one word, or if user says so, upcase it all. */
Fupcase_region (make_number (wordstart), make_number (PT));
caped: ;
}
else if (uccount)
{
/* Abbrev included some caps. Cap first initial of expansion */
int pos = wordstart_byte;
/* Find the initial. */
while (pos < PT_BYTE
&& SYNTAX (*BUF_BYTE_ADDRESS (current_buffer, pos)) != Sword)
pos++;
/* Change just that. */
pos = BYTE_TO_CHAR (pos);
Fupcase_initials_region (make_number (pos), make_number (pos + 1));
}
}
hook = XSYMBOL (sym)->function;
if (!NILP (hook))
{
Lisp_Object expanded, prop;
/* If the abbrev has a hook function, run it. */
expanded = call0 (hook);
/* In addition, if the hook function is a symbol with a a
non-nil `no-self-insert' property, let the value it returned
specify whether we consider that an expansion took place. If
it returns nil, no expansion has been done. */
if (SYMBOLP (hook)
&& NILP (expanded)
&& (prop = Fget (hook, intern ("no-self-insert")),
!NILP (prop)))
value = Qnil;
}
return value;
}
DEFUN ("unexpand-abbrev", Funexpand_abbrev, Sunexpand_abbrev, 0, 0, "",
"Undo the expansion of the last abbrev that expanded.\n\
This differs from ordinary undo in that other editing done since then\n\
is not undone.")
()
{
int opoint = PT;
int adjust = 0;
if (last_abbrev_point < BEGV
|| last_abbrev_point > ZV)
return Qnil;
SET_PT (last_abbrev_point);
if (STRINGP (Vlast_abbrev_text))
{
/* This isn't correct if Vlast_abbrev->function was used
to do the expansion */
Lisp_Object val;
int zv_before;
val = XSYMBOL (Vlast_abbrev)->value;
if (!STRINGP (val))
error ("value of abbrev-symbol must be a string");
zv_before = ZV;
del_range_byte (PT_BYTE, PT_BYTE + STRING_BYTES (XSTRING (val)), 1);
/* Don't inherit properties here; just copy from old contents. */
insert_from_string (Vlast_abbrev_text, 0, 0,
XSTRING (Vlast_abbrev_text)->size,
STRING_BYTES (XSTRING (Vlast_abbrev_text)), 0);
Vlast_abbrev_text = Qnil;
/* Total number of characters deleted. */
adjust = ZV - zv_before;
}
SET_PT (last_abbrev_point < opoint ? opoint + adjust : opoint);
return Qnil;
}
static void
write_abbrev (sym, stream)
Lisp_Object sym, stream;
{
Lisp_Object name;
if (NILP (XSYMBOL (sym)->value))
return;
insert (" (", 5);
XSETSTRING (name, XSYMBOL (sym)->name);
Fprin1 (name, stream);
insert (" ", 1);
Fprin1 (XSYMBOL (sym)->value, stream);
insert (" ", 1);
Fprin1 (XSYMBOL (sym)->function, stream);
insert (" ", 1);
Fprin1 (XSYMBOL (sym)->plist, stream);
insert (")\n", 2);
}
static void
describe_abbrev (sym, stream)
Lisp_Object sym, stream;
{
Lisp_Object one;
if (NILP (XSYMBOL (sym)->value))
return;
one = make_number (1);
Fprin1 (Fsymbol_name (sym), stream);
Findent_to (make_number (15), one);
Fprin1 (XSYMBOL (sym)->plist, stream);
Findent_to (make_number (20), one);
Fprin1 (XSYMBOL (sym)->value, stream);
if (!NILP (XSYMBOL (sym)->function))
{
Findent_to (make_number (45), one);
Fprin1 (XSYMBOL (sym)->function, stream);
}
Fterpri (stream);
}
DEFUN ("insert-abbrev-table-description", Finsert_abbrev_table_description,
Sinsert_abbrev_table_description, 1, 2, 0,
"Insert before point a full description of abbrev table named NAME.\n\
NAME is a symbol whose value is an abbrev table.\n\
If optional 2nd arg READABLE is non-nil, a human-readable description\n\
is inserted. Otherwise the description is an expression,\n\
a call to `define-abbrev-table', which would\n\
define the abbrev table NAME exactly as it is currently defined.")
(name, readable)
Lisp_Object name, readable;
{
Lisp_Object table;
Lisp_Object stream;
CHECK_SYMBOL (name, 0);
table = Fsymbol_value (name);
CHECK_VECTOR (table, 0);
XSETBUFFER (stream, current_buffer);
if (!NILP (readable))
{
insert_string ("(");
Fprin1 (name, stream);
insert_string (")\n\n");
map_obarray (table, describe_abbrev, stream);
insert_string ("\n\n");
}
else
{
insert_string ("(define-abbrev-table '");
Fprin1 (name, stream);
insert_string (" '(\n");
map_obarray (table, write_abbrev, stream);
insert_string (" ))\n\n");
}
return Qnil;
}
DEFUN ("define-abbrev-table", Fdefine_abbrev_table, Sdefine_abbrev_table,
2, 2, 0,
"Define TABLENAME (a symbol) as an abbrev table name.\n\
Define abbrevs in it according to DEFINITIONS, which is a list of elements\n\
of the form (ABBREVNAME EXPANSION HOOK USECOUNT).")
(tablename, definitions)
Lisp_Object tablename, definitions;
{
Lisp_Object name, exp, hook, count;
Lisp_Object table, elt;
CHECK_SYMBOL (tablename, 0);
table = Fboundp (tablename);
if (NILP (table) || (table = Fsymbol_value (tablename), NILP (table)))
{
table = Fmake_abbrev_table ();
Fset (tablename, table);
Vabbrev_table_name_list = Fcons (tablename, Vabbrev_table_name_list);
}
CHECK_VECTOR (table, 0);
for (; !NILP (definitions); definitions = Fcdr (definitions))
{
elt = Fcar (definitions);
name = Fcar (elt); elt = Fcdr (elt);
exp = Fcar (elt); elt = Fcdr (elt);
hook = Fcar (elt); elt = Fcdr (elt);
count = Fcar (elt);
Fdefine_abbrev (table, name, exp, hook, count);
}
return Qnil;
}
void
syms_of_abbrev ()
{
DEFVAR_LISP ("abbrev-table-name-list", &Vabbrev_table_name_list,
"List of symbols whose values are abbrev tables.");
Vabbrev_table_name_list = Fcons (intern ("fundamental-mode-abbrev-table"),
Fcons (intern ("global-abbrev-table"),
Qnil));
DEFVAR_LISP ("global-abbrev-table", &Vglobal_abbrev_table,
"The abbrev table whose abbrevs affect all buffers.\n\
Each buffer may also have a local abbrev table.\n\
If it does, the local table overrides the global one\n\
for any particular abbrev defined in both.");
Vglobal_abbrev_table = Fmake_abbrev_table ();
DEFVAR_LISP ("fundamental-mode-abbrev-table", &Vfundamental_mode_abbrev_table,
"The abbrev table of mode-specific abbrevs for Fundamental Mode.");
Vfundamental_mode_abbrev_table = Fmake_abbrev_table ();
current_buffer->abbrev_table = Vfundamental_mode_abbrev_table;
buffer_defaults.abbrev_table = Vfundamental_mode_abbrev_table;
DEFVAR_LISP ("last-abbrev", &Vlast_abbrev,
"The abbrev-symbol of the last abbrev expanded. See `abbrev-symbol'.");
DEFVAR_LISP ("last-abbrev-text", &Vlast_abbrev_text,
"The exact text of the last abbrev expanded.\n\
nil if the abbrev has already been unexpanded.");
DEFVAR_INT ("last-abbrev-location", &last_abbrev_point,
"The location of the start of the last abbrev expanded.");
Vlast_abbrev = Qnil;
Vlast_abbrev_text = Qnil;
last_abbrev_point = 0;
DEFVAR_LISP ("abbrev-start-location", &Vabbrev_start_location,
"Buffer position for `expand-abbrev' to use as the start of the abbrev.\n\
nil means use the word before point as the abbrev.\n\
Calling `expand-abbrev' sets this to nil.");
Vabbrev_start_location = Qnil;
DEFVAR_LISP ("abbrev-start-location-buffer", &Vabbrev_start_location_buffer,
"Buffer that `abbrev-start-location' has been set for.\n\
Trying to expand an abbrev in any other buffer clears `abbrev-start-location'.");
Vabbrev_start_location_buffer = Qnil;
DEFVAR_PER_BUFFER ("local-abbrev-table", &current_buffer->abbrev_table, Qnil,
"Local (mode-specific) abbrev table of current buffer.");
DEFVAR_BOOL ("abbrevs-changed", &abbrevs_changed,
"Set non-nil by defining or altering any word abbrevs.\n\
This causes `save-some-buffers' to offer to save the abbrevs.");
abbrevs_changed = 0;
DEFVAR_BOOL ("abbrev-all-caps", &abbrev_all_caps,
"*Set non-nil means expand multi-word abbrevs all caps if abbrev was so.");
abbrev_all_caps = 0;
DEFVAR_LISP ("pre-abbrev-expand-hook", &Vpre_abbrev_expand_hook,
"Function or functions to be called before abbrev expansion is done.\n\
This is the first thing that `expand-abbrev' does, and so this may change\n\
the current abbrev table before abbrev lookup happens.");
Vpre_abbrev_expand_hook = Qnil;
Qpre_abbrev_expand_hook = intern ("pre-abbrev-expand-hook");
staticpro (&Qpre_abbrev_expand_hook);
defsubr (&Smake_abbrev_table);
defsubr (&Sclear_abbrev_table);
defsubr (&Sdefine_abbrev);
defsubr (&Sdefine_global_abbrev);
defsubr (&Sdefine_mode_abbrev);
defsubr (&Sabbrev_expansion);
defsubr (&Sabbrev_symbol);
defsubr (&Sexpand_abbrev);
defsubr (&Sunexpand_abbrev);
defsubr (&Sinsert_abbrev_table_description);
defsubr (&Sdefine_abbrev_table);
}

169
test/etags/c-src/c.c Normal file
View file

@ -0,0 +1,169 @@
T f(){if(x){}
}T i;
// The next two functions must be kept together
void bar() {while(0) {}}
int foobar() {;}
struct interface *
interface_locate(void)
{ return 0; }
#line 123 "c.c"
// 7.4: string literal in #line directive shall be a character string
// literal.
//E t_6_062.cpp(21): warning: ill formed #line directive: 123 L"wide"
#line 123 L"wide.c"
#line 123 L"wide.c"
#line 123L"wide.c"
void (*fa) (void);
void (__attribute__((noreturn)) *fb) (void);
extern int
my_printf (void *my_object, const char *my_format, ...)
__attribute__ ((format (printf, 2, 3)));
void fatala () __attribute__ ((noreturn));
void fatalb ();
max (int a, int b)
{ if (a > b) return a; else return b; }
struct bar {
char z;
struct foo f;
};
__attribute__ ((always_inline)) max (int a, int b)
{ if (a > b) return a; else return b }
extern int old_var __attribute__ ((deprecated));
struct foo
{
char a;
int x[2] __attribute__ ((packed));
};
char stack[10000] __attribute__ ((section ("STACK"))) = { 0 };
struct S { short f[3]; } __attribute__ ((aligned (8)));
typedef union
{
int *__ip;
union wait *__up;
} wait_status_ptr_t __attribute__ ((__transparent_union__));
Some_Class A __attribute__ ((init_priority (2000)));
typedef T1 T3 __attribute__ ((deprecated));
T3 z __attribute__ ((deprecated));
typedef int more_aligned_int __attribute__ ((aligned (8)));
struct S __attribute__ ((vector_size (16))) foo;
int foo __attribute__ ((vector_size (16)));
char *__attribute__((aligned(8))) *f;
int i __attribute__ ((visibility ("hidden")));
extern void foobar (void) __attribute__ ((section ("bar")));
typedef struct cacheLRUEntry_s
{
U16 next;
U16 prev;
}
__attribute__ ((packed)) cacheLRUEntry_t;
struct foo {
int x;
char a, b, c, d;
} __attribute__((packed));
void __attribute__ ((visibility ("protected")))
f1 () { /* Do something. */; }
void f2 () { /* Do something. */; }
__attribute__((noreturn)) void d0 (void),
__attribute__((format(printf, 1, 2))) d1 (const char *, ...),
d2 (void);
int x __attribute__ ((aligned (16))) = 0;
struct foo { int x[2] __attribute__ ((aligned (8))); };
short array[3] __attribute__ ((aligned));
asm(" section 10");
int f
() {}
DEAFUN ("expand-file-name", Fexpand_file_name, Sexpand_file_name, 1, 2, 0,
"name.")
(name, defalt)
Lisp_Object name, defalt;
{
unsigned char *nm;
}
XDEFUN ("x-get-selection-internal", Fx_get_selection_internal,
Sx_get_selection_internal, 2, 2, 0, "")
{}
DEFUN ("x-get-selection-internal", Fx_get_selection_internal,
Sx_get_selection_internal, 2, 2, 0, "")
{}
/* The next two are not tagged correctly. To prevent this, the code in
Emacs should contain the two first args of DEFUN on the same line. */
DEFUN ("x-get-selection-internal",
Fx_get_selection_internal, Sx_get_selection_internal, 2, 2, 0, "")
{}
DEFUN
("y-get-selection-internal",
Fy_get_selection_internal, Sy_get_selection_internal, 2, 2, 0, "")
{}
defun_func1()
{}
DEFUN_func2()
{}
typedef int bool;
bool funcboo ()
{}
static void (*lang_func) () = NULL;
struct my_struct {
};
typedef struct my_struct my_typedef;
int bla ()
{
PrkList ExistingOperations =
ProcedureOperationSelections(PrkNull, CalledFromDomain);
}
a()
b c;
{}
int func1
(a,b,c,d) {};
static struct cca_control init_control = { 0 };
static tpcmd rbtp [RB_TPSZ];
static byte ring1 [(RBUFNO + 1) + 8];
static byte ring2 [(RBUFNO + 1) * sizeof (struct le_md) + 8];
request request (a, b)
{
}
int func2 (a,b
c,d) {};
int wrongfunc
aaa;
struct wrongstruct
bbb;
struct sss1 {};
struct sss2
{
struct ss3
{
};
};
struct a b;
struct aa *b;
struct aaa
**b;
caccacacca (a,b,c,d,e,f,g)
struct aa *b;
{
}
a ()
{
typedef struct aa {} aaa;
}
static void inita () {}
node *lasta = NULL;
b ()
{
typedef int bb;
}
static void initb () {}
node *lastb = NULL;
typedef enum { REG_ENOSYS = -1, aa } reg_errcode_t;

View file

@ -0,0 +1,107 @@
/* Date: Thu, 05 Aug 1993 20:28:03 +0200
From: "Tom R.Hageman" <tom@basil.icce.rug.nl>
Subject: more etags torture;-) [etags 7.3 patch#3]
To: pot@CNUCE.CNR.IT
Hi,
This test file illustrates some more problems with etags (7.3):
1. parentheses are confusing,
2. preprocessor directives can disrupt other state machines. */
/* A small torture test for etags. */
/* The classic parenthesis nightmare, based on signal(). */
void
(*tag1 (sig, handler)) ()
int sig;
void (*handler) ();
{
(*handler)(sig);
return handler;
}
#define notag2 void
/* The classic, with user-defined return type. */
notag2
(*tag2 (sig, handler)) ()
int sig;
void (*handler) ();
{
(*handler)(sig);
return handler;
}
/* The classic, in ANSI C style. */
void
(*tag3 (int sig, void (*handler) (int))) (int)
{
(*handler)(sig);
return handler;
}
#define notag4 void
/* The classic, with user-defined return type, in ANSI C style. */
notag4
(*tag4 (int sig, void (*handler) (int))) (int)
{
(*handler)(sig);
return handler;
}
/* A less tortuous example. */
void
tag5 (handler, arg)
void (*handler)();
void *arg;
{
(*handler)(arg);
}
/* A less tortuous example, in ANSI C style. */
void
tag6 (void (*handler) (void *), void *arg)
{
(*handler)(arg);
}
/* Interfering preprocessing torture */
int pp1(
#if (__STDC__)
int
#endif
bar)
#if (!__STDC__)
int bar;
#endif
{
return bar;
}
int
pp2
#if __STDC__
(int bar)
#else
(bar)
int bar;
#endif
{
return bar;
}
int
#if __STDC__
pp3(int bar)
#else
pp3(bar)
int bar;
#endif
{
return bar;
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,630 @@
/* Definitions for data structures and routines for the regular
expression library, version 0.12.
Copyright (C) 1985, 1989-1993, 1995, 2000-2015 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 3, 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, see <http://www.gnu.org/licenses/>. */
#ifndef _REGEX_H
#define _REGEX_H 1
/* Allow the use in C++ code. */
#ifdef __cplusplus
extern "C" {
#endif
/* POSIX says that <sys/types.h> must be included (by the caller) before
<regex.h>. */
#if !defined _POSIX_C_SOURCE && !defined _POSIX_SOURCE && defined VMS
/* VMS doesn't have `size_t' in <sys/types.h>, even though POSIX says it
should be there. */
# include <stddef.h>
#endif
/* The following bits are used to determine the regexp syntax we
recognize. The set/not-set meanings where historically chosen so
that Emacs syntax had the value 0.
The bits are given in alphabetical order, and
the definitions shifted by one from the previous bit; thus, when we
add or remove a bit, only one other definition need change. */
typedef unsigned long reg_syntax_t;
/* If this bit is not set, then \ inside a bracket expression is literal.
If set, then such a \ quotes the following character. */
#define RE_BACKSLASH_ESCAPE_IN_LISTS ((unsigned long int) 1)
/* If this bit is not set, then + and ? are operators, and \+ and \? are
literals.
If set, then \+ and \? are operators and + and ? are literals. */
#define RE_BK_PLUS_QM (RE_BACKSLASH_ESCAPE_IN_LISTS << 1)
/* If this bit is set, then character classes are supported. They are:
[:alpha:], [:upper:], [:lower:], [:digit:], [:alnum:], [:xdigit:],
[:space:], [:print:], [:punct:], [:graph:], and [:cntrl:].
If not set, then character classes are not supported. */
#define RE_CHAR_CLASSES (RE_BK_PLUS_QM << 1)
/* If this bit is set, then ^ and $ are always anchors (outside bracket
expressions, of course).
If this bit is not set, then it depends:
^ is an anchor if it is at the beginning of a regular
expression or after an open-group or an alternation operator;
$ is an anchor if it is at the end of a regular expression, or
before a close-group or an alternation operator.
This bit could be (re)combined with RE_CONTEXT_INDEP_OPS, because
POSIX draft 11.2 says that * etc. in leading positions is undefined.
We already implemented a previous draft which made those constructs
invalid, though, so we haven't changed the code back. */
#define RE_CONTEXT_INDEP_ANCHORS (RE_CHAR_CLASSES << 1)
/* If this bit is set, then special characters are always special
regardless of where they are in the pattern.
If this bit is not set, then special characters are special only in
some contexts; otherwise they are ordinary. Specifically,
* + ? and intervals are only special when not after the beginning,
open-group, or alternation operator. */
#define RE_CONTEXT_INDEP_OPS (RE_CONTEXT_INDEP_ANCHORS << 1)
/* If this bit is set, then *, +, ?, and { cannot be first in an re or
immediately after an alternation or begin-group operator. */
#define RE_CONTEXT_INVALID_OPS (RE_CONTEXT_INDEP_OPS << 1)
/* If this bit is set, then . matches newline.
If not set, then it doesn't. */
#define RE_DOT_NEWLINE (RE_CONTEXT_INVALID_OPS << 1)
/* If this bit is set, then . doesn't match NUL.
If not set, then it does. */
#define RE_DOT_NOT_NULL (RE_DOT_NEWLINE << 1)
/* If this bit is set, nonmatching lists [^...] do not match newline.
If not set, they do. */
#define RE_HAT_LISTS_NOT_NEWLINE (RE_DOT_NOT_NULL << 1)
/* If this bit is set, either \{...\} or {...} defines an
interval, depending on RE_NO_BK_BRACES.
If not set, \{, \}, {, and } are literals. */
#define RE_INTERVALS (RE_HAT_LISTS_NOT_NEWLINE << 1)
/* If this bit is set, +, ? and | aren't recognized as operators.
If not set, they are. */
#define RE_LIMITED_OPS (RE_INTERVALS << 1)
/* If this bit is set, newline is an alternation operator.
If not set, newline is literal. */
#define RE_NEWLINE_ALT (RE_LIMITED_OPS << 1)
/* If this bit is set, then `{...}' defines an interval, and \{ and \}
are literals.
If not set, then `\{...\}' defines an interval. */
#define RE_NO_BK_BRACES (RE_NEWLINE_ALT << 1)
/* If this bit is set, (...) defines a group, and \( and \) are literals.
If not set, \(...\) defines a group, and ( and ) are literals. */
#define RE_NO_BK_PARENS (RE_NO_BK_BRACES << 1)
/* If this bit is set, then \<digit> matches <digit>.
If not set, then \<digit> is a back-reference. */
#define RE_NO_BK_REFS (RE_NO_BK_PARENS << 1)
/* If this bit is set, then | is an alternation operator, and \| is literal.
If not set, then \| is an alternation operator, and | is literal. */
#define RE_NO_BK_VBAR (RE_NO_BK_REFS << 1)
/* If this bit is set, then an ending range point collating higher
than the starting range point, as in [z-a], is invalid.
If not set, then when ending range point collates higher than the
starting range point, the range is ignored. */
#define RE_NO_EMPTY_RANGES (RE_NO_BK_VBAR << 1)
/* If this bit is set, then an unmatched ) is ordinary.
If not set, then an unmatched ) is invalid. */
#define RE_UNMATCHED_RIGHT_PAREN_ORD (RE_NO_EMPTY_RANGES << 1)
/* If this bit is set, succeed as soon as we match the whole pattern,
without further backtracking. */
#define RE_NO_POSIX_BACKTRACKING (RE_UNMATCHED_RIGHT_PAREN_ORD << 1)
/* If this bit is set, do not process the GNU regex operators.
If not set, then the GNU regex operators are recognized. */
#define RE_NO_GNU_OPS (RE_NO_POSIX_BACKTRACKING << 1)
/* If this bit is set, then *?, +? and ?? match non greedily. */
#define RE_FRUGAL (RE_NO_GNU_OPS << 1)
/* If this bit is set, then (?:...) is treated as a shy group. */
#define RE_SHY_GROUPS (RE_FRUGAL << 1)
/* If this bit is set, ^ and $ only match at beg/end of buffer. */
#define RE_NO_NEWLINE_ANCHOR (RE_SHY_GROUPS << 1)
/* If this bit is set, turn on internal regex debugging.
If not set, and debugging was on, turn it off.
This only works if regex.c is compiled -DDEBUG.
We define this bit always, so that all that's needed to turn on
debugging is to recompile regex.c; the calling code can always have
this bit set, and it won't affect anything in the normal case. */
#define RE_DEBUG (RE_NO_NEWLINE_ANCHOR << 1)
/* This global variable defines the particular regexp syntax to use (for
some interfaces). When a regexp is compiled, the syntax used is
stored in the pattern buffer, so changing this does not affect
already-compiled regexps. */
extern reg_syntax_t re_syntax_options;
#ifdef emacs
/* In Emacs, this is the string or buffer in which we
are matching. It is used for looking up syntax properties. */
extern Lisp_Object re_match_object;
#endif
/* Roughly the maximum number of failure points on the stack. */
extern size_t re_max_failures;
/* Define combinations of the above bits for the standard possibilities.
(The [[[ comments delimit what gets put into the Texinfo file, so
don't delete them!) */
/* [[[begin syntaxes]]] */
#define RE_SYNTAX_EMACS \
(RE_CHAR_CLASSES | RE_INTERVALS | RE_SHY_GROUPS | RE_FRUGAL)
#define RE_SYNTAX_AWK \
(RE_BACKSLASH_ESCAPE_IN_LISTS | RE_DOT_NOT_NULL \
| RE_NO_BK_PARENS | RE_NO_BK_REFS \
| RE_NO_BK_VBAR | RE_NO_EMPTY_RANGES \
| RE_DOT_NEWLINE | RE_CONTEXT_INDEP_ANCHORS \
| RE_UNMATCHED_RIGHT_PAREN_ORD | RE_NO_GNU_OPS)
#define RE_SYNTAX_GNU_AWK \
((RE_SYNTAX_POSIX_EXTENDED | RE_BACKSLASH_ESCAPE_IN_LISTS | RE_DEBUG) \
& ~(RE_DOT_NOT_NULL | RE_INTERVALS | RE_CONTEXT_INDEP_OPS))
#define RE_SYNTAX_POSIX_AWK \
(RE_SYNTAX_POSIX_EXTENDED | RE_BACKSLASH_ESCAPE_IN_LISTS \
| RE_INTERVALS | RE_NO_GNU_OPS)
#define RE_SYNTAX_GREP \
(RE_BK_PLUS_QM | RE_CHAR_CLASSES \
| RE_HAT_LISTS_NOT_NEWLINE | RE_INTERVALS \
| RE_NEWLINE_ALT)
#define RE_SYNTAX_EGREP \
(RE_CHAR_CLASSES | RE_CONTEXT_INDEP_ANCHORS \
| RE_CONTEXT_INDEP_OPS | RE_HAT_LISTS_NOT_NEWLINE \
| RE_NEWLINE_ALT | RE_NO_BK_PARENS \
| RE_NO_BK_VBAR)
#define RE_SYNTAX_POSIX_EGREP \
(RE_SYNTAX_EGREP | RE_INTERVALS | RE_NO_BK_BRACES)
/* P1003.2/D11.2, section 4.20.7.1, lines 5078ff. */
#define RE_SYNTAX_ED RE_SYNTAX_POSIX_BASIC
#define RE_SYNTAX_SED RE_SYNTAX_POSIX_BASIC
/* Syntax bits common to both basic and extended POSIX regex syntax. */
#define _RE_SYNTAX_POSIX_COMMON \
(RE_CHAR_CLASSES | RE_DOT_NEWLINE | RE_DOT_NOT_NULL \
| RE_INTERVALS | RE_NO_EMPTY_RANGES)
#define RE_SYNTAX_POSIX_BASIC \
(_RE_SYNTAX_POSIX_COMMON | RE_BK_PLUS_QM)
/* Differs from ..._POSIX_BASIC only in that RE_BK_PLUS_QM becomes
RE_LIMITED_OPS, i.e., \? \+ \| are not recognized. Actually, this
isn't minimal, since other operators, such as \`, aren't disabled. */
#define RE_SYNTAX_POSIX_MINIMAL_BASIC \
(_RE_SYNTAX_POSIX_COMMON | RE_LIMITED_OPS)
#define RE_SYNTAX_POSIX_EXTENDED \
(_RE_SYNTAX_POSIX_COMMON | RE_CONTEXT_INDEP_ANCHORS \
| RE_CONTEXT_INDEP_OPS | RE_NO_BK_BRACES \
| RE_NO_BK_PARENS | RE_NO_BK_VBAR \
| RE_CONTEXT_INVALID_OPS | RE_UNMATCHED_RIGHT_PAREN_ORD)
/* Differs from ..._POSIX_EXTENDED in that RE_CONTEXT_INDEP_OPS is
removed and RE_NO_BK_REFS is added. */
#define RE_SYNTAX_POSIX_MINIMAL_EXTENDED \
(_RE_SYNTAX_POSIX_COMMON | RE_CONTEXT_INDEP_ANCHORS \
| RE_CONTEXT_INVALID_OPS | RE_NO_BK_BRACES \
| RE_NO_BK_PARENS | RE_NO_BK_REFS \
| RE_NO_BK_VBAR | RE_UNMATCHED_RIGHT_PAREN_ORD)
/* [[[end syntaxes]]] */
/* Maximum number of duplicates an interval can allow. Some systems
(erroneously) define this in other header files, but we want our
value, so remove any previous define. */
#ifdef RE_DUP_MAX
# undef RE_DUP_MAX
#endif
/* If sizeof(int) == 2, then ((1 << 15) - 1) overflows. */
#define RE_DUP_MAX (0x7fff)
/* POSIX `cflags' bits (i.e., information for `regcomp'). */
/* If this bit is set, then use extended regular expression syntax.
If not set, then use basic regular expression syntax. */
#define REG_EXTENDED 1
/* If this bit is set, then ignore case when matching.
If not set, then case is significant. */
#define REG_ICASE (REG_EXTENDED << 1)
/* If this bit is set, then anchors do not match at newline
characters in the string.
If not set, then anchors do match at newlines. */
#define REG_NEWLINE (REG_ICASE << 1)
/* If this bit is set, then report only success or fail in regexec.
If not set, then returns differ between not matching and errors. */
#define REG_NOSUB (REG_NEWLINE << 1)
/* POSIX `eflags' bits (i.e., information for regexec). */
/* If this bit is set, then the beginning-of-line operator doesn't match
the beginning of the string (presumably because it's not the
beginning of a line).
If not set, then the beginning-of-line operator does match the
beginning of the string. */
#define REG_NOTBOL 1
/* Like REG_NOTBOL, except for the end-of-line. */
#define REG_NOTEOL (1 << 1)
/* If any error codes are removed, changed, or added, update the
`re_error_msg' table in regex.c. */
typedef enum
{
#ifdef _XOPEN_SOURCE
REG_ENOSYS = -1, /* This will never happen for this implementation. */
#endif
REG_NOERROR = 0, /* Success. */
REG_NOMATCH, /* Didn't find a match (for regexec). */
/* POSIX regcomp return error codes. (In the order listed in the
standard.) */
REG_BADPAT, /* Invalid pattern. */
REG_ECOLLATE, /* Not implemented. */
REG_ECTYPE, /* Invalid character class name. */
REG_EESCAPE, /* Trailing backslash. */
REG_ESUBREG, /* Invalid back reference. */
REG_EBRACK, /* Unmatched left bracket. */
REG_EPAREN, /* Parenthesis imbalance. */
REG_EBRACE, /* Unmatched \{. */
REG_BADBR, /* Invalid contents of \{\}. */
REG_ERANGE, /* Invalid range end. */
REG_ESPACE, /* Ran out of memory. */
REG_BADRPT, /* No preceding re for repetition op. */
/* Error codes we've added. */
REG_EEND, /* Premature end. */
REG_ESIZE, /* Compiled pattern bigger than 2^16 bytes. */
REG_ERPAREN, /* Unmatched ) or \); not returned from regcomp. */
REG_ERANGEX /* Range striding over charsets. */
} reg_errcode_t;
/* This data structure represents a compiled pattern. Before calling
the pattern compiler, the fields `buffer', `allocated', `fastmap',
`translate', and `no_sub' can be set. After the pattern has been
compiled, the `re_nsub' field is available. All other fields are
private to the regex routines. */
#ifndef RE_TRANSLATE_TYPE
# define RE_TRANSLATE_TYPE char *
#endif
struct re_pattern_buffer
{
/* [[[begin pattern_buffer]]] */
/* Space that holds the compiled pattern. It is declared as
`unsigned char *' because its elements are
sometimes used as array indexes. */
unsigned char *buffer;
/* Number of bytes to which `buffer' points. */
size_t allocated;
/* Number of bytes actually used in `buffer'. */
size_t used;
/* Syntax setting with which the pattern was compiled. */
reg_syntax_t syntax;
/* Pointer to a fastmap, if any, otherwise zero. re_search uses
the fastmap, if there is one, to skip over impossible
starting points for matches. */
char *fastmap;
/* Either a translate table to apply to all characters before
comparing them, or zero for no translation. The translation
is applied to a pattern when it is compiled and to a string
when it is matched. */
RE_TRANSLATE_TYPE translate;
/* Number of subexpressions found by the compiler. */
size_t re_nsub;
/* Zero if this pattern cannot match the empty string, one else.
Well, in truth it's used only in `re_search_2', to see
whether or not we should use the fastmap, so we don't set
this absolutely perfectly; see `re_compile_fastmap'. */
unsigned can_be_null : 1;
/* If REGS_UNALLOCATED, allocate space in the `regs' structure
for `max (RE_NREGS, re_nsub + 1)' groups.
If REGS_REALLOCATE, reallocate space if necessary.
If REGS_FIXED, use what's there. */
#define REGS_UNALLOCATED 0
#define REGS_REALLOCATE 1
#define REGS_FIXED 2
unsigned regs_allocated : 2;
/* Set to zero when `regex_compile' compiles a pattern; set to one
by `re_compile_fastmap' if it updates the fastmap. */
unsigned fastmap_accurate : 1;
/* If set, `re_match_2' does not return information about
subexpressions. */
unsigned no_sub : 1;
/* If set, a beginning-of-line anchor doesn't match at the
beginning of the string. */
unsigned not_bol : 1;
/* Similarly for an end-of-line anchor. */
unsigned not_eol : 1;
/* If true, the compilation of the pattern had to look up the syntax table,
so the compiled pattern is only valid for the current syntax table. */
unsigned used_syntax : 1;
#ifdef emacs
/* If true, multi-byte form in the regexp pattern should be
recognized as a multibyte character. */
unsigned multibyte : 1;
/* If true, multi-byte form in the target of match should be
recognized as a multibyte character. */
unsigned target_multibyte : 1;
/* Charset of unibyte characters at compiling time. */
int charset_unibyte;
#endif
/* [[[end pattern_buffer]]] */
};
typedef struct re_pattern_buffer regex_t;
/* Type for byte offsets within the string. POSIX mandates this to be an int,
but the Open Group has signaled its intention to change the requirement to
be that regoff_t be at least as wide as ptrdiff_t and ssize_t. Current
gnulib sources also use ssize_t, and we need this for supporting buffers and
strings > 2GB on 64-bit hosts. */
typedef ssize_t regoff_t;
/* This is the structure we store register match data in. See
regex.texinfo for a full description of what registers match. */
struct re_registers
{
unsigned num_regs;
regoff_t *start;
regoff_t *end;
};
/* If `regs_allocated' is REGS_UNALLOCATED in the pattern buffer,
`re_match_2' returns information about at least this many registers
the first time a `regs' structure is passed. */
#ifndef RE_NREGS
# define RE_NREGS 30
#endif
/* POSIX specification for registers. Aside from the different names than
`re_registers', POSIX uses an array of structures, instead of a
structure of arrays. */
typedef struct
{
regoff_t rm_so; /* Byte offset from string's start to substring's start. */
regoff_t rm_eo; /* Byte offset from string's start to substring's end. */
} regmatch_t;
/* Declarations for routines. */
/* Sets the current default syntax to SYNTAX, and return the old syntax.
You can also simply assign to the `re_syntax_options' variable. */
extern reg_syntax_t re_set_syntax (reg_syntax_t __syntax);
/* Compile the regular expression PATTERN, with length LENGTH
and syntax given by the global `re_syntax_options', into the buffer
BUFFER. Return NULL if successful, and an error string if not. */
extern const char *re_compile_pattern (const char *__pattern, size_t __length,
struct re_pattern_buffer *__buffer);
/* Compile a fastmap for the compiled pattern in BUFFER; used to
accelerate searches. Return 0 if successful and -2 if was an
internal error. */
extern int re_compile_fastmap (struct re_pattern_buffer *__buffer);
/* Search in the string STRING (with length LENGTH) for the pattern
compiled into BUFFER. Start searching at position START, for RANGE
characters. Return the starting position of the match, -1 for no
match, or -2 for an internal error. Also return register
information in REGS (if REGS and BUFFER->no_sub are nonzero). */
extern regoff_t re_search (struct re_pattern_buffer *__buffer,
const char *__string, size_t __length,
ssize_t __start, ssize_t __range,
struct re_registers *__regs);
/* Like `re_search', but search in the concatenation of STRING1 and
STRING2. Also, stop searching at index START + STOP. */
extern regoff_t re_search_2 (struct re_pattern_buffer *__buffer,
const char *__string1, size_t __length1,
const char *__string2, size_t __length2,
ssize_t __start, ssize_t __range,
struct re_registers *__regs,
ssize_t __stop);
/* Like `re_search', but return how many characters in STRING the regexp
in BUFFER matched, starting at position START. */
extern regoff_t re_match (struct re_pattern_buffer *__buffer,
const char *__string, size_t __length,
ssize_t __start, struct re_registers *__regs);
/* Relates to `re_match' as `re_search_2' relates to `re_search'. */
extern regoff_t re_match_2 (struct re_pattern_buffer *__buffer,
const char *__string1, size_t __length1,
const char *__string2, size_t __length2,
ssize_t __start, struct re_registers *__regs,
ssize_t __stop);
/* Set REGS to hold NUM_REGS registers, storing them in STARTS and
ENDS. Subsequent matches using BUFFER and REGS will use this memory
for recording register information. STARTS and ENDS must be
allocated with malloc, and must each be at least `NUM_REGS * sizeof
(regoff_t)' bytes long.
If NUM_REGS == 0, then subsequent matches should allocate their own
register data.
Unless this function is called, the first search or match using
PATTERN_BUFFER will allocate its own register data, without
freeing the old data. */
extern void re_set_registers (struct re_pattern_buffer *__buffer,
struct re_registers *__regs,
unsigned __num_regs,
regoff_t *__starts, regoff_t *__ends);
#if defined _REGEX_RE_COMP || defined _LIBC
# ifndef _CRAY
/* 4.2 bsd compatibility. */
extern char *re_comp (const char *);
extern int re_exec (const char *);
# endif
#endif
/* GCC 2.95 and later have "__restrict"; C99 compilers have
"restrict", and "configure" may have defined "restrict".
Other compilers use __restrict, __restrict__, and _Restrict, and
'configure' might #define 'restrict' to those words, so pick a
different name. */
#ifndef _Restrict_
# if 199901L <= __STDC_VERSION__
# define _Restrict_ restrict
# elif 2 < __GNUC__ || (2 == __GNUC__ && 95 <= __GNUC_MINOR__)
# define _Restrict_ __restrict
# else
# define _Restrict_
# endif
#endif
/* gcc 3.1 and up support the [restrict] syntax. Don't trust
sys/cdefs.h's definition of __restrict_arr, though, as it
mishandles gcc -ansi -pedantic. */
#ifndef _Restrict_arr_
# if ((199901L <= __STDC_VERSION__ \
|| ((3 < __GNUC__ || (3 == __GNUC__ && 1 <= __GNUC_MINOR__)) \
&& !defined __STRICT_ANSI__)) \
&& !defined __GNUG__)
# define _Restrict_arr_ _Restrict_
# else
# define _Restrict_arr_
# endif
#endif
/* POSIX compatibility. */
extern reg_errcode_t regcomp (regex_t *_Restrict_ __preg,
const char *_Restrict_ __pattern,
int __cflags);
extern reg_errcode_t regexec (const regex_t *_Restrict_ __preg,
const char *_Restrict_ __string, size_t __nmatch,
regmatch_t __pmatch[_Restrict_arr_],
int __eflags);
extern size_t regerror (int __errcode, const regex_t * __preg,
char *__errbuf, size_t __errbuf_size);
extern void regfree (regex_t *__preg);
#ifdef __cplusplus
}
#endif /* C++ */
/* For platform which support the ISO C amendment 1 functionality we
support user defined character classes. */
#if WIDE_CHAR_SUPPORT
/* Solaris 2.5 has a bug: <wchar.h> must be included before <wctype.h>. */
# include <wchar.h>
# include <wctype.h>
#endif
#if WIDE_CHAR_SUPPORT
/* The GNU C library provides support for user-defined character classes
and the functions from ISO C amendment 1. */
# ifdef CHARCLASS_NAME_MAX
# define CHAR_CLASS_MAX_LENGTH CHARCLASS_NAME_MAX
# else
/* This shouldn't happen but some implementation might still have this
problem. Use a reasonable default value. */
# define CHAR_CLASS_MAX_LENGTH 256
# endif
typedef wctype_t re_wctype_t;
typedef wchar_t re_wchar_t;
# define re_wctype wctype
# define re_iswctype iswctype
# define re_wctype_to_bit(cc) 0
#else
# define CHAR_CLASS_MAX_LENGTH 9 /* Namely, `multibyte'. */
# define btowc(c) c
/* Character classes. */
typedef enum { RECC_ERROR = 0,
RECC_ALNUM, RECC_ALPHA, RECC_WORD,
RECC_GRAPH, RECC_PRINT,
RECC_LOWER, RECC_UPPER,
RECC_PUNCT, RECC_CNTRL,
RECC_DIGIT, RECC_XDIGIT,
RECC_BLANK, RECC_SPACE,
RECC_MULTIBYTE, RECC_NONASCII,
RECC_ASCII, RECC_UNIBYTE
} re_wctype_t;
extern char re_iswctype (int ch, re_wctype_t cc);
extern re_wctype_t re_wctype (const unsigned char* str);
typedef int re_wchar_t;
extern void re_set_whitespace_regexp (const char *regexp);
#endif /* not WIDE_CHAR_SUPPORT */
#endif /* regex.h */

6563
test/etags/c-src/etags.c Normal file

File diff suppressed because it is too large Load diff

77
test/etags/c-src/exit.c Normal file
View file

@ -0,0 +1,77 @@
/* Copyright (C) 1991 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
The GNU C Library 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
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with the GNU C Library; see the file COPYING.LIB. If
not, write to the Free Software Foundation, Inc., 675 Mass Ave,
Cambridge, MA 02139, USA. */
#include <ansidecl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "exit.h"
#ifdef HAVE_GNU_LD
CONST struct
{
size_t n;
void EXFUN((*fn[1]), (NOARGS));
} __libc_atexit;
#endif
/* Call all functions registered with `atexit' and `on_exit',
in the reverse of the order in which they were registered
perform stdio cleanup, and terminate program execution with STATUS. */
__NORETURN
void
DEFUN(exit, (status), int status)
{
register CONST struct exit_function_list *l;
for (l = __exit_funcs; l != NULL; l = l->next)
{
register size_t i = l->idx;
while (i-- > 0)
{
CONST struct exit_function *CONST f = &l->fns[i];
switch (f->flavor)
{
case ef_free:
break;
case ef_on:
(*f->func.on.fn)(status, f->func.on.arg);
break;
case ef_at:
(*f->func.at)();
break;
}
}
}
#ifdef HAVE_GNU_LD
{
void EXFUN((*CONST *fn), (NOARGS));
for (fn = __libc_atexit.fn; *fn != NULL; ++fn)
(**fn) ();
}
#else
{
extern void EXFUN(_cleanup, (NOARGS));
_cleanup();
}
#endif
_exit(status);
}

View file

@ -0,0 +1,77 @@
/* Copyright (C) 1991 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
The GNU C Library 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
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with the GNU C Library; see the file COPYING.LIB. If
not, write to the Free Software Foundation, Inc., 675 Mass Ave,
Cambridge, MA 02139, USA. */
#include <ansidecl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "exit.h"
#ifdef HAVE_GNU_LD
CONST struct
{
size_t n;
void EXFUN((*fn[1]), (NOARGS));
} __libc_atexit;
#endif
/* Call all functions registered with `atexit' and `on_exit',
in the reverse of the order in which they were registered
perform stdio cleanup, and terminate program execution with STATUS. */
__NORETURN
void
DEFUN(exit, (status), int status)
{
register CONST struct exit_function_list *l;
for (l = __exit_funcs; l != NULL; l = l->next)
{
register size_t i = l->idx;
while (i-- > 0)
{
CONST struct exit_function *CONST f = &l->fns[i];
switch (f->flavor)
{
case ef_free:
break;
case ef_on:
(*f->func.on.fn)(status, f->func.on.arg);
break;
case ef_at:
(*f->func.at)();
break;
}
}
}
#ifdef HAVE_GNU_LD
{
void EXFUN((*CONST *fn), (NOARGS));
for (fn = __libc_atexit.fn; *fn != NULL; ++fn)
(**fn) ();
}
#else
{
extern void EXFUN(_cleanup, (NOARGS));
_cleanup();
}
#endif
_exit(status);
}

1
test/etags/c-src/fail.c Normal file
View file

@ -0,0 +1 @@
void (*prt_call())();

125
test/etags/c-src/getopt.h Normal file
View file

@ -0,0 +1,125 @@
/* Declarations for getopt.
Copyright (C) 1989, 1990, 1991, 1992 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;
/* 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
{
#if __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
#if __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 */

119
test/etags/c-src/h.h Normal file
View file

@ -0,0 +1,119 @@
typedef enum
{
ELEM_I/**< Comment Element i
Second comment line. */
} Fails_t;
typedef void Lang_function ();
void Asm_labels ();
typedef struct tpcmd
{
#define ggg hhh
union
{
} arg;
}
tpcmd;
typedef struct foobar2_ {
fu int (*funcptr) (void *ptr);
long foo;
char bar;
} foobar2;
typedef enum
{
DEVICE_SWP,
DEVICE_LAST
} bsp_DevId;
typedef union {
struct constant_args {
unsigned int burst;
} constant;
} args;
typedef int *regset;
typedef int INT;
typedef union abc
{
int def;
} ghi1;
typedef union abc {
int def;
} ghi2;
typedef struct a {
} b;
#define c() d
typedef struct an_extern_linkage *an_extern_linkage_ptr;
typedef struct an_extern_linkage {
a_name_linkage_kind
kind;
/* The kind of external linkage ("C++" or "C"). */
a_byte_boolean
is_explicit;
/* TRUE if the external linkage requirement is
explicitly specified in the source; FALSE for the
default set for the translation unit as a whole. */
#ifdef CL_CHANGES
a_byte_boolean is_curly_brace_form;
#endif
} an_extern_linkage;
typedef struct pollfd pfdset[FD_SETSIZE];
typedef union rtunion_def
{
int rtint;
char *rtstr;
struct rtx_def *rtx;
} womboid ;
typedef union rtunion_def
{
int rtint;
char *rtstr;
struct rtx_def *rtxp;
struct rtx_def rtxnp;
}
womboid
;
/* Leave the next two lines in that order. They exercise an old bug. */
enum {dog, cat} animals;
typedef void (_CALLBACK_ *signal_handler)(int);
typedef void (_CALLBACK_ *signal_handler1)(int);
/* comment */ #define ANSIC
#define ANSIC
#else
typedef void (proc) ();
typedef void OperatorFun(int opId);
typedef int f(int a,
int b);
struct my_struct {
};
typedef struct my_struct my_typedef;
typedef RETSIGTYPE (*signal_handler_t) (int);
#if 0
Date 04 May 87 235311 PDT (Mon)
Date: 04 May 87 23:53:11 PDT (Mon)
#endif
typedef unsigned char unchar;
typedef int X, Y, Z;
typedef mio mao;
extern void ab();
typedef struct a { } b;
typedef struct b
{
} c;
int (*oldhup)();
request (*oldhup) ();
int extvar;
#define tag1
#define aaaaaa \
bbbbbb
#define bbbbbb\
cccccc
#define cccccccccc
#define enter_critical_section do { int pri = spl7();
#define exit_critical_to_previous splarg (pri); } while (0)
#define UNDEFINED
struct re_pattern_buffer { unsigned char *buffer; };

View file

@ -0,0 +1,10 @@
/* Aliases for basic Mach system calls:
mach_task_self -> __mach_task_self, etc. */
#include <gnu-stabs.h>
#define SYSCALL(name, number, type, args, typed_args) \
function_alias (name, __##name, type, args, \
name typed_args)
#include "mach_syscalls.h"

View file

@ -0,0 +1,31 @@
SYSCALL (mach_msg_trap, -25,
mach_msg_return_t,
(msg, option, send_size,
rcv_size, rcv_name, timeout, notify),
(mach_msg_header_t *msg,
mach_msg_option_t option,
mach_msg_size_t send_size,
mach_msg_size_t rcv_size,
mach_port_t rcv_name,
mach_msg_timeout_t timeout,
mach_port_t notify))
SYSCALL (mach_reply_port, -26,
mach_port_t,
(),
(void))
SYSCALL (mach_thread_self, -27,
mach_port_t,
(),
(void))
SYSCALL (mach_task_self, -28,
mach_port_t,
(),
(void))
SYSCALL (mach_host_self, -29,
mach_port_t,
(),
(void))

57
test/etags/c-src/sysdep.h Normal file
View file

@ -0,0 +1,57 @@
/* Copyright (C) 1992, 1993 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
The GNU C Library 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
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with the GNU C Library; see the file COPYING.LIB. If
not, write to the Free Software Foundation, Inc., 675 Mass Ave,
Cambridge, MA 02139, USA. */
#include <sysdeps/unix/sysdep.h>
#define ENTRY(name) \
.globl _##name; \
.align 2; \
_##name##:
#define PSEUDO(name, syscall_name, args) \
.text; \
.globl syscall_error; \
ENTRY (name) \
XCHG_##args
movl $SYS_##syscall_name, %eax; \
int $0x80; \
test %eax, %eax; \
jl syscall_error; \
XCHG_##args
/* Linux takes system call arguments in registers:
1: %ebx
2: %ecx
3: %edx
4: %esi
5: %edi
We put the arguments into registers from the stack,
and save the registers, by using the 386 `xchg' instruction
to swap the values in both directions. */
#define XCHG_0 /* No arguments to frob. */
#define XCHG_1 xchg 8(%esp), %ebx; XCHG_0
#define XCHG_2 xchg 12(%esp), %ecx; XCHG_1
#define XCHG_3 xchg 16(%esp), %edx; XCHG_2
#define XCHG_4 xchg 20(%esp), %esi; XCHG_3
#define XCHG_5 xchg 24(%esp), %edi; XCHG_3
#define r0 %eax /* Normal return-value register. */
#define r1 %edx /* Secondary return-value register. */
#define scratch %ecx /* Call-clobbered register for random use. */
#define MOVE(x,y) movl x, y

112
test/etags/c-src/tab.c Normal file
View file

@ -0,0 +1,112 @@
/*
** tab.c for in
**
** Made by Pierric
** Login <pierric@seignobosc.com>
**
** Started on Thu Jan 24 18:36:47 2002 Pierric
** Last update Mon Sep 23 18:02:02 2002 Pierric
*/
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "my_malloc.h"
static int count_words(char *str, char delim)
{
int count;
count = 0;
while (*str)
{
if (*str != delim)
{
count++;
if (!strchr(str + 1, delim))
return (count);
str = strchr(str + 1, delim);
}
else
str++;
}
return (count);
}
static char *get_word(char **str, char delim)
{
char *tmp;
char *new;
while (**str == delim)
(*str)++;
if (**str == 0)
return (NULL);
tmp = strchr(*str, delim);
if (!tmp)
{
new = strdup(*str);
while (**str)
(*str)++;
return (new);
}
my_malloc(new, tmp - *str + 1);
new[tmp - *str] = '\0';
strncpy(new, *str, tmp - *str);
*str = tmp;
return (new);
}
void tab_free(char **tab)
{
int index;
if (!tab)
return;
for (index = 0; tab[index]; index++)
free(tab[index]);
free(tab);
}
char **tab_fill(char *str, char delim)
{
int count;
char **tab;
int index;
if (!str)
return (NULL);
count = count_words(str, delim);
if (!count)
return (NULL);
my_malloc(tab, (count + 1) * sizeof(char *));
for (index = 0; (tab[index] = get_word(&str, delim)); index++)
;
return (tab);
}
/*
** Deletes the first element of a wordtab, shifting the other
** elements. The size of the malloced area stays the same, though
*/
int tab_delete_first(char **tab)
{
int i;
if (!tab[0])
return (-1);
free(tab[0]);
for (i = 0; tab[i]; i++)
tab[i] = tab[i + 1];
return (0);
}
int tab_count_words(char **tab)
{
int count;
if (!tab)
return (0);
for (count = 0; tab[count]; count++)
;
return (count);
}

107
test/etags/c-src/torture.c Normal file
View file

@ -0,0 +1,107 @@
/* Date: Thu, 05 Aug 1993 20:28:03 +0200
From: "Tom R.Hageman" <tom@basil.icce.rug.nl>
Subject: more etags torture;-) [etags 7.3 patch#3]
To: pot@CNUCE.CNR.IT
Hi,
This test file illustrates some more problems with etags (7.3):
1. parentheses are confusing,
2. preprocessor directives can disrupt other state machines. */
/* A small torture test for etags. */
/* The classic parenthesis nightmare, based on signal(). */
void
(*tag1 (sig, handler)) ()
int sig;
void (*handler) ();
{
(*handler)(sig);
return handler;
}
#define notag2 void
/* The classic, with user-defined return type. */
notag2
(*tag2 (sig, handler)) ()
int sig;
void (*handler) ();
{
(*handler)(sig);
return handler;
}
/* The classic, in ANSI C style. */
void
(*tag3 (int sig, void (*handler) (int))) (int)
{
(*handler)(sig);
return handler;
}
#define notag4 void
/* The classic, with user-defined return type, in ANSI C style. */
notag4
(*tag4 (int sig, void (*handler) (int))) (int)
{
(*handler)(sig);
return handler;
}
/* A less tortuous example. */
void
tag5 (handler, arg)
void (*handler)();
void *arg;
{
(*handler)(arg);
}
/* A less tortuous example, in ANSI C style. */
void
tag6 (void (*handler) (void *), void *arg)
{
(*handler)(arg);
}
/* Interfering preprocessing torture */
int pp1(
#if (__STDC__)
int
#endif
bar)
#if (!__STDC__)
int bar;
#endif
{
return bar;
}
int
pp2
#if __STDC__
(int bar)
#else
(bar)
int bar;
#endif
{
return bar;
}
int
#if __STDC__
pp3(int bar)
#else
pp3(bar)
int bar;
#endif
{
return bar;
}

View file

@ -0,0 +1,163 @@
// Template array classes with like-type math ops
/*
Copyright (C) 1996 John W. Eaton
This file is part of Octave.
Octave 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.
Octave 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 Octave; see the file COPYING. If not, write to the Free
Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#if defined (__GNUG__)
#pragma interface
#endif
#if !defined (octave_MDiagArray2_h)
#define octave_MDiagArray2_h 1
#include "DiagArray2.h"
#include "MArray2.h"
#if defined (LTGT)
#undef LTGT
#endif
#if !defined (CXX_NEW_FRIEND_TEMPLATE_DECL)
#define LTGT
#else
#define LTGT <>
template <class T>
class MDiagArray2;
template <typename T> MDiagArray2<T>&
operator += (MDiagArray2<T>& a, const MDiagArray2<T>& b);
template <typename T> MDiagArray2<T>&
operator -= (MDiagArray2<T>& a, const MDiagArray2<T>& b);
template <typename T> MDiagArray2<T>
operator * (const MDiagArray2<T>& a, const T& s);
template <typename T> MDiagArray2<T>
operator / (const MDiagArray2<T>& a, const T& s);
template <typename T> MDiagArray2<T>
operator * (const T& s, const MDiagArray2<T>& a);
template <typename T> MDiagArray2<T>
operator + (const MDiagArray2<T>& a, const MDiagArray2<T>& b);
template <typename T> MDiagArray2<T>
operator - (const MDiagArray2<T>& a, const MDiagArray2<T>& b);
template <typename T> MDiagArray2<T>
product (const MDiagArray2<T>& a, const MDiagArray2<T>& b);
template <typename T> MDiagArray2<T>
operator - (const MDiagArray2<T>& a);
#endif
// Two dimensional diagonal array with math ops.
template <class T>
class MDiagArray2 : public DiagArray2<T>
{
protected:
MDiagArray2 (T *d, int r, int c) : DiagArray2<T> (d, r, c) { }
public:
MDiagArray2 (void) : DiagArray2<T> () { }
MDiagArray2 (int r, int c) : DiagArray2<T> (r, c) { }
MDiagArray2 (int r, int c, const T& val) : DiagArray2<T> (r, c, val) { }
MDiagArray2 (const Array<T>& a) : DiagArray2<T> (a) { }
MDiagArray2 (const DiagArray2<T>& a) : DiagArray2<T> (a) { }
MDiagArray2 (const MDiagArray2<T>& a) : DiagArray2<T> (a) { }
~MDiagArray2 (void) { }
MDiagArray2<T>& operator = (const MDiagArray2<T>& a)
{
DiagArray2<T>::operator = (a);
return *this;
}
operator MArray2<T> () const
{
MArray2<T> retval (nr, nc, T (0));
int len = nr < nc ? nr : nc;
for (int i = 0; i < len; i++)
retval.xelem (i, i) = xelem (i, i);
return retval;
}
// element by element MDiagArray2 by MDiagArray2 ops
friend MDiagArray2<T>&
operator += LTGT (MDiagArray2<T>& a, const MDiagArray2<T>& b);
friend MDiagArray2<T>&
operator -= LTGT (MDiagArray2<T>& a, const MDiagArray2<T>& b);
// element by element MDiagArray2 by scalar ops
friend MDiagArray2<T> operator * LTGT (const MDiagArray2<T>& a, const T& s);
friend MDiagArray2<T> operator / LTGT (const MDiagArray2<T>& a, const T& s);
// element by element scalar by MDiagArray2 ops
friend MDiagArray2<T> operator * LTGT (const T& s, const MDiagArray2<T>& a);
// element by element MDiagArray2 by MDiagArray2 ops
friend MDiagArray2<T>
operator + LTGT (const MDiagArray2<T>& a, const MDiagArray2<T>& b);
friend MDiagArray2<T>
operator - LTGT (const MDiagArray2<T>& a, const MDiagArray2<T>& b);
friend MDiagArray2<T>
product LTGT (const MDiagArray2<T>& a, const MDiagArray2<T>& b);
friend MDiagArray2<T> operator - LTGT (const MDiagArray2<T>& a);
};
#undef LTGT
#define INSTANTIATE_MDIAGARRAY_FRIENDS(T) \
template MDiagArray2<T>& operator += (MDiagArray2<T>& a, const MDiagArray2<T>& b); \
template MDiagArray2<T>& operator -= (MDiagArray2<T>& a, const MDiagArray2<T>& b); \
template MDiagArray2<T> operator * (const MDiagArray2<T>& a, const T& s); \
template MDiagArray2<T> operator / (const MDiagArray2<T>& a, const T& s); \
template MDiagArray2<T> operator * (const T& s, const MDiagArray2<T>& a); \
template MDiagArray2<T> operator + (const MDiagArray2<T>& a, const MDiagArray2<T>& b); \
template MDiagArray2<T> operator - (const MDiagArray2<T>& a, const MDiagArray2<T>& b); \
template MDiagArray2<T> product (const MDiagArray2<T>& a, const MDiagArray2<T>& b); \
template MDiagArray2<T> operator - (const MDiagArray2<T>& a);
#endif
/*
;;; Local Variables: ***
;;; mode: C++ ***
;;; End: ***
*/

View file

@ -0,0 +1,99 @@
// -*- c++ -*-
//
// $Id: Pctest.h,v 1.14 2000/01/19 17:14:42 bmah Exp $
//
// Pctest.h
// Bruce A. Mah <bmah@ca.sandia.gov>
//
// This work was first produced by an employee of Sandia National
// Laboratories under a contract with the U.S. Department of Energy.
// Sandia National Laboratories dedicates whatever right, title or
// interest it may have in this software to the public. Although no
// license from Sandia is needed to copy and use this software,
// copying and using the software might infringe the rights of
// others. This software is provided as-is. SANDIA DISCLAIMS ANY
// WARRANTY OF ANY KIND, EXPRESS OR IMPLIED.
//
// Header for virtual base class of tests. A particular protocol (e.g.
// IPv4, IPv6) will override the methods of this base class
// with protocol-specific implementations.
//
//
#ifndef PCTEST_H
#define PCTEST_H
#include <stdio.h>
#if STDC_HEADERS
#include <stdlib.h>
#include <string.h>
#endif /* STDC_HEADERS */
#if HAVE_UNISTD_H
#include <sys/types.h>
#endif /* HAVE_UNISTD_H */
#include <sys/socket.h>
#include <sys/time.h>
#include "pc.h"
// #include "TestRecord.h"
class TestRecord;
// Action codes. ICMPv4 and ICMPv6 have different values for their type
// and code fields. The Pctest abstracts these differences.
typedef enum {
PctestActionValid, // store valid measurement (e.g. ICMP
// time exceeded)
PctestActionValidLasthop, // store valid measurement, this is last hop
// (e.g. ICMP port unreachable)
PctestActionFiltered, // packets filtered, give up (e.g.
// ICMP prohibited)
PctestActionAbort // huh? we haven't a clue
} PctestActionType;
class Pctest {
public:
Pctest() {
initialized = 0;
TimeSyscall(syscallTime);
IF_DEBUG(3, fprintf(stderr, "syscallTime.tv_usec = %ld\n", syscallTime.tv_usec));
}
virtual ~Pctest() { };
// Get gettimeofday() system call overhead.
virtual void TimeSyscall(struct timeval &diff);
// Get random payload buffer
virtual char *GeneratePayload(int size);
// Set target host for our tests (resolve if necessary)
virtual int SetTargetName(char *target) = 0;
// Get target host name and address
virtual char *GetTargetName() { return targetName; };
virtual char *GetPrintableAddress() = 0;
virtual char *GetPrintableAddress(void *a) = 0;
virtual char *GetName(void *a) = 0;
virtual char *GetAddressFamily() = 0;
// Perform a test and return statistics
virtual int Test(TestRecord &tr) = 0;
virtual PctestActionType GetAction(TestRecord &tr) = 0;
virtual PctestActionType GetAction(TestRecord *tr) {
return this->GetAction(*tr);
};
virtual int GetMinSize() = 0;
protected:
int initialized; // initialization flag
char *targetName; // target hostname
struct timeval syscallTime; // estimated overhead for gettimeofday()
};
#endif /* PCTEST_H */

96
test/etags/cp-src/Range.h Normal file
View file

@ -0,0 +1,96 @@
/*
Copyright (C) 1996 John W. Eaton
This file is part of Octave.
Octave 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.
Octave 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 Octave; see the file COPYING. If not, write to the Free
Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#if !defined (octave_Range_h)
#define octave_Range_h 1
#if defined (__GNUG__)
#pragma interface
#endif
class istream;
class ostream;
class Matrix;
class
Range
{
public:
Range (void)
: rng_base (-1), rng_limit (-1), rng_inc (-1), rng_nelem (-1) { }
Range (const Range& r)
: rng_base (r.rng_base), rng_limit (r.rng_limit), rng_inc (r.rng_inc),
rng_nelem (r.rng_nelem) { }
Range (double b, double l)
: rng_base (b), rng_limit (l), rng_inc (1),
rng_nelem (nelem_internal ()) { }
Range (double b, double l, double i)
: rng_base (b), rng_limit (l), rng_inc (i),
rng_nelem (nelem_internal ()) { }
double base (void) const { return rng_base; }
double limit (void) const { return rng_limit; }
double inc (void) const { return rng_inc; }
int nelem (void) const { return rng_nelem; }
bool all_elements_are_ints (void) const;
Matrix matrix_value (void) const;
double min (void) const;
double max (void) const;
void sort (void);
void set_base (double b) { rng_base = b; }
void set_limit (double l) { rng_limit = l; }
void set_inc (double i) { rng_inc = i; }
friend ostream& operator << (ostream& os, const Range& r);
friend istream& operator >> (istream& is, Range& r);
void print_range (void);
private:
double rng_base;
double rng_limit;
double rng_inc;
int rng_nelem;
int nelem_internal (void) const;
};
extern Range operator - (const Range& r);
#endif
/*
;;; Local Variables: ***
;;; mode: C++ ***
;;; End: ***
*/

4840
test/etags/cp-src/abstract.C Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,993 @@
/*****************************************************************************
Copyright (c) 1992 Consorzio Pisa Ricerche.
Authors: Caneve Maurizio, Salvatori Elena
This software was produced under the ESPRIT/LOTOSPHERE
project. All rights reserved.
*****************************************************************************/
/* */
/* @(#)abstract.h 4.31 2/1/93 */
/* */
#ifndef abstract_hh
#define abstract_hh
#include <tree.h>
#include <adatat.h>
class SignatureSorts;
class ID_Place: public Tree_Node
{
char *str;
char RBubble;
friend class Gl_Identifier;
public:
ID_Place();
void SetIdent(char *);
void SetPosition(Coord, Coord);
void SetDimensions(void);
void SetVisible(char);
void SetFather(Tree_Node *);
void ClearID(void);
virtual ~ID_Place();
/* inline functions */
char *GetIdent() {return(str);};
void SetRBubble(char r) { RBubble = r; };
char GetRBubble(void) { return(RBubble); };
}; /* end of class ID_Place */
class ID_List: public Tree_Node
{
ID_Place *elem;
ID_List *next;
friend class Gl_Id_List;
friend class Oper;
public:
ID_List(ID_Place *, ID_List *);
void SetPosition(Coord, Coord);
void SetDimensions(void);
void SetFather(Tree_Node *);
ID_Place *GetElem();
void HideMe(void);
void SetCollapsed(char);
void SetRBubble(char);
void BuildSigSorts(char, SignatureSorts **, char, Oper *);
void SetVisible(char);
void SetAlignement(char);
void ClearIDs(void);
int GetCardinality(int);
}; /* end of class ID_List */
class Id_Decl: public Tree_Node
{
ID_List *id_list;
ID_Place *sort_id;
friend class Gl_Id_Decl;
public:
Id_Decl(ID_List *, ID_Place *);
void SetPosition(Coord, Coord);
void SetDimensions(void);
void SetFather(Tree_Node *);
void SetCollapsed(char);
}; /* end of class Id_Decl */
class Id_Decl_List: public Tree_Node
{
Id_Decl *elem;
Id_Decl_List *next;
friend class Gl_Id_Decl_List;
public:
Id_Decl_List(Id_Decl *, Id_Decl_List *);
void SetPosition(Coord, Coord);
void SetDimensions(void);
void SetFather(Tree_Node *);
void SetCollapsed(char);
}; /* end of class Id_Decl_List */
class Comment: public Tree_Node
{
char *comm;
friend class Gl_Comment;
public:
Comment();
Comment(Tree_Node*, Coord , Coord);
void SetComment(char *);
void SetPosition(Coord, Coord);
void SetDimensions(void);
void SetFather(Tree_Node *);
virtual ~Comment();
}; /* end of class Comment */
class Comment_List: public Tree_Node
{
Comment *elem;
Comment_List *next;
public:
Comment_List(Comment *, Comment_List *);
void SetPosition(Coord, Coord);
void SetDimensions(void);
void SetFather(Tree_Node *);
}; /* end of class Comment_List */
class Value_Expr: public Tree_Node
{
friend class Gl_Value_Expr;
public:
Value_Expr();
void SetPosition(Coord, Coord);
void SetDimensions(void);
void SetFather(Tree_Node *);
}; /* end of class Value_Expr */
class Value_Expr_List: public Tree_Node
{
Tree_Node *elem;
Value_Expr_List *next;
friend class Gl_Value_Expr_List;
public:
Value_Expr_List(Tree_Node *, Value_Expr_List *);
void SetPosition(Coord, Coord);
void SetDimensions(void);
void SetFather(Tree_Node *);
void SetCollapsed(char);
}; /* end of class Value_Expr_List */
class Exit_Entry: public Tree_Node
{
friend class Gl_Exit_Entry;
public:
Exit_Entry();
void SetPosition(Coord, Coord);
void SetDimensions(void);
void SetFather(Tree_Node *);
}; /* end of class Exit_Entry */
class Exit_Entry_List: public Tree_Node
{
Tree_Node *elem;
Exit_Entry_List *next;
friend class Gl_Exit_Entry_List;
public:
Exit_Entry_List(Tree_Node *, Exit_Entry_List *);
void SetPosition(Coord, Coord);
void SetDimensions(void);
void SetFather(Tree_Node *);
void SetCollapsed(char);
}; /* end of class Exit_Entry_List */
class Exper_Off: public Tree_Node
{
public:
Exper_Off();
void SetPosition(Coord, Coord);
void SetDimensions(void);
void SetFather(Tree_Node *);
}; /* end of class Exper_Off */
class Exper_Off_List: public Tree_Node
{
Exper_Off *elem;
Exper_Off_List *next;
friend class Gl_Exper_Off_List;
public:
Exper_Off_List(Exper_Off *, Exper_Off_List *);
void SetPosition(Coord, Coord);
void SetDimensions(void);
void SetFather(Tree_Node *);
void SetCollapsed(char);
}; /* end of class Exper_Off_List */
class Gate_Decl: public Tree_Node
{
ID_List *gate_id_list1;
ID_List *gate_id_list2;
friend class Gl_Gate_Decl;
public:
Gate_Decl(ID_List *, ID_List *);
void SetPosition(Coord, Coord);
void SetDimensions(void);
void SetFather(Tree_Node *);
void SetCollapsed(char);
}; /* end of class Gate_Decl */
class Gate_Decl_List: public Tree_Node
{
Gate_Decl *elem;
Gate_Decl_List *next;
friend class Gl_Gate_Decl_List;
public:
Gate_Decl_List(Gate_Decl *, Gate_Decl_List *);
void SetPosition(Coord, Coord);
void SetDimensions(void);
void SetFather(Tree_Node *);
void SetCollapsed(char);
}; /* end of class Gate_Decl_List */
class Ident_Eq: public Tree_Node
{
Id_Decl *iddecl;
Value_Expr *expr;
friend class Gl_Ident_Eq;
public:
Ident_Eq(Id_Decl *, Value_Expr *);
void SetPosition(Coord, Coord);
void SetDimensions(void);
void SetFather(Tree_Node *);
void SetCollapsed(char);
}; /* end of class Ident_Eq */
class Ident_Eq_List: public Tree_Node
{
Ident_Eq *elem;
Ident_Eq_List *next;
friend class Gl_Ident_Eq_List;
public:
Ident_Eq_List(Ident_Eq *, Ident_Eq_List *);
void SetPosition(Coord, Coord);
void SetDimensions(void);
void SetFather(Tree_Node *);
void SetCollapsed(char);
}; /* end of class Ident_Eq_List */
class Half_Container: public Tree_Node
{
ID_List *gate_list;
friend class Gl_Half_Container;
public:
Half_Container(ID_List *);
void SetPosition(Coord, Coord);
void SetDimensions(void);
void SetFather(Tree_Node *);
void SetCollapsed(char);
}; /* end of class Half_Container */
/* */
/* Process Definitions */
/* */
class Specification: public Tree_Node
{
class Definition;
Comment_List *com_list;
ID_Place *ident;
ID_List *gate_list;
Id_Decl_List *id_decl_list;
Comment_List *com_list1;
Tree_Node *func;
Data_List *dt_list;
Definition *def;
Coord yl1,yl2,yl3;
Coord MaxX, MaxY;
friend class Gl_Specification;
public:
Specification(Comment_List *, ID_Place *, ID_List *, Id_Decl_List *,
Comment_List *, Definition *, Tree_Node *, Data_List *);
void SetPosition(Coord, Coord);
void SetDimensions(void);
void SetFather(Tree_Node *);
void SetPath(int&, int&);
Coord GetMaxX();
Coord GetMaxY();
}; /* end of class Specification */
class Process: public Tree_Node
{
Comment_List *com_list;
ID_Place *ident;
ID_List *gate_list;
Id_Decl_List *id_decl_list;
Definition *def;
Tree_Node *func;
char nesting;
Coord yl1,yl2,yl3,ypath;
Coord MaxX, MaxY;
friend class Gl_Process;
public:
Process(Comment_List *, ID_Place *, ID_List *,Id_Decl_List *, Definition *, Tree_Node *);
void SetPosition(Coord, Coord);
void SetDimensions(void);
void SetFather(Tree_Node *);
void SetPath(char *, char, int&, int&);
void NewBex(Tree_Node *);
Coord GetMaxY();
Coord GetMaxX();
/* inline functions */
char GetNesting() {return(nesting);};
}; /* end of class Process */
class Proc_List: public Tree_Node
{
Process *elem;
Proc_List *next;
public:
Proc_List(Process *, Proc_List *);
void SetPosition(Coord, Coord);
void SetDimensions(void);
void SetFather(Tree_Node *);
void SetPath(char *, char, int&, int&);
char *GetPath();
}; /* end of class Proc_List */
class Definition: public Tree_Node
{
Tree_Node *bex;
Proc_List *process_list;
Data_List *data_list;
char path[PATH_LENGHT];
public:
Definition(Tree_Node *, Proc_List *, Data_List *);
void SetPosition(Coord, Coord);
void SetDimensions(void);
void SetFather(Tree_Node *);
void SetPath(char *, char, int&, int&);
/* inline functions */
char *GetPath() { return(path);};
}; /* end of class Definition */
/* */
/* Functionalities */
/* */
class Exit: public Tree_Node
{
ID_List *sort_list;
friend class Gl_Exit;
public:
Exit(ID_List *);
void SetPosition(Coord, Coord, Coord, Coord);
void SetDimensions(void);
void SetFather(Tree_Node *);
}; /*end of class Exit */
class NoExit: public Tree_Node
{
friend class Gl_NoExit;
public:
NoExit();
void SetPosition(Coord, Coord);
void SetDimensions(void);
void SetFather(Tree_Node *);
}; /*end of class NoExit */
/* */
/* Value Expressions */
/* */
class Value: public Tree_Node
{
ID_Place *ident;
ID_Place *sort_id;
friend class Gl_Value;
public:
Value(ID_Place *, ID_Place *);
void SetPosition(Coord, Coord);
void SetDimensions(void);
void SetFather(Tree_Node *);
void SetCollapsed(char);
}; /* end of class Value */
class Term: public Tree_Node
{
ID_Place *op_ident;
Value_Expr_List *expr_list;
ID_Place *sort_id;
friend class Gl_Term;
public:
Term(ID_Place *, Value_Expr_List *, ID_Place *);
void SetPosition(Coord, Coord);
void SetDimensions(void);
void SetFather(Tree_Node *);
void SetCollapsed(char);
}; /* end of class Term */
class Equality: public Tree_Node
{
Tree_Node *express1;
Tree_Node *express2;
friend class Gl_Equality;
public:
Equality();
Equality(Tree_Node *, Tree_Node *);
void SetPosition(Coord, Coord);
void SetDimensions(void);
void SetFather(Tree_Node *);
void SetCollapsed(char);
}; /* end of class Equality */
class Sort_Id_Exit: public Tree_Node
{
ID_Place *sort_id;
friend class Gl_Sort_Id_Exit;
public:
Sort_Id_Exit(ID_Place *);
void SetPosition(Coord, Coord);
void SetDimensions(void);
void SetFather(Tree_Node *);
void SetCollapsed(char);
}; /* end of class Sort_id_Exit */
/* */
/* Guard Options */
/* */
class NoGuard: public Tree_Node
{
friend class Gl_NoGuard;
public:
NoGuard();
void SetPosition(Coord, Coord);
void SetDimensions(void);
void SetFather(Tree_Node *);
}; /* end of class NoGuard */
class Guard: public Tree_Node
{
Equality *equality;
friend class Gl_Guard;
public:
Guard(Equality *);
void SetPosition(Coord, Coord);
void SetDimensions(void);
void SetFather(Tree_Node *);
void SetCollapsed(char);
}; /* end of class Guard */
/* */
/* Experiment Offers */
/* */
class NoExperiment: public Tree_Node
{
friend class Gl_NoExperiment;
public:
NoExperiment();
void SetPosition(Coord, Coord);
void SetDimensions(void);
void SetFather(Tree_Node *);
}; /* end of class NoExperiment */
class Experiment: public Tree_Node
{
Exper_Off_List *exp_offer_list;
Tree_Node *guard_option;
friend class Gl_Experiment;
public:
Experiment(Exper_Off_List *, Tree_Node *);
void SetPosition(Coord, Coord);
void SetDimensions(void);
void SetFather(Tree_Node *);
void SetTextual(char, char = FALSE);
void SetCollapsed(char);
/* inline functions */
Tree_Node *GetGuard(void) { return(guard_option); };
}; /* end of class Experiment */
class Exclam: public Tree_Node
{
Tree_Node *value_exp;
friend class Gl_Exclam;
public:
Exclam(Tree_Node *);
void SetPosition(Coord, Coord);
void SetDimensions(void);
void SetFather(Tree_Node *);
void SetCollapsed(char);
}; /* end of class Exclam */
class Query: public Tree_Node
{
Id_Decl *id_decl;
friend class Gl_Query;
public:
Query(Id_Decl *);
void SetPosition(Coord, Coord);
void SetDimensions(void);
void SetFather(Tree_Node *);
void SetCollapsed(char);
}; /* end of class Query */
/* */
/* Action Denotations */
/* */
class Internal: public Tree_Node
{
friend class Gl_Internal;
public:
Internal();
void SetPosition(Coord, Coord);
void SetDimensions(void);
void SetFather(Tree_Node *);
}; /* end of class Internal */
class Communication: public Tree_Node
{
ID_Place *gate_identifier;
Tree_Node *experiment_option;
Coord xl, yl;
int hr;
friend class Gl_Communication;
public:
Communication(ID_Place *, Tree_Node *);
void SetPosition(Coord, Coord);
void SetDimensions(void);
void SetFather(Tree_Node *);
void SetTextual(char, char = FALSE);
void SetCollapsed(char);
}; /* end of class Communication */
/* */
/* Parallel Operators */
/* */
class Gen_Paral: public Tree_Node
{
ID_List *gate_id_list;
Coord Xclose;
char border;
friend class Gl_Gen_Paral;
public:
Gen_Paral(ID_List *);
void SetPosition(Coord, Coord);
void SetDimensions(void);
void SetFather(Tree_Node *);
void SetCollapsed(char);
/* inline functions */
void HideGate() { ((ID_List *)gate_id_list)->HideMe(); };
}; /* end of class Gen_Paral */
class Interl: public Tree_Node
{
friend class Gl_Interl;
public:
Interl();
void SetPosition(Coord, Coord);
void SetDimensions(void);
void SetFather(Tree_Node *);
}; /* end of class Interl */
class Syncr: public Tree_Node
{
friend class Gl_Syncr;
public:
Syncr();
void SetPosition(Coord, Coord);
void SetDimensions(void);
void SetFather(Tree_Node *);
}; /* end of class Syncr */
/* */
/* Bejhviour Expressions */
/* */
class Action_Pref: public Tree_Node
{
Tree_Node *action_den;
Tree_Node *bex;
char havebox;
char border;
friend class Gl_Action_Pref;
public:
Action_Pref(Tree_Node *, Tree_Node *);
void SetPosition(Coord, Coord);
void SetDimensions(void);
void SetFather(Tree_Node *);
void SetTextual(char, char = FALSE);
void SetCollapsed(char);
}; /* end of class Action_Pref */
class Enable: public Tree_Node
{
Tree_Node *bex1, *bex2;
ID_List *gate_id_list;
Coord xl, yl1, xl2, yl2, xid, yid, Yclose;
char havebox;
char border;
friend class Gl_Enable;
public:
Enable(Tree_Node *, ID_List *, Tree_Node *);
void SetPosition(Coord, Coord);
void SetDimensions(void);
void SetFather(Tree_Node *);
void SetTextual(char, char = FALSE);
int Get_Textual_H(void);
int Get_Textual_W(void);
void SetTerminalPos(void);
void SetCollapsed(char);
}; /* end of class Enable */
class Disable: public Tree_Node
{
Tree_Node *bex1, *bex2;
Coord xl, yl, yl2;
char havebox;
char border;
friend class Gl_Disable;
public:
Disable(Tree_Node *, Tree_Node *);
void SetPosition(Coord, Coord);
void SetDimensions(void);
void SetFather(Tree_Node *);
void SetTextual(char, char = FALSE);
int Get_Textual_H(void);
int Get_Textual_W(void);
void SetTerminalPos(void);
void SetCollapsed(char);
}; /* end of class Disable */
class Choice: public Tree_Node
{
Tree_Node *bex1, *bex2;
Coord xl, yl, yl1;
char havebox;
int delta;
char border;
friend class Gl_Choice;
public:
Choice(Tree_Node *, Tree_Node *);
void SetPosition(Coord, Coord);
void SetDimensions(void);
void SetFather(Tree_Node *);
void SetTextual(char, char = FALSE);
void SetCollapsed(char);
int Get_Textual_H(void);
int Get_Textual_W(void);
void SetTerminalPos(void);
void ChangeH(int);
void ChangeW(int);
}; /* end of class Choice */
class Stop: public Tree_Node
{
char havebox;
char border;
friend class Gl_Stop;
public:
Stop();
void SetPosition(Coord, Coord);
void SetDimensions(void);
void SetFather(Tree_Node *);
void SetTextual(char, char = FALSE);
void SetCollapsed(char);
}; /* end of class Stop */
class Exit_Bex: public Tree_Node
{
Exit_Entry_List *entry_list;
Coord Xopen, Xclose;
char havebox;
char border;
friend class Gl_Exit_Bex;
public:
Exit_Bex(Exit_Entry_List *);
void SetPosition(Coord, Coord);
void SetDimensions(void);
void SetFather(Tree_Node *);
void SetTextual(char, char = FALSE);
void SetCollapsed(char);
}; /*end of class Exit_Bex */
class Hide: public Tree_Node
{
ID_List *gate_list;
Tree_Node *bex;
char border;
Coord yl;
friend class Gl_Hide;
public:
Hide(ID_List *, Tree_Node *);
void SetPosition(Coord, Coord);
void SetDimensions(void);
void SetFather(Tree_Node *);
void SetTextual(char, char = FALSE);
void SetCollapsed(char);
}; /* end of class Hide */
class Guarded: public Tree_Node
{
Equality *equality;
Tree_Node *bex;
Coord Xclose;
char border;
friend class Gl_Guarded;
public:
Guarded(Equality *, Tree_Node *);
void SetPosition(Coord, Coord);
void SetDimensions(void);
void SetFather(Tree_Node *);
void SetTextual(char, char = FALSE);
void SetCollapsed(char);
}; /* end of class Guarded */
class Proc_Inst: public Tree_Node
{
ID_List *gate_list;
ID_Place *ident;
Value_Expr_List *value_expr_list;
Coord yp, yl1, Xopen, Xclose;
int hp;
char border;
friend class Gl_Proc_Inst;
public:
Proc_Inst(ID_Place *, ID_List *, Value_Expr_List *);
void SetPosition(Coord, Coord);
void SetDimensions(void);
void SetFather(Tree_Node *);
void SetTextual(char, char = FALSE);
void SetCollapsed(char);
}; /* end of class Proc_inst */
class Parallel: public Tree_Node
{
Tree_Node *bex1, *bex2, *oper;
Coord xl, yl, yl1;
char havebox;
int delta;
char border;
friend class Gl_Parallel;
public:
Parallel(Tree_Node *, Tree_Node *, Tree_Node *);
void SetPosition(Coord, Coord);
void SetDimensions(void);
void SetFather(Tree_Node *);
void SetTextual(char, char = FALSE);
int Get_Textual_W(void);
int Get_Textual_H(void);
void SetTerminalPos(void);
void SetCollapsed(char);
/* inline functions */
char GetOperType(void) { return(oper->GetType());};
}; /* end of class Parallel */
class Local_Def: public Tree_Node
{
Ident_Eq_List *equa_list;
Tree_Node *bex;
Coord yl;
char border;
friend class Gl_Local_Def;
public:
Local_Def(Ident_Eq_List *, Tree_Node *);
void SetPosition(Coord, Coord);
void SetDimensions(void);
void SetFather(Tree_Node *);
void SetTextual(char, char = FALSE);
void SetCollapsed(char);
}; /* end of class Local_Def */
class Par: public Tree_Node
{
Gate_Decl_List *gate_decl_list;
Tree_Node *oper, *bex;
Coord xl, yl;
char border;
friend class Gl_Par;
public:
Par(Gate_Decl_List *, Tree_Node *, Tree_Node *);
void SetPosition(Coord, Coord);
void SetDimensions(void);
void SetFather(Tree_Node *);
void SetTextual(char, char = FALSE);
void SetCollapsed(char);
}; /* end of class Par */
class Sum_Gate: public Tree_Node
{
Gate_Decl_List *gate_decl_list;
Tree_Node *bex;
Coord xl, yl, Xch, Ych, Xclose, Yclose;
char border;
friend class Gl_Sum_Gate;
public:
Sum_Gate(Gate_Decl_List *, Tree_Node *);
void SetPosition(Coord, Coord);
void SetDimensions(void);
void SetFather(Tree_Node *);
void SetTextual(char, char = FALSE);
void SetTerminalPos(void);
void SetCollapsed(char);
}; /* end of class Sum_Gate */
class Sum_Ident: public Tree_Node
{
Id_Decl_List *ident_decl_list;
Tree_Node *bex;
Coord xl, yl, Xch, Ych, Xclose, Yclose;
char border;
friend class Gl_Sum_Ident;
public:
Sum_Ident(Id_Decl_List *, Tree_Node *);
void SetPosition(Coord, Coord);
void SetDimensions(void);
void SetFather(Tree_Node *);
void SetTextual(char, char = FALSE);
void SetTerminalPos(void);
void SetCollapsed(char);
}; /* end of class Sum_Ident */
#endif

View file

@ -0,0 +1,14 @@
::dummy::dummy test::dummy1(void)
{
return ::dummy::dummy;
}
::dummy::dummy test::dummy2(::CORBA::Long dummy)
{
return ::dummy::dummy;
}
::dummy::dummy test::dummy3(char* name, ::CORBA::Long dummy)
{
return ::dummy::dummy;
}

156
test/etags/cp-src/c.C Normal file
View file

@ -0,0 +1,156 @@
template <typename ipc3dIslandHierarchy, typename ipc3dChannelType, unsigned numOfChannels, typename ipc3dLinkControl, typename ipc3dLinkControlSetup>
class CMultiChannelCSC19_3D
{
private:
ipc3dLinkControlSetup setup;
ipc3dCSC19<ipc3dIslandHierarchy,ipcMultiChannel<ipc3dChannelType,numOfChannels>,ipcMultiChannel<ipc3dChannelType,numOfChannels>,ipc3dLinkControl> mcCSC;
advTimer cscInitTime;
advTimer cscSegmentationTime;
advTimer outputTime;
public:
void execute(CPluginCSCState& p, int w, int h, int d, const ipcMultiChannel<ipc3dChannelType,numOfChannels>* orgImage, ipcMultiChannel<ipc3dChannelType,numOfChannels>* regionImage, unsigned int* mapImage, ipc3dBlockCompressedLabelImage* compressedMapImage=NULL)
{
if (orgImage!=NULL)
{
//do something
}
}
class foo {
int const_func() const;
int b;
int non_const_func2(void);
};
static void my_function1(int var1) const;
int main (void) { my_function0(0); my_function1(1); return; }
double base (void) const { return rng_base; }
template <typename T> MDiagArray2<T>&
operator += (MDiagArray2<T>& a, const MDiagArray2<T>& b);
class TestRecord;
typedef struct s1 {
int counter;
} t1;
struct s2 {
int counter;
};
typedef struct s2 t2;
class A {
enum { rosso, giallo, verde } colori;
const A& operator+(const A&);
};
const A& A::operator+(const A&) { }
void operator+(int, int) {}
void operator -(int, int) {}
void operator int(int, int) {}
A<int>* f() {}
int f(A<int> x) {}
int A<int>::f(A<int>* x) {}
A<float,B<int> > A<B<float>,int>::f(A<int>* x) {}
template <class C, int n> class AT { C t[n]; };
class AU { T x; };
class B<int> { void f() {} };
const A::B::T& abt = abc;
class A { class B { int f(); }; };
class A {
int get_data() const;
A operator+(A& a) {};
};
is_muldiv_operation(pc)
{
}
#ifdef __cplusplus
extern "C" {
#endif
domain foo {
void f() {}
};
void A::A() {}
struct A { A(); }
struct B { B(); };
void B::B() {}
void BE_Node::BE_Node() {}
class BE_Node {};
struct foo {
int x;
};
#ifdef __cplusplus
}
#endif
class test {
int f(){return 0;}; // first comment
// second comment
int ff(){return 1;};
int g(){return 2;};
}
class AST_Root : public virtual AST_Module
{
};
class AST_Root; // The root of an AST 112,3888
// etags finds
AST_ConcreteType::AST_ConcreteType(AST_Decl::NodeType nt, UTL_ScopedName *n,
UTL_StrList *p)
: AST_Decl(nt, n, p)
{
}
// and
AST_Array::AST_Array(UTL_ScopedName *n, unsigned long nd, UTL_ExprList *ds)
: pd_n_dims(nd), pd_base_type(NULL),
AST_Decl(AST_Decl::NT_array, n, NULL)
{
}
// as definitions of AST_Decl.
class {
void f() {}
};
struct A {
~A();
};
A::~A() {}
struct B {
~B() {};
};
enum {dog, cat} animals;
struct {int teats;} cow;
class Boo {
enum {dog, cat} animals;
struct {int treats;} cow;
int i,a,b;
foo() {
cout << "hi";
}
Boo(int _i, int _a, int _b) : i(_i), a(_a), b(_b) {}
Boo(Boo);
};
Boo::Boo(Boo) :
i(i),
a(a),
b(b)
{}
/* extern "C" grot: */
extern "C" {
typedef int should_see_this_one_enclosed_in_extern_C;
}
/* Typedefs: */
typedef int (*should_see_this_function_pointer) (
void *but_not_this_argument);
typedef int should_see_this_array_type[but_not_this_subscript];

836
test/etags/cp-src/cfront.H Normal file
View file

@ -0,0 +1,836 @@
/*ident "@(#)cfront:src/cfront.h 1.13" */
/***********************************************************************
C++ source for cfront, the C++ compiler front-end
written in the computer science research center of Bell Labs
Copyright (c) 1984 AT&T, Inc. All Rights Reserved
THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T, INC.
When reading cfront code please remember that C++ was not available
when it was originally written. Out of necessity cfront is written
in a style that takes advantage of only few of C++'s features.
cfront.h:
Here is all the class definitions for cfront, and most of the externs
***********************************************************************/
/* WARNING:
This program relies on non-initialized class members being ZERO.
This will be true as long as they are allocated using the "new" operator
*/
#include "token.h"
#include "typedef.h"
extern bit old_fct_accepted; /* if set:
old style function definitions are legal,
implicit declarations are legal
*/
extern bit fct_void; /* if set:
int f(); ... f(1); gives a warning per file
undeclared(); gives a warning per file
if not:
int f(); ... f(1); is an error
undeclared(); is an error (currently only a warning)
*/
#ifndef GRAM
extern char* prog_name; // compiler name and version
extern int inline_restr; // inline expansion restrictions
extern bit emode; // print_mode error
#endif
extern Pname name_free; // free lists
extern Pexpr expr_free;
extern Pstmt stmt_free;
/* "spy" counters: */
extern int Nspy;
extern int Nfile, Nline, Ntoken, Nname, Nfree_store, Nalloc, Nfree;
extern int Nn, Nbt, Nt, Ne, Ns, Nstr, Nc, Nl;
extern int NFn, NFtn, NFpv, NFbt, NFf, NFs, NFc, NFe, NFl;
extern TOK lex();
extern Pname syn();
extern void init_print(); // stage initializers
extern void init_lex();
extern void int_syn();
extern void ext(int);
extern char* make_name(TOK);
struct loc // a source file location
{
short file; // index into file_name[], or zero
short line;
#ifndef GRAM
void put(FILE*);
void putline();
#endif
};
extern Loc curloc;
extern int curr_file;
struct ea { // fudge portable printf-like formatting for error()
union {
void* p;
int i;
};
ea(void* pp) { p = pp; }
ea(int ii) { i = ii; }
ea() {}
ea(int i) { x; }
};
extern ea* ea0;
overload error;
int error(const char*, ea& = *ea0, ea& = *ea0, ea& = *ea0, ea& = *ea0);
int error(loc*, const char*, ea& = *ea0, ea& = *ea0, ea& = *ea0, ea& = *ea0);
int error(int, const char*, ea& = *ea0, ea& = *ea0, ea& = *ea0, ea& = *ea0);
int error(int, loc*, const char*, ea& = *ea0, ea& = *ea0, ea& = *ea0, ea& = *ea0);
#ifndef GRAM
extern int error_count;
extern bit debug;
extern int vtbl_opt;
extern FILE* out_file;
extern FILE* in_file;
extern char scan_started;
extern bit warn;
#endif
extern int br_level;
extern int bl_level;
extern Ptable ktbl; // keywords and typedef names
extern Ptable gtbl; // global names
extern char* oper_name(TOK);
extern Pclass ccl;
extern Pbase defa_type;
extern Pbase moe_type;
#ifndef GRAM
extern Pstmt Cstmt; // current statement, or 0
extern Pname Cdcl; // name currently being declared, or 0
extern void put_dcl_context();
extern Ptable any_tbl; // table of undefined struct members
extern Pbase any_type;
#endif
extern Pbase int_type;
extern Pbase char_type;
extern Pbase short_type;
extern Pbase long_type;
extern Pbase uint_type;
extern Pbase float_type;
extern Pbase double_type;
extern Pbase void_type;
#ifndef GRAM
extern Pbase uchar_type;
extern Pbase ushort_type;
extern Pbase ulong_type;
extern Ptype Pchar_type;
extern Ptype Pint_type;
extern Ptype Pfctvec_type;
extern Ptype Pfctchar_type;
extern Ptype Pvoid_type;
extern Pbase zero_type;
extern int byte_offset;
extern int bit_offset;
extern int max_align;
extern int stack_size;
extern int enum_count;
extern int const_save;
#endif
extern Pexpr dummy; /* the empty expression */
extern Pexpr zero;
extern Pexpr one;
extern Pname sta_name; /* qualifier for unary :: */
#define DEL(p) if (p && (p->permanent==0)) p->del()
#define PERM(p) p->permanent=1
#define UNPERM(p) p->permanent=0
struct node {
TOK base;
TOK n_key; /* for names in table: class */
bit permanent;
};
#ifndef GRAM
extern Pclass Ebase, Epriv; /* lookc return values */
#endif
struct table : node {
/* a table is a node only to give it a "base" for debugging */
char init_stat; /* ==0 if block(s) of table not simplified,
==1 if simplified but had no initializers,
==2 if simplified and had initializers.
*/
short size;
short hashsize;
short free_slot; /* next free slot in entries */
Pname* entries;
short* hashtbl;
Pstmt real_block; /* the last block the user wrote,
not one of the ones cfront created
*/
Ptable next; /* table for enclosing scope */
Pname t_name; /* name of the table */
table(short, Ptable, Pname);
Pname look(char*, TOK);
Pname insert(Pname, TOK);
#ifndef GRAM
void grow(int);
void set_scope(Ptable t) { next = t; };
void set_name(Pname n) { t_name = n; };
Pname get_mem(int);
int max() { return free_slot-1; };
void dcl_print(TOK,TOK);
Pname lookc(char*, TOK);
Pexpr find_name(Pname, bit, Pexpr);
void del();
#endif
};
#ifndef GRAM
extern bit Nold;
extern bit vec_const, fct_const;
#endif
extern void restore();
extern void set_scope(Pname);
extern Plist modified_tn;
extern Pbase start_cl(TOK, Pname, Pname);
extern void end_cl();
extern Pbase end_enum(Pname, Pname);
/************ types : basic types, aggregates, declarators ************/
#ifndef GRAM
extern bit new_type;
extern Pname cl_obj_vec;
extern Pname eobj;
#endif
#define DEFINED 01 /* definition fed through ?::dcl() */
#define SIMPLIFIED 02 /* in ?::simpl() */
#define DEF_SEEN 04 /* definition seen, but not processed */
/* used for class members in norm.c */
#define IN_ERROR 010
struct type : node {
bit defined; /* flags DEF_SEEN, DEFINED, SIMPLIFIED, IN_ERROR
not used systematically yet
*/
char* signature(char*);
#ifndef GRAM
void print();
void dcl_print(Pname);
void base_print();
void del();
Pname is_cl_obj(); /* sets cl_obj_vec */
int is_ref();
void dcl(Ptable);
int tsizeof();
bit tconst();
TOK set_const(bit);
int align();
TOK kind(TOK,TOK);
TOK integral(TOK oo) { return kind(oo,I); };
TOK numeric(TOK oo) { return kind(oo,N); };
TOK num_ptr(TOK oo) { return kind(oo,P); };
bit vec_type();
bit check(Ptype, TOK);
Ptype deref();
Pptr addrof();
#endif
};
struct enumdef : type { /* ENUM */
bit e_body;
short no_of_enumerators;
Pname mem;
enumdef(Pname n) { base=ENUM; mem=n; };
#ifndef GRAM
void print();
void dcl_print(Pname);
void dcl(Pname, Ptable);
void simpl();
#endif
};
struct classdef : type { /* CLASS */
bit pubbase;
bit c_body; /* print definition only once */
TOK csu; /* CLASS, STRUCT, UNION, or ANON */
char obj_align;
char bit_ass; // 1 if no member has operator=()
char virt_count; /* number of virtual functions
incl. virtuals in base classes */
Pname clbase; // base class
char* string; /* name of class */
Pname mem_list;
Ptable memtbl;
int obj_size;
int real_size; /* obj_size - alignment waste */
Plist friend_list;
Pname pubdef;
Plist tn_list; // list of member names hiding type names
Pclass in_class; /* enclosing class, or 0 */
Ptype this_type;
Pname* virt_init; /* vector of jump table initializers */
Pname itor; /* constructor X(X&) */
Pname conv; /* operator T() chain */
classdef(TOK);
TOK is_simple() { return (csu==CLASS)?0:csu; };
#ifndef GRAM
void print();
void dcl_print(Pname);
void simpl();
void print_members();
void dcl(Pname, Ptable);
bit has_friend(Pname);
bit baseof(Pname);
bit baseof(Pclass);
Pname has_oper(TOK);
Pname has_ctor() { return memtbl->look("_ctor",0); }
Pname has_dtor() { return memtbl->look("_dtor",0); }
Pname has_itor() { return itor; }
Pname has_ictor();
#endif
};
struct basetype : type
/* ZTYPE CHAR SHORT INT LONG FLOAT DOUBLE
FIELD EOBJ COBJ TYPE ANY
*/
/* used for gathering all the attributes
for a list of declarators
ZTYPE is the (generic) type of ZERO
ANY is the generic type of an undeclared name
*/
{
bit b_unsigned;
bit b_const;
bit b_typedef;
bit b_inline;
bit b_virtual;
bit b_short;
bit b_long;
char b_bits; /* number of bits in field */
char b_offset; // bit offset of field
TOK b_sto; /* AUTO STATIC EXTERN REGISTER 0 */
Pname b_name; /* name of non-basic type */
Ptable b_table; /* memtbl for b_name, or 0 */
Pexpr b_field; /* field size expression for a field */
Pname b_xname; /* extra name */
Ptype b_fieldtype;
basetype(TOK, Pname);
Pbase type_adj(TOK);
Pbase base_adj(Pbase);
Pbase name_adj(Pname);
Pname aggr();
void normalize();
#ifndef GRAM
Pbase check(Pname);
void dcl_print();
Pbase arit_conv(Pbase);
#endif
};
struct fct : type // FCT
{
TOK nargs;
TOK nargs_known; // KNOWN, ELLIPSIS, or 0
char f_virtual; // 1+index in virtual table, or 0
char f_inline; // 1 if inline, 2 if being expanded, else 0
Ptype returns;
Pname argtype;
Ptype s_returns;
Pname f_this;
Pclass memof; // member of class memof
Pblock body;
Pname f_init; // base/member initializers
// null name => base class init;
// ids => member classes (with ctors)
Pexpr b_init; // base class initializer
// ctor call after fct.dcl()
// int frame_size;
Pexpr f_expr; // body expanded into an expression
Pexpr last_expanded;
Pname f_result; // extra second argument of type X&
fct(Ptype, Pname, TOK);
void argdcl(Pname,Pname);
#ifndef GRAM
Ptype normalize(Ptype);
void dcl_print();
void dcl(Pname);
Pexpr base_init(Pname, Pexpr, Ptable);
Pexpr mem_init(Pname, Pexpr, Ptable);
bit declared() { return nargs_known; };
void simpl();
Pexpr expand(Pname,Ptable,Pexpr);
#endif
};
struct name_list {
Pname f;
Plist l;
name_list(Pname ff, Plist ll) { f=ff; l=ll; };
};
#ifndef GRAM
struct gen : type { // OVERLOAD
Plist fct_list;
char* string;
gen(char*);
Pname add(Pname, int);
Pname find(Pfct, bit);
};
#endif
struct pvtyp : type {
Ptype typ;
};
struct vec : pvtyp // VEC
// typ [ dim ]
{
Pexpr dim;
int size;
vec(Ptype t, Pexpr e) { Nt++; base=VEC; typ=t; dim=e; };
#ifndef GRAM
Ptype normalize(Ptype);
#endif
};
struct ptr : pvtyp // PTR, RPTR i.e. reference
{
Pclass memof; // pointer to member of memof: memof::*
bit rdo; // "*const"
ptr(TOK b, Ptype t, bit r = 0) { Nt++; base=b; typ=t; rdo=r; };
#ifndef GRAM
Ptype normalize(Ptype);
#endif
};
#ifndef GRAM
inline Pptr type::addrof() { return new ptr(PTR,this,0); }
extern bit vrp_equiv;
#endif
/****************************** constants ********************************/
/* STRING ZERO ICON FCON CCON ID */
/* IVAL FVAL LVAL */
/***************************** expressions ********************************/
#ifndef GRAM
extern Pexpr next_elem();
extern void new_list(Pexpr);
extern void list_check(Pname, Ptype, Pexpr);
extern Pexpr ref_init(Pptr,Pexpr,Ptable);
extern Pexpr class_init(Pexpr,Ptype,Pexpr,Ptable);
extern Pexpr check_cond(Pexpr, TOK, Ptable);
#endif
struct expr : node /* PLUS, MINUS, etc. */
/* IMPORTANT: all expressions are of sizeof(expr) */
/* DEREF => *e1 (e2==0) OR e1[e2]
UMINUS => -e2
INCR (e1==0) => ++e2
INCR (e2==0) => e1++
CM => e1 , e2
ILIST => LC e1 RC (an initializer list)
a Pexpr may denote a name
*/
{
union {
Ptype tp;
int syn_class;
};
union {
Pexpr e1;
char* string;
int i1;
};
union {
Pexpr e2;
Pexpr n_initializer;
char* string2;
};
union { /* used by the derived classes */
Ptype tp2;
Pname fct_name;
Pexpr cond;
Pname mem;
Ptype as_type;
Ptable n_table;
Pin il;
};
expr(TOK, Pexpr, Pexpr);
~expr();
#ifndef GRAM
void del();
void print();
Pexpr typ(Ptable);
int eval();
int lval(TOK);
Ptype fct_call(Ptable);
Pexpr address();
Pexpr contents();
void simpl();
Pexpr expand();
bit not_simple();
Pexpr try_to_overload(Ptable);
Pexpr docast(Ptable);
Pexpr dovalue(Ptable);
Pexpr donew(Ptable);
void simpl_new();
void simpl_delete();
#endif
};
struct texpr : expr { // NEW CAST VALUE
texpr(TOK bb, Ptype tt, Pexpr ee) : (bb,ee,0) {this=0; tp2=tt;}
};
struct ival : expr { // NEW CAST VALUE
ival(int ii) : (IVAL,0,0) {this=0; i1 = ii;}
};
struct call : expr { // CALL
call(Pexpr aa, Pexpr bb) : (CALL,aa,bb) { this=0; }
#ifndef GRAM
void simpl();
Pexpr expand(Ptable);
#endif
};
struct qexpr : expr { // QUEST cond ? e1 : e2
qexpr(Pexpr ee, Pexpr ee1, Pexpr ee2) : (QUEST,ee1,ee2) { this=0; cond=ee; }
};
struct ref : expr { // REF DOT e1->mem OR e1.mem
ref(TOK ba, Pexpr a, Pname b) : (ba,a,0) { this=0; mem=b; }
};
struct text_expr : expr { // TEXT
text_expr(char* a, char* b) : (TEXT,0,0) { string=a; string2=b; }
};
/************************* names (are expressions) ****************************/
struct name : expr { // NAME TNAME and the keywords in the ktbl
TOK n_oper; // name of operator or 0
TOK n_sto; // EXTERN STATIC AUTO REGISTER ENUM 0
TOK n_stclass; // STATIC AUTO REGISTER 0
TOK n_scope; // EXTERN STATIC FCT ARG PUBLIC 0
unsigned char n_union; // 0 or union index
bit n_evaluated; // 0 or n_val holds the value
bit n_xref; // argument of type X(X&)
unsigned char lex_level;
TOK n_protect; // PROTECTED (<=>n_scope==0) or 0
short n_addr_taken;
short n_used;
short n_assigned_to;
Loc where;
int n_val; // the value of n_initializer
// also used as the argument number
// for inline arguments
int n_offset; // byte offset in frame or struct
Pname n_list;
Pname n_tbl_list;
union {
Pname n_qualifier; // name of containing class
Ptable n_realscope; /* for labels (always entered in
function table) the table for the
actual scope in which label occurred.
*/
};
name(char* =0);
~name();
Pname normalize(Pbase, Pblock, bit);
Pname tdef();
Pname tname(TOK);
void hide();
void unhide() { n_key=0; n_list=0; };
#ifndef GRAM
Pname dcl(Ptable,TOK);
int no_of_names();
void use() { n_used++; };
void assign();
void take_addr() { n_addr_taken++; };
void check_oper(Pname);
void simpl();
void del();
void print();
void dcl_print(TOK);
void field_align();
Pname dofct(Ptable,TOK);
#endif
};
#ifndef GRAM
extern int friend_in_class;
#endif
/******************** statements *********************************/
struct stmt : node { /* BREAK CONTINUE DEFAULT */
/* IMPORTANT: all statement nodes have sizeof(stmt) */
Pstmt s;
Pstmt s_list;
Loc where;
union {
Pname d;
Pexpr e2;
Pstmt has_default;
int case_value;
Ptype ret_tp;
};
union {
Pexpr e;
bit own_tbl;
Pstmt s2;
};
Ptable memtbl;
union {
Pstmt for_init;
Pstmt else_stmt;
Pstmt case_list;
bit empty;
};
stmt(TOK, loc, Pstmt);
~stmt();
#ifndef GRAM
void del();
void print();
void dcl();
void reached();
Pstmt simpl();
Pstmt expand();
Pstmt copy();
#endif
};
#ifndef GRAM
extern char* Neval;
extern Pname dcl_temp(Ptable, Pname);
extern char* temp(char*, char*, char*);
extern Ptable scope;
extern Ptable expand_tbl;
extern Pname expand_fn;
#endif
struct estmt : stmt /* SM WHILE DO SWITCH RETURN CASE */
/* SM (e!=0) => e;
in particular assignments and function calls
SM (e==0) => ; (the null statement)
CASE => case e : s ;
*/
{
estmt(TOK t, loc ll, Pexpr ee, Pstmt ss) : (t,ll,ss) { this=0; e=ee; }
};
struct ifstmt : stmt /* IF */
// else_stme==0 => if (e) s
// else_stmt!=0 => if (e) s else else_stmt
{
ifstmt(loc ll, Pexpr ee, Pstmt ss1, Pstmt ss2)
: (IF,ll,ss1) { this=0; e=ee; else_stmt=ss2; };
};
struct lstmt : stmt /* LABEL GOTO */
/*
d : s
goto d
*/
{
lstmt(TOK bb, loc ll, Pname nn, Pstmt ss) : (bb,ll,ss) { this=0; d=nn; }
};
struct forstmt : stmt { // FOR
forstmt(loc ll, Pstmt fss, Pexpr ee1, Pexpr ee2, Pstmt ss)
: (FOR,ll,ss) { this=0; for_init=fss; e=ee1; e2=ee2; }
};
struct block : stmt { // BLOCK { d s }
block(loc ll, Pname nn, Pstmt ss) : (BLOCK,ll,ss) { this=0; d=nn; }
#ifndef GRAM
void dcl(Ptable);
Pstmt simpl();
#endif
};
#ifndef GRAM
struct pair : public stmt { // PAIR
pair(loc ll, Pstmt a, Pstmt b) : (PAIR,ll,a) { this=0; s2 = b; }
};
#endif
struct nlist {
Pname head;
Pname tail;
nlist(Pname);
void add(Pname n) { tail->n_list = n; tail = n; };
void add_list(Pname);
};
extern Pname name_unlist(nlist*);
struct slist {
Pstmt head;
Pstmt tail;
slist(Pstmt s) { Nl++; head = tail = s; };
void add(Pstmt s) { tail->s_list = s; tail = s; };
};
extern Pstmt stmt_unlist(slist*);
struct elist {
Pexpr head;
Pexpr tail;
elist(Pexpr e) { Nl++; head = tail = e; };
void add(Pexpr e) { tail->e2 = e; tail = e; };
};
extern Pexpr expr_unlist(elist*);
#ifndef GRAM
extern class dcl_context * cc;
struct dcl_context {
Pname c_this; /* current fct's "this" */
Ptype tot; /* type of "this" or 0 */
Pname not; /* name of "this"'s class or 0 */
Pclass cot; /* the definition of "this"'s class */
Ptable ftbl; /* current fct's symbol table */
Pname nof; /* current fct's name */
void stack() { cc++; *cc = *(cc-1); };
void unstack() { cc--; };
};
#define MAXCONT 20
extern dcl_context ccvec[MAXCONT];
#endif
extern void yyerror(char*);
extern TOK back;
#ifndef GRAM
extern char* line_format;
extern Plist isf_list;
extern Pstmt st_ilist;
extern Pstmt st_dlist;
extern Ptable sti_tbl;
extern Ptable std_tbl;
Pexpr try_to_coerce(Ptype, Pexpr, char*, Ptable);
extern bit can_coerce(Ptype, Ptype);
extern Ptype np_promote(TOK, TOK, TOK, Ptype, Ptype, TOK);
extern void new_key(char*, TOK, TOK);
extern Pname dcl_list;
extern int over_call(Pname, Pexpr);
extern Pname Nover;
extern Pname Ntncheck;
extern Pname Ncoerce;
extern Nover_coerce;
const MIA = 8;
struct iline {
Pname fct_name; /* fct called */
Pin i_next;
Ptable i_table;
Pname local[MIA]; /* local variable for arguments */
Pexpr arg[MIA]; /* actual arguments for call */
Ptype tp[MIA]; /* type of formal arguments */
};
extern Pexpr curr_expr;
extern Pin curr_icall;
#define FUDGE111 111
extern Pstmt curr_loop;
extern Pblock curr_block;
extern Pstmt curr_switch;
extern bit arg_err_suppress;
extern loc last_line;
extern no_of_undcl;
extern no_of_badcall;
extern Pname undcl, badcall;
extern int strlen(const char*);
extern char* strcpy(char*, const char*);
extern int str_to_int(const char*);
extern int c_strlen(const char* s);
#endif
extern int strcmp(const char*, const char*);
#ifndef GRAM
extern Pname vec_new_fct;
extern Pname vec_del_fct;
extern int Nstd; // standard coercion used (derived* =>base* or int=>long or ...)
extern int stcount; // number of names generated using make_name()
extern Pname find_hidden(Pname);
Pexpr replace_temp(Pexpr,Pexpr);
void make_res(Pfct);
Pexpr ptr_init(Pptr,Pexpr,Ptable);
#endif
extern bit fake_sizeof; // suppress error message for ``int v[];''
extern TOK lalex();
#ifdef DEBUG
extern fprintf(FILE*, char* ...);
#define DB(a) fprintf a
#else
#define DB(a) /**/
#endif
/* end */

Binary file not shown.

View file

@ -0,0 +1,82 @@
/* ======================================================================= */
/* CLHEIR.H */
/* ======================================================================= */
// CLASS HEIRARCHY
// Locations or Agents are both of type generic_object. Generic_objects may
// have states, and are responsible for updating their states appropriately
// when their step() functions are executed.
extern void init_registry(void);
extern void step_everybody(void);
class generic_object
{
int where_in_registry;
public:
generic_object(); // enter generic_object into ObjectRegistry
// We never copy generic_objects, so we don't need a copy constructor.
~generic_object(void); // delete from ObjectRegistry
// Simulation steps, accomodate different kinds of time
virtual void compute_next_state(void) { }
virtual void step(void) { }
};
// =======================================================================
// Locations can be regular (like a field of squares or hexagons) or
// irregular. Regular locations have 2-D or 3-D positions represented
// by integers. Locations are never copied; no need for copy constructors.
const int max_num_directions = 6; // handles both cubes and hexagons
class location: public generic_object
{
// Any kind of location needs a physical position, but for a regular
// location, this may be implicit, and for an irregular location, it
// should be custom-defined.
// Any kind of location needs a private list of neighbors, but for a
// regular location, this may be implicit.
public:
location() { }
~location();
};
class irregular_location: public location
{
double x, y, z;
public:
irregular_location(double xi, double yi, double zi)
{ x = xi; y = yi; z = zi; }
~irregular_location();
};
class discrete_location: public location
{
int x, y, z;
class location *neighbors[max_num_directions];
void clear_neighbors(void);
public:
discrete_location(int xi, int yi, int zi):
x(xi), y(yi), z(zi)
{ clear_neighbors(); }
~discrete_location(void);
void assign_neighbor(int direction, location *x)
{ neighbors[direction] = x; }
};
// =======================================================================
// Agents are generic_objects with locations, who can move. Examples in
// Pacman would be the protagonist, the monsters, and the monsters' ghosts.
class agent: public generic_object
{
location *where;
public:
agent();
~agent();
void move(int);
};

View file

@ -0,0 +1,95 @@
/* ======================================================================= */
/* CONWAY.CPP */
/* ======================================================================= */
#include "assert.h"
#include "iostream.h"
#include "conio.h"
#include "clheir.h"
#include "screen.h"
#include "conway.h"
#define max(x,y) ((x > y) ? x : y)
#define min(x,y) ((x > y) ? y : x)
const int num_rows = min(50, NUM_ROWS);
const int num_columns = 40;
class site *field_of_play[num_rows][num_columns];
int site::total_surrounding(void)
{
int i, j, imin, imax, jmin, jmax, total;
total = 0;
imin = max(0, x - 1);
imax = min(num_rows - 1, x + 1);
jmin = max(0, y - 1);
jmax = min(num_columns - 1, y + 1);
for (i = imin; i <= imax; i++)
for (j = jmin; j <= jmax; j++)
if (field_of_play[i][j]->read()) total++;
if (alive) total--;
return total;
}
void display(void)
{
int i, j;
for (i = 0; i < num_rows; i++)
for (j = 0; j < num_columns; j++)
{
if (field_of_play[i][j]->read()) write_xyc(2*j, i, 'X');
else write_xyc(2*j, i, '.');
}
hide_cursor();
}
void glider(int x, int y)
{
field_of_play[x - 1][y + 0]->set();
field_of_play[x - 1][y + 1]->set();
field_of_play[x + 0][y - 1]->set();
field_of_play[x + 0][y + 0]->set();
field_of_play[x + 1][y + 1]->set();
}
void traffic_light(int x, int y)
{
field_of_play[x - 1][y]->set();
field_of_play[x + 0][y]->set();
field_of_play[x + 1][y]->set();
}
void main(void)
{
int i, j, c;
init_registry();
for (i = 0; i < num_rows; i++)
for (j = 0; j < num_columns; j++)
field_of_play[i][j] = new site(i, j);
start_over:
traffic_light(num_rows/2 - 8, num_columns/2 - 8);
glider(num_rows/2 + 8, num_columns/2 + 8);
clear_screen();
while (1)
{
display();
if ((c = getch()) == 'q') { clear_screen(); return; }
if (c == 'i')
{
for (i = 0; i < num_rows; i++)
for (j = 0; j < num_columns; j++)
field_of_play[i][j]->clear();
goto start_over;
}
step_everybody();
}
}

View file

@ -0,0 +1,23 @@
/* ======================================================================= */
/* CONWAY.H */
/* ======================================================================= */
class site: public location
{
char x, y, alive, next_alive;
int total_surrounding(void);
public:
site(int xi, int yi): x(xi), y(yi), alive(0) { }
~site();
char read() { return alive; }
void set(void) { alive = 1; }
void clear(void) { alive = 0; }
void compute_next_state(void)
{
int n = total_surrounding();
next_alive = alive;
if (n < 2 || n > 3) next_alive = 0;
else if (n > 2) next_alive = 1;
}
void step(void) { alive = next_alive; }
};

52
test/etags/cp-src/fail.C Normal file
View file

@ -0,0 +1,52 @@
/* Examples provided by Sam Kendall <kendall@mv.mv.com>, Jan 1997 */
// check use of references with nested/local classes
// This example causes etags 13 to abort when compiled with -DDEBUG.
// Etags 13 cannot deal with nested structures after the first level.
struct A {
struct B {
struct C {
int x;
C(int i) {x = i;}
operator int() const {return x;}
};
typedef C T;
};
typedef B T2;
};
class String;
class A {
class B {
class C {};
int f() { return 5; }
};
};
int A::B::f() { return 2; }
A::B::C abc(-37);
main()
{
if (abc != -37 || abt != -37) return 1;
class D : public A::B::C {
public:
D() : ::A::T2::T(97), x(1066) {}
int x;
} &d = D();
if (d.x != 1066 || d.A::T2::T::x != 97) return 2;
return 0;
}
template <class T>

View file

@ -0,0 +1,239 @@
#include "main.hpp"
#pragma ident "@(#)functions.cpp 1.0 98/11/12 (c) Rupak Rathore"
// Constructor default argument initialises to today's values
void Date::setDate ( int d , int m , int y ){
time_t t;
struct tm * ptm;
t = time ( NULL ) ;
if ( date != NULL )
delete date;
date = NULL;
if ( d == 0 && m == 0 && y == 0 ) // explicity called or default constructor hence leave it.
return;
if ( d < 0 && m < 0 && d < 0 ) // Special instruction to intialise to today's value
d=m=y=0;
date = new tm;
ptm=localtime ( &t ) ;
*date=(*ptm);
if ( d )
date->tm_mday = d;
if ( m )
date->tm_mon = m - 1; // Months are counted from January
if ( y > 1900 ) // Complete year specified so take into account
y -= 1900;
if ( y )
date->tm_year = y;
date->tm_sec=date->tm_min=date->tm_hour=0;
t = mktime ( date ) ;
}
// Addition operation ::: Warning ::: A combination of addition and substraction does not give a proper result
void Date::plus ( int days , int month , int year ){
if ( ! set () )
return;
date->tm_mday += days ;
date->tm_mon += month ;
date->tm_year += year ;
mktime ( date );
}
//Substraction operation ::: Warning ::: A combination of addition and substraction does not give a proper result
void Date::minus ( int days , int month , int year ){
if ( ! set () )
return;
date->tm_mday -= days ;
date->tm_mon -= month ;
date->tm_year -= year ;
mktime ( date );
}
void Date::shift ( void ){//Shift this date to previous working days (useful for benchmarks)
if ( ! set() )
return ;
while(isHoliday(*this)||isweekend()){
date->tm_mday -= 1 ;
mktime ( date );
}
}
// Assignment
Date & Date::operator = ( Date d ){
if ( d.set() )
setDate ( d.date->tm_mday, d.date->tm_mon + 1, d.date->tm_year );
return(*this);
}
// Add number of days
Date & Date::operator += ( int days ){
if ( set () ){
date->tm_mday += days ;
mktime ( date );
}
return(*this);
}
// Substract number of days
Date & Date::operator -= ( int days ){
if ( set () ){
date->tm_mday -= days ;
mktime ( date );
}
return(*this);
}
// Advance one day
Date & Date::operator ++ ( void ){
if ( set () ){
date->tm_mday += 1 ;
mktime ( date );
}
return(*this);
}
// Backwards one day
Date & Date::operator -- ( void ){
if ( set () ){
date->tm_mday -= 1 ;
mktime ( date );
}
return(*this);
}
int Date::operator - ( Date d ){
long l;
if (( ! set() ) || (! d.set()))
return(0);
l=(mktime(date)-mktime(d.date))/(3600*24);
return((int)l);
}
int Date::operator < ( Date d ) {
return ( unidate() < d.unidate() );
}
int Date::operator > ( Date d ) {
return ( unidate() > d.unidate() );
}
int Date::operator == ( Date d ) {
return ( unidate() == d.unidate() );
}
ostream& operator << ( ostream &c, Date d ) {
if ( ! d.set() )
c << "Null";
else
c << d.date->tm_mday << ":" << d.date->tm_mon + 1 << ":" << d.date->tm_year + 1900 ;
return ( c );
}
// Modified to read date in yyyymmdd format.
istream& operator >> ( istream &i, Date & dd ){
int d,m,y,tmp;
i >> tmp;
d=tmp%100;
tmp/=100;
m=tmp%100;
tmp/=100;
y=tmp;
dd.setDate(d,m,y);
return(i);
}
/*
istream& operator >> ( istream &i, Date &dd ) {
char input[11];
int d,m,y;
cout << "Enter the date ( dd-mm-yyyy ) : ";
i >> input ;
d = ( input[0] - '0' ) * 10 + ( input[1] - '0' );
m = ( input[3] - '0' ) * 10 + ( input[4] - '0' );
y = ( input[6] - '0' ) * 1000 + ( input[7] - '0' ) * 100 + ( input[8] - '0' ) * 10 + ( input[9] - '0' );
dd.setDate ( d, m, y );
return ( i );
}
*/
// Check whether given year is leap or not
bool isLeap ( int year ){
return ( (year%100==0) ? (year%400==0) : (year%4==0) );
}
bool isHoliday ( Date d ){
long int ld;
ld = ( d.year()*100 + d.month() )*100 + d.day();
for ( int i=0; i<no_of_vacations;i++)
if ( ld == vacation[i] )
return(true);
return(false);
}
// Sort the given array in ascending order
void asort(int *a, int num){
int i,k,mini,tmp;
for ( k=1; k<num; k++ ){
mini=k-1;
for ( i=k; i<num; i++ )
if ( a[mini] > a[i] ) {
tmp=a[i];
a[i]=a[mini];
a[mini]=tmp;
}
}
}
void ReadVacation ( char *filename ) {
// cerr << filename;
ifstream vacfile(filename);
if ( ! vacfile.good() )
d_error("ReadVacation","Unable to find the vacation and holidays file");
// cerr << filename ;
d_silent("ReadVacation","vacation file successfully opened.");
no_of_vacations = 0;
while ( !vacfile.eof() )
vacfile >> vacation[no_of_vacations++];
--no_of_vacations;
d_silent("ReadVacation","Finished Reading file");
vacfile.close();
}
void Debug ( int lineno, int level, char* func , char* mesg ) // error_level, function, message
{
if ( debug_level <= level )
cerr << PROGNAME << ": " << func << ": " << lineno << ": " << debug_string[level] << ": " << mesg << endl;
if ( level == ERROR ){
cerr << PROGNAME << ": Exiting because of fatal error." <<endl ;
exit(2);
}
}
int WorkingDays(Date a, Date b){
Date tmp;
int wdays=0,days=0;
if ( (! a.set()) || (! b.set()) )
return(0);
days=b-a+1; // Inclusive
tmp=a;
for ( int i=0;i<days;i++){
if((!isHoliday(tmp))&&(!tmp.isweekend()))
wdays++;
tmp++;
}
return(wdays);
}
Date StartDay(Date a,int days){//Function to calculate the apropriate start day to finish in days working days
Date tmp;
int wdays=0;
if ( ! a.set() )
return (a);
tmp=a;
while(wdays<days){
if((!isHoliday(tmp))&&(!tmp.isweekend()))
wdays++;
tmp--;
}
tmp++;
return(tmp);
}

View file

@ -0,0 +1,62 @@
/* ======================================================================= */
/* SCREEN.CPP */
/* ======================================================================= */
#include "stdio.h"
#include "stdlib.h"
#include "dos.h"
#include "screen.h"
/* ----------------------------------------------------------------------- */
/* Cursor Position and Screen Buffering Functions */
/* ----------------------------------------------------------------------- */
unsigned char cursor_x, cursor_y;
static union REGS regs;
void goto_xy(unsigned char x, unsigned char y)
{
regs.h.ah = 2;
regs.h.bh = 0;
regs.h.dh = y;
regs.h.dl = x;
int86(0x10, &regs, &regs);
}
void hide_cursor(void)
{
goto_xy(0, NUM_ROWS);
}
void cursor_position(void)
{
regs.h.ah = 3;
regs.h.bh = 0;
int86(0x10, &regs, &regs);
cursor_x = regs.h.dl;
cursor_y = regs.h.dh;
}
void clear_screen(void)
{
unsigned int i, j;
char far *p;
p = SCREEN_START;
for (i = 0; i < NUM_ROWS; i++)
for (j = 0; j < 80; j++)
{
*p++ = ' ';
*p++ = LIGHTGRAY;
}
}
void write_xyc(int x, int y, char c)
{
char far *p;
p = SCREEN_FP(x, y);
*p++ = c;
*p = LIGHTGRAY;
}

View file

@ -0,0 +1,39 @@
/* ======================================================================= */
/* SCREEN.H */
/* ======================================================================= */
// This stuff is entirely non-portable MSDOS-ish code. Note the hardware
// address below, for the standard location of the EGA video buffer.
#if !defined(__COLORS)
#define __COLORS
enum COLORS {
BLACK, /* dark colors */
BLUE,
GREEN,
CYAN,
RED,
MAGENTA,
BROWN,
LIGHTGRAY,
DARKGRAY, /* light colors */
LIGHTBLUE,
LIGHTGREEN,
LIGHTCYAN,
LIGHTRED,
LIGHTMAGENTA,
YELLOW,
WHITE
};
#endif
#define SCREEN_FP(x,y) \
((char far *) (0xB8000000L | ((unsigned) (160 * (y) + 2 * (x)))))
#define SCREEN_START SCREEN_FP(0, 0)
void goto_xy(unsigned char x, unsigned char y);
void hide_cursor(void);
void cursor_position(void);
void clear_screen(void);
void write_xyc(int x, int y, char c);

View file

@ -0,0 +1,31 @@
(foo::defmumble bletch beuarghh)
;;; Ctags test file for lisp mode.
;; from emacs/lisp/delsel.el:76:
(defalias 'pending-delete-mode 'delete-selection-mode)
;; compare with:
(defalias (quote explicitly-quoted-pending-delete-mode) 'delete-selection-mode)
;;
;; Output from original ctags:
;;
;'pending-delete-mode tagstest.el /^(defalias 'pending-delete-mode 'delete-selection-m/
;(quote tagstest.el /^(defalias (quote explicitly-quoted-pending-delete-/
;;
;; Output from ctags with my patch in L-getit():
;;
;pending-delete-mode tagstest.el /^(defalias 'pending-delete-mode 'delete-selection-m/
;explicitly-quoted-pending-delete-mode tagstest.el /^(defalias (quote explicitly-quoted-pending-delete-/
;; Output from original etags:
;;
;tagstest.el,61
;(defalias 'pending-delete-mode 4,68
;(defalias (quote 7,141
;;
;; Output from patched etags:
;;
;tagstest.el,99
;(defalias 'pending-delete-mode 4,68
;(defalias (quote explicitly-quoted-pending-delete-mode)7,141
;;

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,271 @@
-module(gs_dialog). % behaviour
-define(VERSION, '2001.1101').
-vsn(?VERSION).
-author('cpressey@catseye.mb.ca').
-copyright('Copyright (c)2001 Cat`s Eye Technologies. All rights reserved.').
%%% Redistribution and use in source and binary forms, with or without
%%% modification, are permitted provided that the following conditions
%%% are met:
%%%
%%% Redistributions of source code must retain the above copyright
%%% notice, this list of conditions and the following disclaimer.
%%%
%%% Redistributions in binary form must reproduce the above copyright
%%% notice, this list of conditions and the following disclaimer in
%%% the documentation and/or other materials provided with the
%%% distribution.
%%%
%%% Neither the name of Cat's Eye Technologies nor the names of its
%%% contributors may be used to endorse or promote products derived
%%% from this software without specific prior written permission.
%%%
%%% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
%%% CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
%%% INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
%%% MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
%%% DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
%%% LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
%%% OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
%%% PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
%%% OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
%%% ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
%%% OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
%%% OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
%%% POSSIBILITY OF SUCH DAMAGE.
-export([behaviour_info/1,
show/4,
test/0]).
%%% BEGIN gs_dialog.erl %%%
%%% This module specifies a common behaviour for "modal" dialog boxes
%%% using GS.
%%--------------------------------------------------------------------
%% behaviour_info(callbacks) -> ListOfFunctionArityTuples
%% Used by R8 to check the implementation modules for consistency
%% with the behaviour specification, what callbacks this module needs.
behaviour_info(callbacks) ->
[
%%----------------------------------------------------------------
%% Module:buttons() -> ListOfAtoms
%% Should return the labels used on the main (non-extra) buttons
%% of the dialog box.
%% e.g. ['OK', 'Cancel'].
{buttons, 0},
%%----------------------------------------------------------------
%% Module:icon() -> FileNameString | {Text, FgColour, BgColour}
%% Should return the the icon displayed in the dialog box.
%% This should either be the fully qualified filename of a 32x32 GIF
%% file (e.g. in the application's priv dir,) or a 3-tuple
%% describing a simple "circle" icon to be rendered by GS itself.
%% The latter option was added because some versions of Erlang for
%% Windows use a Tk emulation package which is not always on the
%% ball when it comes to correct image transparency and colour.
%% e.g. filename:join(code:priv_dir(?MODULE), "notify.gif")
{icon, 0},
%%----------------------------------------------------------------
%% Module:controls(Parent, ArgList) -> {GSControl | nil, NewArgList}
%% Used by the implementation to provide extra controls in the dialog
%% box, if any. If not, nil should be returned instead of the control.
%% If many controls are added, it is recommended they are placed in a
%% frame, with the frame returned as the control.
%% The control need not have positioning information, as it will be
%% assigned a pack_xy option when it is placed into the Parent frame.
%% The list of arguments may be modified by this callback.
%% e.g. {nil, Args}
{controls, 2},
%%----------------------------------------------------------------
%% Module:on_key(ExtraControl, KeyAtom, ArgList) ->
%% {button, ButtonNameAtom} | nil
%% Called when a key is pressed in the dialog box. The return value
%% specified whether it is linked to pressing a button, or whether it
%% it is ignored and passed on to a further handler (if any.)
{on_key, 3},
%%----------------------------------------------------------------
%% Module:on_button(ExtraControl, ButtonNameAtom, ArgList) -> Result
%% Called when one of the main (non-extra) buttons are pressed in
%% the dialog box. Since this closes the dialog box, the implementation
%% module is expected to provide a final result term with this function.
{on_button, 3},
%%----------------------------------------------------------------
%% Module:on_event(ExtraControl, Event, ArgList) -> Result
%% Allows the implementation module to handle other GS events,
%% e.g. those generated by the extra controls specified.
{on_event, 3}
].
%%% Public Interface
%%--------------------------------------------------------------------
%% show(ModuleNameAtom, TitleString, MessageString, ArgList) -> Result
%% Display a generic modal dialog box, customized by the
%% callback functions in Module. This should be called by
%% the 'show' function in the Module in question.
%% The argument list is passed back to the callback functions in the
%% module, for retaining information pertinent to the callback module;
%% the behaviour itself does not inspect or care about this list.
show(Module, Title, Message, Args) ->
Screen = gs:start(),
Buttons = Module:buttons(),
NumButtons = length(Buttons),
application:load(?MODULE),
{ok, Font} = application:get_env(?MODULE, font),
{ok, {ScreenWidth, ScreenHeight}} =
application:get_env(?MODULE, screen_size),
{ok, {DialogWidth, DialogHeight}} =
application:get_env(?MODULE, dialog_size),
Window = gs:create(window, Screen,
[{width, DialogWidth}, {height, DialogHeight},
{x, (ScreenWidth - DialogWidth) div 2},
{y, (ScreenHeight - DialogHeight) div 2},
{title, Title},
{configure, true}, {keypress, true}]),
Frame = gs:create(frame, Window,
[{bw, 0},
{packer_x, lists:duplicate(NumButtons, {stretch, 1})},
{packer_y, [{stretch, 1},{stretch, 2},{stretch, 1}]}]),
case Module:icon() of
nil ->
Label = gs:create(label, Frame,
[{label, {text, Message}}, {font, Font}, {justify, center},
{pack_xy, {{1, NumButtons}, 1}}]);
{Text, Fg, Bg} ->
InnerFrame = gs:create(frame, Frame,
[{pack_xy, {{1, NumButtons}, 1}}, {bw, 0},
{packer_x, [{stretch, 1}, {fixed, 32}, {stretch, 8}]},
{packer_y, [{stretch, 1}, {fixed, 32}, {stretch, 1}]}]),
IconCanvas = gs:create(canvas, InnerFrame,
[{pack_xy, {2, 2}}]),
IconCircle = gs:create(oval, IconCanvas,
[{coords, [{0, 0}, {31, 31}]}, {fg, black}, {fill, Bg}]),
IconFont = {screen, bold, 24},
{ITW,ITH} = gs:read(IconCanvas, {font_wh, {IconFont, Text}}),
ITX = 16 - ITW div 2,
ITY = 16 - ITH div 2,
IconText = gs:create(text, IconCanvas,
[{coords, [{ITX, ITY}]}, {fg, Fg}, {text, Text}, {font, IconFont}]),
Label = gs:create(label, InnerFrame,
[{label, {text, Message}}, {font, Font}, {justify, center},
{pack_xy, {3, {1,3}}}]);
FileName when list(FileName) ->
InnerFrame = gs:create(frame, Frame,
[{pack_xy, {{1, NumButtons}, 1}}, {bw, 0},
{packer_x, [{stretch, 1}, {fixed, 32}, {stretch, 8}]},
{packer_y, [{stretch, 1}, {fixed, 32}, {stretch, 1}]}]),
IconCanvas = gs:create(canvas, InnerFrame,
[{pack_xy, {2, 2}}]),
Icon = gs:create(image, IconCanvas, [{coords, [{0, 0}]},
{load_gif, FileName}]),
Label = gs:create(label, InnerFrame,
[{label, {text, Message}}, {font, Font}, {justify, center},
{pack_xy, {3, {1,3}}}])
end,
{Extra, NewArgs} = Module:controls(Frame, Args),
case Extra of
nil -> gs:config(Frame, {packer_y, [{stretch, 2},{fixed, 0},{stretch, 1}]});
_ -> gs:config(Extra, {pack_xy, {{1, NumButtons}, 2}})
end,
lists:foldl(fun(X, A) ->
I = gs:create(frame, Frame, [{packer_x, [{stretch, 1}, {fixed, 80}, {stretch, 1}]},
{packer_y, [{stretch, 1}, {fixed, 24}, {stretch, 1}]},
{pack_xy, {A, 3}}]),
gs:create(button, I, [{label, {text, atom_to_list(X)}}, {font, Font},
{data, {button, X}},
{pack_xy, {2, 2}}]),
A + 1
end, 1, Buttons),
gs:config(Frame, [{width, DialogWidth}, {height, DialogHeight}]),
{MessageWidth, MessageHeight} = gs:read(Frame, {font_wh, {Font, Message}}),
case MessageWidth of
N1 when N1 > trunc(DialogWidth * 0.8) ->
NewDialogWidth = trunc(MessageWidth * 1.2),
gs:config(Window,
[{width, NewDialogWidth},
{x, (ScreenWidth - NewDialogWidth) div 2}]);
_ -> ok
end,
case MessageHeight of
N2 when N2 > trunc(DialogHeight * 0.666) ->
NewDialogHeight = trunc(MessageHeight * 1.666),
gs:config(Window,
[{height, NewDialogHeight},
{y, (ScreenHeight - NewDialogHeight) div 2}]);
_ -> ok
end,
gs:config(Window, {map, true}),
dialog_loop(Module, Window, Frame, Extra, NewArgs).
%%--------------------------------------------------------------------
%% dialog_loop(Module, Window, Frame, Extra, Args) -> Result
%% Called by show/4, handles generic events in a dialog box.
dialog_loop(Module, Window, Frame, Extra, Args) ->
receive
{gs, Window, destroy, Data, EventArgs} ->
Module:on_button(Extra, 'Cancel', Args);
{gs, Window, configure, Data, [W,H | Rest]} ->
gs:config(Frame, [{width, W}, {height, H}]),
dialog_loop(Module, Window, Frame, Extra, Args);
{gs, Window, keypress, Data, [KeyCode | Rest]} ->
case Module:on_key(Extra, KeyCode, Args) of
{button, ButtonType} ->
Return = Module:on_button(Extra, ButtonType, Args),
gs:destroy(Window),
Return;
_ -> dialog_loop(Module, Window, Frame, Extra, Args)
end;
{gs, Button, click, {button, ButtonType}, EventArgs} ->
Return = Module:on_button(Extra, ButtonType, Args),
gs:destroy(Window),
Return;
Other -> % io:fwrite("~w~n", [Other]),
case Module:on_event(Extra, Other, Args) of
{button, ButtonType} ->
Return = Module:on_button(Extra, ButtonType, Args),
gs:destroy(Window),
Return;
_ -> dialog_loop(Module, Window, Frame, Extra, Args)
end
end.
%%--------------------------------------------------------------------
%% test() -> ResultTuple.
%% Tests some of the common dialog boxes implemented with this behaviour.
test() ->
A = gs_dialog_notify:show("Notification", "This is a notification dialog."),
B = gs_dialog_confirm:show("Confirmation",
"Are you sure you want to\ntake some sort of drastic action?"),
C = gs_dialog_question:show("Question", "Save your barcodes first?"),
D = gs_dialog_entry:show("Text Entry",
"Enter the address of this order:", "555 Twenty-third St."),
E = gs_dialog_list:show("Select One", "Select a game to play.",
["Chess", "Checkers", "Othello", "Go", "Backgammon", "Kali", "Sink"]),
F = gs_dialog_color:show("Choose Colour", "Pick your favourite colour.",
{255, 0, 128}),
G = gs_dialog_notify:show("Lengthy Notification",
"This is an extremely long message with no line breaks. "
"The dialog box should expand to display the entire message."),
H = gs_dialog_notify:show("Lengthy Notification",
"This is an extremely\nlong message with\nmany lines.\n\n"
"The dialog box\nshould\nexpand\nto\ndisplay\nthe\nentire\nmessage."),
{A,B,C,D,E,F,G,H}.
%%% END of gs_dialog.erl %%%

View file

@ -0,0 +1,297 @@
%%% The contents of this file are subject to the Erlang Public License,
%%% Version 1.0, (the "License"); you may not use this file except in
%%% compliance with the License. You may obtain a copy of the License at
%%% http://www.erlang.org/license/EPL1_0.txt
%%%
%%% Software distributed under the License is distributed on an "AS IS"
%%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
%%% the License for the specific language governing rights and limitations
%%% under the License.
%%%
%%% The Original Code is lines-1.0.
%%%
%%% The Initial Developer of the Original Code is Ericsson Telecom
%%% AB. Portions created by Ericsson are Copyright (C), 1998, Ericsson
%%% Telecom AB. All Rights Reserved.
%%%
%%% Contributor(s): ______________________________________.
%%%----------------------------------------------------------------------
%%% #0. BASIC INFORMATION
%%%----------------------------------------------------------------------
%%% File: lines.erl
%%% Author : Ulf Wiger <ulf.wiger@ericsson.com>
%%% Description : Efficient array of lines (e.g. for text editor)
%%%
%%% Modules used : lists
%%%
%%%----------------------------------------------------------------------
%%% Efficient array of lines (e.g. for text editor)
%%% allows for append, as well as insert, replace, delete in any position
%%% with reasonable access times.
%%% Rough benchmarking indicates (on a 440MHz Ultra):
%%%
%%% NoOfLines Append (uSec) Read (uSec) Delete (uSec)
%%% 100 9 7 7
%%% 1,000 14 10 11
%%% 10,000 22 13 15
%%% 100,000 30 16 18
%%%
%%% Comment on the benchmark: The times for Append and Delete are mean
%%% times for "growing file" and "shrinking file", that is, starting from
%%% an empty array and inserting 100,000 lines took ca 3 seconds; deleting
%%% them took ca 1.8 seconds. The Read test involved accessing all lines
%%% in the full array and calculating the mean time.
%%%
%%% The array doesn't care what goes into each position. In other words,
%%% it can be used for any datatype -- not just lines of text.
%%%----------------------------------------------------------------------
-module(lines).
-vsn('1.0').
-date('00-03-13').
-author('ulf.wiger@ericsson.com').
-export([new/0,
count/1,
nth/2,
append/2,
replace/3,
insert/3,
insert_after/3,
delete/2,
convert_to_list/1,
convert_from_list/1]).
-define(BREAK, 10). % how many lines to store in each leaf
-define(dbg(Fmt, Args), ok=io:format("~p: " ++ Fmt, [?LINE|Args])).
%% new() -> line_array()
%%
%% Creates a new line array.
%%
new() ->
{0, []}.
%% line_count(line_array()) -> integer()
%%
%% Returns the number of lines stored in the array
%%
count({N, _}) ->
N.
%% nth(LineNo : integer(), Array : line_array()) -> line()
%%
%% Returns the line in position LineNo
%%
nth(L, _) when L < 1 ->
exit({out_of_range, L});
nth(L, {LMax, _}) when L > LMax ->
exit({out_of_range, L});
nth(L, {LMax, List}) when list(List) ->
lists:nth(L, List);
nth(L, {LMax, {Left = {LL, _}, Right}}) when L > LL ->
nth(L-LL, Right);
nth(L, {_, {Left, _}}) ->
nth(L, Left).
%% append(Line : line(), Array : line_array()) -> line_array().
%%
%% Appends Line to the end of Array.
%% e.g. append(x, [1,2,3,4]) -> [1,2,3,4,x].
%% Returns the modified array.
%%
append(Line, {L, List}) when list(List), L < ?BREAK ->
{L+1, List ++ [Line]};
append(Line, {L, List}) when list(List) ->
{L+1, {{L, List}, {1, [Line]}}};
append(Line, {L, {Left = {LL1, L1}, Right}}) ->
NewRight = append(Line, Right),
balance_left(L+1, Left, NewRight).
%% replace(LineNo : integer(), Array : line_array(), NewLine : line()) ->
%% line_array().
%%
%% Replaces the line in position LineNo with NewLine.
%% e.g. replace(3, [1,2,3,4], x) -> [1,2,x,4].
%% Returns the modified array.
%%
replace(Lno, _, _) when Lno < 1 ->
exit({out_of_range, Lno});
replace(Lno, {L, _}, NewLine) when Lno > L ->
exit({out_of_range, Lno});
replace(Lno, {L, List}, NewLine) when list(List) ->
{L, replace_nth(Lno, List, NewLine)};
replace(Lno, {L, {Left={LL1, L1}, Right={LL2, L2}}}, NewLine) when Lno > LL1 ->
NewRight = replace(Lno-LL1, Right, NewLine),
{L, Left, NewRight};
replace(Lno, {L, {Left={LL1,L1}, Right={LL2,L2}}}, NewLine) ->
NewLeft = replace(Lno, Left, NewLine),
{L, NewLeft, Right}.
%% insert(LineNo : integer(), Array : line_array(), NewLine) -> line_array().
%%
%% Inserts NewLine *before* the line in position LineNo.
%% e.g. insert(3, [1,2,3,4], x) -> [1,2,x,3,4].
%% Returns the modified array.
%%
insert(Lno, _, _) when Lno < 1 ->
exit({out_of_range, Lno});
insert(Lno, {L, _}, NewLine) when Lno > L ->
exit({out_of_range, Lno});
insert(Lno, {L, List}, NewLine) when list(List) ->
if L < ?BREAK ->
{L+1, insert_nth(Lno, List, NewLine)};
true ->
NewList = insert_nth(Lno, List, NewLine),
{L1, L2} = split_at(?BREAK, NewList),
NewL = L+1,
{NewL, {{?BREAK, L1}, {NewL-?BREAK, L2}}}
end;
insert(Lno, {L, {Left={LL,_}, Right}}, NewLine) when Lno > LL ->
NewRight = insert(Lno-LL, Right, NewLine),
balance_left(L+1, Left, NewRight);
insert(Lno, {L, {Left, Right}}, NewLine) ->
NewLeft = insert(Lno, Left, NewLine),
balance_right(L+1, NewLeft, Right).
%% insert_after(LineNo : integer(), Array : line_array(), NewLine) ->
%% line_array().
%%
%% Inserts NewLine *after* the line in position LineNo.
%% e.g. insert(3, [1,2,3,4], x) -> [1,2,3,x,4].
%% Returns the modified array.
%%
insert_after(Lno, _, _) when Lno < 1 ->
exit({out_of_range, Lno});
insert_after(Lno, {L, _}, NewLine) when Lno > L ->
exit({out_of_range, Lno});
insert_after(Lno, {L, List}, NewLine) when list(List) ->
if L < ?BREAK ->
{L+1, insert_after_nth(Lno, List, NewLine)};
true ->
NewList = insert_after_nth(Lno, List, NewLine),
{L1, L2} = split_at(?BREAK, NewList),
NewL = L+1,
{NewL, {{?BREAK, L1}, {NewL-?BREAK, L2}}}
end;
insert_after(Lno, {L, {Left={LL,_}, Right}}, NewLine) when Lno > LL ->
NewRight = insert_after(Lno-LL, Right, NewLine),
balance_left(L+1, Left, NewRight);
insert_after(Lno, {L, {Left, Right}}, NewLine) ->
NewLeft = insert_after(Lno, Left, NewLine),
balance_right(L+1, NewLeft, Right).
%% delete(LineNo : integer(), Array : line_array()) -> line_array().
%%
%% Deletes the line in position LineNo.
%% e.g. delete(3, [1,2,3,4]) -> [1,2,4].
%% Returns the modified array.
%%
delete(Lno, _) when Lno < 1 ->
exit({out_of_range, Lno});
delete(Lno, {N_Tot, _}) when Lno > N_Tot ->
exit({out_of_range, Lno});
delete(Lno, {N, List}) when list(List) ->
{N-1, delete_nth(Lno, List)};
delete(Lno, {N, {Left = {N_Left, _}, Right}}) when Lno > N_Left ->
case delete(Lno-N_Left, Right) of
{0, _} ->
case N-1 of N_Left -> ok end, % Assert
Left;
NewRight ->
balance_right(N-1, Left, NewRight)
end;
delete(Lno, {N, {Left, Right = {N_Right,_}}}) ->
case delete(Lno, Left) of
{0, _} ->
case N-1 of N_Right -> ok end, % Assert
Right;
NewLeft ->
balance_left(N-1, NewLeft, Right)
end.
convert_to_list({_, List}) when list(List) ->
List;
convert_to_list({L, {Left, Right}}) ->
convert_to_list(Left) ++ convert_to_list(Right).
convert_from_list(L) when list(L) ->
lists:foldl(fun(Ln, Lsx) ->
append(Ln, Lsx)
end, new(), L).
%%% ===========================================================
%%% internal functions
%%% ===========================================================
replace_nth(1, [H|T], X) ->
[X|T];
replace_nth(N, [H|T], X) ->
[H|replace_nth(N-1, T, X)].
insert_nth(1, L, X) ->
[X|L];
insert_nth(N, [H|T], X) ->
[H|insert_nth(N-1, T, X)].
insert_after_nth(1, [H|T], X) ->
[H,X|T];
insert_after_nth(N, [H|T], X) ->
[H|insert_after_nth(N-1, T, X)].
delete_nth(1, [H|T]) ->
T;
delete_nth(N, [H|T]) ->
[H|delete_nth(N-1, T)].
%% split_at(Pos, List) -> {List1, List2}
%% split List into two after position Pos (List1 includes List[Pos])
%%
split_at(Pos, L) ->
split_at(Pos, L, []).
split_at(0, L, Acc) ->
{lists:reverse(Acc), L};
split_at(Pos, [H|T], Acc) ->
split_at(Pos-1, T, [H|Acc]).
%% Balancing functions
%% Since we know whether we inserted/deleted in the right or left subtree,
%% we have explicit balancing functions for each case.
%% We rebalance if the number of elements in one sub-subtree exceeds the
%% sum of elements in the others.
balance_left(N_Tot,
Left = {N_Left, _},
Right = {N_Right, {RLeft = {N_RLeft, _},
RRight = {N_RRight, _}}}) ->
NewN_Left = N_Left + N_RLeft,
if N_RRight > NewN_Left ->
NewLeft = {NewN_Left, {Left, RLeft}},
NewRight = RRight,
{N_Tot, {NewLeft, NewRight}};
true ->
{N_Tot, {Left, Right}}
end;
balance_left(N_Tot, Left, Right) ->
{N_Tot, {Left, Right}}.
balance_right(N_Tot,
Left = {N_Left, {LLeft = {N_LLeft, _},
LRight = {N_LRight, _}}},
Right = {N_Right, _}) ->
NewN_Right = N_Right + N_LRight,
if N_LLeft > NewN_Right ->
NewLeft = LLeft,
NewRight = {NewN_Right, {LRight, Right}},
{N_Tot, {NewLeft, NewRight}};
true ->
{N_Tot, {Left, Right}}
end;
balance_right(N_Tot, Left, Right) ->
{N_Tot, {Left, Right}}.

Binary file not shown.

581
test/etags/f-src/entry.for Normal file
View file

@ -0,0 +1,581 @@
C$Procedure PRTPKG ( Declare Arguments for Error Message Routines )
LOGICAL FUNCTION PRTPKG ( SHORT, LONG, EXPL, TRACE, DFAULT, TYPE )
C$ Abstract
C
C Declare the arguments for the error message selection entry
C points. DO NOT CALL THIS ROUTINE.
C
C$ Required_Reading
C
C ERROR
C
C$ Keywords
C
C ERROR
C
C$ Declarations
LOGICAL SHORT
LOGICAL EXPL
LOGICAL LONG
LOGICAL TRACE
LOGICAL DFAULT
CHARACTER*(*) TYPE
INTEGER FILEN
PARAMETER ( FILEN = 128 )
C$ Brief_I/O
C
C VARIABLE I/O ENTRY
C -------- --- --------------------------------------------------
C
C SHORT I SETPRT
C EXPL I SETPRT
C LONG I SETPRT
C TRACE I SETPRT
C DFAULT I SETPRT
C TYPE I MSGSEL
C FILEN P MSGSEL
C
C$ Detailed_Input
C
C See the ENTRY points for discussions of their arguments.
C
C$ Detailed_Output
C
C See the ENTRY points for discussions of their arguments.
C
C$ Parameters
C
C See the ENTRY points for discussions of their parameters.
C
C$ Exceptions
C
C This routine signals an error IF IT IS CALLED.
C
C$ Files
C
C None.
C
C$ Particulars
C
C DO NOT CALL THIS ROUTINE.
C
C The entry points declared in this routine are:
C
C SETPRT
C MSGSEL
C
C There is no reason to call this subroutine.
C The purpose of this subroutine is to make the
C declarations required by the various entry points.
C This routine has no run-time function.
C
C$ Examples
C
C None. DO NOT CALL THIS ROUTINE.
C
C$ Restrictions
C
C DO NOT CALL THIS ROUTINE.
C
C$ Literature_References
C
C None.
C
C$ Author_and_Institution
C
C
C$ Version
C
C-
C Comment section for permuted index source lines was added
C following the header.
C
C
C-&
C$ Index_Entries
C
C None.
C
C-&
C$ Revisions
C
C
C- Beta Version 1.0.1, 08-FEB-1989
C
C PRTPKG, though it performs no run-time function, must
C still return a value, in order to comply with the Fortran
C standard. So, now it does.
C
C- Beta Version 1.0.1, 08-FEB-1989
C
C Warnings added to discourage use of this routine.
C Parameter declarations moved to "Declarations" section.
C Two local declarations moved to the correct location.
C-&
C
C SPICELIB functions
C
LOGICAL SETPRT
LOGICAL MSGSEL
C
C Local variables:
C
CHARACTER*(FILEN) DEVICE
CHARACTER*(10) LTYPE
CHARACTER*(10) LOCTYP
C
C Saved variables:
C
LOGICAL SVSHRT
LOGICAL SVEXPL
LOGICAL SVLONG
LOGICAL SVTRAC
LOGICAL SVDFLT
SAVE SVSHRT
SAVE SVEXPL
SAVE SVLONG
SAVE SVTRAC
SAVE SVDFLT
C
C Initial values:
C
DATA SVSHRT / .TRUE. /
DATA SVEXPL / .TRUE. /
DATA SVLONG / .TRUE. /
DATA SVTRAC / .TRUE. /
DATA SVDFLT / .TRUE. /
C
C Executable Code:
C
CALL GETDEV ( DEVICE )
CALL WRLINE ( DEVICE,
. 'PRTPKG: You have called an entry point which' //
. ' has no run-time function; this may indicate' //
. ' a program bug. Please check the PRTPKG' //
. ' documentation. ' )
CALL WRLINE ( DEVICE, 'SPICE(BOGUSENTRY)' )
PRTPKG = .FALSE.
RETURN
C$Procedure SETPRT ( Store Error Message Types to be Output )
C ENTRY BOGUS (X, Y, Z)
ENTRY SETPRT ( SHORT, EXPL, LONG, TRACE, DFAULT )
C$ Abstract
C
C Store (a representation of) the selection of types of error
C messages to be output. DO NOT CALL THIS ROUTINE.
C
C$ Required_Reading
C
C ERROR
C
C$ Keywords
C
C ERROR
C
C$ Declarations
C
C LOGICAL SHORT
C LOGICAL EXPL
C LOGICAL LONG
C LOGICAL TRACE
C LOGICAL DFAULT
C
C$ Brief_I/O
C
C VARIABLE I/O DESCRIPTION
C -------- --- --------------------------------------------------
C
C SHORT I Select output of short error message?
C EXPL I Select output of explanation of short message?
C LONG I Select output of long error message?
C TRACE I Select output of traceback?
C DFAULT I Select output of default message?
C
C$ Detailed_Input
C
C SHORT indicates whether the short error message is selected
C as one of the error messages to be output when an error
C is detected. A value of .TRUE. indicates that the
C short error message IS selected.
C
C EXPL indicates whether the explanatory text for the short
C error message is selected as one of the error messages
C to be output when an error is detected. A value of
C .TRUE. indicates that the explanatory text for the
C short error message IS selected.
C
C LONG indicates whether the long error message is selected
C as one of the error messages to be output when an error
C is detected. A value of .TRUE. indicates that the
C long error message IS selected.
C
C TRACE indicates whether the traceback is selected
C as one of the error messages to be output when an error
C is detected. A value of .TRUE. indicates that the
C traceback IS selected.
C
C DFAULT indicates whether the default message is selected
C as one of the error messages to be output when an error
C is detected. A value of .TRUE. indicates that the
C default message IS selected.
C
C
C$ Detailed_Output
C
C None.
C
C$ Parameters
C
C None.
C
C$ Exceptions
C
C None.
C
C$ Files
C
C None.
C
C$ Particulars
C
C DO NOT CALL THIS ROUTINE.
C
C The effect of this routine is an ENVIRONMENTAL one. This
C routine performs no output; it stores the error message
C selection provided as input.
C
C Note that the actual output of error messages depends not
C only on the selection made using this routine, but also
C on the selection of the error output device (see ERRDEV)
C and the choice of error response action (see ERRACT). If
C the action is not 'IGNORE' (possible choices are
C 'IGNORE', 'ABORT', 'DEFAULT', 'REPORT', and 'RETURN'),
C the selected error messages will be written to the chosen
C output device when an error is detected.
C
C$ Examples
C
C 1. In this example, the short and long messages are selected.
C
C C
C C Select short and long error messages for output
C C (We don't examine the status returned because no
C C errors are detected by SETPRT):
C C
C
C STATUS = SETPRT ( .TRUE., .FALSE., .TRUE., .FALSE.,
C . .FALSE. )
C
C
C
C$ Restrictions
C
C DO NOT CALL THIS ROUTINE.
C
C$ Literature_References
C
C None.
C
C$ Author_and_Institution
C
C
C$ Version
C
C-
C
C-&
C$ Index_Entries
C
C None.
C
C-&
C$ Revisions
C
C-
C Warnings added to discourage use of this routine in
C non-error-handling code. Parameters section added.
C
C-&
C
C Executable Code:
C
IF ( SHORT ) THEN
SVSHRT = .TRUE.
ELSE
SVSHRT = .FALSE.
END IF
IF ( EXPL ) THEN
SVEXPL = .TRUE.
ELSE
SVEXPL = .FALSE.
END IF
IF ( LONG ) THEN
SVLONG = .TRUE.
ELSE
SVLONG = .FALSE.
END IF
IF ( TRACE ) THEN
SVTRAC = .TRUE.
ELSE
SVTRAC = .FALSE.
END IF
IF ( DFAULT ) THEN
SVDFLT = .TRUE.
ELSE
SVDFLT = .FALSE.
END IF
C
C We assign a value to SETPRT, but this value is
C not meaningful...
C
SETPRT = .TRUE.
RETURN
C$Procedure MSGSEL ( Is This Message Type Selected for Output? )
ENTRY MSGSEL ( TYPE )
C$ Abstract
C
C Indicate whether the specified message type has been selected
C for output.
C
C$ Required_Reading
C
C ERROR
C
C$ Keywords
C
C ERROR
C
C$ Declarations
C
C TYPE
C
C$ Brief_I/O
C
C VARIABLE I/O DESCRIPTION
C -------- --- --------------------------------------------------
C
C TYPE I Type of message whose selection status is queried.
C FILEN P Maximum length of a file name.
C
C The function takes the value .TRUE. if the message type indicated
C by TYPE has been selected for output to the error output device.
C
C
C$ Detailed_Input
C
C TYPE Refers to a type of error message. Possible values
C are 'SHORT', 'EXPLAIN', 'LONG', 'DEFAULT',
C and 'TRACEBACK'.
C
C$ Detailed_Output
C
C The function takes the value .TRUE. if the message type indicated
C by TYPE has been selected for output to the error output device.
C
C$ Parameters
C
C FILEN is the maximum length of a file name.
C
C$ Exceptions
C
C Additionally, invalid values of TYPE are detected.
C
C The short error message set in this case is:
C 'SPICE(INVALIDMSGTYPE)'
C
C The handling of this error is a special case; to avoid recursion
C problems, SIGERR is not called when the error is detected.
C Instead, the short and long error messages are output directly.
C
C
C$ Files
C
C None.
C
C$ Particulars
C
C This routine is part of the SPICELIB error handling mechanism.
C
C Note that even though a given type of message may have been
C selected for output, the output device and error response
C action must also have been selected appropriately.
C Use ERRDEV to choose the output device for error messages.
C Use ERRACT to choose the error response action. Any action
C other than 'IGNORE' will result in error messages being
C written to the error output device when errors are detected.
C See ERRACT for details.
C
C$ Examples
C
C
C 1. We want to know if the short message has been selected
C for output:
C
C C
C C Test whether the short message has been selected:
C C
C
C SELECT = MSGSEL ( 'SHORT' )
C
C
C$ Restrictions
C
C None.
C
C$ Literature_References
C
C None.
C
C$ Author_and_Institution
C
C
C$ Version
C
C
C-&
C$ Index_Entries
C
C None.
C
C-&
C$ Revisions
C
C
C Parameters section added; parameter declaration added
C to brief I/O section as well.
C
C-&
C
C Executable Code:
C
CALL LJUST ( TYPE, LTYPE )
CALL UCASE ( LTYPE, LTYPE )
IF ( LTYPE .EQ. 'SHORT' ) THEN
MSGSEL = SVSHRT
ELSE IF ( LTYPE .EQ. 'EXPLAIN' ) THEN
MSGSEL = SVEXPL
ELSE IF ( LTYPE .EQ. 'LONG' ) THEN
MSGSEL = SVLONG
ELSE IF ( LTYPE .EQ. 'TRACEBACK' ) THEN
MSGSEL = SVTRAC
ELSE IF ( LTYPE .EQ. 'DEFAULT' ) THEN
MSGSEL = SVDFLT
ELSE
C
C Bad value of type! We have a special case here; to
C avoid recursion, we output the messages directly,
C rather than call SIGERR.
C
CALL GETDEV ( DEVICE )
CALL WRLINE ( DEVICE, 'SPICE(INVALIDMSGTYPE)' )
CALL WRLINE ( DEVICE, ' ' )
LOCTYP = TYPE
C
C Note: What looks like a typo below isn't; there's
C a line break after the substring 'specified' of
C the "word" 'specifiedwas'.
C
CALL WRLINE ( DEVICE,
. 'MSGSEL: An invalid error message type was supplied as' //
. ' input; the type specifiedwas: ' // LOCTYP
. )
END IF
subroutine
& intensity1(efv,fv,svin,svquad,sfpv,maxp,value,jndex,k,kj,jmod,isup)
character*(*) function foo()
END

Binary file not shown.

View file

@ -0,0 +1,581 @@
C$Procedure PRTPKG ( Declare Arguments for Error Message Routines )
LOGICAL FUNCTION PRTPKG ( SHORT, LONG, EXPL, TRACE, DFAULT, TYPE )
C$ Abstract
C
C Declare the arguments for the error message selection entry
C points. DO NOT CALL THIS ROUTINE.
C
C$ Required_Reading
C
C ERROR
C
C$ Keywords
C
C ERROR
C
C$ Declarations
LOGICAL SHORT
LOGICAL EXPL
LOGICAL LONG
LOGICAL TRACE
LOGICAL DFAULT
CHARACTER*(*) TYPE
INTEGER FILEN
PARAMETER ( FILEN = 128 )
C$ Brief_I/O
C
C VARIABLE I/O ENTRY
C -------- --- --------------------------------------------------
C
C SHORT I SETPRT
C EXPL I SETPRT
C LONG I SETPRT
C TRACE I SETPRT
C DFAULT I SETPRT
C TYPE I MSGSEL
C FILEN P MSGSEL
C
C$ Detailed_Input
C
C See the ENTRY points for discussions of their arguments.
C
C$ Detailed_Output
C
C See the ENTRY points for discussions of their arguments.
C
C$ Parameters
C
C See the ENTRY points for discussions of their parameters.
C
C$ Exceptions
C
C This routine signals an error IF IT IS CALLED.
C
C$ Files
C
C None.
C
C$ Particulars
C
C DO NOT CALL THIS ROUTINE.
C
C The entry points declared in this routine are:
C
C SETPRT
C MSGSEL
C
C There is no reason to call this subroutine.
C The purpose of this subroutine is to make the
C declarations required by the various entry points.
C This routine has no run-time function.
C
C$ Examples
C
C None. DO NOT CALL THIS ROUTINE.
C
C$ Restrictions
C
C DO NOT CALL THIS ROUTINE.
C
C$ Literature_References
C
C None.
C
C$ Author_and_Institution
C
C
C$ Version
C
C-
C Comment section for permuted index source lines was added
C following the header.
C
C
C-&
C$ Index_Entries
C
C None.
C
C-&
C$ Revisions
C
C
C- Beta Version 1.0.1, 08-FEB-1989
C
C PRTPKG, though it performs no run-time function, must
C still return a value, in order to comply with the Fortran
C standard. So, now it does.
C
C- Beta Version 1.0.1, 08-FEB-1989
C
C Warnings added to discourage use of this routine.
C Parameter declarations moved to "Declarations" section.
C Two local declarations moved to the correct location.
C-&
C
C SPICELIB functions
C
LOGICAL SETPRT
LOGICAL MSGSEL
C
C Local variables:
C
CHARACTER*(FILEN) DEVICE
CHARACTER*(10) LTYPE
CHARACTER*(10) LOCTYP
C
C Saved variables:
C
LOGICAL SVSHRT
LOGICAL SVEXPL
LOGICAL SVLONG
LOGICAL SVTRAC
LOGICAL SVDFLT
SAVE SVSHRT
SAVE SVEXPL
SAVE SVLONG
SAVE SVTRAC
SAVE SVDFLT
C
C Initial values:
C
DATA SVSHRT / .TRUE. /
DATA SVEXPL / .TRUE. /
DATA SVLONG / .TRUE. /
DATA SVTRAC / .TRUE. /
DATA SVDFLT / .TRUE. /
C
C Executable Code:
C
CALL GETDEV ( DEVICE )
CALL WRLINE ( DEVICE,
. 'PRTPKG: You have called an entry point which' //
. ' has no run-time function; this may indicate' //
. ' a program bug. Please check the PRTPKG' //
. ' documentation. ' )
CALL WRLINE ( DEVICE, 'SPICE(BOGUSENTRY)' )
PRTPKG = .FALSE.
RETURN
C$Procedure SETPRT ( Store Error Message Types to be Output )
C ENTRY BOGUS (X, Y, Z)
ENTRY SETPRT ( SHORT, EXPL, LONG, TRACE, DFAULT )
C$ Abstract
C
C Store (a representation of) the selection of types of error
C messages to be output. DO NOT CALL THIS ROUTINE.
C
C$ Required_Reading
C
C ERROR
C
C$ Keywords
C
C ERROR
C
C$ Declarations
C
C LOGICAL SHORT
C LOGICAL EXPL
C LOGICAL LONG
C LOGICAL TRACE
C LOGICAL DFAULT
C
C$ Brief_I/O
C
C VARIABLE I/O DESCRIPTION
C -------- --- --------------------------------------------------
C
C SHORT I Select output of short error message?
C EXPL I Select output of explanation of short message?
C LONG I Select output of long error message?
C TRACE I Select output of traceback?
C DFAULT I Select output of default message?
C
C$ Detailed_Input
C
C SHORT indicates whether the short error message is selected
C as one of the error messages to be output when an error
C is detected. A value of .TRUE. indicates that the
C short error message IS selected.
C
C EXPL indicates whether the explanatory text for the short
C error message is selected as one of the error messages
C to be output when an error is detected. A value of
C .TRUE. indicates that the explanatory text for the
C short error message IS selected.
C
C LONG indicates whether the long error message is selected
C as one of the error messages to be output when an error
C is detected. A value of .TRUE. indicates that the
C long error message IS selected.
C
C TRACE indicates whether the traceback is selected
C as one of the error messages to be output when an error
C is detected. A value of .TRUE. indicates that the
C traceback IS selected.
C
C DFAULT indicates whether the default message is selected
C as one of the error messages to be output when an error
C is detected. A value of .TRUE. indicates that the
C default message IS selected.
C
C
C$ Detailed_Output
C
C None.
C
C$ Parameters
C
C None.
C
C$ Exceptions
C
C None.
C
C$ Files
C
C None.
C
C$ Particulars
C
C DO NOT CALL THIS ROUTINE.
C
C The effect of this routine is an ENVIRONMENTAL one. This
C routine performs no output; it stores the error message
C selection provided as input.
C
C Note that the actual output of error messages depends not
C only on the selection made using this routine, but also
C on the selection of the error output device (see ERRDEV)
C and the choice of error response action (see ERRACT). If
C the action is not 'IGNORE' (possible choices are
C 'IGNORE', 'ABORT', 'DEFAULT', 'REPORT', and 'RETURN'),
C the selected error messages will be written to the chosen
C output device when an error is detected.
C
C$ Examples
C
C 1. In this example, the short and long messages are selected.
C
C C
C C Select short and long error messages for output
C C (We don't examine the status returned because no
C C errors are detected by SETPRT):
C C
C
C STATUS = SETPRT ( .TRUE., .FALSE., .TRUE., .FALSE.,
C . .FALSE. )
C
C
C
C$ Restrictions
C
C DO NOT CALL THIS ROUTINE.
C
C$ Literature_References
C
C None.
C
C$ Author_and_Institution
C
C
C$ Version
C
C-
C
C-&
C$ Index_Entries
C
C None.
C
C-&
C$ Revisions
C
C-
C Warnings added to discourage use of this routine in
C non-error-handling code. Parameters section added.
C
C-&
C
C Executable Code:
C
IF ( SHORT ) THEN
SVSHRT = .TRUE.
ELSE
SVSHRT = .FALSE.
END IF
IF ( EXPL ) THEN
SVEXPL = .TRUE.
ELSE
SVEXPL = .FALSE.
END IF
IF ( LONG ) THEN
SVLONG = .TRUE.
ELSE
SVLONG = .FALSE.
END IF
IF ( TRACE ) THEN
SVTRAC = .TRUE.
ELSE
SVTRAC = .FALSE.
END IF
IF ( DFAULT ) THEN
SVDFLT = .TRUE.
ELSE
SVDFLT = .FALSE.
END IF
C
C We assign a value to SETPRT, but this value is
C not meaningful...
C
SETPRT = .TRUE.
RETURN
C$Procedure MSGSEL ( Is This Message Type Selected for Output? )
ENTRY MSGSEL ( TYPE )
C$ Abstract
C
C Indicate whether the specified message type has been selected
C for output.
C
C$ Required_Reading
C
C ERROR
C
C$ Keywords
C
C ERROR
C
C$ Declarations
C
C TYPE
C
C$ Brief_I/O
C
C VARIABLE I/O DESCRIPTION
C -------- --- --------------------------------------------------
C
C TYPE I Type of message whose selection status is queried.
C FILEN P Maximum length of a file name.
C
C The function takes the value .TRUE. if the message type indicated
C by TYPE has been selected for output to the error output device.
C
C
C$ Detailed_Input
C
C TYPE Refers to a type of error message. Possible values
C are 'SHORT', 'EXPLAIN', 'LONG', 'DEFAULT',
C and 'TRACEBACK'.
C
C$ Detailed_Output
C
C The function takes the value .TRUE. if the message type indicated
C by TYPE has been selected for output to the error output device.
C
C$ Parameters
C
C FILEN is the maximum length of a file name.
C
C$ Exceptions
C
C Additionally, invalid values of TYPE are detected.
C
C The short error message set in this case is:
C 'SPICE(INVALIDMSGTYPE)'
C
C The handling of this error is a special case; to avoid recursion
C problems, SIGERR is not called when the error is detected.
C Instead, the short and long error messages are output directly.
C
C
C$ Files
C
C None.
C
C$ Particulars
C
C This routine is part of the SPICELIB error handling mechanism.
C
C Note that even though a given type of message may have been
C selected for output, the output device and error response
C action must also have been selected appropriately.
C Use ERRDEV to choose the output device for error messages.
C Use ERRACT to choose the error response action. Any action
C other than 'IGNORE' will result in error messages being
C written to the error output device when errors are detected.
C See ERRACT for details.
C
C$ Examples
C
C
C 1. We want to know if the short message has been selected
C for output:
C
C C
C C Test whether the short message has been selected:
C C
C
C SELECT = MSGSEL ( 'SHORT' )
C
C
C$ Restrictions
C
C None.
C
C$ Literature_References
C
C None.
C
C$ Author_and_Institution
C
C
C$ Version
C
C
C-&
C$ Index_Entries
C
C None.
C
C-&
C$ Revisions
C
C
C Parameters section added; parameter declaration added
C to brief I/O section as well.
C
C-&
C
C Executable Code:
C
CALL LJUST ( TYPE, LTYPE )
CALL UCASE ( LTYPE, LTYPE )
IF ( LTYPE .EQ. 'SHORT' ) THEN
MSGSEL = SVSHRT
ELSE IF ( LTYPE .EQ. 'EXPLAIN' ) THEN
MSGSEL = SVEXPL
ELSE IF ( LTYPE .EQ. 'LONG' ) THEN
MSGSEL = SVLONG
ELSE IF ( LTYPE .EQ. 'TRACEBACK' ) THEN
MSGSEL = SVTRAC
ELSE IF ( LTYPE .EQ. 'DEFAULT' ) THEN
MSGSEL = SVDFLT
ELSE
C
C Bad value of type! We have a special case here; to
C avoid recursion, we output the messages directly,
C rather than call SIGERR.
C
CALL GETDEV ( DEVICE )
CALL WRLINE ( DEVICE, 'SPICE(INVALIDMSGTYPE)' )
CALL WRLINE ( DEVICE, ' ' )
LOCTYP = TYPE
C
C Note: What looks like a typo below isn't; there's
C a line break after the substring 'specified' of
C the "word" 'specifiedwas'.
C
CALL WRLINE ( DEVICE,
. 'MSGSEL: An invalid error message type was supplied as' //
. ' input; the type specifiedwas: ' // LOCTYP
. )
END IF
subroutine
& intensity1(efv,fv,svin,svquad,sfpv,maxp,value,jndex,k,kj,jmod,isup)
character*(*) function foo()
END

View file

@ -0,0 +1,53 @@
\
\ This is a file that tests Forth tags
\
\ You should get:
\ a-forth-word (twice)
\ a-forth-constant!
\ a-forth-value?
\ :a-forth-dictionary-entry
\ #a-defer-word
\ (another-forth-word)
\ (a-forth-constant
\ #some-storage
\ assemby-code-word
\ This is a forth comment
( Another forth comment )
: a-forth-word ( a b c -- a*b+c ) + * ;
99 constant a-forth-constant!
55 value a-forth-value?
create :a-forth-dictionary-entry
0 c, 9 c, 5 c, 7 c, 999999 ,
defer #a-defer-word
: (another-forth-word) ( -- )
." Hello world"
;
' (another-forth-word) to #a-defer-word
struct
9 field >field1
5 field >field2
constant (a-forth-constant
2000 buffer: #some-storage
code assemby-code-word ( dunno what it does )
g1 g2 mov \ Move from here to there
sc2 h# 13 sc2 sllx \ shift stuff 'round
c;
\ And for the heck of it, redefine a-forth-word.
: a-forth-word ( a b c -- )
a-forth-word dup 200 > abort" Eek. The number is too big"
." Result is " . cr
;

View file

@ -0,0 +1,519 @@
<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<meta name="Author" content="Chip Fleming">
<meta name="GENERATOR" content="Mozilla/4.7 [en] (Win95; U) [Netscape]">
<title>Tutorial on Convolutional Coding with Viterbi Decoding--Description of the Data Generation, Convolutional Encoding, Channel Mapping and AWGN, and Quantizing Algorithms</title>
</head>
<body>
<a NAME="algorithms"></a><b><font face="Arial"><font size=+1>Description
of the Algorithms&nbsp; (Part 1)</font></font></b>
<p>&nbsp;The steps involved in simulating a communication channel using
convolutional encoding and Viterbi decoding are as follows:
<ul>
<li>
<a href="#genalgorithm">Generate the data</a> to be transmitted through
the channel-result is binary data bits</li>
<li>
<a href="#conalgorithm">Convolutionally encode</a> the data-result is channel
symbols</li>
<li>
<a href="#mapping">Map the one/zero channel symbols</a> onto an antipodal
baseband signal, producing transmitted channel symbols</li>
<li>
<a href="#addnoise">Add noise</a> to the transmitted channel symbols-result
is received channel symbols</li>
<li>
<a href="#quantizing">Quantize</a> the received channel levels-one bit
quantization is called hard-decision, and two to n bit quantization is
called soft-decision (n is usually three or four)</li>
<li>
<a href="algrthms2.html">Perform Viterbi decoding</a> on the quantized
received channel symbols-result is again binary data bits</li>
<li>
Compare the decoded data bits to the transmitted data bits and count the
number of errors.</li>
</ul>
<i>Many of you will notice that I left out the steps of modulating the
channel symbols onto a transmitted carrier, and then demodulating the received
carrier to recover the channel symbols. You're right, but we can accurately
model the effects of AWGN even though we bypass those steps.</i>
<p><a NAME="genalgorithm"></a><b><i><font face="Arial">Generating the Data</font></i></b>
<p>Generating the data to be transmitted through the channel can be accomplished
quite simply by using a random number generator. One that produces a uniform
distribution of numbers on the interval 0 to a maximum value is provided
in C: <tt>rand ()</tt>. Using this function, we can say that any value
less than half of the maximum value is a zero; any value greater than or
equal to half of the maximum value is a one.
<p><a NAME="conalgorithm"></a><b><i><font face="Arial">Convolutionally
Encoding the Data</font></i></b>
<p>Convolutionally encoding the data is accomplished using a shift register
and associated combinatorial logic that performs modulo-two addition. (A
shift register is merely a chain of flip-flops wherein the output of the
nth flip-flop is tied to the input of the (n+1)th flip-flop. Every time
the active edge of the clock occurs, the input to the flip-flop is clocked
through to the output, and thus the data are shifted over one stage.) The
combinatorial logic is often in the form of cascaded exclusive-or gates.
As a reminder, exclusive-or gates are two-input, one-output gates often
represented by the logic symbol shown below,
<center>
<p><img SRC="figs/xor_gate.gif" ALT="exclusive-or gate symbol" height=64 width=93></center>
<p>that implement the following truth-table:
<br>&nbsp;
<br>&nbsp;
<center><table BORDER CELLPADDING=7 WIDTH="218" >
<tr>
<td VALIGN=TOP WIDTH="28%">
<center><b><tt>Input A</tt></b></center>
</td>
<td VALIGN=TOP WIDTH="27%">
<center><b><tt>Input B</tt></b></center>
</td>
<td VALIGN=TOP WIDTH="45%">
<center><b><tt>Output</tt></b>
<p><b><tt>(A xor B)</tt></b></center>
</td>
</tr>
<tr>
<td VALIGN=TOP WIDTH="28%">
<center><tt>0</tt></center>
</td>
<td VALIGN=TOP WIDTH="27%">
<center><tt>0</tt></center>
</td>
<td VALIGN=TOP WIDTH="45%">
<center><tt>0</tt></center>
</td>
</tr>
<tr>
<td VALIGN=TOP WIDTH="28%">
<center><tt>0</tt></center>
</td>
<td VALIGN=TOP WIDTH="27%">
<center><tt>1</tt></center>
</td>
<td VALIGN=TOP WIDTH="45%">
<center><tt>1</tt></center>
</td>
</tr>
<tr>
<td VALIGN=TOP WIDTH="28%">
<center><tt>1</tt></center>
</td>
<td VALIGN=TOP WIDTH="27%">
<center><tt>0</tt></center>
</td>
<td VALIGN=TOP WIDTH="45%">
<center><tt>1</tt></center>
</td>
</tr>
<tr>
<td VALIGN=TOP WIDTH="28%">
<center><tt>1</tt></center>
</td>
<td VALIGN=TOP WIDTH="27%">
<center><tt>1</tt></center>
</td>
<td VALIGN=TOP WIDTH="45%">
<center><tt>0</tt></center>
</td>
</tr>
</table></center>
<p>The exclusive-or gate performs modulo-two addition of its inputs. When
you cascade q two-input exclusive-or gates, with the output of the first
one feeding one of the inputs of the second one, the output of the second
one feeding one of the inputs of the third one, etc., the output of the
last one in the chain is the modulo-two sum of the q + 1 inputs.
<p>Another way to illustrate the modulo-two adder, and the way that is
most commonly used in textbooks, is as a circle with a + symbol inside,
thus:
<center>
<p><img SRC="figs/ringsum.gif" ALT="modulo-two adder symbol" height=48 width=48></center>
<p>Now that we have the two basic components of the convolutional encoder
(flip-flops comprising the shift register and exclusive-or gates comprising
the associated modulo-two adders) defined, let's look at a picture of a
convolutional encoder for a rate 1/2, K = 3, m = 2 code:
<br>&nbsp;
<br>&nbsp;
<br>
<center>
<p><img SRC="figs/ce_7_5_a.gif" ALT="rate 1/2 K = 3 (7, 5) convolutional encoder" height=232 width=600></center>
<p>In this encoder, data bits are provided at a rate of k bits per second.
Channel symbols are output at a rate of n = 2k symbols per second. The
input bit is stable during the encoder cycle. The encoder cycle starts
when an input clock edge occurs. When the input clock edge occurs, the
output of the left-hand flip-flop is clocked into the right-hand flip-flop,
the previous input bit is clocked into the left-hand flip-flop, and a new
input bit becomes available. Then the outputs of the upper and lower modulo-two
adders become stable. The output selector (SEL A/B block) cycles through
two states-in the first state, it selects and outputs the output of the
upper modulo-two adder; in the second state, it selects and outputs the
output of the lower modulo-two adder.
<p>The encoder shown above encodes the K = 3, (7, 5) convolutional code.
The octal numbers 7 and 5 represent the code generator polynomials, which
when read in binary (111<sub>2</sub> and 101<sub>2</sub>) correspond to
the shift register connections to the upper and lower modulo-two adders,
respectively. This code has been determined to be the "best" code for rate
1/2, K = 3. It is the code I will use for the remaining discussion and
examples, for reasons that will become readily apparent when we get into
the Viterbi decoder algorithm.
<p>Let's look at an example input data stream, and the corresponding output
data stream:
<p>Let the input sequence be 010111001010001<sub>2</sub>.
<p>Assume that the outputs of both of the flip-flops in the shift register
are initially cleared, i.e. their outputs are zeroes. The first clock cycle
makes the first input bit, a zero, available to the encoder. The flip-flop
outputs are both zeroes. The inputs to the modulo-two adders are all zeroes,
so the output of the encoder is 00<sub>2</sub>.
<p>The second clock cycle makes the second input bit available to the encoder.
The left-hand flip-flop clocks in the previous bit, which was a zero, and
the right-hand flip-flop clocks in the zero output by the left-hand flip-flop.
The inputs to the top modulo-two adder are 100<sub>2</sub>, so the output
is a one. The inputs to the bottom modulo-two adder are 10<sub>2</sub>,
so the output is also a one. So the encoder outputs 11<sub>2</sub> for
the channel symbols.
<p>The third clock cycle makes the third input bit, a zero, available to
the encoder. The left-hand flip-flop clocks in the previous bit, which
was a one, and the right-hand flip-flop clocks in the zero from two bit-times
ago. The inputs to the top modulo-two adder are 010<sub>2</sub>, so the
output is a one. The inputs to the bottom modulo-two adder are 00<sub>2</sub>,
so the output is zero. So the encoder outputs 10<sub>2</sub> for the channel
symbols.
<p>And so on. The timing diagram shown below illustrates the process:
<br>&nbsp;
<br>&nbsp;
<br>
<center>
<p><img SRC="figs/ce_td.gif" ALT="timing diagram for rate 1/2 convolutional encoder" height=322 width=600></center>
<p><br>
<br>
<br>
<p>After all of the inputs have been presented to the encoder, the output
sequence will be:
<p>00 11 10 00 01 10 01 11 11 10 00 10 11 00 11<sub>2</sub>.
<p>Notice that I have paired the encoder outputs-the first bit in each
pair is the output of the upper modulo-two adder; the second bit in each
pair is the output of the lower modulo-two adder.
<p>You can see from the structure of the rate 1/2 K = 3 convolutional encoder
and from the example given above that each input bit has an effect on three
successive pairs of output symbols. That is an extremely important point
and that is what gives the convolutional code its error-correcting power.
The reason why will become evident when we get into the Viterbi decoder
algorithm.
<p>Now if we are only going to send the 15 data bits given above, in order
for the last bit to affect three pairs of output symbols, we need to output
two more pairs of symbols. This is accomplished in our example encoder
by clocking the convolutional encoder flip-flops two ( = m) more times,
while holding the input at zero. This is called "flushing" the encoder,
and results in two more pairs of output symbols. The final binary output
of the encoder is thus 00 11 10 00 01 10 01 11 11 10 00 10 11 00 11 10
11<sub>2</sub>. If we don't perform the flushing operation, the last m
bits of the message have less error-correction capability than the first
through (m - 1)th bits had. This is a pretty important thing to remember
if you're going to use this FEC technique in a burst-mode environment.
So's the step of clearing the shift register at the beginning of each burst.
The encoder must start in a known state and end in a known state for the
decoder to be able to reconstruct the input data sequence properly.
<p>Now, let's look at the encoder from another perspective. You can think
of the encoder as a simple state machine. The example encoder has two bits
of memory, so there are four possible states. Let's give the left-hand
flip-flop a binary weight of 2<sup>1</sup>, and the right-hand flip-flop
a binary weight of 2<sup>0</sup>. Initially, the encoder is in the all-zeroes
state. If the first input bit is a zero, the encoder stays in the all zeroes
state at the next clock edge. But if the input bit is a one, the encoder
transitions to the 10<sub>2</sub> state at the next clock edge. Then, if
the next input bit is zero, the encoder transitions to the 01<sub>2</sub>
state, otherwise, it transitions to the 11<sub>2</sub> state. The following
table gives the next state given the current state and the input, with
the states given in binary:
<br>&nbsp;
<br>&nbsp;
<center><table BORDER CELLSPACING=2 CELLPADDING=7 WIDTH="282" >
<tr>
<td VALIGN=TOP WIDTH="33%"><font face="Arial"><font size=-1>&nbsp;</font></font></td>
<td VALIGN=TOP COLSPAN="2" WIDTH="67%">
<center><a NAME="statetable"></a><b><font face="Arial"><font size=-1>Next
State, if&nbsp;</font></font></b></center>
</td>
</tr>
<tr>
<td VALIGN=TOP WIDTH="33%">
<center><b><font face="Arial"><font size=-1>Current State</font></font></b></center>
</td>
<td VALIGN=TOP WIDTH="33%">
<center><b><font face="Arial"><font size=-1>Input = 0:</font></font></b></center>
</td>
<td VALIGN=TOP WIDTH="33%">
<center><b><font face="Arial"><font size=-1>Input = 1:</font></font></b></center>
</td>
</tr>
<tr>
<td VALIGN=TOP WIDTH="33%">
<center><font face="Arial"><font size=-1>00</font></font></center>
</td>
<td VALIGN=TOP WIDTH="33%">
<center><font face="Arial"><font size=-1>00</font></font></center>
</td>
<td VALIGN=TOP WIDTH="33%">
<center><font face="Arial"><font size=-1>10</font></font></center>
</td>
</tr>
<tr>
<td VALIGN=TOP WIDTH="33%">
<center><font face="Arial"><font size=-1>01</font></font></center>
</td>
<td VALIGN=TOP WIDTH="33%">
<center><font face="Arial"><font size=-1>00</font></font></center>
</td>
<td VALIGN=TOP WIDTH="33%">
<center><font face="Arial"><font size=-1>10</font></font></center>
</td>
</tr>
<tr>
<td VALIGN=TOP WIDTH="33%">
<center><font face="Arial"><font size=-1>10</font></font></center>
</td>
<td VALIGN=TOP WIDTH="33%">
<center><font face="Arial"><font size=-1>01</font></font></center>
</td>
<td VALIGN=TOP WIDTH="33%">
<center><font face="Arial"><font size=-1>11</font></font></center>
</td>
</tr>
<tr>
<td VALIGN=TOP WIDTH="33%">
<center><font face="Arial"><font size=-1>11</font></font></center>
</td>
<td VALIGN=TOP WIDTH="33%">
<center><font face="Arial"><font size=-1>01</font></font></center>
</td>
<td VALIGN=TOP WIDTH="33%">
<center><font face="Arial"><font size=-1>11</font></font></center>
</td>
</tr>
</table></center>
<br>&nbsp;
<p>The above table is often called a state transition table. We'll refer
to it as the <tt>next state</tt> table.<tt> </tt>Now let us look at a table
that lists the channel output symbols, given the current state and the
input data, which we'll refer to as the <tt>output</tt> table:
<br>&nbsp;
<br>&nbsp;
<center><table BORDER CELLSPACING=2 CELLPADDING=7 WIDTH="282" >
<tr>
<td VALIGN=TOP WIDTH="33%"></td>
<td VALIGN=TOP COLSPAN="2" WIDTH="67%">
<center><a NAME="outputtable"></a><b><font face="Arial"><font size=-1>Output
Symbols, if</font></font></b></center>
</td>
</tr>
<tr>
<td VALIGN=TOP WIDTH="33%">
<center><b><font face="Arial"><font size=-1>Current State</font></font></b></center>
</td>
<td VALIGN=TOP WIDTH="33%">
<center><b><font face="Arial"><font size=-1>Input = 0:</font></font></b></center>
</td>
<td VALIGN=TOP WIDTH="33%">
<center><b><font face="Arial"><font size=-1>Input = 1:</font></font></b></center>
</td>
</tr>
<tr>
<td VALIGN=TOP WIDTH="33%">
<center><font face="Arial"><font size=-1>00</font></font></center>
</td>
<td VALIGN=TOP WIDTH="33%">
<center><font face="Arial"><font size=-1>00</font></font></center>
</td>
<td VALIGN=TOP WIDTH="33%">
<center><font face="Arial"><font size=-1>11</font></font></center>
</td>
</tr>
<tr>
<td VALIGN=TOP WIDTH="33%">
<center><font face="Arial"><font size=-1>01</font></font></center>
</td>
<td VALIGN=TOP WIDTH="33%">
<center><font face="Arial"><font size=-1>11</font></font></center>
</td>
<td VALIGN=TOP WIDTH="33%">
<center><font face="Arial"><font size=-1>00</font></font></center>
</td>
</tr>
<tr>
<td VALIGN=TOP WIDTH="33%">
<center><font face="Arial"><font size=-1>10</font></font></center>
</td>
<td VALIGN=TOP WIDTH="33%">
<center><font face="Arial"><font size=-1>10</font></font></center>
</td>
<td VALIGN=TOP WIDTH="33%">
<center><font face="Arial"><font size=-1>01</font></font></center>
</td>
</tr>
<tr>
<td VALIGN=TOP WIDTH="33%">
<center><font face="Arial"><font size=-1>11</font></font></center>
</td>
<td VALIGN=TOP WIDTH="33%">
<center><font face="Arial"><font size=-1>01</font></font></center>
</td>
<td VALIGN=TOP WIDTH="33%">
<center><font face="Arial"><font size=-1>10</font></font></center>
</td>
</tr>
</table></center>
<br>&nbsp;
<p>You should now see that with these two tables, you can completely describe
the behavior of the example rate 1/2, K = 3 convolutional encoder. Note
that both of these tables have 2<sup>(K - 1)</sup> rows, and 2<sup>k</sup>
columns, where K is the constraint length and k is the number of bits input
to the encoder for each cycle. These two tables will come in handy when
we start discussing the Viterbi decoder algorithm.
<p><a NAME="mapping"></a><b><i><font face="Arial">Mapping the Channel Symbols
to Signal Levels</font></i></b>
<p>Mapping the one/zero output of the convolutional encoder onto an antipodal
baseband signaling scheme is simply a matter of translating zeroes to +1s
and ones to -1s. This can be accomplished by performing the operation y
= 1 - 2x on each convolutional encoder output symbol.
<p><a NAME="addnoise"></a><b><i><font face="Arial">Adding Noise to the
Transmitted Symbols</font></i></b>
<p>Adding noise to the transmitted channel symbols produced by the convolutional
encoder involves generating Gaussian random numbers, scaling the numbers
according to the desired energy per symbol to noise density ratio, E<sub>s</sub>/N<sub>0</sub>,
and adding the scaled Gaussian random numbers to the channel symbol values.
<p>For the uncoded channel, E<sub>s</sub>/N<sub>0 </sub>= E<sub>b</sub>/N<sub>0</sub>,
since there is one channel symbol per bit.&nbsp; However, for the coded
channel, E<sub>s</sub>/N<sub>0 </sub>= E<sub>b</sub>/N<sub>0</sub> + 10log<sub>10</sub>(k/n).&nbsp;
For example, for rate 1/2 coding, E<sub>s</sub>/N<sub>0 </sub>= E<sub>b</sub>/N<sub>0</sub>
+ 10log<sub>10</sub>(1/2) = E<sub>b</sub>/N<sub>0</sub> - 3.01 dB.&nbsp;
Similarly, for rate 2/3 coding, E<sub>s</sub>/N<sub>0 </sub>= E<sub>b</sub>/N<sub>0</sub>
+ 10log<sub>10</sub>(2/3) = E<sub>b</sub>/N<sub>0</sub> - 1.76 dB.
<p>The Gaussian random number generator is the only interesting part of
this task. C only provides a uniform random number generator, <tt>rand()</tt>.
In order to obtain Gaussian random numbers, we take advantage of relationships
between uniform, Rayleigh, and Gaussian distributions:
<p>Given a uniform random variable U, a Rayleigh random variable R can
be obtained by:
<p><img SRC="figs/eqn01.gif" ALT="equation for Rayleigh random deviate given uniform random deviate" height=30 width=297 align=ABSCENTER>
<p>where&nbsp;<img SRC="figs/eqn02.gif" height=24 width=24 align=ABSCENTER>is
the variance of the Rayleigh random variable, and given R and a second
uniform random variable V, two Gaussian random variables G and H can be
obtained by
<p><i>G</i> = <i>R</i> cos <i>U</i> and <i>H</i> = <i>R</i> sin <i>V</i>.
<p>In the AWGN channel, the signal is corrupted by additive noise, n(t),
which has the power spectrum <i>No</i>/2 watts/Hz. The variance&nbsp;<img SRC="figs/eqn02.gif" ALT="variance" height=24 width=24 align=ABSBOTTOM>of
this noise is equal to&nbsp;<img SRC="figs/eqn03.gif" ALT="noise density div by two" height=22 width=38 align=TEXTTOP>.
If we set the energy per symbol <i>E<sub>s</sub></i> equal to 1, then&nbsp;<img SRC="figs/eqn04.gif" ALT="equation relating variance to SNR" height=28 width=110 align=ABSBOTTOM>.
So&nbsp;<img SRC="figs/eqn05.gif" ALT="equation for AWGN st dev given SNR" height=28 width=139 align=ABSCENTER>.
<p><a NAME="quantizing"></a><b><i><font face="Arial">Quantizing the Received
Channel Symbols</font></i></b>
<p>An ideal Viterbi decoder would work with infinite precision, or at least
with floating-point numbers. In practical systems, we quantize the received
channel symbols with one or a few bits of precision in order to reduce
the complexity of the Viterbi decoder, not to mention the circuits that
precede it. If the received channel symbols are quantized to one-bit precision
(&lt; 0V = 1, <u>></u> 0V = 0), the result is called hard-decision data.
If the received channel symbols are quantized with more than one bit of
precision, the result is called soft-decision data. A Viterbi decoder with
soft decision data inputs quantized to three or four bits of precision
can perform about 2 dB better than one working with hard-decision inputs.
The usual quantization precision is three bits. More bits provide little
additional improvement.
<p>The selection of the quantizing levels is an important design decision
because it can have a significant effect on the performance of the link.
The following is a very brief explanation of one way to set those levels.
Let's assume our received signal levels in the absence of noise are -1V
= 1, +1V = 0. With noise, our received signal has mean +/- 1 and standard
deviation&nbsp;<img SRC="figs/eqn05.gif" ALT="equation for AWGN st dev given SNR" height=28 width=139 align=ABSCENTER>.
Let's use a uniform, three-bit quantizer having the input/output relationship
shown in the figure below, where D is a decision level that we will calculate
shortly:
<center>
<p><img SRC="figs/quantize.gif" ALT="8-level quantizer function plot" height=342 width=384></center>
<p>The decision level, D, can be calculated according to the formula&nbsp;<img SRC="figs/eqn06.gif" ALT="equation for quantizer decision level" height=28 width=228 align=ABSCENTER>,
where E<sub>s</sub>/N<sub>0</sub> is the energy per symbol to noise density
ratio<i>. (The above figure was redrawn from Figure 2 of Advanced Hardware
Architecture's ANRS07-0795, "Soft Decision Thresholds and Effects on Viterbi
Performance". See the </i><a href="fecbiblio.html">bibliography</a><i>&nbsp;
for a link to their web pages.)</i>
<p>Click <a href="algrthms2.html">here</a> to proceed to the description
of the Viterbi decoding algorithm itself...
<p>Or click on one of the links below to go to the beginning of that section:
<p>&nbsp;<a href="tutorial.html">Introduction</a>
<br>&nbsp;<a href="algrthms2.html">Description of the Algorithms&nbsp;
(Part 2)</a>
<br>&nbsp;<a href="examples.html">Simulation Source Code Examples</a>
<br>&nbsp;<a href="simrslts.html">Example Simulation Results</a>
<br>&nbsp;<a href="fecbiblio.html">Bibliography</a>
<br>&nbsp;<a href="tutorial.html#specapps">About Spectrum Applications...</a>
<br>&nbsp;
<br>&nbsp;
<br>
<br>
<center>
<p><img SRC="figs/stripe.gif" height=6 width=600></center>
</body>
</html>

View file

@ -0,0 +1,70 @@
<!--#set var="chiavi" value="
prima pagina principale, home page, assoli,
free software, open source, italia, italy, italiano" -->
<!--#include virtual="/inc/h.shtml"-->
<!--#include virtual="/inc/menu-generico.html"-->
<!--#include virtual="/inc/content-begin.html"-->
<H3>&nbsp;</H3> <!-- un po' di spazio in cima -->
<!--
La rubrica "in evidenza" va commentata se non c'è niente di serio
da mettere in evidenza
-->
<H2>
In evidenza
</H2>
<ul>
<li>Assieme alla <A HREF="http://www.linux.it/">Italian Linux
Society</A> sollecitiamo una <A
HREF="/misc/raccoltafirme.shtml">raccolta di firme</A> per
sostenere il <a href="/altri/cortiana.shtml">disegno di legge</a> sul
software libero dal titolo "<i>Norme in materia di pluralismo
informatico sulla adozione e la diffusione del software libero e sulla
portabilità dei documenti informatici nella Pubblica
Amministrazione</i>" (XIV Legislatura Atto Senato n. 1188).<P>
</ul>
<H2>
Comunicati e iniziative
</H2>
<ul>
<p></p><li>
Combattiamo il "bollino SIAE". Nel <A HREF="/news/">notiziario</A>
tutte le nostre iniziative in proposito. Insieme al <a
href="http://www.lugroma.org">LUG Roma</a> abbiamo scritto il <A
HREF="/bollino/">Bollino-HOWTO</A>, istruzioni passo passo su come
ottenere l'esenzione dal bollilno SIAE per la distribuzione di
software libero a titolo oneroso o gratuito. <A
HREF="/altri/semenzato-pieroni.shtml">Qui</A> il disegno di legge
Semenzato Pieroni sul diritto d'autore. E non è finita.
<p></p><li>
<a href="/altri/adeos.shtml">Salutiamo</a> l'arrivo di ADEOS, kernel
real-time per Linux libero da brevetti
<p></p><li>
<a href="/news/news020315_01.shtml">Comunicato</a> stampa di FSF Europa
ed Assoli in appoggio al disegno di legge per l'uso del software libero
nella pubblica amministrazione
<p></p><li>
<a href="/docs/pirateria.shtml">Posizione dell'Associazione</a> sulle
attuali campagna anti-"pirateria"</a>
</ul>
<H2>
Ultime notizie dall'associazione
</H2>
<P>
<!--#include virtual="/news/notizie.shtml"-->
</P>
<!--#include virtual="inc/content-end.html"-->
<!--#include virtual="inc/f.shtml"-->

View file

@ -0,0 +1,241 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40">
<HTML LANG="en">
<HEAD>
<STYLE TYPE="text/css"><!--
BODY { font-size: 12pt; }
P { text-indent: 0; text-align: justify }
DD { text-indent: 0; text-align: justify }
--></STYLE>
<TITLE>Francesco Potortì Software Page</TITLE>
<LINK REV="made" HREF="mailto:F.Potorti@cnuce.cnr.it">
<META NAME="description" CONTENT="Home page of Francesco Potortì.">
<META NAME="keywords"
CONTENT="Potorti Potortì Potorti' Potorti`
satellites MTG fracas simulator LEO MEO GEO
GNU emacs etags checkiso debian-bug">
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
</HEAD><BODY>
<CENTER>
[<A HREFLANG="en" HREF="/home.html">home</A>]
| [<A HREFLANG="en" HREF="/foda/foda.html">FODA/IBEA</A>]
| [<A HREFLANG="en" HREF="/galileo/index.html">GaliLEO</A>]
| [<A HREFLANG="en" HREF="#fracas">fracas</A>]
| [<A HREFLANG="en" HREF="#leasqr">leasqr</A>]<BR>
[<A HREFLANG="en" HREF="#etags">etags</A>]
| [<A HREFLANG="en" HREF="#checkiso">checkiso</A>]
| [<A HREFLANG="en" HREF="#cgrep">cgrep</A>]
| [<A HREFLANG="en" HREF="#debian-bug">debian-bug</A>]
</CENTER>
<HR> <!---------------------------------------------------------------->
<H4 ID="simulation">
<IMG SRC="/pictures/cnr-4.png" ALIGN="right"
ALT="CNR logo (png 3k)">
Software that I wrote for supporting my research activity
</H4>
<H5 ID="mtg">
MTG
</H5>
<P> The <A
HREF="/curriculum/pot-abstracts.html#R05:MTG-RealTimeSystems97"><CITE>M</CITE>ulti-Application
<cite>t</CITE>raffic <cite>g</CITE>enerator</A> was written in 1990 to run on
a proprietary Motorola Delta SysV Unix running on 68030. It is a
programmable packet traffic generator for Ethernet with a
<CITE>curses</CITE>-based frontend and a backend that I wrote. MTG was
used to develop, test and evaluate the <A HREF="/foda/foda.html">FODA/IBEA</A>
satellite access protocol.
<P> The backend of MTG
was a Unix device driver which took control of the timer and Lance
interrupts, after having programmed them at the unmaskable level. Since I
had no access to the kernel sources, after having studied <CITE>Writing a
Unix device driver</CITE> by Egan Teixeira I had to get really well
acquainted with the Motorola C compiler and then to disassemble a couple of
kernel routines. For anyone interested in historical programming, <A
HREF="ftp://fly.cnuce.cnr.it/pub/software/unix/mtg.tgz"
TYPE="application/octet-stream">here</A> is the code.
<H5 ID="fracas">
Fracas
</H5>
<P> The <A
HREF="/curriculum/pot-abstracts.html#R12:Fracas-TelCommSystems99"><CITE>Fra</CITE>med
<CITE>C</CITE>hannel <CITE>A</CITE>ccess <CITE>S</CITE>imulator</A> was
written around 1995 to study MAC protocols to access a geostationary
satellite channel. It is a little more general than that, though, and can
be used to simulate any framed multiple access scheme. It is a very fast,
extensible, non-user friendly C program that has been used for several
protocol studies:
<UL>
<LI> <A HREF="/curriculum/pot-abstracts.html#R03:FODAIBEAvsDistributed-IJSC96">
<i>Comparison between distributed and centralised demand
assignment TDMA satellite access schemes</i></A>
<LI><A HREF="/curriculum/pot-abstracts.html#R07:FODAIBEAvsCFRA-IJSC97">
<i>Delay analysis for interlan traffic using two suitable TDMA
satellite access schemes</i></A>
<LI><A HREF="/curriculum/pot-abstracts.html#R17:VnL-IJSC00">
<i>A multi-level satellite channel allocation algorithm for
real-time VBR data</i></A>
</UL>
<P> Everyone is welcome to download the <A
HREF="ftp://fly.cnuce.cnr.it/pub/software/C/fracas.tgz"
TYPE="application/octet-stream">complete sources</A> and a <A
HREF="ftp://fly.cnuce.cnr.it/pub/software/C/fracas-man-0.0.pdf"
TYPE="application/pdf">draft manual</A>. There is also a short <A
HREF="ftp://fly.cnuce.cnr.it/pub/data/docs/Fracas-slides.pdf">presentation</A>
(10 slides, 340KB). I will be happy to assist those who would like to
adapt Fracas to their purposes.
<H5 ID="galileo">
GaliLEO
</H5>
<P> A simulator for Low Earth Orbit satellite constellations that I contributed
to design and implement in Java. This is work in progress, of which I made
a short <A
HREF="ftp://fly.cnuce.cnr.it/pub/data/docs/GaliLEO-slides.pdf">presentation</A>
(10 slides, 500KB). GaliLEO has <A HREF="http://galileo.tesa.prd.fr/">its
own page</A> and a <A HREF="/galileo/index.html">local mirror</A>.
<H5 ID="leasqr">
Leasqr
</H5>
<P> This is a package for <A HREF="http://www.octave.org/">Octave</A>, a
high-level language which uses a language very similar to that of Matlab.
Leasqr uses the Levenberg-Marquardt algorithm for doing nonlinear regression.
I found leasqr on the web, but it did not run on Octave (it was made for
Matlab) and so I adapted it and <A
HREF="ftp://fly.cnuce.cnr.it/pub/software/octave/leasqr/">published</A> it.
Since then, the original authors Richard I. Shrager, A.Jutan, Ray Muzic, and
Sean Brennan agreed to put it under the <A
HREF="http://www.gnu.org/licenses/gpl.html">GPL</A>. Matthias Jueschke tested
the program using a non-linear optimisation <A
HREF="http://www.itl.nist.gov/div898/strd/nls/nls_main.shtml">test suite</A>,
and was satisfied with the results.
<P>The most current version of the leasqr is part of the optimization package
at <a href="http://octave.sf.net">octave-forge</a>. You should refer to the
files leasqr.m, leasqrdemo.m and dfdp.m <a
href="http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/octave/octave-forge/main/optim/">therein</a>.
The names of the individual files may change in the future. Please let me know
if that happens so I can update this page.
<HR> <!---------------------------------------------------------------->
<H4 ID="gnu">
<IMG SRC="/pictures/gnu-head-3.png" ALIGN="right"
ALT="small GNU Head (png 3k)">
Free software that I wrote for the GNU project or for my personal or work
interest
</H4>
<H5 ID="etags">
Etags
</H5>
<P> On behalf of the <A HREF="http://www.gnu.org/fsf/fsf.html">Free
Software Foundation (FSF)</A> I currently volunteer to maintain
<CITE>etags</CITE>, a program that can be compiled either as a replacement
of the classic <CITE>ctags</CITE> Unix program or as <CITE>etags</CITE>,
whose output file format is used by Emacs. The latest (unofficial) version
of etags is available for <A HREF="ftp://fly.cnuce.cnr.it/pub/etags.c.gz"
TYPE="application/octet-stream">download</A> (30&nbsp;KB).
<H5 ID="checkiso">
checkiso
</H5>
<P> A Unix <A HREF="ftp://fly.cnuce.cnr.it/pub/software/unix/checkiso"
TYPE="application/octet-stream">shell script</A> for checking a CD against
the iso image from which it has been burned. The comparison is made using
an MD5 signature built from the original image or from a known good CD.
Shows the location of the first read error detected. Can extract a disk Id
from the image or the CD itself and build a local database of Ids for
future checking of archived CDs. The Id contains the image length, the MD5
signature and the Volume ID of the disk, so it can automatically recognise
the CD to check. Contains a small internal database of <A
HREF="http://www.debian.org/">Debian</A> <A
HREF="http://cdimage.debian.org/">CD images</A>.
<H5 ID="cgrep">
cgrep
</H5>
<P> A Unix <A HREF="ftp://fly.cnuce.cnr.it/pub/software/unix/cgrep"
TYPE="application/octet-stream">shell script</A> that wraps around grep to
make it understand files compressed with gzip or bzip2. You just use it
like grep. If you rename it cegrep or cfgrep it will wrap around egrep or
fgrep, respectively. Instead of renaming it, you can use a symbolic or
hard link.
<H5 ID="debian-bug">
debian-bug.el
</H5>
<P> An Emacs add-on script in emacs lisp which simplifies
the task of submitting a bug report to the <A
HREF="http://www.debian.org/Bugs/">Debian bug tracking system</A>. Part of
the <A
HREF="http://packages.debian.org/testing/utils/debbugs-el.html">debbugs-el</A>
Debian package. I handed the package over to Peter Galbraith, who is
maintaining it much more actively than I was. You can download its <A
HREF="http://people.debian.org/~psg/debian-bug.el"
TYPE="application/octet-stream">latest version</A>.
<H5 ID="tcpdump">
tcpdump
</H5>
<P> A Unix <A HREF="ftp://fly.cnuce.cnr.it/pub/software/unix/pottcpdump-1.3"
TYPE="application/octet-stream">shell wrapper</A> around
<CITE>tcpdump</CITE> which optionally displays the contents of the packets.
<HR> <!---------------------------------------------------------------->
<H4 ID="links">
Links to interesting software
</H4>
<DL>
<DT>The Error Correcting Codes (ECC) Page
<DD><A
HREF="http://www.csl.sony.co.jp/person/morelos/ecc/codes.html">This</A> is a
really good list of free (in various senses) programs for coding and
decoding. I keep a <A HREF="codes.html">mirror</A> of this page.
<DT>Forward error correcting codes by Phil Karn
<DD>Phil Karn's optimised really <A HREF="http://www.ka9q.net/code/fec/">free
codes</A>.
</DL>
</BODY>
<!--
Local variables:
fill-column: 79
end:
-->
</HTML>

View file

@ -0,0 +1,313 @@
<DIV LANG="it" ALIGN="justify">
<H2>
Cos'è il software libero?
</H2>
<P>
Il concetto di software libero discende naturalmente da quello di
libertà di scambio di idee e di informazioni. Negli ambienti
scientifici, quest'ultimo principio è tenuto in alta considerazione
per la fecondità che ha dimostrato; ad esso infatti è generalmente
attribuita molta parte dell'eccezionale ed imprevedibile crescita del
sapere negli ultimi tre secoli.
</P>
<P>
La libertà di scambio di idee non è tuttavia una questione puramente
pratica: essa è anche alla base dei concetti di libertà di pensiero e
di espressione. Analogamente alle idee, il software è immateriale, e
può essere riprodotto e trasmesso facilmente. In modo simile a quanto
avviene per le idee, parte essenziale del processo che sostiene la
crescita e l'evoluzione del software è la sua libera diffusione. Ed
ogni giorno di più, come le idee, il software permea il tessuto
sociale e lo influenza, produce effetti etici, economici, politici e
in un senso più generale culturali.
</P>
<P>
Fu Richard M. Stallman, nei primi anni Ottanta, a formalizzare per la
prima volta il concetto di software libero. La <A TITLE="definizione
di software libero secondo FSF"
href="http://www.it.gnu.org/philosophy/free-sw.it.html">definizione</A>
di Stallman, che da subito assurse al ruolo di definizione per
eccellenza di software libero, assume la forma di quattro principi di
libertà:
</P>
<P>
<DL>
<DT>Libertà 0, o libertà fondamentale:
<DD>La libertà di eseguire il programma per qualunque scopo, senza
vincoli sul suo utilizzo.
<DT>Libertà 1:
<DD>La libertà di studiare il funzionamento del programma, e
di adattarlo alle proprie esigenze.
<DT>Libertà 2:
<DD>La libertà di redistribuire copie del programma.
<DT>Libertà 3:
<DD>La libertà di migliorare il programma, e di distribuirne
i miglioramenti.
</DL>
</P>
<P>
Il software distribuito con una licenza che rispetti questi principi è
detto <Q><EM>software libero</EM></Q> (in inglese <Q><EM>free
software</EM></Q>). Nel 1984 Richard M. Stallman <A TITLE="storia
del progetto GNU"
HREF="http://www.it.gnu.org/gnu/thegnuproject.it.html">diede vita al
progetto GNU</A>, con lo scopo di tradurre in pratica il concetto di
software libero, e creò la <Q>Free Software Foundation</Q> per
dare supporto logistico, legale ed economico al progetto GNU.
</P>
<H3><A NAME="licenze">
Licenze d'uso di un programma
</A></H3>
<P>
La <EM>licenza d'uso</EM> è un documento legale generalmente
distribuito assieme a ogni programma. Essa, appoggiandosi alle norme
sul diritto d'autore, specifica diritti e doveri di chi riceve tale
programma.
</P>
<P>
Gran parte delle licenze comunemente usate sono <EM>proprietarie</EM>,
cioè non libere, in quanto non garantiscono le quattro libertà. Quasi
sempre tali licenze non consentono infatti la libera copia del
programma, né la sua modifica. Spesso, se il programma è installato
sul computer di casa, la licenza impedisce persino di installarlo sul
proprio portatile (per utilizzare il programma fuori casa); se il
programma è utilizzato in uno studio professionale, non consente di
tenerlo installato su un computer di riserva, nel caso che quello
principale si guasti.
</P>
<P>
La licenza del progetto GNU, la <EM>Licenza Pubblica Generica GNU (<A
TITLE="traduzione della licenza GNU GPL"
HREF="http://softwarelibero.it/gnudoc/gpl.it.txt">GNU GPL</A>)</EM>,
al contrario, concede all'utente del programma tutte e quattro le
libertà suddette. Inoltre si occupa anche di proteggerle: chi
modifichi un programma protetto da GPL e lo distribuisca con tali
modifiche, deve distribuirlo sotto licenza GPL. È grazie a questo
tipo di protezione che la GPL è attualmente la licenza più usata per
il software libero.
</P>
<P>
Con un gioco di parole, il nome dato a questo tipo di protezione
è <EM>permesso d'autore</EM> (in inglese <A TITLE="definizione di
copyleft (inglese)" LANG="en"
HREF="http://www.it.gnu.org/copyleft/copyleft.html"><EM>copyleft</EM></A>):
è il criterio che prevede che le modifiche ad un programma possano
essere distribuite solo con la stessa licenza del programma originale.
Le licenze proprietarie usano le norme sul diritto d'autore (copyright
in inglese) per togliere libertà agli utenti di un programma; il
permesso d'autore usa le stesse norme per garantire quelle libertà e
per proteggerle.
</P>
<P>
La GNU GPL non è unica nel suo genere. Diverse <A TITLE="lista di
licenze libere e non"
HREF="http://www.it.gnu.org/licenses/license-list.it.html">altre
licenze</A> garantiscono le quattro libertà e si possono pertanto
qualificare come licenze per il software libero. Fra queste, merita
una speciale menzione per la sua diffusione la <A TITLE="la licenza
BSD (in inglese)" LANG="en"
HREF="http://www.freebsd.org/copyright/license.html">licenza BSD</A>,
la cui principale differenza dalla GPL è che, non essendo basata sul
permesso d'autore, non ha fra i propri obiettivi quello di proteggere
la libertà del software cui è applicata. Chi infatti modifichi un
programma protetto da BSD, può distribuirlo con le modifiche usando
qualunque licenza.
</P>
<P>
Sia BSD che GPL hanno pro e contro. La licenza GPL riflette l'idea
della cooperazione: se io concedo ad altri la libertà di modificare e
redistribuire il mio programma, costoro sono tenuti a concedere le
stesse libertà sulle loro modifiche. Il problema è che alcuni vedono
questo vincolo come un'imposizione ingenerosa, se non addirittura una
restrizione insopportabile. La licenza BSD riflette l'idea del dono
liberale: chiunque può fare ciò che meglio crede del mio programma.
Il problema è che questo significa che chiunque può redistribuire
anche in forma chiusa con una licenza proprietaria un programma BSD
modificato, impedendo così ai propri acquirenti di modificarlo e
redistribuirlo a loro volta.
</P>
<H3><A NAME="miti">
Sfatiamo alcuni miti
</A></H3>
<P>
<DL>
<DT>Il software libero è gratuito
<DD>È falso: la libertà del software non ha nulla a che vedere con
il suo prezzo. Benché gran parte del software libero più diffuso
sia distribuito gratuitamente, ci sono programmatori che vivono
della vendita e della manutenzione dei programmi liberi da loro
creati.
<DT>Il software gratuito è libero
<DD>È falso. Molti programmi proprietari vengono distribuiti
gratuitamente.
<DT>Il software libero è privo di copyright
<DD>È falso. Benché si possa rinunciare al copyright su un proprio
programma e renderlo così di pubblico dominio, la gran parte del
software libero è distribuito con una licenza. Per esempio, sono
licenze di copyright la licenza BSD e la GNU GPL, anche se per
qualificare quest'ultima spesso si parla di permesso d'autore
(copyleft).
<DT>L'introduzione del software libero nella scuola e nella pubblica
amministrazione, ma anche nei paesi poveri, ridurrebbe i costi
relativi al software
<DD>Potrebbe essere vero, ma una seria valutazione dei costi è molto
difficile. Qualunque tipo di software, se usato in ambito non
domestico, ha dei costi di manutenzione che sono solitamente
maggiori del suo prezzo di acquisto. I motivi per sostenere l'uso
del software libero, specie in ambiti pubblici, riguardano anzitutto
la libertà, non il prezzo.
<!-- Discorso inadatto ad un documento introduttivo
<DT>Chi scrive un programma libero lo deve pubblicare su Internet
<DD>È una falsa argomentazione spesso usata per scoraggiare
un'azienda dall'uso di una licenza libera per i suoi programmi.
Sia gli autori che gli acquirenti di un programma libero hanno il
diritto di distribuirlo a titolo oneroso o gratuito, ma non hanno
alcun obbligo in tal senso.
-->
</DL>
</P>
<H3><A NAME="oss">
Il movimento open source
</A></H3>
<P>
Nel 1998 Bruce Perens, Eric Raymond e altre personalità nel campo del
software libero si convinsero che i principi di libertà associati ad
esso fossero malvisti nel mondo degli affari, a causa della loro
carica ideologica. Decisero perciò di evitare accuratamente ogni
riferimento a considerazioni politiche o di principio, e di lanciare
una campagna di promozione del software libero che ne mettesse in luce
i numerosi <A TITLE="un discorso di Robert Chassell di FSF"
HREF="http://softwarelibero.it/altri/economia-sl.shtml">vantaggi
pratici</A>, come la facilità di adattamento, l'affidabilità, la
sicurezza, la conformità agli standard, l'indipendenza dai singoli
fornitori. A tal fine scrissero la <Q><A TITLE="la definizione di
Open Source (in inglese)" LANG="en"
HREF="http://www.opensource.org/docs/definition.html">Open Source
Definition</A></Q>, il documento fondamentale del movimento <A
TITLE="il sito di Open Source Initiative (OSI), in inglese" LANG="en"
HREF="http://opensource.org/"><EM>open source</EM></A>.
</P>
<P>
Il movimento open source fu un successo, e contribuì a sdoganare il
concetto di software libero in campo aziendale, dove era guardato con
sospetto o condiscendenza. Un esempio di questo successo è
l'atteggiamento dell'IBM, l'azienda che ha fatto di gran lunga i
maggiori investimenti nel campo del software libero, la quale parla
esclusivamente di open source, mai di software libero.
</P>
<P>
La voluta neutralità del movimento open source verso gli aspetti
etici e politici del software libero è la caratteristica sostanziale
che lo distingue dalla filosofia del software libero, che al contrario
pone l'accento sulle motivazioni ideali. Parlare di software libero
piuttosto che di open source è una questione politica piuttosto che
pratica; i due movimenti concordano infatti sulle licenze considerate
accettabili, ed hanno obiettivi e mezzi comuni.
</P>
<H3><A NAME="impatto">
Impatto pratico del software libero
</A></H3>
<P>
La <A TITLE="usi commerciali del software libero, di Alessandro
Rubini"
HREF="http://www.it.gnu.org/philosophy/software-libre-commercial-viability.it.html">rilevanza
economica</A> del software libero è ancora molto ridotta, ma è in
fortissima crescita ormai da alcuni anni, e tutto consente di supporre
che tale crescita <A TITLE="prospettive del software libero, gruppo di
studio dell'UE"
HREF="http://eu.conecta.it/paper/Economics_open_source.html">continui
nel prossimo futuro</A>, anche grazie ai <A TITLE="vantaggi del
software libero, gruppo di studio UE"
HREF="http://eu.conecta.it/paper/Advantages_open_source_soft.html">vantaggi
tecnici ed economici</A> del software libero.
</P>
<P>
Ad oggi, il software libero è ampiamente diffuso in ambito accademico,
industriale e fra gli appassionati di calcolatori, soprattutto grazie
ai sistemi GNU/Linux. Questi sistemi liberi sono disponibili a costi
molto bassi, ben inferiori a quelli di analoghi sistemi proprietari.
Tuttavia, a causa delle loro caratteristiche, il loro uso richiede una
buona cultura di base nel campo del software.
</P>
<P>
In ambito accademico viene molto apprezzata la possibilità di
personalizzare ogni parte del sistema, visto che i programmi liberi
sono liberamente modificabili (libertà numero uno). In ambito
industriale, si apprezza l'affidabilità dei sistemi liberi, dovuta al
fatto che quando un utente corregge un errore in un programma
solitamente rende disponibile la correzione agli altri utenti (libertà
numero tre). Gli appassionati di calcolatori apprezzano lo spirito di
condivisione esistente fra gli utenti di software libero.
</P>
<P>
Ma le implicazioni dell'uso del software libero non sono soltanto
tecniche ed economiche, perché il software da tempo ormai è avviato ad
occupare un ruolo di primo piano nella nostra vita quotidiana, ed è
destinato a cambiare in maniera profonda la società.
</P>
<P>
È per queste ragioni che la nostra libertà futura dipenderà anche
dalla capacità di ognuno di noi di controllare il software. È per
queste ragioni che ai tradizionali principi di libertà sessuale, di
culto, di movimento, di espressione deve essere affiancata la libertà
del software. È per queste ragioni che la nostra libertà futura
dipenderà anche dall'uso di software libero.
</P>
<P>
<EM>scritto da <A TITLE="pot@softwarelibero.it"
HREF="mailto:pot@softwarelibero.it">Francesco Potortì</A> per l'<A
TITLE="il sito dell'Associazione Software Libero"
HREF="http://softwarelibero.it/">Associazione Software
Libero</A></EM>
</P>
<HR NOSHADE>
<P>
Copyright &copy; 2002 Francesco Potortì
<BR>
Ultima versione ipertestuale disponibile su <A TITLE="versione
stampabile"
HREF="http://softwarelibero.it/documentazione/softwarelibero.html">&lt;http://softwarelibero.it/documentazione/softwarelibero.html></A>
</P>
<P>
La copia letterale e integrale e la distribuzione sono permesse con
qualsiasi mezzo, a condizione che questa nota sia riprodotta.
</P>
<!--
Local variables:
fill-column: 72
time-stamp-active: t
time-stamp-time-zone: "GMT"
time-stamp-format: "%:y-%02m-%02d"
time-stamp-line-limit: 30
time-stamp-start: "ultima\\s-+modifica\\s-+è\\s-+del\\s-+"
time-stamp-end: "\\."
End:
-->
</DIV>

View file

@ -0,0 +1,658 @@
/*
* @(#)AWTEventMulticaster.java 1.10 97/01/23
*
* Copyright (c) 1996 Sun Microsystems, Inc. All Rights Reserved.
*
* This software is the confidential and proprietary information of Sun
* Microsystems, Inc. ("Confidential Information"). You shall not
* disclose such Confidential Information and shall use it only in
* accordance with the terms of the license agreement you entered into
* with Sun.
*
* SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE
* SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
* IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
* PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR ANY DAMAGES
* SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING
* THIS SOFTWARE OR ITS DERIVATIVES.
*
* CopyrightVersion 1.1_beta
*
*/
package java.awt;
import java.awt.event.*;
import java.util.EventListener;
import java.io.Serializable;
import java.io.ObjectOutputStream;
import java.io.IOException;
/**
* A class which implements efficient multi-cast event dispatching
* for the AWT events defined in the java.awt.event package. This
* class will manage the structure of a chain of event listeners
* and dispatch events to those listeners.
*
* An example of how this class could be used to implement a new
* component which fires "action" events:
*
* <pre><code>
* public myComponent extends Component {
* ActionListener actionListener = null;
*
* public void addActionListener(ActionListener l) {
* actionListener = AWTEventMulticaster.add(actionListener, l);
* }
* public void removeActionListener(ActionListener l) {
* actionListener = AWTEventMulticaster.remove(actionListener, l);
* }
* public void processEvent(AWTEvent e) {
* // when event occurs which causes "action" semantic
* if (actionListener != null) {
* actionListener.actionPerformed(new ActionEvent());
* }
* }
* </code></pre>
*
* @version 1.10, 23 Jan 1997
* @author John Rose
* @author Amy Fowler
*/
public class AWTEventMulticaster implements
ComponentListener, ContainerListener, FocusListener, KeyListener,
MouseListener, MouseMotionListener, WindowListener,
ActionListener, ItemListener, AdjustmentListener,
TextListener {
protected EventListener a, b;
/**
* Creates an event multicaster instance which chains listener-a
* with listener-b.
* @param a listener-a
* @param b listener-b
*/
protected AWTEventMulticaster(EventListener a, EventListener b) {
this.a = a; this.b = b;
}
/**
* Removes a listener from this multicaster and returns the
* resulting multicast listener.
* @param oldl the listener to be removed
*/
protected EventListener remove(EventListener oldl) {
if (oldl == a) return b;
if (oldl == b) return a;
EventListener a2 = removeInternal(a, oldl);
EventListener b2 = removeInternal(b, oldl);
if (a2 == a && b2 == b) {
return this; // it's not here
}
return addInternal(a2, b2);
}
/**
* Handles the componentResized event by invoking the
* componentResized methods on listener-a and listener-b.
* @param e the component event
*/
public void componentResized(ComponentEvent e) {
((ComponentListener)a).componentResized(e);
((ComponentListener)b).componentResized(e);
}
/**
* Handles the componentMoved event by invoking the
* componentMoved methods on listener-a and listener-b.
* @param e the component event
*/
public void componentMoved(ComponentEvent e) {
((ComponentListener)a).componentMoved(e);
((ComponentListener)b).componentMoved(e);
}
/**
* Handles the componentShown event by invoking the
* componentShown methods on listener-a and listener-b.
* @param e the component event
*/
public void componentShown(ComponentEvent e) {
((ComponentListener)a).componentShown(e);
((ComponentListener)b).componentShown(e);
}
/**
* Handles the componentHidden event by invoking the
* componentHidden methods on listener-a and listener-b.
* @param e the component event
*/
public void componentHidden(ComponentEvent e) {
((ComponentListener)a).componentHidden(e);
((ComponentListener)b).componentHidden(e);
}
/**
* Handles the componentAdded container event by invoking the
* componentAdded methods on listener-a and listener-b.
* @param e the component event
*/
public void componentAdded(ContainerEvent e) {
((ContainerListener)a).componentAdded(e);
((ContainerListener)b).componentAdded(e);
}
/**
* Handles the componentRemoved container event by invoking the
* componentRemoved methods on listener-a and listener-b.
* @param e the component event
*/
public void componentRemoved(ContainerEvent e) {
((ContainerListener)a).componentRemoved(e);
((ContainerListener)b).componentRemoved(e);
}
/**
* Handles the focusGained event by invoking the
* focusGained methods on listener-a and listener-b.
* @param e the focus event
*/
public void focusGained(FocusEvent e) {
((FocusListener)a).focusGained(e);
((FocusListener)b).focusGained(e);
}
/**
* Handles the focusLost event by invoking the
* focusLost methods on listener-a and listener-b.
* @param e the focus event
*/
public void focusLost(FocusEvent e) {
((FocusListener)a).focusLost(e);
((FocusListener)b).focusLost(e);
}
/**
* Handles the keyTyped event by invoking the
* keyTyped methods on listener-a and listener-b.
* @param e the key event
*/
public void keyTyped(KeyEvent e) {
((KeyListener)a).keyTyped(e);
((KeyListener)b).keyTyped(e);
}
/**
* Handles the keyPressed event by invoking the
* keyPressed methods on listener-a and listener-b.
* @param e the key event
*/
public void keyPressed(KeyEvent e) {
((KeyListener)a).keyPressed(e);
((KeyListener)b).keyPressed(e);
}
/**
* Handles the keyReleased event by invoking the
* keyReleased methods on listener-a and listener-b.
* @param e the key event
*/
public void keyReleased(KeyEvent e) {
((KeyListener)a).keyReleased(e);
((KeyListener)b).keyReleased(e);
}
/**
* Handles the mouseClicked event by invoking the
* mouseClicked methods on listener-a and listener-b.
* @param e the mouse event
*/
public void mouseClicked(MouseEvent e) {
((MouseListener)a).mouseClicked(e);
((MouseListener)b).mouseClicked(e);
}
/**
* Handles the mousePressed event by invoking the
* mousePressed methods on listener-a and listener-b.
* @param e the mouse event
*/
public void mousePressed(MouseEvent e) {
((MouseListener)a).mousePressed(e);
((MouseListener)b).mousePressed(e);
}
/**
* Handles the mouseReleased event by invoking the
* mouseReleased methods on listener-a and listener-b.
* @param e the mouse event
*/
public void mouseReleased(MouseEvent e) {
((MouseListener)a).mouseReleased(e);
((MouseListener)b).mouseReleased(e);
}
/**
* Handles the mouseEntered event by invoking the
* mouseEntered methods on listener-a and listener-b.
* @param e the mouse event
*/
public void mouseEntered(MouseEvent e) {
((MouseListener)a).mouseEntered(e);
((MouseListener)b).mouseEntered(e);
}
/**
* Handles the mouseExited event by invoking the
* mouseExited methods on listener-a and listener-b.
* @param e the mouse event
*/
public void mouseExited(MouseEvent e) {
((MouseListener)a).mouseExited(e);
((MouseListener)b).mouseExited(e);
}
/**
* Handles the mouseDragged event by invoking the
* mouseDragged methods on listener-a and listener-b.
* @param e the mouse event
*/
public void mouseDragged(MouseEvent e) {
((MouseMotionListener)a).mouseDragged(e);
((MouseMotionListener)b).mouseDragged(e);
}
/**
* Handles the mouseMoved event by invoking the
* mouseMoved methods on listener-a and listener-b.
* @param e the mouse event
*/
public void mouseMoved(MouseEvent e) {
((MouseMotionListener)a).mouseMoved(e);
((MouseMotionListener)b).mouseMoved(e);
}
/**
* Handles the windowOpened event by invoking the
* windowOpened methods on listener-a and listener-b.
* @param e the window event
*/
public void windowOpened(WindowEvent e) {
((WindowListener)a).windowOpened(e);
((WindowListener)b).windowOpened(e);
}
/**
* Handles the windowClosing event by invoking the
* windowClosing methods on listener-a and listener-b.
* @param e the window event
*/
public void windowClosing(WindowEvent e) {
((WindowListener)a).windowClosing(e);
((WindowListener)b).windowClosing(e);
}
/**
* Handles the windowClosed event by invoking the
* windowClosed methods on listener-a and listener-b.
* @param e the window event
*/
public void windowClosed(WindowEvent e) {
((WindowListener)a).windowClosed(e);
((WindowListener)b).windowClosed(e);
}
/**
* Handles the windowIconified event by invoking the
* windowIconified methods on listener-a and listener-b.
* @param e the window event
*/
public void windowIconified(WindowEvent e) {
((WindowListener)a).windowIconified(e);
((WindowListener)b).windowIconified(e);
}
/**
* Handles the windowDeiconfied event by invoking the
* windowDeiconified methods on listener-a and listener-b.
* @param e the window event
*/
public void windowDeiconified(WindowEvent e) {
((WindowListener)a).windowDeiconified(e);
((WindowListener)b).windowDeiconified(e);
}
/**
* Handles the windowActivated event by invoking the
* windowActivated methods on listener-a and listener-b.
* @param e the window event
*/
public void windowActivated(WindowEvent e) {
((WindowListener)a).windowActivated(e);
((WindowListener)b).windowActivated(e);
}
/**
* Handles the windowDeactivated event by invoking the
* windowDeactivated methods on listener-a and listener-b.
* @param e the window event
*/
public void windowDeactivated(WindowEvent e) {
((WindowListener)a).windowDeactivated(e);
((WindowListener)b).windowDeactivated(e);
}
/**
* Handles the actionPerformed event by invoking the
* actionPerformed methods on listener-a and listener-b.
* @param e the action event
*/
public void actionPerformed(ActionEvent e) {
((ActionListener)a).actionPerformed(e);
((ActionListener)b).actionPerformed(e);
}
/**
* Handles the itemStateChanged event by invoking the
* itemStateChanged methods on listener-a and listener-b.
* @param e the item event
*/
public void itemStateChanged(ItemEvent e) {
((ItemListener)a).itemStateChanged(e);
((ItemListener)b).itemStateChanged(e);
}
/**
* Handles the adjustmentValueChanged event by invoking the
* adjustmentValueChanged methods on listener-a and listener-b.
* @param e the adjustment event
*/
public void adjustmentValueChanged(AdjustmentEvent e) {
((AdjustmentListener)a).adjustmentValueChanged(e);
((AdjustmentListener)b).adjustmentValueChanged(e);
}
public void textValueChanged(TextEvent e) {
((TextListener)a).textValueChanged(e);
((TextListener)b).textValueChanged(e);
}
/**
* Adds component-listener-a with component-listener-b and
* returns the resulting multicast listener.
* @param a component-listener-a
* @param b component-listener-b
*/
public static ComponentListener add(ComponentListener a, ComponentListener b) {
return (ComponentListener)addInternal(a, b);
}
/**
* Adds container-listener-a with container-listener-b and
* returns the resulting multicast listener.
* @param a container-listener-a
* @param b container-listener-b
*/
public static ContainerListener add(ContainerListener a, ContainerListener b) {
return (ContainerListener)addInternal(a, b);
}
/**
* Adds focus-listener-a with focus-listener-b and
* returns the resulting multicast listener.
* @param a focus-listener-a
* @param b focus-listener-b
*/
public static FocusListener add(FocusListener a, FocusListener b) {
return (FocusListener)addInternal(a, b);
}
/**
* Adds key-listener-a with key-listener-b and
* returns the resulting multicast listener.
* @param a key-listener-a
* @param b key-listener-b
*/
public static KeyListener add(KeyListener a, KeyListener b) {
return (KeyListener)addInternal(a, b);
}
/**
* Adds mouse-listener-a with mouse-listener-b and
* returns the resulting multicast listener.
* @param a mouse-listener-a
* @param b mouse-listener-b
*/
public static MouseListener add(MouseListener a, MouseListener b) {
return (MouseListener)addInternal(a, b);
}
/**
* Adds mouse-motion-listener-a with mouse-motion-listener-b and
* returns the resulting multicast listener.
* @param a mouse-motion-listener-a
* @param b mouse-motion-listener-b
*/
public static MouseMotionListener add(MouseMotionListener a, MouseMotionListener b) {
return (MouseMotionListener)addInternal(a, b);
}
/**
* Adds window-listener-a with window-listener-b and
* returns the resulting multicast listener.
* @param a window-listener-a
* @param b window-listener-b
*/
public static WindowListener add(WindowListener a, WindowListener b) {
return (WindowListener)addInternal(a, b);
}
/**
* Adds action-listener-a with action-listener-b and
* returns the resulting multicast listener.
* @param a action-listener-a
* @param b action-listener-b
*/
public static ActionListener add(ActionListener a, ActionListener b) {
return (ActionListener)addInternal(a, b);
}
/**
* Adds item-listener-a with item-listener-b and
* returns the resulting multicast listener.
* @param a item-listener-a
* @param b item-listener-b
*/
public static ItemListener add(ItemListener a, ItemListener b) {
return (ItemListener)addInternal(a, b);
}
/**
* Adds adjustment-listener-a with adjustment-listener-b and
* returns the resulting multicast listener.
* @param a adjustment-listener-a
* @param b adjustment-listener-b
*/
public static AdjustmentListener add(AdjustmentListener a, AdjustmentListener b) {
return (AdjustmentListener)addInternal(a, b);
}
public static TextListener add(TextListener a, TextListener b) {
return (TextListener)addInternal(a, b);
}
/**
* Removes the old component-listener from component-listener-l and
* returns the resulting multicast listener.
* @param l component-listener-l
* @param oldl the component-listener being removed
*/
public static ComponentListener remove(ComponentListener l, ComponentListener oldl) {
return (ComponentListener) removeInternal(l, oldl);
}
/**
* Removes the old container-listener from container-listener-l and
* returns the resulting multicast listener.
* @param l container-listener-l
* @param oldl the container-listener being removed
*/
public static ContainerListener remove(ContainerListener l, ContainerListener oldl) {
return (ContainerListener) removeInternal(l, oldl);
}
/**
* Removes the old focus-listener from focus-listener-l and
* returns the resulting multicast listener.
* @param l focus-listener-l
* @param oldl the focus-listener being removed
*/
public static FocusListener remove(FocusListener l, FocusListener oldl) {
return (FocusListener) removeInternal(l, oldl);
}
/**
* Removes the old key-listener from key-listener-l and
* returns the resulting multicast listener.
* @param l key-listener-l
* @param oldl the key-listener being removed
*/
public static KeyListener remove(KeyListener l, KeyListener oldl) {
return (KeyListener) removeInternal(l, oldl);
}
/**
* Removes the old mouse-listener from mouse-listener-l and
* returns the resulting multicast listener.
* @param l mouse-listener-l
* @param oldl the mouse-listener being removed
*/
public static MouseListener remove(MouseListener l, MouseListener oldl) {
return (MouseListener) removeInternal(l, oldl);
}
/**
* Removes the old mouse-motion-listener from mouse-motion-listener-l
* and returns the resulting multicast listener.
* @param l mouse-motion-listener-l
* @param oldl the mouse-motion-listener being removed
*/
public static MouseMotionListener remove(MouseMotionListener l, MouseMotionListener oldl) {
return (MouseMotionListener) removeInternal(l, oldl);
}
/**
* Removes the old window-listener from window-listener-l and
* returns the resulting multicast listener.
* @param l window-listener-l
* @param oldl the window-listener being removed
*/
public static WindowListener remove(WindowListener l, WindowListener oldl) {
return (WindowListener) removeInternal(l, oldl);
}
/**
* Removes the old action-listener from action-listener-l and
* returns the resulting multicast listener.
* @param l action-listener-l
* @param oldl the action-listener being removed
*/
public static ActionListener remove(ActionListener l, ActionListener oldl) {
return (ActionListener) removeInternal(l, oldl);
}
/**
* Removes the old item-listener from item-listener-l and
* returns the resulting multicast listener.
* @param l item-listener-l
* @param oldl the item-listener being removed
*/
public static ItemListener remove(ItemListener l, ItemListener oldl) {
return (ItemListener) removeInternal(l, oldl);
}
/**
* Removes the old adjustment-listener from adjustment-listener-l and
* returns the resulting multicast listener.
* @param l adjustment-listener-l
* @param oldl the adjustment-listener being removed
*/
public static AdjustmentListener remove(AdjustmentListener l, AdjustmentListener oldl) {
return (AdjustmentListener) removeInternal(l, oldl);
}
public static TextListener remove(TextListener l, TextListener oldl) {
return (TextListener) removeInternal(l, oldl);
}
/**
* Returns the resulting multicast listener from adding listener-a
* and listener-b together.
* If listener-a is null, it returns listener-b;
* If listener-b is null, it returns listener-a
* If neither are null, then it creates and returns
* a new AWTEventMulticaster instance which chains a with b.
* @param a event listener-a
* @param b event listener-b
*/
protected static EventListener addInternal(EventListener a, EventListener b) {
if (a == null) return b;
if (b == null) return a;
return new AWTEventMulticaster(a, b);
}
/**
* Returns the resulting multicast listener after removing the
* old listener from listener-l.
* If listener-l equals the old listener OR listener-l is null,
* returns null.
* Else if listener-l is an instance of AWTEventMulticaster,
* then it removes the old listener from it.
* Else, returns listener l.
* @param l the listener being removed from
* @param oldl the listener being removed
*/
protected static EventListener removeInternal(EventListener l, EventListener oldl) {
if (l == oldl || l == null) {
return null;
} else if (l instanceof AWTEventMulticaster) {
return ((AWTEventMulticaster)l).remove(oldl);
} else {
return l; // it's not here
}
}
/* Serialization support.
*/
protected void saveInternal(ObjectOutputStream s, String k) throws IOException {
if (a instanceof AWTEventMulticaster) {
((AWTEventMulticaster)a).saveInternal(s, k);
}
else if (a instanceof Serializable) {
s.writeObject(k);
s.writeObject(a);
}
if (b instanceof AWTEventMulticaster) {
((AWTEventMulticaster)b).saveInternal(s, k);
}
else if (b instanceof Serializable) {
s.writeObject(k);
s.writeObject(b);
}
}
static void save(ObjectOutputStream s, String k, EventListener l) throws IOException {
if (l == null) {
return;
}
else if (l instanceof AWTEventMulticaster) {
((AWTEventMulticaster)l).saveInternal(s, k);
}
else if (l instanceof Serializable) {
s.writeObject(k);
s.writeObject(l);
}
}
}

View file

@ -0,0 +1,440 @@
/*
* @(#)KeyEvent.java 1.20 97/01/30
*
* Copyright (c) 1995, 1996 Sun Microsystems, Inc. All Rights Reserved.
*
* This software is the confidential and proprietary information of Sun
* Microsystems, Inc. ("Confidential Information"). You shall not
* disclose such Confidential Information and shall use it only in
* accordance with the terms of the license agreement you entered into
* with Sun.
*
* SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE
* SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
* IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
* PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR ANY DAMAGES
* SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING
* THIS SOFTWARE OR ITS DERIVATIVES.
*
* CopyrightVersion 1.1_beta
*
*/
package java.awt.event;
import java.awt.Event;
import java.awt.Component;
import java.awt.Toolkit;
/**
* The component-level keyboard event.
*
* @version 1.20 30 Jan 1997
* @author Carl Quinn
* @author Amy Fowler
*/
public class KeyEvent extends InputEvent {
/**
* Marks the first integer id for the range of key event ids.
*/
public static final int KEY_FIRST = 400;
/**
* Marks the last integer id for the range of key event ids.
*/
public static final int KEY_LAST = 402;
/**
* The key typed event type. This type is generated by a combination
* of a key press followed by a key release.
*/
public static final int KEY_TYPED = KEY_FIRST;
/**
* The key pressed event type.
*/
public static final int KEY_PRESSED = 1 + KEY_FIRST; //Event.KEY_PRESS
/**
* The key released event type.
*/
public static final int KEY_RELEASED = 2 + KEY_FIRST; //Event.KEY_RELEASE
/**
* Virtual key codes. These codes report which keyboard key has
* been pressed, rather than any character generated by one or more
* keys being pressed.
*
* For example, pressing the Shift key will cause a KEY_PRESSED event
* with a VK_SHIFT keyCode, while pressing the 'a' key will result in
* a VK_A keyCode. After the 'a' key is released, a KEY_RELEASED event
* will be fired with VK_A, followed by a KEY_TYPED event with a keyChar
* value of 'A'. Key combinations which do not result in characters,
* such as action keys like F1, will not generate KEY_TYPED events.
*
* Note: not all keyboards or systems are capable of generating all
* virtual key codes. No attempt is made in Java to artificially
* generate these keys.
*
* WARNING: aside from those keys where are defined by the Java language
* (VK_ENTER, VK_BACK_SPACE, and VK_TAB), do not rely on the values of these
* constants. Sun reserves the right to change these values as needed
* to accomodate a wider range of keyboards in the future.
*/
public static final int VK_ENTER = '\n';
public static final int VK_BACK_SPACE = '\b';
public static final int VK_TAB = '\t';
public static final int VK_CANCEL = 0x03;
public static final int VK_CLEAR = 0x0C;
public static final int VK_SHIFT = 0x10;
public static final int VK_CONTROL = 0x11;
public static final int VK_ALT = 0x12;
public static final int VK_PAUSE = 0x13;
public static final int VK_CAPS_LOCK = 0x14;
public static final int VK_ESCAPE = 0x1B;
public static final int VK_SPACE = 0x20;
public static final int VK_PAGE_UP = 0x21;
public static final int VK_PAGE_DOWN = 0x22;
public static final int VK_END = 0x23;
public static final int VK_HOME = 0x24;
public static final int VK_LEFT = 0x25;
public static final int VK_UP = 0x26;
public static final int VK_RIGHT = 0x27;
public static final int VK_DOWN = 0x28;
public static final int VK_COMMA = 0x2C;
public static final int VK_PERIOD = 0x2E;
public static final int VK_SLASH = 0x2F;
/** VK_0 thru VK_9 are the same as ASCII '0' thru '9' (0x30 - 0x39) */
public static final int VK_0 = 0x30;
public static final int VK_1 = 0x31;
public static final int VK_2 = 0x32;
public static final int VK_3 = 0x33;
public static final int VK_4 = 0x34;
public static final int VK_5 = 0x35;
public static final int VK_6 = 0x36;
public static final int VK_7 = 0x37;
public static final int VK_8 = 0x38;
public static final int VK_9 = 0x39;
public static final int VK_SEMICOLON = 0x3B;
public static final int VK_EQUALS = 0x3D;
/** VK_A thru VK_Z are the same as ASCII 'A' thru 'Z' (0x41 - 0x5A) */
public static final int VK_A = 0x41;
public static final int VK_B = 0x42;
public static final int VK_C = 0x43;
public static final int VK_D = 0x44;
public static final int VK_E = 0x45;
public static final int VK_F = 0x46;
public static final int VK_G = 0x47;
public static final int VK_H = 0x48;
public static final int VK_I = 0x49;
public static final int VK_J = 0x4A;
public static final int VK_K = 0x4B;
public static final int VK_L = 0x4C;
public static final int VK_M = 0x4D;
public static final int VK_N = 0x4E;
public static final int VK_O = 0x4F;
public static final int VK_P = 0x50;
public static final int VK_Q = 0x51;
public static final int VK_R = 0x52;
public static final int VK_S = 0x53;
public static final int VK_T = 0x54;
public static final int VK_U = 0x55;
public static final int VK_V = 0x56;
public static final int VK_W = 0x57;
public static final int VK_X = 0x58;
public static final int VK_Y = 0x59;
public static final int VK_Z = 0x5A;
public static final int VK_OPEN_BRACKET = 0x5B;
public static final int VK_BACK_SLASH = 0x5C;
public static final int VK_CLOSE_BRACKET = 0x5D;
public static final int VK_NUMPAD0 = 0x60;
public static final int VK_NUMPAD1 = 0x61;
public static final int VK_NUMPAD2 = 0x62;
public static final int VK_NUMPAD3 = 0x63;
public static final int VK_NUMPAD4 = 0x64;
public static final int VK_NUMPAD5 = 0x65;
public static final int VK_NUMPAD6 = 0x66;
public static final int VK_NUMPAD7 = 0x67;
public static final int VK_NUMPAD8 = 0x68;
public static final int VK_NUMPAD9 = 0x69;
public static final int VK_MULTIPLY = 0x6A;
public static final int VK_ADD = 0x6B;
public static final int VK_SEPARATER = 0x6C;
public static final int VK_SUBTRACT = 0x6D;
public static final int VK_DECIMAL = 0x6E;
public static final int VK_DIVIDE = 0x6F;
public static final int VK_F1 = 0x70;
public static final int VK_F2 = 0x71;
public static final int VK_F3 = 0x72;
public static final int VK_F4 = 0x73;
public static final int VK_F5 = 0x74;
public static final int VK_F6 = 0x75;
public static final int VK_F7 = 0x76;
public static final int VK_F8 = 0x77;
public static final int VK_F9 = 0x78;
public static final int VK_F10 = 0x79;
public static final int VK_F11 = 0x7A;
public static final int VK_F12 = 0x7B;
public static final int VK_DELETE = 0x7F; /* ASCII DEL */
public static final int VK_NUM_LOCK = 0x90;
public static final int VK_SCROLL_LOCK = 0x91;
public static final int VK_PRINTSCREEN = 0x9A;
public static final int VK_INSERT = 0x9B;
public static final int VK_HELP = 0x9C;
public static final int VK_META = 0x9D;
public static final int VK_BACK_QUOTE = 0xC0;
public static final int VK_QUOTE = 0xDE;
/** for Asian Keyboard */
public static final int VK_FINAL = 0x18;
public static final int VK_CONVERT = 0x1C;
public static final int VK_NONCONVERT = 0x1D;
public static final int VK_ACCEPT = 0x1E;
public static final int VK_MODECHANGE = 0x1F;
public static final int VK_KANA = 0x15;
public static final int VK_KANJI = 0x19;
/**
* KEY_TYPED events do not have a defined keyCode.
*/
public static final int VK_UNDEFINED = 0x0;
/**
* KEY_PRESSED and KEY_RELEASED events which do not map to a
* valid Unicode character do not have a defined keyChar.
*/
public static final char CHAR_UNDEFINED = 0x0;
int keyCode;
char keyChar;
/*
* JDK 1.1 serialVersionUID
*/
private static final long serialVersionUID = -2352130953028126954L;
/**
* Constructs a KeyEvent object with the specified source component,
* type, modifiers, and key.
* @param source the object where the event originated
* @id the event type
* @when the time the event occurred
* @modifiers the modifier keys down during event
* @keyCode the integer code representing the key of the event
* @keyChar the Unicode character generated by this event, or NUL
*/
public KeyEvent(Component source, int id, long when, int modifiers,
int keyCode, char keyChar) {
super(source, id, when, modifiers);
if (id == KEY_TYPED && keyChar == CHAR_UNDEFINED) {
throw new IllegalArgumentException("invalid keyChar");
}
if (id == KEY_TYPED && keyCode != VK_UNDEFINED) {
throw new IllegalArgumentException("invalid keyCode");
}
this.keyCode = keyCode;
this.keyChar = keyChar;
}
/*
* @deprecated, as of JDK1.1 - Do NOT USE; will be removed in 1.1.1.
*/
public KeyEvent(Component source, int id, long when, int modifiers,
int keyCode) {
this(source, id, when, modifiers, keyCode, (char)keyCode);
}
/**
* Returns the integer key-code associated with the key in this event.
* For KEY_TYPED events, keyCode is VK_UNDEFINED.
*/
public int getKeyCode() {
return keyCode;
}
public void setKeyCode(int keyCode) {
this.keyCode = keyCode;
}
public void setKeyChar(char keyChar) {
this.keyChar = keyChar;
}
public void setModifiers(int modifiers) {
this.modifiers = modifiers;
}
/**
* Returns the character associated with the key in this event.
* If no valid Unicode character exists for this key event, keyChar
* is CHAR_UNDEFINED.
*/
public char getKeyChar() {
return keyChar;
}
/**
* Returns a String describing the keyCode, such as "HOME", "F1" or "A".
* These strings can be localized by changing the awt.properties file.
*/
public static String getKeyText(int keyCode) {
if (keyCode >= VK_0 && keyCode <= VK_9 ||
keyCode >= VK_A && keyCode <= VK_Z) {
return String.valueOf((char)keyCode);
}
// Check for other ASCII keyCodes.
int index = ",./;=[\\]".indexOf(keyCode);
if (index >= 0) {
return String.valueOf((char)keyCode);
}
switch(keyCode) {
case VK_ENTER: return Toolkit.getProperty("AWT.enter", "Enter");
case VK_BACK_SPACE: return Toolkit.getProperty("AWT.backSpace", "Backspace");
case VK_TAB: return Toolkit.getProperty("AWT.tab", "Tab");
case VK_CANCEL: return Toolkit.getProperty("AWT.cancel", "Cancel");
case VK_CLEAR: return Toolkit.getProperty("AWT.clear", "Clear");
case VK_SHIFT: return Toolkit.getProperty("AWT.shift", "Shift");
case VK_CONTROL: return Toolkit.getProperty("AWT.control", "Control");
case VK_ALT: return Toolkit.getProperty("AWT.alt", "Alt");
case VK_PAUSE: return Toolkit.getProperty("AWT.pause", "Pause");
case VK_CAPS_LOCK: return Toolkit.getProperty("AWT.capsLock", "Caps Lock");
case VK_ESCAPE: return Toolkit.getProperty("AWT.escape", "Escape");
case VK_SPACE: return Toolkit.getProperty("AWT.space", "Space");
case VK_PAGE_UP: return Toolkit.getProperty("AWT.pgup", "Page Up");
case VK_PAGE_DOWN: return Toolkit.getProperty("AWT.pgdn", "Page Down");
case VK_END: return Toolkit.getProperty("AWT.end", "End");
case VK_HOME: return Toolkit.getProperty("AWT.home", "Home");
case VK_LEFT: return Toolkit.getProperty("AWT.left", "Left");
case VK_UP: return Toolkit.getProperty("AWT.up", "Up");
case VK_RIGHT: return Toolkit.getProperty("AWT.right", "Right");
case VK_DOWN: return Toolkit.getProperty("AWT.down", "Down");
case VK_MULTIPLY: return Toolkit.getProperty("AWT.multiply", "NumPad *");
case VK_ADD: return Toolkit.getProperty("AWT.add", "NumPad +");
case VK_SEPARATER: return Toolkit.getProperty("AWT.separater", "NumPad ,");
case VK_SUBTRACT: return Toolkit.getProperty("AWT.subtract", "NumPad -");
case VK_DECIMAL: return Toolkit.getProperty("AWT.decimal", "NumPad .");
case VK_DIVIDE: return Toolkit.getProperty("AWT.divide", "NumPad /");
case VK_F1: return Toolkit.getProperty("AWT.f1", "F1");
case VK_F2: return Toolkit.getProperty("AWT.f2", "F2");
case VK_F3: return Toolkit.getProperty("AWT.f3", "F3");
case VK_F4: return Toolkit.getProperty("AWT.f4", "F4");
case VK_F5: return Toolkit.getProperty("AWT.f5", "F5");
case VK_F6: return Toolkit.getProperty("AWT.f6", "F6");
case VK_F7: return Toolkit.getProperty("AWT.f7", "F7");
case VK_F8: return Toolkit.getProperty("AWT.f8", "F8");
case VK_F9: return Toolkit.getProperty("AWT.f9", "F9");
case VK_F10: return Toolkit.getProperty("AWT.f10", "F10");
case VK_F11: return Toolkit.getProperty("AWT.f11", "F11");
case VK_F12: return Toolkit.getProperty("AWT.f12", "F12");
case VK_DELETE: return Toolkit.getProperty("AWT.delete", "Delete");
case VK_NUM_LOCK: return Toolkit.getProperty("AWT.numLock", "Num Lock");
case VK_SCROLL_LOCK: return Toolkit.getProperty("AWT.scrollLock", "Scroll Lock");
case VK_PRINTSCREEN: return Toolkit.getProperty("AWT.printScreen", "Print Screen");
case VK_INSERT: return Toolkit.getProperty("AWT.insert", "Insert");
case VK_HELP: return Toolkit.getProperty("AWT.help", "Help");
case VK_META: return Toolkit.getProperty("AWT.meta", "Meta");
case VK_BACK_QUOTE: return Toolkit.getProperty("AWT.backQuote", "Back Quote");
case VK_QUOTE: return Toolkit.getProperty("AWT.quote", "Quote");
case VK_FINAL: return Toolkit.getProperty("AWT.final", "Final");
case VK_CONVERT: return Toolkit.getProperty("AWT.convert", "Convert");
case VK_NONCONVERT: return Toolkit.getProperty("AWT.noconvert", "No Convert");
case VK_ACCEPT: return Toolkit.getProperty("AWT.accept", "Accept");
case VK_MODECHANGE: return Toolkit.getProperty("AWT.modechange", "Mode Change");
case VK_KANA: return Toolkit.getProperty("AWT.kana", "Kana");
case VK_KANJI: return Toolkit.getProperty("AWT.kanji", "Kanji");
}
if (keyCode >= VK_NUMPAD0 && keyCode <= VK_NUMPAD9) {
String numpad = Toolkit.getProperty("AWT.numpad", "NumPad");
char c = (char)(keyCode - VK_NUMPAD0 + '0');
return numpad + "-" + c;
}
String unknown = Toolkit.getProperty("AWT.unknown", "Unknown keyCode");
return unknown + ": 0x" + Integer.toString(keyCode, 16);
}
/**
* Returns a String describing the modifier key(s), such as "Shift",
* or "Ctrl+Shift". These strings can be localized by changing the
* awt.properties file.
*/
public static String getKeyModifiersText(int modifiers) {
StringBuffer buf = new StringBuffer();
if ((modifiers & Event.META_MASK) != 0) {
buf.append(Toolkit.getProperty("AWT.meta", "Meta"));
buf.append("+");
}
if ((modifiers & Event.CTRL_MASK) != 0) {
buf.append(Toolkit.getProperty("AWT.control", "Ctrl"));
buf.append("+");
}
if ((modifiers & Event.META_MASK) != 0) {
buf.append(Toolkit.getProperty("AWT.alt", "Alt"));
buf.append("+");
}
if ((modifiers & Event.SHIFT_MASK) != 0) {
buf.append(Toolkit.getProperty("AWT.shift", "Shift"));
buf.append("+");
}
if (buf.length() > 0) {
buf.setLength(buf.length()-1); // remove trailing '+'
}
return buf.toString();
}
/** Returns whether or not the key in this event is an "action" key.
*/
public boolean isActionKey() {
return (keyChar == CHAR_UNDEFINED);
}
public String paramString() {
String typeStr;
switch(id) {
case KEY_PRESSED:
typeStr = "KEY_PRESSED";
break;
case KEY_RELEASED:
typeStr = "KEY_RELEASED";
break;
case KEY_TYPED:
typeStr = "KEY_TYPED";
break;
default:
typeStr = "unknown type";
}
String str = typeStr + ",keyCode=" + keyCode;
if (isActionKey() || keyCode == VK_ENTER || keyCode == VK_BACK_SPACE ||
keyCode == VK_TAB || keyCode == VK_ESCAPE || keyCode == VK_DELETE ||
(keyCode >= VK_NUMPAD0 && keyCode <= VK_NUMPAD9)) {
str += "," + getKeyText(keyCode);
} else if (keyChar == '\n' || keyChar == '\b' ||
keyChar == '\t' || keyChar == VK_ESCAPE || keyChar == VK_DELETE) {
str += "," + getKeyText(keyChar);
} else {
str += ",keyChar='" + keyChar + "'";
}
if (modifiers > 0) {
str += ",modifiers=" + getKeyModifiersText(modifiers);
}
return str;
}
}

View file

@ -0,0 +1,848 @@
/*
* @(#)SecurityManager.java 1.46 97/01/27
*
* Copyright (c) 1995, 1996 Sun Microsystems, Inc. All Rights Reserved.
*
* This software is the confidential and proprietary information of Sun
* Microsystems, Inc. ("Confidential Information"). You shall not
* disclose such Confidential Information and shall use it only in
* accordance with the terms of the license agreement you entered into
* with Sun.
*
* SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE
* SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
* IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
* PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR ANY DAMAGES
* SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING
* THIS SOFTWARE OR ITS DERIVATIVES.
*
* CopyrightVersion 1.1_beta
*
*/
package java.lang;
import java.io.FileDescriptor;
import java.util.Hashtable;
import java.net.InetAddress;
import java.lang.reflect.Member;
/**
* The security manager is an abstract class that allows
* applications to implement a security policy. It allows an
* application to determine, before performing a possibly unsafe or
* sensitive operation, what the operation is and whether the
* operation is being performed by a class created via a class loader
* rather than installed locally. Classes loaded via a class loader
* (especially if they have been downloaded over a network) may be
* less trustworthy than classes from files installed locally. The
* application can allow or disallow the operation.
* <p>
* The <code>SecurityManager</code> class contains many methods with
* names that begin with the word <code>check</code>. These methods
* are called by various methods in the Java libraries before those
* methods perform certain potentially sensitive operations. The
* invocation of such a check method typically looks like this:
* <p><blockquote><pre>
* SecurityManager security = System.getSecurityManager();
* if (security != null) {
* security.check</code><i>XXX</i><code>(argument, &nbsp;.&nbsp;.&nbsp;.&nbsp;);
* }
* </pre></blockquote>
* <p>
* The security manager is thereby given an opportunity to prevent
* completion of the operation by throwing an exception. A security
* manager routine simply returns if the operation is permitted, but
* throws a <code>SecurityException</code> if the operation is not
* permitted. The only exception to this convention is
* <code>checkTopLevelWindow</code>, which returns a
* <code>boolean</code> value.
* <p>
* The current security manager is set by the
* <code>setSecurityManager</code> method in class
* <code>System</code>. The current security manager is obtained
* by the <code>getSecurityManager</code> method.
* <p>
* The default implementation of each of the
* <code>check</code><i>XXX</i> methods is to assume that the caller
* does <i>not</i> have permission to perform the requested operation.
*
* @author Arthur van Hoff
* @version 1.46, 27 Jan 1997
* @see java.lang.ClassLoader
* @see java.lang.SecurityException
* @see java.lang.SecurityManager#checkTopLevelWindow(java.lang.Object)
* @see java.lang.System#getSecurityManager()
* @see java.lang.System#setSecurityManager(java.lang.SecurityManager)
* @since JDK1.0
*/
public abstract
class SecurityManager {
/**
* This field is <code>true</code> if there is a security check in
* progress; <code>false</code> otherwise.
*
* @since JDK1.0
*/
protected boolean inCheck;
// Have we been initialized. Effective against finalizer attacks.
private boolean initialized = false;
/**
* Tests if there is a security check in progress.
*
* @return the value of the <code>inCheck</code> field. This field should
* contain <code>true</code> if a security check is in progress;
* <code>false</code> otherwise.
* @see java.lang.SecurityManager#inCheck
* @since JDK1.0
*/
public boolean getInCheck() {
return inCheck;
}
/**
* Constructs a new <code>SecurityManager</code>. An application is
* not allowed to create a new security manager if there is already a
* current security manager.
*
* @exception SecurityException if a security manager already exists.
* @see java.lang.System#getSecurityManager()
* @since JDK1.0
*/
protected SecurityManager() {
// checkCreateSecurityManager(); ? REMIND
initialized = true;
}
/**
* Returns the current execution stack as an array of classes.
* <p>
* The length of the array is the number of methods on the execution
* stack. The element at index <code>0</code> is the class of the
* currently executing method, the element at index <code>1</code> is
* the class of that method's caller, and so on.
*
* @return the execution stack.
* @since JDK1.0
*/
protected native Class[] getClassContext();
/**
* Returns an object describing the most recent class loader executing
* on the stack.
*
* @return the class loader of the most recent occurrence on the stack
* of a method from a class defined using a class loader;
* returns <code>null</code> if there is no occurrence on the
* stack of a method from a class defined using a class loader.
* @since JDK1.0
*/
protected native ClassLoader currentClassLoader();
/**
* Returns the current Class with a ClassLoader on the execution stack.
*
* @since JDK1.1
*/
protected Class currentLoadedClass() {
return currentLoadedClass0();
}
/**
* Returns the stack depth of the specified class.
*
* @param name the fully qualified name of the class to search for.
* @return the depth on the stack frame of the first occurrence of a
* method from a class with the specified name;
* <code>-1</code> if such a frame cannot be found.
* @since JDK1.0
*/
protected native int classDepth(String name);
/**
* Returns the stack depth of the most recently executing method
* from a class defined using a class loader.
*
* @return the depth on the stack frame of the most recent occurrence of a
* method from a class defined using a class loader; returns
* <code>-1</code> if there is no occurrence of a method from
* a class defined using a class loader.
* @since JDK1.0
*/
protected native int classLoaderDepth();
/**
* Tests if the specified String is in this Class.
*
* @param name the fully qualified name of the class.
* @return <code>true</code> if a method from a class with the specified
* name is on the execution stack; <code>false</code> otherwise.
* @since JDK1.0
*/
protected boolean inClass(String name) {
return classDepth(name) >= 0;
}
/**
* Tests if the current ClassLoader is equal to
* <code>null</code>.
*
* @return <code>true</code> if a method from a class defined using a
* class loader is on the execution stack.
* @since JDK1.0
*/
protected boolean inClassLoader() {
return currentClassLoader() != null;
}
/**
* Creates an object that encapsulates the current execution
* environment. The result of this method is used by the
* three-argument <code>checkConnect</code> method and by the
* two-argument <code>checkRead</code> method.
* <p>
* These methods are needed because a trusted method may be called
* on to read a file or open a socket on behalf of another method.
* The trusted method needs to determine if the other (possibly
* untrusted) method would be allowed to perform the operation on its
* own.
*
* @return an implementation-dependent object that encapsulates
* sufficient information about the current execution environment
* to perform some security checks later.
* @see java.lang.SecurityManager#checkConnect(java.lang.String,
* int, java.lang.Object)
* @see java.lang.SecurityManager#checkRead(java.lang.String,
* java.lang.Object)
* @since JDK1.0
*/
public Object getSecurityContext() {
return null;
}
/**
* Throws a <code>SecurityException</code> if the
* calling thread is not allowed to create a new class loader.
* <p>
* The <code>checkCreateClassLoader</code> method for class
* <code>SecurityManager</code> always throws a
* <code>SecurityException</code>.
*
* @exception SecurityException if the caller does not have permission
* to create a new class loader.
* @see java.lang.ClassLoader#ClassLoader()
* @since JDK1.0
*/
public void checkCreateClassLoader() {
throw new SecurityException();
}
/**
* Throws a <code>SecurityException</code> if the
* calling thread is not allowed to modify the thread argument.
* <p>
* This method is invoked for the current security manager by the
* <code>stop</code>, <code>suspend</code>, <code>resume</code>,
* <code>setPriority</code>, <code>setName</code>, and
* <code>setDaemon</code> methods of class <code>Thread</code>.
* <p>
* The <code>checkAccess</code> method for class
* <code>SecurityManager</code> always throws a
* <code>SecurityException</code>.
*
* @param g the thread to be checked.
* @exception SecurityException if the caller does not have permission
* to modify the thread.
* @see java.lang.System#getSecurityManager()
* @see java.lang.Thread#resume()
* @see java.lang.Thread#setDaemon(boolean)
* @see java.lang.Thread#setName(java.lang.String)
* @see java.lang.Thread#setPriority(int)
* @see java.lang.Thread#stop()
* @see java.lang.Thread#suspend()
* @since JDK1.0
*/
public void checkAccess(Thread g) {
throw new SecurityException();
}
/**
* Throws a <code>SecurityException</code> if the
* calling thread is not allowed to modify the thread group argument.
* <p>
* This method is invoked for the current security manager when a
* new child thread or child thread group is created, and by the
* <code>setDaemon</code>, <code>setMaxPriority</code>,
* <code>stop</code>, <code>suspend</code>, <code>resume</code>, and
* <code>destroy</code> methods of class <code>ThreadGroup</code>.
* <p>
* The <code>checkAccess</code> method for class
* <code>SecurityManager</code> always throws a
* <code>SecurityException</code>.
*
* @param g the thread group to be checked.
* @exception SecurityException if the caller does not have permission
* to modify the thread group.
* @see java.lang.System#getSecurityManager()
* @see java.lang.ThreadGroup#destroy()
* @see java.lang.ThreadGroup#resume()
* @see java.lang.ThreadGroup#setDaemon(boolean)
* @see java.lang.ThreadGroup#setMaxPriority(int)
* @see java.lang.ThreadGroup#stop()
* @see java.lang.ThreadGroup#suspend()
* @since JDK1.0
*/
public void checkAccess(ThreadGroup g) {
throw new SecurityException();
}
/**
* Throws a <code>SecurityException</code> if the
* calling thread is not allowed to cause the Java Virtual Machine to
* halt with the specified status code.
* <p>
* This method is invoked for the current security manager by the
* <code>exit</code> method of class <code>Runtime</code>. A status
* of <code>0</code> indicates success; other values indicate various
* errors.
* <p>
* The <code>checkExit</code> method for class
* <code>SecurityManager</code> always throws a
* <code>SecurityException</code>.
*
* @param status the exit status.
* @exception SecurityException if the caller does not have permission
* to halt the Java Virtual Machine with the specified status.
* @see java.lang.Runtime#exit(int)
* @see java.lang.System#getSecurityManager()
* @since JDK1.0
*/
public void checkExit(int status) {
throw new SecurityException();
}
/**
* Throws a <code>SecurityException</code> if the
* calling thread is not allowed to create a subprocss.
* <p>
* This method is invoked for the current security manager by the
* <code>exec</code> methods of class <code>Runtime</code>.
* <p>
* The <code>checkExec</code> method for class
* <code>SecurityManager</code> always throws a
* <code>SecurityException</code>.
*
* @param cmd the specified system command.
* @exception SecurityException if the caller does not have permission
* to create a subprocess.
* @see java.lang.Runtime#exec(java.lang.String)
* @see java.lang.Runtime#exec(java.lang.String, java.lang.String[])
* @see java.lang.Runtime#exec(java.lang.String[])
* @see java.lang.Runtime#exec(java.lang.String[],
* java.lang.String[])
* @see java.lang.System#getSecurityManager()
* @since JDK1.0
*/
public void checkExec(String cmd) {
throw new SecurityException();
}
/**
* Throws a <code>SecurityException</code> if the
* calling thread is not allowed to dynamic link the library code
* specified by the string argument file. The argument is either a
* simple library name or a complete filename.
* <p>
* This method is invoked for the current security manager by
* methods <code>load</code> and <code>loadLibrary</code> of class
* <code>Runtime</code>.
* <p>
* The <code>checkLink</code> method for class
* <code>SecurityManager</code> always throws a
* <code>SecurityException</code>.
*
* @param lib the name of the library.
* @exception SecurityException if the caller does not have permission
* to dynamically link the library.
* @see java.lang.Runtime#load(java.lang.String)
* @see java.lang.Runtime#loadLibrary(java.lang.String)
* @see java.lang.System#getSecurityManager()
* @since JDK1.0
*/
public void checkLink(String lib) {
throw new SecurityException();
}
/**
* Throws a <code>SecurityException</code> if the
* calling thread is not allowed to read from the specified file
* descriptor.
* <p>
* The <code>checkRead</code> method for class
* <code>SecurityManager</code> always throws a
* <code>SecurityException</code>.
*
* @param fd the system-dependent file descriptor.
* @exception SecurityException if the caller does not have permission
* to access the specified file descriptor.
* @see java.io.FileDescriptor
* @since JDK1.0
*/
public void checkRead(FileDescriptor fd) {
throw new SecurityException();
}
/**
* Throws a <code>SecurityException</code> if the
* calling thread is not allowed to read the file specified by the
* string argument.
* <p>
* The <code>checkRead</code> method for class
* <code>SecurityManager</code> always throws a
* <code>SecurityException</code>.
*
* @param file the system-dependent file name.
* @exception SecurityException if the caller does not have permission
* to access the specified file.
* @since JDK1.0
*/
public void checkRead(String file) {
throw new SecurityException();
}
/**
* Throws a <code>SecurityException</code> if the
* specified security context is not allowed to read the file
* specified by the string argument. The context must be a security
* context returned by a previous call to
* <code>getSecurityContext</code>.
* <p>
* The <code>checkRead</code> method for class
* <code>SecurityManager</code> always throws a
* <code>SecurityException</code>.
*
* @param file the system-dependent filename.
* @param context a system-dependent security context.
* @exception SecurityException if the specified security context does
* not have permission to read the specified file.
* @see java.lang.SecurityManager#getSecurityContext()
* @since JDK1.0
*/
public void checkRead(String file, Object context) {
throw new SecurityException();
}
/**
* Throws a <code>SecurityException</code> if the
* calling thread is not allowed to write to the specified file
* descriptor.
* <p>
* The <code>checkWrite</code> method for class
* <code>SecurityManager</code> always throws a
* <code>SecurityException</code>.
*
* @param fd the system-dependent file descriptor.
* @exception SecurityException if the caller does not have permission
* to access the specified file descriptor.
* @see java.io.FileDescriptor
* @since JDK1.0
*/
public void checkWrite(FileDescriptor fd) {
throw new SecurityException();
}
/**
* Throws a <code>SecurityException</code> if the
* calling thread is not allowed to write to the file specified by
* the string argument.
* <p>
* The <code>checkWrite</code> method for class
* <code>SecurityManager</code> always throws a
* <code>SecurityException</code>.
*
* @param file the system-dependent filename.
* @exception SecurityException if the caller does not have permission
* to access the specified file.
* @since JDK1.0
*/
public void checkWrite(String file) {
throw new SecurityException();
}
/**
* Throws a <code>SecurityException</code> if the
* calling thread is not allowed to delete the specified file.
* <p>
* This method is invoked for the current security manager by the
* <code>delete</code> method of class <code>File</code>.
* <p>
* The <code>checkDelete</code> method for class
* <code>SecurityManager</code> always throws a
* <code>SecurityException</code>.
*
* @param file the system-dependent filename.
* @exception SecurityException if the caller does not have permission
* to delete the file.
* @see java.io.File#delete()
* @see java.lang.System#getSecurityManager()
* @since JDK1.0
*/
public void checkDelete(String file) {
throw new SecurityException();
}
/**
* Throws a <code>SecurityException</code> if the
* calling thread is not allowed to open a socket connection to the
* specified host and port number.
* <p>
* A port number of <code>-1</code> indicates that the calling
* method is attempting to determine the IP address of the specified
* host name.
* <p>
* The <code>checkConnect</code> method for class
* <code>SecurityManager</code> always throws a
* <code>SecurityException</code>.
*
* @param host the host name port to connect to.
* @param port the protocol port to connect to.
* @exception SecurityException if the caller does not have permission
* to open a socket connection to the specified
* <code>host</code> and <code>port</code>.
* @since JDK1.0
*/
public void checkConnect(String host, int port) {
throw new SecurityException();
}
/**
* Throws a <code>SecurityException</code> if the
* specified security context is not allowed to open a socket
* connection to the specified host and port number.
* <p>
* A port number of <code>-1</code> indicates that the calling
* method is attempting to determine the IP address of the specified
* host name.
* <p>
* The <code>checkConnect</code> method for class
* <code>SecurityManager</code> always throws a
* <code>SecurityException</code>.
*
* @param host the host name port to connect to.
* @param port the protocol port to connect to.
* @param context a system-dependent security context.
* @exception SecurityException if the specified security context does
* not have permission to open a socket connection to the
* specified <code>host</code> and <code>port</code>.
* @see java.lang.SecurityManager#getSecurityContext()
* @since JDK1.0
*/
public void checkConnect(String host, int port, Object context) {
throw new SecurityException();
}
/**
* Throws a <code>SecurityException</code> if the
* calling thread is not allowed to wait for a connection request on
* the specified local port number.
* <p>
* The <code>checkListen</code> method for class
* <code>SecurityManager</code> always throws a
* <code>SecurityException</code>.
*
* @param port the local port.
* @exception SecurityException if the caller does not have permission
* to listen on the specified port.
* @since JDK1.0
*/
public void checkListen(int port) {
throw new SecurityException();
}
/**
* Throws a <code>SecurityException</code> if the
* calling thread is not permitted to accept a socket connection from
* the specified host and port number.
* <p>
* This method is invoked for the current security manager by the
* <code>accept</code> method of class <code>ServerSocket</code>.
* <p>
* The <code>checkAccept</code> method for class
* <code>SecurityManager</code> always throws a
* <code>SecurityException</code>.
*
* @param host the host name of the socket connection.
* @param port the port number of the socket connection.
* @exception SecurityException if the caller does not have permission
* to accept the connection.
* @see java.lang.System#getSecurityManager()
* @see java.net.ServerSocket#accept()
* @since JDK1.0
*/
public void checkAccept(String host, int port) {
throw new SecurityException();
}
/**
* Tests if current execution context is allowed to use
* (join/leave/send/receive) IP multicast.
*
* @param multicast Internet group address to be used.
* @exception SecurityException if a security error has occurred.
* @since JDK1.1
*/
public void checkMulticast(InetAddress maddr) {
throw new SecurityException();
}
/**
* Tests to see if current execution context is allowed to use
* (join/leave/send/receive) IP multicast.
*
* @param multicast Internet group address to be used.
* @param ttl value in use, if it is multicast send.
* @exception SecurityException if a security error has occurred.
* @since JDK1.1
*/
public void checkMulticast(InetAddress maddr, byte ttl) {
throw new SecurityException();
}
/**
* Throws a <code>SecurityException</code> if the
* calling thread is not allowed to access or modify the system
* properties.
* <p>
* This method is used by the <code>getProperties</code> and
* <code>setProperties</code> methods of class <code>System</code>.
* <p>
* The <code>checkPropertiesAccess</code> method for class
* <code>SecurityManager</code> always throws a
* <code>SecurityException</code>.
*
* @exception SecurityException if the caller does not have permission
* to access or modify the system properties.
* @see java.lang.System#getProperties()
* @see java.lang.System#setProperties(java.util.Properties)
* @since JDK1.0
*/
public void checkPropertiesAccess() {
throw new SecurityException();
}
/**
* Throws a <code>SecurityException</code> if the
* calling thread is not allowed to access the system property with
* the specified <code>key</code> name.
* <p>
* This method is used by the <code>getProperty</code> method of
* class <code>System</code>.
* <p>
* The <code>checkPropertiesAccess</code> method for class
* <code>SecurityManager</code> always throws a
* <code>SecurityException</code>.
*
* @param key a system property key.
* @exception SecurityException if the caller does not have permission
* to access the specified system property.
* @see java.lang.System#getProperty(java.lang.String)
* @since JDK1.0
*/
public void checkPropertyAccess(String key) {
throw new SecurityException();
}
/**
* Returns <code>false</code> if the calling
* thread is not trusted to bring up the top-level window indicated
* by the <code>window</code> argument. In this case, the caller can
* still decide to show the window, but the window should include
* some sort of visual warning. If the method returns
* <code>true</code>, then the window can be shown without any
* special restrictions.
* <p>
* See class <code>Window</code> for more information on trusted and
* untrusted windows.
* <p>
* The <code>checkSetFactory</code> method for class
* <code>SecurityManager</code> always returns <code>false</code>.
*
* @param window the new window that is being created.
* @return <code>true</code> if the caller is trusted to put up
* top-level windows; <code>false</code> otherwise.
* @exception SecurityException if creation is disallowed entirely.
* @see java.awt.Window
* @since JDK1.0
*/
public boolean checkTopLevelWindow(Object window) {
return false;
}
/**
* Tests if a client can initiate a print job request.
*
* @since JDK1.1
*/
public void checkPrintJobAccess() {
throw new SecurityException();
}
/**
* Tests if a client can get access to the system clipboard.
*
* @since JDK1.1
*/
public void checkSystemClipboardAccess() {
throw new SecurityException();
}
/**
* Tests if a client can get access to the AWT event queue.
*
* @since JDK1.1
*/
public void checkAwtEventQueueAccess() {
throw new SecurityException();
}
/**
* Throws a <code>SecurityException</code> if the
* calling thread is not allowed to access the package specified by
* the argument.
* <p>
* This method is used by the <code>loadClass</code> method of class
* loaders.
* <p>
* The <code>checkPackageAccess</code> method for class
* <code>SecurityManager</code> always throws a
* <code>SecurityException</code>.
*
* @param pkg the package name.
* @exception SecurityException if the caller does not have permission
* to access the specified package.
* @see java.lang.ClassLoader#loadClass(java.lang.String, boolean)
* @since JDK1.0
*/
public void checkPackageAccess(String pkg) {
throw new SecurityException();
}
/**
* Throws a <code>SecurityException</code> if the
* calling thread is not allowed to define classes in the package
* specified by the argument.
* <p>
* This method is used by the <code>loadClass</code> method of some
* class loaders.
* <p>
* The <code>checkPackageDefinition</code> method for class
* <code>SecurityManager</code> always throws a
* <code>SecurityException</code>.
*
* @param pkg the package name.
* @exception SecurityException if the caller does not have permission
* to define classes in the specified package.
* @see java.lang.ClassLoader#loadClass(java.lang.String, boolean)
* @since JDK1.0
*/
public void checkPackageDefinition(String pkg) {
throw new SecurityException();
}
/**
* Throws a <code>SecurityException</code> if the
* calling thread is not allowed to set the socket factory used by
* <code>ServerSocket</code> or <code>Socket</code>, or the stream
* handler factory used by <code>URL</code>.
* <p>
* The <code>checkSetFactory</code> method for class
* <code>SecurityManager</code> always throws a
* <code>SecurityException</code>.
*
* @exception SecurityException if the caller does not have permission
* to specify a socket factory or a stream handler factory.
* @see java.net.ServerSocket#setSocketFactory(
* java.net.SocketImplFactory)
* @see java.net.Socket#setSocketImplFactory(
* java.net.SocketImplFactory)
* @see java.net.URL#setURLStreamHandlerFactory(
* java.net.URLStreamHandlerFactory)
* @since JDK1.0
*/
public void checkSetFactory() {
throw new SecurityException();
}
/**
* Tests if a client is allowed to access members. If access is
* denied, throw a SecurityException.
* The default policy is to deny all accesses.
*
* @since JDK1.1
*/
public void checkMemberAccess(Class clazz, int which) {
throw new SecurityException();
}
/**
* Tests access to certain operations for a security API
* action.
*
* @since JDK1.1
*/
public void checkSecurityAccess(String action) {
throw new SecurityException();
}
private native Class currentLoadedClass0();
/**
* Returns the thread group into which to instantiate any new
* thread being created at the time this is being called.
* By default, it returns the thread group of the current
* thread. This should be overriden by specific security
* manager to return the appropriate thread group.
*
* @since JDK1.1
*/
public ThreadGroup getThreadGroup() {
return Thread.currentThread().getThreadGroup();
}
}
class NullSecurityManager extends SecurityManager {
public void checkCreateClassLoader() { }
public void checkAccess(Thread g) { }
public void checkAccess(ThreadGroup g) { }
public void checkExit(int status) { }
public void checkExec(String cmd) { }
public void checkLink(String lib) { }
public void checkRead(FileDescriptor fd) { }
public void checkRead(String file) { }
public void checkRead(String file, Object context) { }
public void checkWrite(FileDescriptor fd) { }
public void checkWrite(String file) { }
public void checkDelete(String file) { }
public void checkConnect(String host, int port) { }
public void checkConnect(String host, int port, Object context) { }
public void checkListen(int port) { }
public void checkAccept(String host, int port) { }
public void checkMulticast(InetAddress maddr) { }
public void checkMulticast(InetAddress maddr, byte ttl) { }
public void checkPropertiesAccess() { }
public void checkPropertyAccess(String key) { }
public void checkPropertyAccess(String key, String def) { }
public boolean checkTopLevelWindow(Object window) { return true; }
public void checkPrintJobAccess() { }
public void checkSystemClipboardAccess() { }
public void checkAwtEventQueueAccess() { }
public void checkPackageAccess(String pkg) { }
public void checkPackageDefinition(String pkg) { }
public void checkSetFactory() { }
public void checkMemberAccess(Class clazz, int which) { }
public void checkSecurityAccess(String provider) { }
}

View file

@ -0,0 +1,381 @@
/*
* @(#)SystemColor.java 1.5 97/01/27
*
* Copyright (c) 1995, 1996 Sun Microsystems, Inc. All Rights Reserved.
*
* This software is the confidential and proprietary information of Sun
* Microsystems, Inc. ("Confidential Information"). You shall not
* disclose such Confidential Information and shall use it only in
* accordance with the terms of the license agreement you entered into
* with Sun.
*
* SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE
* SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
* IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
* PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR ANY DAMAGES
* SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING
* THIS SOFTWARE OR ITS DERIVATIVES.
*
* CopyrightVersion 1.1_beta
*
*/
package java.awt;
/**
* A class to encapsulate symbolic colors representing the color
* of GUI objects on a system. For systems which support the dynamic
* update of the system colors (when the user changes the colors)
* the actual RGB values of these symbolic colors will also change
* dynamically. In order to compare the "current" RGB value of a SystemColor
* object with a non-symbolic Color object, getRGB() should be used
* rather than equals().
*
* @version 1.5, 27 Jan 1997
* @author Carl Quinn
* @author Amy Fowler
*/
public final class SystemColor extends Color implements java.io.Serializable {
/**
* The array index for the desktop background color.
*/
public final static int DESKTOP = 0;
/**
* The array index for the active caption background color.
*/
public final static int ACTIVE_CAPTION = 1;
/**
* The array index for the action caption text color.
*/
public final static int ACTIVE_CAPTION_TEXT = 2;
/**
* The array index for the active caption border color.
*/
public final static int ACTIVE_CAPTION_BORDER = 3;
/**
* The array index for the inactive caption background color.
*/
public final static int INACTIVE_CAPTION = 4;
/**
* The array index for the inactive caption text color.
*/
public final static int INACTIVE_CAPTION_TEXT = 5;
/**
* The array index for the inactive caption border color.
*/
public final static int INACTIVE_CAPTION_BORDER = 6;
/**
* The array index for the window background color.
*/
public final static int WINDOW = 7;
/**
* The array index for the window border color.
*/
public final static int WINDOW_BORDER = 8;
/**
* The array index for the window text color.
*/
public final static int WINDOW_TEXT = 9;
/**
* The array index for the menu background color.
*/
public final static int MENU = 10;
/**
* The array index for the menu text color.
*/
public final static int MENU_TEXT = 11;
/**
* The array index for the text background color.
*/
public final static int TEXT = 12;
/**
* The array index for the text text color.
*/
public final static int TEXT_TEXT = 13;
/**
* The array index for the text highlight color.
*/
public final static int TEXT_HIGHLIGHT = 14;
/**
* The array index for the text highlight text color.
*/
public final static int TEXT_HIGHLIGHT_TEXT = 15;
/**
* The array index for the text inactive text color.
*/
public final static int TEXT_INACTIVE_TEXT = 16;
/**
* The array index for the control background color.
*/
public final static int CONTROL = 17;
/**
* The array index for the control text color.
*/
public final static int CONTROL_TEXT = 18;
/**
* The array index for the control highlight color.
*/
public final static int CONTROL_HIGHLIGHT = 19;
/**
* The array index for the control light highlight color.
*/
public final static int CONTROL_LT_HIGHLIGHT = 20;
/**
* The array index for the control shadow color.
*/
public final static int CONTROL_SHADOW = 21;
/**
* The array index for the control dark shadow color.
*/
public final static int CONTROL_DK_SHADOW = 22;
/**
* The array index for the scrollbar background color.
*/
public final static int SCROLLBAR = 23;
/**
* The array index for the info background color.
*/
public final static int INFO = 24;
/**
* The array index for the info text color.
*/
public final static int INFO_TEXT = 25;
/**
* The number of system colors in the array.
*/
public final static int NUM_COLORS = 26;
/**
* The color of the desktop background.
*/
public final static SystemColor desktop = new SystemColor((byte)DESKTOP);
/**
* The background color for captions in window borders.
*/
public final static SystemColor activeCaption = new SystemColor((byte)ACTIVE_CAPTION);
/**
* The text color for captions in window borders.
*/
public final static SystemColor activeCaptionText = new SystemColor((byte)ACTIVE_CAPTION_TEXT);
/**
* The border color for captions in window borders.
*/
public final static SystemColor activeCaptionBorder = new SystemColor((byte)ACTIVE_CAPTION_BORDER);
/**
* The background color for inactive captions in window borders.
*/
public final static SystemColor inactiveCaption = new SystemColor((byte)INACTIVE_CAPTION);
/**
* The text color for inactive captions in window borders.
*/
public final static SystemColor inactiveCaptionText = new SystemColor((byte)INACTIVE_CAPTION_TEXT);
/**
* The border color for inactive captios in window borders.
*/
public final static SystemColor inactiveCaptionBorder = new SystemColor((byte)INACTIVE_CAPTION_BORDER);
/**
* The background color for windows.
*/
public final static SystemColor window = new SystemColor((byte)WINDOW);
/**
* The border color for windows.
*/
public final static SystemColor windowBorder = new SystemColor((byte)WINDOW_BORDER);
/**
* The text color for windows.
*/
public final static SystemColor windowText = new SystemColor((byte)WINDOW_TEXT);
/**
* The background color for menus.
*/
public final static SystemColor menu = new SystemColor((byte)MENU);
/**
* The text color for menus.
*/
public final static SystemColor menuText = new SystemColor((byte)MENU_TEXT);
/**
* The background color for text components.
*/
public final static SystemColor text = new SystemColor((byte)TEXT);
/**
* The text color for text components.
*/
public final static SystemColor textText = new SystemColor((byte)TEXT_TEXT);
/**
* The background color for highlighted text.
*/
public final static SystemColor textHighlight = new SystemColor((byte)TEXT_HIGHLIGHT);
/**
* The text color for highlighted text.
*/
public final static SystemColor textHighlightText = new SystemColor((byte)TEXT_HIGHLIGHT_TEXT);
/**
* The text color for inactive text.
*/
public final static SystemColor textInactiveText = new SystemColor((byte)TEXT_INACTIVE_TEXT);
/**
* The background color for control objects.
*/
public final static SystemColor control = new SystemColor((byte)CONTROL);
/**
* The text color for control objects.
*/
public final static SystemColor controlText = new SystemColor((byte)CONTROL_TEXT);
/**
* The light highlight color for control objects.
*/
public final static SystemColor controlHighlight = new SystemColor((byte)CONTROL_HIGHLIGHT);
/**
* The regular highlight color for control objects.
*/
public final static SystemColor controlLtHighlight = new SystemColor((byte)CONTROL_LT_HIGHLIGHT);
/**
* The regular shadow color for control objects.
*/
public final static SystemColor controlShadow = new SystemColor((byte)CONTROL_SHADOW);
/**
* The dark shadow color for control objects.
*/
public final static SystemColor controlDkShadow = new SystemColor((byte)CONTROL_DK_SHADOW);
/**
* The background color for scrollbars.
*/
public final static SystemColor scrollbar = new SystemColor((byte)SCROLLBAR);
/**
* The background color for info(help) text.
*/
public final static SystemColor info = new SystemColor((byte)INFO);
/**
* The text color for info(help) text.
*/
public final static SystemColor infoText = new SystemColor((byte)INFO_TEXT);
/*
* System colors with default initial values, overwritten by toolkit if
* system values differ and are available.
*/
private static int[] systemColors = {
0xFF005C5C, // desktop = new Color(0,92,92);
0xFF000080, // activeCaption = new Color(0,0,128);
0xFFFFFFFF, // activeCaptionText = Color.white;
0xFFC0C0C0, // activeCaptionBorder = Color.lightGray;
0xFF808080, // inactiveCaption = Color.gray;
0xFFC0C0C0, // inactiveCaptionText = Color.lightGray;
0xFFC0C0C0, // inactiveCaptionBorder = Color.lightGray;
0xFFFFFFFF, // window = Color.white;
0xFF000000, // windowBorder = Color.black;
0xFF000000, // windowText = Color.black;
0xFFC0C0C0, // menu = Color.lightGray;
0xFF000000, // menuText = Color.black;
0xFFC0C0C0, // text = Color.lightGray;
0xFF000000, // textText = Color.black;
0xFF000080, // textHighlight = new Color(0,0,128);
0xFFFFFFFF, // textHighlightText = Color.white;
0xFF808080, // textInactiveText = Color.gray;
0xFFC0C0C0, // control = Color.lightGray;
0xFF000000, // controlText = Color.black;
0xFFFFFFFF, // controlHighlight = Color.white;
0xFFE0E0E0, // controlLtHighlight = new Color(224,224,224);
0xFF808080, // controlShadow = Color.gray;
0xFF000000, // controlDkShadow = Color.black;
0xFFE0E0E0, // scrollbar = new Color(224,224,224);
0xFFE0E000, // info = new Color(224,224,0);
0xFF000000, // infoText = Color.black;
};
/*
* JDK 1.1 serialVersionUID
*/
private static final long serialVersionUID = 4503142729533789064L;
static {
updateSystemColors();
}
/**
* called from <init> & toolkit to update the above systemColors cache
*/
private static void updateSystemColors() {
Toolkit.getDefaultToolkit().loadSystemColors(systemColors);
}
/**
* Create a symbolic color that represents an indexed entry into system
* color cache. Used by above static system colors.
*/
private SystemColor(byte index) {
super(0, 0, 0);
value = index;
}
/**
* Gets the "current" RGB value representing the symbolic color.
* (Bits 24-31 are 0xff, 16-23 are red, 8-15 are green, 0-7 are blue).
* @see java.awt.image.ColorModel#getRGBdefault
* @see #getRed
* @see #getGreen
* @see #getBlue
*/
public int getRGB() {
return systemColors[value];
}
/**
* Returns the String representation of this Color's values.
*/
public String toString() {
return getClass().getName() + "[i=" + (value) + "]";
}
}

840
test/etags/java-src/TG.java Normal file
View file

@ -0,0 +1,840 @@
/*
* @(#)ThreadGroup.java 1.31 97/01/20
*
* Copyright (c) 1995, 1996 Sun Microsystems, Inc. All Rights Reserved.
*
* This software is the confidential and proprietary information of Sun
* Microsystems, Inc. ("Confidential Information"). You shall not
* disclose such Confidential Information and shall use it only in
* accordance with the terms of the license agreement you entered into
* with Sun.
*
* SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE
* SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
* IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
* PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR ANY DAMAGES
* SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING
* THIS SOFTWARE OR ITS DERIVATIVES.
*
* CopyrightVersion 1.1_beta
*
*/
package java.lang;
import java.io.PrintStream;
import sun.misc.VM;
/**
* A thread group represents a set of threads. In addition, a thread
* group can also include other thread groups. The thread groups form
* a tree in which every thread group except the initial thread group
* has a parent.
* <p>
* A thread is allowed to access information about its own thread
* group, but not to access information about its thread group's
* parent thread group or any other thread groups.
*
* @author unascribed
* @version 1.31, 20 Jan 1997
* @since JDK1.0
*/
/* The locking strategy for this code is to try to lock only one level of the
* tree wherever possible, but otherwise to lock from the bottom up.
* That is, from child thread groups to parents.
* This has the advantage of limiting the number of locks that need to be held
* and in particular avoids having to grab the lock for the root thread group,
* (or a global lock) which would be a source of contention on a
* multi-processor system with many thread groups.
* This policy often leads to taking a snapshot of the state of a thread group
* and working off of that snapshot, rather than holding the thread group locked
* while we work on the children.
*/
public
class ThreadGroup {
ThreadGroup parent;
String name;
int maxPriority;
boolean destroyed;
boolean daemon;
boolean vmAllowSuspension;
int nthreads;
Thread threads[];
int ngroups;
ThreadGroup groups[];
/**
* Creates an empty Thread group that is not in any Thread group.
* This method is used to create the system Thread group.
*/
private ThreadGroup() { // called from C code
this.name = "system";
this.maxPriority = Thread.MAX_PRIORITY;
}
/**
* Constructs a new thread group. The parent of this new group is
* the thread group of the currently running thread.
*
* @param name the name of the new thread group.
* @since JDK1.0
*/
public ThreadGroup(String name) {
this(Thread.currentThread().getThreadGroup(), name);
}
/**
* Creates a new thread group. The parent of this new group is the
* specified thread group.
* <p>
* The <code>checkAccess</code> method of the parent thread group is
* called with no arguments; this may result in a security exception.
*
* @param parent the parent thread group.
* @param name the name of the new thread group.
* @exception NullPointerException if the thread group argument is
* <code>null</code>.
* @exception SecurityException if the current thread cannot create a
* thread in the specified thread group.
* @see java.lang.SecurityException
* @see java.lang.ThreadGroup#checkAccess()
* @since JDK1.0
*/
public ThreadGroup(ThreadGroup parent, String name) {
if (parent == null) {
throw new NullPointerException();
}
parent.checkAccess();
this.name = name;
this.maxPriority = parent.maxPriority;
this.daemon = parent.daemon;
this.vmAllowSuspension = parent.vmAllowSuspension;
this.parent = parent;
parent.add(this);
}
/**
* Returns the name of this thread group.
*
* @return the name of this thread group.
* @since JDK1.0
*/
public final String getName() {
return name;
}
/**
* Returns the parent of this thread group.
*
* @return the parent of this thread group. The top-level thread group
* is the only thread group whose parent is <code>null</code>.
* @since JDK1.0
*/
public final ThreadGroup getParent() {
return parent;
}
/**
* Returns the maximum priority of this thread group. Threads that are
* part of this group cannot have a higher priority than the maximum
* priority.
*
* @return the maximum priority that a thread in this thread group
* can have.
* @since JDK1.0
*/
public final int getMaxPriority() {
return maxPriority;
}
/**
* Tests if this thread group is a daemon thread group. A
* daemon thread group is automatically destroyed when its last
* thread is stopped or its last thread group is destroyed.
*
* @return <code>true</code> if this thread group is a daemon thread group;
* <code>false</code> otherwise.
* @since JDK1.0
*/
public final boolean isDaemon() {
return daemon;
}
/**
* Tests if this thread group has not been destroyed.
*
* @since JDK1.1
*/
public synchronized boolean isDestroyed() {
return destroyed;
}
/**
* Changes the daemon status of this thread group.
* <p>
* First, the <code>checkAccess</code> method of this thread group is
* called with no arguments; this may result in a security exception.
* <p>
* A daemon thread group is automatically destroyed when its last
* thread is stopped or its last thread group is destroyed.
*
* @param daemon if <code>true</code>, marks this thread group as
* a daemon thread group; otherwise, marks this
* thread group as normal.
* @exception SecurityException if the current thread cannot modify
* this thread.
* @see java.lang.SecurityException
* @see java.lang.ThreadGroup#checkAccess()
* @since JDK1.0
*/
public final void setDaemon(boolean daemon) {
checkAccess();
this.daemon = daemon;
}
/**
* Sets the maximum priority of the group.
* <p>
* First, the <code>checkAccess</code> method of this thread group is
* called with no arguments; this may result in a security exception.
* <p>
* Threads in the thread group that already have a higher priority
* are not affected.
*
* @param pri the new priority of the thread group.
* @exception SecurityException if the current thread cannot modify
* this thread group.
* @see java.lang.SecurityException
* @see java.lang.ThreadGroup#checkAccess()
* @since JDK1.0
*/
public final void setMaxPriority(int pri) {
int ngroupsSnapshot;
ThreadGroup[] groupsSnapshot;
synchronized (this) {
checkAccess();
if (pri < Thread.MIN_PRIORITY) {
maxPriority = Thread.MIN_PRIORITY;
} else if (pri < maxPriority) {
maxPriority = pri;
}
ngroupsSnapshot = ngroups;
if (groups != null) {
groupsSnapshot = new ThreadGroup[ngroupsSnapshot];
System.arraycopy(groups, 0, groupsSnapshot, 0, ngroupsSnapshot);
} else {
groupsSnapshot = null;
}
}
for (int i = 0 ; i < ngroupsSnapshot ; i++) {
groupsSnapshot[i].setMaxPriority(pri);
}
}
/**
* Tests if this thread group is either the thread group
* argument or one of its ancestor thread groups.
*
* @param g a thread group.
* @return <code>true</code> if this thread group is the thread group
* argument or one of its ancestor thread groups;
* <code>false</code> otherwise.
* @since JDK1.0
*/
public final boolean parentOf(ThreadGroup g) {
for (; g != null ; g = g.parent) {
if (g == this) {
return true;
}
}
return false;
}
/**
* Determines if the currently running thread has permission to
* modify this thread group.
* <p>
* If there is a security manager, its <code>checkAccess</code> method
* is called with this thread group as its argument. This may result
* in throwing a <code>SecurityException</code>.
*
* @exception SecurityException if the current thread is not allowed to
* access this thread group.
* @see java.lang.SecurityManager#checkAccess(java.lang.ThreadGroup)
* @since JDK1.0
*/
public final void checkAccess() {
SecurityManager security = System.getSecurityManager();
if (security != null) {
security.checkAccess(this);
}
}
/**
* Returns an estimate of the number of active threads in this
* thread group.
*
* @return the number of active threads in this thread group and in any
* other thread group that has this thread group as an ancestor.
* @since JDK1.0
*/
public int activeCount() {
int result;
// Snapshot sub-group data so we don't hold this lock
// while our children are computing.
int ngroupsSnapshot;
ThreadGroup[] groupsSnapshot;
synchronized (this) {
if (destroyed) {
return 0;
}
result = nthreads;
ngroupsSnapshot = ngroups;
if (groups != null) {
groupsSnapshot = new ThreadGroup[ngroupsSnapshot];
System.arraycopy(groups, 0, groupsSnapshot, 0, ngroupsSnapshot);
} else {
groupsSnapshot = null;
}
}
for (int i = 0 ; i < ngroupsSnapshot ; i++) {
result += groupsSnapshot[i].activeCount();
}
return result;
}
/**
* Copies into the specified array every active thread in this
* thread group and its subgroups.
* <p>
* An application should use the <code>activeCount</code> method to
* get an estimate of how big the array should be. If the array is
* too short to hold all the threads, the extra threads are silently
* ignored.
*
* @param list an array into which to place the list of threads.
* @return the number of threads put into the array.
* @see java.lang.ThreadGroup#activeCount()
* @since JDK1.0
*/
public int enumerate(Thread list[]) {
return enumerate(list, 0, true);
}
/**
* Copies into the specified array every active thread in this
* thread group. If the <code>recurse</code> flag is
* <code>true</code>, references to every active thread in this
* thread's subgroups are also included. If the array is too short to
* hold all the threads, the extra threads are silently ignored.
* <p>
* An application should use the <code>activeCount</code> method to
* get an estimate of how big the array should be.
*
* @param list an array into which to place the list of threads.
* @param recurse a flag indicating whether also to include threads
* in thread groups that are subgroups of this
* thread group.
* @return the number of threads placed into the array.
* @see java.lang.ThreadGroup#activeCount()
* @since JDK1.0
*/
public int enumerate(Thread list[], boolean recurse) {
return enumerate(list, 0, recurse);
}
private int enumerate(Thread list[], int n, boolean recurse) {
int ngroupsSnapshot = 0;
ThreadGroup[] groupsSnapshot = null;
synchronized (this) {
if (destroyed) {
return 0;
}
int nt = nthreads;
if (nt > list.length - n) {
nt = list.length - n;
}
if (nt > 0) {
System.arraycopy(threads, 0, list, n, nt);
n += nt;
}
if (recurse) {
ngroupsSnapshot = ngroups;
if (groups != null) {
groupsSnapshot = new ThreadGroup[ngroupsSnapshot];
System.arraycopy(groups, 0, groupsSnapshot, 0, ngroupsSnapshot);
} else {
groupsSnapshot = null;
}
}
}
if (recurse) {
for (int i = 0 ; i < ngroupsSnapshot ; i++) {
n = groupsSnapshot[i].enumerate(list, n, true);
}
}
return n;
}
/**
* Returns an estimate of the number of active groups in this
* thread group.
*
* @return the number of active thread groups with this thread group as
* an ancestor.
* @since JDK1.0
*/
public int activeGroupCount() {
int ngroupsSnapshot;
ThreadGroup[] groupsSnapshot;
synchronized (this) {
if (destroyed) {
return 0;
}
ngroupsSnapshot = ngroups;
if (groups != null) {
groupsSnapshot = new ThreadGroup[ngroupsSnapshot];
System.arraycopy(groups, 0, groupsSnapshot, 0, ngroupsSnapshot);
} else {
groupsSnapshot = null;
}
}
int n = ngroupsSnapshot;
for (int i = 0 ; i < ngroupsSnapshot ; i++) {
n += groupsSnapshot[i].activeGroupCount();
}
return n;
}
/**
* Copies into the specified array references to every active
* subgroup in this thread group.
* <p>
* An application should use the <code>activeGroupCount</code>
* method to get an estimate of how big the array should be. If the
* array is too short to hold all the thread groups, the extra thread
* groups are silently ignored.
*
* @param list an array into which to place the list of thread groups.
* @return the number of thread groups put into the array.
* @see java.lang.ThreadGroup#activeGroupCount()
* @since JDK1.0
*/
public int enumerate(ThreadGroup list[]) {
return enumerate(list, 0, true);
}
/**
* Copies into the specified array references to every active
* subgroup in this thread group. If the <code>recurse</code> flag is
* <code>true</code>, references to all active subgroups of the
* subgroups and so forth are also included.
* <p>
* An application should use the <code>activeGroupCount</code>
* method to get an estimate of how big the array should be.
*
* @param list an array into which to place the list of threads.
* @param recurse a flag indicating whether to recursively enumerate
* all included thread groups.
* @return the number of thread groups put into the array.
* @see java.lang.ThreadGroup#activeGroupCount()
* @since JDK1.0
*/
public int enumerate(ThreadGroup list[], boolean recurse) {
return enumerate(list, 0, recurse);
}
private int enumerate(ThreadGroup list[], int n, boolean recurse) {
int ngroupsSnapshot = 0;
ThreadGroup[] groupsSnapshot = null;
synchronized (this) {
if (destroyed) {
return 0;
}
int ng = ngroups;
if (ng > list.length - n) {
ng = list.length - n;
}
if (ng > 0) {
System.arraycopy(groups, 0, list, n, ng);
n += ng;
}
if (recurse) {
ngroupsSnapshot = ngroups;
if (groups != null) {
groupsSnapshot = new ThreadGroup[ngroupsSnapshot];
System.arraycopy(groups, 0, groupsSnapshot, 0, ngroupsSnapshot);
} else {
groupsSnapshot = null;
}
}
}
if (recurse) {
for (int i = 0 ; i < ngroupsSnapshot ; i++) {
n = groupsSnapshot[i].enumerate(list, n, true);
}
}
return n;
}
/**
* Stops all processes in this thread group.
* <p>
* First, the <code>checkAccess</code> method of this thread group is
* called with no arguments; this may result in a security exception.
* <p>
* This method then calls the <code>stop</code> method on all the
* threads in this thread group and in all of its subgroups.
*
* @exception SecurityException if the current thread is not allowed
* to access this thread group or any of the threads in
* the thread group.
* @see java.lang.SecurityException
* @see java.lang.Thread#stop()
* @see java.lang.ThreadGroup#checkAccess()
* @since JDK1.0
*/
public final void stop() {
int ngroupsSnapshot;
ThreadGroup[] groupsSnapshot;
synchronized (this) {
checkAccess();
for (int i = 0 ; i < nthreads ; i++) {
threads[i].stop();
}
ngroupsSnapshot = ngroups;
if (groups != null) {
groupsSnapshot = new ThreadGroup[ngroupsSnapshot];
System.arraycopy(groups, 0, groupsSnapshot, 0, ngroupsSnapshot);
} else {
groupsSnapshot = null;
}
}
for (int i = 0 ; i < ngroupsSnapshot ; i++) {
groupsSnapshot[i].stop();
}
}
/**
* Suspends all processes in this thread group.
* <p>
* First, the <code>checkAccess</code> method of this thread group is
* called with no arguments; this may result in a security exception.
* <p>
* This method then calls the <code>suspend</code> method on all the
* threads in this thread group and in all of its subgroups.
*
* @exception SecurityException if the current thread is not allowed
* to access this thread group or any of the threads in
* the thread group.
* @see java.lang.SecurityException
* @see java.lang.Thread#suspend()
* @see java.lang.ThreadGroup#checkAccess()
* @since JDK1.0
*/
public final void suspend() {
int ngroupsSnapshot;
ThreadGroup[] groupsSnapshot;
synchronized (this) {
checkAccess();
for (int i = 0 ; i < nthreads ; i++) {
threads[i].suspend();
}
ngroupsSnapshot = ngroups;
if (groups != null) {
groupsSnapshot = new ThreadGroup[ngroupsSnapshot];
System.arraycopy(groups, 0, groupsSnapshot, 0, ngroupsSnapshot);
} else {
groupsSnapshot = null;
}
}
for (int i = 0 ; i < ngroupsSnapshot ; i++) {
groupsSnapshot[i].suspend();
}
}
/**
* Resumes all processes in this thread group.
* <p>
* First, the <code>checkAccess</code> method of this thread group is
* called with no arguments; this may result in a security exception.
* <p>
* This method then calls the <code>resume</code> method on all the
* threads in this thread group and in all of its sub groups.
*
* @exception SecurityException if the current thread is not allowed to
* access this thread group or any of the threads in the
* thread group.
* @see java.lang.SecurityException
* @see java.lang.Thread#resume()
* @see java.lang.ThreadGroup#checkAccess()
* @since JDK1.0
*/
public final void resume() {
int ngroupsSnapshot;
ThreadGroup[] groupsSnapshot;
synchronized (this) {
checkAccess();
for (int i = 0 ; i < nthreads ; i++) {
threads[i].resume();
}
ngroupsSnapshot = ngroups;
if (groups != null) {
groupsSnapshot = new ThreadGroup[ngroupsSnapshot];
System.arraycopy(groups, 0, groupsSnapshot, 0, ngroupsSnapshot);
} else {
groupsSnapshot = null;
}
}
for (int i = 0 ; i < ngroupsSnapshot ; i++) {
groupsSnapshot[i].resume();
}
}
/**
* Destroys this thread group and all of its subgroups. This thread
* group must be empty, indicating that all threads that had been in
* this thread group have since stopped.
*
* @exception IllegalThreadStateException if the thread group is not
* empty or if the thread group has already been destroyed.
* @exception SecurityException if the current thread cannot modify this
* thread group.
* @since JDK1.0
*/
public final void destroy() {
int ngroupsSnapshot;
ThreadGroup[] groupsSnapshot;
synchronized (this) {
checkAccess();
if (destroyed || (nthreads > 0)) {
throw new IllegalThreadStateException();
}
ngroupsSnapshot = ngroups;
if (groups != null) {
groupsSnapshot = new ThreadGroup[ngroupsSnapshot];
System.arraycopy(groups, 0, groupsSnapshot, 0, ngroupsSnapshot);
} else {
groupsSnapshot = null;
}
if (parent != null) {
destroyed = true;
ngroups = 0;
groups = null;
nthreads = 0;
threads = null;
}
}
for (int i = 0 ; i < ngroupsSnapshot ; i += 1) {
groupsSnapshot[i].destroy();
}
if (parent != null) {
parent.remove(this);
}
}
/**
* Adds the specified Thread group to this group.
* @param g the specified Thread group to be added
* @exception IllegalThreadStateException If the Thread group has been destroyed.
*/
private final void add(ThreadGroup g){
synchronized (this) {
if (destroyed) {
throw new IllegalThreadStateException();
}
if (groups == null) {
groups = new ThreadGroup[4];
} else if (ngroups == groups.length) {
ThreadGroup newgroups[] = new ThreadGroup[ngroups * 2];
System.arraycopy(groups, 0, newgroups, 0, ngroups);
groups = newgroups;
}
groups[ngroups] = g;
// This is done last so it doesn't matter in case the
// thread is killed
ngroups++;
}
}
/**
* Removes the specified Thread group from this group.
* @param g the Thread group to be removed
* @return if this Thread has already been destroyed.
*/
private void remove(ThreadGroup g) {
synchronized (this) {
if (destroyed) {
return;
}
for (int i = 0 ; i < ngroups ; i++) {
if (groups[i] == g) {
ngroups -= 1;
System.arraycopy(groups, i + 1, groups, i, ngroups - i);
// Zap dangling reference to the dead group so that
// the garbage collector will collect it.
groups[ngroups] = null;
break;
}
}
if (nthreads == 0) {
notifyAll();
}
if (daemon && (nthreads == 0) && (ngroups == 0)) {
destroy();
}
}
}
/**
* Adds the specified Thread to this group.
* @param t the Thread to be added
* @exception IllegalThreadStateException If the Thread group has been destroyed.
*/
void add(Thread t) {
synchronized (this) {
if (destroyed) {
throw new IllegalThreadStateException();
}
if (threads == null) {
threads = new Thread[4];
} else if (nthreads == threads.length) {
Thread newthreads[] = new Thread[nthreads * 2];
System.arraycopy(threads, 0, newthreads, 0, nthreads);
threads = newthreads;
}
threads[nthreads] = t;
// This is done last so it doesn't matter in case the
// thread is killed
nthreads++;
}
}
/**
* Removes the specified Thread from this group.
* @param t the Thread to be removed
* @return if the Thread has already been destroyed.
*/
void remove(Thread t) {
synchronized (this) {
if (destroyed) {
return;
}
for (int i = 0 ; i < nthreads ; i++) {
if (threads[i] == t) {
System.arraycopy(threads, i + 1, threads, i, --nthreads - i);
// Zap dangling reference to the dead thread so that
// the garbage collector will collect it.
threads[nthreads] = null;
break;
}
}
if (nthreads == 0) {
notifyAll();
}
if (daemon && (nthreads == 0) && (ngroups == 0)) {
destroy();
}
}
}
/**
* Prints information about this thread group to the standard
* output. This method is useful only for debugging.
*
* @since JDK1.0
*/
public void list() {
list(System.out, 0);
}
void list(PrintStream out, int indent) {
int ngroupsSnapshot;
ThreadGroup[] groupsSnapshot;
synchronized (this) {
for (int j = 0 ; j < indent ; j++) {
out.print(" ");
}
out.println(this);
indent += 4;
for (int i = 0 ; i < nthreads ; i++) {
for (int j = 0 ; j < indent ; j++) {
out.print(" ");
}
out.println(threads[i]);
}
ngroupsSnapshot = ngroups;
if (groups != null) {
groupsSnapshot = new ThreadGroup[ngroupsSnapshot];
System.arraycopy(groups, 0, groupsSnapshot, 0, ngroupsSnapshot);
} else {
groupsSnapshot = null;
}
}
for (int i = 0 ; i < ngroupsSnapshot ; i++) {
groupsSnapshot[i].list(out, indent);
}
}
/**
* Called by the Java Virtual Machine when a thread in this
* thread group stops because of an uncaught exception.
* <p>
* The <code>uncaughtException</code> method of
* <code>ThreadGroup</code> does the following:
* <ul>
* <li>If this thread group has a parent thread group, the
* <code>uncaughtException</code> method of that parent is called
* with the same two arguments.
* <li>Otherwise, this method determines if the <code>Throwable</code>
* argument is an instance of <code>ThreadDeath</code>. If so, nothing
* special is done. Otherwise, the <code>Throwable</code>'s
* <code>printStackTrace</code> method is called to print a stack
* backtrace to the standard error stream.
* </ul>
* <p>
* Applications can override this method in subclasses of
* <code>ThreadGroup</code> to provide alternative handling of
* uncaught exceptions.
*
* @param t the thread that is about to exit.
* @param e the uncaught exception.
* @see java.lang.System#err
* @see java.lang.ThreadDeath
* @see java.lang.Throwable#printStackTrace(java.io.PrintStream)
* @since JDK1.0
*/
public void uncaughtException(Thread t, Throwable e) {
if (parent != null) {
parent.uncaughtException(t, e);
} else if (!(e instanceof ThreadDeath)) {
e.printStackTrace(System.err);
}
}
/**
* Used by VM to control lowmem implicit suspension.
*
* @since JDK1.1
*/
public boolean allowThreadSuspension(boolean b) {
this.vmAllowSuspension = b;
if (!b) {
VM.unsuspendSomeThreads();
}
return true;
}
/**
* Returns a string representation of this Thread group.
*
* @return a string representation of this thread group.
* @since JDK1.0
*/
public String toString() {
return getClass().getName() + "[name=" + getName() + ",maxpri=" + maxPriority + "]";
}
}

View file

@ -0,0 +1,282 @@
-- ase -- allegro-sprite-editor: the ultimate sprites factory
-- Copyright (C) 2001-2004 by David A. Capello
--
-- Read "LEGAL.txt" for more information.
-- internal routine
local function get_layer_by_name (sprite, layer, name)
if layer.readable == false then
return nil;
end
if layer.name and strcmp (layer.name, name) == 0 then
return layer;
end
if layer_is_set (layer) then
local it, sub;
it = layer.layers;
while it do
sub = get_layer_by_name (sprite, it, name)
if sub then
return sub;
end
it = it.next
end
end
return nil;
end
-- internal routine
local function count_layers (layer)
local count;
if layer.parent.type == GFXOBJ_SPRITE then
count = 0;
else
count = 1;
end
if layer_is_set (layer) then
local it = layer.layers;
while it do
count = count + count_layers (it);
it = it.next;
end
end
return count;
end
-- Layer *GetLayerByName (const char *name);
function GetLayerByName (name)
local sprite = current_sprite;
if sprite and name then
return get_layer_by_name (sprite, sprite.set, name);
else
return nil;
end
end
-- const char *GetUniqueLayerName (void);
function GetUniqueLayerName ()
local sprite = current_sprite;
if sprite then
return _("Layer") .. " " .. count_layers (sprite.set);
else
return nil;
end
end
-- void SelectLayer (Layer *layer);
function SelectLayer (layer)
if current_sprite then
sprite_set_layer (current_sprite, layer);
end
end
-- Layer *NewLayer (const char *name, int x, int y, int w, int h);
-- creates a new layer with the "name" in the current sprite (in the
-- current frame) with the specified position and size (if w=h=0 the
-- routine will use the sprite dimension)
function NewLayer (name, x, y, w, h)
local sprite = current_sprite;
local layer = nil;
local image, frame, index;
if sprite and name then
if not w or w == 0 then w = sprite.w; end
if not h or h == 0 then h = sprite.h; end
-- new image
image = image_new (sprite.imgtype, w, h);
if not image then
return nil;
end
-- new layer
layer = layer_image_new (sprite.imgtype, w, h);
if not layer then
image_free (image);
return nil;
end
-- clear with mask color
image_clear (image, 0);
-- configure layer name and blend mode
layer_set_name (layer, name);
layer_set_blend_mode (layer, BLEND_MODE_NORMAL);
-- add image in the layer stock
index = stock_add_image (layer.stock, image);
-- create frame (XXX in the current frpos? --dacap)
frame = frame_new (sprite.frpos, index, x, y, 255);
-- add frame
layer_add_frame (layer, frame);
-- undo stuff
if undo_is_enabled (sprite.undo) then
undo_open (sprite.undo);
undo_add_layer (sprite.undo, sprite.set, layer);
undo_set_layer (sprite.undo, sprite);
undo_close (sprite.undo);
end
-- add the layer in the sprite set
layer_add_layer (sprite.set, layer);
-- select the new layer
sprite_set_layer (sprite, layer);
end
return layer;
end
-- Layer *NewLayerSet (const char *name);
-- creates a new layer set with the "name" in the current sprite
function NewLayerSet (name)
local sprite = current_sprite;
local layer = nil;
if sprite and name then
-- new layer
layer = layer_set_new ();
if not layer then
return nil;
end
-- configure layer name and blend mode
layer_set_name (layer, name);
-- add the layer in the sprite set
layer_add_layer (sprite.set, layer);
-- select the new layer
sprite_set_layer (sprite, layer);
end
return layer;
end
-- void RemoveLayer (void);
-- removes the current selected layer
function RemoveLayer ()
local sprite = current_sprite;
if sprite and sprite.layer then
local layer = sprite.layer;
local parent = layer.parent;
local layer_select;
-- select: previous layer, or next layer, or parent (if it is not
-- the main layer of sprite set)
if layer.prev then
layer_select = layer.prev;
elseif layer.next then
layer_select = layer.next;
elseif parent != sprite.set then
layer_select = parent;
else
layer_select = nil;
end
-- undo stuff
if undo_is_enabled (sprite.undo) then
undo_open (sprite.undo);
undo_set_layer (sprite.undo, sprite);
undo_remove_layer (sprite.undo, layer);
undo_close (sprite.undo);
end
-- select other layer
sprite_set_layer (sprite, layer_select);
-- remove the layer
layer_remove_layer (parent, layer);
-- destroy the layer
layer_free (layer);
end
end
-- void MoveLayerTop (void);
-- moves the current layer in the top of the main set
function MoveLayerTop ()
if current_sprite and current_sprite.layer then
local layer = current_sprite.layer;
layer_remove_layer (layer.parent, layer);
layer_add_layer (current_sprite.set, layer);
end
end
-- void MoveLayerBottom (void);
-- moves the current layer in the bottom of the main set
function MoveLayerBottom ()
if current_sprite and current_sprite.layer then
local layer = current_sprite.layer;
layer_remove_layer (layer.parent, layer);
layer_add_layer (current_sprite.set, layer);
layer_move_layer (current_sprite.set, layer, nil);
end
end
-- void MoveLayerBefore (Layer *this_one);
-- moves the current layer above the layer "this_one"
function MoveLayerBefore (this_one)
if current_sprite and current_sprite.layer then
local layer = current_sprite.layer;
local layer_dest;
if not this_one then
layer_dest = current_sprite.set;
else
layer_dest = this_one;
end
if layer_dest then
layer_remove_layer (layer.parent, layer);
layer_add_layer (layer_dest.parent, layer);
layer_move_layer (layer_dest.parent, layer, layer_dest);
end
end
end
-- void MoveLayerAfter (Layer *this_one);
-- moves the current layer below the layer "this_one" (if that layer
-- is a set, the layer is put in the top of the layer set)
function MoveLayerAfter (this_one)
if current_sprite and current_sprite.layer then
local layer = current_sprite.layer;
local layer_dest;
if not this_one then
layer_dest = current_sprite.set;
else
layer_dest = this_one;
end
if layer_dest then
layer_remove_layer (layer.parent, layer);
-- insert in the first position of the set
if layer_is_set (layer_dest) then
layer_add_layer (layer_dest, layer);
-- insert below the layer
else
layer_add_layer (layer_dest.parent, layer);
layer_move_layer (layer_dest.parent, layer, layer_dest.prev);
end
end
end
end

View file

@ -0,0 +1,226 @@
LATEST=17
RELEASELIST=pot@gnu.org xemacs-review@xemacs.org jcwren@jcwren.com sxemacs-devel@sxemacs.org
ADASRC=etags-test-for.ada 2ataspri.adb 2ataspri.ads waroquiers.ada
ASRC=empty.zz empty.zz.gz
CSRC=abbrev.c ../etags/h.h .//c.c torture.c getopt.h etags.c\
exit.c exit.strange_suffix sysdep.h tab.c\
emacs/src/gmalloc.c emacs/src/regex.h emacs/src/keyboard.c dostorture.c\
machsyscalls.c machsyscalls.h fail.c a/b/b.c
CPSRC=c.C abstract.C abstract.H cfront.H burton.cpp burton.cpp\
functions.cpp MDiagArray2.h Pctest.h Range.h\
screen.cpp screen.hpp conway.cpp conway.hpp clheir.cpp.gz clheir.hpp.gz fail.C
ELSRC=TAGTEST.EL emacs/lisp/progmodes/etags.el
ERLSRC=gs_dialog.erl lines.erl lists.erl
FORTHSRC=test-forth.fth
FSRC=entry.for entry.strange_suffix entry.strange
HTMLSRC=softwarelibero.html index.shtml algrthms.html software.html
JAVASRC=AWTEMul.java KeyEve.java SMan.java SysCol.java TG.java
LUASRC=allegro.lua
MAKESRC=Makefile
OBJCSRC=Subprocess.h Subprocess.m PackInsp.h PackInsp.m
OBJCPPSRC=SimpleCalc.H SimpleCalc.M
PASSRC=common.pas
PERLSRC=htlmify-cystic yagrip.pl kai-test.pl mirror.pl
PHPSRC=lce_functions.php ptest.php sendmail.php
PSSRC=rfc1245.ps
PROLSRC=ordsets.prolog natded.prolog
PYTSRC=server.py
TEXSRC=testenv.tex gzip.texi texinfo.tex nonewline.tex
YSRC=parse.y parse.c atest.y cccp.c cccp.y
SRCS=Makefile ${ADASRC} ${ASRC} ${CSRC} ${CPSRC} ${ELSRC} ${ERLSRC} ${FSRC}\
${FORTHSRC} ${HTMLSRC} ${JAVASRC} ${LUASRC} ${MAKESRC} ${OBJCSRC}\
${OBJCPPSRC} ${PASSRC} ${PHPSRC} ${PERLSRC} ${PSSRC} ${PROLSRC} ${PYTSRC}\
${TEXSRC} ${YSRC}
NONSRCS=entry.strange lists.erl clheir.hpp.gz
VHDLFLAGS=--language=none --regex='/[ \t]*\(ARCHITECTURE\|CONFIGURATION\) +[^ ]* +OF/' --regex='/[ \t]*\(ATTRIBUTE\|ENTITY\|FUNCTION\|PACKAGE\( BODY\)?\|PROCEDURE\|PROCESS\|TYPE\)[ \t]+\([^ \t(]+\)/\3/'
COBOLFLAGS=--language=none --regex='/.......[a-zA-Z0-9-]+\./'
POSTSCRIPTFLAGS=--language=none --regex='#/[^ \t{]+#'
TCLFLAGS=--lang=none --regex='/proc[ \t]+\([^ \t]+\)/\1/'
GETOPTOBJS= #getopt.o getopt1.o
RXINCLUDE=-Iemacs/src
REGEXOBJS=regex.o
CHECKOBJS=chkmalloc.o chkxm.o
CHECKFLAGS=-DDEBUG -Wno-unused-function
OBJS=${GETOPTOBJS} ${REGEXOBJS} ${CHECKOBJS}
CPPFLAGS=${CHECKFLAGS} -DSTDC_HEADERS -DHAVE_GETCWD ${RXINCLUDE} -I.
LDFLAGS=#-static -lc_p
WARNINGS=-pedantic -Wall -Wpointer-arith -Winline -Wmissing-prototypes -Wmissing-declarations -Wunused -Wformat -Wno-switch -Wsign-compare -Wpointer-arith -Wshadow -Wstrict-prototypes
CFLAGS=${WARNINGS} -ansi -g3 # -pg -O
#CC=gcc-3.0
#TARGET_ARCH=
FASTCFLAGS=-O3 -finline-functions -ffast-math -funroll-loops
FASTCFLAGSWARN=${WARNINGS} -Werror ${FASTCFLAGS}
FILTER=grep -v '\.[Cchefy][lor]*,[1-9][0-9]*' || true
REGEX=/[ \t]*DEFVAR_[A-Z_ \t\n(]+"\([^"]+\)"/
xx="this line is here because of a fontlock bug
MAKE:=$(MAKE) --no-print-directory
RUN=time --quiet --format '%U + %S: %E'
RUN=
OPTIONS=--members --declarations --regex=@regexfile
ARGS=- < srclist
infiles = $(filter-out ${NONSRCS},${SRCS}) srclist regexfile
quiettest:
@rm -f /tmp/[0-9][0-9][0-9][0-9][0-9][0-9]malloc
@-$(MAKE) OPTIONS='--no-members' ${LATEST}ediff
@-$(MAKE) OPTIONS='--declarations --no-members' ${LATEST}ediff
@-$(MAKE) OPTIONS='--members' ${LATEST}ediff
@-$(MAKE) OPTIONS='--regex=@regexfile --no-members' ${LATEST}ediff
@-$(MAKE) OPTIONS='nonexistent --members --declarations --regex=@regexfile' ${LATEST}ediff
@-$(MAKE) ${LATEST}cdiff
test:
@rm -f /tmp/[0-9][0-9][0-9][0-9][0-9][0-9]malloc
@$(MAKE) OPTIONS='--no-members' ${LATEST}ediff
@$(MAKE) OPTIONS='--declarations --no-members' ${LATEST}ediff
@$(MAKE) OPTIONS='--members' ${LATEST}ediff
@$(MAKE) OPTIONS='--regex=@regexfile --no-members' ${LATEST}ediff
@$(MAKE) OPTIONS='nonexistent --members --declarations --regex=@regexfile' ${LATEST}ediff
@$(MAKE) ${LATEST}cdiff
${CHECKOBJS}: CFLAGS=-g3 -DNULLFREECHECK=0
checker:
@rm -f /tmp/[0-9][0-9][0-9][0-9][0-9][0-9]malloc ${REGEXOBJS}
@env CHECKEROPTS="--trace --profile --Wfree-null" \
$(MAKE) CFLAGS= CHECKOBJS= CHECKFLAGS= CC=checkergcc ${LATEST}ediff
rm -f $REGEXOBJS
standalone:
rm -f etags ctags
@$(MAKE) etags "CPPFLAGS=-UVERSION"
@$(MAKE) ctags "CPPFLAGS=-UVERSION"
prof: ETAGS
prof -xgs etags
fastetags:
rm -f etags ${GETOPTOBJS} ${REGEXOBJS}
@$(MAKE) CHECKOBJS= CHECKFLAGS= etags "CFLAGS=-ansi ${FASTCFLAGSWARN}"
fastctags:
rm -f ctags ${GETOPTOBJS} ${REGEXOBJS}
@$(MAKE) CHECKOBJS= CHECKFLAGS= ctags "CFLAGS=-ansi ${FASTCFLAGSWARN}"
staticetags:
rm -f etags ${GETOPTOBJS} ${REGEXOBJS}
@$(MAKE) etags CHECKOBJS= CHECKFLAGS= REGEXOBJS= GETOPTOBJS= RXINCLUDE= "CFLAGS=${FASTCFLAGSWARN} -static"
rsynctofly:
rsync --exclude "*~" --exclude core --exclude etags -zauRv . fly:gnu/etags/
rsyncfromfly:
rsync --exclude "*~" --exclude core --exclude etags -zauRv fly:gnu/etags/ ../..
web ftp publish:
@-echo -e \\ttesting with debugging enabled...; $(MAKE) quiettest
@-echo -e \\ttesting standalone...; $(MAKE) standalone quiettest
@-echo -e \\ttesting fast versions...; $(MAKE) fastetags fastctags quiettest
@$(MAKE) /home/www/pub/etags.c.gz
@$(MAKE) /home/www/pub/software/unix/etags.tar.gz
release distrib: web
cat xemacs-mail | /usr/sbin/sendmail -f pot@gnu.org ${RELEASELIST}
mv etags etags${LATEST}
mv ctags ctags${LATEST}
tags: TAGS
clean:
rm -f ${OBJS} etags ETAGS
srclist: Makefile
@for i in $(SRCS); do echo $$i; done > srclist
@echo srclist remade
regexfile: Makefile
@echo ' -- This is for GNU Emacs source files' > regexfile
@echo '${REGEX}' >> regexfile
@echo '{c}${REGEX}\\1/m' >> regexfile
@echo regexfile remade
/home/www/pub/etags.c.gz: etags.c
co -kv etags.c
gzip --best -c etags.c > $@
#/home/www/pub/software/unix/etags.tar.gz: Makefile staticetags etags.1.man ETAGS.EBNF ETAGS.README
# tar -hzcf $@ COPYING ChangeLog ETAGS.EBNF etags.c etags.1 etags.1.man etags
/home/www/pub/software/unix/etags.tar.gz: Makefile etags.1.man ETAGS.EBNF ETAGS.README maintaining.texi
tar -hzcf $@ COPYING ChangeLog ETAGS.EBNF ETAGS.README etags.c etags.1 etags.1.man maintaining.texi
regex.o: emacs/src/regex.c
$(CC) ${FASTCFLAGS} -c $?
getopt.o: emacs/lib-src/getopt.c
$(CC) ${FASTCFLAGS} -c $?
getopt1.o: emacs/lib-src/getopt1.c
$(CC) ${FASTCFLAGS} -c $?
etags: etags.c ${OBJS}
$(CC) $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) -o etags etags.c ${OBJS}
ctags: etags.c ${OBJS}
$(CC) $(CFLAGS) $(CPPFLAGS) -DCTAGS $(LDFLAGS) -o ctags etags.c ${OBJS}
man manpage: etags.1.man
etags.1.man: etags.1
nroff -man -Tman etags.1 > $@
maintaining.info: maintaining.texi
makeinfo --force --no-split maintaining.texi
TAGS: etags.c
etags etags.c
%ediff: ETAGS% ETAGS ${infiles}
sdiff --suppress-common-lines --width=103 ETAGS$* ETAGS
oediff: OTAGS ETAGS ${infiles}
sdiff --suppress-common-lines --width=103 OTAGS ETAGS
%cdiff: CTAGS% CTAGS ${infiles}
sdiff --suppress-common-lines --width=103 CTAGS$* CTAGS
xdiff: ETAGS EXTAGS ${infiles}
sdiff --suppress-common-lines --width=103 ETAGS EXTAGS
ETAGS: FRC etags ${infiles}
${RUN} ./etags ${OPTIONS} -o $@ ${ARGS}
ETAGS%: FRC etags% ${infiles}
${RUN} etags$* ${OPTIONS} -o $@ ${ARGS}
ETAGS13 ETAGS14 ETAGS15: etags% ${infiles}
TEXTAGS=def:newcommand:newenvironment ${RUN} etags$* --regex=@regexfile} -o $@ ${ARGS}
ETAGS12: etags12 ${infiles}
${RUN} etags12 --members -o $@ --regex='${REGEX}' ${ARGS}
OTAGS: oetags ${SRCS} srclist
${RUN} ./oetags -o $@ -t ${ARGS}
CTAGS: ctags ${infiles}
${RUN} ./ctags -o $@ --regex=@regexfile ${ARGS}
CTAGS%: ctags% ${infiles}
${RUN} ctags$* -wtTd --globals --members -o $@ --regex=@regexfile ${ARGS}
CTAGS13 CTAGS14 CTAGS15: ctags% ${infiles}
TEXTAGS=def:newcommand:newenvironment ${RUN} ctags$* -wt -o $@ --regex='${REGEX}' ${ARGS}
EXTAGS: extags ${infiles} Makefile
${RUN} ./extags -e --regex-c='${REGEX}' --c++-types=+x --c-types=+x --if0=yes --line-directives=yes -o $@ -L - < srclist
.PRECIOUS: ETAGS CTAGS ETAGS16 CTAGS16 ETAGS17 CTAGS17
FRC:;

View file

@ -0,0 +1,120 @@
/*+++*
* title: PackageInspector.h
* abstract: interface definitions for WM PackageInspector
* author: T.R.Hageman, Groningen, The Netherlands
* created: November 1994
* modified: (see RCS Log at end)
* copyleft:
*
* Copyright (C) 1994,1995 Tom R. Hageman.
*
* This 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 software 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 software; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* description:
*
*---*/
#import <appkit/appkit.h>
#import <apps/Workspace.h>
#include <sys/stat.h>
#import "Subprocess.h"
#define NUMSTATS 4
#define TYPESTOSTAT "bom", "info", "sizes", "tiff"
@interface PackageInspector:WMInspector
{
// Outlets
id packageArchesField;
id packageDescriptionText;
id packageIconButton;
id packageLocationField;
id packageSizesField;
id packageStatusField;
id packageTitleField;
id packageVersionField;
id inspectorVersionField;
id infoPanel;
id infoVersionField;
// other variables.
NXBundle *bundle; // class bundle.
NXBundle *package; // package bundle.
struct stat stats[NUMSTATS]; // for lazy inspection.
enum { listContents, listDescription } revertButtonState;
Subprocess *archProcess; // To determine architectures.
}
// Actions.
-showInfo:sender;
-open:sender;
// The workhorses
-(BOOL)shouldLoad;
-load;
-toggleDescription;
// Load helper methods
-loadKeyValuesFrom:(const char *)type inTable:(HashTable *)table;
-loadContentsOf:(const char *)type inTable:(HashTable *)table;
-loadImage;
// Support methods
-(const char *)getPath:(char *)path forType:(const char *)type;
-setRevertButtonTitle;
-(const char *)formatSize:(const char *)size inBuf:(char *)buf;
// Determine architectures, in separate subprocess.
-(void)getArchs;
// Subprocess [TRH-enhanced] delegate methods:
// Subprocess delegate methods:
-subprocess:(Subprocess *)sender output:(char *)buffer;
-subprocessDone:(Subprocess *)sender;
@end // PackageInspector
/*======================================================================
* PackageInspector.h,v
* Revision 1.7 1995/08/17 22:18:24 tom
* (-open:): new method.
*
* Revision 1.6 1995/07/30 16:59:51 tom
* import Subprocess.h; (archProcess): new ivar;
* (-getArchs,-subprocess:output:,-subprocessDone:): new methods;
* added for asynchronous arch-determination.
*
* Revision 1.5 1995/07/29 02:59:55 tom
* (NUMSTATS,TYPESTOSTAT): new defines, (stats[NUMSTATS]): new ivar, replaces
* bomstat, infostat, t ogeneralize lazy-load code.
*
* Revision 1.4 1995/04/02 02:39:05 tom
* (package): NXBundle instead of (const char *). so that localized info files
* are found. (this loses out if *.pkg is a symbolic link, though.)
*
* Revision 1.3 1994/12/07 00:00:36 tom
* add GNU copleft comment.
*
* Revision 1.2 1994/11/25 20:18:56 tom
* (package ivar): use (char*) instead of (NXBundle*) to workaround symlink problems
*
* Revision 1.1 1994/11/24 22:39:56 tom
* Initial revision
*
*======================================================================*/

View file

@ -0,0 +1,505 @@
/*+++*
* title: PackageInspector.m
* abstract: NEXTSTEP Workspace Manager Inspector for Installer ".pkg" files.
* author: T.R.Hageman, Groningen, The Netherlands
* created: November 1994
* modified: (see RCS Log at end)
* copyleft:
*
* Copyright (C) 1994,1995 Tom R. Hageman.
*
* This 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 software 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 software; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* description:
*
*---*/
#ifdef RCS_ID
static const char RCSid[] =
"PackageInspector.m,v 1.8 1995/09/01 21:46:27";
#endif
#define VERSION "0.951"
#ifndef DEBUG
# define DEBUG 0
#endif
#define LISTCONTENTS 0 // List Contents not yet implemented
#import "PackageInspector.h"
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
// Localized strings
#define OPENBUTTON NXLocalizedStringFromTableInBundle(NULL, bundle, "Open", NULL, button label)
#define LISTCONTENTSBUTTON NXLocalizedStringFromTableInBundle(NULL, bundle, "List Contents", NULL, button label)
#define LISTDESCRIPTIONBUTTON NXLocalizedStringFromTableInBundle(NULL, bundle, "Description", NULL, button label)
// States
#define STATE_UNINSTALLED NXLocalizedStringFromTableInBundle(NULL, bundle, "Uninstalled", NULL, original package state)
#define STATE_INSTALLED NXLocalizedStringFromTableInBundle(NULL, bundle, "installed", "Installed", package has been uncompressed unto disk)
#define STATE_COMPRESSD NXLocalizedStringFromTableInBundle(NULL, bundle, "compressed", "Compressed", installed package has been recompressed)
// so InfoView.strings can be ripped off from Installer.app
#define SIZEFORMAT NXLocalizedStringFromTableInBundle("InfoView", bundle, "%s installed, %s compressed", NULL, Short indication to user about the size of a package once installed and the size when compressed)
#define KBYTES NXLocalizedStringFromTableInBundle("InfoView", bundle, "KB", NULL, Kilobytes -- package size)
#define MBYTES NXLocalizedStringFromTableInBundle("InfoView", bundle, "MB", NULL, MegaBytes -- package size)
#define LOCALIZE(s) NXLoadLocalizedStringFromTableInBundle(NULL, bundle, s, NULL)
#define LOCALIZE_ARCH(s) NXLoadLocalizedStringFromTableInBundle("Architectures", bundle, s, NULL)
@implementation PackageInspector
+new
{
static PackageInspector *instance;
if (instance == nil) {
char path[MAXPATHLEN+1];
const char *nibname = [self name];
instance = [super new];
instance->bundle = [NXBundle bundleForClass:self];
if ([instance->bundle getPath:path forResource:nibname ofType:"nib"] &&
[NXApp loadNibFile:path owner:instance]) {
[instance->inspectorVersionField setStringValue:VERSION];
[instance->packageDescriptionText setVertResizable:YES]; // ??Necessary??
}
else {
fprintf(stderr, "Couldn't load %s.nib\n", nibname);
[instance free];
instance = nil;
}
}
return instance;
}
-showInfo:sender
{
if (infoPanel == nil) {
char path[MAXPATHLEN+1];
if ([bundle getPath:path forResource:"Info" ofType:"nib"] &&
[NXApp loadNibFile:path owner:self]) {
[infoVersionField setStringValue:[inspectorVersionField stringValue]];
}
}
[infoPanel makeKeyAndOrderFront:sender];
return self;
}
-revert:sender
{
[super revert:sender];
if ([self selectionCount] != 1) {
return nil;
}
if (sender == [self revertButton]) {
[self toggleDescription];
}
else {
char path[MAXPATHLEN+1];
[package free];
[self selectionPathsInto:path separator:'\0'];
if (!(package = [[NXBundle allocFromZone:[self zone]] initForDirectory:path])) {
return nil;
}
if ([self shouldLoad]) {
[self load];
revertButtonState = listContents;
}
}
[[[self okButton] setTitle:OPENBUTTON] setEnabled:YES];
[self setRevertButtonTitle];
return self;
}
-ok:sender
{
[self perform:@selector(open:) with:sender afterDelay:0 cancelPrevious:NO];
[super ok:sender];
return self;
}
-load
{
char buf[256], size[2][20];
HashTable *table = [[HashTable alloc] initKeyDesc:"*" valueDesc:"*"];
[self getArchs];
// Collect information about the package in a hashtable.
[self loadKeyValuesFrom:"info" inTable:table];
[self loadKeyValuesFrom:"sizes" inTable:table];
[self loadContentsOf:"location" inTable:table];
[self loadContentsOf:"status" inTable:table];
// Convenience macro.
#define LOOKUP(key, notfound) ([table isKey:key] ? [table valueForKey:key] : \
(notfound))
#if 0
// Set the various controls.
sprintf(buf, "<<not yet implemented>>");
// Well then, how *DOES* Installer determine this???
[packageArchesField setStringValue:buf];
#endif
[packageDescriptionText setText:LOOKUP("Description", "")];
[packageLocationField setStringValue:
LOOKUP("location", LOOKUP("DefaultLocation", "???"))];
[self formatSize:[table valueForKey:"InstalledSize"] inBuf:size[0]];
[self formatSize:[table valueForKey:"CompressedSize"] inBuf:size[1]];
sprintf(buf, SIZEFORMAT, size[0], size[1]);
[packageSizesField setStringValue:buf];
[packageStatusField setStringValue:LOCALIZE(LOOKUP("status", "Uninstalled"))];
[packageTitleField setStringValue:LOOKUP("Title", "???")];
[packageVersionField setStringValue:LOOKUP("Version", "???")];
#undef LOOKUP
// Is this how one frees the contents of a hashtable?
[table freeKeys:free values:free];
[table free];
[self loadImage];
return self;
}
-loadKeyValuesFrom:(const char *)type inTable:(HashTable *)table
{
char path[MAXPATHLEN+1];
NXStream *stream;
if (stream = NXMapFile([self getPath:path forType:type], NX_READONLY)) {
int c;
#if DEBUG & 1
fprintf(stderr, "loadKeyValuesFrom:%s\n", path);
#endif
while ((c = NXGetc(stream)) >= 0) {
// Buffer sizes should be enough, according to doc.
char key[1024+1], value[1024+1];
char *p;
if (NXIsSpace(c)) continue;
if (c == '#') {
while ((c = NXGetc(stream)) >= 0 && c != '\n') ;
continue;
}
// Found key; collect it.
p = key;
do {
if (p < &key[sizeof key-1]) *p++ = c;
} while ((c = NXGetc(stream)) >= 0 && !NXIsSpace(c));
*p = '\0';
// Skip over spaces and tabs.
while (c == ' ' || c == '\t') c = NXGetc(stream);
// Value is rest of line, up to newline.
p = value;
do {
if (p < &value[sizeof value-1]) *p++ = c;
} while ((c = NXGetc(stream)) >= 0 && c != '\n');
*p = '\0';
// Insert key/value pair in hashtable.
#if DEBUG & 1
fprintf(stderr, "key:%s value:%s\n", key, value);
#endif
[table insertKey:NXCopyStringBuffer(key)
value:NXCopyStringBuffer(value)];
}
NXCloseMemory(stream, NX_FREEBUFFER);
}
return self;
}
-loadContentsOf:(const char *)type inTable:(HashTable *)table
{
char path[MAXPATHLEN+1];
NXStream *stream;
if (stream = NXMapFile([self getPath:path forType:type], NX_READONLY)) {
char line[1024+1];
int n = NXRead(stream, line, sizeof line);
if (n > 0 && line[n-1] == '\n') line[n-1] = '\0'; // remove trailing newline.
NXCloseMemory(stream, NX_FREEBUFFER);
[table insertKey:NXCopyStringBuffer(type)
value:NXCopyStringBuffer(line)];
}
return self;
}
-loadImage
{
char path[MAXPATHLEN+1];
NXImage *image;
// Remove old image from the button.
if (image = [packageIconButton image]) {
[packageIconButton setImage:nil];
[image free];
}
// Get the image (if any) from the package
image = [[NXImage allocFromZone:[self zone]] initFromFile:[self getPath:path forType:"tiff"]];
[packageIconButton setImage:image];
return self;
}
#define STAT_EQ(s1, s2) ((s1)->st_ino == (s2)->st_ino && \
(s1)->st_dev == (s2)->st_dev && \
(s1)->st_mtime == (s2)->st_mtime && \
(s1)->st_size == (s2)->st_size)
-(BOOL)shouldLoad
{
char path[MAXPATHLEN+1];
struct stat newstats[NUMSTATS];
static const char * const typesToStat[NUMSTATS] = { TYPESTOSTAT };
BOOL result = NO;
int i;
for (i = 0; i < NUMSTATS; i++) {
memset(&newstats[i], 0, sizeof(struct stat));
if (!(stat([self getPath:path forType:typesToStat[i]], &newstats[i]) == 0 &&
STAT_EQ(&newstats[i], &stats[i]))) {
result = YES;
///break; // NOT!!! must stat all for accurate cache.
}
stats[i] = newstats[i];
}
return result;
}
-toggleDescription
{
switch (revertButtonState) {
case listContents:
// TODO: swap views?
revertButtonState = listDescription;
break;
case listDescription:
revertButtonState = listContents;
break;
}
return [self setRevertButtonTitle];
}
// Support methods
-(const char *)getPath:(char *)buf forType:(const char *)type
{
char name[MAXPATHLEN+1];
// Get package name, sans extension.
*strrchr(strcpy(name, strrchr([package directory], '/')+1), '.') = '\0';
// Now get the full pathname.
[package getPath:buf forResource:name ofType:type];
#if DEBUG & 2
fprintf(stderr, "PackageInspector: type=\"%s\" name=\"%s\" path=\"%s\"\n",
type, name, buf);
#endif
return buf;
}
-setRevertButtonTitle
{
#if LISTCONTENTS
[[[self revertButton]
setTitle:LOCALIZE(revertButtonState == listContents ?
"List Contents" : "Description")]
setEnabled:YES];
#endif
return self;
}
-(const char *)formatSize:(const char *)size inBuf:(char *)buf
{
// [TRH] this is very simplistic (but seems consistent with Installer.app)
if (!size) {
strcpy(buf, "???");
}
else {
int len = strlen(size);
if (len < 4) {
sprintf(buf, "%s%s", size, KBYTES);
}
else if (len < 6) {
sprintf(buf, "%.*s.%.*s%s",
(len-3), size, 3-(len-3), size+(len-3), MBYTES);
}
else {
sprintf(buf, "%.*s%s", (len-3), size, MBYTES);
}
}
return buf;
}
// Determine architectures, in separate subprocess.
#define WORKING " ..." // `I'm still busy' indicator.
-(void)getArchs
{
char command[2*MAXPATHLEN+10+1];
if (archProcess) [archProcess terminate:self];
[packageArchesField setStringValue:WORKING];
[bundle getPath:command forResource:"archbom" ofType:NULL];
strcat(command, " ");
[self getPath:&command[strlen(command)] forType:"bom"];
archProcess = [[Subprocess allocFromZone:[self zone]] init:command
withDelegate:self andPtySupport:NO andStdErr:NO];
}
-(void)addArchs:(const char *)string
{
char result[1024]; // Should be big enough...
const char *s;
char *d;
strcpy(result, [packageArchesField stringValue]);
if ((d = strstr(result, WORKING)) != NULL) {
*d = '\0';
}
else {
d = result + strlen(result);
}
if ((s = string)) {
do {
char name[100];
char *t = name;
while (*s && !NXIsAlNum(*s)) {
if (*s == '\n') {
*d++ = ' ', s++;
}
else {
*d++ = *s++;
}
}
while (NXIsAlNum(*s)) *t++ = *s++;
*t = '\0';
if (t > name) {
#if DEBUG & 4
fprintf(stderr, "addArchs:\"%s\" localized: \"%s\"\n", name, LOCALIZE_ARCH(name));
#endif
strcpy(d, LOCALIZE_ARCH(name));
d += strlen(d);
}
} while (*s);
strcpy(d, WORKING);
}
[packageArchesField setStringValue:result];
[window displayIfNeeded]; // necessary??
}
-subprocess:(Subprocess *)sender output:(char *)buffer
{
if (sender == archProcess) {
[self addArchs:buffer];
}
return self;
}
-subprocessDone:(Subprocess *)sender
{
if (sender == archProcess) {
archProcess = nil;
[self addArchs:NULL];
}
[sender free];
return self;
}
static void openInWorkspace(const char *filename)
{
// Indirect approach to circumvent Workspace deadlock/timeout.
char command[14+3*MAXPATHLEN+1];
const char *s;
char *d = command;
for (s = "exec open '"; *s; ) *d++ = *s++;
// Escape single quote characters.
for (s = filename; *s; ) {
if ((*d++ = *s++) == '\'') {
*d++ = '\\', *d++ = '\'', *d++ = '\'';
}
}
for (s = "'&"; *d++ = *s++; ) ;
system(command);
}
-open:sender
{
openInWorkspace([package directory]);
return self;
}
@end
/*======================================================================
* PackageInspector.m,v
* Revision 1.8 1995/09/01 21:46:27 tom
* Circumvent open deadlock/timeout (when Installer.app is not yet launched);
* (openInWorkspace): new private function; (-open:): new method.
*
* Revision 1.7 1995/07/30 22:20:26 tom
* (LOCALIZE_ARCH): new macro; (-addArchs:): new method;
* (-subprocess:output:,-subprocessDone:) use it.
*
* Revision 1.6 1995/07/30 16:59:51 tom
* import Subprocess.h; (archProcess): new ivar;
* (-getArchs,-subprocess:output:,-subprocessDone:): new methods;
* added for asynchronous arch-determination.
*
* Revision 1.5 1995/07/29 19:13:35 tom
* (+new): avoid reassignment of self;
* make packageDescriptionText vertically resizable;
* (-shouldLoad): rewritten to generalized array-driven approach.
*
* Revision 1.4 1995/04/02 02:39:01 tom
* (package): NXBundle instead of (const char *). so that localized info files
* are found. (this loses out if *.pkg is a symbolic link, though.)
*
* Revision 1.3 1994/12/07 00:00:36 tom
* (RCSid): add spaces.
*
* Revision 1.2 1994/11/25 21:27:18 tom
* (package ivar): use (char*) instead of (NXBundle*) to workaround symlink problems
*
* Revision 1.1 1994/11/25 16:13:12 tom
* Initial revision
*
*======================================================================*/

View file

@ -0,0 +1,81 @@
/*
Subprocess.h (v10)
by Charles L. Oei
pty support by Joe Freeman
with encouragement from Kristofer Younger
Subprocess Example, Release 2.0
NeXT Computer, Inc.
You may freely copy, distribute and reuse the code in this example.
NeXT disclaims any warranty of any kind, expressed or implied, as to
its fitness for any particular use.
Hacked up for use in PackageInspector by Tom Hageman.
*/
#import <objc/Object.h>
#import <stdio.h>
/*
This subprocess object sends/receives data to/from any UNIX
subprocess asynchronously (via vfork/pipe).
Its delegate, if any, will receive the following messages:
- subprocessDone;
// sent when the subprocess exits
- subprocessOutput:(char *)buffer;
// sent whenever there is data on the standard output pipe;
// buffer is only valid until next call
- subprocessError:(const char *)errorString;
// sent when an error occurs;
// if it ever happens, it's usually only at startup time
// [TRH] and this is how these should have been done in the first place...
- subprocessDone:(SubProcess *)sender;
- subprocess:(SubProcess *)sender output:(char *)buffer;
*/
// Hack to uniquize classname (to avoid dynload errors.)
#define Subprocess SubprocessForPackageInspector
#define BUFFERSIZE 2048
@interface Subprocess:Object
{
FILE *fpToChild;
int fromChild;
int childPid;
id delegate;
int masterPty; // file descriptor for master/slave pty
int slavePty;
int bufferCount;
char outputBuffer[BUFFERSIZE];
}
- init:(const char *)subprocessString;
// a cover for the below withDelegate:nil, andPtySupport:NO, andStdErr:YES
- init:(const char *)subprocessString
withDelegate:theDelegate
andPtySupport:(BOOL)wantsPty
andStdErr:(BOOL)wantsStdErr;
// optional requests for pseudo terminal support and
// redirecting the standard error stream thru standard output
- send:(const char *)string withNewline:(BOOL)wantNewline;
// send the string optionally followed by a new line
- send:(const char *)string;
// sends the string followed by a new line
// shorthand for above withNewline:YES
- terminateInput;
// sends an end-of-file (EOF) to the subprocess
// (and closes input pipe to child)
- terminate:sender;
// forces the subprocess to terminate (w/ SIGTERM)
- setDelegate:anObject;
- delegate;
@end

View file

@ -0,0 +1,343 @@
/*
Subprocess.m (v10)
by Charles L. Oei
pty support by Joe Freeman
Subprocess Example, Release 2.0
NeXT Computer, Inc.
You may freely copy, distribute and reuse the code in this example.
NeXT disclaims any warranty of any kind, expressed or implied, as to
its fitness for any particular use.
*/
#import "Subprocess.h"
// #import <sgtty.h> // needed to compile under Release 1.0
#import <appkit/nextstd.h>
#import <appkit/Application.h>
#import <appkit/Panel.h>
#import <sys/wait.h>
#define PTY_TEMPLATE "/dev/pty??"
#define PTY_LENGTH 11
static void showError();
/*==========================================================
*
* Private Instance Methods
*
*==========================================================*/
@interface Subprocess(Private)
- childDidExit;
- fdHandler:(int)theFd;
@end
@implementation Subprocess(Private)
- childDidExit
// cleanup after a child process exits
{
if (childPid)
{
union wait exitstatus;
int waitresult;
DPSRemoveFD(fromChild);
close(fromChild);
fclose(fpToChild);
// Cleanup zombie processes. (blocking wait is too dangerous here...)
waitresult = wait4(childPid, &exitstatus, WNOHANG, NULL);
if (waitresult != childPid) {
/* XXX should handle this gracefully, e.g, timed entry. */
}
childPid=0; // specify that child is dead
if (delegate)
{
if ([delegate respondsTo:@selector(subprocessDone:)])
[delegate perform:@selector(subprocessDone:) with:self];
else if ([delegate respondsTo:@selector(subprocessDone)])
[delegate perform:@selector(subprocessDone)];
}
}
return self;
}
- fdHandler:(int)theFd
// DPS handler for output from subprocess
{
if ((bufferCount = read(theFd, outputBuffer, BUFFERSIZE-1)) <= 0)
{
[self childDidExit];
return self;
}
outputBuffer[bufferCount] = '\0';
if (delegate)
{
if ([delegate respondsTo:@selector(subprocess:output:)])
[delegate perform:@selector(subprocess:output:)
with:self with:(void *)&outputBuffer];
else if ([delegate respondsTo:@selector(subprocessOutput:)])
[delegate perform:@selector(subprocessOutput:)
with:(void *)&outputBuffer];
}
return self;
}
@end
/*==========================================================
*
* Private Utility Routines
*
*==========================================================*/
static void
showError (const char *errorString, id theDelegate)
// ensure errors never get dropped on the floor
{
if (theDelegate && [theDelegate respondsTo:@selector(subprocessError:)])
[theDelegate
perform:@selector(subprocessError:)
with:(void *)errorString];
else if (NXApp) // no delegate, but we're running w/in an App
NXRunAlertPanel(0, errorString, 0, 0, 0);
else
perror(errorString);
}
static void
fdHandler (int theFd, id self)
// DPS handler for output from subprocess
{
[self fdHandler:theFd];
}
static void
getptys (int *master, int *slave)
// attempt to setup the ptys
{
char device[PTY_LENGTH];
char *block, *num;
char *blockLoc; // specifies the location of block for the device string
char *numLoc; // specifies the pty name with the digit ptyxD
char *msLoc; // specifies the master (ptyxx) or slave (ttyxx)
struct sgttyb setp =
{B9600, B9600, (char)0x7f, (char)0x15, (CRMOD|ANYP)};
struct tchars setc =
{CINTR, CQUIT, CSTART, CSTOP, CEOF, CBRK};
struct ltchars sltc =
{CSUSP, CDSUSP, CRPRNT, CFLUSH, CWERASE, CLNEXT};
int lset =
(LCRTBS|LCRTERA|LCRTKIL|LCTLECH|LPENDIN|LDECCTQ);
int setd = NTTYDISC;
strcpy(device, PTY_TEMPLATE); // string constants are not writable
blockLoc = &device[ strlen("/dev/pty") ];
numLoc = &device[ strlen("/dev/pty?") ];
msLoc = &device[ strlen("/dev/") ];
for (block = "pqrs"; *block; block++)
{
*blockLoc = *block;
for (num = "0123456789abcdef"; *num; num++)
{
*numLoc = *num;
*master = open(device, O_RDWR);
if (*master >= 0)
{
*msLoc = 't';
*slave = open(device, O_RDWR);
if (*slave >= 0)
{
(void) ioctl(*slave, TIOCSETP, (char *)&setp);
(void) ioctl(*slave, TIOCSETC, (char *)&setc);
(void) ioctl(*slave, TIOCSETD, (char *)&setd);
(void) ioctl(*slave, TIOCSLTC, (char *)&sltc);
(void) ioctl(*slave, TIOCLSET, (char *)&lset);
return;
} else {
// close the master and reset the device
// name so that the master opens it properly
*msLoc = 'p';
close(*master);
}
}
} /* hunting through a bank of ptys */
} /* hunting through blocks of ptys in all the right places */
*master = -1;
*slave = -1;
}
@implementation Subprocess
/*==========================================================
*
* Public Instance Methods
*
*==========================================================*/
- init:(const char *)subprocessString
// a cover for the below withDelegate:nil, andPtySupport:NO, andStdErr:YES
{
return
[self
init:subprocessString
withDelegate:nil
andPtySupport:NO
andStdErr:YES];
}
- init:(const char *)subprocessString
withDelegate:theDelegate
andPtySupport:(BOOL)wantsPty
andStdErr:(BOOL)wantsStdErr
// initializes an instance of Subprocess and corresponding UNIX process
{
int pipeTo[2]; // for non-Pty support
int pipeFrom[2];
int tty, numFds, fd; // for temporary use
int processGroup;
int pidChild; // needed because childPid does not exist
// until Subprocess is instantiated
if (wantsPty)
{
tty = open("/dev/tty", O_RDWR);
getptys(&masterPty,&slavePty);
if (masterPty <= 0 || slavePty <= 0)
{
showError("Error grabbing ptys for subprocess.", theDelegate);
return self;
}
// remove the controlling tty if launched from a shell,
// but not Workspace;
// so that we have job control over the parent application in shell
// and so that subprocesses can be restarted in Workspace
if ((tty<0) && ((tty = open("/dev/tty", 2))>=0))
{
ioctl(tty, TIOCNOTTY, 0);
close(tty);
}
}
else
{
if (pipe(pipeTo) < 0 || pipe(pipeFrom) < 0)
{
showError("Error starting UNIX pipes to subprocess.", theDelegate);
return self;
}
}
switch (pidChild = vfork())
{
case -1: // error
showError("Error starting UNIX vfork of subprocess.", theDelegate);
return self;
case 0: // child
if (wantsPty)
{
dup2(slavePty, 0);
dup2(slavePty, 1);
if (wantsStdErr)
dup2(slavePty, 2);
}
else
{
dup2(pipeTo[0], 0);
dup2(pipeFrom[1], 1);
if (wantsStdErr)
dup2(pipeFrom[1], 2);
}
numFds = getdtablesize();
for (fd=3; fd<numFds; fd++)
close(fd);
processGroup = getpid();
ioctl(0, TIOCSPGRP, (char *)&processGroup);
setpgrp (0, processGroup);
// we exec a /bin/sh so that cmds are easier to specify for the user
execl("/bin/sh", "sh", "-c", subprocessString, 0);
perror("vfork (child)"); // should never gets here tho
exit(1);
default: // parent
[self setDelegate:theDelegate];
childPid = pidChild;
if (wantsPty)
{
close(slavePty);
fpToChild = fdopen(masterPty, "w");
fromChild = masterPty;
}
else
{
close(pipeTo[0]);
close(pipeFrom[1]);
fpToChild = fdopen(pipeTo[1], "w");
fromChild = pipeFrom[0];
}
setbuf(fpToChild, NULL);
DPSAddFD(
fromChild,
(DPSFDProc)fdHandler,
(id)self,
NX_MODALRESPTHRESHOLD+1);
return self;
}
}
- send:(const char *)string withNewline:(BOOL)wantNewline
{
fputs(string, fpToChild);
if (wantNewline)
fputc('\n', fpToChild);
return self;
}
- send:(const char *)string
{
[self send:string withNewline:YES];
return self;
}
- terminateInput
// effectively sends an EOF to the child process stdin
{
fclose(fpToChild);
return self;
}
- terminate:sender
{
if (childPid)
{
//kill(childPid+1, SIGTERM);
killpg(childPid, SIGTERM);
[self childDidExit];
}
return self;
}
- setDelegate:anObject
{
delegate = anObject;
return self;
}
- delegate
{
return delegate;
}
@end

View file

@ -0,0 +1,49 @@
//
// SimpleCalc -- Randy Nelson -- NeXT Developer Training
// A general class that serves as a liaison between a calculator interface
// and a calculator engine.
//
// You may freely copy, distribute and reuse the code in this example.
// NeXT disclaims any warranty of any kind, expressed or implied, as to
// its fitness for any particular use.
//
// Created 8-8-90
//
#import <objc/Object.h>
@interface SimpleCalc:Object
{
// outlets...the front-end.
id display;
id enterKey;
id minusKey;
id infoManager;
id myNXStringTable;
// C++ object's can be a-part-of Objective-C objects.
class CalcEngine *cplus_object;
// record each previous user action
SEL previousAction;
}
// actions.
- numberKeys:sender;
- decimalKey:sender;
- operationKeys:sender;
- equalsKey:sender;
- clearKey:sender;
- clearAllKey:sender;
- infoPanel:sender;
- helpPanel:sender;
// delegate methods.
- windowWillClose:sender;
- appDidInit:sender;
- registerAction:(SEL)action;
- appendToDisplay:(const char *)theString;
@end

View file

@ -0,0 +1,207 @@
// SimpleCalc -- Randy Nelson -- NeXT Developer Training
// A general class that serves as a liaison between a calculator interface
// and a calculator engine.
//
// You may freely copy, distribute and reuse the code in this example.
// NeXT disclaims any warranty of any kind, expressed or implied, as to
// its fitness for any particular use.
//
// Created 8-22-90
//
// C++ "linkage" directive - tells the C++ compiler that the following
// interface files contain Objective-C code.
extern "Objective-C"
{
#import <appkit/Application.h>
#import <appkit/Panel.h>
#import <appkit/TextField.h>
#import <appkit/Button.h>
}
extern "C"
{
#import <appkit/publicWraps.h>
#import <objc/error.h>
#import <objc/NXStringTable.h>
#import <strings.h>
}
// The C++ "linkage" directive serves two purposes (when importing
// interface files that contain straight ANSI-C/Objective-C code). It:
//
// (a) allows you to link with libraries that have not been compiled with
// the C++ compiler. Since libraries on the NeXT computer are compiled
// with the Objective-C compiler (cc, not cc++), you must use the C++
// linkage directive when importing interface files that represent NeXT
// libraries (or any library that is not compiled with cc++).
//
// (b) tells the compiler to ignore C++ keywords that will result in
// syntax errors when importing ANSI-C/Objective-C interface files.
// The linkage directive essentially tells the C++ compiler to treat
// keywords (such as "new", "delete", etc.) as normal identifiers.
#import "SimpleCalc.h"
#import "CalcEngine.h"
#import "InfoManager.h"
@implementation SimpleCalc
// Initialize an instance of the SimpleCalc class. One instance variable of
// that class is the C++ calculator engine.
- init
{
cplus_object = new CalcEngine; // new is a keyword in C++.
previousAction = 0;
return self;
}
// Append a new digit entered by the user to the text field display.
- appendToDisplay:(const char *)theDigit
{
char *copyOfDisplay = NXCopyStringBuffer([display stringValue]);
[display setStringValue: strcat(copyOfDisplay, theDigit)];
return self;
}
// We need to keep a history of one action to make decisions about the display.
- registerAction:(SEL)action
{
previousAction = action;
return self;
}
// The user has pushed the decimal key on the calculator.
- decimalKey:sender
{
if (previousAction == @selector(operationKeys:))
[display setStringValue:"."];
else {
if (strchr([display stringValue], '.'))
NXBeep();
else
[self appendToDisplay:"."];
}
return [self registerAction:_cmd];
}
// One of the number keys was selected by the user.
- numberKeys:sender
{
char aDigit[2];
int digit = [sender selectedTag];
sprintf(aDigit, "%d", digit);
if (previousAction == @selector(operationKeys:) ||
previousAction == @selector(equalsKey:))
{
[display setStringValue:aDigit];
} else {
if ([display doubleValue] == 0 && !strchr([display stringValue], '.'))
[display setStringValue:aDigit];
else
[self appendToDisplay:aDigit];
}
return [self registerAction:_cmd];
}
// The user pressed the equals key on the calculator interface.
- equalsKey:sender
{
if (previousAction == 0)
NXBeep();
else {
NX_DURING
[display setDoubleValue:
cplus_object->equalsKey([display doubleValue])];
NX_HANDLER
NXRunAlertPanel(
[myNXStringTable valueForStringKey:"operationFailed"],
[myNXStringTable valueForStringKey:NXLocalHandler.data1],
[myNXStringTable valueForStringKey:"OK"], NULL, NULL);
NX_ENDHANDLER
}
return [self registerAction:_cmd];
}
// The user pressed one of the operation keys.
- operationKeys:sender
{
if (previousAction == 0)
NXBeep();
else if (previousAction == @selector(operationKeys:))
cplus_object->setOperation([sender selectedTag]);
else {
NX_DURING
[display setDoubleValue:
cplus_object->operationKeys([sender selectedTag],
[display doubleValue])];
NX_HANDLER
NXRunAlertPanel(
[myNXStringTable valueForStringKey:"operationFailed"],
[myNXStringTable valueForStringKey:NXLocalHandler.data1],
[myNXStringTable valueForStringKey:"OK"], NULL, NULL);
NX_ENDHANDLER
}
return [self registerAction:_cmd];
}
// User pressed the Clear key.
- clearKey:sender
{
[display setStringValue:"0"];
return self;
}
// User pressed the Clear All key.
- clearAllKey:sender
{
cplus_object->clear();
[self registerAction:0];
return [self clearKey:sender];
}
// Called just after the application initializes and starts up.
- appDidInit:sender
{
// Set the Enter key on the keypad to be equivalent to the = key.
[[display window] addToEventMask:NX_SYMBOLSET];
[enterKey setKeyEquivalent:3];
[[display window] makeKeyAndOrderFront:self];
return self;
}
// Called just before the window closes.
- windowWillClose:sender
{
return [NXApp terminate:self];
}
// Brings up the Info panel. Not done on startup because it's in a separate
// interface file. Saves startup time for the user if we do this when they ask
// for it, and not before.
- infoPanel:sender
{
if(infoManager == nil){
infoManager = [[InfoManager alloc] init];
}
[infoManager orderInfoPanelFront:sender];
return self;
}
// Brings up the Help panel. Not done on startup because it's in a separate
// interface file. Saves startup time for the user if we do this when they ask
// for it, and not before.
- helpPanel:sender
{
if(infoManager == nil){
infoManager = [[InfoManager alloc] init];
}
[infoManager orderHelpPanelFront:sender];
return self;
}
@end

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,382 @@
#! /uns/bin/perl -w
# htmlify-cystic-l-faq: turn text version of cystic-l faq into html
# run like this: htmlify-cystic-l-faq < cystic-l-faq-all
# Ron Trueworthy should put the date on the FAQ.
use English;
use Carp;
use strict;
my @section_name;
my @appendix_name;
my @section_toc;
my @appendix_toc;
my $new_tag = "[NEW]";
if (! -d "faq")
{ die "Can't find faq directory"; }
# Initially undefined
my $appendix;
my $section;
my $subsection;
my $subsubsection;
my $this_file_toc = "";
my %file_tocs;
my @output_files = ();
my $file_index = 0;
my $output_file;
my $line;
while (defined($line = <>))
{
### Message headers
if ($line =~ /^From /)
{ while ($line ne "\n")
{ $line = <>; } }
if ($line =~ /^See PART ONE of this FAQ for/)
{ while (defined($line = <>) && ($line ne "\n"))
{ }
next; }
if ($line =~ /^\s*[-+]+$/)
{ next; }
### File headers
if ($line =~ /^\s*CYSTIC-L Frequently Asked Questions - PART (.*)\n$/)
{ # print "part $1\n";
if ($1 ne "ONE")
{ next; }
if ($output_file)
{ die "output_file shouldn't have been set yet: $output_file"; }
$output_file = "faq/index.html";
open(OUTPUT, ">$output_file") || die "Couldn't open $output_file";
select OUTPUT;
print "<HEAD>
<TITLE>CYSTIC-L FAQ Table of Contents
</TITLE>
</HEAD>
<BODY>
<H1>CYSTIC-L Frequently Asked Questions</H1>
<h2>Knowledge Is Power</h2>
";
next; }
if ($line =~ /^\s*~ Knowledge Is Power ~$/)
{ next; }
### Table of contents
if ($line =~ /^\s*~ FAQ Table of Contents ~$/)
{ read_toc();
print "<hr><a href=\"../\">Info-Zone</a> <a href=\"../../\">CF-WEB</a>\n";
close(OUTPUT);
next;
}
if ($line =~ /^PART /)
{ next; }
if ($line =~ s/^>?APPENDIX ([A-Z])\.\s*//)
{ if (!defined($appendix))
{ if ($1 ne "A")
{ die "First appendix is $1"; } }
elsif ($1 ne chr(ord($appendix)+1))
{ die "Appendix $1 follows Appendix $appendix"; }
file_end();
close(OUTPUT);
$appendix = $1;
$section = undef;
$subsection = undef;
$subsubsection = undef;
$output_file = section_url_base();
open(OUTPUT, "> faq/$output_file") || die "Can't open faq/$output_file";
select OUTPUT;
chomp($line);
print "<title>$line</title>\n<h1>$line</h1>\n";
if (defined($file_tocs{$output_file}) && $file_tocs{$output_file})
{ print "Contents: $file_tocs{$output_file}\n"; }
next; }
if (($line =~ /^>?([0-9]+)\.\s+/) && (!defined($section) || ($1 == $section+1)))
{ $line =~ s/^>?([0-9]+)\.\s+//;
if (!defined($appendix))
{ # should do some more here
if (defined($section))
{ file_end(); }
close(OUTPUT); }
$section = $1;
$subsection = undef;
$subsubsection = undef;
$output_file = section_url_base();
if (!defined($appendix))
{ open(OUTPUT, "> faq/$output_file") || die "Can't open faq/$output_file";
select OUTPUT;
chomp($line);
print "<title>$line</title>\n<h1>$line</h1>\n";
if (defined($file_tocs{$output_file}) && $file_tocs{$output_file})
{ print "Contents: $file_tocs{$output_file}\n"; }
next; }
}
if ($line =~ s/^>?o\s+//)
{ $line =~ s/^>//; # sometimes the > follows the itemization
if (!defined($subsection))
{ $subsection = 1; }
else
{ $subsection++; }
$subsubsection = undef;
print "<h2>", section_name($line), "</h2>\n";
next; }
if ($line =~ s/^>?-\s+//)
{ $line =~ s/^>//; # sometimes the > follows the itemization
if (!defined($subsubsection))
{ $subsubsection = 1; }
else
{ $subsubsection++; }
print "<h3>", section_name($line), "</h3>\n";
next; }
### A paragraph of ordinary text
if ($line !~ /^\s*$/)
{ print "<p>$line";
while (defined($line = <>) && ($line ne "\n"))
{ print $line; }
print "</p>\n";
}
}
file_end();
my $subsection_marker;
my $new;
sub read_toc ()
{ # These variables are initially undefined
if (defined($appendix)
|| defined($section)
|| defined($subsection)
|| defined($subsubsection))
{ die "some value should have been undefined when calling read_toc: `$appendix' `$section' `$subsection' `$subsubsection'"; }
while (defined($line = <>) && $line)
{ if ($line =~ /^\s*$/)
{ next; }
if ($line =~ /^\s*\((Portions updated since.*)>\)\n/)
{ print "$1$new_tag<p>\n";
next; }
if ($line =~ /^PART (.*)$/)
# { if ($MATCH eq "ONE")
# { print ... }
{ next; }
if ($line eq "APPENDICES\n")
{ next; }
if ($line =~ /^\s*INDEX/)
{ next; }
if ($line =~ /^\s*[-+]+$/)
{ finish_appendices();
if (defined($appendix)
|| defined($section)
|| defined($subsection)
|| defined($subsubsection))
{ die "some value should have been undefined when exiting read_toc: `$appendix' `$section' `$subsection' `$subsubsection'"; }
return; }
$new = ($line =~ s/>//);
# # Not sure if this is the right place to do this.
# if (($line !~ /^\s*([-o]|[0-9A-Z]+\.|APPENDIX [A-Z]\.)/)
# && ($line !~ /[ .]*[0-9]+$/))
# { die "What line? $line"; }
while (!($line =~ s/[ .]*[0-9]+$//))
{ $line .= <>; }
chomp($line);
if ($line =~ s/^\s*APPENDIX ([A-Z])\.\s*//)
{ finish_sections();
if (!defined($appendix))
{ if ($1 ne "A")
{ die "First appendix is $1"; }
print "Appendices\n";
print "<ol type=\"A\" start=\"$1\">\n"; }
elsif ($1 ne chr(ord($appendix)+1))
{ die "Appendix $1 follows Appendix $appendix"; }
$appendix = $1;
$appendix_name[ord($appendix)-ord('A')+1] = $line;
my $entry = toc_line($line);
print $entry;
push(@output_files,section_url_base());
next; }
if ($line =~ s/^\s*([0-9]+)\.\s*//)
{ finish_subsections();
if (!defined($section))
{ my $entry = "<ol start=$1>\n";
print $entry;
if (defined($appendix))
{ $this_file_toc .= $entry; } }
elsif ($1 != $section+1)
{ die "Section $1 follows section $section"; }
$section = $1;
$section_name[$section] = $line;
my $entry = " " . toc_line($line);
print $entry;
if (defined($appendix))
{ $this_file_toc .= $entry; }
else
{ push(@output_files,section_url_base()); }
next; }
if ($line =~ s/^\s*o\s+//)
{ if (!defined($subsection))
{ $subsection = 1;
my $entry = " <ul>\n";
print $entry;
$this_file_toc .= $entry;
$subsection_marker = "ul"; }
else
{ finish_subsubsections();
$subsection++; }
my $entry = " " . toc_line($line);
print $entry;
$this_file_toc .= $entry;
next; }
if ($line =~ s/^\s*([A-Z])\.\s+//)
{ finish_subsubsections();
if (!defined($subsection))
{ my $entry = " <ol type=\"A\" start=\"$1\">\n";
print $entry;
$this_file_toc .= $entry;
$subsection_marker = "ol"; }
else
{ if ($1 ne chr(ord($subsection)+1))
{ die "Subsection $1 follows subsection $subsection"; } }
$subsection = $1;
my $entry = " " . toc_line($line);
print $entry;
$this_file_toc .= $entry;
next; }
if ($line =~ s/^\s*-\s+//)
{ if (!defined($subsubsection))
{ $subsubsection = 1;
my $entry = " <ul>\n";
print $entry;
$this_file_toc .= $entry; }
else
{ $subsubsection++; }
my $entry = " " . toc_line($line);
print $entry;
$this_file_toc .= $entry;
next; }
# Itemized line without leading "o" (grrr).
if (!defined($subsection))
{ my $entry = " <ul>\n";
print $entry;
$this_file_toc .= $entry;
$subsection = 1;
$subsection_marker = "ul"; }
else
{ $subsection++; }
$line =~ s/^\s*//;
my $entry = " " . toc_line($line);
$this_file_toc .= $entry;
print $entry;
}
}
sub finish_subsubsections ()
{ if (defined($subsubsection))
{ my $entry = " </ul>\n";
print $entry;
$this_file_toc .= $entry;
$subsubsection = undef; } }
sub finish_subsections ()
{ finish_subsubsections();
if (defined($subsection))
{ my $entry = " </$subsection_marker>\n";
print $entry;
$this_file_toc .= $entry;
$subsection = undef;
if (!defined($appendix))
{ $file_tocs{section_url_base()} = $this_file_toc;
$this_file_toc = ""; } } }
sub finish_sections ()
{ finish_subsections();
if (defined($section))
{ my $entry = " </ol>\n";
print $entry;
if (defined($appendix))
{ $this_file_toc .= $entry;
$file_tocs{section_url_base()} = $this_file_toc;
$this_file_toc = ""; }
$section = undef; } }
sub finish_appendices ()
{ finish_sections();
if (defined($appendix))
{ print "</ol>\n";
$appendix = undef; } }
sub section_url_base ()
{ if (!defined($appendix) && !defined($section))
{ die "undefined appendix and section"; }
return (defined($appendix) ? "app-$appendix.html" : "sec-$section.html"); }
sub section_url_name ()
{ my $sans_subsubsection
= (defined($appendix)
? (defined($section)
? "sec-$section" . (defined($subsection)
? "-$subsection" : "")
: "")
: (defined($subsection) ? "ssec-$subsection" : ""));
if (defined($subsubsection))
{ $sans_subsubsection . "-$subsubsection"; }
else
{ $sans_subsubsection; } }
sub section_url ()
{ my $base = section_url_base();
my $name = section_url_name();
if ($name)
{ return $base . "\#" . $name; }
else
{ return $base; } }
sub section_href ($)
{ my ($text) = @_;
return "<a href=\"" . section_url() . "\">$text</a>"; }
sub section_name ($)
{ my ($text) = @_;
return "<a name=\"" . section_url_name() . "\">$text</a>"; }
sub toc_line ($)
{ return " <LI>" . section_href($line) . ($new ? " $new_tag" : "") . "\n"; }
sub file_end ()
{ print "\n\n<hr>\n"
. (($file_index < $#output_files)
? "<a href=\"$output_files[$file_index+1]\">Next</a> " : "")
. (($file_index > 0)
? "<a href=\"$output_files[$file_index-1]\">Previous</a> " : "")
. "<a href=\"./\">FAQ</a> <a href=\"../\">Info-Zone</a> <a href=\"../../\">CF-WEB</a>\n";
$file_index++; }

View file

@ -0,0 +1,39 @@
#!/usr/bin/perl
sub f1 {
print "f1\n";
}
sub main::f2 {
print "f2\n";
}
package Foo;
sub f3 {
print "f3\n";
}
sub Bar::f4 {
print "f4\n";
}
package Bar;
sub f5 {
print "f5\n";
}
package Foo::Bar;
sub f6 {
print "f6\n";
}
package main;
sub f7 {
print "f7\n";
}
exit 0;
# end of Perl code

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,54 @@
#Yet Another Getopt Routine In Perl
# jgreely@cis.ohio-state.edu, 89/11/1
#usage:
#&getopt("f:bar") ||
# die &usage("script","f:bar","oo","[files ...]");
#
sub getopt {
local($_,$flag,$opt,$f,$r,@temp) = @_;
@temp = split(/(.):/);
while ($#temp >= $[) {
$flag .= shift(@temp);
$opt .= shift(@temp);
}
while ($_ = $ARGV[0], /^-(.)(.*)/ && shift(@ARGV)) {
($f,$r) = ($1,$2);
last if $f eq '-';
if (index($flag,$f) >= $[) {
eval "\$opt_$f++;";
$r =~ /^(.)(.*)/,redo if $r ne '';
}elsif (index($opt,$f) >= $[) {
$r = $r eq '' ? shift(@ARGV) : $r;
eval "\$opt_$f = \$r;";
}else{
print STDERR "Unrecognized switch \"-$f\".\n";
return 0;
}
}
return 1;
}
#usage: usage:
# &usage(progname,arglist,@names,@last);
#ex:
# &usage("script","f:bar","oo","[file ...]");
#would return
# "usage: script [-f oo] [-bar] [file ...]"
#
sub usage {
local($prog,$_,@list) = @_;
local($string,$flag,@string,@temp,@last) = ();
@temp = split(/(.):/);
push(@string,"usage:",$prog);
while ($#temp >= $[) {
if (($flag = shift(@temp)) ne '') {
push(@string,"[-$flag]");
}
if (($flag = shift(@temp)) ne '') {
push(@string,sprintf("[-%s %s]",$flag,shift(@list)));
}
}
push(@string,@list) if $#list >= $[;
return join(' ',@string) . "\n";
}
1;

View file

@ -0,0 +1,699 @@
<?php
if(!defined("LCE_FUNCTIONS"))
{
define("LCE_FUNCTIONS", 1);
include("base.php");
include("lce_config.php");
// Unknown line class
define("LCE_UNKNOWN", 0);
// pure whitespace
define("LCE_WS", 1);
// a unqualified comment
define("LCE_COMMENT", 2);
// a user/translator comment
define("LCE_COMMENT_USER", 3);
// a tool-generated comment
define("LCE_COMMENT_TOOL", 4);
// A line containing a MSGID
define("LCE_MSGID", 5);
// A line containing a MSGSTR
define("LCE_MSGSTR", 6);
// A quoted text string
define("LCE_TEXT", 7);
define("STATE_ABORT", 0);
define("STATE_OK", 1);
define("STATE_LOOP", 2);
class POEntryAD extends AD
{
function validate($value)
{
// print '"<pre>' . $value . '"<br></pre>';
$result = AD::validate(trim($value));
//return $result;
if($result[0])
{
$lines = explode("\n", ereg_replace("\r", "", $result[1]));
//$lines = explode("\n", $result[1]);
/* print "<pre>";
print_r($lines);
print "</pre>";*/
$res = array();
for($i = 0; $i < count($lines); $i++)
{
if(trim($lines[$i]) != "")
$res[] = $lines[$i];
}
$result[1] = join("\n", $res);
/* print "<pre>";
print_r($result[1]);
print "</pre>";*/
$result[0] = $this->checkQuotation($result[1]);
}
return $result;
}
function checkQuotation($str)
{
$rex = "\\\\n|\\\\t|\\\\r|\\\\\"";
$str = ereg_replace($rex, "", $str);
$str = ereg_replace("\\\\\\\\", "", $str);
return !(strstr($str, "\"")
|| strstr($str, "\\"));
}
}
class CommentAD extends AD
{
var $prefix;
function CommentAD(
$name, // the name of the variable
$not_null = 0,
$type = "", // as returned by gettype
$prefix = "# ")
{
$this->prefix = $prefix;
AD::AD($name, $not_null, $type);
}
function validate($value)
{
$res = AD::validate($value);
return $res;
if($res[0] && $res[1] != "")
{
$mod_lines = array();
$lines = explode("\n", $res[1]);
for($i = 0; $i < count($lines); $i++)
{
$line = $lines[$i];
if(substr($line, 0, 1) != "#")
$line = $this->prefix . $line;
$mod_lines[] = $line;
}
$res[1] = join("\n", $mod_lines);
}
return $res;
}
}
class POEntry extends HtmlValidator
{
var $msgid;
var $msgstr;
var $user_comment;
var $sys_comment;
var $unk_comment;
var $msgid_lc = 0;
var $msgstr_lc = 0;
var $user_comment_lc = 0;
var $sys_comment_lc = 0;
var $unk_comment_lc = 0;
function POEntry()
{
$this->atts = array(
new AD("msgid"),
new POEntryAD("msgstr", REQUIRED_ATTRIBUTE),
new CommentAD("user_comment"),
new POEntryAD("sys_comment"),
new POEntryAD("unk_comment"),
new AD("msgid_lc", NOT_REQUIRED_ATTRIBUTE, 0),
new AD("msgstr_lc", NOT_REQUIRED_ATTRIBUTE, 0),
new AD("user_comment_lc", NOT_REQUIRED_ATTRIBUTE, 0),
new AD("sys_comment_lc", NOT_REQUIRED_ATTRIBUTE, 0),
new AD("unk_comment_lc", NOT_REQUIRED_ATTRIBUTE, 0)
);
}
function lineCount($entry)
{
$lc = count(explode("\n", $entry));
return $lc;
}
function serializeToVars($prefix)
{
$this->user_comment_lc = $this->lineCount($this->user_comment);
$this->unk_comment_lc = $this->lineCount($this->sys_comment);
$this->sys_comment_lc = $this->lineCount($this->unk_comment);
$this->msgid_lc = $this->lineCount($this->msgid);
$this->msgstr_lc = $this->lineCount($this->msgstr);
return HtmlValidator::serializeToVars($prefix);
}
function write()
{
$content = "";
$content .= $this->user_comment . "\n";
$content .= $this->unk_comment . "\n";
$content .= $this->sys_comment . "\n";
$content .= "msgid \"" . $this->msgid . "\"\n";
$content .= 'msgstr "' . join("\"\n\"", explode("\n", $this->msgstr)) . "\"" . "\n\n";
return $content;
}
}
class POReader extends HTMLValidator
{
var $msgid;
var $msgstr;
var $user_comment;
var $sys_comment;
var $unk_comment;
var $state;
var $ignore_ws;
var $po_entries;
var $poe_num;
var $filename;
var $domain;
function gettext($msgid)
{
if(isset($this->po_entries[$msgid]))
{
$po = $this->po_entries[$msgid];
return StripCSlashes(join("", explode("\n", $po->msgstr)));
//return $po->msgstr;
}
return $msgid;
}
function parseFromVars($prefix)
{
$res = HtmlValidator::parseFromVars($prefix);
if($res[0])
{
$poe_res = true;
$this->po_entries = array();
for($i = 0; $i < $this->poe_num; $i++)
{
$poe = new POEntry;
$res = $poe->parseFromVars($prefix . "_POE$i");
if($res[0])
{
$msgid = $prefix . "_POE" . $i . "_MSGID";
$msgid = $$msgid;
$this->po_entries[$prefix . "_POE" . $i . "_MSGID"] = $res[1];
}
else
$poe_res = false;
}
}
if(!$poe_res)
$GLOBALS[$prefix . "_ERR"] = 1;
return array($poe_res, $this);
}
function serializeToVars($prefix)
{
HtmlValidator::serializeToVars($prefix);
reset($this->po_entries);
$i = 0;
while($poe = each($this->po_entries))
{
$poe = $poe[1];
$poe->serializeToVars($prefix . "_POE$i");
$i++;
}
}
function POReader($domain, $filename)
{
$this->domain = $domain;
$this->filename = $filename;
$this->ignore_ws = true;
$this->po_entries = array();
$this->atts = array(
new AD("domain", REQUIRED_ATTRIBUTE),
new AD("filename", REQUIRED_ATTRIBUTE),
new AD("poe_num", REQUIRED_ATTRIBUTE, 0)
);
}
function read()
{
if($fh = fopen($this->filename, "r"))
{
$this->lines = array();
while (!feof ($fh))
{
$line = fgets($fh, 4096);
$this->lines[] = $line;
}
fclose($fh);
}
$this->createPOEntries();
$this->poe_num = count($this->po_entries);
}
function write($save="yes")
{
reset($this->po_entries);
$content = "";
while($poe = each($this->po_entries))
{
$poe = $poe[1];
$content .= $poe->write();
}
if(($fh = fopen($this->filename, "w"))
&& $save == "yes")
{
fwrite($fh, $content);
}
return $content;
}
function isComment($class)
{
if($class == LCE_COMMENT || $class == LCE_COMMENT_USER || $class == LCE_COMMENT_TOOL)
return true;
return false;
}
function comment($line, $class)
{
if($this->isComment($class))
{
if($class == LCE_COMMENT_USER)
$this->user_comment .= $line;
else if($class == LCE_COMMENT_TOOL)
$this->sys_comment .= $line;
else
$this->unk_comment .= $line;
return STATE_OK;
}
if($class == LCE_MSGID)
{
$this->state = "msgid";
return STATE_LOOP;
}
return STATE_ABORT;
}
function msgid($line, $class)
{
if($class == LCE_MSGID || $class == LCE_TEXT)
{
$line = $this->stripLine($line, LCE_MSGID);
$this->msgid .= $line;
return STATE_OK;
}
if($class == LCE_MSGSTR)
{
$this->state = "msgstr";
return STATE_LOOP;
}
return STATE_ABORT;
}
function msgstr($line, $class)
{
if($class == LCE_MSGSTR || $class == LCE_TEXT)
{
$line = $this->stripLine($line, $class);
$this->msgstr .= $line;
return STATE_OK;
}
// We have a different state, so we have to create a POEntry
$poe = new POEntry;
$poe->user_comment = trim($this->user_comment);
$poe->sys_comment = trim($this->sys_comment);
$poe->unk_comment = trim($this->unk_comment);
$poe->msgid = trim($this->msgid);
$poe->msgstr = trim($this->msgstr);
$this->po_entries[trim($this->msgid)] = $poe;
$this->state = "start";
return STATE_LOOP;
}
function start($line, $class)
{
$this->user_comment = "";
$this->sys_comment = "";
$this->unk_comment = "";
$this->msgid = "";
$this->msgstr = "";
if($this->isComment($class))
{
$this->state = "comment";
return STATE_LOOP;
}
if($class == LCE_MSGID)
{
$this->state = "msgid";
return STATE_LOOP;
}
return STATE_OK;
}
function createPOEntries()
{
$this->msgid = "";
$this->msgstr = "";
$this->user_comment = "";
$this->sys_comment = "";
$this->state = "start";
reset($this->lines);
for($i = 0; $i < count($this->lines); $i++)
{
$line = $this->lines[$i];
$class = $this->classifyLine($line);
if($class != LCE_WS || !$this->ignore_ws)
{
$state_ret = STATE_LOOP;
while($state_ret == STATE_LOOP)
{
$state = $this->state;
//print "$this->state $class:$line <br>";
$state_ret = $this->$state($line, $class);
}
//print "state_ret = $state_ret <br>";
}
if($state_ret == STATE_ABORT)
break;
}
// Get the last entry
if($state_ret != STATE_ABORT)
{
$this->msgstr("", LCE_UNKNOWN);
}
}
function stripLine($line, $class)
{
switch($class)
{
case LCE_TEXT:
ereg('^"(.*)"', $line, $regs);
$line = $regs[1] . "\n";
break;
case LCE_MSGID:
if(substr($line, strlen("msgid")) == "msgid")
{
$line = substr($line, strlen("msgid") + 1);
}
ereg('"(.*)"', $line, $regs);
$line = $regs[1];
break;
case LCE_MSGSTR:
// TODO: Check if ^ can be removed
$line = substr($line, strlen("msgstr") + 1);
ereg('^"(.*)"', $line, $regs);
$line = $regs[1] . "\n";
break;
}
return $line;
}
function printClassification()
{
reset($this->lines);
for($i = 0; $i < count($this->lines); $i++)
{
$line = $this->lines[$i];
$class = $this->classifyLine($line);
print "#$i: $class $line<br>";
}
}
function classifyLine($line)
{
if(ereg("^[ \n\r\t]*$", $line))
return LCE_WS;
if(ereg("^#.*\$", $line))
{
if(ereg("^[,:-~].*", substr($line, 1)))
{
return LCE_COMMENT_TOOL;
}
if(ereg("^[ \n\r\t].*", substr($line, 1)))
{
return LCE_COMMENT_USER;
}
return LCE_COMMENT;
}
if(ereg("^msgid (.*)\$", $line, $regs))
{
$line = $regs[1];
if($this->classifyLine($line) == LCE_TEXT)
return LCE_MSGID;
}
if(ereg("^msgstr (.*)\$", $line, $regs))
{
$line = $regs[1];
if($this->classifyLine($line) == LCE_TEXT)
return LCE_MSGSTR;
}
if(ereg('^".*"', $line))
{
// TODO: Check correct escapes
return LCE_TEXT;
}
return LCE_UNKNOWN;
}
}
function getTextDomains($lines)
{
$default_domain = "";
$domains = array();
while($gl = each($GLOBALS))
{
$gname = $gl[0];
global $$gname;
}
for($i = 0; $i < count($lines); $i++)
{
if(ereg("bindtextdomain\(([^,]+),([^\)]+)\)", $lines[$i], $regs))
{
//print "Line:" . $lines[$i] . " <br>";
$name = $regs[1];
$ev = "\$directory = ". $regs[2] . ";";
print $ev;
eval($ev);
$domains[] = array($name, $directory);
}
if(ereg("textdomain\(([^\)]+)\)", $lines[$i], $regs))
$default_domain = $regs[1];
}
return array($default_domain, $domains);
}
class PORManager extends HtmlValidator
{
var $por_a;
function PORManager()
{
$this->por_a = array();
}
function addPOReader($d_name, &$por)
{
$this->por_a[$d_name] = &$por;
}
function &getPOReader($domain)
{
return $this->por_a[$domain];
}
function getDomainNames()
{
return array_keys($this->por_a);
}
}
function &loadPORManager()
{
global $LCE_PORMAN;
if(!isset($LCE_PORMAN))
{
$LCE_PORMAN = new PORManager();
}
return $LCE_PORMAN;
}
// More or less intelligent filename joining
// As available in PYTHONs os.path
function fileJoin()
{
$numargs = func_num_args();
$args = func_get_args();
for($i = 0; $i < $numargs - 1; $i++)
{
if(substr($args[$i], -1) != "/")
$args[$i] = $args[$i] . "/";
if($i > 0)
{
if(substr($args[$i],0 , 1) == "/")
$args[$i] = substr($args[$i], 1);
}
}
return join("", $args);
}
if(defined("LCE_TESTSERVER"))
{
function lce_bindtextdomain($d_name, $d_path)
{
global $LANG, $LC_MESSAGES, $LC_ALL, $LCE_LANG;
global $LCE_ERR;
global $LCE_PO_SUFFIX;
global $LCE_MANAGER;
$path_orig = $d_path;
// This is not complete and reflects
// my not very far going understanding of the
// different $LC_x thingies.
if(isset($LC_MESSAGES))
{
//print "LC_MESSAGES<br>";
$lang_suffix = $LC_MESSAGES;
}
else if(isset($LC_ALL))
{
//print "LC_ALL<br>";
$lang_suffix = $LC_ALL;
}
else if(isset($LANG))
{
//print "LANG<br>";
$lang_suffix = $LANG;
}
else
{
//print "LCE_LANG<br>";
$lang_suffix = $LCE_LANG;
}
//print "LangSuffix: $lang_suffix \n";
//print "D_Path: " . fileJoin($d_path, $lang_suffix, "LC_MESSAGES", $d_name . $LCE_PO_SUFFIX) . "<br>";
// First try: the whole lang_suffix
if(file_exists(fileJoin($d_path, $lang_suffix, "LC_MESSAGES", $d_name . $LCE_PO_SUFFIX)))
$d_path = fileJoin($d_path, $lang_suffix, "LC_MESSAGES", $d_name . $LCE_PO_SUFFIX);
else
{
$lang_suffix = substr($lang_suffix, 0, 2);
if(file_exists(fileJoin($d_path, $lang_suffix, "LC_MESSAGES", $d_name. $LCE_PO_SUFFIX)))
$d_path = fileJoin(fileJoin($d_path, $lang_suffix, "LC_MESSAGES", $d_name . $LCE_PO_SUFFIX));
else
{
$LCE_ERR = "No PO-file found";
return false;
}
}
//print "D_Path: $d_path \n";
$por = new POReader($d_name, $d_path, $path_orig);
$por->read();
$porman =& loadPORManager();
$porman->addPOReader($d_name, $por);
return true;
}
function lce_textdomain($domain)
{
global $LCE_DOMAIN;
$LCE_DOMAIN = $domain;
}
function lce_gettext($msgid)
{
global $LCE_DOMAIN;
return lce_dgettext($LCE_DOMAIN, $msgid);
}
function lce_dgettext($domain, $msgid)
{
$porman =& loadPORManager();
if($por = &$porman->getPOReader($domain))
return $por->gettext($msgid);
return $msgid;
}
function lce()
{
global $LCE_LCEDITLOC;
$porman =& loadPORManager();
$domains = $porman->getDomainNames();
for($i = 0; $i < count($domains); $i++)
{
$por =& $porman->getPOReader($domains[$i]);
$domain = "domain=" . urlencode($por->domain);
$filename = "filename=" . urlencode($por->filename);
$url = $LCE_LCEDITLOC . "?" . $domain . "&" . $filename;
print "<a target=\"_blank\" href=\"" . $url . "\">Domain: $por->domain</a><br>";
}
}
}
else
{
function lce_bindtextdomain($domain, $path)
{
bindtextdomain($domain, $path);
}
function lce_textdomain($domain)
{
textdomain($domain);
}
function lce_gettext($msgid)
{
return gettext($msgid);
}
function lce_dgettext($domain, $msgid)
{
return dgettext($domain, $msgid);
}
function lce()
{
}
}
function lce_geteditcode($type, $name, $text, $rows=2)
{
global $LCE_EDIT_LEVEL;
$level_map = array("msgid" => 4,
"sys_comment" => 3,
"user_comment" => 2,
"msgstr" => 1
);
if($level_map[$type] > $LCE_EDIT_LEVEL)
{
return "<input type=\"hidden\" name=\"" . $name . "\" value=\"" . $text . "\"><pre>\n" . $text . "\n</pre>";
}
else
{
return "<textarea name=\"" . $name . "\" rows=\"" . $rows . "\" cols=\"60\">" . $text . "</textarea>";
}
}
}
/*
;;; Local Variables: ***
;;; mode:C ***
;;; End: ***
*/
?>

View file

@ -0,0 +1,18 @@
define("TEST", 0);
class
test
extends base
{
// use --member to tag
var $member;
var $memassign="hallo";
var $memassign_space ="hallo";
// Syntactical wrong, but tagged
var $test
}
function
foo()
{
}

View file

@ -0,0 +1,527 @@
<?php
/*
Classe creata da Santoro Diego.
Per aiuti nella programmazione in PHP, PERL, C e ECMAScript contattatemi
e-Mail vincenza.tralice@tiscali.it oppure santoro.diego@3000.it
La classe ? ancora in fase beta.
*/
final class sendMail {
const eMailAddressErrorMessage="L' e-Mail indicata non rispetta un formato valido.";
const defaultSubject="this is the subject.";
const defaultTextMessage="this is text message.";
const defaultHtmlMessage="this is html message.";
const defaultHeaderMessage="this is a multi-part message in MIME format.";
private static $messageProperties=array(
"charset" => array(
"modifiable" => true,
"values" => array(
"iso-8859-1",
"iso-8859-15",
"utf-8",
"utf-16"
)
),
"content-transfer-encoding" => array(
"modifiable" => true,
"values" => array(
"7bit",
"8bit",
"quoted-printable"
)
)
);
private $attachmentProperties=array(
"content-type" => array(
"modifiable" => false,
"values" => array(
"application/octet-stream"
)
),
"content-transfer-encoding" => array(
"modifiable" => false,
"values" => array(
"base64"
)
),
"content-disposition" => array(
"modifiable" => true,
"values" => array(
"attachment",
"inline"
)
)
);
private static $relatedProperties=array(
"content-transfer-encoding" => array(
"modifiable" => false,
"values" => array(
"base64"
)
)
);
private $html;
private $text;
private $related;
private $attachments;
public static function valid_eMailAddress($eMailAddress) {
if(ereg("^[^@ ]+@[^@ ]+\.[^@ ]+$", $eMailAddress))
return true;
else
return false;
}
public static function validContentId($contentId) {
if(ereg("^[a-zA-Z0-9]+$", $contentId))
return true;
else
return false;
}
public static function validContentKey($contentKey) {
if(ereg("^[a-zA-Z0-9]+$", $contentKey))
return true;
else
return false;
}
public static function mime_content_type($filename) {
$mime=array(
'.3dmf' => 'x-world/x-3dmf',
'.a' => 'application/octet-stream',
'.aab' => 'application/x-authorware-bin',
'.xwd' => 'image/x-xwd',
'.xyz' => 'chemical/x-pdb',
'.z' => 'application/x-compressed',
'.zip' => 'application/x-zip-compressed',
'.zoo' => 'application/octet-stream',
'.zsh' => 'text/x-script.zsh',
'.css' => 'text/css'
);
return $mime[strrchr($filename, '.')];
}
private $from;
private $to;
private $subject;
private $finalized;
private $headerMessage;
private $bodyMessage;
private $boundaries;
public function __construct($from, $to, $subject=self::defaultSubject) {
// set from
if(!self::valid_eMailAddress($from))
die(self::eMailAddressErrorMessage);
else
$this->from=$from;
// set to
if(!self::valid_eMailAddress($to))
die(self::eMailAddressErrorMessage);
else
$this->to=$to;
// set subject
$this->subject=$subject;
// set text
$this->text=array(
"message" => self::defaultTextMessage,
"properties" => array(
"charset" => self::$messageProperties["charset"]["values"][0],
"content-transfer-encoding" => self::$messageProperties["content-transfer-encoding"]["values"][0]
)
);
// set html
$this->html=array(
"message" => self::defaultHtmlMessage,
"properties" => array(
"charset" => self::$messageProperties["charset"]["values"][0],
"content-transfer-encoding" => self::$messageProperties["content-transfer-encoding"]["values"][1]
)
);
// set related and attachments
$this->related=array();
$this->attachments=array();
// set finalizater counter
$this->finalized=false;
$this->headerMessage="";
$this->bodyMessage="";
$this->boundaries=array(
"multipart/alternative" => md5(uniqid(microtime())),
"multipart/related" => md5(uniqid(microtime())),
"multipart/mixed" => md5(uniqid(microtime()))
);
}
public function setTo($to, &$errorString) {
if(self::valid_eMailAddress($to)) {
$this->to=$to;
return true;
} else {
$errorString=eMailAddressErrorMessage;
return false;
}
}
public function setFrom($from, &$errorString) {
if(self::valid_eMailAddress($from)) {
$this->from=$from;
return true;
} else {
$errorString=eMailAddressErrorMessage;
return false;
}
}
public function setSubject($subject=self::defaultSubject) {
$this->subject=$subject;
}
public function setTextMessage($textMessage=self::defaultTextMessage) {
$this->text["message"]=$textMessage;
}
public function setTextMessageProperty($key, $value, &$errorString) {
$key=strtolower($key);
$value=strtolower($value);
if(isset(self::$messageProperties[$key])) {
if(in_array($value, self::$messageProperties[$key]["values"])) {
if(self::$messageProperties[$key]["modifiable"]) {
$this->text["properties"][$key]=$value;
return true;
} else {
$errorString="Il valore della propriet? indicata non ? modificabile.";
return false;
}
} else {
$errorString="Il valore indicato per questa propriet? non ? valido.";
return false;
}
} else {
$errorString="Non esiste questa propriet? per i messaggi html.";
return false;
}
}
public function setHtmlMessage($htmlMessage=self::defaultHtmlMessage) {
$this->html["message"]=$htmlMessage;
}
public function setHtmlMessageProperty($key, $value, &$errorString) {
$key=strtolower($key);
$value=strtolower($value);
if(isset(self::$messageProperties[$key])) {
if(in_array($value, self::$messageProperties[$key]["values"])) {
if(self::$messageProperties[$key]["modifiable"]) {
$this->html["properties"][$key]=$value;
return true;
} else {
$errorString="Il valore della propriet? indicata non ? modificabile.";
return false;
}
} else {
$errorString="Il valore indicato per questa propriet? non ? valido.";
return false;
}
} else {
$errorString="Non esiste questa propriet? per i messaggi html.";
return false;
}
}
public function addRelated($fileName, $relatedKey, $contentId, &$errorString) {
if(is_file($fileName)) {
if($fileHandle=fopen($fileName, "r")) {
if(self::validContentId($contentId)) {
if(!isset($this->related[$relatedKey])) {
if(self::validContentKey($relatedKey)) {
$this->related[$relatedKey]=array(
"fileName" => basename($fileName),
"properties" => array(
"content-type" => self::mime_content_type($fileName),
"content-transfer-encoding" => self::$relatedProperties["content-transfer-encoding"]["values"][0],
"content-id" => $contentId
),
"source" => base64_encode(
fread($fileHandle, filesize($fileName))
)
);
return true;
} else {
$errorString="L' id specificato non ? valido.";
return false;
}
} else {
$errorString="La chiave specificata ? gi? associata ad un altro related.";
return false;
}
} else {
$errorString="La chiave specificata per il related non ? valida.";
return false;
}
} else {
$errorString="Non ? possibile aprire il file indicato.";
return false;
}
} else {
$errorString="Il nome del file indicato non ? valido.";
return false;
}
}
public function setRelatedProperty($relatedKey, $key, $value, &$errorString) {
$key=strtolower($key);
$value=strtolower($value);
if(isset(self::$relatedProperties[$key])) {
if(in_array($value, self::$relatedProperties[$key]["values"])) {
if(self::$relatedProperties[$key]["modifiable"]) {
if(isset($this->related[$relatedKey])) {
$this->related[$relatedKey]["properties"][$key]=$value;
return true;
} else {
$errorString="Il related indicato non esiste.";
return false;
}
} else {
$errorString="Il valore della propriet? indicata non ? modificabile.";
return false;
}
} else {
$errorString="Il valore indicato per questa propriet? non ? valido.";
return false;
}
} else {
$errorString="Non esiste questa propriet? per i related.";
return false;
}
}
public function addAttachment($fileName, $attachmentKey, &$errorString) {
if(is_file($fileName)) {
if($fileHandle=fopen($fileName, "r")) {
if(self::validContentKey($attachmentKey)) {
if(!isset($this->attachments[$attachmentKey])) {
$this->attachments[$attachmentKey]=array(
"fileName" => basename($fileName),
"properties" => array(
"content-type" => self::$attachmentProperties["content-type"]["values"][0],
"content-disposition" => self::$attachmentProperties["content-disposition"]["values"][0],
"content-transfer-encoding" => self::$attachmentProperties["content-transfer-encoding"]["values"][0]
),
"source" => base64_encode(
fread($fileHandle, filesize($fileName))
)
);
return true;
} else {
$errorString="La chiave specificata ? gi? associata ad un altro allegato.";
return false;
}
} else {
$errorString="La chiave specificata per l'allegato non ? valida.";
return false;
}
} else {
$errorString="Non ? possibile aprire il file indicato.";
return false;
}
} else {
$errorString="Il nome del file indicato non ? valido.";
return false;
}
}
public function setAttachmentProperty($attachmentKey, $key, $value, &$errorString) {
$key=strtolower($key);
$value=strtolower($value);
if(isset(self::$attachmentProperties[$key])) {
if(in_array($value, self::$attachmentProperties[$key]["values"])) {
if(self::$attachmentProperties[$key]["modifiable"]) {
if(isset($this->attachments[$attachmentKey])) {
$this->attachments[$attachmentKey]["properties"][$key]=$value;
return true;
} else {
$errorString="L'allegato indicato non esiste.";
return false;
}
} else {
$errorString="Il valore della propriet? indicata non ? modificabile.";
return false;
}
} else {
$errorString="Il valore indicato per questa propriet? non ? valido.";
return false;
}
} else {
$errorString="Non esiste questa propriet? per gli allegati.";
return false;
}
}
public function finalize(&$errorString) {
if(!$this->finalized) {
$this->headerMessage="from: ".($this->from)."\n";
$this->headerMessage.="to: ".($this->to)."\n";
$this->headerMessage.="subject: ".($this->subject)."\n";
$this->headerMessage.="mime-version: 1.0\n";
if(($countAttachments=count($this->attachments))>0) {
$this->headerMessage.="content-type: multipart/mixed; boundary=\"".($this->boundaries["multipart/mixed"])."\"\n\n";
$this->headerMessage.=self::defaultHeaderMessage;
$this->headerMessage.="\n\n";
$this->bodyMessage="--".($this->boundaries["multipart/mixed"])."\n";
if(($countRelated=count($this->related))>0) {
$this->bodyMessage.="content-type: multipart/related; type=\"multipart/alternative\"; boundary=\"".($this->boundaries["multipart/related"])."\"\n\n";
$this->bodyMessage.="--".($this->boundaries["multipart/related"])."\n";
$this->bodyMessage.="content-type: multipart/alternative; boundary=\"".($this->boundaries["multipart/alternative"])."\"\n\n";
$this->createMultipartAlternativeMessage($this->boundaries["multipart/alternative"]);
$this->bodyMessage.="--".($this->boundaries["multipart/alternative"])."--\n\n";
// aggiungere i related e chiudere
$relatedCounter=0;
while(list($key,)=each($this->related)) {
$relatedCounter++;
$this->bodyMessage.="--".$this->boundaries["multipart/related"]."\n";
$this->createMultipartRelatedMessage($key);
if($relatedCounter!=$countRelated) $this->bodyMessage.="--".($this->boundaries["multipart/related"])."\n";
else $this->bodyMessage.="--".($this->boundaries["multipart/related"])."--\n\n";
}
} else {
$this->bodyMessage.="content-type: multipart/alternative; boundary=\"".($this->boundaries["multipart/alternative"])."\"\n\n";
$this->createMultipartAlternativeMessage();
$this->bodyMessage.="--".($this->boundaries["multipart/alternative"])."--\n\n";
}
$attachmentsCounter=0;
while(list($key,)=each($this->attachments)) {
$attachmentsCounter++;
$this->bodyMessage.="--".($this->boundaries["multipart/mixed"])."\n";
$this->createMultipartMixedMessage($key);
if($attachmentsCounter!=$countAttachments) $this->bodyMessage.="--".($this->boundaries["multipart/mixed"])."\n";
else $this->bodyMessage.="--".($this->boundaries["multipart/mixed"])."--\n\n";
}
} else {
if(($countRelated=count($this->related))>0) {
$this->headerMessage.="content-type: multipart/related; type=\"multipart/alternative\"; boundary=\"".($this->boundaries["multipart/related"])."\"\n\n";
$this->headerMessage.=self::defaultHeaderMessage;
$this->headerMessage.="\n\n";
$this->bodyMessage="--".($this->boundaries["multipart/related"])."\n";
$this->bodyMessage.="content-type: multipart/alternative; boundary=\"".($this->boundaries["multipart/alternative"])."\"\n\n";
$this->createMultipartAlternativeMessage();
$this->bodyMessage.="--".($this->boundaries["multipart/alternative"])."--\n\n";
$relatedCounter=0;
while(list($key,)=each($this->related)) {
$relatedCounter++;
$this->bodyMessage.="--".$this->boundaries["multipart/related"]."\n";
$this->createMultipartRelatedMessage($key);
if($relatedCounter!=$countRelated) $this->bodyMessage.="--".($this->boundaries["multipart/related"])."\n";
else $this->bodyMessage.="--".($this->boundaries["multipart/related"])."--\n\n";
}
} else {
$this->headerMessage.="content-type: multipart/alternative; boundary=\"".($this->boundaries["multipart/alternative"])."\"\n\n";
$this->headerMessage.=self::defaultHeaderMessage;
$this->headerMessage.="\n\n";
$this->createMultipartAlternativeMessage();
$this->bodyMessage.="--".($this->boundaries["multipart/alternative"])."--";
}
}
$this->finalized=true;
return true;
} else {
$errorString="Al momento non ? possibile finalizzare.";
return false;
}
}
private function createMultipartAlternativeMessage() {
$multipartAlternativeBoundary=$this->boundaries["multipart/alternative"];
$this->bodyMessage.="--$multipartAlternativeBoundary\n";
$this->bodyMessage.="content-type: text/plain; charset=\"".($this->text["properties"]["charset"])."\"\n";
$this->bodyMessage.="content-transfer-encoding: ".($this->text["properties"]["content-transfer-encoding"])."\n\n";
$this->bodyMessage.=$this->text["message"];
$this->bodyMessage.="\n\n";
$this->bodyMessage.="--$multipartAlternativeBoundary\n";
$this->bodyMessage.="content-type: text/html; charset=\"".($this->html["properties"]["charset"])."\"\n";
$this->bodyMessage.="content-transfer-encoding: ".($this->html["properties"]["content-transfer-encoding"])."\n\n";
$this->bodyMessage.=$this->html["message"];
$this->bodyMessage.="\n\n";
}
private function createMultipartRelatedMessage($key) {
$obj=$this->related[$key];
$this->bodyMessage.="content-type: ".($obj["properties"]["content-type"])."; name=\"".($obj["fileName"])."\"\n";
$this->bodyMessage.="content-transfer-encoding: ".($obj["properties"]["content-transfer-encoding"])."\n";
$this->bodyMessage.="content-id: <".($obj["properties"]["content-id"]).">\n\n";
$this->bodyMessage.=$obj["source"];
$this->bodyMessage.="\n\n";
}
private function createMultipartMixedMessage($key) {
$obj=$this->attachments[$key];
$this->bodyMessage.="content-type: ".($obj["properties"]["content-type"])."; name=\"".($obj["fileName"])."\"\n";
$this->bodyMessage.="content-transfer-encoding: ".($obj["properties"]["content-transfer-encoding"])."\n";
$this->bodyMessage.="content-disposition: ".($obj["properties"]["content-disposition"])."; filename=\"".($obj["fileName"])."\"\n\n";
$this->bodyMessage.=$obj["source"];
$this->bodyMessage.="\n\n";
}
public function getSource(&$errorString) {
if($this->finalized) {
return ($this->headerMessage).($this->bodyMessage);
} else {
$errorString="Ancora non ? avvenuta la finalizzazione.";
return false;
}
}
public function sendMail(&$errorString) {
if($this->finalized) {
mail($this->to, $this->subject, $this->bodyMessage, $this->headerMessage);
$this->finalized=false;
return true;
} else {
$errorString="Ancora non ? avvenuta la finalizzazione.";
return false;
}
}
}
?>

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,337 @@
/* Copyright(C) 1988, Swedish Institute of Computer Science */
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% File : ORDSETS.PL %
% Author : Lena Flood %
% Updated: 9 September 1988 %
% Purpose: Ordered set manipulation utilities %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
:- module(ordsets, [
is_ordset/1,
list_to_ord_set/2,
ord_add_element/3,
ord_del_element/3,
ord_disjoint/2,
ord_intersect/2,
ord_intersection/3,
ord_intersection/4,
ord_intersection/2,
ord_member/2,
ord_seteq/2,
ord_setproduct/3,
ord_subset/2,
ord_subtract/3,
ord_symdiff/3,
ord_union/3,
ord_union/4,
ord_union/2
]).
% Adapted from shared code written by Richard A O'Keefe.
% In this package, sets are represented by ordered lists with no
% duplicates. Thus {c,r,a,f,t} would be [a,c,f,r,t]. The ordering
% is defined by the @< family of term comparison predicates, which
% is the ordering used by sort/2 and setof/3.
% The benefit of the ordered representation is that the elementary
% set operations can be done in time proportional to the Sum of the
% argument sizes rather than their Product.
% is_ordset(+Set)
% is true when Set is an ordered set.
is_ordset(X) :- var(X), !, fail.
is_ordset([]).
is_ordset([Head|Tail]) :-
is_ordset(Tail, Head).
is_ordset(X, _) :- var(X), !, fail.
is_ordset([], _).
is_ordset([Head|Tail], Left) :-
Left @< Head,
is_ordset(Tail, Head).
% list_to_ord_set(+List, ?Set)
% is true when Set is the ordered representation of the set represented
% by the unordered representation List.
list_to_ord_set(List, Set) :-
sort(List, Set).
% ord_add_element(+Set1, +Element -Set2)
% is true when Set2 is Set1 with Element inserted in it, preserving
% the order.
ord_add_element([], Element, [Element]).
ord_add_element([Head|Tail], Element, Set) :-
compare(Order, Head, Element),
ord_add_element(Order, Head, Tail, Element, Set).
ord_add_element(<, Head, Tail, Element, [Head|Set]) :-
ord_add_element(Tail, Element, Set).
ord_add_element(=, Head, Tail, _, [Head|Tail]).
ord_add_element(>, Head, Tail, Element, [Element,Head|Tail]).
% ord_del_element(+Set1, +Element, ?Set2)
% is true when Set2 is Set1 but with Element removed.
ord_del_element([], _, []).
ord_del_element([Head|Tail], Element, Set) :-
compare(Order, Head, Element),
ord_del_element(Order, Head, Tail, Element, Set).
ord_del_element(<, Head, Tail, Element, [Head|Set]) :-
ord_del_element(Tail, Element, Set).
ord_del_element(=, _, Tail, _, Tail).
ord_del_element(>, Head, Tail, _, [Head|Tail]).
% ord_disjoint(+Set1, +Set2)
% is true when the two ordered sets have no element in common.
ord_disjoint(Set1, Set2) :-
\+ ord_intersect(Set1, Set2).
% ord_intersect(+Set1, +Set2)
% is true when the two ordered sets have at least one element in common.
ord_intersect([Head1|Tail1], [Head2|Tail2]) :-
compare(Order, Head1, Head2),
ord_intersect(Order, Head1, Tail1, Head2, Tail2).
ord_intersect(<, _, [Head1|Tail1], Head2, Tail2) :-
compare(Order, Head1, Head2),
ord_intersect(Order, Head1, Tail1, Head2, Tail2).
ord_intersect(=, _, _, _, _).
ord_intersect(>, Head1, Tail1, _, [Head2|Tail2]) :-
compare(Order, Head1, Head2),
ord_intersect(Order, Head1, Tail1, Head2, Tail2).
% ord_intersection(+Set1, +Set2, ?Intersection)
% is true when Intersection is the intersecton of Set1
% and Set2, provided that Set1 and Set2 are ordered sets.
ord_intersection([], _, []).
ord_intersection([Head1|Tail1], Set2, Intersection) :-
ord_intersection3(Set2, Head1, Tail1, Intersection).
ord_intersection3(<, _, Set1, Head2, Tail2, Intersection) :-
ord_intersection3(Set1, Head2, Tail2, Intersection).
ord_intersection3(=, Head, Tail1, _, Tail2, [Head|Intersection]) :-
ord_intersection(Tail1, Tail2, Intersection).
ord_intersection3(>, Head1, Tail1, _, Set2, Intersection) :-
ord_intersection3(Set2, Head1, Tail1, Intersection).
% could be a disjunction, but is used in three places
ord_intersection3([], _, _, []).
ord_intersection3([Head2|Tail2], Head1, Tail1, Intersection) :-
compare(Order, Head1, Head2),
ord_intersection3(Order, Head1, Tail1, Head2, Tail2, Intersection).
% ord_intersection(+Set1, +Set2, ?Intersection, ?Difference)
% is true when Intersection is the intersection of Set1 and Set2,
% and Differens is Set2 \ Set1 (like in ord_union/4),
% provided that Set1 and Set2 are ordered sets.
ord_intersection([], Set2, [], Set2).
ord_intersection([Head1|Tail1], Set2, Intersection, Difference) :-
ord_intersection4(Set2, Head1, Tail1, Intersection, Difference).
ord_intersection4(<, _, Set1, Head2, Tail2, Intersection, Difference) :-
( Set1 = [], Intersection = [], Difference = [Head2|Tail2]
; Set1 = [Head1|Tail1],
compare(Order, Head1, Head2),
ord_intersection4(Order, Head1, Tail1, Head2, Tail2, Intersection, Difference)
).
ord_intersection4(=, Head, Tail1, _, Tail2, [Head|Intersection], Difference) :-
ord_intersection(Tail1, Tail2, Intersection, Difference).
ord_intersection4(>, Head1, Tail1, Head2, Set2, Intersection, [Head2|Difference]) :-
ord_intersection4(Set2, Head1, Tail1, Intersection, Difference).
ord_intersection4([], _, _, [], []).
ord_intersection4([Head2|Tail2], Head1, Tail1, Intersection, Difference) :-
compare(Order, Head1, Head2),
ord_intersection4(Order, Head1, Tail1, Head2, Tail2, Intersection, Difference).
% ord_intersection(+Sets, ?Intersection)
% is true when Intersection is the ordered set representation of the
% intersection of all the sets in Sets.
ord_intersection(Sets, Intersection) :-
length(Sets, NumberOfSets),
NumberOfSets > 0,
ord_intersection2(NumberOfSets, Sets, Intersection, []).
ord_intersection2(1, [Set|Sets], Set0, Sets0) :- !,
Set = Set0,
Sets = Sets0.
ord_intersection2(2, [Set,Set2|Sets], Intersection, Sets0) :- !,
Sets = Sets0,
ord_intersection2(Set, Set2, Intersection).
ord_intersection2(N, Sets0, Intersection, Sets) :-
% N > 2,
A is N>>1,
Z is N-A,
ord_intersection2(A, Sets0, X, Sets1),
ord_intersection2(Z, Sets1, Y, Sets),
ord_intersection(X, Y, Intersection).
% ord_member(+Elt, +Set)
% is true when Elt is a member of Set. Suggested by Mark Johnson.
ord_member(X, [E|Es]) :-
compare(C, X, E),
ord_member(C, X, Es).
ord_member(=, _X, _Es).
ord_member(>, X, [E|Es]) :-
compare(C, X, E),
ord_member(C, X, Es).
% ord_seteq(+Set1, +Set2)
% is true when the two arguments represent the same set. Since they
% are assumed to be ordered representations, they must be identical.
ord_seteq(Set1, Set2) :-
Set1 == Set2.
% ord_setproduct(+Set1, +Set2, ?SetProduct)
% is true when SetProduct is the cartesian product of Set1 and Set2. The
% product is represented as pairs Elem1-Elem2, where Elem1 is an element
% from Set1 and Elem2 is an element from Set2.
ord_setproduct([], _, []).
ord_setproduct([Head|Tail], Set, SetProduct) :-
ord_setproduct(Set, Head, SetProduct, Rest),
ord_setproduct(Tail, Set, Rest).
ord_setproduct([], _, Set, Set).
ord_setproduct([Head|Tail], X, [X-Head|TailX], Tl) :-
ord_setproduct(Tail, X, TailX, Tl).
% ord_subset(+Set1, +Set2)
% is true when every element of the ordered set Set1 appears in the
% ordered set Set2.
ord_subset([], _).
ord_subset([Head1|Tail1], [Head2|Tail2]) :-
compare(Order, Head1, Head2),
ord_subset(Order, Head1, Tail1, Tail2).
ord_subset(=, _, Tail1, Tail2) :-
ord_subset(Tail1, Tail2).
ord_subset(>, Head1, Tail1, [Head2|Tail2]) :-
compare(Order, Head1, Head2),
ord_subset(Order, Head1, Tail1, Tail2).
% ord_subtract(+Set1, +Set2, ?Difference)
% is true when Difference contains all and only the elements of Set1
% which are not also in Set2, i.e. Set1 \ Set2.
ord_subtract(Set1, Set2, Union) :-
prolog:subtract(Set1, Set2, Union).
% ord_symdiff(+Set1, +Set2, ?Difference)
% is true when Difference is the symmetric difference of Set1 and Set2.
ord_symdiff([], Set2, Set2).
ord_symdiff([Head1|Tail1], Set2, Symdiff) :-
ord_symdiff(Set2, Head1, Tail1, Symdiff).
ord_symdiff(<, Head1, Set1, Head2, Tail2, [Head1|Symdiff]) :-
ord_symdiff(Set1, Head2, Tail2, Symdiff).
ord_symdiff(=, _, Tail1, _, Tail2, Symdiff) :-
ord_symdiff(Tail1, Tail2, Symdiff).
ord_symdiff(>, Head1, Tail1, Head2, Set2, [Head2|Symdiff]) :-
ord_symdiff(Set2, Head1, Tail1, Symdiff).
% could be a disjunction, but is used in three places
ord_symdiff([], Head1, Tail1, [Head1|Tail1]).
ord_symdiff([Head2|Tail2], Head1, Tail1, Symdiff) :-
compare(Order, Head1, Head2),
ord_symdiff(Order, Head1, Tail1, Head2, Tail2, Symdiff).
% ord_union(+Set1, +Set2, ?Union)
% is true when Union is the union of Set1 and Set2. Note that when
% something occurs in both sets, we want to retain only one copy.
ord_union(Set1, Set2, Union) :-
prolog:merge(Set1, Set2, Union).
% ord_union(+Set1, +Set2, ?Union, ?New)
% is true when Union is the union of Set1 and Set2, and New is
% Set2 \ Set1. This is useful if you
% are accumulating members of a set and you want to process new
% elements as they are added to the set.
ord_union([], Set2, Set2, Set2).
ord_union([Head1|Tail1], Set2, Union, Difference) :-
ord_union4(Set2, Head1, Tail1, Union, Difference).
ord_union4(<, Head, Set1, Head2, Tail2, [Head|Union], Difference) :-
( Set1 = [], Union = [Head2|Tail2], Difference = [Head2|Tail2]
; Set1 = [Head1|Tail1],
compare(Order, Head1, Head2),
ord_union4(Order, Head1, Tail1, Head2, Tail2, Union, Difference)
).
ord_union4(=, Head, Tail1, _, Tail2, [Head|Union], Difference) :-
ord_union(Tail1, Tail2, Union, Difference).
ord_union4(>, Head1, Tail1, Head2, Set2, [Head2|Union], [Head2|Difference]) :-
ord_union4(Set2, Head1, Tail1, Union, Difference).
ord_union4([], Head1, Tail1, [Head1|Tail1], []).
ord_union4([Head2|Tail2], Head1, Tail1, Union, Difference) :-
compare(Order, Head1, Head2),
ord_union4(Order, Head1, Tail1, Head2, Tail2, Union, Difference).
% ord_union(+Sets, ?Union)
% is true when Union is the union of all the sets in Sets.
ord_union([], Union) :- !, Union = [].
ord_union(Sets, Union) :-
length(Sets, NumberOfSets),
ord_union_all(NumberOfSets, Sets, Union, []).
ord_union_all(1, [Set|Sets], Set, Sets) :- !.
ord_union_all(2, [Set,Set2|Sets], Union, Sets) :- !,
ord_union(Set, Set2, Union).
ord_union_all(N, Sets0, Union, Sets) :-
A is N>>1,
Z is N-A,
ord_union_all(A, Sets0, X, Sets1),
ord_union_all(Z, Sets1, Y, Sets),
ord_union(X, Y, Union).

2085
test/etags/ps-src/rfc1245.ps Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,819 @@
#!/usr/bin/python
#
# NOTE: THIS PROGRAM DOES NOT WORK!
# It is intended as a regression test source for the Python support in etags.
# If you want a working version, you'll find it in the fetchmail distribution.
#
from Tkinter import *
from Dialog import *
import sys
import time
import os
#
# Define the data structures the GUIs will be tossing around
#
class Controls:
def __init__(self):
self.foreground = FALSE; # Run in background
self.daemon = 300 # Default to 5-minute timeout
self.syslog = FALSE # Use syslogd for logging?
self.logfile = None # No logfile, initially
def __repr__(self):
str = "";
if self.syslog:
str = str + ("set syslog\n")
elif self.logfile:
str = str + ("set logfile \"%s\"\n" % (self.logfile,));
if not self.foreground and self.daemon:
str = str + ("set daemon %s\n" % (self.daemon,))
return str + "\n"
def __str__(self):
return "[Server: " + repr(self) + "]"
class Server:
def __init__(self):
self.pollname = None # Poll label
self.via = None # True name of host
self.active = TRUE # Poll status
self.interval = 0 # Skip interval
self.protocol = 'auto' # Default to auto protocol
self.port = 0 # Port number to use
self.uidl = FALSE # Don't use RFC1725 UIDLs by default
self.auth = "password" # Default to password authentication
self.timeout = 300 # 5-minute timeout
self.envelope = "Received" # Envelope-address header
self.aka = [] # List of DNS aka names
self.dns = TRUE # Enable DNS lookup on multidrop
self.localdomains = [] # Domains to be considered local
self.interface = None # IP address and range
self.monitor = None # IP address and range
self.userlist = [] # List of user entries for site
self.typemap = (
('pollname', 'String'),
('via', 'String'),
('active', 'Boolean'),
('interval', 'Int'),
('protocol', 'String'),
('interval', 'Int'),
('port', 'Int'),
('uidl', 'Boolean'),
('auth', 'String'),
('timeout', 'Int'),
('envelope', 'String'),
# leave aka out
('dns', 'Boolean'),
# leave localdomains out
('interface', 'String'),
('monitor', 'String'))
def dump(self, folded):
str = ""
if self.active: str = str + "poll"
else: str = str + "skip"
str = str + (" " + self.pollname)
if self.via != self.pollname:
str = str + " via " + self.via
if self.protocol != ServerDefaults.protocol:
str = str + " with proto " + self.protocol
if self.port != defaultports[self.protocol]:
str = str + " port " + `self.port`
if self.timeout != ServerDefaults.timeout:
str = str + " timeout " + `self.timeout`
if self.interval != ServerDefaults.interval:
str = str + " interval " + `self.interval`
if self.envelope != ServerDefaults.envelope:
str = str + " envelope " + self.envelope
if self.auth != ServerDefaults.auth:
str = str + " auth " + self.auth
if self.dns != ServerDefaults.dns or self.uidl != ServerDefaults.uidl:
str = str + " and options"
if self.dns != ServerDefaults.dns:
str = str + flag2str(self.dns, 'dns')
if self.uidl != ServerDefaults.uidl:
str = str + flag2str(self.uidl, 'uidl')
if folded: str = str + "\n\t"
else: str = str + " "
if self.aka:
str = str + "aka"
for x in self.aka:
str = str + " " + x
if self.aka and self.localdomains: str = str + " "
if self.localdomains:
str = str + ("localdomains")
for x in self.localdomains:
str = str + " " + x
if (self.aka or self.localdomains):
if folded:
str = str + "\n\t"
else:
str = str + " "
if self.interface: str = str + " interface " + self.interface
if self.monitor: str = str + " monitor " + self.monitor
if (self.interface or self.monitor):
if folded:
str = str + "\n"
if str[-1] == "\t": str = str[0:-1]
return str;
def __repr__(self):
return self.dump(TRUE)
def __str__(self):
return "[Server: " + self.dump(FALSE) + "]"
class User:
def __init__(self):
self.username = "" # Remote username
self.localnames = None # Local names
self.password = "" # Password for mail account access
self.smpthost = 'localhost' # Host to forward to
self.mda = "" # Mail Delivery Agent
self.preconnect = "" # Connection setup
self.postconnect = "" # Connection wrapup
self.keep = FALSE # Keep messages
self.flush = FALSE # Flush messages
self.fetchall = FALSE # Fetch old messages
self.rewrite = TRUE # Rewrite message headers
self.forcecr = FALSE # Force LF -> CR/LF
self.stripcr = FALSE # Strip CR
self.pass8bits = FALSE # Force BODY=7BIT
self.dropstatus = FALSE # Force BODY=7BIT
self.limit = 0 # Message size limit
self.fetchlimit = 0 # Max messages fetched per batch
self.batchlimit = 0 # Max message forwarded per batch
self.typemap = (
('username', 'String')
('folder', 'String')
# leave out localnames
('password', 'String')
('smtphost', 'String')
('preconnect', 'String')
('postconnect', 'String')
('mda', 'String')
('keep', 'Boolean')
('flush', 'Boolean')
('fetchall', 'Boolean')
('rewrite', 'Boolean')
('forcecr', 'Boolean')
('stripcr', 'Boolean')
('pass8bits', 'Boolean')
('dropstatus', 'Boolean')
('limit', 'Int')
('fetchlimit', 'Int')
('batchlimit', 'Int'))
def __repr__(self):
str = ""
str = str + "user " + self.user;
if self.password: str = str + "with password " + self.password
if self.localnames:
str = str + "localnames"
for x in self.localnames:
str = str + " " + x
if (self.keep or self.flush or self.fetchall or self.rewrite or
self.forcecr or self.stripcr or self.pass8bits or self.dropstatus):
str = str + " options"
if self.keep != UserDefaults.keep:
str = str + flag2str(self.keep, 'keep')
if self.flush != UserDefaults.flush:
str = str + flag2str(self.flush, 'flush')
if self.fetchall != UserDefaults.fetchall:
str = str + flag2str(self.fetchall, 'fetchall')
if self.rewrite != UserDefaults.rewrite:
str = str + flag2str(self.rewrite, 'rewrite')
if self.forcecr != UserDefaults.forcecr:
str = str + flag2str(self.forcecr, 'forcecr')
if self.stripcr != UserDefaults.stripcr:
str = str + flag2str(self.stripcr, 'stripcr')
if self.pass8bits != UserDefaults.pass8bits:
str = str + flag2str(self.pass8bits, 'pass8bits')
if self.dropstatus != UserDefaults.dropstatus:
str = str + flag2str(self.dropstatus, 'dropstatus')
if self.limit != UserDefaults.limit:
str = str + " limit " + `self.limit`
if self.fetchlimit != UserDefaults.fetchlimit:
str = str + " fetchlimit " + `self.fetchlimit`
if self.batchlimit != UserDefaults.batchlimit:
str = str + " batchlimit " + `self.batchlimit`
def __str__(self):
return "[User: " + repr(self) + "]"
#
# Helper code
#
defaultports = {"auto":0,
"POP2":109,
"POP3":110, "APOP":110, "KPOP":1109, "IMAP":143,
"IMAP-K4":143,
"ETRN":25}
protolist = ("auto", "POP2", "POP3", "APOP", "KPOP", "IMAP", "IMAP-K4", "ETRN")
authlist = ("password", "kerberos")
def flag2str(value, string):
# make a string representation of a .fetchmailrc flag or negated flag
str = ""
if value != None:
str = str + (" ")
if value == FALSE: str = str + ("no ")
str = str + string;
return str
class LabeledEntry(Frame):
# widget consisting of entry field with caption to left
def bind(self, key, action):
self.E.bind(key, action)
def focus_set(self):
self.E.focus_set()
def __init__(self, Master, text, textvar, width):
Frame.__init__(self, Master)
self.L = Label(self, {'text':text, 'width':width, 'anchor':'w'})
self.E = Entry(self, {'textvar':textvar})
self.L.pack({'side':'left'})
self.E.pack({'side':'left', 'expand':'1', 'fill':'x'})
def ButtonBar(frame, legend, ref, alternatives, command):
# horizontal bar of radio buttons, caption to left, picking from a string list
bar = Frame(frame)
Label(bar, text=legend).pack(side=LEFT)
for alt in alternatives:
Radiobutton(bar,
{'text':alt, 'variable':ref, 'value':alt, 'command':command}).pack(side=LEFT)
bar.pack(side=TOP);
return bar
def helpwin(helpdict):
# help message window with a self-destruct button
helpwin = Toplevel()
helpwin.title(helpdict['title'])
helpwin.iconname(helpdict['title'])
Label(helpwin, text=helpdict['banner']).pack()
textwin = Message(helpwin, text=helpdict['text'], width=600)
textwin.pack()
Button(helpwin, text='Done',
command=lambda x=helpwin: Widget.destroy(x),
relief=SUNKEN, bd=2).pack()
class ListEdit(Frame):
# edit a list of values (duplicates not allowed) with a supplied editor hook
def __init__(self, newlegend, list, editor, master):
self.editor = editor
self.list = list
# Set up a widget to accept new sites
self.newval = StringVar(master)
newwin = LabeledEntry(master, newlegend, self.newval, '16')
newwin.bind('<Double-1>', self.handleNew)
newwin.bind('<Return>', self.handleNew)
newwin.pack(side=TOP, fill=X, anchor=E)
# Create the sitelist for site-configuration selection
listframe = Frame(master)
scroll = Scrollbar(listframe)
listwidget = Listbox(listframe, height=0, selectmode='browse')
if list:
for dnsname in list:
listwidget.insert('end', dnsname)
listframe.pack(side=TOP, expand=YES, fill=BOTH)
listwidget.config(yscrollcommand=scroll.set, relief=SUNKEN)
listwidget.pack(side=LEFT, expand=YES, fill=BOTH)
scroll.config(command=listwidget.yview, relief=SUNKEN)
scroll.pack(side=RIGHT, fill=BOTH)
listwidget.config(selectmode=SINGLE, setgrid=TRUE)
listwidget.bind('<Double-1>', self.handleList);
listwidget.bind('<Return>', self.handleList);
self.listwidget = listwidget
bf = Frame(master);
if self.editor:
Button(bf, text='Edit', command=self.editItem).pack(side=LEFT)
Button(bf, text='Delete', command=self.deleteItem).pack(side=RIGHT)
bf.pack(fill=X)
def handleList(self, event):
self.editItem();
def handleNew(self, event):
item = self.newval.get()
entire = self.listwidget.get(0, self.listwidget.index('end'));
if item and (not entire) or (not item in self.listwidget.get(0, self.listwidget.index('end'))):
self.listwidget.insert('end', item)
if self.list != None: self.list.append(item)
self.newval.set('')
def editItem(self):
index = self.listwidget.curselection()[0]
if index and self.editor:
label = self.listwidget.get(index);
apply(self.editor, (label,))
def deleteItem(self):
index = self.listwidget.curselection()[0]
if index:
self.listwidget.delete(index)
if self.list != None: del self.list[index]
def ConfirmQuit(frame, context):
ans = Dialog(frame,
title = 'Quit?',
text = 'Really quit ' + context + ' without saving?',
bitmap = 'question',
strings = ('Yes', 'No'),
default = 1)
return ans.num == 0
#
# First, code to set the global fetchmail run controls.
#
confighelp = {
'title' : 'Fetchmail configurator help',
'banner': 'Configurator help',
'text' : """
In the `Configurator Controls' panel, you can:
Press `Save' to save the new fetchmail configuration you have created.
Press `Quit' to exit without saving.
Press `Help' to bring up this help message.
In the `Configurator Controls' panel, you can set the following options that
control how fetchmail runs:
Poll interval
Number of seconds to wait between polls in the background.
Ignored if the `Run in Foreground?' option is on.
Logfile
If empty, emit progress and error messages to stderr.
Otherwise this gives the name of the files to write to.
This field is ignored if the "Log to syslog?" option is on.
In the `Remote Mail Configurations' panel, you can:
1. Enter the name of a new remote mail server you want fetchmail to query.
To do this, simply enter a label for the poll configuration in the
`New Server:' box. The label should be a DNS name of the server (unless
you are using ssh or some other tunneling method and will fill in the `via'
option on the site configuration screen).
2. Change the configuration of an existing site.
To do this, find the site's label in the listbox and double-click it.
This will take you to a site configuration dialogue.
"""}
class ControlEdit(Frame):
def PostControls(self):
self.foreground = BooleanVar(self)
self.foreground.set(self.controls.foreground)
self.daemon = StringVar(self)
self.daemon.set(`self.controls.daemon`)
self.syslog = BooleanVar(self)
self.syslog.set(self.controls.syslog);
self.logfile = StringVar(self)
if self.controls.logfile: self.logfile.set(self.controls.logfile);
gf = Frame(self, relief=RAISED, bd = 5)
Label(gf,
text='Fetchmail Run Controls',
bd=2).pack(side=TOP, pady=10)
df = Frame(gf, relief=RAISED, bd=2)
# Run in foreground?
Checkbutton(df,
{'text':'Run in foreground?',
'variable':self.foreground,
'relief':GROOVE}).pack(side=LEFT,anchor=W)
# Set the poll interval
de = LabeledEntry(df, ' Poll interval:', self.daemon, '14')
de.pack(side=RIGHT, anchor=E)
df.pack();
sf = Frame(gf, relief=RAISED, bd=2)
# Use syslog for logging?
Checkbutton(sf,
{'text':'Log to syslog?',
'variable':self.syslog,
'relief':GROOVE}).pack(side=LEFT, anchor=W)
# Set the logfile
log = LabeledEntry(sf, ' Logfile:', self.logfile, '14')
log.pack(side=RIGHT, anchor=E)
sf.pack(fill=X)
gf.pack(fill=X)
def GatherControls(self):
self.controls.daemon = self.daemon.get()
self.controls.foreground = self.foreground.get()
self.controls.logfile = self.logfile.get()
self.controls.syslog = self.syslog.get()
#
# Server editing stuff.
#
serverhelp = {
'title' : 'Server options help',
'banner': 'Server Options',
'text' : """
The server options screen controls fetchmail
options that apply to one of your mailservers.
Once you have a mailserver configuration set
up as you like it, you can select `Save' to
store it in the server list maintained in
the main configuration window.
If you wish to discard changes to a server
configuration, select `Quit'.
"""}
controlhelp = {
'title' : 'Run Control help',
'banner': 'Run Controls',
'text' : """
If the `Poll normally' checkbox is on, the host is polled as part of
the normal operation of fetchmail when it is run with no arguments.
If it is off, fetchmail will only query this host when it is given as
a command-line argument.
The `True name of server' box should specify the actual DNS name
to query. By default this is the same as the poll name.
Normally each host described in the file is queried once each
poll cycle. If `Cycles to skip between polls' is greater than 0,
that's the number of poll cycles that are skipped between the
times this post is actually polled.
The `Server timeout' is the number of seconds fetchmail will wait
for a reply from the mailserver before concluding it is hung and
giving up.
"""}
protohelp = {
'title' : 'Protocol and Port help',
'banner': 'Protocol and Port',
'text' : """
These options control the remote-mail protocol
and TCP/IP service port used to query this
server.
The `Protocol' button bar offers you a choice of
all the different protocols available. The `auto'
protocol is a special mode that probes the host
ports for POP3 and IMAP to see if either is
available.
Normally the TCP/IP service port to use is
dictated by the protocol choice. The `Port'
field lets you set a non-standard port.
"""}
sechelp = {
'title' : 'Security option help',
'banner': 'Security',
'text' : """
These options control the security procedure used
to protect mail transfer
Normally the mail fetch is validated using an
ordinary password logon. If your server speaks
MIT Kerberos IV it is possible to pre-authenticate
the exxchange with a Kerberos ticket.
The `interface' and `monitor' options are available
only for Linux systems. See the fetchmail manual page
for details on these.
"""}
multihelp = {
'title' : 'Multidrop option help',
'banner': 'Multidrop',
'text' : """
These options are only useful with multidrop mode.
See the manual page for extended discussion.
"""}
class ServerEdit(Frame):
def __init__(self, host, sitelist, master=None):
Frame.__init__(self, master)
Pack.config(self)
self.master.title('Fetchmail host ' + host);
self.master.iconname('Fetchmail host ' + host);
self.server = Server()
self.server.pollname = host
self.server.via = host
self.sitelist = sitelist
self.post()
self.createWidgets(host)
def post(self):
# we can't abstract this away, execs would happen in the wrong scope
for x in self.server.typemap:
target = "self." + x[0]
source = "self.server." + x[0]
if x[1] == 'Boolean':
exec target + " = BooleanVar(self)"
if eval(source):
exec target + ".set(" + source + ")"
elif x[1] == 'String':
exec target + " = StringVar(self)"
if eval(source):
exec target + ".set(" + source + ")"
elif x[1] == 'Int':
exec target + " = IntVar(self)"
if eval(source):
exec target + ".set(" + source + ")"
def gather(self):
for x in self.server.typemap:
setattr(self.server, x[0], getattr(self, x[0]).get())
def nosave(self):
if ConfirmQuit(self, 'server option editing'):
Widget.destroy(self.master)
def save(self):
self.gather()
self.sitelist.append(self.server)
Widget.destroy(self.master)
def refreshPort(self):
proto = self.protocol.get()
self.port.set(defaultports[proto])
if not proto in ("POP3", "APOP", "KPOP"): self.uidl = FALSE
def createWidgets(self, host):
topwin = Frame(self, relief=RAISED, bd=5)
Label(topwin, text="Server options for " + host).pack(side=TOP,pady=10)
Button(topwin, text='Save', fg='blue',
command=self.save).pack(side=LEFT)
Button(topwin, text='Quit', fg='blue',
command=self.nosave).pack(side=LEFT)
Button(topwin, text='Help', fg='blue',
command=lambda: helpwin(serverhelp)).pack(side=RIGHT)
topwin.pack(fill=X)
ctlwin = Frame(self, relief=RAISED, bd=5)
Label(ctlwin, text="Run Controls").pack(side=TOP)
Checkbutton(ctlwin, text='Poll ' + host + ' normally?', variable=self.active).pack(side=TOP)
LabeledEntry(ctlwin, 'True name of ' + host + ':',
self.via, '30').pack(side=TOP, fill=X)
LabeledEntry(ctlwin, 'Cycles to skip between polls:',
self.interval, '30').pack(side=TOP, fill=X)
LabeledEntry(ctlwin, 'Server timeout (seconds):',
self.timeout, '30').pack(side=TOP, fill=X)
Button(ctlwin, text='Help', fg='blue',
command=lambda: helpwin(controlhelp)).pack(side=RIGHT)
ctlwin.pack(fill=X)
protwin = Frame(self, relief=RAISED, bd=5)
Label(protwin, text="Protocol and Port").pack(side=TOP)
pb = ButtonBar(protwin, 'Protocol:', self.protocol, protolist, self.refreshPort)
LabeledEntry(protwin, 'TCP/IP service port to query:',
self.port, '30').pack(side=TOP, fill=X)
Checkbutton(protwin,
text="Track seen POP3 messages with client-side UIDL list?",
variable=self.uidl).pack(side=TOP)
Button(protwin, text='Help', fg='blue',
command=lambda: helpwin(protohelp)).pack(side=RIGHT)
protwin.pack(fill=X)
secwin = Frame(self, relief=RAISED, bd=5)
Label(secwin, text="Security").pack(side=TOP)
ButtonBar(secwin, 'Authorization mode:',
self.auth, authlist, None).pack(side=TOP)
if os.popen("uname").readlines()[0] == 'Linux\n':
LabeledEntry(secwin, 'Interface to check before polling:',
self.interface, '30').pack(side=TOP, fill=X)
LabeledEntry(secwin, 'IP addresses to watch for activity:',
self.monitor, '30').pack(side=TOP, fill=X)
Button(secwin, text='Help', fg='blue',
command=lambda: helpwin(sechelp)).pack(side=RIGHT)
secwin.pack(fill=X)
mdropwin = Frame(self, relief=RAISED, bd=5)
Label(mdropwin, text="Multidrop options").pack(side=TOP)
LabeledEntry(mdropwin, 'Envelope address header:',
self.envelope, '30').pack(side=TOP, fill=X)
Checkbutton(mdropwin, text="Enable multidrop DNS lookup?",
variable=self.dns).pack(side=TOP)
Label(mdropwin, text="DNS aliases").pack(side=TOP)
ListEdit("New site alias: ", self.server.aka, None, mdropwin)
Label(mdropwin, text="Domains to be considered local").pack(side=TOP)
ListEdit("New local domain: ", self.server.localdomains, None,mdropwin)
Button(mdropwin, text='Help', fg='blue',
command=lambda: helpwin(multihelp)).pack(side=RIGHT)
mdropwin.pack(fill=X)
userwin = Frame(self, relief=RAISED, bd=5)
Label(userwin, text="User entries for " + host).pack(side=TOP)
ListEdit("New user: ", None, self.edituser, userwin)
userwin.pack(fill=X)
def edituser(self, user):
UserEdit(user, self.server.userlist, Toplevel())
#
# User editing stuff
#
userhelp = {
'title' : 'User option help',
'banner': 'User options',
'text' : """
FIXME
"""}
class UserEdit(Frame):
def __init__(self, user, userlist, master=None):
Frame.__init__(self, master)
Pack.config(self)
self.master.title('Fetchmail user ' + user);
self.master.iconname('Fetchmail user ' + user);
self.user = User()
self.user.remote = user
self.user.localnames = [user]
self.userlist = userlist
self.post()
self.createWidgets(user)
def post(self):
# we can't abstract this away, execs would happen in the wrong scope
for x in self.user.typemap:
target = "self." + x[0]
source = "self.user." + x[0]
if x[1] == 'Boolean':
exec target + " = BooleanVar(self)"
if eval(source):
exec target + ".set(" + source + ")"
elif x[1] == 'String':
exec target + " = StringVar(self)"
if eval(source):
exec target + ".set(" + source + ")"
elif x[1] == 'Int':
exec target + " = IntVar(self)"
if eval(source):
exec target + ".set(" + source + ")"
def gather(self):
for x in self.user.typemap:
setattr(self.user, x[0], getattr(self, x[0]).get())
def nosave(self):
if ConfirmQuit(self, 'user option editing'):
Widget.destroy(self.master)
def save(self):
self.gather()
self.userlist.append(self.user)
Widget.destroy(self.master)
def createWidgets(self):
topwin = Frame(self, relief=RAISED, bd=5)
Label(topwin,
text="User options for " + self.user.remote).pack(side=TOP,pady=10)
Button(topwin, text='Save', fg='blue',
command=self.save).pack(side=LEFT)
Button(topwin, text='Quit', fg='blue',
command=self.nosave).pack(side=LEFT)
Button(topwin, text='Help', fg='blue',
command=lambda: helpwin(userhelp)).pack(side=RIGHT)
topwin.pack(fill=X)
secwin = Frame(self, relief=RAISED, bd=5)
Label(secwin, text="Authentication").pack(side=TOP)
LabeledEntry(mdropwin, 'Password:',
self.password, '30').pack(side=TOP, fill=X)
LabeledEntry(mdropwin, 'Remote folder:',
self.folder, '30').pack(side=TOP, fill=X)
secwin.pack(fill=X)
names = Frame(self, relief=RAISED, bd=5)
Label(names, text="Local names").pack(side=TOP)
ListEdit("New local name: ", self.localnames, None, names)
names.pack(fill=X)
targwin = Frame(self, relief=RAISED, bd=5)
Label(targwin, text="Forwarding Options").pack(side=TOP)
LabeledEntry(targwin, 'System to forward to:',
self.smtphost, '30').pack(side=TOP, fill=X)
LabeledEntry(targwin, 'Connection setup command:',
self.preconnect, '30').pack(side=TOP, fill=X)
LabeledEntry(targwin, 'Connection wrapup command:',
self.postconnect, '30').pack(side=TOP, fill=X)
LabeledEntry(targwin, 'Local delivery agent:',
self.mda, '30').pack(side=TOP, fill=X)
targwin.pack(fill=X)
optwin = Frame(self, relief=RAISED, bd=5)
Checkbutton(optwin, "Suppress deletion of messages after reading",
self.keep)
Checkbutton(optwin, "Flush seen messages before retrieval",
self.flush)
Checkbutton(optwin, "Fetch old messages as well as new",
self.fetchall)
Checkbutton(optwin, "Rewrite To/Cc/Bcc messages to enable reply",
self.rewrite)
Checkbutton(optwin, "Force CR/LF at end of each line",
self.forcecr)
Checkbutton(optwin, "Strip CR from end of eacgh line",
self.stripcr)
Checkbutton(optwin, "Pass 8 bits even theough SMTP says 7BIT",
self.pass8bits)
Checkbutton(optwin, "Drop Status lines from forwarded messages",
self.dropstatus)
optwin.pack(fill=X)
limwin = Frame(self, relief=RAISED, bd=5)
Label(limwin, text="Resource Limits").pack(side=TOP)
LabeledEntry(limwin, 'Message size limit:',
self.limit, '30').pack(side=TOP, fill=X)
LabeledEntry(limwin, 'Maximum messages to fetch each poll:',
self.fetchlimit, '30').pack(side=TOP, fill=X)
LabeledEntry(limwin, 'Maximum messages to forward each poll:',
self.batchlimit, '30').pack(side=TOP, fill=X)
limwin.pack(fill=X)
#
# Configure drives the configuration dialogue. It may call multiple
# instances of ServerEdit to do its job.
#
class Configure(Frame, ControlEdit):
def __init__(self, master=None):
Frame.__init__(self, master)
self.master.title('fetchmail configurator');
self.master.iconname('fetchmail configurator');
Pack.config(self)
self.MakeDispose()
self.controls = Controls()
self.PostControls()
self.MakeSitelist(master)
self.sites = []
def MakeDispose(self):
# Set the disposal of the given configuration
dispose = Frame(self, relief=RAISED, bd=5);
Label(dispose,
text='Configurator Controls',
bd=2).pack(side=TOP, pady=10)
Button(dispose, text='Save', fg='blue',
command=self.save).pack(side=LEFT)
Button(dispose, text='Quit', fg='blue',
command=self.nosave).pack(side=LEFT)
Button(dispose, text='Help', fg='blue',
command=lambda: helpwin(confighelp)).pack(side=RIGHT)
dispose.pack(side=TOP, fill=X);
def MakeSitelist(self, master):
lf = Frame(master, relief=RAISED, bd=5)
Label(lf,
text='Remote Mail Server Configurations',
bd=2).pack(side=TOP, pady=10)
ListEdit('New Server:', None, self.editsite, lf)
lf.pack(fill=X)
def editsite(self, site):
ServerEdit(site, self.sites, Toplevel())
def save(self):
self.GatherControls()
sys.stdout.write("# Configuration created %s\n" % time.ctime(time.time()))
sys.stdout.write(`self.controls`)
for site in self.sites:
sys.stdout.write(`site`)
for user in self.sites.userlist:
sys.stdout.write(`user`)
self.quit()
def nosave(self):
if ConfirmQuit(self, "configuration editor"):
self.quit()
if __name__ == '__main__':
ServerDefaults = Server()
UserDefaults = User()
Configure().mainloop()
# The following sets edit modes for GNU EMACS
# Local Variables:
# mode:python
# End:

View file

@ -0,0 +1,479 @@
\input texinfo @c -*-texinfo-*-
@c %**start of header
@setfilename gzip.info
@settitle Gzip User's Manual
@finalout
@setchapternewpage odd
@c %**end of header
@ifinfo
This file documents the the GNU @code{gzip} command for compressing files.
Copyright (C) 1992-1993 Jean-loup Gailly
Permission is granted to make and distribute verbatim copies of
this manual provided the copyright notice and this permission notice
are preserved on all copies.
@ignore
Permission is granted to process this file through TeX and print the
results, provided the printed document carries copying permission
notice identical to this one except for the removal of this paragraph
(this paragraph not being relevant to the printed manual).
@end ignore
Permission is granted to copy and distribute modified versions of this
manual under the conditions for verbatim copying, provided that the entire
resulting derived work is distributed under the terms of a permission
notice identical to this one.
Permission is granted to copy and distribute translations of this manual
into another language, under the above conditions for modified versions,
except that this permission notice may be stated in a translation approved
by the Foundation.
@end ifinfo
@titlepage
@title gzip
@subtitle The data compression program
@subtitle Edition 1.2.4, for Gzip Version 1.2.4
@subtitle July 1993
@author by Jean-loup Gailly
@page
@vskip 0pt plus 1filll
Copyright @copyright{} 1992-1993 Jean-loup Gailly
Permission is granted to make and distribute verbatim copies of
this manual provided the copyright notice and this permission notice
are preserved on all copies.
Permission is granted to copy and distribute modified versions of this
manual under the conditions for verbatim copying, provided that the entire
resulting derived work is distributed under the terms of a permission
notice identical to this one.
Permission is granted to copy and distribute translations of this manual
into another language, under the above conditions for modified versions,
except that this permission notice may be stated in a translation approved
by the Foundation.
@end titlepage
@node Top, , , (dir)
@ifinfo
This file documents the @code{gzip} command to compress files.
@end ifinfo
@menu
* Copying:: How you can copy and share @code{gzip}.
* Overview:: Preliminary information.
* Sample:: Sample output from @code{gzip}.
* Invoking gzip:: How to run @code{gzip}.
* Advanced usage:: Concatenated files.
* Environment:: The @code{GZIP} environment variable
* Tapes:: Using @code{gzip} on tapes.
* Problems:: Reporting bugs.
* Concept Index:: Index of concepts.
@end menu
@node Copying, Overview, , Top
@include gpl.texinfo
@node Overview, Sample, Copying, Top
@chapter Overview
@cindex overview
@code{gzip} reduces the size of the named files using Lempel-Ziv coding
(LZ77). Whenever possible, each file is replaced by one with the
extension @samp{.gz}, while keeping the same ownership modes, access and
modification times. (The default extension is @samp{-gz} for VMS,
@samp{z} for MSDOS, OS/2 FAT and Atari.) If no files are specified or
if a file name is "-", the standard input is compressed to the standard
output. @code{gzip} will only attempt to compress regular files. In
particular, it will ignore symbolic links.
If the new file name is too long for its file system, @code{gzip}
truncates it. @code{gzip} attempts to truncate only the parts of the
file name longer than 3 characters. (A part is delimited by dots.) If
the name consists of small parts only, the longest parts are truncated.
For example, if file names are limited to 14 characters, gzip.msdos.exe
is compressed to gzi.msd.exe.gz. Names are not truncated on systems
which do not have a limit on file name length.
By default, @code{gzip} keeps the original file name and timestamp in
the compressed file. These are used when decompressing the file with the
@samp{-N} option. This is useful when the compressed file name was
truncated or when the time stamp was not preserved after a file
transfer.
Compressed files can be restored to their original form using @samp{gzip -d}
or @code{gunzip} or @code{zcat}. If the original name saved in the
compressed file is not suitable for its file system, a new name is
constructed from the original one to make it legal.
@code{gunzip} takes a list of files on its command line and replaces
each file whose name ends with @samp{.gz}, @samp{.z}, @samp{.Z},
@samp{-gz}, @samp{-z} or @samp{_z} and which begins with the correct
magic number with an uncompressed file without the original extension.
@code{gunzip} also recognizes the special extensions @samp{.tgz} and
@samp{.taz} as shorthands for @samp{.tar.gz} and @samp{.tar.Z}
respectively. When compressing, @code{gzip} uses the @samp{.tgz}
extension if necessary instead of truncating a file with a @samp{.tar}
extension.
@code{gunzip} can currently decompress files created by @code{gzip},
@code{zip}, @code{compress} or @code{pack}. The detection of the input
format is automatic. When using the first two formats, @code{gunzip}
checks a 32 bit CRC (cyclic redundancy check). For @code{pack},
@code{gunzip} checks the uncompressed length. The @code{compress} format
was not designed to allow consistency checks. However @code{gunzip} is
sometimes able to detect a bad @samp{.Z} file. If you get an error when
uncompressing a @samp{.Z} file, do not assume that the @samp{.Z} file is
correct simply because the standard @code{uncompress} does not complain.
This generally means that the standard @code{uncompress} does not check
its input, and happily generates garbage output. The SCO @samp{compress
-H} format (@code{lzh} compression method) does not include a CRC but
also allows some consistency checks.
Files created by @code{zip} can be uncompressed by @code{gzip} only if
they have a single member compressed with the 'deflation' method. This
feature is only intended to help conversion of @code{tar.zip} files to
the @code{tar.gz} format. To extract @code{zip} files with several
members, use @code{unzip} instead of @code{gunzip}.
@code{zcat} is identical to @samp{gunzip -c}. @code{zcat}
uncompresses either a list of files on the command line or its standard
input and writes the uncompressed data on standard output. @code{zcat}
will uncompress files that have the correct magic number whether they
have a @samp{.gz} suffix or not.
@code{gzip} uses the Lempel-Ziv algorithm used in @code{zip} and PKZIP.
The amount of compression obtained depends on the size of the input and
the distribution of common substrings. Typically, text such as source
code or English is reduced by 60-70%. Compression is generally much
better than that achieved by LZW (as used in @code{compress}), Huffman
coding (as used in @code{pack}), or adaptive Huffman coding
(@code{compact}).
Compression is always performed, even if the compressed file is slightly
larger than the original. The worst case expansion is a few bytes for
the @code{gzip} file header, plus 5 bytes every 32K block, or an expansion
ratio of 0.015% for large files. Note that the actual number of used
disk blocks almost never increases. @code{gzip} preserves the mode,
ownership and timestamps of files when compressing or decompressing.
@node Sample, Invoking gzip, Overview, Top
@chapter Sample Output
@cindex sample
Here are some realistic examples of running @code{gzip}.
This is the output of the command @samp{gzip -h}:
@example
gzip 1.2.4 (18 Aug 93)
usage: gzip [-cdfhlLnNrtvV19] [-S suffix] [file ...]
-c --stdout write on standard output, keep original files unchanged
-d --decompress decompress
-f --force force overwrite of output file and compress links
-h --help give this help
-l --list list compressed file contents
-L --license display software license
-n --no-name do not save or restore the original name and time stamp
-N --name save or restore the original name and time stamp
-q --quiet suppress all warnings
-r --recursive operate recursively on directories
-S .suf --suffix .suf use suffix .suf on compressed files
-t --test test compressed file integrity
-v --verbose verbose mode
-V --version display version number
-1 --fast compress faster
-9 --best compress better
file... files to (de)compress. If none given, use standard input.
@end example
This is the output of the command @samp{gzip -v texinfo.tex}:
@example
texinfo.tex: 71.6% -- replaced with texinfo.tex.gz
@end example
The following command will find all @code{gzip} files in the current
directory and subdirectories, and extract them in place without
destroying the original:
@example
find . -name '*.gz' -print | sed 's/^\(.*\)[.]gz$/gunzip < "&" > "\1"/' | sh
@end example
@node Invoking gzip, Advanced usage, Sample, Top
@chapter Invoking @code{gzip}
@cindex invoking
@cindex options
The format for running the @code{gzip} program is:
@example
gzip @var{option} @dots{}
@end example
@code{gzip} supports the following options:
@table @samp
@item --stdout
@itemx --to-stdout
@itemx -c
Write output on standard output; keep original files unchanged.
If there are several input files, the output consists of a sequence of
independently compressed members. To obtain better compression,
concatenate all input files before compressing them.
@item --decompress
@itemx --uncompress
@itemx -d
Decompress.
@item --force
@itemx -f
Force compression or decompression even if the file has multiple links
or the corresponding file already exists, or if the compressed data
is read from or written to a terminal. If the input data is not in
a format recognized by @code{gzip}, and if the option --stdout is also
given, copy the input data without change to the standard ouput: let
@code{zcat} behave as @code{cat}. If @samp{-f} is not given, and
when not running in the background, @code{gzip} prompts to verify
whether an existing file should be overwritten.
@item --help
@itemx -h
Print an informative help message describing the options then quit.
@item --list
@itemx -l
For each compressed file, list the following fields:
@example
compressed size: size of the compressed file
uncompressed size: size of the uncompressed file
ratio: compression ratio (0.0% if unknown)
uncompressed_name: name of the uncompressed file
@end example
The uncompressed size is given as @samp{-1} for files not in @code{gzip}
format, such as compressed @samp{.Z} files. To get the uncompressed size for
such a file, you can use:
@example
zcat file.Z | wc -c
@end example
In combination with the --verbose option, the following fields are also
displayed:
@example
method: compression method (deflate,compress,lzh,pack)
crc: the 32-bit CRC of the uncompressed data
date & time: time stamp for the uncompressed file
@end example
The crc is given as ffffffff for a file not in gzip format.
With --verbose, the size totals and compression ratio for all files
is also displayed, unless some sizes are unknown. With --quiet,
the title and totals lines are not displayed.
@item --license
@itemx -L
Display the @code{gzip} license then quit.
@item --no-name
@itemx -n
When compressing, do not save the original file name and time stamp by
default. (The original name is always saved if the name had to be
truncated.) When decompressing, do not restore the original file name
if present (remove only the @code{gzip}
suffix from the compressed file name) and do not restore the original
time stamp if present (copy it from the compressed file). This option
is the default when decompressing.
@item --name
@itemx -N
When compressing, always save the original file name and time stamp; this
is the default. When decompressing, restore the original file name and
time stamp if present. This option is useful on systems which have
a limit on file name length or when the time stamp has been lost after
a file transfer.
@item --quiet
@itemx -q
Suppress all warning messages.
@item --recursive
@itemx -r
Travel the directory structure recursively. If any of the file names
specified on the command line are directories, @code{gzip} will descend
into the directory and compress all the files it finds there (or
decompress them in the case of @code{gunzip}).
@item --suffix @var{suf}
@itemx -S @var{suf}
Use suffix @samp{@var{suf}} instead of @samp{.gz}. Any suffix can be
given, but suffixes other than @samp{.z} and @samp{.gz} should be
avoided to avoid confusion when files are transferred to other systems.
A null suffix forces gunzip to try decompression on all given files
regardless of suffix, as in:
@example
gunzip -S "" * (*.* for MSDOS)
@end example
Previous versions of gzip used the @samp{.z} suffix. This was changed to
avoid a conflict with @code{pack}.
@item --test
@itemx -t
Test. Check the compressed file integrity.
@item --verbose
@itemx -v
Verbose. Display the name and percentage reduction for each file compressed.
@item --version
@itemx -V
Version. Display the version number and compilation options, then quit.
@item --fast
@itemx --best
@itemx -@var{n}
Regulate the speed of compression using the specified digit @var{n},
where @samp{-1} or @samp{--fast} indicates the fastest compression
method (less compression) and @samp{--best} or @samp{-9} indicates the
slowest compression method (optimal compression). The default
compression level is @samp{-6} (that is, biased towards high compression at
expense of speed).
@end table
@node Advanced usage, Environment, Invoking gzip, Top
@chapter Advanced usage
@cindex concatenated files
Multiple compressed files can be concatenated. In this case,
@code{gunzip} will extract all members at once. If one member is
damaged, other members might still be recovered after removal of the
damaged member. Better compression can be usually obtained if all
members are decompressed and then recompressed in a single step.
This is an example of concatenating @code{gzip} files:
@example
gzip -c file1 > foo.gz
gzip -c file2 >> foo.gz
@end example
Then
@example
gunzip -c foo
@end example
is equivalent to
@example
cat file1 file2
@end example
In case of damage to one member of a @samp{.gz} file, other members can
still be recovered (if the damaged member is removed). However,
you can get better compression by compressing all members at once:
@example
cat file1 file2 | gzip > foo.gz
@end example
compresses better than
@example
gzip -c file1 file2 > foo.gz
@end example
If you want to recompress concatenated files to get better compression, do:
@example
zcat old.gz | gzip > new.gz
@end example
If a compressed file consists of several members, the uncompressed
size and CRC reported by the @samp{--list} option applies to the last member
only. If you need the uncompressed size for all members, you can use:
@example
zcat file.gz | wc -c
@end example
If you wish to create a single archive file with multiple members so
that members can later be extracted independently, use an archiver such
as @code{tar} or @code{zip}. GNU @code{tar} supports the @samp{-z}
option to invoke @code{gzip} transparently. @code{gzip} is designed as a
complement to @code{tar}, not as a replacement.
@node Environment, Tapes, Advanced usage, Top
@chapter Environment
@cindex Environment
The environment variable @code{GZIP} can hold a set of default options for
@code{gzip}. These options are interpreted first and can be overwritten by
explicit command line parameters. For example:
@example
for sh: GZIP="-8v --name"; export GZIP
for csh: setenv GZIP "-8v --name"
for MSDOS: set GZIP=-8v --name
@end example
On Vax/VMS, the name of the environment variable is @code{GZIP_OPT}, to
avoid a conflict with the symbol set for invocation of the program.
@node Tapes, Problems, Environment, Top
@chapter Using @code{gzip} on tapes
@cindex tapes
When writing compressed data to a tape, it is generally necessary to pad
the output with zeroes up to a block boundary. When the data is read and
the whole block is passed to @code{gunzip} for decompression,
@code{gunzip} detects that there is extra trailing garbage after the
compressed data and emits a warning by default. You have to use the
@samp{--quiet} option to suppress the warning. This option can be set in the
@code{GZIP} environment variable, as in:
@example
for sh: GZIP="-q" tar -xfz --block-compress /dev/rst0
for csh: (setenv GZIP "-q"; tar -xfz --block-compress /dev/rst0)
@end example
In the above example, @code{gzip} is invoked implicitly by the @samp{-z}
option of GNU @code{tar}. Make sure that the same block size (@samp{-b}
option of @code{tar}) is used for reading and writing compressed data on
tapes. (This example assumes you are using the GNU version of
@code{tar}.)
@node Problems, Concept Index, Tapes, Top
@chapter Reporting Bugs
@cindex bugs
If you find a bug in @code{gzip}, please send electronic mail to
@w{@samp{jloup@@chorus.fr}} or, if this fails, to
@w{@samp{bug-gnu-utils@@prep.ai.mit.edu}}. Include the version number,
which you can find by running @w{@samp{gzip -V}}. Also include in your
message the hardware and operating system, the compiler used to compile
@code{gzip},
a description of the bug behavior, and the input to @code{gzip} that triggered
the bug.@refill
@node Concept Index, , Problems, Top
@unnumbered Concept Index
@printindex cp
@contents
@bye

View file

@ -0,0 +1 @@
% This comment does not end with newline

View file

@ -0,0 +1,15 @@
\documentclass[11pt]{report}
\usepackage{verbatim,amsmath,amssymb,morehelp}
\newcommand{\nm}[2]{\nomenclature{#1}{#2}}
\begin{document}
\section{blah}
MAKE PICTURE
To develop notation, we examine a few particular cases.
\end{document}

File diff suppressed because it is too large Load diff

5
test/etags/y-src/atest.y Normal file
View file

@ -0,0 +1,5 @@
%%
exp : exp '*' exp
{ $$.value = $1.value ? $3.value : $5.value;
$$.unsignedp = $3.unsignedp || $5.unsignedp; }
;

2202
test/etags/y-src/cccp.c Normal file

File diff suppressed because it is too large Load diff

1006
test/etags/y-src/cccp.y Normal file

File diff suppressed because it is too large Load diff

2236
test/etags/y-src/parse.c Normal file

File diff suppressed because it is too large Load diff

875
test/etags/y-src/parse.y Normal file
View file

@ -0,0 +1,875 @@
%{
/* Copyright (C) 1990, 1992, 1993 Free Software Foundation, Inc.
This file is part of Oleo, the GNU Spreadsheet.
Oleo 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.
Oleo 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 Oleo; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
%}
%right '?' ':'
/* %left '|' */
%left '&'
%nonassoc '=' NE
%nonassoc '<' LE '>' GE
%left '+' '-'
%left '*' '/' '%'
%right '^'
%left NEG '!'
%token L_CELL L_RANGE
%token L_VAR
%token L_CONST
%token L_FN0 L_FN1 L_FN2 L_FN3 L_FN4 L_FNN
%token L_FN1R L_FN2R L_FN3R L_FN4R L_FNNR
%token L_LE L_NE L_GE
%{
#include "funcdef.h"
#include <ctype.h>
#define obstack_chunk_alloc ck_malloc
#define obstack_chunk_free free
#include "obstack.h"
#include "sysdef.h"
#include "global.h"
#include "errors.h"
#include "node.h"
#include "eval.h"
#include "ref.h"
int yylex ();
#ifdef __STDC__
void yyerror (char *);
#else
void yyerror ();
#endif
VOIDSTAR parse_hash;
extern VOIDSTAR hash_find();
/* This table contains a list of the infix single-char functions */
unsigned char fnin[] = {
SUM, DIFF, DIV, PROD, MOD, /* AND, OR, */ POW, EQUAL, IF, CONCAT, 0
};
#define YYSTYPE _y_y_s_t_y_p_e
typedef struct node *YYSTYPE;
YYSTYPE parse_return;
#ifdef __STDC__
YYSTYPE make_list (YYSTYPE, YYSTYPE);
#else
YYSTYPE make_list ();
#endif
char *instr;
int parse_error = 0;
extern struct obstack tmp_mem;
%}
%%
line: exp
{ parse_return=$1; }
| error {
if(!parse_error)
parse_error=PARSE_ERR;
parse_return=0; }
;
exp: L_CONST
| cell
| L_FN0 '(' ')' {
$$=$1; }
| L_FN1 '(' exp ')' {
($1)->n_x.v_subs[0]=$3;
($1)->n_x.v_subs[1]=(struct node *)0;
$$=$1; }
| L_FN2 '(' exp ',' exp ')' {
($1)->n_x.v_subs[0]=$3;
($1)->n_x.v_subs[1]=$5;
$$=$1; }
| L_FN3 '(' exp ',' exp ',' exp ')' {
($1)->n_x.v_subs[0]=make_list($3,$5);
($1)->n_x.v_subs[1]=$7;
$$=$1;}
| L_FN4 '(' exp ',' exp ',' exp ',' exp ')' {
($1)->n_x.v_subs[0]=make_list($3,$5);
($1)->n_x.v_subs[1]=make_list($7,$9);
$$=$1;}
| L_FNN '(' exp_list ')' {
($1)->n_x.v_subs[0]=(struct node *)0;
($1)->n_x.v_subs[1]=$3;
$$=$1; }
| L_FN1R '(' L_RANGE ')' {
$1->n_x.v_subs[0]=$3;
$$=$1; }
| L_FN1R '(' L_VAR ')' {
$1->n_x.v_subs[0]=$3;
$$=$1; }
| L_FN2R '(' L_RANGE ',' exp ')' {
$1->n_x.v_subs[0]=$3;
$1->n_x.v_subs[1]=$5;
$$=$1; }
| L_FN2R '(' L_VAR ',' exp ')' {
$1->n_x.v_subs[0]=$3;
$1->n_x.v_subs[1]=$5;
$$=$1; }
/* JF: These should be FN2R, but I'm hacking this for SYLNK */
| L_FN2R '(' L_RANGE ',' exp ',' exp ')' {
if($1->comp_value!=F_INDEX)
parse_error=PARSE_ERR;
$1->comp_value=F_INDEX2;
$1->n_x.v_subs[0]=make_list($3,$5);
$1->n_x.v_subs[1]=$7;
$$=$1; }
| L_FN2R '(' L_VAR ',' exp ',' exp ')' {
if($1->comp_value!=F_INDEX)
parse_error=PARSE_ERR;
$1->comp_value=F_INDEX2;
$1->n_x.v_subs[0]=make_list($3,$5);
$1->n_x.v_subs[1]=$7;
$$=$1; }
| L_FN3R '(' L_RANGE ',' exp ',' exp ')' {
($1)->n_x.v_subs[0]=make_list($3,$5);
($1)->n_x.v_subs[1]=$7;
$$=$1;}
| L_FN3R '(' L_VAR ',' exp ',' exp ')' {
($1)->n_x.v_subs[0]=make_list($3,$5);
($1)->n_x.v_subs[1]=$7;
$$=$1;}
| L_FNNR '(' range_exp_list ')' {
($1)->n_x.v_subs[0]=(struct node *)0;
($1)->n_x.v_subs[1]=$3;
$$=$1; }
| exp '?' exp ':' exp {
$2->comp_value=IF;
$2->n_x.v_subs[0]=$4;
$2->n_x.v_subs[1]=$5;
$4->n_x.v_subs[0]=$1;
$4->n_x.v_subs[1]=$3;
$$=$2; }
/* | exp '|' exp {
$2->n_x.v_subs[0]=$1;
$2->n_x.v_subs[1]=$3;
$$ = $2; } */
| exp '&' exp {
$2->n_x.v_subs[0]=$1;
$2->n_x.v_subs[1]=$3;
$$ = $2; }
| exp '<' exp {
$2->n_x.v_subs[0]=$1;
$2->n_x.v_subs[1]=$3;
$$ = $2; }
| exp LE exp {
$2->n_x.v_subs[0]=$1;
$2->n_x.v_subs[1]=$3;
$$ = $2; }
| exp '=' exp {
$2->n_x.v_subs[0]=$1;
$2->n_x.v_subs[1]=$3;
$$ = $2; }
| exp NE exp {
$2->n_x.v_subs[0]=$1;
$2->n_x.v_subs[1]=$3;
$$ = $2; }
| exp '>' exp {
$2->n_x.v_subs[0]=$1;
$2->n_x.v_subs[1]=$3;
$$ = $2; }
| exp GE exp {
$2->n_x.v_subs[0]=$1;
$2->n_x.v_subs[1]=$3;
$$ = $2; }
| exp '+' exp {
$2->n_x.v_subs[0]=$1;
$2->n_x.v_subs[1]=$3;
$$ = $2; }
| exp '-' exp {
$2->n_x.v_subs[0]=$1;
$2->n_x.v_subs[1]=$3;
$$ = $2; }
| exp '*' exp {
$2->n_x.v_subs[0]=$1;
$2->n_x.v_subs[1]=$3;
$$ = $2; }
| exp '/' exp {
$2->n_x.v_subs[0]=$1;
$2->n_x.v_subs[1]=$3;
$$ = $2; }
| exp '%' exp {
$2->n_x.v_subs[0]=$1;
$2->n_x.v_subs[1]=$3;
$$ = $2; }
| exp '^' exp {
$2->n_x.v_subs[0]=$1;
$2->n_x.v_subs[1]=$3;
$$ = $2; }
| '-' exp %prec NEG {
if($2->comp_value==CONST_FLT) {
$2->n_x.v_float= -($2->n_x.v_float);
/* free($1); */
$$=$2;
} else if($2->comp_value==CONST_INT) {
$2->n_x.v_int= -($2->n_x.v_int);
/* free($1); */
$$=$2;
} else {
$1->comp_value = NEGATE;
$1->n_x.v_subs[0]=$2;
$1->n_x.v_subs[1]=(struct node *)0;
$$ = $1;
} }
| '!' exp {
$1->n_x.v_subs[0]=$2;
$1->n_x.v_subs[1]=(struct node *)0;
$$ = $1; }
| '(' exp ')'
{ $$ = $2; }
| '(' exp error {
if(!parse_error)
parse_error=NO_CLOSE;
}
/* | exp ')' error {
if(!parse_error)
parse_error=NO_OPEN;
} */
| '(' error {
if(!parse_error)
parse_error=NO_CLOSE;
}
;
exp_list: exp
{ $$ = make_list($1, 0); }
| exp_list ',' exp
{ $$ = make_list($3, $1); }
;
range_exp: L_RANGE
| exp
;
range_exp_list: range_exp
{ $$=make_list($1, 0); }
| range_exp_list ',' range_exp
{ $$=make_list($3,$1); }
;
cell: L_CELL
{ $$=$1; }
| L_VAR
;
%%
void
yyerror FUN1(char *, s)
{
if(!parse_error)
parse_error=PARSE_ERR;
}
YYSTYPE
make_list FUN2(YYSTYPE, car, YYSTYPE, cdr)
{
YYSTYPE ret;
ret=(YYSTYPE)obstack_alloc(&tmp_mem,sizeof(*ret));
ret->comp_value = 0;
ret->n_x.v_subs[0]=car;
ret->n_x.v_subs[1]=cdr;
return ret;
}
#define ERROR -1
extern struct node *yylval;
#ifdef __STDC__
unsigned char parse_cell_or_range (char **,struct rng *);
#else
unsigned char parse_cell_or_range ();
#endif
int
yylex FUN0()
{
int ch;
struct node *new;
int isflt;
char *begin;
char *tmp_str;
unsigned char byte_value;
int n;
/* unsigned char *ptr; */
int nn;
struct function *fp;
int tmp_ch;
#ifdef TEST
if(!instr)
return ERROR;
#endif
while(isspace(*instr))
instr++;
ch = *instr++;
if(ch=='(' || ch==',' || ch==')')
return ch;
new=(struct node *)obstack_alloc(&tmp_mem,sizeof(struct node));
new->add_byte=0;
new->sub_value=0;
switch(ch) {
case 0:
return 0;
case '0': case '1': case '2': case '3': case '4': case '5': case '6':
case '7': case '8': case '9': case '.':
isflt = (ch=='.');
begin=instr-1;
tmp_str=instr;
while(isdigit(*tmp_str) || (!isflt && *tmp_str=='.' && ++isflt))
tmp_str++;
if(*tmp_str=='e' || *tmp_str=='E') {
isflt=1;
tmp_str++;
if(*tmp_str=='-' || *tmp_str=='+')
tmp_str++;
while(isdigit(*tmp_str))
tmp_str++;
}
if(isflt) {
new->n_x.v_float=astof((char **)(&begin));
byte_value=CONST_FLT;
} else {
new->n_x.v_int=astol((char **)(&begin));
if(begin!=tmp_str) {
begin=instr-1;
new->n_x.v_float=astof((char **)(&begin));
byte_value=CONST_FLT;
} else
byte_value=CONST_INT;
}
ch=L_CONST;
instr=begin;
break;
case '"':
begin=instr;
while(*instr && *instr!='"') {
if(*instr=='\\' && instr[1])
instr++;
instr++;
}
if(!*instr) {
parse_error=NO_QUOTE;
return ERROR;
}
tmp_str=new->n_x.v_string=(char *)ck_malloc(1+instr-begin);
while(begin!=instr) {
unsigned char n;
if(*begin=='\\') {
begin++;
if(begin[0]>='0' && begin[0]<='7') {
if(begin[1]>='0' && begin[1]<='7') {
if(begin[2]>='0' && begin[2]<='7') {
n=(begin[2]-'0') + (010 * (begin[1]-'0')) + ( 0100 * (begin[0]-'0'));
begin+=3;
} else {
n=(begin[1]-'0') + (010 * (begin[0]-'0'));
begin+=2;
}
} else {
n=begin[0]-'0';
begin++;
}
} else
n= *begin++;
*tmp_str++= n;
} else
*tmp_str++= *begin++;
}
*tmp_str='\0';
instr++;
byte_value=CONST_STR;
ch=L_CONST;
break;
case '+': case '-':
case '*': case '/': case '%': case '&':
/* case '|': */ case '^': case '=':
case '?':
{
unsigned char *ptr;
for(ptr= fnin;*ptr;ptr++)
if(the_funs[*ptr].fn_str[0]==ch)
break;
#ifdef TEST
if(!*ptr)
panic("Can't find fnin[] entry for '%c'",ch);
#endif
byte_value= *ptr;
}
break;
case ':':
byte_value=IF;
break;
case '!':
case '<':
case '>':
if(*instr!='=') {
byte_value = (ch=='<') ? LESS : (ch=='>') ? GREATER : NOT;
break;
}
instr++;
byte_value = (ch=='<') ? LESSEQ : (ch=='>') ? GREATEQ : NOTEQUAL;
ch = (ch=='<') ? LE : (ch=='>') ? GE : NE;
break;
case '\'':
case ';':
case '[':
case '\\':
case ']':
case '`':
case '{':
case '}':
case '~':
bad_chr:
parse_error=BAD_CHAR;
return ERROR;
case '#':
begin=instr-1;
while(*instr && (isalnum(*instr) || *instr=='_'))
instr++;
ch= *instr;
*instr=0;
if(!stricmp(begin,tname))
byte_value=F_TRUE;
else if(!stricmp(begin,fname))
byte_value=F_FALSE;
else if(!stricmp(begin,iname) && (begin[4]==0 || !stricmp(begin+4,"inity")))
byte_value=CONST_INF;
else if(!stricmp(begin,mname) ||
!stricmp(begin,"#ninf"))
byte_value=CONST_NINF;
else if(!stricmp(begin,nname) ||
!stricmp(begin,"#nan"))
byte_value=CONST_NAN;
else {
for(n=1;n<=ERR_MAX;n++)
if(!stricmp(begin,ename[n]))
break;
if(n>ERR_MAX)
n=BAD_CHAR;
new->n_x.v_int=n;
byte_value=CONST_ERR;
}
*instr=ch;
ch=L_CONST;
break;
default:
if(!a0 && (ch=='@' || ch=='$'))
goto bad_chr;
if(a0 && ch=='@') {
begin=instr;
while(*instr && (isalpha(*instr) || isdigit(*instr) || *instr=='_'))
instr++;
n=instr-begin;
} else {
begin=instr-1;
byte_value=parse_cell_or_range(&begin,&(new->n_x.v_rng));
if(byte_value) {
if((byte_value& ~0x3)==R_CELL)
ch=L_CELL;
else
ch=L_RANGE;
instr=begin;
break;
}
while(*instr && (isalpha(*instr) || isdigit(*instr) || *instr=='_'))
instr++;
n=instr-begin;
while(isspace(*instr))
instr++;
if(*instr!='(') {
ch=L_VAR;
byte_value=VAR;
new->n_x.v_var=find_or_make_var(begin,n);
break;
}
}
tmp_ch=begin[n];
begin[n]='\0';
fp=hash_find(parse_hash,begin);
begin[n]=tmp_ch;
byte_value= ERROR;
if(!fp) {
parse_error=BAD_FUNC;
return ERROR;
}
if(fp>=the_funs && fp<=&the_funs[USR1])
byte_value=fp-the_funs;
else {
for(nn=0;nn<n_usr_funs;nn++) {
if(fp>=&usr_funs[nn][0] && fp<=&usr_funs[nn][usr_n_funs[nn]]) {
byte_value=USR1+nn;
new->sub_value=fp-&usr_funs[nn][0];
break;
}
}
#ifdef TEST
if(nn==n_usr_funs) {
io_error_msg("Couln't turn fp into a ##");
parse_error=BAD_FUNC;
return ERROR;
}
#endif
}
if(fp->fn_argn&X_J)
ch= byte_value==F_IF ? L_FN3 : L_FN2;
else if(fp->fn_argt[0]=='R' || fp->fn_argt[0]=='E')
ch=L_FN1R-1+fp->fn_argn-X_A0;
else
ch=L_FN0 + fp->fn_argn-X_A0;
break;
}
/* new->node_type=ch; */
new->comp_value=byte_value;
yylval=new;
return ch;
}
/* Return value is
0 if it doesn't look like a cell or a range,
R_CELL if it is a cell (ptr now points past the characters, lr and lc hold the row and col of the cell)
RANGE if it is a range (ptr points past the chars)
*/
unsigned char
parse_cell_or_range FUN2(char **,ptr, struct rng *,retp)
{
if(a0) {
unsigned tmpc,tmpr;
char *p;
int abz = ROWREL|COLREL;
p= *ptr;
tmpc=0;
if(*p=='$') {
abz-=COLREL;
p++;
}
if(!isalpha(*p))
return 0;
tmpc=str_to_col(&p);
if(tmpc<MIN_COL || tmpc>MAX_COL)
return 0;
if(*p=='$') {
abz-=ROWREL;
p++;
}
if(!isdigit(*p))
return 0;
for(tmpr=0;isdigit(*p);p++)
tmpr=tmpr*10 + *p - '0';
if(tmpr<MIN_ROW || tmpr>MAX_ROW)
return 0;
if(*p==':' || *p=='.') {
unsigned tmpc1,tmpr1;
abz = ((abz&COLREL) ? LCREL : 0)|((abz&ROWREL) ? LRREL : 0)|HRREL|HCREL;
p++;
if(*p=='$') {
abz-=HCREL;
p++;
}
if(!isalpha(*p))
return 0;
tmpc1=str_to_col(&p);
if(tmpc1<MIN_COL || tmpc1>MAX_COL)
return 0;
if(*p=='$') {
abz-=HRREL;
p++;
}
if(!isdigit(*p))
return 0;
for(tmpr1=0;isdigit(*p);p++)
tmpr1=tmpr1*10 + *p - '0';
if(tmpr1<MIN_ROW || tmpr1>MAX_ROW)
return 0;
if(tmpr<tmpr1) {
retp->lr=tmpr;
retp->hr=tmpr1;
} else {
retp->lr=tmpr1;
retp->hr=tmpr;
}
if(tmpc<tmpc1) {
retp->lc=tmpc;
retp->hc=tmpc1;
} else {
retp->lc=tmpc1;
retp->hc=tmpc;
}
*ptr= p;
return RANGE | abz;
}
retp->lr = retp->hr = tmpr;
retp->lc = retp->hc = tmpc;
*ptr=p;
return R_CELL | abz;
} else {
char *p;
unsigned char retr;
unsigned char retc;
int ended;
long num;
CELLREF tmp;
#define CK_ABS_R(x) if((x)<MIN_ROW || (x)>MAX_ROW) \
return 0; \
else
#define CK_REL_R(x) if( ((x)>0 && MAX_ROW-(x)<cur_row) \
|| ((x)<0 && MIN_ROW-(x)>cur_row)) \
return 0; \
else
#define CK_ABS_C(x) if((x)<MIN_COL || (x)>MAX_COL) \
return 0; \
else
#define CK_REL_C(x) if( ((x)>0 && MAX_COL-(x)<cur_col) \
|| ((x)<0 && MIN_COL-(x)>cur_col)) \
return 0; \
else
#define MAYBEREL(p) (*(p)=='[' && (isdigit((p)[1]) || (((p)[1]=='+' || (p)[1]=='-') && isdigit((p)[2]))))
p= *ptr;
retr=0;
retc=0;
ended=0;
while(ended==0) {
switch(*p) {
case 'r':
case 'R':
if(retr) {
ended++;
break;
}
p++;
retr=R_CELL;
if(isdigit(*p)) {
num=astol(&p);
CK_ABS_R(num);
retp->lr= retp->hr=num;
} else if(MAYBEREL(p)) {
p++;
num=astol(&p);
CK_REL_R(num);
retp->lr= retp->hr=num+cur_row;
retr|=ROWREL;
if(*p==':') {
retr=RANGE|LRREL|HRREL;
p++;
num=astol(&p);
CK_REL_R(num);
retp->hr=num+cur_row;
}
if(*p++!=']')
return 0;
} else if(retc || *p=='c' || *p=='C') {
retr|=ROWREL;
retp->lr= retp->hr=cur_row;
} else
return 0;
if(*p==':' && retr!=(RANGE|LRREL|HRREL)) {
retr= (retr&ROWREL) ? RANGE|LRREL : RANGE;
p++;
if(isdigit(*p)) {
num=astol(&p);
CK_ABS_R(num);
retp->hr=num;
} else if(MAYBEREL(p)) {
p++;
num=astol(&p);
CK_REL_R(num);
retp->hr=num+cur_row;
retr|=HRREL;
if(*p++!=']')
return 0;
} else
return 0;
}
if(retc)
ended++;
break;
case 'c':
case 'C':
if(retc) {
ended++;
break;
}
p++;
retc=R_CELL;
if(isdigit(*p)) {
num=astol(&p);
CK_ABS_C(num);
retp->lc= retp->hc=num;
} else if(MAYBEREL(p)) {
p++;
num=astol(&p);
CK_REL_C(num);
retp->lc= retp->hc=num+cur_col;
retc|=COLREL;
if(*p==':') {
retc=RANGE|LCREL|HCREL;
p++;
num=astol(&p);
CK_REL_C(num);
retp->hc=num+cur_col;
}
if(*p++!=']')
return 0;
} else if(retr || *p=='r' || *p=='R') {
retc|=COLREL;
retp->lc= retp->hc=cur_col;
} else
return 0;
if(*p==':' && retc!=(RANGE|LCREL|HCREL)) {
retc= (retc&COLREL) ? RANGE|LCREL : RANGE;
p++;
if(isdigit(*p)) {
num=astol(&p);
CK_ABS_C(num);
retp->hc=num;
} else if(MAYBEREL(p)) {
p++;
num=astol(&p);
CK_REL_C(num);
retp->hc=num+cur_col;
retc|=HCREL;
if(*p++!=']')
return 0;
} else
return 0;
}
if(retr)
ended++;
break;
default:
if(retr) {
*ptr=p;
retp->lc=MIN_COL;
retp->hc=MAX_COL;
if((retr|ROWREL)==(R_CELL|ROWREL))
return (retr&ROWREL) ? (RANGE|LRREL|HRREL) : RANGE;
else
return retr;
} else if(retc) {
*ptr=p;
retp->lr=MIN_ROW;
retp->hr=MAX_COL;
if((retc|COLREL)==(R_CELL|COLREL))
return (retc&COLREL) ? (RANGE|LCREL|HCREL) : RANGE;
else
return retc;
}
return 0;
}
}
if(!retr || !retc)
return 0;
*ptr=p;
if(retp->lr>retp->hr)
tmp=retp->lr,retp->lr=retp->hr,retp->hr=tmp;
if(retp->lc>retp->hc)
tmp=retp->lc,retp->lc=retp->hc,retp->hc=tmp;
if((retr|ROWREL)==(R_CELL|ROWREL)) {
if((retc|COLREL)==(R_CELL|COLREL))
return retr|retc;
return (retr&ROWREL) ? (retc|LRREL|HRREL) : retc;
}
if((retc|COLREL)==(R_CELL|COLREL))
return (retc&COLREL) ? (retr|LCREL|HCREL) : retr;
return retr|retc;
}
}
int
str_to_col FUN1(char **,str)
{
int ret;
char c,cc,ccc;
#if MAX_COL>702
char cccc;
#endif
ret=0;
c=str[0][0];
if(!isalpha((cc=str[0][1]))) {
(*str)++;
return MIN_COL + (isupper(c) ? c-'A' : c-'a');
}
if(!isalpha((ccc=str[0][2]))) {
(*str)+=2;
return MIN_COL+26 + (isupper(c) ? c-'A' : c-'a')*26 + (isupper(cc) ? cc-'A' : cc-'a');
}
#if MAX_COL>702
if(!isalpha((cccc=str[0][3]))) {
(*str)+=3;
return MIN_COL+702 + (isupper(c) ? c-'A' : c-'a')*26*26 + (isupper(cc) ? cc-'A' : cc-'a')*26 + (isupper(ccc) ? ccc-'A' : ccc-'a');
}
if(!isalpha(str[0][4])) {
(*str)+=4;
return MIN_COL+18278 + (isupper(c) ? c-'A' : c-'a')*26*26*26 + (isupper(cc) ? cc-'A' : cc-'a')*26*26 + (isupper(ccc) ? ccc-'A' : ccc-'a')*26 + (isupper(cccc) ? cccc-'A' : cccc-'a');
}
#endif
return 0;
}