Parseing PCL5

State Description
1. NotinPCL
2. Seen an Escape
3. Loaded a 2 char command
4. Loaded last term of commnd
5. Loaded last term with binary data
6. Loaded a term, another term waiting
7. Loaded a term with binary data, another term waiting

State First Second Value Parm Command Left in Buffer
3 X <esc>X
4 x X # X <esc>x#X
4 x X X <esc>xX
4 x y # Z <esc>xy#Z
6 x y # z <esc>xy#z#Z #Z

Delphi code:

function Buffer.PCLGet: boolean;
var
  Len: Word;
begin
{ Commented out?
  if PCLState > 2 then begin
      if PCLChrOne=PCLOldOne and PCLChrTwo=PCLOldTwo then begin
            Buffer.InsertP(Lower(PCLOldParm)
            Buffer.InsertS(ParmVal);
            PCLOldParm := PCLChrParm;
            end;
         else begin
            Buffer.InsertP(UpCase(PCLOldParm));
            Buffer.InsertP('#27'+PCLChrOne+PCLChrTwo


      PCLOldOne := PCLChrOne;
      PCLOldTwo := PCLChrTwo;
      Buffer.InsertS(ParmVal);
      PCLOldParm := PCLChrParm;
      end;
);

if PCLState in [1,3,4,5] and Data[0]=#27 then PCLState := 2;

if PCLState in [2,6,7] then begin
  ParmVal:='';
  if PCLState=2 then begin {starting a command, seen escape)
    PCLChrOne := Buffer.GetChar;
      if IsCharUpper(PCLChrOne) then
        PCLState := 3; (EOC on first character = 2 Char command)
      else begin
        PCLState := 6; {first term or 3 char command waiting}
        PCLChrOne := UpCase(PCLChrOne);
        ParmVal := Buffer.GetNum; {only sees a number on 3 char command)
        PCLChrTwo := Buffer.GetChar;
        if IsCharUpper(PCLChrTwo) then begin
          PCLChrParm := PCLChrTwo;
          PCLState := 4
        if Length(ParmVal)>O then begin
          PCLChrParm := UpCase(PCLChrTwo);
          end;
        end;
     end;
  if PCLState in [6,7] and Length(ParmVal) = O then begin (term waiting)
      ParmVal := Buffer.GetNum;
      PCLChrParm := Buffer.GetChar;
      if IsCharUpper(PCLChrParm) then
       PCLState := PCLState-2; {last term. 6 becomes 4, 7 becomes 5)
      else
        PCLChrParm := UpCase(PCLChrParm);
      end;
  if PCLState in [4,6,7] and PCLChrParm='W' then begin
     Len := ValS(ParmVal);
     Len := MinP(Len,EndPtr-BufPtr);
      Move(Binary, BufPtr[O], Len); Ilotta room for crashing here!)
      BufPtr := BufPtr+Len;
      PCLState := Min(PCLState +1,7); 14 becomes 5, 6 becomes 7~
    end;
  Buffer.Delete;
  PCLGet := True;
  end;
 else begin
  {We have ended a previous command and are being ask to load a PCL
  command but the escape character is not at the begining of the buffer
  indicating that something is wrong}
  PCLGet := False;
  end;
end;

Delphi PCLOut

State Description
1 Not in PCL
2 Stored an Escape
3 Stored a 2 char command
4 Stored last term of command
5 Stored last term with binary data
6 Stored a term, waiting for another term
7 Stored a term with binary data, waiting for another term

procedure Buffer.PCLPut;
var

Ptr: PChar;
begin
  Ptr := BufPtr;
  case PCLState of
  1..3: begin
{
Previously:
  1 Not in PCL
or 2 Seen an Escape
or 3 Loaded a 2 char command
With any of these, this is the first term of the new command
}
      if PCLState o 2 then Buffer.InsertS(#27); {not already passed the escape}
      Buffer.InsertS(PCLChrOne));
      if IsCharLower(PCLChrOne) then begin
      Buffer.InsertS(LowerCase(PCLChrTwo));
       Buffer.InsertS(ParmVal);
       Buffer.StuffS(UpCase(PCLChrParm));
       end;
      end;
   4..5: begin
{
or 4 Loaded last term of command
or 5 Loaded last term with binary data
}
      end;
   6..7: begin
{
Previously:
6 Loaded a term, another term waiting
or 7 Loaded a term with binary data, another term waiting
}
      end;
   end;

QBASIC

true = -1
false = 0
DataBinary = 0
DataText = 1
DataPCL = 2
DataUnknown = 3
DataMode = DataText

PCLStart = 0
PCLCmd = 1
PCLGrp = 2
PCLVal = 3
PCLPrm = 4
PCLUnknown = 5
PCLState = PCLUnknown

TYPE TextFile
 Chars AS STRING * 1
DIM MyFile AS TextFile
OPEN $ FOR RANDOM AS #1 LEN = LEN(MyFile)
inlen = LOF(1)
WHILE incount <= inlen
 incount = incount + 1
 GET #1, incount, MyFile
 in = ASC(MyFile.Chars)

 IF DataMode = DataPCL THEN
  PRINT #2, "CHAR '"; CHR$(in); "'";

  IF PCLState = PCLVal THEN
   SELECT CASE in
    CASE 43 'positive
     PCLSign = 1
     PRINT #2, "+"

    CASE 45  'negative
     PCLSign = -1
     PRINT #2, "-"

    CASE 46 'decimal
     PCLFrac = true
     PRINT #2, "."
    
    CASE 48 TO 57 'digit
     
     IF PCLFrac THEN
      PCLValueFrac = PCLValueFrac * 10
      PRINT #2, PCLValueFrac
      END IF
     PCLValue = PCLValue * 10 + (in - 48)
     PRINT #2, PCLValue
     
    CASE ELSE
     PCLPrms = PCLPrms + 1
     PCLValue(PCLPrms) = PCLValue * PCLSign
     PCLValueFrac(PCLPrms) = PCLValueFrac
     PCLValue = 0
     PCLSign = 1
     PCLFrac = false
     PCLValueFrac = 1
     PCLParm(PCLPrms) = ASC(UCASE$(MyFile.Chars)) - 64
     PRINT #2, " parm #"; PCLPrms
    END SELECT
   
   END IF

  IF PCLState = PCLGrp THEN
   PCLGroup = INSTR("abcdflprstuv", MyFile.Chars)
   PCLGr$ = MyFile.Chars
   PRINT #2, " group"
   PCLState = PCLVal
   END IF
 
  IF PCLState = PCLCmd THEN
   i = INSTR("=9EYZ", MyFile.Chars)
   IF i > 0 THEN
    PCLCommand = ASC(MID$(",-./+", i, 1)) - 32
    PRINT #2, " two-char"
    DataMode = DataUnknown
    PCLState = PCLUnknown
   ELSE
    PCLCommand = in - 32
    PCLState = PCLGrp
    PRINT #2, " parm-command"
    END IF
    
   END IF
  
  
  IF in > 64 AND in < 96 THEN 'Termination Character
   IF in = 87 THEN '=W so it is binary data
    DataMode = DataBinary
    BinaryLength = PCLValue(1)
    PCLState = PCLUnknown
   ELSE
    DataMode = DataUnknown 'we dont know what is next so mode is undefined
    PCLState = PCLUnknown
    END IF
   END IF

  
  GOTO nextchar
  END IF
   
 IF in = 27 AND DataMode <> DataBinary THEN
  DataMode = DataPCL
  PCLState = PCLCmd
  PCLPrms = 0
  PRINT #2, "pcl "
'  bitcount = bitcount + 4
  GOTO nextchar
  END IF

See:

Questions: