-- Copyright (C) 1985, 1986  by Xerox Corporation. All rights reserved. 
-- CFormatIO.mesa
-- NFS	 2-Aug-85 17:10:34
-- MEW	 3-Mar-86  9:02:33
-- NFS   3-Mar-86 13:25:01

-- C library formatted I/O functions.

DIRECTORY
  Ascii USING [NUL],
  BucketAlloc USING [Alloc, Free],
  CFormatIOUtil USING [DoPrint, DoScan],
  CIOLib USING [],
  CRuntime USING [GetStdin, GetStdout],
  CString USING [CString, IncrBPointer, ReadByte, WriteByte],
  Stream USING [
    defaultObject, GetByteProcedure, Handle, Object, PutByteProcedure, PutChar],
  VarArgs USING [VaStart, VaEnd];

CFormatIO: PROGRAM
  IMPORTS BucketAlloc, CFormatIOUtil, CRuntime, CString, Stream, VarArgs
  EXPORTS CIOLib =
  {

  ParamFrame: TYPE = LONG POINTER TO ARRAY INTEGER [0..0) OF LONG UNSPECIFIED;
  StringStream: TYPE = LONG POINTER TO StringStreamObject;
  StringStreamObject: TYPE = RECORD [
    object: Stream.Object, string: CString.CString];

  fscanf: PUBLIC PROCEDURE RETURNS [INTEGER] = {
    pf: ParamFrame ← VarArgs.VaStart[];
    nMatch: INTEGER = CFormatIOUtil.DoScan[
      LOOPHOLE[pf[0]], LOOPHOLE[pf[1]], LOOPHOLE[@pf[2]]];
    [] ← VarArgs.VaEnd[pf];
    RETURN[nMatch];
    };

  scanf: PUBLIC PROCEDURE RETURNS [INTEGER ← 0] = {
    pf: ParamFrame ← VarArgs.VaStart[];
    nMatch: INTEGER = CFormatIOUtil.DoScan[
      CRuntime.GetStdin[], LOOPHOLE[pf[0]], LOOPHOLE[@pf[1]]];
    [] ← VarArgs.VaEnd[pf];
    RETURN[nMatch];
    };

  sscanf: PUBLIC PROCEDURE RETURNS [INTEGER ← 0] = {
    pf: ParamFrame ← VarArgs.VaStart[];
    inStream: Stream.Handle;
    nMatch: INTEGER;
    inStream ← LOOPHOLE[InStringStream[pf[0]]];
    nMatch ← CFormatIOUtil.DoScan[@inStream, LOOPHOLE[pf[1]], LOOPHOLE[@pf[2]]];
    BucketAlloc.Free[@inStream, SIZE[StringStreamObject]];
    [] ← VarArgs.VaEnd[pf];
    RETURN[nMatch];
    };

  fprintf: PUBLIC PROCEDURE RETURNS [INTEGER] = {
    charsPrinted: INTEGER;
    pf: ParamFrame ← VarArgs.VaStart[];
    charsPrinted ← CFormatIOUtil.DoPrint[
      LOOPHOLE[pf[0]], LOOPHOLE[pf[1]], LOOPHOLE[@pf[2]]];
    [] ← VarArgs.VaEnd[pf];
    RETURN[charsPrinted];
    };

  printf: PUBLIC PROCEDURE RETURNS [INTEGER] = {
    charsPrinted: INTEGER;
    pf: ParamFrame ← VarArgs.VaStart[];
    charsPrinted ← CFormatIOUtil.DoPrint[
      CRuntime.GetStdout[], LOOPHOLE[pf[0]], LOOPHOLE[@pf[1]]];
    [] ← VarArgs.VaEnd[pf];
    RETURN[charsPrinted];
    };

  sprintf: PUBLIC PROCEDURE RETURNS [CString.CString] = {
    -- sprintf returns the string passed in.
    pf: ParamFrame ← VarArgs.VaStart[];
    charsPrinted: INTEGER;
    outStream: Stream.Handle;
    copyString: CString.CString ← LOOPHOLE[pf[0]];
    outStream ← LOOPHOLE[OutStringStream[pf[0]]];
    charsPrinted ← CFormatIOUtil.DoPrint[
      @outStream, LOOPHOLE[pf[1]], LOOPHOLE[@pf[2]]];
    Stream.PutChar[LOOPHOLE[outStream], Ascii.NUL];
    BucketAlloc.Free[@outStream, SIZE[StringStreamObject]];
    [] ← VarArgs.VaEnd[pf];
    RETURN[copyString];
    };

  InStringStream: PROCEDURE [string: LONG UNSPECIFIED]
    RETURNS [sStream: StringStream] = {
    sStream ← BucketAlloc.Alloc[SIZE[StringStreamObject]];
    sStream.object ← Stream.defaultObject;
    sStream.object.getByte ← ReadFromString;
    sStream.string ← LOOPHOLE[string];
    };

  OutStringStream: PROCEDURE [string: LONG UNSPECIFIED]
    RETURNS [sStream: StringStream] = {
    sStream ← BucketAlloc.Alloc[SIZE[StringStreamObject]];
    sStream.object ← Stream.defaultObject;
    sStream.object.putByte ← WriteToString;
    sStream.string ← LOOPHOLE[string];
    };

  ReadFromString: Stream.GetByteProcedure = {
    byte ← CString.ReadByte[SS[sH].string];
    SS[sH].string ← CString.IncrBPointer[SS[sH].string];
    };

  WriteToString: Stream.PutByteProcedure = {
    CString.WriteByte[byte, SS[sH].string];
    SS[sH].string ← CString.IncrBPointer[SS[sH].string];
    };

  SS: PROCEDURE [sH: Stream.Handle] RETURNS [StringStream] = INLINE {
    RETURN[LOOPHOLE[sH]]; };

  }.