Hlavní navigace

Makro procesor GNU m4 (9)

Michal Burda

Dnes nás čekají tato témata: spouštění příkazů Unixu, generování jedinečných jmen souborů, chybová hlášení, ukládání vstupu pro pozdější zpracování a další...

Spouštění příkazů Unixu

Makro procesor m4 obsahuje několik vestavěných maker, která umožňují přímo ze zdrojového textu volat příkazy Unixu. Nejjednodušším makrem, které to umožňuje, je syscmd:

syscmd(příkaz shellu)

Makro syscmd vykoná příkaz shellu, který mu předáte jako argument. Výsledkem expanze je prázdný řetězec, ne výsledek příkazu. Výstup a chybová hlášení příkazu nejsou makro procesorem čtena (k tomu slouží jiné makro).

Standardní vstup, výstup a chybový výstup makro procesoru jsou při vykonávání přímo napojeny na spouštěný příkaz.

   syscmd(`ls')
=> Makefile
=> test.txt
=> dopis1.m4
=> dopis2.m4

Makro syscmd je rozpoznáváno jen s argumenty.

Chcete-li výstup externího programu ještě nějak zpracovávat, použijte místo syscmd makro esyscmd.

esyscmd(příkaz shellu)

esyscmd expanduje na to, co daný příkaz zapíše na svůj standardní výstup. Standardní vstup a standardní chybový vstup příkazu se opět napojí na I/O makro procesoru, což znamená, že zahlásí-li příkaz chybu, nedostanete ji jako výsledek expanze, ale objeví se mezi chybami samotného m4.

   define(`dnesni_datum', `esyscmd(`date "+%d. %m. %Y"')')
=>
   dnesni_datum
=> 16. 11. 2001

