From 6ad3b3078fd863b3ed981894c407101302523020 Mon Sep 17 00:00:00 2001
From: cuz <cuz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Date: Tue, 3 Dec 2002 21:44:58 +0000
Subject: [PATCH] Close all open files on exit

git-svn-id: svn://svn.cc65.org/cc65/trunk@1707 b7a2c559-68d2-44c3-8de9-860c34a00d81
---
 libsrc/cbm/open.s     | 35 +++++++++++++++++++++++++++-
 libsrc/common/_file.s | 53 +++++++++++++++++++++++++++++++++++++++----
 2 files changed, 83 insertions(+), 5 deletions(-)

diff --git a/libsrc/cbm/open.s b/libsrc/cbm/open.s
index e27f475f2..5f2d7b627 100644
--- a/libsrc/cbm/open.s
+++ b/libsrc/cbm/open.s
@@ -3,8 +3,13 @@
 ;
 ; int open (const char* name, int flags, ...);	/* May take a mode argument */
 ;
+; Be sure to keep the value priority of closeallfiles lower than that of
+; closeallstreams (which is the high level C file I/O counterpart and must be
+; called before closeallfiles).
+
 
         .export         _open
+        .destructor     closeallfiles, 17
 
         .import         SETLFS, OPEN, CLOSE
         .import         addysp, popax
@@ -12,6 +17,7 @@
         .import         opencmdchannel, closecmdchannel, readdiskerror
         .import         __oserror
         .import         fnunit
+        .import         _close
         .importzp       sp, tmp2, tmp3
 
         .include        "errno.inc"
@@ -20,7 +26,34 @@
 
 
 ;--------------------------------------------------------------------------
-; initstdout: Open the stdout and stderr file descriptors for the screen.
+; closeallfiles: Close all open files.
+
+.proc   closeallfiles
+
+        ldx     #MAX_FDS
+loop:   lda     fdtab-1,x
+        beq     next            ; Skip unused entries
+
+; Close this file
+
+        txa
+        pha                     ; Save current value of X
+        ldx     #0
+        jsr     _close
+        pla
+        tax
+
+; Next file
+
+next:   dex
+        bne     loop
+
+        rts
+
+.endproc
+
+;--------------------------------------------------------------------------
+; _open
 
 .proc   _open
 
diff --git a/libsrc/common/_file.s b/libsrc/common/_file.s
index 4a4545a87..50ef6e1a3 100644
--- a/libsrc/common/_file.s
+++ b/libsrc/common/_file.s
@@ -3,11 +3,49 @@
 ;
 ; Data for the stdio file stream.
 ;
+; Be sure to keep the value priority of closeallstreams lower than that of
+; closeallfiles (which is the low level POSIX counterpart and must be
+; called after closeallstreams).
 
-	.export		__filetab, _stdin, _stdout, _stderr
+	.export	 	__filetab, _stdin, _stdout, _stderr
+        .destructor     closeallstreams, 16
+        .import         _close
 
+        .include        "fcntl.inc"
         .include        "_file.inc"
 
+;----------------------------------------------------------------------------
+; Close all files on exit
+
+.proc   closeallstreams
+
+       	ldy	#((FOPEN_MAX - 1) * _FILE_size)
+loop:  	sty     index                           ; Save the index
+        lda     __filetab + _FILE_f_flags,y     ; Load file flags
+        and     #_FOPEN                         ; Is it open?
+       	beq    	next                            ; jump if closed
+
+; Close this file
+
+        lda     __filetab + _FILE_f_fd,y
+        ldx     #0
+        jsr     _close
+
+; Next file
+
+next:   lda     index
+        sec
+        sbc     #_FILE_size
+        tay
+        bcs     loop
+
+        rts
+
+.endproc
+
+;----------------------------------------------------------------------------
+; File data
+
 .data
 
 __filetab:
@@ -22,10 +60,17 @@ __filetab:
 ; Standard file descriptors
 
 _stdin:
-	.word	__filetab + (0 * _FILE_size)
+	.word	__filetab + (STDIN_FILENO * _FILE_size)
 
 _stdout:
-	.word	__filetab + (1 * _FILE_size)
+	.word	__filetab + (STDOUT_FILENO * _FILE_size)
 
 _stderr:
-	.word	__filetab + (2 * _FILE_size)
+	.word	__filetab + (STDERR_FILENO * _FILE_size)
+
+
+; Temp storage for closeallstreams
+
+.bss
+index:  .res    1
+