[Back to ENTRY SWAG index] [Back to Main SWAG index] [Original]

    {
    >Format is really a good function for use on output and it corresponds roughly
    >to the printf function in C, but I really need the corresponding input
    >function as well (scanf etc)
    >
    >does anyone know of such a function? I would hate to spend the time
    >reinventing the wheel, when I could be concentrating on other things.

    Here's my implementation of scanf:

    --------------------------------------------------------------------------}

    function sscanf(Input, Format : PChar; var ArgList) : PChar;
    type
      WordPtr = ^word;
      LongPtr = ^longint;
      PCharPtr = ^PChar;
    var
      DelimPos : PChar;
      ArgPtr : PChar;
      n : longint;
      FmtCmd : char;
      code : integer;
      LongCmd : boolean;
      LenStr : string[8];
      MaxLen : integer;
    begin
      sscanf := nil;
      ArgPtr := addr(ArgList);
      if (Format = nil) then Exit;
      while (Format^ <> #0) do begin
        if (Input = nil) or (Input^ = #0) then Exit; { ***ERROR }
        if Format^ = '%' then begin
          inc(Format);
          FmtCmd := Format^;

          if FmtCmd in ['0'..'9'] then begin
            LenStr := '';
            repeat
              LenStr := LenStr + FmtCmd;
              inc(Format);
              FmtCmd := Format^;
            until not (FmtCmd in ['0'..'9']);
            if LenStr <> '' then begin
              Val(LenStr, MaxLen, code);
              if code <> 0 then Exit;
            end;
          end else
            MaxLen := $7FFF;

          if FmtCmd = 'l' then begin
            LongCmd := true;
            inc(Format);
            FmtCmd := Format^;
          end else
            LongCmd := false;

          case FmtCmd of
            'c' : begin
              ArgPtr^ := Input^;
              inc(ArgPtr, 2);
            end;
            'd','i','u','s','*' : begin
              { look for delimiter }
              DelimPos := StrScan(Input, (Format+1)^);
              if DelimPos <> nil then begin
                if (DelimPos-Input > MaxLen) then Exit;
                DelimPos^ := #0; { zero delimiter }
              end;

              if FmtCmd = 's' then begin
                if PCharPtr(ArgPtr)^ = nil then { if dest. string is NIL }
                  PCharPtr(ArgPtr)^ := StrNew(Input) { then allocate a new one }
                else
                  StrCopy(PCharPtr(ArgPtr)^, Input); { else copy to dest buffer }
              end else
                if FmtCmd <> '*' then
                  Val(Input, n, code);

              if DelimPos <> nil then DelimPos^ := (Format+1)^; { set it back }
              case FmtCmd of
                's' : inc(ArgPtr, 4);
                '*' : ; { dummy }
              else
                if code <> 0 then Exit; { could not convert }
                if LongCmd then begin
                  LongPtr(ArgPtr)^ := n;
                  inc(ArgPtr, 4);
                end else begin
                  WordPtr(ArgPtr)^ := LongRec(n).Lo;
                  inc(ArgPtr, 2);
                end;
              end;
              Input := DelimPos; { move input pointer to delimiter }
            end;
          else
            Exit;
          end;
          inc(Format);
        end else begin
          if Input^ <> Format^ then Exit;
          inc(Format);
          inc(Input);
        end;
      end;
      sscanf := Input;
    end;

[Back to ENTRY SWAG index] [Back to Main SWAG index] [Original]