1
0
Files
2022-09-29 17:59:04 +03:00

505 lines
11 KiB
Plaintext

%{
/*
* Copyright 1991 Silicon Graphics, Inc. All rights reserved.
*
* Lex specification for PIDL.
*/
#include <bstring.h>
#include <errno.h>
#include <limits.h>
#include <stdarg.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "expr.h"
#include "heap.h"
#include "macros.h"
#include "pidl.h"
#include "scope.h"
#include "treenode.h"
#include "x.tab.h"
extern int yychar; /* imported from the yacc parser */
extern int indecl; /* true if we're in a declarator */
char *yyfilename; /* exported to pidl_tree.c */
int rpclmode; /* exported to main() in pidl.c */
#define LINESIZE 512
#define PUSHSIZE 128
typedef struct inputstack {
char *i_name;
FILE *i_file;
unsigned short i_rpcl;
unsigned short i_lineno;
char i_linebuf[LINESIZE];
int i_count;
char *i_nextcp;
char i_pushbuf[PUSHSIZE];
char *i_pushbp;
struct inputstack *i_down;
} InputStack;
static InputStack *instack;
static int nextline(InputStack *);
#ifdef sun
static int overflow();
#else
static void overflow();
#endif
static void pushback(char *, int);
static int scanimport();
static int scanaddress(char *, Address *);
#undef input
#define input() ((instack->i_pushbp < instack->i_pushbuf+PUSHSIZE) ? \
*instack->i_pushbp++ : ((--instack->i_count >= 0) ? \
*instack->i_nextcp++ : nextline(instack)))
#undef unput
#ifdef sun
#define unput(c) ((instack->i_pushbp > instack->i_pushbuf) ? \
(*--instack->i_pushbp = (c)) : overflow())
#else
#define unput(c) ((instack->i_pushbp > instack->i_pushbuf) ? \
(void)(*--instack->i_pushbp = (c)) : overflow())
#endif
#define RPCL_KEYWORD(t) if (instack->i_rpcl) return t; goto name
%}
%Start Comm1 Comm2 PassThru Token
BEGINCOMM1 "/*"
ENDCOMM1 "*/"
BEGINCOMM2 "//"
ENDCOMM2 \n
BEGINPASS "%{"
ENDPASS "%}"
%%
/*
* Witchcraft.
*/
BEGIN Token;
<Comm1>{BEGINCOMM1} { yyerror("nested comment"); }
<Comm1>{ENDCOMM1} { BEGIN Token; }
<Comm1>\n { }
<Comm1>. { }
<Comm2>{ENDCOMM2} { BEGIN Token; }
<Comm2>. { }
<Token>{BEGINCOMM1} { BEGIN Comm1; }
<Token>{BEGINCOMM2} { BEGIN Comm2; }
<Token>{ENDCOMM1} { yyerror("extra comment terminator"); }
<Token>[ \t\n]+ { }
<Token>^%pragma[ \t].* { addpragma(&yytext[8]); }
<Token>^{BEGINPASS} { if (instack->i_down == 0) {
if (ptfile == 0) {
ptfile = fdopen(mkstemp(ptname),
"w+");
}
if (ptfile == 0) {
yyerror(
"can't create temporary file %s",
ptname);
} else {
fprintf(ptfile,
"\n#line %d \"%s\"\n",
yylineno, yyfilename ?
yyfilename : "");
}
}
BEGIN PassThru;
}
<Token>^{ENDPASS} { yyerror("extra pass-through terminator"); }
<PassThru>^{BEGINPASS} { yyerror("nested pass-through"); }
<PassThru>^{ENDPASS} { BEGIN Token; }
<PassThru>\n { if (instack->i_down == 0)
putc(yytext[0], ptfile); }
<PassThru>.+ { if (instack->i_down == 0)
fputs(yytext, ptfile); }
<Token>bitset { yylval.op = opBitSet; return ENUM; }
<Token>const { return CONST; }
<Token>define { return DEFINE; }
<Token>enum { yylval.op = opEnum; return ENUM; }
<Token>expect { return EXPECT; }
<Token>export { return EXPORT; }
<Token>import { if (scanimport()) return IMPORT; }
<Token>protocol { return PROTOCOL; }
<Token>struct { return STRUCT; }
<Token>typedef { return TYPEDEF; }
<Token>if { return IF; }
<Token>else { return ELSE; }
<Token>switch { return SWITCH; }
<Token>case { return CASE; }
<Token>default { return DEFAULT; }
<Token>footer { return FOOTER; }
<Token>nest { return NEST; }
<Token>sizeof { return SIZEOF; }
<Token>union { RPCL_KEYWORD(UNION); }
<Token>program { RPCL_KEYWORD(PROGRAM); }
<Token>version { RPCL_KEYWORD(VERSION); }
<Token>big-endian { yylval.val = drBigEndian; return DREP; }
<Token>little-endian { yylval.val = drLittleEndian; return DREP; }
<Token>XDR { yylval.val = drXDR; return DREP; }
<Token>ASN\.1 { yylval.val = drASN1; return DREP; }
<Token>-v+ { yylval.val = yyleng - 1; return LEVEL; }
<Token>[A-Za-z_][A-Za-z_0-9]* { hash_t hash;
Symbol *sym;
name:
hash = hashname(yytext, yyleng);
sym = find(innermost, yytext, yyleng, hash);
if (sym == 0) {
yylval.sym =
enter(&strings, yytext, yyleng,
hash, stNil, sfSaveName);
} else {
yylval.sym = sym;
if (sym->s_flags & sfTypeName) {
if (!instack->i_rpcl)
return TYPE;
if (!indecl)
return RPCLTYPE;
}
}
return NAME;
}
<Token>[0-9]+ { yylval.val = strtol(yytext, 0, 0);
return NUMBER; }
<Token>0[Xx][0-9A-Fa-f]+ { yylval.val = strtoul(yytext, 0, 16);
return NUMBER; }
<Token>\"[^\n"]* { if (yytext[yyleng-1] == '\\')
yymore();
else {
int c, len;
Expr *ex;
yytext[yyleng++] = c = input();
if (c == '\n')
yyerror("unterminated string");
if (scanaddress(yytext+1, &yylval.addr))
return ADDRESS;
ex = ex_string(yytext+1, yyleng-2);
len = ex->ex_str.s_len;
yylval.sym =
enter(&strings, yytext+1, len,
hashname(yytext+1, len),
stNil, sfSaveName);
ex_destroy(ex);
return STRING;
}
}
<Token>[{}[\];,=?:] { return yytext[0]; }
<Token>"||" { return OR; }
<Token>"&&" { return AND; }
<Token>"==" { yylval.op = opEQ; return EQOP; }
<Token>"!=" { yylval.op = opNE; return EQOP; }
<Token>[<>] { return yytext[0]; }
<Token>"<=" { yylval.op = opLE; return RELOP; }
<Token>">=" { yylval.op = opGE; return RELOP; }
<Token>[|^&] { return yytext[0]; }
<Token>"<<" { yylval.op = opLsh; return SHOP; }
<Token>">>" { yylval.op = opRsh; return SHOP; }
<Token>[+\-*] { return yytext[0]; }
<Token>"/" { yylval.op = opDiv; return DIVOP; }
<Token>"%" { yylval.op = opMod; return DIVOP; }
<Token>"!" { yylval.op = opNot; return UNOP; }
<Token>"~" { yylval.op = opBitNot; return UNOP; }
<Token>\$ds { yylval.op = opDataStream; return MACHREG; }
<Token>\$ps { yylval.op = opProtoStack; return MACHREG; }
<Token>[.()$] { return yytext[0]; }
<Token>. { yyerror("illegal character"); }
%%
static char *severities[] = { "Warning", "Error", "Internal" };
void
vferror(enum severity sev, char *filename, int lineno, char *format, va_list ap)
{
InputStack *ip;
int dot, col, tab;
char *bp;
fprintf(stderr, "%s: %s: ", exc_progname, severities[sev]);
if (filename)
fprintf(stderr, "%s, ", filename);
if (lineno != 0)
fprintf(stderr, "%d: ", lineno);
vfprintf(stderr, format, ap);
fputs(".\n", stderr);
ip = instack;
if (ip) { /* XXX if (ip == 0) open & read till line */
fputs(ip->i_linebuf, stderr);
if (ip->i_nextcp[ip->i_count-1] != '\n')
putc('\n', stderr);
dot = ip->i_nextcp - (ip->i_pushbuf + PUSHSIZE - ip->i_pushbp)
- yyleng - ip->i_linebuf;
for (bp = ip->i_linebuf, col = 0; --dot >= 0; bp++, col++) {
if (*bp == '\t') {
for (tab = 8 - col % 8; --tab > 0; col++)
putc('.', stderr);
}
putc('.', stderr);
}
fputs("^\n", stderr);
}
if (sev != WARNING && ++status >= 10) {
fprintf(stderr, "%s: sorry, too many errors.\n", exc_progname);
terminate(0);
}
}
void
yyerror(char *format, ...)
{
va_list ap;
if (!strcmp(format, "syntax error")) {
if (yychar == 0)
format = "unexpected end of file";
else if (yychar == '$') {
if (instack->i_down)
format = "unexpected end of imported module";
else
format = "illegal character";
}
}
va_start(ap, format);
vferror(ERROR, yyfilename, yylineno, format, ap);
va_end(ap);
}
void
pushinput(FILE *file, char *name, int namlen)
{
InputStack *ip;
ip = new(InputStack);
ip->i_name = yyfilename = name;
ip->i_file = file;
ip->i_rpcl = (instack == 0) ? rpclmode : !strcmp(name+namlen-3, ".x");
ip->i_lineno = yylineno = 0;
ip->i_count = 0;
ip->i_pushbp = ip->i_pushbuf + PUSHSIZE;
ip->i_down = instack;
instack = ip;
}
typedef struct importdir {
char *id_name;
struct importdir *id_next;
} ImportDir;
static ImportDir *importdirs;
static ImportDir **lastimport = &importdirs;
void
addimportdir(char *name)
{
ImportDir *id;
id = new(ImportDir);
id->id_name = name;
id->id_next = 0;
*lastimport = id;
lastimport = &id->id_next;
}
static FILE *
findimport(char *name, int namlen, char *path, int *pathlen)
{
char newname[_POSIX_PATH_MAX];
int absolute;
FILE *file;
ImportDir *id;
if (strncmp(&name[namlen-3], ".pi", 3)) {
namlen = nsprintf(newname, _POSIX_PATH_MAX, "%s.pi", name);
name = newname;
}
absolute = (name[0] == '/');
if (!absolute) {
*pathlen = nsprintf(path, _POSIX_PATH_MAX, "%s/%s",
dirname(instack->i_name), name);
} else {
(void) strcpy(path, name);
*pathlen = namlen;
}
file = fopen(path, "r");
if (file)
return file;
if (!absolute) {
for (id = importdirs; id; id = id->id_next) {
*pathlen = nsprintf(path, _POSIX_PATH_MAX, "%s/%s",
id->id_name, name);
file = fopen(path, "r");
if (file)
return file;
}
}
return 0;
}
static void
pushback(char *s, int len)
{
InputStack *ip;
ip = instack;
if (ip == 0)
return;
ip->i_pushbp -= len;
if (ip->i_pushbp < ip->i_pushbuf)
overflow();
bcopy(s, ip->i_pushbp, len);
}
static void
endimport()
{
static char import[] = "import ";
if (yylex() == ',')
pushback(import, constrlen(import));
else
pushback(yytext, yyleng);
unput('$'); /* balance { */
unput('}');
}
static int
scanimport()
{
int token, pathlen;
Symbol *sym;
char path[_POSIX_PATH_MAX];
FILE *file;
hash_t hash;
token = yylex();
if (token != NAME && token != STRING) {
yyerror("name expected after import");
return 0;
}
sym = yylval.sym;
file = findimport(sym->s_name, sym->s_namlen, path, &pathlen);
if (file == 0) {
yyerror("can't find import module %s", sym->s_name);
return 0;
}
hash = hashname(path, pathlen);
sym = lookup(&imports, path, pathlen, hash);
if (sym == 0) {
sym = enter(&imports, path, pathlen, hash, stNil, sfSaveName);
pushinput(file, sym->s_name, pathlen);
} else {
fclose(file);
endimport();
}
unput('{'); /* balance } */
yylval.sym = sym;
return 1;
}
static int
yywrap()
{
InputStack *ip;
ip = instack;
fclose(ip->i_file);
instack = ip->i_down;
delete(ip);
if ((ip = instack) == 0)
return 1;
yyfilename = ip->i_name;
yylineno = ip->i_lineno;
endimport();
return 0;
}
static int
scanaddress(char *s, Address *a)
{
int n, v[5];
unsigned long b;
char *p;
unsigned char *vp;
n = 0;
for (;;) {
b = strtoul(s, &p, 16);
if (p == s || b > 255)
return 0;
v[n++] = b;
if (*p == '\0' || *p == '"')
break;
if (*p != ':' || n == sizeof a->a_vec)
return 0;
s = p + 1;
}
vp = &a->a_vec[sizeof a->a_vec];
while (--n >= 0)
*--vp = v[n];
while (vp > &a->a_vec[0])
*--vp = 0;
return 1;
}
static int
nextline(InputStack *ip)
{
char *bp;
int lastc, count, c;
if (ip == 0)
return 0;
bp = ip->i_nextcp = ip->i_linebuf;
lastc = 0;
count = sizeof ip->i_linebuf;
while (--count > 0) {
c = getc(ip->i_file);
if (c == EOF)
break;
if (c == '\n') {
yylineno = ++ip->i_lineno;
if (lastc == '\\') {
--bp, count++;
continue;
}
*bp++ = c;
break;
}
*bp++ = lastc = c;
}
*bp = '\0';
ip->i_count = bp - ip->i_linebuf;
if (ip->i_count == 0)
return 0;
return input();
}
#ifdef sun
static int
#else
static void
#endif
overflow()
{
yyerror("too much input pushback");
terminate(0);
}