IMPLEMENTATION MODULE TempFiles;

        (********************************************************)
        (*                                                      *)
        (*                    DKIM Signatures                   *)
        (*                                                      *)
        (*                                                      *)
        (*  Programmer:         Peter Moylan                    *)
        (*  Started:            5 August 2023                   *)
        (*  Last edited:        11 August 2023                  *)
        (*  Status:             OK                              *)
        (*                                                      *)
        (********************************************************)


FROM SYSTEM IMPORT
    (* type *)  CARD8;

IMPORT Strings, FileSys;

FROM FileOps IMPORT
    (* type *)  ChanId, FilenameString,
    (* proc *)  OpenNewFile1, OpenNewHiddenFile;

FROM TaskControl IMPORT
    (* type *)  Lock,
    (* proc *)  CreateLock, DestroyLock, Obtain, Release;

(********************************************************************)

VAR
    (* Variable used in creating a unique file name, and its lock.  *)

    NextName: ARRAY [0..7] OF CHAR;
    NextNameLock: Lock;

(************************************************************************)
(*                    CREATING A UNIQUE FILENAME                        *)
(*                                                                      *)
(* NOTE: These procedures duplicate procedures with the same name in    *)
(* modules Delivery and SMTPData. At some stage I should check to see   *)
(* whether I can reduce the duplication. One reason for the duplication *)
(* is the two modules just mentioned each have their separate NextName  *)
(* variable, for different purposes.                                    *)
(*                                                                      *)
(************************************************************************)

PROCEDURE MakeUniqueName (VAR (*OUT*) name: ARRAY OF CHAR);

    (* Generates a unique 8-character string.  The argument must of     *)
    (* course be big enough to take at least 8 characters.              *)

    (********************************************************************)

    PROCEDURE Increment (N: CARDINAL);

        (* Increments NextName[N], with carry as appropriate. *)

        BEGIN
            IF NextName[N] = '9' THEN
                NextName[N] := 'A';
            ELSIF NextName[N] = 'Z' THEN
                NextName[N] := '0';
                IF N > 0 THEN
                    Increment (N-1);
                END (*IF*);
            ELSE
                INC (NextName[N]);
            END (*IF*);
        END Increment;

    (********************************************************************)

    BEGIN
        Obtain (NextNameLock);
        Strings.Assign (NextName, name);
        Increment (7);
        Release (NextNameLock);
    END MakeUniqueName;

(************************************************************************)

PROCEDURE MakeNewFilename (BaseName, tail: ARRAY OF CHAR;
                       VAR (*OUT*) NewName: ARRAY OF CHAR);

    (* Creates a file name of the form BaseNamexxxtail, where xxx is    *)
    (* chosen such that a file of that name does not already exist.     *)
    (* Note that BaseName and tail can include punctuation.             *)

    VAR UName: FilenameString;

    BEGIN
        REPEAT
            MakeUniqueName (UName);
            Strings.Assign (BaseName, NewName);
            Strings.Append (UName, NewName);
            Strings.Append (tail, NewName);
        UNTIL NOT FileSys.Exists(NewName);
    END MakeNewFilename;

(************************************************************************)

PROCEDURE OpenNewOutputFile (BaseName, tail: ARRAY OF CHAR;
                       VAR (*OUT*) NewName: ARRAY OF CHAR;
                                               Visible: BOOLEAN): ChanId;

    (* Creates a file name of the form BaseNamexxxtail, where xxx is    *)
    (* chosen such that a file of that name does not already exist, and *)
    (* opens that file.                                                 *)
    (* Note that BaseName and tail can include punctuation.             *)

    VAR cid: ChanId;  duplication: BOOLEAN;

    BEGIN
        REPEAT
            MakeNewFilename (BaseName, tail, NewName);
            IF Visible THEN
                cid := OpenNewFile1 (NewName, duplication);
            ELSE
                cid := OpenNewHiddenFile (NewName, duplication);
            END (*IF*);
        UNTIL NOT duplication;
        RETURN cid;
    END OpenNewOutputFile;

(********************************************************************)

BEGIN
    NextName := "00000000";
    CreateLock (NextNameLock);
FINALLY
    DestroyLock (NextNameLock);
END TempFiles.


