Makrá #
Prostredie CircuitMacros je rozšírením programovacieho jazyka dpic určeného pre kreslenie diagramov a grafov (staršia verzia je označovaná ako gpic) pomocou súboru makier pre makroprocesor m4. Makrá môžeme považovať za malé programy alebo skripty, ktorými sú nahradzované ich mená pri ich použití v hlavnom programe. Pomocou rozšírenia jazyka dpic makrami je možné vytvárať elektrické zapojenia a schémy, zároveň je možné v nich používať aj grafické prvky jazyka dpic.
Makroprocesor m4
Makroprocesor je univerzálny program pre spracovanie makier široko využívaný v programátorskej praxi najmä pri jazykoch nižšej úrovne a assembleroch. Makrá nachádzajú uplatnenie v rôznych implementáciách aj v textových a tabulkových procesoroch. Makroprocesor kopíruje vstupný text zo vstupu na výstup a popritom prí nájdení mena vopred definovaného makra
nahrádza meno makra textom z definície makra
nahrádza parametre makra ich hodnotami
vkladá súbory
prevádza manipulácie s textovými reťazcami
vyhodnocuje podmienky
vyhodnocuje aritmetické výrazy
Refenčnou implementáciou makroprocesora m4 je GNU M4.
Makrá definované v knižniciach CircuitMacros expandujú značky elektronických prvkov do množiny príkazov jazyka dpic, z vytvoreného programu je pomocou interpreteru príkazov vygenerovaný výsledný obrázok vo zvolenom rastrovom alebo vektorovom formáte.
Obr. 35 Postup generovania obrázkov.#
Warning
Kódy makier sú v podstate pomenované textové reťazce, ktorými nahrádza makrorocesor pred samotným spracovaním zdrojového kódu všetky časti zdrojového kódu zhodné s menom makra. Táto substitúcia je čisto mechanická, bez ohľadu na kontext v ktorom sa text zhodný s menom makra vyskytuje. Toto môže spôsobiť pri interpretácii kódu chybu, ktorá je spôsobená substitúciou makra na nevhodnom mieste a to aj napriek tomu, že kód programu je formálne syntakticky správny.
R1: resistor;
"terminal resistor" at R1.c above; # chyba, substitucia v texte
Pre odstránenie tejto chyby je potrebné vhodným spôsobom pozmeniť text tak, aby makroprocesor text nenahrádzal, napríklad
"terminal res\\istor" at R1.c above; # dve lomítka \\ sú pri zobrazení ignorované
Použitie makier #
Makrá sa definujú podľa syntaxe makroprocesora m4. Všeobecný tvar makra je
define (name, [expansion])
Reťazec name je nahradený reťazcom expansion, typ úvodzoviek v makre je dôležitý. Príklad
define(`foo', `Hello world.')
po spracovaní dostaneme
foo
Hello world.
Poznámka
Substitučné reťazce v makrách m4 začínajú znakom spätného apostrofu chr(96) a končia znakom apostrofu chr(39). Textové reťazce v jazyku dpic začínajú a končia úvodzovkami ".
Makro môže mať argumenty, tieto sú označované ako $1, $2 … , špeciálny význam má argument označený ako $0, ktorý obsahuje meno makra. Príklad makra, ktoré vymení poradie argumentov
define(`exch', `$2, $1')
po spracovaní dostaneme
exch(`arg1', `arg2')
arg2, arg1
Nasledujúci príklad ukazuje použitie makier.
# definicia makier
#--------------------------------------------
define(`text', `klukata ciara');
define(`zigzac', `[line up_ $1 right_ $1 then down_ $1 right_ $1 then up_ $1 right_ $1]' )
# pouzitie
#--------------------------------------------
move to (0.5,0.5); dot;
ZG: zigzac(0.5); zigzac(1);
"text" at ZG.n above;
Makro text je jednoducha nahrada reťazca. Makro zigzac má jeden parameter a pri jeho použití je jeho meno nahradené príkazom, argument je nahradený jeho hodnotou. Uzatvorenie príkazov do hranatých zátvoriek […] znamená, že obsah príkazov v zátvorkách bude pokladaný za jeden zložený objekt.
Obr. 36 Príklad použitia makier#
Vytvorenie makra #
Pri tvorbe makier pre kreslenie vlastných prvkov zapojenia môžeme využiť nasledujúci vzor, v ktorom sú v makre vyhodnotené dva parametre
#----------------------------------------------
# vzor(n, c) - template pre makro
# n - numericky parameter
# c - znakovy parameter L|R|U|P
#----------------------------------------------
define(`vzor',`[
# kontrola existencie numerickeho parametra
# pri chybajucom parametri nahradenie default hodnotou
ifelse(defn(`par1'), $1, par1=1, par1=$1)
# vyber indexu 0...3 z preddefinovanej množiny parametrov L R U P
# pri neexistujucej ma index hodnotu -1
par2 = index(`LRUD', $3)
# vyhodnotenie pre hodnoty parametra podla hodnoty indexu
if <= 0 then { line -> left_ par1; }
if == 1 then { line -> right_ par1; }
if == 2 then { line -> up_ par1; }
if == 3 then { line -> down_ par1; }
]')
Makro defn() v predlohe vytvorí premennú par1 a skontroluje existenciu argumentu $1, ak tento neexistuje, ifelse priradí par1=1, ak existuje, tak potom jej priradí hodnotu par1=$1. Premenná par2 je inicializovaná hodnotou indexu z poľa dovolených parametrov. Makro pri použití pokrýva nasledujúce prípady
vzor; -> vzor(1,L)
vzor(); -> vzor(1,L)
vzor(2); -> vzor(2,L)
vzor(3,R); -> vzor(3,R)
vzor(,X); -> vzor(1,L)
vzor(,); -> vzor(1,L)
Nižšie je uvedené makro pre zobrazenie spínača s parametrami dĺžka spínača a ‘stav (ON, OFF) spínača. Aby bol komponent presne umiestnený v mriežke bez ohľadu na jeho aktuálne grafické zobrazenie, je vhodné ho umiestniť do neviditeľného boxu s fixnými rozmermi. Pre vonkajší box potom platia štandardné atribúty w,e,s,n,nw ….
Implementácie makra #
Nasledujúci príklad implementuje zobrazenie spínača s dvoma parametrami - dĺžka spínača a stavu zopnutia (ON, OFF) spínača. Aby bol komponent presne umiestnený v mriežke bez ohľadu na jeho aktuálne grafické zobrazenie, je vhodné ho umiestniť do neviditeľného boxu s fixnými rozmermi. Pre vonkajší box potom platia štandardné atribúty w,e,s,n,nw ….
Pre ilustráciu je zobrazený vonkajší box, ktorý umožňuje ukladanie komponentu v rastri, parameter invis spôsobi skrytie obrysu.
# horizontal switch
# usage:
# swh(length, ON | OFF );
define(`swh',`[
B: box ht 1 wid $1 dotted 0.04 #invis; # vonkajsi okraj pola 1. parametra
rr = 0.15;
p = 1.5;
C1: circle diameter rr at B.c + (rr/2 - p/4, 0)
C2: circle diameter rr at B.c + (-rr/2 + p/4, 0) fill 0;
line from C1.w to B.w
line from C2.e to B.e
ifinstr($2,OFF, # kontrola hodnoty 2. parametra
{ # stav OFF
line from C2.c to C1.c + (0, p/4)
},
{ # stav ON
line from C2.c to C1.c
}
);
]')
Vytvorené makro požívame ako akýkoľvek iný príkaz pre kreslenie prvkov zapojenia. Príklad použitia implmentovaného spínača je v nasledujúcom kóde, pre názornosť je ponechané zobrazenie vonkajšieho obrysu prvku.
move to (0.5, 2); right_;
swh(1, OFF);
line 0.5;
swh(1, ON);
line 0.5;
swh(2, OFF);
dot;
{ line up_ 1; right_; S1: swh(2, ON); "$S_1$" at S1.n; }
{ line down_ 1; right_; S2: swh(2, OFF); "$S_2$" at S2.n; }
Obr. 37 Makro a jeho použitie#
Modifikácia makra #
V niektorých prípadoch nepotrebujeme vytvárať nové makro, ale len rozšíriť existujúce makro o ďalši popis alebo grafiku. V niektoých zapojeniach napríklad je značka rezistora doplnená o označenie jeho výkonovej straty, ktorá môže súvisieť s jeho typom púzdra.
define(`res_025w', `[
R: resistor($1,$2,$3);
dx = 0.065*linewid;
line from R.c+(dx,-dx) to R.c+(-dx,dx);
]')