+
+
+## File access modes
+FAM_RO = 0
+FAM_WO = 1
+FAM_RO_CFA = defConst("R/O", FAM_RO)
+FAM_WO_CFA = defConst("W/O", FAM_WO)
+
+function fileOpener(create::Bool)
+ fnameLen = popPS()
+ fnameAddr = popPS()
+ fam = popPS()
+
+ fname = getString(fnameAddr, fnameLen)
+
+ if create && !isfile(fname)
+ pushPS(0)
+ pushPS(-1) # error
+ return NEXT
+ end
+
+ if (fam == FAM_RO)
+ mode = "r"
+ else
+ mode = "w"
+ end
+
+ openFiles[nextFileID] = open(fname, mode)
+ pushPS(nextFileID)
+ pushPS(0)
+
+ nextFileID += 1
+end
+
+OPEN_FILE_CFA = defPrimWord("OPEN-FILE", () -> begin
+ fileOpener(false)
+ return NEXT
+end);
+
+CREATE_FILE_CFA = defPrimWord("CREATE-FILE", () -> begin
+ fileOpener(true)
+ return NEXT
+end);
+
+CLOSE_FILE_CFA = defPrimWord("CLOSE-FILE", () -> begin
+ fid = popPS()
+ close(openFiles[fid])
+ delete!(openFiles, fid)
+ return NEXT
+end)
+
+CLOSE_FILES_CFA = defPrimWord("CLOSE-FILES", () -> begin
+ for fh in values(openFiles)
+ close(fh)
+ end
+ empty!(openFiles)
+
+ return NEXT
+end)
+
+READ_LINE_CFA = defPrimWord("READ-LINE", () -> begin
+ fid = popPS()
+ maxSize = popPS()
+ addr = popPS()
+
+ fh = openFiles[fid]
+ line = readline(fh)
+
+ eofFlag = endswith(line, '\n') ? 0 : -1
+ line = chomp(line)
+
+ putString(line, addr, maxSize)
+
+ pushPS(length(line))
+ pushPS(eofFlag)
+ pushPS(0)
+
+ return NEXT
+end)
+