-- ==================================================================================
--  WHAT WRITING DOES 
--
--  opens one file ("writing_input.txt"), reads the contents, and prints it to another 
--  file ("writing_output.txt"), adding some more text as it goes. 
--
--  The tricky thing here was figuring out how to use the file.open3 process to correctly allocate
--  posix file permissions. 
--
--  Makes use of INLINE proc calls. 
-- ==================================================================================


#INCLUDE "course.module"
#INCLUDE "file.module"

PROC outer (CHAN BYTE in?, SHARED CHAN BYTE out!, CHAN BYTE err!)
  
  MOBILE []BYTE file.name :
  INT file.descriptor :
  MOBILE []BYTE additional.text :
  INT mode :
  INT result :
  INT access :
  INT size :

  --{{{ variables for reading from file
  -- buffer is made very large since it has to be bigger than the text contained within the file.
  --  there is no way to dynamically allocate a buffer of the correct size as it is needed based on file contents. 
  MOBILE []BYTE buffer :      
  --}}} 



  --{{{ INLINE PROC print.result
  --  prints the result of performing an operation on a file to the terminal
  INLINE PROC print.result(VAL []BYTE file.name, VAL []BYTE operation, INT result)
    CLAIM out!
      SEQ
        out.string("*nresult of ", 0, out!) 
        out.string(operation, 0, out!)
        out.string(" the file ", 0, out!)
        out.string(file.name, 0, out!)
        out.string(" was : ", 0, out!)
        out.int   (result, 0, out!)
        out.string("*n", 0, out!)
  :
  --}}}


  --{{{ PROC file.reader
  -- process opens and reads the contents of a file. Returns the file descriptor, and it's contents. 
  PROC file.reader(VAL []BYTE file.name, RESULT INT file.descriptor, RESULT MOBILE []BYTE file.contents)
    [512]BYTE contents :
    INT mode, result, size :                            -- result from opening/closing operations

    SEQ
      file.size(file.name, size)
      print.result(file.name, "checking size of", result)

      --{{{ setting up mode for openning file
      mode := 0
      mode := mode \/ O.RDONLY                  -- bitwise or
      --}}} 

      file.open(file.name, mode, file.descriptor)       -- open the file, and get its descriptor
      file.read(file.descriptor, contents, result)      -- read the contents of the file

      IF
        (result = 0) OR (result = (-1))                 -- file empty, or error          
          file.contents := MOBILE [0]BYTE               -- return nothing
        TRUE                                            -- otherwise
          SEQ
            file.contents := MOBILE [result]BYTE
            [file.contents FOR result] := [contents FOR result]

      print.result(file.name, "opening", result)        
      file.close(file.descriptor, result)
      print.result(file.name, "closing", result)          
  :
  --}}}




  --{{{ the main body of the program
  SEQ
    file.name := "writing_output.txt"

    CLAIM out!
      out.string("*n*nprogram started, attempting to open file.*n*n", 0, out!)
      
    file.reader("writing_input.txt", file.descriptor, buffer)

    CLAIM out!
      SEQ
        out.string("*nthis is the file descriptor: ", 0, out!)
        out.int(file.descriptor, 0, out!)
        out.string("*n", 0, out!)
        out.string(buffer, 0, out!)

    file.name := "writing_output.txt"
    mode := 0
    mode := mode \/ O.CREAT     -- create file if it does note exist
    mode := mode \/ O.APPEND    -- append text to end of file. COMMENTING THIS OUT OVERWRITES FROM START OF FILE. 
    mode := mode \/ O.RDWR      -- open in read-write mode

    access := 420               -- "-rw-r--r--"

    file.open3(file.name, mode, access, file.descriptor)      -- process call required when we with to create the file if it does not exist. 
                                                          
    
    additional.text := "mark is here."
    

    file.write(file.descriptor, buffer, result)               -- write text to file. 
    file.write(file.descriptor, additional.text, result)      -- write more text to file.
    file.write(file.descriptor, "and he brought some friends... and some cookies*n*n", result)
    
    

    file.close(file.descriptor, result) 



    buffer := MOBILE [512]BYTE                                -- super massive because we dont know how much text there is in file. 
    file.reader(file.name, file.descriptor, buffer)           -- read and output the contents

    CLAIM out!
      SEQ
        out.string("*n*n", 0, out!)
        out.string(buffer, 0, out!)
  --}}}

:
