#! /bin/bash
# Last edited on 2021-02-28 20:33:58 by jstolfi

# Extracts a specific layer of a G-code file. 

layer="$1"; shift  # Layer number.
prefix="$1"; shift # Prefix of layer number line.
fname="$1"; shift  # File name.

name="${fname%%.*}"  # File name sans ".gcode".
xlayer=`printf "%06d" "${layer}"`

cat ${fname} \
  | gawk \
    -v layer="${layer}" \
    -v prefix="${prefix}" \
    ' BEGIN { 
        layer = layer + 0; 
        cur_layer = -9999; 
        np = length(prefix)
        nlast = 30
        split("",last) # {last[K % nlast]} is line {K} of file (from 1).
      }
      // { gsub(/[\015]/, "", $0) }
      (substr($0,1,np) == prefix) { 
        cur_layer = substr($0,np+1)
        gsub(/^[^-0-9]*/, "", cur_layer)
        gsub(/[,;].*$/, "", cur_layer)
        gsub(/[^0-9]*$/, "", cur_layer)
        cur_layer += 0
        if (cur_layer == layer) {
          # Print the last {nlast} lines to {stderr}:
          for (K = FNR - nlast; K < FNR; K++) {
            if (K > 0) { print last[K % nlast] > "/dev/stderr" }
          }
          # Print the layer header line
          print
          nok = 1
        }
        print > "/dev/stderr"
        printf "layer = %d\n", cur_layer > "/dev/stderr"
        next
      }
      /^ *[;]/ { 
        print > "/dev/stderr"
      }
      (cur_layer == layer) {
        if (match($0, /^ *G[01][ ][^;]*[Z]/)) { 
          # Z-move
          print "ignoring {Z}-move within layer" > "/dev/stderr"
          print > "/dev/stderr"
          # Erase the "Z" argument:
          gsub(/[Z][-+]?[.0-9]*/, "", $0)
          # If there is no other argument except speed, discard the line:
          gsub(/[;].*$/, "", $0)
          if (! match($0, /^ *G[01][ ] *([F][.0-9]+)? *$/)) {
            print "keeping XYE move:" > "/dev/stderr"
            print > "/dev/stderr"
            print
          }
        } else {
          print
          nok++
        }
        next
      }
      /^ *M1(0[4679]|[49]0)|G9[01]|G2[01]([ ;]|$)/ { 
        print
        print > "/dev/stderr"
        next
      }
      ((cur_layer != -9999) && (cur_layer < layer)) {
        last[FNR % nlast] = $0
      }
      END{ printf "%d lines extracted\n", nok > "/dev/stderr" }
    ' \
  > ${name}_${xlayer}.gcode
  
        
         
