Zadanie 5 (termin oddania: 12 stycznia 2006, godz. 23:59)

Makrem (od angielskiego słowa "macro") nazywamy przyporządkowanie
nazwie pewnego tekstu, nazywanego treścią makra. Rozwinięciem makra
w tekście nazywamy zastąpienie jego nazwy treścią.
(Uwaga: to definicja uproszczona - często spotykamy mechanizmy makr
znacznie bardziej złożone, niż przedstawiony w tym zadaniu).

Napisz program który, wywołany z trzema argumentami będącymi nazwami
plików tekstowych, nazywanych dalej odpowiednio plikiem makr, plikiem
danych i plikiem wynikowym, utworzy plik wynikowy kopiując do niego
zawartość pliku danych i rozwijając przy tym makra zdefiniowane w pliku
makr.

W pliku makr zapisane są kolejno ich definicje, każda w oddzielnym
wierszu. Każdy wiersz rozpoczyna się od nazwy makra, będacej małą literą.
Reszta wiersza, aż do jego końca, jest treścią makra. Koniec wiersza do
treści makra już nie należy.

W pliku danych użycie makra oznaczamy pytajnikiem, po którym następuje
nazwa. Wystąpienie dwóch pytajników oznacza, że nie mamy tu do czynienia
z nazwą makra i do pliku wynikowego należy wpisać jeden pytajnik.

Użycie makra może też wystąpić w treści (innego) makra. Podczas
rozwijania jednego makra może się pojawic potrzeba rozwinięcia innego.

Np. jeśli w pliku makra.txt jest:

aAl?x
z?a ?m ?k
mm?x
kkot?x
xa

a w pliku dane.txt:

Czy ?z??
Tak. ?a ?k ?m.

to program wywołany poleceniem:

./zad5 makra.txt dane.txt wynik.txt

powinien utworzyć plik wynik.txt o zawartości:

Czy Ala ma kota?
Tak. Ala kota ma.

Uwagi:
Można założyć, że wiersze w pliku makr nie są długie, a więc całą
definicję makra można wczytać na zmienną typu string. Nie wolno jednak
przyjmować takiego założenia w stosunku do pliku danych i tym bardziej
pliku wynikowego, gdyż w rezultacie rozwinięcia makra możemy otrzymać
tekst bardzo długi.

Program powinien sprawdzać poprawność danych. Jedynym warunkiem, którego
badać nie trzeba, jest brak cyklu w definicji makr (chodzi o sytuację,
w której makro korzysta, bezpośrednio lub pośrednio, z siebie samego).
Program po stwierdzeniu błędu, powinien wypisać na standardowe wyjście
jeden wiersz ze słowem "BLAD" (bez cudzysłowów z L, a nie Ł).

Wskazówki:
Liczbę argumentów, które program otrzymał w chwili wywołania, daje
bezparametrowa funkcja "paramcount", a ich wartości funkcja
"paramstr(i)", gdzie "i" jest numerem kolejnym argumentu, liczonym od 1.

W rozwiązaniu zadania pomocna może się okazać rekurencja.