/*
This file is part of web2w.
Copyright 2017 Martin Ruckert
web2w is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
web2w is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with web2w. If not, see .
Martin Ruckert, Hochschule Muenchen, Lothstrasse 64, 80336 Muenchen
*/
/*1:*/
#line 501 "web2w.w"
#include
#include
#include
#include
#include
#include
#include
#include "web2w.h"
#include "pascal.tab.h"
/*3:*/
#line 544 "web2w.w"
extern int wwlex(void);
extern FILE*wwin;
extern FILE*wwout;
/*:3*//*11:*/
#line 692 "web2w.w"
#define MAX_TOKEN_MEM 250000
/*:11*//*29:*/
#line 857 "web2w.w"
#define MAX_STRING_MEM 800000
/*:29*//*34:*/
#line 934 "web2w.w"
#define MAX_SYMBOL_TABLE 6007
#define MAX_SYMBOLS 5200
/*:34*//*54:*/
#line 1258 "web2w.w"
#define MAX_MODULE_TABLE 1009
/*:54*//*99:*/
#line 2088 "web2w.w"
static char*token2string(token*t);
/*:99*//*103:*/
#line 2148 "web2w.w"
static token*wprint_to(token*t,token*end);
static token*wskip_to(token*t,token*end);
/*:103*//*111:*/
#line 2257 "web2w.w"
static bool following_directive(token*t);
/*:111*//*118:*/
#line 2395 "web2w.w"
static void wid(token*t);
/*:118*//*158:*/
#line 3131 "web2w.w"
static token*varlist;
/*:158*//*169:*/
#line 3363 "web2w.w"
int generate_constant(token*t,char sign,int value);
/*:169*/
#line 512 "web2w.w"
/*12:*/
#line 696 "web2w.w"
static token token_mem[MAX_TOKEN_MEM]= {{0}};
static int free_tokens= MAX_TOKEN_MEM;
/*:12*//*16:*/
#line 724 "web2w.w"
int sequenceno= 0;
/*:16*//*21:*/
#line 757 "web2w.w"
static token*first_token;
token*last_token;
/*:21*//*30:*/
#line 861 "web2w.w"
static char string_mem[MAX_STRING_MEM];
static int free_strings= MAX_STRING_MEM;
static int current_string= 0;
/*:30*//*35:*/
#line 939 "web2w.w"
symbol*symbol_table[MAX_SYMBOL_TABLE]= {NULL};
static symbol symbols[MAX_SYMBOLS]= {{0}};
static int free_symbols= MAX_SYMBOLS;
/*:35*//*43:*/
#line 1045 "web2w.w"
#define MAX_LOCALS 50
static int locals[MAX_LOCALS];
static symbol*globals[MAX_LOCALS];
static int free_locals= MAX_LOCALS;
/*:43*//*46:*/
#line 1125 "web2w.w"
#define MAX_WWSTACK 200
static token*wwstack[MAX_WWSTACK]= {0};
static int wwsp= 0;
/*:46*//*52:*/
#line 1221 "web2w.w"
static token*first_string= NULL,**last_string= &first_string;
/*:52*//*55:*/
#line 1262 "web2w.w"
static module module_table[MAX_MODULE_TABLE]= {{0}};
static int free_modules= MAX_MODULE_TABLE;
static module*module_root= NULL;
/*:55*//*62:*/
#line 1355 "web2w.w"
token*program;
/*:62*//*71:*/
#line 1491 "web2w.w"
#define MAX_PPSTACK 40
static struct{
token*next,*end,*link;
int environment;
token*parameter;
}pp_stack[MAX_PPSTACK];
static int pp_sp= MAX_PPSTACK;
/*:71*//*97:*/
#line 2053 "web2w.w"
static int alfanum= 0;
static int comma= 0;
static int column= 0;
/*:97*//*114:*/
#line 2346 "web2w.w"
static int float_constant_no;
/*:114*//*134:*/
#line 2725 "web2w.w"
int print_no,print_str_no,overflow_no,print_err_no,
print_nl_no,fatal_error_no,prompt_file_name_no,
help_line_no,empty_string_no,max_reg_help_line_no;
/*:134*//*139:*/
#line 2798 "web2w.w"
int TeXinputs_no,TeXfonts_no,fmt_no,math_spacing_no;
/*:139*//*147:*/
#line 2958 "web2w.w"
static char*hash_str;
/*:147*//*152:*/
#line 3023 "web2w.w"
int exit_no;
/*:152*//*159:*/
#line 3134 "web2w.w"
static token*varlist= NULL;
/*:159*//*196:*/
#line 4035 "web2w.w"
unsigned int param_mask,param_bit;
/*:196*//*204:*/
#line 4236 "web2w.w"
int x_over_n,xn_over_d;
/*:204*//*213:*/
#line 4446 "web2w.w"
#define MAX_NAME 256
static char basename[MAX_NAME];
static FILE*w= NULL;
static FILE*pascal= NULL;
FILE*logfile= NULL;
debugmode debugflags= dbgnone;
/*:213*/
#line 513 "web2w.w"
/*14:*/
#line 705 "web2w.w"
static token*new_token(int tag)
{token*n;
if(free_tokens> 0)n= &token_mem[--free_tokens];
else ERROR("token mem overflow");
n->lineno= wwlineno;
n->sequenceno= sequenceno;
n->tag= tag;
return n;
}
/*:14*//*19:*/
#line 740 "web2w.w"
void seq(token*t,token*s)
{CHECK(t->sequenceno==s->sequenceno,
"tokens in line %d and %d belong to different code sequences",t->lineno,s->lineno);
}
/*:19*//*24:*/
#line 773 "web2w.w"
token*add_token(int tag)
{token*n= new_token(tag);
last_token->next= n;
n->previous= last_token;
last_token= n;
return n;
}
/*:24*//*32:*/
#line 876 "web2w.w"
char*new_string(void)
{current_string= MAX_STRING_MEM-free_strings;
return string_mem+current_string;
}
void add_string(char*str)
{while(free_strings> 0)
{if(*str!=0)
string_mem[MAX_STRING_MEM-free_strings--]= *str++;
else
return;
}
ERROR("String mem overflow");
}
char*end_string(void)
{char*str= string_mem+current_string;
if(free_strings> 0)
string_mem[MAX_STRING_MEM-free_strings--]= 0;
else
ERROR("String mem overflow");
current_string= MAX_STRING_MEM-free_strings;
return str;
}
char*copy_string(char*str)
{new_string();
add_string(str);
return end_string();
}
int string_length(void)
{return(MAX_STRING_MEM-free_strings)-current_string;}
/*:32*//*37:*/
#line 951 "web2w.w"
static int symbol_hash(char*name)
{int hash= 0;
while(*name!=0)
hash= hash+(*(name++)^0x9E);
return hash;
}
static symbol*new_symbol(void)
{CHECK(free_symbols> 0,"Symbol table overflow");
free_symbols--;
return symbols+free_symbols;
}
int get_sym_no(char*name)
{int i,c;
i= symbol_hash(name)%MAX_SYMBOL_TABLE;
if(symbol_table[i]!=NULL)
{if(strcmp(symbol_table[i]->name,name)==0)
return i;
if(i==0)c= 1;else c= MAX_SYMBOL_TABLE-i;
while(true)
{i= i-c;
if(i<0)i= i+MAX_SYMBOL_TABLE;
if(symbol_table[i]==NULL)break;
if(strcmp(symbol_table[i]->name,name)==0)
return i;
}
}
symbol_table[i]= new_symbol();
symbol_table[i]->name= new_string();add_string(name);end_string();
symbol_table[i]->tag= ID;
return i;
}
/*:37*//*44:*/
#line 1053 "web2w.w"
void scope_open(void)
{
CHECK(free_locals==MAX_LOCALS,"Opening a new scope without closing the previous one");
}
void scope_close(void)
{int i;
for(i= free_locals;isym_no;
symbol*l,*g;
l= new_symbol();
g= symbol_table[sym_no];
l->name= g->name;
l->tag= g->tag;
l->eq= g->eq;
symbol_table[sym_no]= l;
CHECK(free_locals> 0,"Overflow of local symbols in line %d",t->lineno);
free_locals--;
locals[free_locals]= sym_no;
globals[free_locals]= g;
t->sym_ptr= l;
}
/*:45*//*48:*/
#line 1143 "web2w.w"
void ww_push(token*left)
{CHECK(wwsp 0,"Mode stack underflow");
left= wwstack[--wwsp];
if(left!=NULL)left->link= right;
DBG(dbglink,"Popping[%d]:",wwsp);if(left!=NULL)DBG(dbglink,THE_TOKEN(left));
return left;
}
int ww_is(int tag)
{return wwsp> 0&&wwstack[wwsp-1]!=NULL&&wwstack[wwsp-1]->tag==tag;
}
/*:48*//*51:*/
#line 1209 "web2w.w"
void wwstring(char*wwtext)
{token*t= add_token(STRING);
t->sym_no= get_sym_no(wwtext);
t->text= SYM(t)->name;
*last_string= t;
last_string= &(t->link);
}
/*:51*//*53:*/
#line 1246 "web2w.w"
static int module_name_cmp(token*n,token*m)
{n= n->next;m= m->next;
if(n->next->tag==ELIPSIS)
return strncmp(n->text,m->text,strlen(n->text));
else
return strcmp(n->text,m->text);
}
/*:53*//*58:*/
#line 1288 "web2w.w"
module*find_module(token*atless)
{module**m= &module_root;
while(*m!=NULL)
{int d= module_name_cmp(atless,(*m)->atless);
if(d==0)
return*m;
else if(d<0)m= &((*m)->left);
else m= &((*m)->right);
}
CHECK(free_modules> 0,"Module table overflow");
*m= module_table+MAX_MODULE_TABLE-free_modules--;
(*m)->atless= atless;
return*m;
}
/*:58*//*59:*/
#line 1310 "web2w.w"
void add_module(token*atless)
{module*m= find_module(atless);
token*atgreater= m->atgreater;
if(atgreater==NULL)
m->atgreater= atless->link;
else
{while(atgreater->link!=NULL)atgreater= atgreater->link;
atgreater->link= atless->link;
}
}
/*:59*//*65:*/
#line 1391 "web2w.w"
void def_macro(token*eq,int tag)
{token*id;
if(eq->previous->tag==PARAM)
{id= eq->previous->previous;
tag= PMACRO;
}
else
{id= eq->previous;
}
CHGTAG(id,tag);
CHGID(id,tag);
SYM(id)->eq= eq;
DBG(dbgexpand,"Defining %s: %s\n",tagname(tag),SYM(id)->name);
}
/*:65*//*70:*/
#line 1475 "web2w.w"
void pperror(const char*message)
{ERROR("Parse error line %d: %s",pplval->lineno,message);}
/*:70*//*72:*/
#line 1530 "web2w.w"
token*pp_push(token*link,token*eq,int environment,token*parameter)
{CHECK(pp_sp> 0,"Pascal lexer stack overflow");
pp_sp--;
pp_stack[pp_sp].link= link;
pp_stack[pp_sp].next= eq->next;
pp_stack[pp_sp].end= eq->link;
pp_stack[pp_sp].environment= environment;
pp_stack[pp_sp].parameter= parameter;
DBG(dbgexpand,"Push pplex[%d]: ",MAX_PPSTACK-pp_sp);DBGTOKS(dbgexpand,eq->next,eq->link);
return pp_stack[pp_sp].next;
}
token*pp_pop(void)
{CHECK(pp_spnext;
link= link->link;
pp_pop();
t= pp_push(link,eq,0,NULL);
}
else
t= pp_pop();
/*:88*/
#line 1569 "web2w.w"
continue;
}
tag= t->tag;
tag_known:
if(tag> FIRST_PASCAL_TOKEN)
{
pp_stack[pp_sp].next= t->next;
goto found;
}
else
{switch(tag)
{/*74:*/
#line 1600 "web2w.w"
case NL:
case INDENT:
if(pascal!=NULL)fprintf(pascal,"%s",token2string(t));
case METACOMMENT:
case ATT:
case ATEX:
case ATQM:
case ATPLUS:
case ATSLASH:
case ATBACKSLASH:
case ATBAR:
case ATHASH:
case ATCOMMA:
case ATINDEX:
case ATINDEXTT:
case ATINDEX9:
case ATAND:
case ATSEMICOLON:
case ATLEFT:
case ATRIGHT:
t= t->next;
continue;
/*:74*//*75:*/
#line 1625 "web2w.w"
case MLEFT:
case PLEFT:
t= t->link->next;
continue;
/*:75*//*76:*/
#line 1634 "web2w.w"
case PEOF:
pp_stack[pp_sp].next= t->next;
goto found;
/*:76*//*77:*/
#line 1646 "web2w.w"
case ATDOLLAR:
case OCTAL:
case HEX:
case CHAR:
pp_stack[pp_sp].next= t->next;
tag= PINTEGER;
goto found;
/*:77*//*78:*/
#line 1662 "web2w.w"
case ID:
{symbol*s= SYM(t);
tag= s->tag;
if(tag==ID)
tag= s->tag= PID;
t->sym_ptr= s;
t->tag= tag;
goto tag_known;
}
/*:78*//*79:*/
#line 1707 "web2w.w"
case WDEBUG:
case WGUBED:
case WINIT:
case WTINI:
case WSTAT:
case WTATS:
t= t->next;
continue;
/*:79*//*83:*/
#line 1794 "web2w.w"
case NMACRO:
t->sym_ptr= SYM(t);
if(t->sym_ptr->eq->next->tag==STRING)
{token*s= t->sym_ptr->eq->next;
s->sym_ptr= SYM(s);
s->sym_ptr->value++;
DBG(dbgstring,"Using numeric macro %s (%d) in line %d\n",
s->sym_ptr->name,s->sym_ptr->value,t->lineno);
}
pp_stack[pp_sp].next= t->next;
goto found;
case STRING:
t->sym_ptr= SYM(t);
t->sym_ptr->value++;
DBG(dbgstring,"Using string %s (%d) in line %d\n",
t->sym_ptr->name,t->sym_ptr->value,t->lineno);
pp_stack[pp_sp].next= t->next;
goto found;
/*:83*//*87:*/
#line 1868 "web2w.w"
case ATLESS:
{token*eq,*atgreater;
atgreater= find_module(t)->atgreater;
CHECK(atgreater!=NULL,"Undefined module @<%s ...@> in line %d",
token2string(t->next),t->lineno);
DBG(dbgexpand,"Expanding module @<%s@> in line %d\n",
token2string(t->next),t->lineno);
eq= atgreater->next;
pp_stack[pp_sp].next= t->link->next;
t= pp_push(atgreater->link,eq,0,NULL);
continue;
}
/*:87*//*89:*/
#line 1900 "web2w.w"
case OMACRO:
{token*eq;
eq= SYM(t)->eq;
pp_stack[pp_sp].next= t->next;
DBG(dbgexpand,"Expanding ordinary macro %s in line %d\n",token2string(t),t->lineno);
t= pp_push(NULL,eq,0,NULL);
continue;
}
/*:89*//*91:*/
#line 1954 "web2w.w"
case PMACRO:
{token*open,*eq;
int popen;
DBG(dbgexpand,"Expanding parameter macro %s in line %d\n",
token2string(t),t->lineno);
eq= SYM(t)->eq;
pp_stack[pp_sp].next= t->next;
popen= pplex();
CHECK(popen==POPEN,"expected ( after macro with parameter");
open= pplval;
pp_stack[pp_sp].next= open->link->next;
/*145:*/
#line 2928 "web2w.w"
{token*p;int count= 1;
if(open->next->tag==HASH)
{DBG(dbgmacro,"Counting %s parameters (#) in line %d\n",SYM(t)->name,t->lineno);}
else
{for(p= open->next;p!=open->link;p= p->next)
if(p->tag==PCOMMA)count++;
else if(p->tag==POPEN)p= p->link;
if(SYM(t)->value==0)SYM(t)->value= count;
else if(SYM(t)->value!=count)SYM(t)->value= 4;
DBG(dbgmacro,"Counting %s parameters %d line %d\n",SYM(t)->name,SYM(t)->value,t->lineno);
}
}
/*:145*/
#line 1966 "web2w.w"
t= pp_push(NULL,eq,pp_sp,open);
continue;
}
/*:91*//*92:*/
#line 1977 "web2w.w"
case HASH:
{token*parameter= pp_stack[pp_sp].parameter;
int environment= pp_stack[pp_sp].environment;
pp_stack[pp_sp].next= t->next;
t= pp_push(NULL,parameter,pp_stack[environment].environment,
pp_stack[environment].parameter);
continue;
}
/*:92*//*154:*/
#line 3036 "web2w.w"
case PRETURN:
t->sym_ptr= SYM(t);
pp_stack[pp_sp].next= t->next;
goto found;
/*:154*//*191:*/
#line 3953 "web2w.w"
case CSEMICOLON:
t= t->next;
continue;
/*:191*/
#line 1581 "web2w.w"
default:
ERROR("Unexpected token in pplex:"THE_TOKEN(t));
}
}
}
found:
DBG(dbgpascal,"pplex: %s->\t",tagname(tag));
DBG(dbgpascal,THE_TOKEN(t));
if(pascal!=NULL)fprintf(pascal,"%s ",token2string(t));
pplval= t;
return tag;
}
/*:73*//*85:*/
#line 1822 "web2w.w"
int getval(token*t)
{int n= 0;
switch(t->tag)
{case ATDOLLAR:n= 0;break;
case PINTEGER:n= strtol(t->text,NULL,10);break;
case NMACRO:
t= SYM(t)->eq;
CHECK(t->tag==EQEQ,"= expected in numeric macro in line %d",t->lineno);
t= t->next;
if(t->tag==PMINUS){t= t->next;n= -getval(t);}
else n= getval(t);
while(true)
{if(t->next->tag==PPLUS)
{t= t->next->next;n= n+getval(t);}
else if(t->next->tag==PMINUS)
{t= t->next->next;n= n-getval(t);}
else break;
}
break;
case OCTAL:n= strtol(t->text+2,NULL,8);break;
case HEX:n= strtol(t->text+2,NULL,16);break;
case CHAR:n= (int)(unsigned char)t->text[1];break;
case PCONSTID:n= SYM(t)->value;break;
default:ERROR("Unable to get value for tag %s in line %d",TAG(t),t->lineno);
}
return n;
}
/*:85*//*96:*/
#line 2024 "web2w.w"
token*join(int tag,token*left,token*right,int value)
{token*n= new_token(tag);
n->previous= left;
n->next= right;
n->value= value;
DBG(dbgjoin,"tree: ");DBGTREE(dbgjoin,n);
return n;
}
/*:96*//*98:*/
#line 2059 "web2w.w"
static void wput(char c)
{fputc(c,w);
alfanum= isalnum(c);
comma= c==',';
if(c=='\n')column= 0;else column++;
}
static void wputs(char*str)
{while(*str!=0)wput(*str++);
}
static void wputi(int i)
{if(alfanum||comma)fputc(' ',w),column++;
column+= fprintf(w,"%d",i);
alfanum= true;
comma= false;
}
static void wprint(char*str)
{if((alfanum||comma)&&isalnum(str[0]))fputc(' ',w);
wputs(str);
}
/*:98*//*100:*/
#line 2092 "web2w.w"
static char*token2string(token*t)
{CHECK(t!=NULL,"Unable to convert NULL token to a string");
switch(t->tag)
{default:
if(t->text!=NULL)
return t->text;
else
return"";
/*40:*/
#line 1008 "web2w.w"
case ID:case PID:case PCONSTID:
case PARRAYFILETYPEID:case PARRAYFILEID:
case PFUNCID:case PPROCID:
case PDEFVARID:case PDEFPARAMID:case PDEFREFID:case PDEFCONSTID:
case PDEFTYPEID:case PDEFTYPESUBID:case PDEFFUNCID:case CREFID:
case NMACRO:case OMACRO:case PMACRO:
return SYM(t)->name;
/*:40*//*190:*/
#line 3948 "web2w.w"
case CSEMICOLON:
return";";
/*:190*/
#line 2101 "web2w.w"
}
}
/*:100*//*102:*/
#line 2131 "web2w.w"
static token*wtoken(token*t)
{static int level= 0;
level++;
DBG(dbgcweb,"wtoken[%d] %s (%s) line %d\n",level,TAG(t),token2string(t),t->lineno);
switch(t->tag)
{/*80:*/
#line 1721 "web2w.w"
case WDEBUG:
if(t->previous->tag==BAR)
wputs(t->text);
else
{if(column!=0)wput('\n');
wputs("#ifdef @!DEBUG\n");
}
t= t->next;break;
case WINIT:
if(t->previous->tag==BAR)
wputs(t->text);
else
{if(column!=0)wput('\n');
wputs("#ifdef @!INIT\n");
}
t= t->next;break;
case WSTAT:
if(t->previous->tag==BAR)
wputs(t->text);
else
{
if(column!=0)wput('\n');
wputs("#ifdef @!STAT\n");
}
t= t->next;break;
case WGUBED:
case WTINI:
case WTATS:
if(t->previous->tag==BAR)
wputs(t->text);
else
{if(column!=0)wput('\n');
wputs("#endif\n");
}
t= t->next;
if(t->tag==ATPLUS||t->tag==ATSLASH)t= t->next;
if(t->tag==NL)t= t->next;
break;
/*:80*//*81:*/
#line 1763 "web2w.w"
case ATPLUS:
t= t->next;
if(!following_directive(t))
wputs("@+");
else
DBG(dbgcweb,"Eliminating @+ in line %d\n",t->lineno);
break;
/*:81*//*105:*/
#line 2172 "web2w.w"
case CIGNORE:case PPROGRAM:case PLABEL:case PCONST:case PVAR:
case PPACKED:case POF:case ATQM:case ATBACKSLASH:
t= t->next;break;
/*:105*//*107:*/
#line 2186 "web2w.w"
case PFORWARD:
if(t->next->tag==PSEMICOLON)wput(';'),t= t->next->next;
else wprint("forward"),t= t->next;
if(t->tag==ATT)t= t->next;
break;
/*:107*//*108:*/
#line 2200 "web2w.w"
case METACOMMENT:
{char*c;
wputs("/*");
for(c= t->text+2;c[0]!='@'||c[1]!='}';c++)wput(*c);
wputs("*/");
t= t->next;
}
break;
case ATLEFT:
if(column!=0)wput('\n');
wputs("#if 0\n");
t= t->next;break;
case ATRIGHT:
if(column!=0)wput('\n');
wputs("#endif\n");
t= t->next;break;
/*:108*//*109:*/
#line 2224 "web2w.w"
case PLEFT:case MLEFT:wputs(" /*");t= t->next;break;
case RIGHT:wputs("*/ ");t= t->next;break;
case PSEMICOLON:wputs(";");t= t->next;break;
case PCOMMA:wputs(",");t= t->next;break;
case PMOD:wput('%');t= t->next;break;
case PDIV:wput('/');t= t->next;break;
case PNIL:wprint("NULL");t= t->next;break;
case POR:wputs("||");t= t->next;break;
case PAND:wputs("&&");t= t->next;break;
case PNOT:wputs("!");t= t->next;break;
case PIF:wprint("if (");t= t->next;break;
case PTHEN:wputs(") ");t= t->next;break;
case PASSIGN:wput('=');t= t->next;break;
case PNOTEQ:wputs("!=");t= t->next;break;
case PEQ:wputs("==");t= t->next;break;
case EQEQ:wput('\t');t= t->next;break;
case OCTAL:wprint("0");wputs(t->text+2);t= t->next;break;
case HEX:wprint("0x");wputs(t->text+2);t= t->next;break;
case PTYPEINT:wprint("int");t= t->next;break;
case PTYPEREAL:wprint("double");t= t->next;break;
case PTYPEBOOL:wprint("bool");t= t->next;break;
case PTYPECHAR:wprint("unsigned char");t= t->next;break;
/*:109*//*110:*/
#line 2252 "web2w.w"
case PBEGIN:wput('{'),t= t->next;
if(!following_directive(t))wputs("@+");
break;
/*:110*//*113:*/
#line 2275 "web2w.w"
case PDOTDOT:wprint("dotdot");t= t->next;break;
/*:113*//*116:*/
#line 2354 "web2w.w"
case PSLASH:
wput('/');
if(t->next->tag!=PMACRO||t->next->sym_no!=float_constant_no)
{wprint("(double)");
DBG(dbgslash,"Inserting (double) after / in line %d\n",t->lineno);
}
t= t->next;break;
/*:116*//*117:*/
#line 2377 "web2w.w"
case ATEX:
t= t->next;
if(t->tag!=ID&&t->tag!=PID&&t->tag!=PFUNCID&&
t->tag!=PDEFVARID&&t->tag!=PDEFPARAMID&&t->tag!=PDEFTYPEID&&
t->tag!=OMACRO&&t->tag!=PMACRO&&t->tag!=NMACRO&&
t->tag!=CINTDEF&&t->tag!=CSTRDEF&&t->tag!=PDIV&&
t->tag!=WDEBUG&&t->tag!=WINIT&&t->tag!=WSTAT)
{wputs("@!");
DBG(dbgbasic,"Tag after @! is %s in line %d\n",tagname(t->tag),t->lineno);
}
break;
/*:117*//*120:*/
#line 2406 "web2w.w"
case ID:
case PID:
case OMACRO:
case PMACRO:
case NMACRO:
wid(t);t= t->next;break;
/*:120*//*122:*/
#line 2450 "web2w.w"
case PCHAR:
{char*str= t->text;
wput(' ');
wput('\''),str++;
if(str[0]=='\'')wputs("\\'");
else if(str[0]=='\\')wputs("\\\\");
else if(str[0]=='@')wputs("@@");
else wput(str[0]);
wput('\'');
wput(' ');
}
t= t->next;
break;
case PSTRING:
{char*str= t->text;
wput('"'),str++;
while(*str!=0)
{if(str[0]=='\''&&str[1]=='\'')wput('\''),str++;
else if(str[0]=='"'&&str[1]=='"')wputs("\\\""),str++;
else if(str[0]=='\\')wputs("\\\\");
else if(str[0]=='\''&&str[1]==0)wput('"');
else if(str[0]=='"'&&str[1]==0)wput('"');
else if(str[0]=='"')wput('\\'),wput('"');
else wput(str[0]);
str++;
}
}
t= t->next;
break;
/*:122*//*123:*/
#line 2487 "web2w.w"
case ATLESS:
wputs("@<");
t= t->next;
CHECK(t->tag==TEXT,"Module name expected instead of %s in line %d",
token2string(t),t->lineno);
{char*str= t->text;
do
if(str[0]=='@'&&str[1]==',')
str= str+2;
else if(column> 80&&isspace(*str))wput('\n'),str++;
else wput(*str++);
while(*str!=0);
}
t= t->next;
if(t->tag==ELIPSIS)wputs("..."),t= t->next;
CHECK(t->tag==ATGREATER,"@> expected instead of %s in line %d",
token2string(t),t->lineno);
wputs("@>");
t= t->next;
if(t->tag==ATSLASH)wputs("@;"),t= t->next;
else if(t->tag==PELSE||
(t->tag==NL))wputs("@;");
break;
/*:123*//*124:*/
#line 2526 "web2w.w"
case CHAR:
{char c= t->text[1];
wput('\'');
if(c=='\''||c=='\\')wput('\\');
wput(c);
wput('\'');
t= t->next;break;
}
case ATDOLLAR:wputs("0");t= t->next;break;
/*:124*//*125:*/
#line 2549 "web2w.w"
case STRING:
{/*126:*/
#line 2564 "web2w.w"
if(t->sym_no==empty_string_no)
wprint("empty_string");
/*:126*//*137:*/
#line 2783 "web2w.w"
else if(t->sym_no==TeXinputs_no)wprint("TEX_area");
else if(t->sym_no==TeXfonts_no)wprint("TEX_font_area");
else if(t->sym_no==fmt_no)wprint("format_extension");
else if(t->sym_no==math_spacing_no)wprint("math_spacing");
/*:137*/
#line 2551 "web2w.w"
else
{wputs("@[@<|");wputs(SYM(t)->name);wputs("|@>@]");}
t= t->next;break;
}
/*:125*//*142:*/
#line 2854 "web2w.w"
case ATD:
{token*eq= t->next->next;
DBG(dbgcweb,"Macro definition in line %d\n",t->lineno);
if(SYM(t->next)->obsolete)
t= wskip_to(t,eq->link);
else
{wputs("@d "),t= t->next;
wprint(SYM(t)->name);
if(t->tag==NMACRO)
/*144:*/
#line 2907 "web2w.w"
{int has_operators;
wput('\t');
has_operators= 0;
for(t= eq->next;t!=eq->link&&t->tag!=MLEFT&&t->tag!=NL;t= t->next)
if(t->tag==PPLUS||t->tag==PMINUS){has_operators= 1;break;}
if(has_operators)wput('(');
for(t= eq->next;t!=eq->link&&t->tag!=MLEFT&&t->tag!=NL;t= wtoken(t))
continue;
if(has_operators)wput(')');
}
/*:144*/
#line 2864 "web2w.w"
else if(t->tag==OMACRO)
/*143:*/
#line 2890 "web2w.w"
{wput('\t');
t= eq->next;
}
/*:143*/
#line 2866 "web2w.w"
else if(t->tag==PMACRO)
/*146:*/
#line 2946 "web2w.w"
{static char*params[4]= {"X","X","X, Y","X, Y, Z"};
char*param;
eq= eq->next;
if(SYM(t)->value> 3)
{param= "...";hash_str= "__VA_ARGS__";}
else
hash_str= param= params[SYM(t)->value];
wput('('),wputs(param),wputs(")\t"),t= eq->next;
}
/*:146*/
#line 2868 "web2w.w"
else
ERROR("Macro name expected in line %d",t->lineno);
}
DBG(dbgcweb,"End Macro definition in line %d\n",t->lineno);
break;
}
case ATF:
{token*eq= t->next->next;
DBG(dbgcweb,"Format definition in line %d\n",t->lineno);
if(SYM(t->next)->obsolete)
t= wskip_to(t,eq->link);
else
{wputs("@f "),t= t->next;
wprint(SYM(t)->name);
t= wprint_to(eq->next,eq->link);
}
break;
}
/*:142*//*148:*/
#line 2962 "web2w.w"
case HASH:
wprint(hash_str),t= t->next;break;
/*:148*//*155:*/
#line 3051 "web2w.w"
case CLABEL:
if(t->sym_ptr->value<=0)
{t= t->next;
if(t->tag==PPLUS)
t= t->next->next;
if(t->tag==PCOLON)
{t= t->next;
if(t->tag==CSEMICOLON)
t= t->next;
}
}
else
{wprint(SYM(t)->name);t= t->next;
if(t->tag==PPLUS)
{t= t->next;wputs(t->text);t= t->next;}
}
break;
case CLABELN:
wprint("label");wputs(t->text);t= t->next;
break;
case PEXIT:
wprint("exit(0)");t= t->next;
break;
case PRETURN:
wprint("goto end");t= t->next;
break;
/*:155*//*156:*/
#line 3091 "web2w.w"
case CINTDEF:
wputs("enum {@+"),wid(t),wput('=');
t= wprint_to(t->link->next,t->link->link);
wputs("@+};");
t= t->next;
break;
case CSTRDEF:
wprint("const char *"),wid(t);t= t->next;break;
/*:156*//*160:*/
#line 3138 "web2w.w"
case PDEFVARID:
{token*type= t->link;
varlist= t;
DBG(dbgcweb,"Converting variable list in line %d\n",t->lineno);
while(type->tag==PID)type= type->link;
{int replace= 0;
/*185:*/
#line 3763 "web2w.w"
{token*subrange= NULL;
if(type->tag==CTSUBRANGE)
subrange= type->up;
else if(type->tag==CIGNORE&&type->next->tag==PID&&
type->next->sym_ptr->type!=NULL&&type->next->sym_ptr->type->tag==PDOTDOT)
subrange= type->next->sym_ptr->type;
if(subrange!=NULL)
{token*id= t;
while(id!=type&&!replace)
{if(id->sym_ptr->for_ctrl!=0)
{int lo= subrange->previous->value;
int hi= subrange->next->value;
int bits= FOR_CTRL_BITS(id->sym_ptr->for_ctrl);
int direction= FOR_CTRL_DIRECTION(id->sym_ptr->for_ctrl);
int lineno= FOR_CTRL_LINE(id->sym_ptr->for_ctrl);
replace= FOR_CTRL_REPLACE(id->sym_ptr->for_ctrl);
DBG(dbgfor,"Subrange for marked variable %s in line %d\n",
token2string(id),id->lineno);
DBG(dbgfor,"\tRange %d to %d, limit %d bits, direction %d in line %d\n",
lo,hi,bits,direction,lineno);
if(direction==DOWNTO_LOOP)
{if(lo>=0&&bits==0)replace= true;
else if(lo<0&&INT8_MIN<=lo&&hi<=INT8_MAX&&bits>=7)replace= true;
else if(lo<0&&INT16_MIN<=lo&&hi<=INT16_MAX&&bits>=15)replace= true;
}
else if(direction==TO_LOOP)
{if(lo<0&&INT8_MIN<=lo&&hi<=INT8_MAX&&bits>=7)replace= true;
else if(0<=lo&&hi<=UINT8_MAX&&bits>=8)replace= true;
else if(lo<0&&INT16_MIN<=lo&&hi<=INT16_MAX&&bits>=15)replace= true;
else if(0<=lo&&hi<=UINT16_MAX&&bits>=16)replace= true;
}
}
id= id->link;
}
}
}
/*:185*/
#line 3145 "web2w.w"
if(replace)
{wprint("int");
DBG(dbgfor,"\tReplacing subrange type by int\n");
}
else
wprint_to(type,type->link);
}
DBG(dbgcweb,"Finished variable type in line %d\n",t->lineno);
if(varlist->tag==PDEFVARID)
{wid(varlist);varlist= varlist->next;}
wprint_to(varlist,type);
t= type->link;
DBG(dbgcweb,"Finishing variable list in line %d\n",t->lineno);
break;
}
/*:160*//*161:*/
#line 3175 "web2w.w"
case PDEFTYPEID:
{token*type_name= t;
token*type= type_name->link;
DBG(dbgcweb,"Defining type %s in line %d\n",token2string(t),t->lineno);
wprint("typedef ");
t= wprint_to(type,type->link);
wprint(token2string(type_name));
break;
}
/*:161*//*162:*/
#line 3196 "web2w.w"
case CTSUBRANGE:
{int lo= t->up->previous->value;
int hi= t->up->next->value;
DBG(dbgcweb,"Defining subrange type %d..%d\n",lo,hi);
if(lo<0&&INT8_MIN<=lo&&hi<=INT8_MAX)wprint("int8_t");
else if(0<=lo&&hi<=UINT8_MAX)wprint("uint8_t");
else if(lo<0&&INT16_MIN<=lo&&hi<=INT16_MAX)wprint("int16_t");
else if(0<=lo&&hi<=UINT16_MAX)wprint("uint16_t");
else if(lo<0&&INT32_MIN<=lo&&hi<=INT32_MAX)wprint("int32_t");
else if(0<=lo&&hi<=UINT32_MAX)wprint("uint32_t");
else ERROR("unable to convert subrange type %d..%d in line %d\n",lo,hi,t->lineno);
t= t->link;
break;
}
/*:162*//*164:*/
#line 3223 "web2w.w"
case PRECORD:
{DBG(dbgcweb,"Converting record type in line %d\n",t->lineno);
wprint("struct { ");
t= wprint_to(t->next,t->link);
DBG(dbgcweb,"Finished record type in line %d\n",t->lineno);
wprint("} ");
break;
}
case CUNION:
{DBG(dbgcweb,"Converting union type in line %d\n",t->lineno);
wprint("union { ");
t= wprint_to(t->next,t->link);
wprint("};");
DBG(dbgcweb,"Finished union type in line %d\n",t->lineno);
break;
}
/*:164*//*165:*/
#line 3267 "web2w.w"
case PARRAY:
if(t->up==NULL)
wputs(t->text),t= t->next;
else
{token*from= t->link;
token*index= from->link;
token*to= index->link;
token*element_type= to->link;
token*subrange= t->up;
int lo,hi,zero_based;
if(subrange->tag==PID)subrange= subrange->sym_ptr->type;
lo= subrange->previous->value;
hi= subrange->next->value;
zero_based= (subrange->previous->tag==PINTEGER&&lo==0)||
subrange->previous->tag==PTYPECHAR;
DBG(dbgarray,"Converting array[%d..%d] type in line %d\n",lo,hi,t->lineno);
t= wprint_to(element_type,element_type->link);
while(true)
{CHECK(varlist!=NULL,"Nonempty variable list expected in line %d",
varlist->lineno);
DBG(dbgarray,"Generating array variable %s in line %d\n",
varlist->sym_ptr->name,varlist->lineno);
wid(varlist);
if(!zero_based)wput('0');
wput('[');/*166:*/
#line 3312 "web2w.w"
{int hi,size;
hi= generate_constant(subrange->next,0,0);
size= generate_constant(subrange->previous,'-',hi);
size= size+1;
if(size<0)wput('-'),wputi(-size);
else if(size> 0)
{if(subrange->previous->tag!=PTYPECHAR&&
(subrange->previous->tag!=PINTEGER||subrange->next->tag!=PINTEGER))wput('+');
wputi(size);
}
}
/*:166*/
#line 3294 "web2w.w"
wput(']');
if(!zero_based)
{DBG(dbgarray,"Generating array pointer %s[%s=%d.. ] in line %d\n",
varlist->sym_ptr->name,token2string(from->next),lo,varlist->lineno);
wputs(", *const ");
wid(varlist);
wputs(" = ");
wid(varlist),wput('0');
/*167:*/
#line 3326 "web2w.w"
{int lo= generate_constant(subrange->previous,'-',0);
if(lo<0)wput('-'),wputi(-lo);
else if(lo> 0)wput('+'),wputi(lo);
}
/*:167*/
#line 3302 "web2w.w"
;
}
varlist= varlist->link;
if(varlist->tag==PDEFVARID||varlist->tag==PID)wput(',');else break;
}
DBG(dbgarray,"Finished array type in line %d\n",t->lineno);
}
break;
/*:165*//*170:*/
#line 3377 "web2w.w"
case PFILE:
{DBG(dbgcweb,"Converting file type in line %d\n",t->lineno);
wprint("struct {@+FILE *f;@+");
t= wprint_to(t->next,t->link);
wprint("@,d;@+} ");
DBG(dbgcweb,"Finished file type in line %d\n",t->lineno);
break;
}
/*:170*//*171:*/
#line 3403 "web2w.w"
case PUP:wputs(".d");t= t->next;break;
/*:171*//*172:*/
#line 3420 "web2w.w"
case PWHILE:
wprint("while ");
if(t->link!=NULL){
wput('(');t= wprint_to(t->next,t->link);wputs(") ");
}
t= t->next;break;
/*:172*//*173:*/
#line 3438 "web2w.w"
case PCASE:
if(t->link==NULL)
{wprint(t->text);t= t->next;}
else
{wprint("switch (");
t= wprint_to(t->next,t->link);
wputs(") {");
}
break;
/*:173*//*176:*/
#line 3484 "web2w.w"
case CBREAK:
if(t->previous->tag!=PSEMICOLON&&t->previous->tag!=CSEMICOLON
&&t->previous->tag!=PEND)wputs("@;");
if(!dead_end(t->up,t->lineno))wprint("@+break;");
t= t->next;
break;
/*:176*//*179:*/
#line 3522 "web2w.w"
case POTHERS:
wprint("default:");
t= t->next;
break;
/*:179*//*180:*/
#line 3545 "web2w.w"
case PREPEAT:wprint("@/do@+{");t= t->next;break;
case PUNTIL:
{int sequenceno,lineno;
token*end;
wputs("}@+ while (!(");
sequenceno= t->sequenceno;
lineno= t->lineno;
end= t->next;
while(true)
{if(end->tag==PSEMICOLON||end->tag==CSEMICOLON||end->tag==PELSE)
break;
else if(end->tag==ATSPACE)
{while(true)
{int tag= end->previous->tag;
if(tag> FIRST_PASCAL_TOKEN||tag==OMACRO||tag==NMACRO||tag==CHAR)break;
end= end->previous;
}
break;
}
end= end->next;
}
CHECK(sequenceno==end->sequenceno,"until: end of expression not found in line %d",lineno);
t= wprint_to(t->next,end);
wputs("))");
break;
}
/*:180*//*181:*/
#line 3582 "web2w.w"
case PFOR:
{token*id= t->next;
token*to= t->link;
if(to==NULL){wprint("for");t= t->next;break;}
wprint("for (");
wprint_to(id,to);
wputs("; ");
wid(id);
if(to->tag==PTO)wputs("<=");
else if(to->tag==PDOWNTO)wputs(">=");
else ERROR("to or downto expected in line %d",to->lineno);
wprint_to(to->next,to->link);
wputs("; ");
wid(id);
if(to->tag==PTO)wputs("++");
else wputs("--");
wputs(") ");
t= to->link->next;
break;
}
/*:181*//*186:*/
#line 3818 "web2w.w"
case PEND:wputs("} "),t= t->next;
if(t->tag==PSEMICOLON)t= t->next;
break;
/*:186*//*192:*/
#line 3964 "web2w.w"
case PPROCEDURE:
DBG(dbgcweb,"Converting procedure heading in line %d\n",t->lineno);
wprint("void");
t= wprint_to(t->next,t->link);
if(t->tag!=POPEN)wputs("(void)");
break;
/*:192*//*193:*/
#line 3983 "web2w.w"
case PDEFPARAMID:
case PDEFREFID:
{token*varlist= t,*type= t->link;
DBG(dbgcweb,"Converting parameter list in line %d\n",t->lineno);
while(type->tag==PDEFPARAMID||type->tag==PDEFREFID)type= type->link;
while(true)
{wprint_to(type,type->link);
if(varlist->tag==PDEFREFID)wputs(" *");
wid(varlist);
varlist= varlist->link;
if(varlist!=type)wput(',');
else break;
}
t= type->link;
DBG(dbgcweb,"Finishing parameter list in line %d\n",t->lineno);
break;
}
/*:193*//*194:*/
#line 4006 "web2w.w"
case CREFID:
wputs("(*"),wid(t),wput(')');
t= t->next;
break;
/*:194*//*197:*/
#line 4054 "web2w.w"
case PCALLID:
DBG(dbgcweb,"Converting call in line %d\n",t->lineno);
wid(t);
if(SYM(t)->value==1)wputs("()");
t= t->next;break;
/*:197*//*198:*/
#line 4068 "web2w.w"
case POPEN:
wput('(');
if(t->up==NULL||SYM(t->up)->value==0)
t= wprint_to(t->next,t->link);
else
{int param_mask= SYM(t->up)->value;
token*close= t->link;
t= t->next;
if(param_mask<0)wput('&');
param_mask= param_mask<<1;
while(t!=close)
{if(t->tag==PCOMMA)
{wputs(", ");t= t->next;
if(param_mask<0)wput('&');
param_mask= param_mask<<1;
}
else
t= wtoken(t);
}
}
break;
/*:198*//*199:*/
#line 4102 "web2w.w"
case PFUNCTION:
{token*param= t->link;
token*type;
DBG(dbgcweb,"Converting function heading in line %d\n",t->lineno);
if(param->tag==POPEN)type= param->link->link;
else type= param;
wprint_to(type,type->link);
wprint_to(t->next,t->link);
if(param->tag!=POPEN)wputs("(void)");
else wprint_to(param,param->link->next);
t= type->link;
break;
}
/*:199*//*206:*/
#line 4251 "web2w.w"
case PFBEGIN:
DBG(dbgcweb,"Adding scaled %s; in line %d\n",SYM(t)->name,t->lineno);
wprint("scaled");wid(t);wputs("; ");
t= t->next;
break;
case PFEND:
DBG(dbgcweb,"Adding return %s; in line %d\n",SYM(t)->name,t->lineno);
wprint("return");wid(t);wputs(";}");
t= t->next;
break;
/*:206*//*207:*/
#line 4265 "web2w.w"
case PFUNCID:
DBG(dbgcweb,"function %s in line %d assigns result variable\n",SYM(t)->name,t->lineno);
wid(t);
t= t->next;
break;
case CRETURN:
DBG(dbgcweb,"Converted function return %s in line %d\n",SYM(t)->name,t->lineno);
wprint("return");
t= t->next;
break;
case CPROCRETURN:
if(t->sym_ptr->value<=0)wprint("return");
else wprint("goto end");
t= t->next;
break;
/*:207*//*208:*/
#line 4291 "web2w.w"
case CMAIN:wprint("int main(void) {");t= t->next;break;
case CMAINEND:wprint("return 0; }");t= t->next;break;
/*:208*/
#line 2137 "web2w.w"
default:wprint(token2string(t));t= t->next;break;
}
level--;
return t;
}
/*:102*//*104:*/
#line 2153 "web2w.w"
static token*wprint_to(token*t,token*end)
{while(t!=end)
t= wtoken(t);
return t;
}
static token*wskip_to(token*t,token*end)
{while(t!=end)
t= t->next;
return t;
}
/*:104*//*112:*/
#line 2260 "web2w.w"
static bool following_directive(token*t)
{while(true)
if(WDEBUG<=t->tag&&t->tag<=WGUBED)return true;
else if(t->tag==ATPLUS||t->tag==ATEX||t->tag==ATSEMICOLON||
t->tag==NL||t->tag==INDENT)t= t->next;
else return false;
}
/*:112*//*119:*/
#line 2398 "web2w.w"
void wid(token*t)
{if(alfanum||comma)wput(' ');
if(t->previous->tag==ATEX)wputs("@!");
wputs(SYM(t)->name);
}
/*:119*//*132:*/
#line 2673 "web2w.w"
static int convert_arg(token*arg)
{if(arg->tag==STRING)
{symbol*s= symbol_table[arg->sym_no];
s->value--;
DBG(dbgstring,"Eliminating string argument %s (%d) in line %d\n",s->name,s->value,arg->lineno);
arg->tag= PSTRING;
return 1;
}
else if(arg->tag==CHAR)
{arg->tag= PSTRING;
return 1;
}
return 0;
}
void pstring_args(token*id,token*arg)
{if(arg->tag==PCOLON||arg->tag==CREFID)return;
if(id->sym_no==overflow_no||id->sym_no==prompt_file_name_no)
{CHECK(arg->tag==PCOMMA,"function should have two arguments in line %d",id->lineno);
convert_arg(arg->previous);
}
else if(id->sym_no==print_no)
{if(convert_arg(arg))id->sym_no= print_str_no;
}
else if(id->sym_no==print_str_no
||id->sym_no==print_nl_no
||id->sym_no==fatal_error_no
)
convert_arg(arg);
}
/*:132*//*133:*/
#line 2709 "web2w.w"
void pstring_assign(token*id,token*val)
{if(id->tag==PID&&(id->sym_no==help_line_no||id->sym_no==max_reg_help_line_no))
{SYM(val)->value--;
DBG(dbgstring,"Eliminating string assignment %s (%d) in line %d\n",
SYM(val)->name,SYM(val)->value,val->lineno);
val->tag= PSTRING;
}
else
DBG(dbgstring,"No string assignment %s (%d) in line %d\n",
SYM(val)->name,SYM(val)->value,val->lineno);
}
/*:133*//*135:*/
#line 2732 "web2w.w"
int predefine(char*name,int tag,int value)
{int sym_no= get_sym_no(name);
symbol*s= symbol_table[sym_no];
s->tag= tag;
s->value= value;
return sym_no;
}
/*:135*//*150:*/
#line 2990 "web2w.w"
void clabel(token*t,int use)
{
if(t->tag==NMACRO)
{SYM(t)->obsolete= true;
SYM(t)->value+= use;
t->tag= CLABEL;
}
else if(t->tag==CLABEL)
SYM(t)->value+= use;
else if(t->tag==PRETURN)
SYM(t)->value+= use;
else
{if(t->tag==PINTEGER)
t->tag= CLABELN;
return;
}
DBG(dbgstring,"Using label %s (%d) in line %d\n",SYM(t)->name,SYM(t)->value,t->lineno);
}
/*:150*//*168:*/
#line 3340 "web2w.w"
int generate_constant(token*t,char sign,int value)
{if(t->tag==PTYPECHAR||t->tag==PINTEGER)
{if(sign=='-')return value-t->value;else return value+t->value;}
else if(t->tag==NMACRO||t->tag==PCONSTID)
{if(sign!=0)wput(sign);wprint(token2string(t->previous));
return value;
}
if(t->tag==PPLUS)
{if(t->previous!=NULL)value= generate_constant(t->previous,sign,value);
if(sign==0)sign= '+';
return generate_constant(t->next,sign,value);
}
if(t->tag==PMINUS)
{if(t->previous!=NULL)value= generate_constant(t->previous,sign,value);
if(sign==0||sign=='+')sign= '-';else sign= '+';
return generate_constant(t->next,sign,value);
}
else
ERROR("Unexpected tag %s while generating a constant expression in line %d",TAG(t),t->lineno);
}
/*:168*//*175:*/
#line 3464 "web2w.w"
token*winsert_after(token*t,int tag,char*text)
{token*n;
DBG(dbgcweb,"Inserting token %s after %s in line %d\n",
tagname(tag),TAG(t),t->lineno);
n= new_token(tag);
n->next= t->next;
n->next->previous= n;
n->previous= t;
t->next= n;
n->sequenceno= t->sequenceno;
n->lineno= t->lineno;
n->text= text;
return n;
}
/*:175*//*178:*/
#line 3504 "web2w.w"
int dead_end(token*t,int lineno)
{DBG(dbgbreak,"Searching for dead end in line %d:\n",lineno);
while(true)
{DBG(dbgbreak,"\t%s\n",TAG(t));
if(t->tag==PGOTO||t->tag==PEXIT||t->tag==CPROCRETURN)return true;
else if(t->tag==PCOLON)t= t->next;
else if(t->tag==PBEGIN)t= t->previous;
else if(t->tag==PSEMICOLON||t->tag==CCASE)
{if(t->next->tag==CEMPTY)t= t->previous;else t= t->next;}
else return false;
}
}
/*:178*//*183:*/
#line 3658 "web2w.w"
void mark_for_variable(token*id,int lineno,int value,int direction)
{int replace= 0;
int bits= 0;
if(direction==VAR_LOOP)replace= 1;
else if(direction==DOWNTO_LOOP)
{if(value>=0)bits= 0;
else if(value> INT8_MIN)bits= 6;
else if(value> INT16_MIN)bits= 14;
else bits= 15;
}
else
{if(value<0)bits= 0;
else if(valuefor_ctrl= FOR_CTRL_PACK(lineno,replace,direction,bits);
}
/*:183*//*187:*/
#line 3854 "web2w.w"
bool wneeds_semicolon(token*p)
{while(p!=NULL)
{switch(p->tag)
{case PCASE:case PBEGIN:case CIGNORE:return false;
case PSEMICOLON:
case CCASE:case PELSE:p= p->next;continue;
case PIF:case PWHILE:case PFOR:case PCOLON:p= p->previous;continue;
case PASSIGN:case PFUNCID:case PCALLID:case PREPEAT:
case PRETURN:case CRETURN:case CPROCRETURN:case PGOTO:case PEXIT:case CEMPTY:
default:return true;
}
}
return false;
}
static token*wback(token*t)
{while(true)
{CHECK(t->previous!=NULL,"Error searching backward");
t= t->previous;
switch(t->tag)
{case PSEMICOLON:case CSEMICOLON:case PEND:return t;
case RIGHT:while(t->tag!=PLEFT&&t->tag!=MLEFT)t= t->previous;
break;
case ATGREATER:case EQ:case HASH:case ATDOLLAR:case NMACRO:case OMACRO:
case OCTAL:case HEX:case CHAR:case STRING:case PRETURN:case CEMPTY:
return t;
case CIGNORE:continue;
default:break;
}
if(t->tag> FIRST_PASCAL_TOKEN)
return t;
}
}
void wsemicolon(token*p,token*t)
{t= wback(t);
if(t->tag!=PSEMICOLON&&t->tag!=CSEMICOLON&&t->tag!=PEND)
{if(wneeds_semicolon(p))
{DBG(dbgsemicolon,"inserting ; in line %d\n",t->lineno);
if(t->next->tag==ATSEMICOLON)
{t->next->tag= CSEMICOLON;t->next->text= ";";}
else
winsert_after(t,CSEMICOLON,";");
}
else if(t->next->tag!=ATSEMICOLON&&t->next->tag!=PSEMICOLON)
{
DBG(dbgsemicolon,"inserting @; in line %d\n",t->lineno);
winsert_after(t,ATSEMICOLON,"@;");
}
}
}
/*:187*//*188:*/
#line 3917 "web2w.w"
void wend(token*p,token*t)
{if(p->tag==PSEMICOLON&&p->next->tag==PCOLON&&
p->next->next->tag==CEMPTY&&p->next->previous->tag==CLABEL&&
p->next->previous->sym_no==exit_no)
{token*label= p->next->previous;
DBG(dbgreturn,"Trailing exit: found preceding line %d\n",t->lineno);
label->tag= CIGNORE;
SYM(label)->value= -1000;
CHECK(label->next->tag==PCOLON,"Expected colon after label in line %d\n",label->lineno);
label->next->tag= CIGNORE;
p->next->tag= CIGNORE;
}
else
DBG(dbgreturn,"No trailing exit: found preceding line %d\n",t->lineno);
}
/*:188*//*200:*/
#line 4135 "web2w.w"
static bool wtail(token*t)
{CHECK(t!=NULL,"Unexpected NULL token while searching for tail statements");
switch(t->tag)
{case PSEMICOLON:case PELSE:case CCASE:
return wtail(t->next)&&wtail(t->previous);
case PCOLON:
return wtail(t->next);
case PRETURN:case CIGNORE:case CEMPTY:
return true;
case PASSIGN:case PCALLID:
case PFUNCID:case CRETURN:case CPROCRETURN:
case PWHILE:case PREPEAT:case PFOR:
case PEXIT:case PGOTO:
return false;
case PBEGIN:case PIF:case PCASE:
return wtail(t->previous);
default:ERROR("Unexpected tag %s while searching for tail statements",TAG(t));
}
}
/*:200*//*202:*/
#line 4175 "web2w.w"
void wreturn(token*t,int tail,token*link)
{CHECK(t!=NULL,"Unexpected NULL token while searching for return statements");
switch(t->tag)
{case PSEMICOLON:
if(t->next->tag==PRETURN)
wreturn(t->previous,true,t->next);
else
{wreturn(t->next,tail,link);
if(wtail(t->next))wreturn(t->previous,tail,link);
else wreturn(t->previous,false,NULL);
}
return;
case PCOLON:
wreturn(t->next,tail,link);
return;
case PASSIGN:case PCALLID:
case PRETURN:case PEXIT:case PGOTO:case CIGNORE:case CEMPTY:
return;
case PWHILE:case PREPEAT:case PFOR:
wreturn(t->previous,false,NULL);return;
case PELSE:case CCASE:
wreturn(t->next,tail,link);wreturn(t->previous,tail,link);return;
case PCASE:case PIF:case PBEGIN:
wreturn(t->previous,tail,link);return;
case PFUNCID:
if(tail)
{DBG(dbgreturn,"Converting assignment to function in line %d\n",t->lineno);
t->tag= CRETURN;IGN(t->next);
if(link!=NULL)
{link->sym_ptr->value--;
t->sym_ptr= link->sym_ptr;
IGN(link),IGN(link->next);
DBG(dbgreturn,"Eliminating label %s (%d) in line %d\n",
link->sym_ptr->name,link->sym_ptr->value,t->lineno);
}
}
return;
case CRETURN:
if(t->sym_ptr!=NULL){
t->sym_ptr->value--;
DBG(dbgreturn,"Eliminating label %s (%d) in line %d\n",
t->sym_ptr->name,t->sym_ptr->value,t->lineno);
}
return;
default:ERROR("Unexpected tag %s in line %d"
" while searching for return statements",TAG(t),t->lineno);
}
}
/*:202*//*210:*/
#line 4380 "web2w.w"
void usage(void)
{fprintf(stderr,
"Usage: web2w [parameters] filename.web\n"
"Parameters:\n"
"\t -p \t generate a pascal output file\n"
"\t -o file \t specify an output file name\n"
"\t -l \t redirect stderr to a log file\n"
"\t -y \t generate a trace while parsing pascal\n"
"\t -d XX\t hexadecimal debug value. OR together these values:\n"
"\t \t \t XX=1 basic debugging\n"
"\t \t \t XX=2 flex debugging\n"
"\t \t \t XX=4 link debugging\n"
"\t \t \t XX=8 token debugging\n"
"\t \t \t XX=10 identifier debugging\n"
"\t \t \t XX=20 pascal tokens debugging\n"
"\t \t \t XX=40 expansion debugging\n"
"\t \t \t XX=80 bison debugging\n"
"\t \t \t XX=100 pascal parser debugging\n"
"\t \t \t XX=200 cweb debugging\n"
"\t \t \t XX=400 join debugging\n"
"\t \t \t XX=800 string pool debugging\n"
"\t \t \t XX=1000 for variables debugging\n"
"\t \t \t XX=2000 for real division debugging\n"
"\t \t \t XX=4000 for macro debugging\n"
"\t \t \t XX=8000 for array debugging\n"
"\t \t \t XX=10000 for return debugging\n"
"\t \t \t XX=20000 for semicolon debugging\n"
"\t \t \t XX=40000 for break debugging\n"
);
exit(1);
}
/*:210*/
#line 514 "web2w.w"
int main(int argc,char*argv[])
{/*214:*/
#line 4455 "web2w.w"
{int mk_logfile= 0,mk_pascal= 0,baselength= 0;
char*w_file_name= NULL;
ww_flex_debug= 0;
ppdebug= 0;
if(argc<2)usage();
argv++;
while(*argv!=NULL)
{if((*argv)[0]=='-')
{char option= (*argv)[1];
switch(option)
{default:usage();
case'p':mk_pascal= 1;break;
case'o':argv++;w_file_name= *argv;break;
case'l':mk_logfile= 1;break;
case'y':ppdebug= 1;break;
case'd':
argv++;if(*argv==NULL)usage();
debugflags= strtol(*argv,NULL,16);
if(debugflags&dbgflex)ww_flex_debug= 1;
if(debugflags&dbgbison)ppdebug= 1;
break;
}
}
else
{strncpy(basename,*argv,MAX_NAME-1);
baselength= strlen(basename)-4;
if(baselength<1||strncmp(basename+baselength,".web",4)!=0)usage();
basename[baselength]= 0;
if(*(argv+1)!=NULL)usage();
}
argv++;
}
/*215:*/
#line 4501 "web2w.w"
if(mk_logfile)
{basename[baselength]= 0;
strcat(basename,".log");
logfile= freopen(basename,"w",stderr);
if(logfile==NULL)
{fprintf(stderr,"Unable to open logfile %s",basename);
logfile= stderr;
}
wwout= logfile;
}
else
{logfile= stderr;
wwout= stderr;
}
basename[baselength]= 0;
strcat(basename,".web");
wwin= fopen(basename,"r");
if(wwin==NULL)ERROR("Unable to open input file %s",basename);
if(w_file_name==NULL)
{w_file_name= basename;
basename[baselength]= 0;
strcat(basename,".w");
}
w= fopen(w_file_name,"w");
if(w==NULL)ERROR("Unable to open output file %s",w_file_name);
if(mk_pascal)
{basename[baselength]= 0;
strcat(basename,".pas");
pascal= fopen(basename,"w");
if(pascal==NULL)ERROR("Unable to open pascal file %s",basename);
}
/*:215*/
#line 4488 "web2w.w"
}
/*:214*/
#line 517 "web2w.w"
/*5:*/
#line 552 "web2w.w"
/*23:*/
#line 768 "web2w.w"
first_token= last_token= new_token(HEAD);
first_token->text= "";
/*:23*//*63:*/
#line 1358 "web2w.w"
program= first_token;
/*:63*//*115:*/
#line 2350 "web2w.w"
float_constant_no= predefine("float_constant",ID,0);
/*:115*//*136:*/
#line 2742 "web2w.w"
print_str_no= predefine("print_str",PPROCID,0);
empty_string_no= predefine("\"\"",PID,1);
help_line_no= predefine("help_line",ID,0);
print_no= predefine("print",PPROCID,0);
overflow_no= predefine("overflow",PPROCID,0);
print_err_no= predefine("print_err",PPROCID,0);
print_nl_no= predefine("print_nl",PPROCID,0);
fatal_error_no= predefine("fatal_error",PPROCID,0);
prompt_file_name_no= predefine("prompt_file_name",PPROCID,0);
max_reg_help_line_no= predefine("max_reg_help_line",ID,0);
/*:136*//*140:*/
#line 2801 "web2w.w"
TeXinputs_no= predefine("\"TeXinputs:\"",PID,0);
TeXfonts_no= predefine("\"TeXfonts:\"",PID,0);
fmt_no= predefine("\".fmt\"",PID,0);
math_spacing_no= predefine(
"\"0234000122*4000133**3**344*0400400*000000234000111*1111112341011\"",PID,1);
/*:140*//*153:*/
#line 3027 "web2w.w"
exit_no= get_sym_no("exit");
/*:153*//*205:*/
#line 4239 "web2w.w"
x_over_n= get_sym_no("x_over_n");
xn_over_d= get_sym_no("xn_over_d");
/*:205*//*209:*/
#line 4324 "web2w.w"
predefine("put",PPROCID,0);
predefine("get",PPROCID,0);
predefine("reset",PPROCID,0);
predefine("rewrite",PPROCID,0);
predefine("abs",PFUNCID,0);
predefine("odd",PFUNCID,0);
predefine("eof",PFUNCID,0);
predefine("eoln",PFUNCID,0);
predefine("round",PFUNCID,0);
predefine("ord",PFUNCID,0);
predefine("chr",PFUNCID,0);
predefine("close",PPROCID,0);
predefine("read",PPROCID,0);
predefine("read_ln",PPROCID,0);
predefine("write",PPROCID,0);
predefine("write_ln",PPROCID,0);
predefine("break",PPROCID,0);
predefine("break_in",PPROCID,0);
predefine("erstat",PFUNCID,0);
predefine("false",PCONSTID,0);
predefine("true",PCONSTID,1);
/*:209*/
#line 553 "web2w.w"
wwlex();
/*67:*/
#line 1423 "web2w.w"
TOK("",ATP);PROGRAM;PUSH;TOK("",PEOF);TOK("",WEBEOF);POP;
/*:67*//*68:*/
#line 1430 "web2w.w"
if(debugflags&dbgtoken)
{token*t= first_token;
while(t!=NULL){MESSAGE(THE_TOKEN(t));t= t->next;}
}
if(debugflags&dbgid)
{int i;
for(i= free_symbols;iobsolete= 1;
SYM_PTR("gubed")->obsolete= 1;
SYM_PTR("stat")->obsolete= 1;
SYM_PTR("tats")->obsolete= 1;
SYM_PTR("init")->obsolete= 1;
SYM_PTR("tini")->obsolete= 1;
/*:82*//*90:*/
#line 1917 "web2w.w"
SYM_PTR("return")->obsolete= 1;
SYM_PTR("endcases")->obsolete= 1;
SYM_PTR("othercases")->obsolete= 1;
SYM_PTR("mtype")->obsolete= 1;
SYM_PTR("final_end")->obsolete= 1;
/*:90*//*121:*/
#line 2427 "web2w.w"
SYM_PTR("xclause")->name= "else";
SYM_PTR("switch")->name= "get_cur_chr";
SYM_PTR("continue")->name= "resume";
SYM_PTR("exit")->name= "end";
SYM_PTR("free")->name= "is_free";
SYM_PTR("int")->name= "i";
SYM_PTR("remainder")->name= "rem";
/*:121*/
#line 555 "web2w.w"
/*:5*/
#line 518 "web2w.w"
/*93:*/
#line 2000 "web2w.w"
program= first_token->link;
pp_push(program->link,program->next,0,NULL);
ppparse();
/*:93*/
#line 519 "web2w.w"
/*101:*/
#line 2119 "web2w.w"
wprint_to(first_token,last_token);
/*:101*//*127:*/
#line 2573 "web2w.w"
wputs("\n@ Appendix: Replacement of the string pool file.\n");
{token*str_k;
int i,k;
/*128:*/
#line 2588 "web2w.w"
wputs("@d str_0_255 ");
for(k= 0;k<256;k++)
{if((k&0xF)==0)wputs("\t\"");
if((/*129:*/
#line 2625 "web2w.w"
(k<' ')||(k> '~')
/*:129*/
#line 2592 "web2w.w"
))
{wputs("^^");
if(k<0100&&k+0100=='@')wputs("@@");
else if(k<0100&&k+0100=='\\')wputs("\\\\");
else if(k<0100)wput(k+0100);
else if(k<0200&&k-0100=='@')wputs("@@");
else if(k<0200)wput(k-0100);
#define HEXDIGIT(x) ((x)<10?((x)+'0'):((x)-10+'a'))
else wput(HEXDIGIT(k/16)),wput(HEXDIGIT(k%16));
}
else if(k=='"')wputs("\\\"");
else if(k=='\\')wputs("\\\\");
else if(k=='@')wputs("@@");
else wput(k);
if((k&0xF)==0xF)wputs("\"@/\n");
}
wputs("@d str_start_0_255");
i= 0;
for(k= 0;k<256;k++)
{if((k&0xF)==0)wput('\t');
wputi(i);
if((/*129:*/
#line 2625 "web2w.w"
(k<' ')||(k> '~')
/*:129*/
#line 2613 "web2w.w"
))
{if(k<0100)i= i+3;
else if(k<0200)i= i+3;
else i= i+4;
}
else i= i+1;
wput(',');
if((k&0xF)==0xF)wputs("@/\n");
}
/*:128*/
#line 2577 "web2w.w"
for(str_k= first_string;str_k!=NULL;str_k= str_k->link)
/*130:*/
#line 2630 "web2w.w"
{symbol*s= SYM(str_k);
if(s->value> 0)
{s->value= 0;
wputs("@ \n");
wputs("@d str_"),wputi(k),wput(' '),wputs(s->name),wput('\n');
/*138:*/
#line 2790 "web2w.w"
if(str_k->sym_no==empty_string_no)wputs("@d empty_string "),wputi(k);
else if(str_k->sym_no==TeXinputs_no)wputs("@d TEX_area "),wputi(k);
else if(str_k->sym_no==TeXfonts_no)wputs("@d TEX_font_area "),wputi(k);
else if(str_k->sym_no==fmt_no)wputs("@d format_extension "),wputi(k);
else if(str_k->sym_no==math_spacing_no)wputs("@d math_spacing "),wputi(k);
/*:138*/
#line 2636 "web2w.w"
else
wputs("@<|"),wputs(s->name),wputs("|@>=@+"),wputi(k);
wput('\n');
k++;
}
}
/*:130*/
#line 2579 "web2w.w"
/*141:*/
#line 2817 "web2w.w"
wputs("\n@ All the above strings together make up the string pool.\n"
"@<|str_pool| initialization@>=\n"
"str_0_255\n");
for(i= 256;i=\n"
"str_start_0_255\n");
for(i= 256;i=\n"
"typedef enum {\n"
"str_start_256=sizeof(str_0_255)-1,\n");
for(i= 257;i<=k;i++)
wputs("str_start_"),wputi(i),wputs("=str_start_"),wputi(i-1),
wputs("+sizeof(str_"),wputi(i-1),wputs(")-1,@/\n");
wputs("str_start_end } str_starts;\n"
"\n@ @<|pool_ptr| initialization@>= str_start_"),wputi(k),wputs("\n"
"\n@ @<|str_ptr| initialization@>= "),wputi(k),wput('\n');
/*:141*/
#line 2580 "web2w.w"
}
/*:127*/
#line 520 "web2w.w"
/*13:*/
#line 701 "web2w.w"
DBG(dbgbasic,"free tokens = %d\n",free_tokens);
/*:13*//*31:*/
#line 867 "web2w.w"
DBG(dbgbasic,"free strings = %d\n",free_strings);
/*:31*//*36:*/
#line 944 "web2w.w"
DBG(dbgbasic,"free symbols = %d\n",free_symbols);
/*:36*//*57:*/
#line 1279 "web2w.w"
DBG(dbgbasic,"free modules = %d\n",free_modules);
/*:57*/
#line 521 "web2w.w"
return 0;
}
/*:1*/