-- ChipAppendNames.mesa

-- Subroutines to append the names of various things to
-- strings.

-- last modified by E. McCreight, September 12, 1983  11:26 AM
-- written by E. McCreight, November 3, 1981  3:06 PM

DIRECTORY
  ChipNetDefs,
  ChipUserInt,
  InlineDefs,
  ppdefs,
  StringDefs;

ChipAppendNames: PROGRAM
  IMPORTS ChipNetDefs, ChipUserInt, InlineDefs,
    ppdefs, StringDefs
  EXPORTS ChipNetDefs =
  BEGIN OPEN ppdefs, ChipNetDefs;


  AppendNet: PUBLIC PROCEDURE[s: STRING, net: netPtr]
    RETURNS[cn: CanonNetPtr] =
    BEGIN OPEN StringDefs;
    cn ← CanonNet[net];
    WITH did: (cn ← CanonNet[net]).id SELECT FROM
      normal => AppendNetId[s, @did];
      ENDCASE => ChipUserInt.Explain["Extractor bug - bogus net"];
    END;


  nextNumericNet: locNum ← 1;

  AppendNetId: PUBLIC PROCEDURE[s: STRING,
    netId: NormalNetIdPtr] =
    BEGIN OPEN StringDefs;
    IF netId.nameClass=anonymous THEN
      BEGIN
      netId.name ← numeric[n: nextNumericNet];
      nextNumericNet ← nextNumericNet+1;
      END;

    WITH dn: netId SELECT FROM
      numeric => {AppendChar[s, 'N]; AppendCard[s, dn.n]};
      qualified => AppendTerminalName[s, [dn.source, dn.see]];
      named => AppendAtom[s, dn.name];
      ENDCASE => ERROR;
    END; -- of AppendNetId


  AppendTerminalName: PUBLIC PROCEDURE[s: STRING,
    c: ItemRef] =
    BEGIN OPEN StringDefs;
    oldLen: CARDINAL ← s.length;
    AppendCallerChain[s, c.head];
    IF s.length>oldLen THEN AppendChar[s, '.];
    AppendLongString[s, AtomToString[FindPropValue[ItemRefToLp[c], signalName]]];
    END; -- of AppendTerminalName


  AppendCallerChain: PUBLIC PROCEDURE[s: STRING,
    c: InstancePtr] =
    BEGIN OPEN StringDefs;
    IF c.caller.head#NIL THEN
      BEGIN
      oldLen: CARDINAL ← s.length;
      AppendCallerChain[s, c.caller.head];
      IF s.length>oldLen THEN AppendChar[s, '.];
      AppendCallerLink[s, c];
      END;
    END; -- of AppendCallerChain


  AppendCallerLink: PUBLIC PROCEDURE[s: STRING,
    c: InstancePtr] =
    BEGIN OPEN StringDefs;
    v: Atom ← FindPropValue[ItemRefToLp[c.caller], instanceName];
    lp: listPtr ← ItemRefToLp[c.caller];
    i: CARDINAL ← 1;
    IF v#NIL THEN AppendLongString[s, AtomToString[v]]
        -- assumes instances are named uniquely
    ELSE -- anonymous instance
      BEGIN
      WITH dob: lp.ob SELECT FROM
        cell =>
          BEGIN
          sameCellCnt: CARDINAL ← 0;
          IF c.proto.name#NIL THEN
            AppendString[s, c.proto.name]
          ELSE
            BEGIN
            cellNo: CARDINAL ← 1;
            AppendString[s, "AnonCell"];
            FOR ob: LONG POINTER TO cell object ←
              GetCellSuper[], ob.super
              WHILE ob#lp.ob AND ob#NIL DO
              cellNo ← cellNo+1;
              ENDLOOP;
            AppendCard[s, cellNo];
            END;
          FOR lpp: listPtr ← c.caller.head.proto.lp, lpp.nxt
            WHILE lpp#NIL DO
            IF lpp.ob=lp.ob THEN
              BEGIN
              sameCellCnt ← sameCellCnt+1;
              IF (lpp.lx<lp.lx OR (lpp.lx=lp.lx AND lpp.ly<lp.ly))
                THEN i ← i+1;
              END;
            ENDLOOP;
          IF sameCellCnt>1 THEN
            {AppendChar[s, '#]; AppendCard[s, i]};
          END;
        xstr =>
          BEGIN
          AppendString[s, "Q"];
          FOR lpp: listPtr ← c.caller.head.proto.lp, lpp.nxt
            WHILE lpp#NIL DO
            IF lpp.ob.otyp=xstr AND
              (lpp.lx<lp.lx OR (lpp.lx=lp.lx AND lpp.ly<lp.ly))
              THEN i ← i+1;
            ENDLOOP;
          AppendCard[s, i];
          END;
        cont =>
          BEGIN
          AppendString[s, "J"];
          FOR lpp: listPtr ← c.caller.head.proto.lp, lpp.nxt
            WHILE lpp#NIL DO
            IF lpp.ob.otyp=cont AND
              (lpp.lx<lp.lx OR (lpp.lx=lp.lx AND lpp.ly<lp.ly))
              THEN i ← i+1;
            ENDLOOP;
          AppendCard[s, i];
          END;
        bus =>
          BEGIN
          AppendString[s, "Bus"];
          FOR lpp: listPtr ← c.caller.head.proto.lp, lpp.nxt
            WHILE lpp#NIL DO
            IF lpp.ob.otyp=bus AND
              (lpp.lx<lp.lx OR (lpp.lx=lp.lx AND lpp.ly<lp.ly))
              THEN i ← i+1;
            ENDLOOP;
          AppendCard[s, i];
          END;
        ENDCASE => NULL;
      END;
    END; -- of AppendCallerLink


  AppendLocNum: PUBLIC PROCEDURE[s: STRING, n: locNum] =
    BEGIN OPEN StringDefs;
    AppendChar[s, ' ];
    IF n<0 THEN {AppendChar[s, '-]; n ← -n};
    AppendCard[s, n/Lambda];
    END;

  AppendCoord: PUBLIC PROCEDURE[s: STRING, n: Coord] =
    BEGIN OPEN StringDefs;
    AppendChar[s, ' ];
    IF n<0 THEN {AppendChar[s, '-]; n ← -n};
    AppendCard[s, n];
    END;

  AppendCard: PUBLIC PROCEDURE[s: STRING,
    n: LONG CARDINAL] =
    BEGIN OPEN StringDefs;
    IF n>9 THEN {AppendCard[s, n/10]; n ← n MOD 10};
    AppendChar[s, '0+InlineDefs.LowHalf[n]];
    END;

  AppendLongString: PUBLIC PROC [to, from: LONG STRING] =
    BEGIN
    FOR i: CARDINAL IN [0..from.length) DO
      to[to.length+i] ← from[i];
      ENDLOOP;
    to.length ← to.length+from.length;
    END;

  AppendAtom: PUBLIC PROC [s: LONG STRING, atom: Atom] =
    {AppendLongString[to: s, from: LOOPHOLE[atom, LONG STRING]]};

  FindPropValue: PUBLIC PROC [lp: listPtr, attribute: Atom] RETURNS [value: Atom] =
    BEGIN
    IF lp#NIL THEN
      FOR p: propPtr ← lp.props, p.next WHILE p#NIL DO
        IF p.attribute=attribute THEN RETURN[p.value];
        ENDLOOP;
    RETURN[NIL];
    END;

  signalName: PUBLIC Atom = MakeAtom["Signal name"];
  instanceName: PUBLIC Atom = MakeAtom["Instance name"];

  END. -- of ChipAppendNames