diff options
Diffstat (limited to 'Build/source/utils/vlna/vlna.w')
-rw-r--r-- | Build/source/utils/vlna/vlna.w | 125 |
1 files changed, 101 insertions, 24 deletions
diff --git a/Build/source/utils/vlna/vlna.w b/Build/source/utils/vlna/vlna.w index da84b8711b6..6d1ff5c2536 100644 --- a/Build/source/utils/vlna/vlna.w +++ b/Build/source/utils/vlna/vlna.w @@ -32,7 +32,7 @@ v~kódu programu, cestinou v~/* komentářích */ a češtinou jinde. Tu cestinu si vynutil fakt, že DOS-ovská varianta \.{tangle} a \.{weave} se nesnáší s~akcentovanými písmeny v~/* komentářích */. A~nyní už slíbený (vícejazyčný) |BANNER|. -@d BANNER "This is program vlna, version 1.2, (c) 1995, 2002 Petr Olsak\n" +@d BANNER "This is program vlna, version 1.5, (c) 1995, 2002, 2009, 2010 Petr Olsak\n" @ V programu jsou použity knihovní funkce, jejíchž prototypy jsou definovány ve třech standardních hlavičkových souborech. @@ -89,6 +89,10 @@ souborů. interpretovány jako neslabičné předložky. Např. \.{-v KkSsVvZzOoUuAI}. Pokud není parametr uveden, je použita skupina uvedená v tomto příkladě. +* \.{-x} \dots\ parametr vymezuje pomocí hexadecimálního zápisu string, + který program vkládá na vyhledaná místa. Implicitně vkládá vlnku. + Například \.{-x C2A0} způsobí, že program bude vkládat místo vlnky dva byty, + první s kódem \.{C2} a druhý s kódem \.{A0}. * \.{-m} \dots\ program neprovádí kontrolu math/text módů, tj. vlnkuje i uvnitř matematického módu \TeX{}u. (Implicite tam nevlnkuje). * \.{-n} \dots\ prorgram neprovádí kontrolu verbatim módu, tj. vlnkuje i @@ -101,7 +105,7 @@ souborů. vlnkuje dokumentační část každé sekce, ale nikoli kód. \enditems -Definujeme funkci |printusage|, které tiskne (při chybě) stručný přehled +Definujeme funkci |printusage|, která tiskne (při chybě) stručný přehled možných parametrů. Nepodařilo se mi zjistit, jak se ve WEBu napíše kulturně dlouhý string obsahující \.{\char92n} s formátovacími požadavky. Byl jsem nucen to takto nehezky zapsat. @@ -117,6 +121,7 @@ static void printusage (void) " -s : silent: no messages to stderr\n" " -r : rmbackup: if nofilter, removes temporary files\n" " -v charset : set of lettres to add tie, default: KkSsVvZzOoUuAI\n" + " -x code : code for tie symbol, default: 7E, example -x C2A0\n" " -m : nomath: ignores math modes\n" " -n : noverb: ignores verbatim modes\n" " -l : LaTeX mode\n" @@ -133,7 +138,18 @@ int isfilter=0, silent=0, rmbackup=0, nomath=0, noverb=0, web=0, latex=0; char charsetdefault[]="KkSsVvZzOoUuAI"; char *charset=charsetdefault; +@ String |tiestr| obsahuje string, kterým se má nahradit vyhledané +místo. Pokud není použit parametr \.{-u}, je tento string jadnoznakový +a obsahuje vlnku. Jinak obsahuje string konvertovaný z parametru \.{-u}. +String má délku |tiestrlen| bez ohledu na to, zda obsahuje nebo +neobsahuje nulové znaky (C-čková konvence pro stringy není použita). +@<Globální deklarace@>= +unsigned char tiestr[MAXLEN]; +int tiestrlen; + @ @<Načtení parametrů ...@>= +tiestr[0] = '~'; +tiestrlen = 1; while (argc>1 && argv[1][0] == '-') { if (argv[1][2] != 0) printusage (), exit (BAD_OPTIONS); switch(argv[1][1]) { @@ -142,6 +158,8 @@ while (argc>1 && argv[1][0] == '-') { case 'r': rmbackup = 1; break; case 'v': if (argc<2) printusage (), exit (BAD_OPTIONS); argv++; argc--; charset = argv[1]; break; + case 'x': if (argc<2) printusage (), exit (BAD_OPTIONS); + argv++; argc--; settiestr(argv[1]); break; case 'm': nomath = 1; break; case 'n': noverb = 1; break; case 'l': latex = 1; break; @@ -152,6 +170,26 @@ while (argc>1 && argv[1][0] == '-') { argc--; argv++; } +@ Vyřešíme konverzi kódu zapsaného za parametrem \.{-x} na string |tiestr|. +@<Pomocné funkce@>= +unsigned char hexnum(char c) { + if (c >= '0' && c <= '9') return c - '0'; + if (c >= 'A' && c <= 'F') return c - 'A' + 10; + if (c >= 'a' && c <= 'f') return c - 'a' + 10; + printusage (), exit (BAD_OPTIONS); +} +void settiestr(char *s) { + int i, j, c; + i = strlen(s); + if ((i > 2*MAXLEN) || i%2 == 1) printusage (), exit (BAD_OPTIONS); + tiestrlen = i/2; + j = 0; + for (i=0; i<tiestrlen; i++) { + tiestr[i] = hexnum(s[j++]) << 4; + tiestr[i] += hexnum(s[j++]); + } +} + @* Zpracování souborů. Parametr |MAXLEN| definuje maximální možnou délku jména souboru, který vytvoříme jako přechodný, nebo zálohový. Dále deklarujeme proměnné typu \uv{stream}. @@ -347,6 +385,20 @@ char c; /* zrovna nacetny znak */ char buff[MAXBUFF]; /* prechodny buffer */ int ind; /* aktualni pozice prechodneho bufferu */ +@ Dne 30. 4. 2009 jsem přidal možnost čtení vstupu, který obsahuje nulové byty. +Takové nuly se přepisují do výstupu, ale program si jich nevšímá při +procházení patternů. Tím je možno program použít na soubory kódované +v UTF16, ačkoli patterny obsahují jen jednobytové ASCII znaky. +Buffer |buff| může obsahovat i nulové byty, které je třeba přepsat do výstupu. +Na druhé straně buffer |buffnz| obsahuje jen nenulové byty, na které se +někdy ptáme při pohledu dozadu. Nejdelší pohled dozadu je o čtyři byty. +Udělám tedy |buffnz| osmibytový, začnu jej plnit od |buffnz|[4] +a kdykoli je buffer zcela zaplněn, přesunu horní čtyři byty na spodní a dále +pokračuji v plnění bufferu od pozice |buffnz|[4]. +@<Globální deklarace@>= +char buffnz[8]; +int inz; + @ Nyní definujeme pomocné funkce |setpattern|, |setpi| a |normalpattern|. Tyto funkce alokují paměť pomocí standardní funkce |malloc|. Abychom mohli ohlídat případnou chybu při alokaci, budeme allokovat paměť zprostředkovaně @@ -514,8 +566,8 @@ static void tie (FILE *input, FILE *output) @<Inicializace proměnných při startu funkce |tie|@>; while (!feof(input)) { - @<Otevři nové patterny@>; if (ap == 0 && ind > BUFI && c !='\\') @<Vyprázdni buffer@>; + @<Otevři nové patterny@>; /* 1. 2. 2010: prohozene poradi */ if (ind >= MAXBUFF) { fprintf (stderr, "Operating buffer overflow, is anything wrong?\n"); exit (BAD_PROGRAM); @@ -523,8 +575,14 @@ static void tie (FILE *input, FILE *output) if ((ic = getc(input)) == EOF) /* opravil Cejka Rudolf */ break; buff[ind++] = c = ic; + if (c == 0) continue; /* 30. 4. 2009 */ + if (inz>=8) { + for (inz=0; inz<4; inz++) buffnz[inz] = buffnz[inz+4]; + inz=4; + } + buffnz[inz++] = c; if (c == '\n') numline++, listpatt = normallist; - if (c == '%' && mode!=VERBMODE && buff[ind-2] != '\\') listpatt = commentlist; + if (c == '%' && mode!=VERBMODE && buffnz[inz-2] != '\\') listpatt = commentlist; @<Projdi otevřené patterny@>; } @<Vyprázdni buffer@>; @@ -535,7 +593,9 @@ static void tie (FILE *input, FILE *output) @ @<Inicializace proměnných při ...@>= for (k=0; k<MAXPATT; k++) lapi[k] = NULL; c = '\n'; -buff[0] = mode = ap = 0; ind = 1; +buff[0] = 1; mode = ap = 0; ind = 1; +for(inz=0; inz<4; inz++) buffnz[inz] = 0; +inz = 4; numline = 1; numchanges = 0; mode = TEXTMODE; @@ -546,11 +606,11 @@ zda tam není symbol \uv{\.{\char92}} (například na výskyt sekvence \.{\char92\char37} je třeba reagovat jinak, než na výskyt obyčejného procenta). Kdybychm zazačali od |buff[0]|, v některých situacích bychom se ptali, zda |buff[-1]=='\\'|, tj. sahali bychom na neošetřené -místo v paměti. +místo v paměti. Od 30. 4. 2009 tento problém pominul, protože se ptáme dozadu pouze +v~|buffnz|, ale vlastnost dříve implementovanou v |buff| jsem ponechal beze změny. @<Vyprázdni buffer@>= { - buff[ind] = 0; - fputs (&buff[1], output); + fwrite (&buff[1], ind-1, 1, output); ind = 1; } @@ -579,7 +639,7 @@ typu |FOUND| nebo |NOFOUND|. V takových případech ani nezanášíme ukazatel na pozici do pole |lapi|. @<Otevři nové patterny@>= pp = listpatt; -while (pp != NULL) { +if (c) while (pp != NULL) { switch (m = match (pp->patt)) { case FOUND: (*pp->proc)(); /* spustit proceduru */ case NOFOUND: break; @@ -656,15 +716,28 @@ setpi (nochar, ONE_NOT); @ @<Inicializace proměnných při ...@>= listpatt = normallist = vlnkalist; -@ @<Pomocné funkce@>= +@ Vložení vlnky znamená vykonat následující práci: Zapamatovat si znak za skupinou mezer +(do proměnné |p|). Pokud před tímto znakem předchází nulový byte, použijeme ho později, proto +si jej uložíme do proměnné |z|. Dále se posuneme v bufferu vlevo přes všechny mezery, tabelátory +(přesněji |blanks|) a přeskakujeme přitom všechny nulové byty. Index |ind| se zastaví +na předložce. Posuneme jej doprava za předložku (++|ind|) a pokud tam je nulový byte a první znak +|tiestr| není nulový, posuneme se až za tento nulový byte. Dále vložíme string |tiestr|, +neboli vlnku. Nakonec připojíme zapamatovaný znak |p|, ovšem pokud před ním byla nula, +vložíme ji ještě před znak |p|. +@<Pomocné funkce@>= static void vlnkain(void) { - char p; + int i; + char p, z; ind--; p = buff[ind--]; - while (strchr(blanks, buff[ind]) !=NULL) ind--; - ind++; - buff[ind++] = '~'; + z = buff[ind]; + while (!buff[ind] || (strchr(blanks, buff[ind]) !=NULL)) ind--; + if (!buff[++ind] && tiestr[0]) ind++; + for (i=0; i<tiestrlen; i++) buff[ind++] = tiestr[i]; + i = tiestrlen; /* nulu pred p vlozime, pokud je z==0 a */ + if (!tiestr[0]) i--; /* pocet vlozenych znaku z tiestr */ + if (!z && (i%2)) buff[ind++] = 0; /* je sudy */ buff[ind++] = p; numchanges++; } @@ -698,20 +771,24 @@ nebudeme vytvářet nové. Na výstupu bude soubor o jeden řádek kratší. @<Pomocné funkce@>= static void vlnkacr(void) { - char p; + char p, z; int i, j; ind--; p = buff[ind--]; - while (strchr(blankscr, buff[ind]) !=NULL) ind--; + z = buff[ind]; + while (!buff[ind] || (strchr(blankscr, buff[ind]) !=NULL)) ind--; i = ind; /* misto predlozky, kterou chceme vazat */ while (i >= 0 && (strchr(blankscr, buff[i]) == NULL)) i--; j = i; - while (i >= 0 && (strchr(blanks, buff[i]) != NULL)) i--; + while (i >= 0 && (!buff[ind] || (strchr(blanks, buff[i]) != NULL))) i--; if (i >= 0 && buff[i] == '\n') j = -1; if (j >= 0) buff[j] = '\n'; else numline--; - ind++; - buff[ind++] = '~'; + if (!buff[++ind] && tiestr[0]) ind++; + for (i=0; i<tiestrlen; i++) buff[ind++] = tiestr[i]; + i = tiestrlen; + if (!tiestr[0]) i--; + if (!z && (i%2)) buff[ind++] = 0; buff[ind++] = p; numchanges++; } @@ -757,7 +834,7 @@ normalpattern (tielock, "\\LaTeX"); setpi (blankscr, ONE); @ Procedura |tielock| obsahuje nečistý trik. Při provádění procedury je -právě načten znak z |blankscr| a je uložen do buff. Testy na otevírání +právě načten znak z |blankscr| a je uložen do |buff|. Testy na otevírání nových patternů pro tento znak teprve budou následovat a testují se na hodnotu proměnné |c|. Stačí tedy změnit hodnotu |c| a vlnkovací patterny se neotevřou. @@ -816,7 +893,7 @@ display módu. V takovém případě také nic neděláme. @<Pomocné funkce@>= static void onedollar (void) { - if (buff[ind-3]=='\\' || (buff[ind-3]=='$' && buff[ind-4]!='\\')) return; + if (buffnz[inz-3]=='\\' || (buffnz[inz-3]=='$' && buffnz[inz-4]!='\\')) return; if (mode==DISPLAYMODE) printwarning (); else { if (mode==TEXTMODE) mathin(); @@ -871,7 +948,7 @@ static void displayout (void) } static void twodollars (void) { - if (buff[ind-3]=='\\') return; + if (buffnz[inz-3]=='\\') return; if (mode==DISPLAYMODE) displayout (); else displayin (); } @@ -939,7 +1016,7 @@ static void verbin (void) case 'm': i = 2; break; case '<': ; case 'd': i = 3; - if (buff[ind-3]=='@@') return; /* dvojity @@ ignorovat */ + if (buffnz[inz-3]=='@@') return; /* dvojity @@ ignorovat */ break; } listpatt = normallist = verboutlist[i]; @@ -952,7 +1029,7 @@ static void verbin (void) static void verbout (void) { if (mode!=VERBMODE) return; - if (web && buff[ind-2] == '@@' && buff[ind-3] == '@@') return; + if (web && buffnz[inz-2] == '@@' && buffnz[inz-3] == '@@') return; mode = prevmode; normallist->next = prevlist; switch (mode) { |