-- BcdOpsImpl.mesa
-- Last Modified by Sandman,  July 17, 1980  11:55 AM 
-- Last Modified by Paul Rovner, 4-Feb-82 11:28:51 

DIRECTORY
  BcdDefs USING [
    Base, CTIndex, CTNull, CTRecord, EVIndex, EVNull, EVRecord, EXPIndex, EXPNull,
    EXPRecord, FTIndex, FTNull, FTRecord, IMPIndex, IMPNull, IMPRecord, Link, MTIndex,
    MTNull, MTRecord, Namee, NameRecord, NTIndex, NTNull, NTRecord, NullName,
    SGIndex, SGNull, SGRecord, SpaceID, SPIndex, SPNull, SPRecord, VersionStamp,
    FPIndex, FPRecord, FPNull],
  BcdOps USING [
    BcdBase, CTHandle, EVHandle, EXPHandle, FTHandle, IMPHandle, MTHandle,
    NTHandle, SGHandle, SPHandle, FPHandle];

BcdOpsImpl: PROGRAM EXPORTS BcdOps = PUBLIC

  BEGIN OPEN BcdOps, BcdDefs;

  ProcessConfigs: PROCEDURE [
    bcd: BcdBase, proc: PROCEDURE [CTHandle, CTIndex] RETURNS [BOOLEAN]]
    RETURNS [cth: CTHandle, cti: CTIndex] =
    BEGIN
    ctb: Base = LOOPHOLE[bcd + bcd.ctOffset];
    i: CARDINAL;
    cti ← FIRST[CTIndex];
    FOR i IN [0..bcd.nConfigs) DO
      cth ← @ctb[cti];
      IF proc[cth, cti] THEN RETURN;
      cti ← cti + SIZE[CTRecord] + cth.nControls;
      ENDLOOP;
    RETURN[NIL, CTNull];
    END;

  ProcessExternals: PROCEDURE [
    bcd: BcdBase, proc: PROCEDURE [EVHandle, EVIndex] RETURNS [BOOLEAN]]
    RETURNS [evh: EVHandle, evi: EVIndex] =
    BEGIN
    evb: Base = LOOPHOLE[bcd + bcd.evOffset];
    FOR evi ← FIRST[EVIndex], evi + SIZE[EVRecord] + evh.length UNTIL evi =
      bcd.evLimit DO evh ← @evb[evi]; IF proc[evh, evi] THEN RETURN; ENDLOOP;
    RETURN[NIL, EVNull];
    END;

  ProcessExports: PROCEDURE [
    bcd: BcdBase, proc: PROCEDURE [EXPHandle, EXPIndex] RETURNS [BOOLEAN]]
    RETURNS [eth: EXPHandle, eti: EXPIndex] =
    BEGIN
    etb: Base = LOOPHOLE[bcd + bcd.expOffset];
    i: CARDINAL;
    eti ← FIRST[EXPIndex];
    FOR i IN [0..bcd.nExports) DO
      eth ← @etb[eti];
      IF proc[eth, eti] THEN RETURN;
      eti ← eti + SIZE[EXPRecord] + eth.size;
      ENDLOOP;
    RETURN[NIL, EXPNull];
    END;

  ProcessFiles: PROCEDURE [
    bcd: BcdBase, proc: PROCEDURE [FTHandle, FTIndex] RETURNS [BOOLEAN]]
    RETURNS [fth: FTHandle, fti: FTIndex] =
    BEGIN
    ftb: Base = LOOPHOLE[bcd + bcd.ftOffset];
    FOR fti ← FIRST[FTIndex], fti + SIZE[FTRecord] UNTIL fti = bcd.ftLimit DO
      fth ← @ftb[fti]; IF proc[fth, fti] THEN RETURN; ENDLOOP;
    RETURN[NIL, FTNull];
    END;

  ProcessImports: PROCEDURE [
    bcd: BcdBase, proc: PROCEDURE [IMPHandle, IMPIndex] RETURNS [BOOLEAN]]
    RETURNS [ith: IMPHandle, iti: IMPIndex] =
    BEGIN
    itb: Base = LOOPHOLE[bcd + bcd.impOffset];
    i: CARDINAL;
    iti ← FIRST[IMPIndex];
    FOR i IN [0..bcd.nImports) DO
      ith ← @itb[iti];
      IF proc[ith, iti] THEN RETURN;
      iti ← iti + SIZE[IMPRecord];
      ENDLOOP;
    RETURN[NIL, IMPNull];
    END;

  ProcessModules: PROCEDURE [
    bcd: BcdBase, proc: PROCEDURE [MTHandle, MTIndex] RETURNS [BOOLEAN]]
    RETURNS [mth: MTHandle, mti: MTIndex] =
    BEGIN
    mtb: Base = LOOPHOLE[bcd + bcd.mtOffset];
    i: CARDINAL;
    mti ← FIRST[MTIndex];
    FOR i IN [0..bcd.nModules) DO
      mth ← @mtb[mti];
      IF proc[mth, mti] THEN RETURN;
      mti ← mti + (WITH m: mtb[mti] SELECT FROM
		     direct => SIZE[MTRecord[direct]] + m.length*SIZE[Link],
		     indirect => SIZE[MTRecord[indirect]],
		     multiple => SIZE[MTRecord[multiple]],
		    ENDCASE => ERROR)
      ENDLOOP;
    RETURN[NIL, MTNull];
    END;

  ProcessNames: PROCEDURE [
    bcd: BcdBase, proc: PROCEDURE [NTHandle, NTIndex] RETURNS [BOOLEAN]]
    RETURNS [nth: NTHandle, nti: NTIndex] =
    BEGIN
    ntb: Base = LOOPHOLE[bcd + bcd.ntOffset];
    FOR nti ← FIRST[NTIndex], nti + SIZE[NTRecord] UNTIL nti = bcd.ntLimit DO
      nth ← @ntb[nti]; IF proc[nth, nti] THEN RETURN; ENDLOOP;
    RETURN[NIL, NTNull];
    END;

  ProcessSegs: PROCEDURE [
    bcd: BcdBase, proc: PROCEDURE [SGHandle, SGIndex] RETURNS [BOOLEAN]]
    RETURNS [sgh: SGHandle, sgi: SGIndex] =
    BEGIN
    sgb: Base = LOOPHOLE[bcd + bcd.sgOffset];
    FOR sgi ← FIRST[SGIndex], sgi + SIZE[SGRecord] UNTIL sgi = bcd.sgLimit DO
      sgh ← @sgb[sgi]; IF proc[sgh, sgi] THEN RETURN; ENDLOOP;
    RETURN[NIL, SGNull];
    END;

  ProcessSpaces: PROCEDURE [
    bcd: BcdBase, proc: PROCEDURE [SPHandle, SPIndex] RETURNS [BOOLEAN]]
    RETURNS [sph: SPHandle, spi: SPIndex] =
    BEGIN
    spb: Base = LOOPHOLE[bcd + bcd.spOffset];
    FOR spi ← FIRST[SPIndex], spi + SIZE[SPRecord] + sph.length*SIZE[SpaceID]
      UNTIL spi = bcd.spLimit DO
      sph ← @spb[spi]; IF proc[sph, spi] THEN RETURN; ENDLOOP;
    RETURN[NIL, SPNull];
    END;

  FindName: PROCEDURE [bcd: BcdBase, owner: Namee] RETURNS [name: NameRecord] =
    BEGIN
    n: NTHandle;

    FindOwner: PROCEDURE [nth: NTHandle, nti: NTIndex] RETURNS [BOOLEAN] =
      BEGIN RETURN[owner = nth.item]; END;

    RETURN[
      IF (n ← ProcessNames[bcd, FindOwner].nth) = NIL THEN NullName ELSE n.name]
    END;

  ModuleVersion: PROCEDURE [bcd: BcdBase, mti: MTIndex]
    RETURNS [version: VersionStamp] =
    BEGIN
    mtb: Base = LOOPHOLE[bcd + bcd.mtOffset];
    ftb: Base = LOOPHOLE[bcd + bcd.ftOffset];
    RETURN[ftb[mtb[mti].file].version];
    END;

  ProcessFramePacks: PUBLIC PROC [bcd: BcdOps.BcdBase,
    proc: PROC [fph: BcdOps.FPHandle, fpi: BcdDefs.FPIndex] RETURNS [BOOLEAN]] 
    RETURNS [fph: BcdOps.FPHandle, fpi: BcdDefs.FPIndex] = {
    fpb: BcdDefs.Base = LOOPHOLE[bcd + bcd.fpOffset];
    FOR fpi: BcdDefs.FPIndex ← FIRST[BcdDefs.FPIndex], 
    fpi + SIZE[BcdDefs.FPRecord] + fph.length*SIZE[BcdDefs.MTIndex]
    UNTIL fpi = bcd.fpLimit DO
      fph ← @fpb[fpi];
      IF proc[fph, fpi] THEN RETURN[fph, fpi];
      ENDLOOP;
    RETURN[NIL, BcdDefs.FPNull]};


  END....