#!/bin/bash ulimit -t 5 ulimit -v 80000 export HOME=/tmp cd /tmp # read the config . /etc/pcblib.cgi.conf CGI=$CGI_param # import the lib . $pcb_rnd_util/cgi_common.sh gen() { cd $gendir ./$gen "$fp_params" } help_params() { awk -v "CGI=$CGI" "$@" ' BEGIN { prm=0 q="\"" fp_base=fp sub("[(].*", "", fp_base) thumbsize=1 } function urlencode(s) { gsub("[#]", "%23", s) return s } function proc_include(fn) { close(fn) while(getline < fn) proc_line() close(fn) } function proc_line() { if (/^[^\"]*@@include/) { proc_include(gendir $2) return } if ((match($0, "@@desc") || match($0, "@@params") || match($0, "@@purpose") || match($0, "@@example"))) { txt=$0 key=substr($0, RSTART, RLENGTH) sub(".*" key "[ \t]*", "", txt) HELP[key] = HELP[key] " " txt next } if (/@@thumbsize/) { sub(".*@@thumbsize", "", $0) if ($1 ~ ":") { sub("^:", "", $1) PDATA[$1,"thumbsize"] = $2 } else thumbsize=$1 return } if (/@@thumbnum/) { sub(".*@@thumbnum", "", $0) if ($1 ~ ":") { sub("^:", "", $1) PDATA[$1,"thumbnum"] = $2 } return } if (/@@param:/) { sub(".*@@param:", "", $0) p=$1 sub(p "[\t ]*", "", $0) PARAM[prm] = p PDESC[prm] = $0 prm++ return } # build PPROP[paramname,propname], e.g. PPROP[pin_mask, dim]=1 if (/@@optional:/ || /@@dim:/ || /@@bool:/) { key = $0 sub("^.*@@", "", key) val = key sub(":.*", "", key) sub("^[^:]*:", "", val) PPROP[val,key] = 1 return } # build PDATA[paramname,propname], e.g. PDATA[pin_mask, default]=123 if ((/@@default:/) || (/@@preview_args:/)) { key = $1 txt = $0 txt = substr(txt, length(key)+1, length(txt)) sub("^[ \t]*", "", txt) sub("^.*@@", "", key) val = key sub(":.*", "", key) sub("^[^:]*:", "", val) PDATA[val,key] = txt return } # build: # PDATAK[paramname,n]=key (name of the value) # PDATAV[paramname,n]=description (of the given value) # PDATAN[paramname]=n number of parameter values if (/@@enum:/) { key = $1 txt = $0 txt = substr(txt, length(key)+1, length(txt)) sub("^[ \t]*", "", txt) sub("^.*@@enum:", "", key) val = key sub(":.*", "", key) sub("^[^:]*:", "", val) idx = int(PDATAN[key]) PDATAK[key,idx] = val PDATAV[key,idx] = txt PDATAN[key]++ return } } { proc_line() } function thumb(prv, gthumbsize, lthumbsize, thumbnum ,lnk,lnk_gen, thumbsize,ann) { if (lthumbsize != "") thumbsize = lthumbsize else thumbsize = gthumbsize if (!thumbnum) ann="&annotation=none" lnk=q CGI "?cmd=" prv "&output=png&grid=none" ann "&thumb=" thumbsize q lnk_gen=q CGI "?cmd=" prv q print "" print "" print "" } END { if (header) { print "" HELP["@@purpose"] "" print "

" print HELP["@@desc"] } if (content) print "

" content "

" if ((print_params) && (HELP["@@params"] != "")) print "

Ordered list (positions): " HELP["@@params"] if (content) { print "" print "
name man
dat
ory
description value (bold: default)" for(p = 0; p < prm; p++) { name=PARAM[p] print "
" name if (PPROP[name, "optional"]) print "  " else print " yes" print "" PDESC[p] print "" vdone=0 if (PDATAN[name] > 0) { print "" for(v = 0; v < PDATAN[name]; v++) { print "
" isdef = (PDATA[name, "default"] == PDATAK[name, v]) if (isdef) print "" print PDATAK[name, v] if (isdef) print "" print "" PDATAV[name, v] if (PDATA[name, "preview_args"] != "") { prv= fp_base "(" PDATA[name, "preview_args"] "," name "=" PDATAK[name, v] ")" print "" thumb(prv, thumbsize, PDATA[name, "thumbsize"], PDATA[name, "thumbnum"]) } } print "
" vdone++ } if (PPROP[name, "dim"]) { print "Dimension: a number with an optional unit (mm or mil, default is mil)" if (PDATA[name, "default"] != "") print "
Default: " PDATA[name, "default"] "" vdone++ } if (PPROP[name, "bool"]) { print "Boolean: yes/no, true/false, 1/0" if (PDATA[name, "default"] != "") print "; Default: " PDATA[name, "default"] "" if (PDATA[name, "preview_args"] != "") { print "
" print "" print "
true:" thumb(fp_base "(" PDATA[name, "preview_args"] "," name "=" 1 ")", thumbsize, PDATA[name, "thumbsize"], PDATA[name, "thumbnum"]) print "false:" thumb(fp_base "(" PDATA[name, "preview_args"] "," name "=" 0 ")", thumbsize, PDATA[name, "thumbsize"], PDATA[name, "thumbnum"]) print "
" } } if (!vdone) print " " } print "
" } if (footer) { print "