Rozdíl mezi syscmd a esyscmd je nejlépe vidět na následujícím příkladu:

   define(`soubory', sysmd(`ls'))
=> Makefile
=> test.txt
=> dopis1.m4
=> dopis2.m4
=>
   soubory
=>
   define(`soubory', esysmd(`ls'))
=>
   soubory
=> Makefile
=> test.txt
=> dopis1.m4
=> dopis2.m4
=>

Upozorňuji, že se snažíme definovat makro makro na seznam souborů v aktuálním adresáři, ne na volání makra sysmd (popř. esysmd).

I esysmd je rozpoznáváno jen s argumenty.

V souvislosti s vykonáváním příkazů Unixu obsahuje m4 ještě jedno vestavěné makro:

sysval

Jeho expanzí je návratový kód posledního externího příkazu vykonaného pomocí syscmd nebo esyscmd.

   syscmd(`false')
=>
   sysval
=> 1
   syscmd(`true')
=>
   sysval
=> 0

Generování jmen dočasných souborů

Příkazy Unixu mohou požadovat jako své argumenty nějaké dočasné soubory. V makrech procesoru m4 může vyvstat problém, jaká jména pro takové soubory zvolit, aby nedošlo ke kolizi mezi několika uživateli.

m4 obsahuje vestavěné makro maketemp, které generuje jedinečné názvy souborů.

maketemp(template)

Makro maketemp expanduje na název neexistujícího souboru. Název je vytvořen ze zadané šablony, která by měla končit řetězcem XXXXXX. Těchto šest X se nahradí něčím, co název souboru učiní jedinečným.

   maketemp(`/tmp/moje_XXXXXX')
=> /tmp/moje_zc7EU8
   maketemp(`/tmp/moje_XXXXXX')
=> tmp/moje_MEHAkw

Pozor! Znaků X musí být opravdu šest (nebo víc) a musí být na konci! Jinak se nevygeneruje nic.

   maketemp(`/tmp/moje_XXX')
=>
   maketemp(`/tmp/moje_XXXXXXXXX')
=> /tmp/moje_XXXFUhUGO
   maketemp(`/tmp/moje_XXXXXX.txt')
=>

Makro maketemp je rozpoznáváno jen s argumenty.

Tisk chybových hlášení

Přímo pomocí volání expanze specializovaných maker můžete makro procesor m4 donutit k tomu, aby na standardní chybový výstup vypsal hlášení o chybě. Asi ani nemusím připomínat, jak je to užitečné při ošetřování nesmyslných vstupů pro vlastní makra. Jednoduše použijte vestavěné makro errprint a chybové hlášení je na světě:

errprint(řetězec, ...)

Makro errprint vypíše hodnoty všech svých parametrů na standardní chybový výstup. Pozor na fakt, že na konec se automaticky NEpřidává znak nového řádku (kromě verze pro BSD) – a tak si musíme pomoci sami:

   errprint(`Čtvrtý argument musí být číslo!
   ')
=>
E> Čtvrtý argument musí být číslo!

Aby chybové hlášení sloužilo ještě lépe, můžete je obohatit informací o jménu souboru a čísle řádku, kde se chyba stala. Vestavěná makra

__file__
__line__

totiž přesně na tyto údaje expandují.

   define(`m4nl', `
   ')
=>
   define(`obycejna_chyba',
          `errprint(`Chyba:'__file__:__line__:$@`'m4nl)')
=>
   Obyčejný text...
=> Obyčejný text...
   Pozor, chyba: obycejna_chyba(`Chybička se vloudí')
=> Pozor, chyba:
E> Chyba:stdin:6:Chybička se vloudí
   Obyčejný text...
=> Obyčejný text...

Předčasné ukončení m4

Pokud potřebujete ukončit zpracování textu ještě dřív, než bude přečten celý vstup, sáhněte po makru

m4exit([návratový_kód])

Toto makro zapříčiní, že se m4 ihned ukončí a systému předá stanovený návratový kód. Pokud návratový kód neuvedete, použije se 0.

   define(`fatalni_chyba',
          `errprint(`Fatální chyba:'__file__:__line__:$@`'m4nl)m4exit(1)')
=>
   Obyčejný text...
=> Obyčejný text...
   Pozor, chyba: fatalni_chyba(`Chybička se vloudí')
=> Pozor, chyba:
E> Fatální chyba:stdin:4:Chybička se vloudí

Makro m4exit je určeno jen pro předčasné ukončování zpracování kvůli chybám, protože se neprovádějí akce, které makro procesor vykonává po normálním skončení čtení. Tj. uložený vstup není načítán a uchovaný výstup není odeslán (o co jde, viz později).

Ukládání vstupu pro pozdější zpracování

V makro procesoru m4 je možné nějaký text „odložit“ pro pozdější zpracování, až se vyčerpá veškerý normální vstup.

m4wrap(řetězec, ...)

Text uložený makrem m4wrap si makro procesor m4 uloží a začne ho číst, až narazí na konec svého normálního vstupu. Potom se uchované řetězce začnou zpracovávat (a expandovat), jako by šlo o pokračování vstupu. Tato vlastnost se používá hlavně k zavolání „úklidových“ maker, například pro smazání dočasných souborů a podobně.

   define(`uklid', `Nějaká úklidová akce')
=>
   m4wrap(`uklid')
=>
   Text, text, text, text, text...
=> Text, text, text, text, text...
   ^D
=> Nějaká úklidová akce

(V ukázce řetězec ^D znamená stisk kláves CTRL+D, což, jak jistě víte, má v Unixu význam konce souboru.)

Jak již bylo zmíněno dříve, uložený vstup je na konci čten jen v případě normálního ukončení činnosti makro procesoru. Vynuceným koncem zpracování pomocí m4exit se zpracování uloženého vstupu přeskočí.

Uložené řetězce jsou zpracovávány v opačném pořadí, než v jakém byly registrovány.

   m4wrap(`jedna')
=>
   m4wrap(`dvě')
=>
   m4wrap(`tři')
=>
   ^D
=> třidvějedna

Pokračování příště.

Našli jste v článku chybu?
Vitalia.cz: Taky věříte na pravidlo 5 sekund?

Taky věříte na pravidlo 5 sekund?

Podnikatel.cz: K EET. Štamgast už peníze na stole nenechá

K EET. Štamgast už peníze na stole nenechá

Lupa.cz: Propustili je z Avastu, už po nich sahá ESET

Propustili je z Avastu, už po nich sahá ESET

Podnikatel.cz: V restauraci bez cigaret? Sněmovna kývla

V restauraci bez cigaret? Sněmovna kývla

120na80.cz: 5 nejčastějších mýtů o kondomech

5 nejčastějších mýtů o kondomech

Podnikatel.cz: Udávání kvůli EET začalo

Udávání kvůli EET začalo

Vitalia.cz: Paštiky plné masa ho zatím neuživí

Paštiky plné masa ho zatím neuživí

Podnikatel.cz: Udávání a účtenková loterie, hloupá komedie

Udávání a účtenková loterie, hloupá komedie

Podnikatel.cz: Podnikatelům dorazí varování od BSA

Podnikatelům dorazí varování od BSA

Vitalia.cz: Jsou čajové sáčky toxické?

Jsou čajové sáčky toxické?

Lupa.cz: Teletext je „internetem hipsterů“

Teletext je „internetem hipsterů“

Vitalia.cz: Nejlepší obranou při nachlazení je útok

Nejlepší obranou při nachlazení je útok

Měšec.cz: U levneELEKTRO.cz už reklamaci nevyřídíte

U levneELEKTRO.cz už reklamaci nevyřídíte

120na80.cz: Jmelí je více léčivé než jedovaté

Jmelí je více léčivé než jedovaté

Vitalia.cz: Jmenuje se Janina a žije bez cukru

Jmenuje se Janina a žije bez cukru

Lupa.cz: Co se dá měřit přes Internet věcí

Co se dá měřit přes Internet věcí

Vitalia.cz: Proč vás každý zubař posílá na dentální hygienu

Proč vás každý zubař posílá na dentální hygienu

120na80.cz: Na ucho teplý, nebo studený obklad?

Na ucho teplý, nebo studený obklad?

Měšec.cz: mBank cenzuruje, zrušila mFórum

mBank cenzuruje, zrušila mFórum

DigiZone.cz: Rádio Šlágr má licenci pro digi vysílání

Rádio Šlágr má licenci pro digi vysílání