diff options
author | Karl Berry <karl@freefriends.org> | 2006-01-17 21:16:42 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2006-01-17 21:16:42 +0000 |
commit | a3d3111bfe26b8e5f5bc6049dfb2a4ca2edc7881 (patch) | |
tree | f4a8a34f904c1bb86adcc3ae0e14434badc6dbe4 /Build/source/utils/vlna | |
parent | 6c0eafbb1395d426a72a74538e0b2a95e8344ca6 (diff) |
utils 1
git-svn-id: svn://tug.org/texlive/trunk@1484 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Build/source/utils/vlna')
-rw-r--r-- | Build/source/utils/vlna/Makefile | 53 | ||||
-rw-r--r-- | Build/source/utils/vlna/README | 68 | ||||
-rw-r--r-- | Build/source/utils/vlna/csmac.tex | 63 | ||||
-rw-r--r-- | Build/source/utils/vlna/depend.mak | 3 | ||||
-rw-r--r-- | Build/source/utils/vlna/vlna.c | 827 | ||||
-rw-r--r-- | Build/source/utils/vlna/vlna.dvi | bin | 0 -> 6968 bytes | |||
-rwxr-xr-x | Build/source/utils/vlna/vlna.exe | bin | 0 -> 13666 bytes | |||
-rw-r--r-- | Build/source/utils/vlna/vlna.man | 130 | ||||
-rw-r--r-- | Build/source/utils/vlna/vlna.txt | 121 | ||||
-rw-r--r-- | Build/source/utils/vlna/vlna.w | 1003 | ||||
-rw-r--r-- | Build/source/utils/vlna/win32.mak | 56 |
11 files changed, 2324 insertions, 0 deletions
diff --git a/Build/source/utils/vlna/Makefile b/Build/source/utils/vlna/Makefile new file mode 100644 index 00000000000..4b6c40e0c4a --- /dev/null +++ b/Build/source/utils/vlna/Makefile @@ -0,0 +1,53 @@ + +DESTDIR=/usr/local +MANEXT=1 +BINDIR=$(DESTDIR)/bin +MANDIR=$(DESTDIR)/man/man$(MANEXT) + +CC=cc +INSTALL=install +MKDIR=mkdir -p +INSTPROGFLAGS=-s -m755 +INSTDATAFLAGS=-m644 + +CFLAGS=-O +LFLAGS= + +CTANGLE=ctangle +CWEAVE=cweave +TEX=csplain + +all: vlna + +vlna: vlna.c + $(CC) $(CFLAGS) $(LFLAGS) $? -o $@ + +install: all install.man + @if [ -d $(BINDIR) ]; then \ + set +x; else (set -x; $(MKDIR) $(BINDIR)); fi + $(INSTALL) $(INSTPROGFLAGS) vlna $(BINDIR)/vlna + +install.man: + sed -e "s|@BINDIR@|$(BINDIR)|;\ + s|@MANDIR@|$(MANDIR)|;\ + s|@MANEXT@|$(MANEXT)|" vlna.man > vlna.$(MANEXT) + @if [ -d $(MANDIR) ]; then \ + set +x; else (set -x; $(MKDIR) $(MANDIR)); fi + $(INSTALL) $(INSTDATAFLAGS) vlna.$(MANEXT) $(MANDIR)/vlna.$(MANEXT) + +vlna.c: vlna.w + $(CTANGLE) $? - $@ + +vlna.tex: vlna.w + $(CWEAVE) $? - $@ + +vlna.dvi: vlna.tex + $(TEX) $? + +clean: + rm -f *.o *~ *.bak core a.out vlna vlna.$(MANEXT) + rm -f vlna.idx vlna.scn vlna.toc vlna.log vlna.tex + +cleanall: clean + rm -f vlna.c vlna.dvi + diff --git a/Build/source/utils/vlna/README b/Build/source/utils/vlna/README new file mode 100644 index 00000000000..d8770c53099 --- /dev/null +++ b/Build/source/utils/vlna/README @@ -0,0 +1,68 @@ + +VLNA v1.2 +========= + +Program vlna přidává vlnky (místo původních mezer) za neslabičné předložky +ve vstupních souborech pro TeX. To zabrání zlomu řádku v nežádoucím místě. + +Obsah distribuce: +----------------- + +README ... tento soubor (formát UNIX, ISO 8859-2), +vlna.txt ... manuál k programu (formát UNIX, ISO 8859-2), +Makefile ... soubor pro program make +vlna.w ... zdrojový text programu v jazyce CWEB (formát UNIX, ISO 8859-2), +vlna.c ... výstup z ctangle vlna (program v jazyce C), +vlna.dvi ... listing programu (vyžaduje csfonty), + listing je vytvořen takto: + cweave vlna + csplain vlna +vlna.man ... kostra manuálové stránky +csmac.tex ... makra potřebná při zpracování dokumentace (formát ISO 8859-2). +vlna.exe ... už zkompilovaný program pro DOS + +Instalace v DOSu: +----------------- + +1) Převedení textových souborů z ISO 8859-2 do použitého kódování + (například programem cstocs). +2) Je možné přímo použít připravený program vlna.exe. +3) S vhodným překladačem a při troše štěstí lze též kompilovat program + jako ze zdrojových textů (například s gcc a několika UNIXovými + utilitami). + +Instalace v UNIXu: +------------------ + +1) Případná úprava Makefile pro přizpůsobení překladu a instalace + na cílovému systému. +2) Překlad a instalace: + make + su + make install + +Šíření programu: +---------------- + +Program poskytuji k veřejnému použití. Pokud někdo udělá užitečné +změny ve zdrojovém textu CWEB, chtěl bych být o tom informován. Bez +souhlasu autora nemůže být změněný program šířen pod stejným názvem. +Program ani jeho modifikace se nesmí prodávat. + +Nedávám žádnou záruku, že program nepoškodí mnohahodinovou práci, +kterou uživatelé editovali. Program sice vytváří zálohové soubory, ale +ty se při dalším použití programu mažou. + +Poděkování: +----------- + +Děkuji panu Rudolfu Čejkovi za vytvoření Makefile a manuálové stranky +k programu. Rovněž mu děkuji za odstranění drobných chyb programu, které +se vyskytly ve verzi 1.0. + +28. 2. 1995 Petr Olšák + +verze 1.2 (20. 5. 2002): + oprava chyby "v<space><cr>lese" -> "v~~lese" + a přidání patternu pro "\uv{v lese}" -> "\uv{v~lese}". + diff --git a/Build/source/utils/vlna/csmac.tex b/Build/source/utils/vlna/csmac.tex new file mode 100644 index 00000000000..0860a70f4f0 --- /dev/null +++ b/Build/source/utils/vlna/csmac.tex @@ -0,0 +1,63 @@ +\chyph +\font\ninerm=csr9 +\font\eightrm=csr8 +\let\sc=\eightrm % small caps (NOT a caps-and-small-caps font) +\font\titlefont=csr7 scaled\magstep4 % title on the contents page +\font\ttitlefont=cstt10 scaled\magstep2 % typewriter type in title +\def\postATL#1 #2 {\bf písmeno \\{\uppercase{\char"#1}} + v~.c kódu jako \tentex "#2"\egroup\par} +\def\ATH{\X\kern-.5em:Definice pro preprocesor\X} +\def\A{\note{Viz také sekci}} % xref for doubly defined section name +\def\As{\note{Viz také sekce}} % xref for multiply defined section name +\def\ET{ a~} % conjunction between two section numbers +\def\ETs{ a~} % conjunction between the last two of several section numbers +\def\Q{\note{Tento kód je citován v~sekci}} % xref for mention of a section +\def\Qs{\note{Tento kód je citován v~sekcích}} % xref for mentions of a section +\def\U{\note{Tento kód je použit v~sekci}} % xref for use of a section +\def\Us{\note{Tento kód je použit v~sekcích}} % xref for uses of a section +\def\ch{\note{Následující sekce byly změněny prostřednictvím změnového + souboru:} \let\*=\relax} +\def\fin{\par\vfill\eject % this is done when we are ending the index + \ifpagesaved\null\vfill\eject\fi % output a null index column + \if L\lr\else\null\vfill\eject\fi % finish the current page + \parfillskip 0pt plus 1fil + \def\grouptitle{NÁZVY SEKCÍ} + \let\topsecno=\nullsec + \message{Section names:} + \output={\normaloutput\page\lheader\rheader} + \setpage + \def\note##1##2.{\quad{\eightrm##1~##2.}} + \def\Q{\note{Citováno v~sekci}} % crossref for mention of a section + \def\Qs{\note{Citováno v~sekcích}} % crossref for mentions of a section + \def\U{\note{Použito v~sekci}} % crossref for use of a section + \def\Us{\note{Použito v~sekcích}} % crossref for uses of a section + \def\I{\par\hangindent 2em}\let\*=* + \readsections} +\def\contentsline#1#2#3#4{\ifnum#2=0 \smallbreak\fi + \line{\consetup{#2}#1 + \rm\leaders\hbox to .5em{.\hfil}\hfil\ #3\hbox to4em{\hss#4}}} +\def\con{\par\vfill\eject % finish the section names +% \ifodd\pageno\else\titletrue\null\vfill\eject\fi % for duplex printers + \rightskip 0pt \hyphenpenalty 50 \tolerance 200 + \setpage \output={\normaloutput\page\lheader\rheader} + \titletrue % prepare to output the table of contents + \pageno=\contentspagenumber + \def\grouptitle{OBSAH} + \message{Table of contents:} + \topofcontents + \line{\hfil Sekce\hbox to4em{\hss Strana}} + \let\ZZ=\contentsline + \readcontents\relax % read the contents info + \botofcontents \end} % print the contents page(s) and terminate +\def\today{\number\day.~\ifcase\month\or ledna\or února\or března\or + dubna\or května\or června\or července\or srpna\or září\or října\or + listopadu\or prosince\fi \space\number\year} +\def\datethis{\def\startsection{\leftline{\sc\today\ v~\hours}\bigskip + \let\startsection=\stsec\stsec}} +\def\datecontentspage{% + \def\topofcontents{\leftline{\sc\today\ v~\hours}\bigskip + \centerline{\titlefont\title}\vfill}} % timestamps the contents page + +\def\allowhyphens{\nobreak\hskip0pt\relax} +\def \uv#1{\char254 \allowhyphens#1\allowhyphens\char255 } + diff --git a/Build/source/utils/vlna/depend.mak b/Build/source/utils/vlna/depend.mak new file mode 100644 index 00000000000..1a3ea97100b --- /dev/null +++ b/Build/source/utils/vlna/depend.mak @@ -0,0 +1,3 @@ +$(objdir)/vlna.obj: \ + + diff --git a/Build/source/utils/vlna/vlna.c b/Build/source/utils/vlna/vlna.c new file mode 100644 index 00000000000..6e4ae12493c --- /dev/null +++ b/Build/source/utils/vlna/vlna.c @@ -0,0 +1,827 @@ +#define BANNER "This is program vlna, version 1.2, (c) 1995, 2002 Petr Olsak\n" \ + +#define OK 0 +#define WARNING 1 +#define IO_ERR 2 +#define BAD_OPTIONS 3 +#define BAD_PROGRAM 4 +#define MAXLEN 120 +#define ONE 1 +#define ANY 2 +#define ONE_NOT -1 +#define ANY_NOT -2 \ + +#define MAXPATT 200 +#define MAXBUFF 500 +#define BUFI 300 +#define FOUND -1 +#define NOFOUND -2 +#define TEXTMODE 0 +#define MATHMODE 1 +#define DISPLAYMODE 2 +#define VERBMODE 3 +/*1:*/ +#line 19 "vlna.w" + +/*3:*/ +#line 39 "vlna.w" + +#include <stdio.h> +#include <string.h> +#include <stdlib.h> + +/*:3*/ +#line 20 "vlna.w" + +/*4:*/ +#line 56 "vlna.w" + +char*prog_name; +int status; + +/*:4*//*7:*/ +#line 133 "vlna.w" + +int isfilter= 0,silent= 0,rmbackup= 0,nomath= 0,noverb= 0,web= 0,latex= 0; +char charsetdefault[]= "KkSsVvZzOoUuAI"; +char*charset= charsetdefault; + +/*:7*//*15:*/ +#line 291 "vlna.w" + +typedef struct PATITEM{ +char*str; +int flag; +struct PATITEM*next; +}PATITEM; +typedef struct PATTERN{ +PATITEM*patt; +void(*proc)(); +struct PATTERN*next; +}PATTERN; + +/*:15*//*16:*/ +#line 343 "vlna.w" + +PATITEM*lapi[MAXPATT]; +PATTERN*lapt[MAXPATT]; +PATTERN*listpatt,*normallist,*commentlist,*pt,*lastpt= NULL; +PATITEM*pi,*lastpi= NULL; +char c; +char buff[MAXBUFF]; +int ind; + +/*:16*//*20:*/ +#line 417 "vlna.w" + +char strings[512]; +int i; + +/*:20*//*25:*/ +#line 505 "vlna.w" + +char*filename; +long int numline,numchanges; +int mode; + +/*:25*//*33:*/ +#line 636 "vlna.w" + +char tblanks[]= " ~\t"; +char blanks[]= " \t"; +char blankscr[]= " \t\n"; +char tblankscr[]= " ~\t\n"; +char nochar[]= "%~\n"; +char cr[]= "\n"; +char prefixes[]= "[({~"; +char dolar[]= "$"; +char backslash[]= "\\"; +char openbrace[]= "{"; +char letters[]= "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; +PATTERN*vlnkalist,*mathlist,*parcheck,*verblist; + +/*:33*/ +#line 21 "vlna.w" + +/*6:*/ +#line 110 "vlna.w" + +void printusage() +{ +fprintf(stderr, +"usage: vlna [opt] [filenames]\n" +" opt -f : filter mode: file1 file2 ... file1->file2\n" +" file1 ... file1->stdout\n" +" ... stdin->stdout\n" +" nofilter: file1 [file2 file3 ...] all are in/out\n" +" -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" +" -m : nomath: ignores math modes\n" +" -n : noverb: ignores verbatim modes\n" +" -l : LaTeX mode\n" +" -w : web mode\n"); +} + +/*:6*//*10:*/ +#line 167 "vlna.w" + +void ioerr(f) +char*f; +{ +fprintf(stderr,"%s: cannot open file %s\n",prog_name,f); +} + +/*:10*//*17:*/ +#line 356 "vlna.w" + +void*myalloc(size) +int size; +{ +void*p; +p= malloc(size); +if(p==NULL) +{ +fprintf(stderr,"%s, no memory, malloc failed\n",prog_name); +exit(BAD_PROGRAM); +} +return p; +} + +/*:17*//*18:*/ +#line 374 "vlna.w" + +PATTERN*setpattern(proc) +void(*proc)(); +{ +PATTERN*pp; +pp= myalloc(sizeof(PATTERN)); +pp->proc= proc; +pp->next= NULL; +pp->patt= NULL; +if(lastpt!=NULL)lastpt->next= pp; +lastpt= pp; +lastpi= NULL; +return pp; +} + +/*:18*//*19:*/ +#line 393 "vlna.w" + +void setpi(str,flag) +char*str; +int flag; +{ +PATITEM*p; +p= myalloc(sizeof(PATITEM)); +p->str= str;p->flag= flag; +p->next= NULL; +if(lastpi==NULL)lastpt->patt= p; +else lastpi->next= p; +lastpi= p; +} + +/*:19*//*22:*/ +#line 428 "vlna.w" + +PATTERN*normalpattern(proc,str) +void(*proc)(); +char*str; +{ +PATTERN*pp; +int j= 0; +pp= setpattern(proc); +while(str[j]){ +if(str[j]=='.'){ +j++; +if(str[j]!='.'){ +setpi(blankscr,ANY); +continue; +} +} +setpi(&strings[(unsigned char)str[j]*2],ONE); +j++; +} +return pp; +} + +/*:22*//*23:*/ +#line 466 "vlna.w" + +int match(p) +PATITEM*p; +{ +int m; +if(strchr(p->str,c)!=NULL)m= 1; +else m= -1; +switch(m*p->flag){ +case ANY:return 0; +case ONE:if(p->next==NULL)return FOUND; +return 1; +case ONE_NOT:return NOFOUND; +case ANY_NOT:/*24:*/ +#line 485 "vlna.w" + +switch(m= match(p->next)){ +case NOFOUND:return NOFOUND; +case FOUND:return FOUND; +default:return 1+m; +} + +/*:24*/ +#line 478 "vlna.w" +; +} +return 0; +} + +/*:23*//*36:*/ +#line 669 "vlna.w" + +void vlnkain() +{ +char p; +ind--; +p= buff[ind--]; +while(strchr(blanks,buff[ind])!=NULL)ind--; +ind++; +buff[ind++]= '~'; +buff[ind++]= p; +numchanges++; +} + +/*:36*//*38:*/ +#line 708 "vlna.w" + +void vlnkacr() +{ +char p; +int i,j; +ind--; +p= buff[ind--]; +while(strchr(blankscr,buff[ind])!=NULL)ind--; +i= ind; +while(i>=0&&(strchr(blankscr,buff[i])==NULL))i--; +j= i; +while(i>=0&&(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++]= '~'; +buff[ind++]= p; +numchanges++; +} + +/*:38*//*41:*/ +#line 774 "vlna.w" + +void tielock() +{ +c= 1; +} + +/*:41*//*42:*/ +#line 783 "vlna.w" + +void printwarning() +{ +if(!silent) +fprintf(stderr, +"~!~ warning: text/math/verb mode mismatch, file: %s, line: %ld\n", +filename,numline-(c=='\n'?1:0)); +status= WARNING; +} + +/*:42*//*44:*/ +#line 808 "vlna.w" + +void mathin() +{ +if(mode!=TEXTMODE)printwarning(); +mode= MATHMODE; +normallist= listpatt= mathlist; +} +void mathout() +{ +if(mode!=MATHMODE)printwarning(); +mode= TEXTMODE; +normallist= listpatt= vlnkalist; +} + +/*:44*//*45:*/ +#line 826 "vlna.w" + +void onedollar() +{ +if(buff[ind-3]=='\\'||(buff[ind-3]=='$'&&buff[ind-4]!='\\'))return; +if(mode==DISPLAYMODE)printwarning(); +else{ +if(mode==TEXTMODE)mathin(); +else mathout(); +} +} + +/*:45*//*47:*/ +#line 845 "vlna.w" + +void checkmode() +{ +if(mode!=TEXTMODE){ +printwarning(); +mode= TEXTMODE; +normallist= listpatt= vlnkalist; +} +} + +/*:47*//*49:*/ +#line 871 "vlna.w" + +void displayin() +{ +if(mode!=TEXTMODE)printwarning(); +mode= DISPLAYMODE;normallist= listpatt= parcheck; +} +void displayout() +{ +if(mode!=DISPLAYMODE)printwarning(); +mode= TEXTMODE;normallist= listpatt= vlnkalist; +} +void twodollars() +{ +if(buff[ind-3]=='\\')return; +if(mode==DISPLAYMODE)displayout(); +else displayin(); +} + +/*:49*//*51:*/ +#line 920 "vlna.w" + +int prevmode; +PATTERN*prevlist,*verboutlist[4]; +char verbchar[2]; +void verbinchar() +{ +prevmode= mode; +verbchar[0]= c; +c= 1; +listpatt= normallist= verboutlist[0]; +prevlist= listpatt->next; +listpatt->next= NULL; +mode= VERBMODE; +} + +/*:51*//*52:*/ +#line 941 "vlna.w" + +void verbin() +{ +int i; +i= 0; +prevmode= mode; +switch(c){ +case't':i= 1;break; +case'm':i= 2;break; +case'<':; +case'd':i= 3; +if(buff[ind-3]=='@')return; +break; +} +listpatt= normallist= verboutlist[i]; +prevlist= listpatt->next; +if(c!='<'&&c!='d')listpatt->next= NULL; +mode= VERBMODE; +} + +/*:52*//*53:*/ +#line 961 "vlna.w" + +void verbout() +{ +if(mode!=VERBMODE)return; +if(web&&buff[ind-2]=='@'&&buff[ind-3]=='@')return; +mode= prevmode; +normallist->next= prevlist; +switch(mode){ +case DISPLAYMODE:normallist= listpatt= parcheck;break; +case MATHMODE:normallist= listpatt= mathlist;break; +case TEXTMODE:normallist= listpatt= vlnkalist;break; +} +} + +/*:53*//*55:*/ +#line 983 "vlna.w" + +void tieoff() +{ +normallist= NULL; +} +void tieon() +{ +normallist= vlnkalist; +} + +/*:55*/ +#line 22 "vlna.w" + +/*26:*/ +#line 514 "vlna.w" + +void tie(input,output) +FILE*input,*output; +{ +int ap; +register int k,m,n; +int ic; +PATTERN*pp; +PATITEM*pi; + +/*27:*/ +#line 545 "vlna.w" + +for(k= 0;k<MAXPATT;k++)lapi[k]= NULL; +c= '\n'; +buff[0]= mode= ap= 0;ind= 1; +numline= 1;numchanges= 0; +mode= TEXTMODE; + +/*:27*//*35:*/ +#line 666 "vlna.w" + +listpatt= normallist= vlnkalist; + +/*:35*/ +#line 524 "vlna.w" +; + +while(!feof(input)){ +/*30:*/ +#line 590 "vlna.w" + +pp= listpatt; +while(pp!=NULL){ +switch(m= match(pp->patt)){ +case FOUND:(*pp->proc)(); +case NOFOUND:break; +default:/*31:*/ +#line 605 "vlna.w" + +pi= pp->patt; +while(m--)pi= pi->next; +n= ap;k= 0; +while(n){ +if(lapi[k]==pi)break; +if(lapi[k++]!=NULL)n--; +} +if(!n){ +k= 0; +while(lapi[k]!=NULL)k++; +if(k>=MAXPATT){ +fprintf(stderr,"I cannot allocate pp, is anything wrong?\n"); +exit(BAD_PROGRAM); +} +lapt[k]= pp;lapi[k]= pi;ap++; +} + +/*:31*/ +#line 596 "vlna.w" +; +} +pp= pp->next; +} + +/*:30*/ +#line 527 "vlna.w" +; +if(ap==0&&ind> BUFI&&c!='\\')/*28:*/ +#line 560 "vlna.w" + +{ +buff[ind]= 0; +fputs(&buff[1],output); +ind= 1; +} + +/*:28*/ +#line 528 "vlna.w" +; +if(ind>=MAXBUFF){ +fprintf(stderr,"Operating buffer overflow, is anything wrong?\n"); +exit(BAD_PROGRAM); +} +if((ic= getc(input))==EOF) +break; +buff[ind++]= c= ic; +if(c=='\n')numline++,listpatt= normallist; +if(c=='%'&&mode!=VERBMODE&&buff[ind-2]!='\\')listpatt= commentlist; +/*29:*/ +#line 573 "vlna.w" + +n= ap;k= 0; +while(n){ +while(lapi[k]==NULL)k++; +switch(m= match(lapi[k])){ +case FOUND:(*lapt[k]->proc)(); +case NOFOUND:lapi[k]= NULL; +ap--;break; +default:while(m--)lapi[k]= lapi[k]->next; +} +k++;n--; +} + +/*:29*/ +#line 538 "vlna.w" +; +} +/*28:*/ +#line 560 "vlna.w" + +{ +buff[ind]= 0; +fputs(&buff[1],output); +ind= 1; +} + +/*:28*/ +#line 540 "vlna.w" +; +if(!web)checkmode(); +if(!silent)/*32:*/ +#line 624 "vlna.w" + +fprintf(stderr,"~~~ file: %s\t lines: %ld, changes: %ld\n", +filename,numline,numchanges); + +/*:32*/ +#line 542 "vlna.w" +; +} + +/*:26*/ +#line 23 "vlna.w" + +/*5:*/ +#line 61 "vlna.w" + +int main(argc,argv) +int argc; +char**argv; +{ +/*9:*/ +#line 160 "vlna.w" + +FILE*infile,*outfile; +char backup[MAXLEN]; +int j; + +/*:9*/ +#line 66 "vlna.w" +; +prog_name= argv[0];status= OK; +/*8:*/ +#line 138 "vlna.w" + +while(argc> 1&&argv[1][0]=='-'){ +if(argv[1][2]!=0)printusage(),exit(BAD_OPTIONS); +switch(argv[1][1]){ +case'f':isfilter= 1;break; +case's':silent= 1;break; +case'r':rmbackup= 1;break; +case'v':argv++;argc--;charset= argv[1];break; +case'm':nomath= 1;break; +case'n':noverb= 1;break; +case'l':latex= 1;break; +case'w':web= 1;break; +default:printusage(),exit(BAD_OPTIONS); + +} +argc--;argv++; +} + +/*:8*/ +#line 68 "vlna.w" +; +if(!silent)fprintf(stderr,BANNER); +/*21:*/ +#line 422 "vlna.w" + +for(i= 0;i<256;i++){ +strings[2*i]= (char)i;strings[2*i+1]= 0; +} + +/*:21*//*34:*/ +#line 656 "vlna.w" + +vlnkalist= setpattern(vlnkain); +setpi(tblankscr,ONE); +setpi(tblanks,ANY); +setpi(prefixes,ANY); +setpi(charset,ONE); +setpi(blanks,ONE); +setpi(blanks,ANY); +setpi(nochar,ONE_NOT); + +/*:34*//*37:*/ +#line 684 "vlna.w" + +setpattern(vlnkacr); +setpi(tblankscr,ONE); +setpi(tblanks,ANY); +setpi(prefixes,ANY); +setpi(charset,ONE); +setpi(blanks,ANY); +setpi(cr,ONE); +setpi(blanks,ANY); +setpi(nochar,ONE_NOT); + +/*:37*//*39:*/ +#line 730 "vlna.w" + +setpattern(vlnkain); +setpi(tblankscr,ONE); +setpi(backslash,ONE); +setpi(letters,ONE); +setpi(letters,ANY); +setpi(openbrace,ONE); +setpi(prefixes,ANY); +setpi(charset,ONE); +setpi(blanks,ONE); +setpi(blanks,ANY); +setpi(nochar,ONE_NOT); + +setpattern(vlnkacr); +setpi(tblankscr,ONE); +setpi(backslash,ONE); +setpi(letters,ONE); +setpi(letters,ANY); +setpi(openbrace,ONE); +setpi(prefixes,ANY); +setpi(charset,ONE); +setpi(blanks,ANY); +setpi(cr,ONE); +setpi(blanks,ANY); +setpi(nochar,ONE_NOT); + + + +/*:39*//*40:*/ +#line 763 "vlna.w" + +normalpattern(tielock,"\\TeX"); +setpi(blankscr,ONE); +normalpattern(tielock,"\\LaTeX"); +setpi(blankscr,ONE); + +/*:40*//*43:*/ +#line 797 "vlna.w" + +if(!nomath){ +mathlist= setpattern(onedollar); +setpi(dolar,ONE); +setpi(dolar,ONE_NOT); +if(latex){ +normalpattern(mathin,"\\begin.{math}"); +normalpattern(mathout,"\\end.{math}"); +} +} + +/*:43*//*46:*/ +#line 839 "vlna.w" + +parcheck= setpattern(checkmode); +setpi(cr,ONE); +setpi(blanks,ANY); +setpi(cr,ONE); + +/*:46*//*48:*/ +#line 860 "vlna.w" + +if(!nomath){ +normalpattern(twodollars,"$$"); +if(latex){ +normalpattern(displayin,"\\begin.{displaymath"); +normalpattern(displayin,"\\begin.{equation"); +normalpattern(displayout,"\\end.{displaymath"); +normalpattern(displayout,"\\end.{equation"); +} +} + +/*:48*//*50:*/ +#line 892 "vlna.w" + +if(!noverb){ +verblist= normalpattern(verbinchar,"\\verb"); +setpi(blankscr,ANY); +setpi(blankscr,ONE_NOT); +normalpattern(verbin,"\\begtt"); +if(latex)normalpattern(verbin,"\\begin.{verbatim"); +} +if(web){ +normalpattern(verbin,"@<"); +normalpattern(verbin,"@d"); +} +if(!noverb){ +verboutlist[0]= setpattern(verbout); +setpi(verbchar,ONE); +verboutlist[1]= normalpattern(verbout,"\\endtt"); +if(latex)verboutlist[2]= normalpattern(verbout,"\\end{verbatim"); +} +if(web){ +verboutlist[3]= normalpattern(verbout,"@ "); +normalpattern(verbout,"@*"); +normalpattern(verbout,"@>|"); +} + + +/*:50*//*54:*/ +#line 978 "vlna.w" + +lastpt= 0; +commentlist= normalpattern(tieoff,"%.~.-"); +normalpattern(tieon,"%.~.+"); + +/*:54*/ +#line 70 "vlna.w" +; +/*11:*/ +#line 175 "vlna.w" + +if(isfilter)/*12:*/ +#line 187 "vlna.w" + +{ +if(argc> 3)printusage(),exit(BAD_OPTIONS); +infile= stdin;outfile= stdout; +if(argc>=2)infile= fopen(argv[1],"r"); +if(infile==NULL)ioerr(argv[1]),exit(IO_ERR); +if(argc==3)outfile= fopen(argv[2],"w"); +if(outfile==NULL)ioerr(argv[2]),exit(IO_ERR); +if(argc>=2)filename= argv[1]; +else filename= NULL; +tie(infile,outfile); +if(outfile!=stdout)fclose(outfile); +if(infile!=stdin)fclose(infile); +} + +/*:12*/ +#line 176 "vlna.w" + +else/*13:*/ +#line 210 "vlna.w" + +{ +if(argc==1)printusage(),exit(BAD_OPTIONS); +while(argc> 1){ +argc--;argv++; +/*14:*/ +#line 241 "vlna.w" + +infile= NULL; +j= strlen(argv[0])-1; +if(j>=MAXLEN||argv[0][j]=='~'){ +if(!silent)fprintf(stderr,"%s: the conflict of file name %s\n", +prog_name,argv[0]); +} +else{ +strcpy(backup,argv[0]); +backup[j]= '~'; +remove(backup); +j= rename(argv[0],backup); +if(j==0)infile= fopen(backup,"r"); +} + +/*:14*/ +#line 215 "vlna.w" +; +if(infile==NULL){ +ioerr(argv[0]);continue; +} +outfile= fopen(argv[0],"w"); +if(outfile==NULL){ +ioerr(argv[0]); +rename(backup,argv[0]); +status= WARNING; +continue; +} +filename= argv[0]; +tie(infile,outfile); +fclose(outfile),fclose(infile); +if(rmbackup)remove(backup); +} +} + +/*:13*/ +#line 177 "vlna.w" + + +/*:11*/ +#line 71 "vlna.w" +; +return status; +} + +/*:5*/ +#line 24 "vlna.w" + + +/*:1*/ diff --git a/Build/source/utils/vlna/vlna.dvi b/Build/source/utils/vlna/vlna.dvi Binary files differnew file mode 100644 index 00000000000..0bf8718cd48 --- /dev/null +++ b/Build/source/utils/vlna/vlna.dvi diff --git a/Build/source/utils/vlna/vlna.exe b/Build/source/utils/vlna/vlna.exe Binary files differnew file mode 100755 index 00000000000..b096673d835 --- /dev/null +++ b/Build/source/utils/vlna/vlna.exe diff --git a/Build/source/utils/vlna/vlna.man b/Build/source/utils/vlna/vlna.man new file mode 100644 index 00000000000..0470461370a --- /dev/null +++ b/Build/source/utils/vlna/vlna.man @@ -0,0 +1,130 @@ +.\" $Id$ +.TH VLNA 1 "4. unora 1998" +.nh +.SH NAZEV +vlna \- pridani vlnek za neslabicne predlozky v TeXu +.SH POUZITI +.B vlna +[\fIvolby\fP] +[\fIsoubory\fP] +.SH POPIS +Program +.B vlna +pridava vlnky (misto puvodnich mezer) za neslabicne predlozky +ve vstupnich souborech pro TeX, coz zabrani zlomu radku v nezadoucich mistech. +.PP +Veskere aktivity programu je mozne vypnout sekvenci \fB%~-\fP a zapnout +sekvenci \fB%~+\fP (mezi uvedenymi znaky muze byt libovolne mnozstvi mezer). +.PP +Pred predlozkou se muze nachazet libovolne mnozstvi oteviracich zavorek, +pred kterymi se musi nachazet mezera nebo zacatek radku. Pred +oteviraci svorkou muze byt take misto mezery TeXova +\(lq\\sekvence\(rq (od verze 1.2). +Napr. za \(lq([{(V\(rq na pocatku radku bude vlnka pridana. +Stejne tak se text \(lq\\uv{V lese}\(rq promeni na +\(lq\\uv{V~lese}\(rq. +.PP +Program kontroluje konzistenci matematickych prostredi (neni-li uveden +parametr \fB\-m\fP). +Vstup do \fIdisplay\fP rezimu (\fB$$\fP) uvnitr \fItext\fP rezimu (\fB$\fP) +(napr. \fB$\fP...\fB$$\fP...\fB$\fP) znamena varovani a prechod do +\fIdisplay\fP. +Podobne prazdny radek uvnitr \fItext\fP nebo \fIdisplay\fP rezimu znamena +vypis varovani a prechod do nematematickeho (standardniho) rezimu. +Uvnitr rezimu \fIdisplay\fP se ignoruji vyskyty samostatneho znaku \fB$\fP, +jelikoz byva vetsinou soucasti konstrukce \fB\\hbox\fP. +.PP +Program kontroluje konzistenci verbatim rezimu na konci souboru. +Nebyl-li ukoncen, vypise se varovani. +Kontrola se neprovadi, pokud je pouzita volba \fB\-n\fP nebo \fB\-w\fP. +.PP +Program nedoplnuje vlnky za samostatna pismena, ktera jako predlozky vypadaji, +ale nasleduji bezprostredne za sekvencemi \fB\\TeX\fP nebo \fB\\LaTeX\fP. +Napr. do textu \(lq\fBVlastnosti \\TeX u jsou\fP\(rq nebude zadna vlnka +doplnena. +.SH VOLBY +Volby jsou nepovinne a mohou byt uvedeny v libovolnem poradi, ale nemohou +byt spojovany. +.TP +.B \-f +Filtr. Jmena souboru jsou interpretovana takto: +.RS +.TP 4 +.B vlna \-f \fIsoubor1 soubor2\fP +Vstup je \fIsoubor1\fP, vystup \fIsoubor2\fP. +.TP 4 +.B vlna \-f \fIsoubor1\fP +Vstup je \fIsoubor1\fP, vystup \fIstdout\fP. +.TP 4 +.B vlna \-f +Vstup je \fIstdin\fP, vystup \fIstdout\fP. +.TP 4 +\fBvlna\fP \fIsoubor1\fP [\fIsoubor2\fP [\fIsoubor3\fP ...]] +Neni-li uveden parametr \fB\-f\fP, kazdy soubor je zpracovavan samostatne. +.RE +.TP +.B \-s +Tichy rezim. Program potlaci vypis uvodni zpravy, varovnych zprav a +statistik o zmenach v souborech +(bez uvedeni parametru jsou zpravy vypisovany na \fIstderr\fP). +V tichem rezimu se vypise jen chyba, ktera predcasne ukonci +cinnost programu. +.TP +.B \-r +Nevytvaret (mazat) zalohy. +Parametr \fB\-r\fP nema vliv, pokud je uveden spolu s \fB\-f\fP. +V opacnem pripade se ke kazdemu souboru vytvari zaloha s vlnkou na konci jmena +a parametr \fB\-r\fP zpusobi, ze na konci zpracovani jsou tyto zalohy mazany. +.TP +.B \-v \fIznaky\fP +Znaky povazovane za neslabicne predlozky, za ktere ma byt pridavana +vlnka. Implicitni hodnota je \fB\-v\ KkSsVvZzOoUuAI\fP. (Mezi +\fB\-v\fP a skupinou znaku musi byt mezera.) +.TP +.B \-m +Ignorovani prechodu do matematickych prostredi +(\fB$\fP...\fB$\fP a \fB$$\fP...\fB$$\fP). +Parametr \fB\-m\fP zpusobi vlnkovani i v matematickych prostredich, ktera +se implicitne vynechavaji. +.TP +.B \-n +Ignorovani verbatim rezimu (\fB\\verb\fP\fI<znak>\fP...\fI<znak>\fP, +\fB\\begtt\fP...\fB\\endtt\fP). +Parametr \fB\-n\fP zpusobi vlnkovani i ve verbatim rezimu, ktery se +implicitne vynechava. +.TP +.B \-l +LaTeX. Pro rozpoznani matematickeho rezimu jsou pridana prostredi +\fB\\begin{display}\fP...\fB\\end{display}\fP a +\fB\\begin{equation}\fP...\fB\\end{equation}\fP. +Pro rozpoznani verbatim rezimu je pridano LaTeXove prostredi +\fB\\begin{verbatim}\fP...\fB\\end{verbatim}\fP. +.TP +.B \-w +Web. Pro rozpoznani verbatim rezimu jsou pridany sekvence +\fB@<\fP, \fB@d\fP...\fB@*\fP, \fB@\fP\fImezera\fP nebo \fB@>|\fP. +Ve zdrojovem kodu se tedy nevlnkuje program, ale jen komentare. +.SH PRIKLADY +.TP +.B vlna \-m \-n \-s \-r \fIsoubor\fP +Volani priblizne odpovida volani puvodniho programu \fBvlna\fP. +(Navic se neprovadi vlnkovani za sekvencemi \fB\\TeX\fP a \fB\\LaTeX\fP.) +.TP +.B vlna *.tex +Vlnkovani vsech souboru s priponou \fBtex\fP. +(Pouze na UNIXu.) +.TP +.B vlna \-f soubor > /dev/null +Test konzistence matematickeho a verbatim rezimu bez provedeni zmen. +(Pouze na UNIXu.) +.SH SOUBORY +.PD 0 +.TP +.I @BINDIR@/vlna +spustitelny program +.TP +.I @MANDIR@/vlna.@MANEXT@ +manualova stranka +.PD +.SH AUTOR +Petr Olsak <olsak@math.feld.cvut.cz>. Manualovou stranku a Makefile vytvoril Rulolf Cejka diff --git a/Build/source/utils/vlna/vlna.txt b/Build/source/utils/vlna/vlna.txt new file mode 100644 index 00000000000..2e50fab9e73 --- /dev/null +++ b/Build/source/utils/vlna/vlna.txt @@ -0,0 +1,121 @@ + + Program VLNA + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + verze 1.2 Petr Olšák + +Program vlna přidává vlnky (místo původních mezer) za neslabičné předložky +ve vstupních souborech pro TeX. To zabrání zlomu řádku v nežádoucím místě. + +Není použit název "vlnka", abychom odlišili původní program vlnka +(autoři O. Ulrych, Š. Kasal) od tohoto programu vlna. Jedná se o +vylepšenou a zcela nově napsanou verzi, která není důsledně zpětně +kompatibilní s původním programem vlnka. + +POUŽITÍ: +-------- + +vlna [opt] [jména souborů] + +[opt] jsou nepovinné přepínače, které musí být odděleny mezerou a uvozeny +znakem "-". Mohou být uvedeny v libovolném pořadí. + +PŘEPÍNAČE: +---------- + +-f : Režim "filtr". V tomto režimu jsou jména souborů interpretována takto: + vlna -f soubor1 soubor2 ... soubor1 -> soubor2 (musí: in!=out) + vlna -f soubor1 ... soubor1 -> stdout + vlna -f ... stdin -> stdout + Není-li program v režimu filtr, pak jsou jména souborů interpretována + takto: + vlna soubor1 [soubor2 [soubor3...]] + Zde je každý soubor "ovlnkován" samostatně, tj. soubory jsou měněny. + Není-li uveden parametr -r, jsou vytvářeny zálohy k souborům + s vlnkou na konci jména. +-s : Tichý režim. Program nevypisuje úvodní zprávu, varovné zprávy a + statistiky o změnách v souborech. Tyto texty se vypisují do stderr, + takže v režimu filtr není nutné -s zapínat, pokud umíme oddělit stderr + od stdout. V tichém režimu se vypíše jen chyba, která předčasně ukončí + činnost programu. +-r : Nevytvářet (mazat) zálohy. Není-li program v režimu filtr, pak se ke + každému souboru vytváří záloha s vlnkou na konci jména. Takové soubory + se interně vytvářejí vždy při běhu programu v režimu ne-filtr. Je-li + uveden parametr -r, jsou na konci zpracování tyto zálohy mazány. + V režimu filtr nemá -r žádný vliv. +-v znaky : Definice znaků, které budeme považovat za neslabičné předložky, + tj. k ovlnkování. Implicitní hodnota -v KkSsVvZzOoUuAI je použitím + tohoto parametru přepsána. Mezi -v a skupinou znaků musí být mezera. +-m : Ignoruje přechody do matematického režimu ($...$ a $$...$$) a vlnkuje + i v těchto prostředích. Imlicitně v matematických prostředích nevlnkuje. +-n : Ignoruje přechody do verbatim režimu (\verb<zn>...<zn>, \begtt...\endtt) + a vlnkuje i v těchto prostředích. +-l : LaTeX mód. K výše uvedeným sekvencím ohraničující display math + mód je přidáno \begin{display}...\end{display} a + \begin{equation}...\end{equation}. K sekvencím ohraničující + verbatim mód je přidáno \begin{verbatim}...\end{verbatim} +-w : web mód. K sekvencím ohraničujícím verbatim mód je přidáno + @< nebo @d ... @* nebo @mezera nebo @>| . To způsobí, že není + provlnkovaný kód programu ve web souborech, ale jenom komentáře. + +POZNÁMKY: +--------- + +* Před předložkou může být libovolné množství otevíracích závorek, + před kterými musí být mezera nebo začátek řádku. Před otevírací + svorkou může také být místo mezery TeXova "\sekvence" (od verze 1.2). + Např. ([{(V tomto případě bude vlnka za V. Stejně tak + se vlnka objeví \boldfont{V tomto případě}. +* Veškeré aktivity programu je možné vypnout sekvencí %~- a zapnout + sekvencí %~+ (mezi uvedenými znaky může být libovoné množství mezer) +* Program kontroluje konzistenci matematických režimů. Dá varování + v těchto případech: + Vstup do display uvnitř t-math (např. $ ...$$... $). -- přejde do display. + Prázdný řádek uvnitř t-math nebo display -- přejde do standardního režimu. + Poznamenejme, že uvnitř display se ignorují výskyty jednoho dolaru + naprosto bez varování, protože ty většinou mohou být součástí \hbox-u. + Při -m není konzistence math. módů kontrolována. +* Program kontroluje konzistenci verbatim módů na konci souboru. + Nebyl-li verbatim mód ukončen, objeví se varování. Tento test + neprobíhá, pokud je nastaven přepínač -n nebo -w. +* Program nedoplňuje vlnky za písmena, která vypadají "jako" + předložky, ale následují bezprostředně za sekvencemi \TeX nebo + \LaTeX, tj. např. v textu "Vlastnosti \TeX u jsou" nepřidá vlnku + mezi u a j. Sekvence \TeX a \LaTeX jsou zatím natvrdo implementovány + do programu. Otázka čtení množiny takových sekvencí z konf. souboru + (nebo odjinud) bude (možná) zahrnuta v další verzi. + +TIPY K POUŽITÍ PROGRAMU: +------------------------ + +vlna -m -n -s -r soubor ... odpovídá zhruba volání původního vlnka. +Není to zcela přesné, protože program navíc nevlnkuje za slovy \TeX a +\LaTeX a to se nedá vypnout. + +vlna *.tex ... provlnkuje všechny soubory s příponou .tex. +Pracuje pouze na UNIXu. + +vlna -f soubor > /dev/null ... provede test konzistence math a +verbatim módů a neudělá žádnou změnu. + +HISTORIE TOHOTO PRODUKTU: +------------------------- + +Původní verzi programu vlnka vytvořil zhruba v roce 1990 Oldřich Ulrych +v Pascalu. Další vylepšení v Pascalském programu udělal Štěpán Kasal. +Tento Pascalský program je šířen v balíku CSTeX. + +Zde uvedená varianta programu (vlna) byla napsána v únoru 1995 pro +použití v UNIXových prostředích, a proto v jazyce C. Přesněji byl +použit prostředek CWEB, který umožňuje snadno číst zdrojový text a +snadno jej modifikovat. Program byl zcela přepracován (z původního +Pascalského kódu nebylo použito vůbec nic) a byl do něj implementován +algoritmus rozpoznávání tzv. patternů (jednoduchých regulárních +výrazů). + +Tato varianta programu byla testována na SUN OS a na MS DOS. + +V únoru 1998 mi poslal pan Rudof Čejka Makefile a manuálovou stránku +k programu a ve zdrojovém kódu poravil drobné chyby. + +23.2.1995 Petr Olšák. + diff --git a/Build/source/utils/vlna/vlna.w b/Build/source/utils/vlna/vlna.w new file mode 100644 index 00000000000..e366bffb146 --- /dev/null +++ b/Build/source/utils/vlna/vlna.w @@ -0,0 +1,1003 @@ + +\input csmac % Makra pro češtinu +\pageheight=9.5in \fullpageheight=9.8in \setpage +%\nocon % omit table of contents +\datethis % print date on listing + +\def\begitems{\medskip\bgroup\catcode`\*=13 \narrower\narrower} +\def\enditems{\par\egroup\medskip} +{\catcode`\*=13 \gdef*{\par\noindent\llap{$\bullet$\ }\ignorespaces}} + + +@* PROGRAM VLNA. +Program čte vstupní textový soubor a nahrazuje za specifikovanými +jednopísmennými slovy (např.~v, k, u) mezery symbolem \uv{\.{\char126}}. To +zabrání při následném zpracování \TeX{}em zlomit řádek na nevhodných +místech, která jsou v rozporu s typografickou normou. + +Program sestává z těchto hlavních celků: +@c +@<Hlavičkové soubory k načtení@>@/ +@<Globální deklarace@>@/ +@<Pomocné funkce@>@/ +@<Vlnkovací funkce |tie|@>@/ +@<Hlavní program@> + +@ Definujeme |BANNER|, což je text, který se objevi při startu +programu a obsahuje číslo verze programu. +Zde je názorně vidět, že míchání dvou jazyků se nevyhneme. Při tisku +textů na terminál nesmíme předpokládat, že tam budou české fonty. +V~této dokumentaci se setkáme se třemi jazyky: angličtinou (většinou +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" + +@ V programu jsou použity knihovní funkce, jejíchž prototypy jsou +definovány ve třech standardních hlavičkových souborech. +@<Hlavičkové ...@>= +#include <stdio.h> +#include <string.h> +#include <stdlib.h> + +@ Definujeme konstanty pro návratový kód. |OK| pro úspěšný běh, +|WARNING| při výskytu aspoň jedné varovné zprávy, |IO_ERR| pro chybu +v~přístupu ke vtupním nebo výstupním souborům, |BAD_OPTIONS| pro +syntaktickou chybu na příkazové řádce a |BAD_PROGRAM| pro případ +havárie programu. Ta by neměla nikdy nastat. Proměnná |status| bude +obsahovat návratový kód a proměnná |prog_name| bude ukazovat na text +nultého parametru příkazové řádky. +@d OK 0 +@d WARNING 1 +@d IO_ERR 2 +@d BAD_OPTIONS 3 +@d BAD_PROGRAM 4 +@<Globální deklarace@>= +char *prog_name; +int status; + +@ Základní rozvržení funkce |main|. +@<Hlavní program@>= +int main (argc,argv) + int argc; + char **argv; +{ + @<Lokální proměnné funkce |main|@>; + prog_name=argv[0]; status = OK; + @<Načtení parametrů příkazového řádku@>; + if (!silent) fprintf (stderr, BANNER); + @<Inicializace datových struktur@>; + @<Zpracování souborů@>; + return status; +} + +@* Parametry příkazového řádku. +Program čte z~příkazového řádku postupně (nepovinné) parametry, +které začínají znakem \uv{\.{-}}. Pak následují jména vstupních a výstupních +souborů. +\begitems +* \.{-f} \dots\ program pracuje jako filtr (viz sekce |@<Zpracování + souborů@>|). Není-li tento parametr použit, program pracuje v tzv. + standardním režimu, kdy jednotlivé soubory jsou vstupní i výstupní. +* \.{-s} \dots\ program nevypíše |BANNER|, ani sumarizaci, ani varování, + při nichž není program předčasně ukončen. Všechny tyto výpisy + směřují do |stderr|, takže pokud program pracuje v režimu \uv{filtr}, + není nutné tento parametr použít. +* \.{-r} \dots\ program maže pracovní soubor (soubory), které vytváří + ve standardním režimu (tj. není použit \.{-f}). V reřimu filter nemá + tento parametr vliv. +* \.{-v} \dots\ parametr definuje skupinu písmen, které budou + interpretovány jako neslabičné předložky. + Např. \.{-v KkSsVvZzOoUuAI}. Pokud není parametr uveden, je použita + skupina uvedená v tomto příkladě. +* \.{-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 + uvnitř verbatim módu definovaném běžnými prostředími. Imlicite ve + verbatim prostředí nevlnkuje. +* \.{-l} \dots\ La\TeX{} režim. Při kontrole text-math-verbatim módů jsou + brány v úvahu další sekvence, obvyklé v La\TeX{}ových dokumentech. +* \.{-w} \dots\ WEB režim. Ohraničení verbatim módu je doplněno znaky + používanými v dokumentech WEB (např. tento dokument). Důsledek: program + vlnkuje dokumentační část každé sekce, ale nikoli kód. +\enditems + +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. +@<Pomocné funkce@>= +void printusage () +{ + fprintf(stderr, + "usage: vlna [opt] [filenames]\n" + " opt -f : filter mode: file1 file2 ... file1->file2\n" + " file1 ... file1->stdout\n" + " ... stdin->stdout\n" + " nofilter: file1 [file2 file3 ...] all are in/out\n" + " -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" + " -m : nomath: ignores math modes\n" + " -n : noverb: ignores verbatim modes\n" + " -l : LaTeX mode\n" + " -w : web mode\n"); +} + +@ Proměnné |isfilter|, |silent|, |rmbackup|, |nomath|, |noverb|, +|latex|, resp. |web| říkají, že je nastaven parametr \.{-f}, \.{-s}, +\.{-r}, \.{-m}, \.{-n}, \.{-l}, resp. \.{-w}. Proměnná |charset| +ukazuje buď na implicitní skupinu znaků |charsetdefault|, nebo (při +použití parametru \.{-v}) na text uvedený v příkazovém řádku. +@<Globální deklarace@>= +int isfilter=0, silent=0, rmbackup=0, nomath=0, noverb=0, web=0, latex=0; +char charsetdefault[]="KkSsVvZzOoUuAI"; +char *charset=charsetdefault; + +@ @<Načtení parametrů ...@>= +while (argc>1 && argv[1][0] == '-') { + if (argv[1][2] != 0) printusage (), exit (BAD_OPTIONS); + switch(argv[1][1]) { + case 'f': isfilter = 1; break; + case 's': silent = 1; break; + case 'r': rmbackup = 1; break; + case 'v': argv++; argc--; charset = argv[1]; break; + case 'm': nomath = 1; break; + case 'n': noverb = 1; break; + case 'l': latex = 1; break; + case 'w': web = 1; break; + default: printusage (), exit (BAD_OPTIONS); + /* nezn\'am\'y parametr */ + } + argc--; argv++; +} + +@* 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}. +@d MAXLEN 120 +@<Lokální proměnné funkce...@>= +FILE *infile, *outfile; +char backup[MAXLEN]; +int j; + +@ Definujeme funkci pro výpis chybového hlášení při neúspěšném otevření +souboru. +@<Pomocné funkce@>= +void ioerr (f) + char *f; +{ + fprintf(stderr, "%s: cannot open file %s\n", prog_name, f); +} + +@ Způsob zpracování souborů rozlišíme podle režimu daným přepínačem \.{-f}. +@<Zpracování souborů@>= +if (isfilter) @<Zpracování v režimu filter@> @/ +else @<Zpracování všech souborů příkazové řádky@> + +@ V režimu |isfilter==1| je další zpracování závislé na počtu souborů v +příkazové řádce: +\begitems +* nula souborů -- vstup je |stdin| a výstup je |stdout|, +* jeden soubor -- je vstupní, výstup je |stdout|, +* dva soubory -- první je vstupní, druhý výstupní, +* více souborů -- program skončí s chybou. +\enditems +@<Zpracování v režimu filter@>= +{ + if (argc > 3) printusage (), exit (BAD_OPTIONS) ; + infile = stdin; outfile = stdout; + if (argc >= 2) infile = fopen (argv[1], "r"); + if (infile == NULL) ioerr (argv[1]), exit (IO_ERR); + if (argc == 3) outfile = fopen(argv[2], "w"); + if (outfile == NULL) ioerr (argv[2]), exit (IO_ERR); + if (argc >= 2) filename = argv[1]; + else filename = NULL; + tie (infile, outfile); + if (outfile != stdout) fclose (outfile); + if (infile != stdin) fclose (infile); +} + +@ V~režimu |isfilter==0| jsou jednotlivé soubory v~příkazovém řádku +interpretovány jako vstupní i výstupní. Více souborů v~příkazovém řádku má +stejný efekt, jako opakované volání programu na jednotlivé soubory. +V~\UNIX/u lze tedy např. napsat \.{\jobname\ *.tex} a program doplní vlnky do +všech souborů s~příponou~\.{tex}. Toto neplatí v~DOSu, protože interpretace +masky je v~\UNIX/u starostí shellu a nikoli programu samotného. Náš program +masku nebude interpretovat. Je-li v~tomto režimu nulový počet souborů, +program se ukončí s~chybou. +@<Zpracování všech souborů příkazové řádky@>= +{ + if (argc==1) printusage (), exit(BAD_OPTIONS); + while (argc>1) { + argc--; argv++; + @<Přejmenuj vstup |argv[0]| na |backup| a otevři jej jako |infile|@>; + if (infile == NULL) { + ioerr (argv[0]); continue; + } + outfile = fopen (argv[0], "w"); + if (outfile == NULL) { + ioerr (argv[0]); + rename (backup, argv[0]); + status = WARNING; + continue; + } + filename = argv[0]; + tie (infile, outfile); + fclose (outfile), fclose (infile); + if (rmbackup) remove (backup); + } +} + +@ Při |isfilter==0| program přejmenuje každý zpracovávaný soubor tak, že +změní poslední písmeno názvu souboru na znak \.{\char126}. Tento +přejmenovaný soubor bude otevřen jako vstupní a výstupem bude původní +soubor. Vstupní soubor při |rmbackup==0| zůstane zachován jako záloha. + +Proč vlnku nepřidáváme na konec názvu souboru, ale měníme ji za poslední +znak souboru? Protože chceme, aby program fungoval i v tak nemožných +systémech, jako je DOS. +@<Přejmenuj vstup...@>= +infile = NULL; +j = strlen (argv[0]) - 1; +if (j >= MAXLEN || argv[0][j] == '~') { + if (!silent) fprintf (stderr, "%s: the conflict of file name %s\n", + prog_name, argv[0]); +} +else { + strcpy (backup, argv[0]); + backup[j] = '~'; + remove (backup); + j = rename (argv[0], backup); + if (j == 0) infile = fopen (backup, "r"); +} + +@* Patterny. Abychom mohli účelně definovat chování programu +v~různých situacích, zavedeme datovou strukturu |PATTERN|. Zhruba +řečeno, budeme sledovat vstup znak po znaku a pokud bude část vstupu +souhlasit s~definovaným patternem, provedeme námi požadovanou +akci. Například nejčastější aktivitu, přidání vlnky uvnitř řádku, +spustíme v~okamžiku, kdy vstupní text odpovídá patternu \uv{\.{\ (v\ +p}}, kde \uv{\.{\ }} znamená jedna nebo více mezer a tabelátorů, +\uv{\.{(}} je nula nebo více otevíracích závorek všeho druhu, +\uv{\.{v}} znamená jedno písmeno z~množiny předložek (viz |charset|) a +\uv{\.{p}} zde znamená libovolné písmeno. Příklad zde není zcela přesný. +Přesně jsou všechny patterny pro náš program definovány v~závěrečných +sekcích tohoto povídání. + +Pattern bude znamenat konečnou sekvenci tzv. pozic patternu (|PATITEM|). +Cykly uvnitř pozic pro jednoduchost nepřipustíme. Každá pozice obsahuje +řetězec znaků, uvažovaný pro danou pozici (v~příkladu pozice~\uv{\.{\ }} by +obsahovala mezeru a tabelátor, zatímco pozice \.{v} odpovídá |charset|). +Každá pozice má svůj přepínač (|flag|), který obsahuje informaci o~tom, +zda shodu testovaného znaku s~některým prvkem v~množině znaků +budeme považovat za úspěch či neúspěch a zda pozice se ve zkoumaném +řetězci může vyskytovat právě jednou nebo opakovaně. Jako druhý případ +stačí implementovat \uv{nula nebo více} protože \uv{jedna nebo více} lze +popsat pomocí dvou pozic, první \uv{právě jednou} a následující \uv{nula +nebo více}. Jednotlivé pozice jsou zřetězeny ukazatelem |next|, poslední +pozice má |next==NULL|. Stejně tak jednotlivé patterny budeme +sestavovat do seznamů a budou rovněž zřetězeny ukazatelem |next|. + +Pattern kromě řetězu pozic obsahuje ukazatel na funkci (proceduru) |proc|, +která se má vykonat v~případě, že testovaný řetězec vyhovuje patternu. + +@d ONE 1 /* flag: prave jeden vyskyt */ +@d ANY 2 /* flag: nula nebo vice */ +@d ONE_NOT -1 /* flag: prave jednou, znak nesmi byt v mnozine */ +@d ANY_NOT -2 /* flag: nula nebo vice, znak nesmi byt v mnozine */ + +@<Globální deklarace@>= +typedef struct PATITEM { /* jedna pozice patternu */ + char *str; /* seznam znaku na teto pozici */ + int flag; /* vyznam seznamu znaku */ + struct PATITEM *next ; /* nasledujici pozice patternu */ +} PATITEM; +typedef struct PATTERN { /* jeden pattern */ + PATITEM *patt; /* ukazatel na prvni pozici */ + void (*proc)(); /* procedura spustena pri souhlasu patternu */ + struct PATTERN *next ; /* nasledujici v seznamu vsech patternu */ +} PATTERN; + +@ Deklarujeme některé globální proměnné pro práci s~patterny. |lapi| je pole +obsahující ukazatele na aktuální pozice v~otevřených patternech. Říkáme, +že \uv{pattern je otevřen}, pokud zkoumaný řetězec s~ním {\it začíná\/} +souhlasit. Pattern se uzavře, pokud nastane jedna ze dvou možností: +zkoumaný řetězec s~mím souhlasí až do konce (v~takovém případě se provede +procedura |proc|), nebo při vyšetřování dalších znaků ze zkoumaného +řetězce přestane řetězec s~patternem souhlasit. + +V~dané chvíli může být pattern otevřen několikrát. Např. pattern \.{abac} +je při stringu \.{aba} při výskytu druhého \.{a} otevřen podruhé. Proto +pole obsahuje ukazatele na právě aktuální pozici patternu a nikoli na +pattern jako takový. + +V~poli |lapi| budou na počátku samá |NULL| (to se při překladu inicializuje +samo) a přemazání ukazatele na pozici konstantou |NULL| budeme považovat +za zavření patternu. Vedle pole |lapi| souměrně udržujeme pole |lapt|, +do něhož budeme ukládat ukazatele na odpovídající otevřený pattern. Tuto +informaci použijeme v~případě, že potřebujeme např, znát |proc| +patternu. + +|listpatt| bude ukazovat na začátek aktuálního seznamu patternů. Seznamy +budeme mít dva. Jeden se použije, nacházíme-li se mimo komentář a druhý +v~případě, že se nacházíme v~prostoru \TeX{}ovského komentáře (tj. za +procentem). Starty těchto seznamů patternů jsou |normallist| a +|commentlist| a aktivní |listpatt| má vždy jednu z~těchto dvou hodnot. + +Proměnné |lastpt| a |lastpi| použijeme pro budování řetězové struktury +patternů. + +Proměnná |c| obsahuje právě testovaný znak ze vstupu (který se rovněž +přepíše do bufferu |buff|). Z~bufferu občas ukládáme data do výstupního +proudu. Děláme to ale vždy jen v~okamžiku, kdy není otevřen žádný +pattern. Tehdy totiž \uv{nehrozí} situace, že by nějaká procedura vyvolaná +souhlasem patternu požadovala v~tomto bufferu nějaké změny se zpětnou +platností. O~vyprázdnění bufferu se začneme zajímat až v~okamžiku, kdy je +zaplněn aspoň na hodnotu |BUFI|, abychom proceduru přepisu bufferu do +výstupního proudu neaktivovali zbytečně často. +@d MAXPATT 200 /* maximalni pocet patternu */ +@d MAXBUFF 500 /* velikost bufferu pro operace */ +@d BUFI 300 /* velikost stredniho zaplneni */ +@<Globální deklarace@>= +PATITEM *lapi[MAXPATT]; /* pole ukazatelu na aktualni pozice */ +PATTERN *lapt[MAXPATT]; /* pole odpovidajicich ukazatelu na patterny */ +PATTERN *listpatt, *normallist, *commentlist, *pt, *lastpt=NULL; +PATITEM *pi, *lastpi=NULL; +char c; /* zrovna nacetny znak */ +char buff[MAXBUFF]; /* prechodny buffer */ +int ind; /* aktualni pozice prechodneho bufferu */ + +@ 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ě +pomocí funkce |myalloc|. +@<Pomocné funkce@>= +void *myalloc (size) + int size; +{ + void *p; + p = malloc (size); + if (p == NULL) + { + fprintf (stderr, "%s, no memory, malloc failed\n", prog_name); + exit (BAD_PROGRAM) ; + } + return p; +} + +@ Funkce |setpattern| alokuje paměťové místo struktury |PATTERN| a napojí +ji pomocí proměnné |lastpt| na už alokovaný řetěz patternů. +Vrátí ukazatel na nově alokované místo. Jednotlivé pozice patternu se musí +následovně alokovat pomocí |setpi|. +@<Pomocné funkce@>= +PATTERN *setpattern (proc) @/ + void (*proc)(); +{ + PATTERN *pp; + pp = myalloc (sizeof (PATTERN)); + pp->proc = proc; + pp->next = NULL; + pp->patt = NULL; + if (lastpt != NULL) lastpt->next = pp; + lastpt = pp; + lastpi = NULL; + return pp; +} + +@ Funkce |setpi| alokuje paměťové místo pro jednu pozici patternu. Provede +zřetězení tak, aby první pozice řetězu pozic byla zaznamenána v položce +|patt| ve struktuře |PATTERN| a další byly provázány položkou |next| ve +struktuře |PATITEM|. Poslední pozice má |next==NULL|. +@<Pomocné funkce@>= +void setpi (str, flag) + char *str; + int flag; +{ + PATITEM* p; + p = myalloc (sizeof (PATITEM)); + p->str = str; p->flag = flag; + p->next = NULL; + if (lastpi == NULL) lastpt->patt = p; + else lastpi->next = p; + lastpi = p; +} + +@ Připravme si půdu pro funkci |normalpattern|. Tato funkce alokuje +strukturu pro jeden pattern včetně pozic patternu na základě vstupního +stringu. Každá pozice patternu obsahuje v~množině znaků jediný znak a má +|flag=ONE|. Znaky ve vstupním stringu odpovídají po řadě jednotlivým +pozicím. Vytvoří se vlastně jakýsi absolutní pattern, tj. testovaný řetězec +se musí přesně shodovat s~uvedeným stringem. Výjimku tvoří znak |"."|, +který se interpretuje jako nula nebo více mezer. Chceme-li tečku +vnutit do patternu, napíšeme dvě tečky za sebou. + +Nejdříve deklarujeme pole všech možných jednopísmenných stringů. +@<Globální deklarace@>= +char strings[512]; +int i; + +@ Inicializujeme toto pole (znak, nula, znak, nula, atd...). +@<Inicializace datových struktur@>= +for (i=0; i<256; i++) { + strings[2*i] = (char) i; strings[2*i+1] = 0; +} + +@ Definujme funkci |normalpattern|. +@<Pomocné funkce@>= +PATTERN *normalpattern (proc, str) @/ + void (*proc)(); + char *str; +{ + PATTERN *pp; + int j=0; + pp = setpattern (proc); + while (str[j]) { + if (str[j]=='.') { + j++; + if (str[j]!='.') { + setpi (blankscr, ANY); + continue; + } + } + setpi (&strings[(unsigned char)str[j]*2], ONE); + j++; + } + return pp; +} + +@ Funkce |match|. Definujeme funkci, která na základě hodnoty znaku |c| +(proměnná |c| je definována jako globální), a pozice patternu |p| (parametr +funkce) vrátí informaci o tom, zda znak souhlasí s patternem. Záporná čísla +|FOUND|, resp. |NOFOUND| znamenají, že je třeba uzavřít pattern s tím, že +vzor odpovídá, resp. neodpovídá patternu. Nezáporné číslo vrátí v případě, +že zkoumaný vstup stále souhlasí s patternem, ale není ještě +rozhodnuto. Velikost návratové hodnoty v takovém případě udává, o kolik +pozic je třeba se posunout v patternu, abychom měli ukazatel na pozici +patternu v souhlase s novou situací, způsobenou znakem |c|. + +Pokud je |c| v množině znaků pro danou pozici |p->str|, bude |m==1|, jinak +je |m==-1|. Pokud tímto číslem pronásobíme hodnotu |p->flag|, nemusíme +větvení podle |p->flag| programovat dvakrát. Hodnoty |flag| jsou totiž +symetrické podle nuly, např. |ANY==-ANY_NOT|. +@d FOUND -1 +@d NOFOUND -2 +@<Pomocné funkce@>= +int match (p) + PATITEM *p; +{ + int m; + if (strchr (p->str, c) != NULL) m = 1; /* Znak nalezen */ + else m = -1; /* Znak nenalezen */ + switch (m * p->flag) { + case ANY: return 0; /* Souhas, neni nutny posun */ + case ONE: if (p->next == NULL) return FOUND; + return 1; /* Souhas, nutny posun o 1 */ + case ONE_NOT: return NOFOUND; /* Nesouhlas */ + case ANY_NOT: @<Vrať hodnotu podle následující...@>; + } + return 0; /* Tady bychom nikdy nemeli byt, return pro potlaceni varovani */ +} + +@ O kolik pozic je třeba se posunout a s jakým výsledkem zjistíme +rekurzivním voláním funkce |match|. +@<Vrať hodnotu podle následující pozice patternu@>= +switch (m = match (p->next)) { +case NOFOUND: return NOFOUND; +case FOUND: return FOUND; +default: return 1 + m; +} + +@* Vlnkovací funkce. +Nejprve připravíme globální deklarace pro \uv{vlnkovací} funkci |tie|. +Funkce |tie| \uv{ovlnkuje} vstupní soubor |infile| a vytvoří soubor +|outfile|. Při |silent=0| tiskne závěrečnou zprávu o zpracování. V této +zprávě se objeví jméno souboru, které se funkce \uv{dozví} prostřednictvím +globální proměnné |filename|. Proměnná |numline| počítá řádky, proměnná +|numchanges| sčítá změny, tj. počet doplněných vlnek. +Proměnná |mode| nabývý některé z hodnot |TEXTMODE|, |MATHMODE|, +|DISPLAYMODE| a |VERBMODE| podle stavu ve čteném textu. +@d TEXTMODE 0 +@d MATHMODE 1 +@d DISPLAYMODE 2 +@d VERBMODE 3 +@<Globální deklarace@>= +char *filename; /* jmeno zpracovavaneho souboru */ +long int numline, numchanges; /* pro zaverecnou statistiku */ +int mode; + +@ Nyní definujeme vlnkovací funkci |tie|. Veškerá činnost se opírá o +strukturu patternů. Výhodné je (z důvodu rychlosti) \uv{natvrdo} zde +implementovat jen přepínání mezi stavem čtení z oblasti komentáře +(|listpatt==commentlist|) a mimo komentář (|listpatt==normallist|); +@<Vlnkovací funkce |tie|@>= +void tie (input, output) + FILE *input, *output; +{ + int ap; /* ap je pocet otevrenych patternu */ + register int k, m, n; + int ic; + PATTERN *pp; + PATITEM *pi; + + @<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@>; + if (ind >= MAXBUFF) { + fprintf (stderr, "Operating buffer overflow, is anything wrong?\n"); + exit (BAD_PROGRAM); + } + if ((ic = getc(input)) == EOF) /* opravil Cejka Rudolf */ + break; + buff[ind++] = c = ic; + if (c == '\n') numline++, listpatt = normallist; + if (c == '%' && mode!=VERBMODE && buff[ind-2] != '\\') listpatt = commentlist; + @<Projdi otevřené patterny@>; + } + @<Vyprázdni buffer@>; + if (!web) checkmode (); /* zaverecna kontrola modu */ + if (!silent) @<Tiskni závěrečnou zprávu@>; +} + +@ @<Inicializace proměnných při ...@>= +for (k=0; k<MAXPATT; k++) lapi[k] = NULL; +c = '\n'; +buff[0] = mode = ap = 0; ind = 1; +numline = 1; numchanges = 0; +mode = TEXTMODE; + +@ Při manipulaci s bufferem byl použit jeden trik. Veškeré načtené znaky +začínají až od |buff[1]|, zatímco |buff[0]| je rovno nule. Je to proto, že +některé algoritmy se vrací o jeden znak zpět za svůj pattern, aby zjistily, +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. +@<Vyprázdni buffer@>= +{ + buff[ind] = 0; + fputs (&buff[1], output); + ind = 1; +} + +@ Při procházení otevřenými patterny posunujeme v poli |lapi| pozice +jednotlivých patternů podle pokynů funkce |match|, případně pattern zavřeme +a případně vyvoláme proceduru patternu. + +Některé patterny v poli |lapi| už mohou být zavřeny, takže je nutno s tímto +polem pracovat jako s jakýmsi děravým sýrem. +@<Projdi otevřené patterny@>= +n = ap; k = 0; +while (n) { + while (lapi[k]==NULL) k++; /* zastav se na prvnim ukazateli na pattern */ + switch (m = match (lapi[k])) { + case FOUND: (*lapt[k]->proc)(); /* Pattern nalezen, spustit proceduru */ + case NOFOUND: lapi[k] = NULL; /* Deaktivace patternu */ + ap--; break; + default: while (m--) lapi[k] = lapi[k]->next; /* dalsi pozice patternu */ + } + k++; n--; +} + +@ Při otevírání nových patternů, které nejsou v tuto chvíli zablokovány, +se hned vypořádáme s takovými patterny, které nám dávají rovnou odpověď +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) { + switch (m = match (pp->patt)) { + case FOUND: (*pp->proc)(); /* spustit proceduru */ + case NOFOUND: break; + default: @<Vytvoř ukazatel na nový pattern a |break|@>; + } + pp=pp->next; +} + +@ Není-li hned známa odpověď, zda pattern vyhovuje či nikoli, +překontrolujeme nejdříve, zda už není pattern ve stejné pozici otevřený. +Pak najdeme první \uv{díru} v tabulce |lapi| a tam uhnízdíme nový ukazatel +na pozici v patternu. +@<Vytvoř ukazatel na nový pattern...@>= +pi = pp->patt; +while (m--) pi = pi->next; +n = ap; k = 0; +while (n) { + if (lapi[k]==pi) break; + if (lapi[k++] != NULL) n--; +} +if (!n) { + k = 0; + while (lapi[k] != NULL) k++; + if (k >= MAXPATT) { + fprintf (stderr, "I cannot allocate pp, is anything wrong?\n"); + exit (BAD_PROGRAM); + } + lapt[k] = pp; lapi[k] = pi; ap++; +} + +@ Poslední věcí ve funci |tie| je tisk závěrečné statistiky zpracování. +@<Tiskni závěrečnou zprávu@>= +fprintf (stderr, "~~~ file: %s\t lines: %ld, changes: %ld\n", + filename, numline, numchanges); + +@* Inicializace patternů. +Po vytvoření předchozího kódu opírajícího se o~patterny máme nyní v~ruce +poměrně silný nástroj na definování různých činností programu prostým +vytvořením patternu a příslušné jeho procedury. Pokud budeme chtít +v~budoucnu nějaký rys programu přidat, pravděpodobně to bude snadné. + +Nejprve deklarujeme některé často používané skupiny znaků v~patternech. + +@<Globální deklarace@>= +char tblanks[] = " ~\t"; +char blanks[] = " \t"; +char blankscr[] = " \t\n"; +char tblankscr[] = " ~\t\n"; +char nochar[] = "%~\n"; +char cr[] = "\n"; +char prefixes[] = "[({~"; +char dolar[] = "$"; +char backslash[] = "\\"; +char openbrace[] = "{"; +char letters[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; +PATTERN *vlnkalist, *mathlist, *parcheck, *verblist ; + +@ Začneme definicí nejčastěji používaného patternu na vlnkování uvnitř +řádku. Připomeňme, že opakované volání funkce |setpattern| vytváří interně +seznam patternů, přičemž o~jejich propojení se nemusíme starat. Vyzvedneme +si z~návratového kódu funkce pouze ukazatel na první položku seznamu +|normallist|. Stejně tak opakované volání funkce |setpi| vytváří seznam +pozic pro naposledy deklarovaný pattern. +@<Inicializace datových struktur@>= +vlnkalist = setpattern (vlnkain); +setpi (tblankscr, ONE); +setpi (tblanks, ANY); +setpi (prefixes, ANY); +setpi (charset, ONE); +setpi (blanks, ONE); +setpi (blanks, ANY); +setpi (nochar, ONE_NOT); + +@ @<Inicializace proměnných při ...@>= +listpatt = normallist = vlnkalist; + +@ @<Pomocné funkce@>= +void vlnkain() +{ + char p; + ind--; + p = buff[ind--]; + while (strchr(blanks, buff[ind]) !=NULL) ind--; + ind++; + buff[ind++] = '~'; + buff[ind++] = p; + numchanges++; +} + +@ Podobně pro tvorbu vlnky \uv{přes řádek} vytvoříme pattern a kód +procedury. +@<Inicializace dat...@>= +setpattern (vlnkacr); +setpi (tblankscr, ONE); +setpi (tblanks, ANY); +setpi (prefixes, ANY); +setpi (charset, ONE); +setpi (blanks, ANY); +setpi (cr, ONE); +setpi (blanks, ANY); +setpi (nochar, ONE_NOT); + +@ V proceduře k tomuto patternu musíme ošetřit případ typu +\uv{\.{a\char126v\char92np}}, +kdy nelze prostě přehodit \uv{\.{\char92n}} za \uv{\.{v}}, protože +bychom roztrhli +mezeru svázanou vlnkou už dříve. Proto musíme vyhledat vhodné místo pro +roztržení řádku, které bude až {\it před\/} znakem \uv{\.{a}}. Při důsledném +ošetření tohoto fenoménu můžeme dokonce narazit na situaci +\uv{\.{\char92n\ v\char126v\char126v\char92np}}, kde nemůžeme vložit +\uv{\.{\char92n}} před první výskyt \uv{\.{v}}, protože bychom dostali +\uv{\.{\char92n\char92n}}, tedy prázdný +řádek. Ten je v \TeX{}u interperetován odlišně. V této výjimečné +situaci pouze zrušíme stávající (v pořadí druhé) \uv{\.{\char92n}} a +nebudeme vytvářet nové. Na výstupu bude soubor o jeden řádek kratší. +@<Pomocné funkce@>= +void vlnkacr() +{ + char p; + int i, j; + ind--; + p = buff[ind--]; + while (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--; + if (i >= 0 && buff[i] == '\n') j = -1; + if (j >= 0) buff[j] = '\n'; + else numline--; + ind++; + buff[ind++] = '~'; + buff[ind++] = p; + numchanges++; +} + +@ Nyní vytvoříme patterny pro případy typu \.{\char92uv\char`\{v lese\char`\}}. +@<Inicializace dat...@>= +setpattern (vlnkain); /* na radku */ +setpi (tblankscr, ONE); +setpi (backslash, ONE); +setpi (letters, ONE); +setpi (letters, ANY); +setpi (openbrace, ONE); +setpi (prefixes, ANY); +setpi (charset, ONE); +setpi (blanks, ONE); +setpi (blanks, ANY); +setpi (nochar, ONE_NOT); + +setpattern (vlnkacr); /* pres radek */ +setpi (tblankscr, ONE); +setpi (backslash, ONE); +setpi (letters, ONE); +setpi (letters, ANY); +setpi (openbrace, ONE); +setpi (prefixes, ANY); +setpi (charset, ONE); +setpi (blanks, ANY); +setpi (cr, ONE); +setpi (blanks, ANY); +setpi (nochar, ONE_NOT); + + + +@ Vytvoříme patterny a proceduru pro potlatčení tvorby vlnky u písmen těsně +následujících sekvence \.{\char92TeX} a \.{\char92LaTeX}. Tj. nechceme, aby +např z textu \uv{\.{Vlastnosti~\char92TeX~u~jsou...}} jsme dostali text +s nesprávně vázaným písmenem +\uv{\.{Vlastnosti~\char92TeX~u\char126jsou...}}. +@<Inicializace dat...@>= +normalpattern (tielock, "\\TeX"); +setpi (blankscr, ONE); +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í +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. +@<Pomocné funkce@>= +void tielock () +{ + c = 1; +} + +@ Ošetříme nyní přechod do/z matematického režimu \TeX{}u. Uvnitř math +módu vlnky neděláme. Při zjištěném nesouladu v přechodech mezi +math-módy spustíme následující proceduru. +@<Pomocné funkce@>= +void printwarning () +{ + if (!silent) + fprintf (stderr, + "~!~ warning: text/math/verb mode mismatch, file: %s, line: %ld\n", + filename, numline - (c=='\n'?1:0)); + status = WARNING; +} + +@ Začneme patterny pro přechod do/z matematického režimu, ohraničeného +jedním dolarem, nebo v La\TeX{}u příslušnými sekvencemi. Sekvence +La\TeX{}u \.{\char92(} a \.{\char92)} nejsou zahrnuty, protože bývají +často předefinovány k jiným užitečnějším věcem. +@<Inicializace datových ...@>= +if (!nomath) { + mathlist = setpattern (onedollar); + setpi (dolar, ONE); + setpi (dolar, ONE_NOT); + if (latex) { + normalpattern (mathin, "\\begin.{math}"); + normalpattern (mathout, "\\end.{math}"); + } +} + +@ @<Pomocné funkce@>= +void mathin () +{ + if (mode!=TEXTMODE) printwarning (); + mode = MATHMODE; + normallist = listpatt = mathlist; +} +void mathout () +{ + if (mode!=MATHMODE) printwarning (); + mode = TEXTMODE; + normallist = listpatt = vlnkalist; +} + +@ Při programování procedury |onedollar| nesmíme zapomenout na výskyt +sekvence \.{\char92\$}. V tom případě akci ignorujeme. Podobně u sekvence +\.{\$\$} souhlasí ten druhý dolar s naším patternem, ale to už jsme uvnitř +display módu. V takovém případě také nic neděláme. +@<Pomocné funkce@>= +void onedollar () +{ + if (buff[ind-3]=='\\' || (buff[ind-3]=='$' && buff[ind-4]!='\\')) return; + if (mode==DISPLAYMODE) printwarning (); + else { + if (mode==TEXTMODE) mathin(); + else mathout(); + } +} + +@ Pokud najdeme prázdný řádek, překontrolujeme, zda náhodou nejsme v +math-módu. Pokud ano, vypíšeme varování a přejdeme do textového módu. +@<Inicializace dat...@>= +parcheck = setpattern (checkmode); +setpi (cr, ONE); +setpi (blanks, ANY); +setpi (cr, ONE); + +@ @<Pomocné funkce@>= +void checkmode () +{ + if (mode!=TEXTMODE) { + printwarning (); + mode = TEXTMODE; + normallist = listpatt = vlnkalist; + } +} + +@ Nyní ošetříme výskyt dvou dolarů, tj. vstup do/z display módu. +Rovněž mysleme na La\TeX{}isty a jejich prostředí pro display-mód. Protože +je možná alternativa s hvězdičkou na konci názvu prostředí, raději už +uzavírací závorku do patternu nezahrnujeme. + +@<Inicializace dat...@>= +if (!nomath) { + normalpattern (twodollars, "$$"); + if (latex) { + normalpattern (displayin, "\\begin.{displaymath"); + normalpattern (displayin, "\\begin.{equation"); + normalpattern (displayout, "\\end.{displaymath"); + normalpattern (displayout, "\\end.{equation"); + } +} + +@ @<Pomocné funkce@>= +void displayin () +{ + if (mode!=TEXTMODE) printwarning (); + mode = DISPLAYMODE; normallist = listpatt = parcheck; +} +void displayout () +{ + if (mode!=DISPLAYMODE) printwarning(); + mode = TEXTMODE; normallist = listpatt = vlnkalist; +} +void twodollars () +{ + if (buff[ind-3]=='\\') return; + if (mode==DISPLAYMODE) displayout (); + else displayin (); +} + +@ Následuje ošetření tzv. verbatim módu. Pro plain i La\TeX{} jsou nejčastější +závorky pro verbatim mod tyto (variantu s \.{\char92begtt} používám +s oblibou já). +@<Inicializace dat...@>= +if (!noverb) { + verblist = normalpattern (verbinchar, "\\verb"); + setpi (blankscr, ANY); + setpi (blankscr, ONE_NOT); + normalpattern (verbin, "\\begtt"); + if (latex) normalpattern (verbin, "\\begin.{verbatim"); +} +if (web) { + normalpattern (verbin, "@@<"); + normalpattern (verbin, "@@d"); +} +if (!noverb) { + verboutlist[0] = setpattern (verbout); + setpi (verbchar, ONE); + verboutlist[1] = normalpattern (verbout, "\\endtt"); + if (latex) verboutlist[2] = normalpattern (verbout, "\\end{verbatim"); +} +if (web) { + verboutlist[3] = normalpattern (verbout, "@@ "); + normalpattern (verbout, "@@*"); + normalpattern (verbout, "@@>|"); +} + + +@ Procedura |verbinchar| se od \uv{společné} procedury |verbin| liší v +tom, že zavede do stringu |verbchar| momentální hodnotu proměnné |c|. +Proto druhý výskyt této hodnoty verbatim režim ukončí. +@<Pomocné funkce@>= +int prevmode; +PATTERN *prevlist, *verboutlist[4]; +char verbchar[2]; +void verbinchar () +{ + prevmode = mode; + verbchar[0] = c; + c = 1; + listpatt = normallist = verboutlist[0]; + prevlist = listpatt->next; + listpatt->next = NULL; + mode = VERBMODE; +} + +@ Při programování \uv{obecné} funkce |verbin| musíme dbát na to, aby +zůstal aktivní pouze odpovídající \uv{výstupní} pattern k danému +vstupnímu. Také si zapamatujeme mód, ze kterého jsme do verbatim +oblasti vstoupili, abychom se k němu mohli vrátit (např. uvnitř +math. módu může být +\.{\char92hbox} a v něm lokálně verbatim konstrukce). +@<Pomocné funkce@>= +void verbin () +{ + int i; + i = 0; + prevmode = mode; + switch (c) { + case 't': i = 1; break; + case 'm': i = 2; break; + case '<': ; + case 'd': i = 3; + if (buff[ind-3]=='@@') return; /* dvojity @@ ignorovat */ + break; + } + listpatt = normallist = verboutlist[i]; + prevlist = listpatt->next; + if (c != '<' && c != 'd') listpatt->next = NULL; + mode = VERBMODE; +} + +@ @<Pomocné funkce@>= +void verbout () +{ + if (mode!=VERBMODE) return; + if (web && buff[ind-2] == '@@' && buff[ind-3] == '@@') return; + mode = prevmode; + normallist->next = prevlist; + switch (mode) { + case DISPLAYMODE: normallist = listpatt = parcheck; break; + case MATHMODE: normallist = listpatt = mathlist; break ; + case TEXTMODE: normallist = listpatt = vlnkalist; break; + } +} + +@ Nyní implementujeme vlastnost dříve používaného programu vlnka, tj. že +lze jeho činnost vypnout a opět zapnout v komentářích. Vytváříme druhý +nezávislý seznam patternů a proto nejprve pronulujeme |lastpt|. +@<Inicializace dat...@>= +lastpt = 0; +commentlist = normalpattern (tieoff, "%.~.-"); +normalpattern (tieon, "%.~.+"); + +@ @<Pomocné funkce@>= +void tieoff () +{ + normallist = NULL; +} +void tieon () +{ + normallist = vlnkalist; +} + +@ Další plánovaná vylepšení. Program by mohl číst definici svého chování +nejen z~příkazové řádky, ale v~mnohem kompletnější podobě, včetně +uživatelsky definovaných patternů, z komentářové oblasti ve čteném souboru. +Parametry zde uvedené by mohly mít vyšší prioritu, než parametry +z~příkazové řádky a mohl by se třeba rozšiřovat seznam sekvencí, za nimiž +písmena nemají být vázana vlnkou (zatím je implemenováno na pevno jen +\.{\char92TeX} a \.{\char92LaTeX}). + +@* Rejstřík. + + diff --git a/Build/source/utils/vlna/win32.mak b/Build/source/utils/vlna/win32.mak new file mode 100644 index 00000000000..a3b16760f1f --- /dev/null +++ b/Build/source/utils/vlna/win32.mak @@ -0,0 +1,56 @@ +################################################################################ +# +# Makefile : Vlna +# Author : Fabrice Popineau <Fabrice.Popineau@supelec.fr> +# Platform : Win32, Microsoft VC++ 6.0, depends upon fpTeX 0.5 sources +# Time-stamp: <02/06/03 15:10:30 popineau> +# +################################################################################ +root_srcdir = ..\.. +!ifdef DEVELOPMENT +INCLUDE=$(INCLUDE);$(root_srcdir)\texk.development +!else +INCLUDE=$(INCLUDE);$(root_srcdir)\texk +!endif + +USE_GNUW32 = 1 + +!include <msvc/common.mak> + +programs = $(objdir)\vlna.exe +manfiles = vlna.1 +infofiles = +installinfoflags = + +objects= $(objdir)\vlna.obj + +default: all + +all: $(objdir) $(programs) + +$(objdir)\vlna.exe: $(objdir)\vlna.obj + $(link) $(**) $(conlibs) + +!include <msvc/config.mak> +!include <msvc/install.mak> + +vlna.1: vlna.man + -@$(sed) -e "s|@BINDIR@|$(bindir)|;\ + s|@MANDIR@|$(mandir)|;\ + s|@MANEXT@|$(manext)|" vlna.man > vlna.$(manext) + +install:: install-exec install-man + + +!include <msvc/clean.mak> + +clean:: + -@$(del) sample1.rb2 sample2.rb2 sample1.tst sample2.tst + +!include <msvc/rdepend.mak> +!include "./depend.mak" + +# +# Local Variables: +# mode: makefile +# End:
\ No newline at end of file |