<html><head><meta name="color-scheme" content="light dark"></head><body><pre style="word-wrap: break-word; white-space: pre-wrap;">#!/bin/csh -f
#
# fretboard.csh - generate PostScript source to print fretboard diagram for
# any chromatic fretted string instrument in any tuning
#
# usage: fretboard.csh [-t title] [open_string_pitches]
#
# e.g.:
#
#	fretboard.csh -t "Mandolin" G D A E
#
# generates a diagram of a mandolin fretboard
#
# if fewer than three pitches are specified, script defaults to guitar in
# standard tuning
#
# valid pitches are [ABCDEFG], [ACDFG]#, [ABDEG]b (upper- or lower-case;
# sorry, Germans, no "H" yet...)
#
# output is to "stdout" for piping directly to a PostScript printer or
# previewer
#From: rogers@hi.com (Andrew Rogers)
#Date: Thu, 9 Nov 1995 14:06:50 -0500

set noglob
set openstrings = ()
set title = ""
set badnote = 0

while ($#argv)
	switch ($1)
	case "-t":
		shift
		set title = "$1"
		breaksw
	case "-*":
		/bin/sh -c "echo unrecognized flag $1 1&gt;&amp;2"
		breaksw
	case "[a-gA-G]":
	case "[acdfgACDFG]#":
	case "[abdegABDEG]b":
		set openstrings = ($openstrings $1)
		breaksw
	default:
		/bin/sh -c "echo unrecognized string pitch $1 1&gt;&amp;2"
		set badnote = 1
	endsw
	shift
end

if ($badnote != 0) then
	exit 1
endif

if ($#openstrings &lt; 3) then
	set openstrings = "E A D G B E"		# default: guitar, std. tuning
	set title = "Guitar (Standard)"
else
	set openstrings = `echo "$openstrings" | tr '[a-g]' '[A-G]' | sed 's/\([A-G]\)B/\1b/g'`
endif

# create PostScript array-of-strings for substitution below
set openstrings = `echo $openstrings | sed -e 's/  */) (/g' -e 's/^/(/' -e 's/$/)/'`
set title = `echo "$title" | sed -e 's/[()]/\\&amp;/g' -e 's/^/(/' -e 's/$/)/'`

# print PostScript boilerplate, substituting list of open string pitches
cat &lt;&lt; EOF
%!
%
% print fretboard diagram for any fretted stringed instrument
%
% fill in names of open strings (upper-case, followed by '#' for sharps, 'b'
% for flats - no B#, Cb, E#, or Fb yet) below and program will do the rest
%
%/openstrings [ (E) (A) (D) (G) (B) (E) ] def		% (example)
%/title (Guitar \(standard\)) def

/openstrings [ $openstrings ] def
/title $title def

/nutwidth 10 def			% width of nut
/fretwidth 4 def			% width of frets
/strwidth 2 def				% width of strings
/strgray 0.6 def			% gray scale of strings
/dotgray 0.9 def			% gray scale of dots
/nfrets 12 def				% number of frets
/fname /Helvetica-Bold def		% font name
/fsize 18 def				% main font size
/fsize2 14 def				% font size for enharmonic equivalents
/tsize 20 def				% title font size

/inch {72 mul} def
/W 0.5 inch def				% space between strings
/S 1 inch def				% space from nut to 1st fret
/R 1.059 def				% ratio for fret spacing (2 ** 1/12)
/D 0.25 inch def			% diameter of dots
/nstrings openstrings length def	% number of strings
/notes nstrings array def		% array of open string values (0-11)
/w W nstrings 1 sub mul def		% total width of fretboard
/X0 8.5 inch w sub 2 div def		% top left corner of fretboard
/Y0 9.75 inch def

% chromatic scale, with enharmonic equivalent pairs where appropriate
/chromatics [ [(C)] [(C#)(Db)] [(D)] [(D#)(Eb)] [(E)] [(F)] [(F#)(Gb)]
              [(G)] [(G#)(Ab)] [(A)] [(A#)(Bb)] [(B)] ] def

% frets/positions for drawing fretboard dots
/Left 1 def	/Ctr 2 def	/Right 3 def
/dotpos [ [3 Ctr] [5 Ctr] [7 Ctr] [9 Ctr] [12 Left] [12 Right] ] def

/center {        % show string centered at current point
  dup stringwidth pop 2 div neg 0 rmoveto show
} def

/showRJ {        % show string right-justified at current point
  dup stringwidth pop neg 0 rmoveto show
} def


% center title at top of fingerboard
fname findfont tsize scalefont setfont
X0 w 2 div add Y0 nutwidth add fsize 2 mul add moveto
title center

% draw nut
nutwidth setlinewidth
newpath
X0 strwidth sub Y0 nutwidth 2 div add moveto
w strwidth 2 mul add 0 rlineto stroke

% draw frets and dots ; print fret number to left of fingerboard (centered
% vertically)

/y Y0 def
/s S def
fretwidth setlinewidth
fname findfont fsize scalefont setfont

1 1 nfrets {				% loop over frets
  /fret exch def
  /y y s sub def
  X0 W sub y s fsize 0.75 mul sub 2 div add moveto
  fret 5 string cvs showRJ		% show fret number

  newpath				% draw fret
  X0 strwidth sub y moveto
  w strwidth 2 mul add 0 rlineto
  stroke

  dotpos {
    /dot exch def
    dot 0 get fret eq {
      newpath
      X0 w dot 1 get mul 4 div add y s 2 div add D 2 div 0 360 arc
      closepath
      dotgray setgray fill
      0 setgray
    } if
  } forall
  /s s R div def			% distance between next pair of frets
} for

/Y1 y fretwidth 2 div sub def		% save location of highest fret

% draw strings

strwidth setlinewidth			% set line width and gray scale
strgray setgray

0 1 nstrings 1 sub {			% loop over strings
  /n exch def
  /x X0 n W mul add def
  newpath
  x Y0 nutwidth add moveto
  x Y1 lineto
  stroke
} for

% print pitches of open strings; fill in 'notes' array with index of each
% into chromatic scale array

0 setgray
fname findfont fsize scalefont setfont

0 1 nstrings 1 sub {			% loop over strings
  /n exch def
  /note openstrings n get def		% print open string pitch over nut
  /x X0 n W mul add def
  x Y0 nutwidth 2 mul add moveto note center

  notes n -1 put			% -1: note unknown
  0 1 11 {				% loop over chromatic scale
    /i exch def
    chromatics i get {			% loop over all note names
      note eq { notes n i put } if	% fill in index if match
    } forall
  } for
  
} for

% print the pitch of the note at each fret

/y Y0 def
/s S def

1 1 nfrets {			% loop over frets
  /fret exch def
  /y y s sub def
  0 1 nstrings 1 sub {		% loop over strings
    /n exch def
    /x X0 n W mul add def
    /note notes n get def	% index into chromatic scale

    note -1 ne {		% ignore if open string not valid pitch
      /tmp chromatics note fret add 12 add 12 mod get def	% pitch(es)

      tmp length 1 eq {		% single pitch
        fname findfont fsize scalefont setfont
        x y s fsize 0.75 mul sub 2 div add moveto
        tmp 0 get center
      } {			% pair of enharmonic equivalents
        fname findfont fsize2 scalefont setfont
        x y s fsize2 1.75 mul sub 2 div add fsize2 add moveto
        tmp 0 get center	% print first (top)
        x y s fsize2 1.75 mul sub 2 div add moveto
        tmp 1 get center	% print second (bottom)
      } ifelse
    } if

  } for
  /s s R div def		% distance between next pair of frets

} for

showpage			% done - display page
EOF

exit 0</pre></body></html>