Ultrix-3.1/src/cmd/troff/checkmm/chekl.l
/* SCCSID: @(#)chekl.l 3.0 4/27/86 */
/* (SYSTEM 5.0) chekl.l 1.1 */
/* Lex source for program chek. Flags questionalbe uses & errors */
/* in usage of PWB/mm macros and some tbl and eqn constructs. */
C [.']
SP [ ]
int i, max, il, jl ; /* for list macros */
char listm[20][20] ; /* storage for list macro args */
int ds, fs, ts, tsh, ns, eq, au, as ; /* use ds, as, ... as indicators of .DS, .AS, ... */
int delset, ldelset, notwarned; /* used for EQN checks */
char ldel, rdel; /* used for EQN checks */
int ae, tl, ok, bs ;
int tm, nd, pla, ofl ;
%% /* lex rules start */
ds = fs = ts = tsh = ns = eq = au = as = ae = au = tl = ok = 0 ;
tm = nd = pla = ofl = bs = 0 ;
il = -1 ; /* list index, indexes listm 0-19 */
delset = ldelset = notwarned = 0;
^{C}ND {if(pla > 1) /* pla is a place keeper for begin macro order */
ofl = 1 ; /* ofl is an order error flag */
else
pla = 1 ;
if(nd)
printf(" Extra .ND at line %d\n",yylineno) ;
if(pla == 9)
printf(" .ND at line %d is after .MT\n",yylineno) ;
nd = 1 ;
}
^{C}TL {if(pla>2)
ofl = 1 ;
else
pla = 2 ;
if(tl)
printf(" Extra .TL at line %d\n",yylineno) ;
if(pla == 9)
printf(" .TL at line %d is after .MT\n",yylineno) ;
tl = 1 ;
}
^{C}AF {if(pla>3)
ofl = 1 ;
else
pla = 3 ;
if(pla == 9)
printf(" .AF at line %d is after .MT\n",yylineno) ;
}
^{C}AU {if(pla>4)
ofl = 1 ;
else
pla = 4 ;
if(pla == 9)
printf(" .AU at line %d is after .MT\n",yylineno) ;
au = 1 ;
}
^{C}TM {if(pla>5)
ofl = 1 ;
else
pla = 5 ;
if(tm)
printf(" Extra .TM at line %d\n",yylineno) ;
if(pla == 9)
printf(" .TM at line %d is after .MT\n",yylineno) ;
tl = 1 ;
}
^{C}AS {if(pla>6)
ofl = 1 ;
else
pla = 6 ;
if(as)
printf(" Extra .AS at line %d\n",yylineno) ;
if(pla == 9)
printf(" .AS at line %d is after .MT\n",yylineno) ;
as = 1 ;
}
^{C}AE {if(pla>7)
ofl = 1 ;
else
pla = 7 ;
if(ae)
printf(" Extra .AE at line %d\n",yylineno) ;
if(pla == 9)
printf(" .AE at line %d is after .MT\n",yylineno) ;
if(!as)
printf(" Missing .AS before .AE at line %d\n",yylineno) ;
ae = 1 ;
}
^{C}OK {if(pla>8)
ofl = 1 ;
else
pla = 8 ;
if(ok)
printf(" Extra .OK at line %d\n",yylineno) ;
if(pla == 9)
printf(" .OK at line %d is after .MT\n",yylineno) ;
ok = 1 ;
}
^{C}MT {if(ofl)
printf(" Beginning macro sequence error before .MT at line %d\n",yylineno) ;
if(pla == 9)
printf(" Extra .MT at line %d\n",yylineno) ;
pla = 9 ;
if(!tl) /* .MT "requires" .TL & .AU */
printf(" No .TL before .MT at line %d\n",yylineno) ;
if(!au)
printf(" No .AU before .MT at line %d\n",yylineno) ;
}
^{C}EQ {if (eq++)
printf(" Spurious EQ, line %d\n", yylineno) ;
if (ldelset)
printf(" EQ in %c%c, line %d\n", ldel, rdel, yylineno) ;
}
^{C}EN {if (eq==0)
printf(" Spurious EN, line %d\n", yylineno) ;
else
eq = 0 ;
if (ldelset) printf(" EN in %c%c, line %d\n", ldel, rdel, yylineno) ;
}
^{SP}*define {if(ds && eq) {
printf(" define at line %d inside .DS\n",yylineno) ; }
}
^{SP}*delim{SP}*.. {if(eq && ds)
printf(" delim at line %d inside .DS\n",yylineno) ;
if(eq && ds==0){
if (ldelset) printf(" Missing right delimiter %c, at delimiter change\n", rdel);
if (yytext[yyleng-2] == 'o' && yytext[yyleng-1] == 'f') {
if (delset == 0)
printf(" Spurious delim off, line %d\n", yylineno) ;
else
delset = 0 ;
ldelset = 0;
}
else {
ldel = yytext[yyleng-2];
rdel = yytext[yyleng-1];
delset = 1;
ldelset = 0;
}
}
if(eq==0) REJECT;
}
^{C}D(S|F) {if(ds) {
printf(" .DS at line %d within .DS\n",yylineno) ; }
if(as && ! ae) {
printf(" .DS at line %d within .AS\n",yylineno) ; }
if(fs) {
printf(" .DS at line %d within .FS\n",yylineno) ; }
ds = 1 ;
}
^{C}FS {if(fs) {
printf(" .FS at line %d within .FS\n",yylineno) ; }
if(ds) {
printf(" .FS at line %d within .DS\n",yylineno) ; }
fs = 1 ;
if(as && !ae)
printf(" .FS at line %d within .AS\n",yylineno) ;
}
^{C}DE {if(ds == 0) {
printf(" Extra .DE at line %d\n",yylineno) ; }
if(fs) {
printf(" .DE at line %d within .FS\n",yylineno) ; }
if(as && !ae)
printf(" .DE at line %d within .AS\n",yylineno) ;
ds = 0 ;
}
^{C}FE {if(fs == 0) {
printf(" Extra .FE at line %d\n",yylineno) ; }
if(as && !ae)
printf(" .FE at line %d within .AS\n",yylineno) ;
if(ds) {
printf(" .FE at line %d within .DS\n",yylineno) ; }
fs = 0 ;
}
^{C}LI {if(il == -1)
printf(" Missing list begin before .LI at line %d\n",yylineno) ;
}
^{C}(AL|LB|DL|BL|RL|ML|VL).*$ {
il++ ;
if(il > 5 )
printf(" Lists nested %d deep at line %d\n",il+1,yylineno) ;
max = (yyleng < 20 ? yyleng : 19 ) ;
for( jl = 0 ; jl < max ; jl++ )
listm[il][jl] = yytext[jl] ;
listm[il][jl] = '\0' ;
}
^{C}SG { if(fs)
printf(" .SG at line %d within .FS\n",yylineno) ;
if(ds)
printf(" .SG at line %d within .DS\n",yylineno) ;
if(!au )
printf(" Missing .AU before .SG at line %d\n",yylineno) ;
}
^{C}LE { if(--il < -1 ) {
printf(" Extra .LE at line %d\n",yylineno) ;
il = -1 ;
}
}
^{C}LC{SP}+[0-5][ \t]*$ {
for( i = 4 ; yytext[i] < '0' || yytext[i] > '6' ; i++) ;
i = yytext[i] - '0' ;
if(i>il)
printf(" .LC %d at line %d with %d lists active\n",i, yylineno, il + 1) ;
else
il = i - 1 ;
}
^{C}LC.*$ {
printf(" .LC syntax error at line %d\n",yylineno) ; }
^{C}NS {ns = 1 ; }
^{C}NE {if(ns == 0) {
printf(" Missing .NS before .NE at line %d\n",yylineno) ; }
ns = 0 ;
}
^{C}H {if(ts) {
printf(" Missing .TE before .H at line %d\n",yylineno) ; }
if(tsh) {
printf(" Missing .TH before .H at line %d\n",yylineno) ; }
if(ds) {
printf(" Missing .DE before .H at line %d\n",yylineno) ; }
if(fs) {
printf(" Missing .FE before .H at line %d\n",yylineno) ; }
if(ns) {
printf(" Missing .NE before .H at line %d\n",yylineno) ; }
if(eq) {
printf(" Missing .EN before .H at line %d\n",yylineno) ; }
if(as && !ae ) {
printf(" Missing .AE before .H at line %d\n",yylineno) ; }
while ( il > -1 ) {
printf(" Missing .LE for \'%s\' before .H at line %d\n",
listm[il--],yylineno) ; }
ds = ns = fs = ts = eq = tsh = as = 0 ;
il = -1 ;
}
^{C}TS {if(ts) {
printf(" .TS at line %d within .TS\n",yylineno) ; }
ts = 1 ;
}
^{C}TS{SP}+H {if(ts) {
printf(" .TS at line %d within .TS\n",yylineno) ; }
if(ds )
printf(" .TS H at line %d within .DS\n",yylineno) ;
tsh = 1 ;
ts = 1 ;
}
^{C}TE {if(ts == 0) {
printf(" Extra .TE at line %d\n",yylineno) ; }
if(tsh) {
printf(" Missing .TH before .TE at line %d\n",yylineno) ; }
ts = tsh = 0 ;
}
^{C}T& {if(ts == 0) {
printf(" Missing .TS before .T& at line %d\n",yylineno) ; }
}
^{C}TH {if(tsh == 0) {
printf(" Missing .TS H before .TH at line %d\n",yylineno) ; }
tsh = 0 ;
}
^{C}BS {if(bs)
printf(" .BS at line %d within .BS\n",yylineno) ;
if(ds)
printf(" .BS at line %d within .DS\n",yylineno) ;
if(as && !ae)
printf(" .BS at line %d within .AS\n",yylineno) ;
if(fs)
printf(" .BS at line %d within .FS\n",yylineno) ;
bs = 1 ;
}
^{C}BE {if(!bs)
printf(" Missing .BS before .BE at line %d\n",yylineno) ;
if(ds || fs )
printf(" .BE at line %d within .DS or .FS\n",yylineno) ;
if(as && !ae)
printf(" .BE at line %d within .AS\n",yylineno) ;
bs = 0 ;
}
. {if(delset){
if(ldelset){
if (yytext[0] == rdel) {
if (notwarned == 0)
printf(" right delimiter %c, alone on line %d\n", rdel, yylineno);
ldelset = 0;
}
}
else {
if (yytext[0] == ldel){
if (eq) printf(" left delimiter %c, in EQ, line %d\n", ldel, yylineno) ;
else { ldelset = 1; notwarned = 1; }
}
}
}
}
\n {if (ldelset && notwarned)
printf(" left delimiter %c, alone on line %d\n", ldel, yylineno-1);
notwarned = 0;
}
%% /* lex rules end */
yywrap(){
if(pla != 9 && pla > 0)
printf(" Missing .MT ! !\n") ;
if(ds) {
printf(" Unfinished .DS\n") ; }
if(bs)
printf(" Unfinished .BS\n") ;
if (eq) {
printf(" Unfinished EQ\n") ; }
if (ldelset) {
printf(" Missing right delimiter %c\n", rdel); }
if(fs) {
printf(" Unfinished .FS\n") ; }
if(ts) {
printf(" Unfinished .TS\n") ; }
if(ns) {
printf(" Unfinished .NS\n") ; }
if(as && !ae ) {
printf(" Unfinished .AS\n") ; }
if(tsh ) {
printf(" Unfinished .TS H\n" ) ; }
while ( il > -1 ) {
printf(" Unfinished \'%s\'\n", listm[il--]) ; }
printf(" %d lines done.\n\n",yylineno- 1) ;
return(1) ;
}