Example

" print "" print HELP["@@example"] print "" print "" } } ' } help() { local incl n echo "

pcblib-param help for $QS_cmd()

" incl=`tempfile` # generate the table help_params -v "fp=$QS_cmd" -v "header=1" -v "content=$gen parameters" -v "print_params=1" -v "gendir=$gendir" < $gendir/$gen # generate the footer help_params -v "fp=$QS_cmd" -v "footer=1" -v "gendir=$gendir" < $gendir/$gen 2>/dev/null } list_gens() { awk -v "CGI=$CGI" ' BEGIN { q="\"" } /@@purpose/ { sub(".*@@purpose", "", $0) PURPOSE[FILENAME] = PURPOSE[FILENAME] $0 next } /@@example/ { sub(".*@@example", "", $0) EXAMPLE[FILENAME] = EXAMPLE[FILENAME] $0 next } /@@params/ { sub(".*@@params", "", $0) PARAMS[FILENAME] = PARAMS[FILENAME] $0 next } function urlencode(s) { gsub("[#]", "%23", s) return s } END { for(fn in PURPOSE) { gn=fn sub(".*/", "", gn) params=PARAMS[fn] sub("^[ \t]*", "", params) sub("[ \t]*$", "", params) print "
  • " gn "(" params ") - " PURPOSE[fn] print "- HELP " } } ' $gendir/* } qs=`echo "$QUERY_STRING" | tr "&" "\n"` for n in $qs do exp="QS_$n" export $exp done export QS_cmd=`echo "$QS_cmd" | url_decode` if test -z "$QS_cmd" then export QS_cmd='connector(2,3)' gen=connector else gen=`awk -v "n=$QS_cmd" ' BEGIN { sub("[(].*", "", n) gsub("[^a-zA-Z0-9_]", "", n) print n } '` ptmp=`grep "@@purpose" $gendir/$gen` if test -z "$ptmp" then error "Invalid generator \"$gen\" (file)" fi fi if test "$QS_output" = "help" then echo "Content-type: text/html" echo "" help exit fi fp_params=`echo $QS_cmd | sed "s/.*[(]//;s/[)]//" ` export fp_full="$gen($fp_params)" fptext=`gen` if test ! "$?" = 0 then echo "Content-type: text/plain" echo "" echo "Error generating the footprint:" gen 2>&1 | grep -i error exit fi if test "$QS_output" = "text" then echo "Content-type: text/plain" echo "" gen exit fi if test "$QS_output" = "png" then cgi_png exit fi echo "Content-type: text/html" echo "" echo "" echo "" echo "

    pcblib-param test page

    " echo '
    "Do you remember the good old days? When I was
    young, I said footprint=CONNECTOR 2 13
    in gschem and got a 2*13 pin connector in PCB."

     
     

    Syntax

    In pcb-rnd, automatic footprint generation on the fly is called "parametric footprints". It is a smaller and more generic infrastructure compared to the m4 footprints in pcb. The goal was to fix three problems.

    • 1. Languages: m4 should not be mandatory for footprint generators - the user should be free to choose any language
    • 2. Simplicity: references to m4 should not be hardwired in pcb, gsch2pcb and gsch2pcb.scm, but footprint generation should be generic, transparent and external
    • 3. Unambiguity: gsch2pcb should not be guessing whether to use file elements or call a generator. Instead of complex heuristics, there should be a simple, distinct syntax for parametric footprints.

    The new syntax is that if a footprint attribute contains parenthesis, it is a parametric footprint, else it is a file footprint. Parametric footprints are sort of a function call. The actual syntax is similar to the one in openscad : parameters are separated by commas, and they are either positional (value) or named (name=value).

    For example a simple pin-grid connector has the "prototype" of connector(nx, ny, spacing), where nx and ny are the number of pins needed in X and Y directions, spacing is the distance between pin centers, with a default of 100 mil. The following calls will output the same 2*3 pin, 100 mil footprint:

    • connector(2, 3)
    • connector(2, 3, 100)
    • connector(nx=2, ny=3, spacing=100)
    • connector(spacing=100, nx=2, ny=3)
    • connector(ny=3, spacing=100, nx=2)
       

    Generators available

      ' list_gens echo '
    ' echo "

    Try it online

    " echo "source:" echo "
    " echo "" echo "" echo "

    " echo "" echo "

    " QS_format=${QS_cmd##*_} QS_cmd_=${QS_cmd%%_*} if test ! -z "$QS_cmd" then echo "

    Result

    " echo "

    $QS_cmd

    " echo "" echo "
    " echo "" echo "     " echo "" echo "
    "
    	echo "$fptext"
    	echo "
    " echo "

    Downloads:" echo "
    footprint file" echo "

    " fi echo "" echo ""