private static String smgObjectAsDot(SMGObject pObject, CLangSMG pSmg) {

    String valid = pSmg.isObjectValid(pObject) ? "" : " : invalid ";
    return pObject.getLabel()
        + " [ shape=rectangle, label = \""
        + pObject.toString()
        + valid
        + "\"];";
  }
  @Nullable
  private String smgScopeFrameAsDot(
      Map<String, SMGRegion> pNamespace, String pStructId, String pFunctionName) {
    StringBuilder sb = new StringBuilder();
    sb.append("struct" + pStructId + "[shape=record,label=\" ");

    // I sooo wish for Python list comprehension here...
    ArrayList<String> nodes = new ArrayList<>();
    for (Entry<String, SMGRegion> entry : pNamespace.entrySet()) {
      String key = entry.getKey();
      SMGObject obj = entry.getValue();

      if (key.equals("node")) {
        // escape Node1
        key = "node1";
      }

      nodes.add("<" + key + "> " + obj.toString());
      Location location = Location.valueOf(obj, pFunctionName);
      locationIndex.put(location, "struct" + pStructId + ":" + key);
    }

    Set<MemoryLocation> memoryLocations;

    if (pFunctionName == null) {
      memoryLocations = explicitState.getGlobalMemoryLocations();
    } else {
      memoryLocations = explicitState.getMemoryLocationsOnStack(pFunctionName);
    }

    for (MemoryLocation memloc : memoryLocations) {
      Location location = Location.valueOf(memloc);
      //  We don't consider values written into explicit cpa under the old
      //  Nomenclature
      if (!locationIndex.containsKey(location) && !location.location.contains("->")) {
        // We don't know the size of the memory location
        nodes.add("<" + memloc.getIdentifier() + "> " + memloc.getIdentifier());
        locationIndex.put(location, "struct" + pStructId + ":" + memloc.getIdentifier());
      }
    }

    sb.append(Joiner.on(" | ").join(nodes));
    sb.append("\"];\n");
    return sb.toString();
  }
  /**
   * Verifies several NULL object-related properties
   *
   * @param pLogger Logger to log the message
   * @param pSmg SMG to check
   * @return True if pSmg is consistent w.r.t. this criteria. False otherwise.
   */
  private static boolean verifyNullObjectCLangProperties(LogManager pLogger, CLangSMG pSmg) {
    // Verify that there is no NULL object in global scope
    for (SMGObject obj : pSmg.getGlobalObjects().values()) {
      if (!obj.notNull()) {
        pLogger.log(
            Level.SEVERE, "CLangSMG inconsistent: null object in global object set [" + obj + "]");
        return false;
      }
    }

    // Verify there is no more than one NULL object in the heap object set
    SMGObject firstNull = null;
    for (SMGObject obj : pSmg.getHeapObjects()) {
      if (!obj.notNull()) {
        if (firstNull != null) {
          pLogger.log(
              Level.SEVERE,
              "CLangSMG inconsistent: second null object in heap object set [first="
                  + firstNull
                  + ", second="
                  + obj
                  + "]");
          return false;
        } else {
          firstNull = obj;
        }
      }
    }

    // Verify there is no NULL object in the stack object set
    for (CLangStackFrame frame : pSmg.getStackFrames()) {
      for (SMGObject obj : frame.getAllObjects()) {
        if (!obj.notNull()) {
          pLogger.log(
              Level.SEVERE, "CLangSMG inconsistent: null object in stack object set [" + obj + "]");
          return false;
        }
      }
    }

    // Verify there is at least one NULL object
    if (firstNull == null) {
      pLogger.log(Level.SEVERE, "CLangSMG inconsistent: no null object");
      return false;
    }

    return true;
  }
  public String smgAsDot(CLangSMG smg, String name, String location) {
    StringBuilder sb = new StringBuilder();

    sb.append("digraph gr_" + name.replace('-', '_') + "{\n");
    offset += 2;
    sb.append(newLineWithOffset("label = \"Location: " + location.replace("\"", "") + "\";"));

    addStackSubgraph(smg, sb);

    for (SMGObject heapObject : smg.getHeapObjects()) {
      sb.append(newLineWithOffset(smgObjectAsDot(heapObject, smg)));
      locationIndex.put(Location.valueOf(heapObject), heapObject.getLabel());
    }

    // This only works after creating all heap Objects,
    // because we can't differentiate between global Memlocs and heap Memlocs
    addGlobalObjectSubgraph(smg, sb);

    Map<Integer, MemoryLocation> coveredBySMG = new HashMap<>();
    Set<MemoryLocation> coveredMemloc = new HashSet<>();

    for (SMGEdgeHasValue edge : smg.getHVEdges()) {

      SMGObject obj = edge.getObject();
      String functionName = smg.getFunctionName(obj);
      MemoryLocation memloc =
          smgState.resolveMemLoc(SMGAddress.valueOf(obj, edge.getOffset()), functionName);
      if (explicitState.contains(memloc)) {
        coveredBySMG.put(edge.getValue(), memloc);
        coveredMemloc.add(memloc);
      }
    }

    for (int value : smg.getValues()) {
      sb.append(newLineWithOffset(smgValueAsDot(value, coveredBySMG)));
    }

    Set<MemoryLocation> notCoveredBySMG = new HashSet<>();

    for (MemoryLocation memloc : explicitState.getTrackedMemoryLocations()) {
      // We don't consider values from the old Nomenclature in explicit cpa
      if (!coveredMemloc.contains(memloc) && !memloc.getAsSimpleString().contains("->")) {
        sb.append(newLineWithOffset(explicitValueAsDot(memloc)));
        notCoveredBySMG.add(memloc);
      }
    }

    for (SMGEdgeHasValue edge : smg.getHVEdges()) {
      sb.append(newLineWithOffset(smgHVEdgeAsDot(edge, smg)));
    }

    for (MemoryLocation memloc : notCoveredBySMG) {
      sb.append(newLineWithOffset(memlocAsDot(memloc)));
    }

    for (SMGEdgePointsTo edge : smg.getPTEdges().values()) {
      sb.append(newLineWithOffset(smgPTEdgeAsDot(edge, smg)));
    }

    sb.append("}");

    return sb.toString();
  }
 private Location(SMGObject pSmgObject) {
   location = pSmgObject.getLabel();
 }
 private Location(SMGObject pSmgObject, String functionName) {
   location = functionName + "::" + pSmgObject.getLabel();
 }