809 lines · 20.4 KB · C
RawDownload
/* Copyright (c) 2007--2013 by Ian Piumarta * All rights reserved. *  * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the 'Software'), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, provided that the above copyright notice(s) and this * permission notice appear in all copies of the Software.  Acknowledgement * of the use of this Software in supporting documentation would be * appreciated but is not required. *  * THE SOFTWARE IS PROVIDED 'AS IS'.  USE ENTIRELY AT YOUR OWN RISK. *  * Last edited: 2013-12-18 10:09:42 by piumarta on linux32 */ #include <u.h>#include <libc.h>#include <stdio.h> #ifdef WIN32# undef inline# define inline __inline#endif #include "version.h"#include "tree.h" static int yyl(void){  static int prev= 0;  return ++prev;} static void charClassSet  (unsigned char bits[], int c)	{ bits[c >> 3] |=  (1 << (c & 7)); }static void charClassClear(unsigned char bits[], int c)	{ bits[c >> 3] &= ~(1 << (c & 7)); } typedef void (*setter)(unsigned char bits[], int c); static inline int oigit(int c)	{ return ('0' <= c && c <= '7'); }static inline int higit(int c)	{ return ('0' <= c && c <= '9') || ('A' <= c && c <= 'F') || ('a' <= c && c <= 'f'); } static inline int hexval(int c){    if ('0' <= c && c <= '9') return c - '0';    if ('A' <= c && c <= 'F') return 10 - 'A' + c;    if ('a' <= c && c <= 'f') return 10 - 'a' + c;    return 0;} static int cnext(unsigned char **ccp){    unsigned char *cclass= *ccp;    int c= *cclass++;    if (c)    {	if ('\\' == c && *cclass)	{	    switch (c= *cclass++)	    {		case 'a':  c= '\a';   break;	/* bel */		case 'b':  c= '\b';   break;	/* bs */		case 'e':  c= '\033'; break;	/* esc */		case 'f':  c= '\f';   break;	/* ff */		case 'n':  c= '\n';   break;	/* nl */		case 'r':  c= '\r';   break;	/* cr */		case 't':  c= '\t';   break;	/* ht */		case 'v':  c= '\v';   break;	/* vt */		case 'x':		    c= 0;		    if (higit(*cclass)) c= (c << 4) + hexval(*cclass++);		    if (higit(*cclass)) c= (c << 4) + hexval(*cclass++);		    break;		default:		    if (oigit(c))		    {			c -= '0';			if (oigit(*cclass)) c= (c << 3) + *cclass++ - '0';			if (oigit(*cclass)) c= (c << 3) + *cclass++ - '0';		    }		    break;	    }	}	*ccp= cclass;    }    return c;} static char *makeCharClass(unsigned char *cclass){  unsigned char	 bits[32];  setter	 set;  int		 c, prev= -1;  static char	 string[256];  char		*ptr;   if ('^' == *cclass)    {      memset(bits, 255, 32);      set= charClassClear;      ++cclass;    }  else    {      memset(bits, 0, 32);      set= charClassSet;    }   while (*cclass)    {      if ('-' == *cclass && cclass[1] && prev >= 0)	{	  ++cclass;	  for (c= cnext(&cclass);  prev <= c;  ++prev)	    set(bits, prev);	  prev= -1;	}      else	{	  c= cnext(&cclass);	  set(bits, prev= c);	}    }   ptr= string;  for (c= 0;  c < 32;  ++c)    ptr += sprintf(ptr, "\\%03o", bits[c]);   return string;} static void bbegin(void)		{ fprintf(output, "\n  {"); }static void bend(void)		{ fprintf(output, "\n  }"); }static void label(int n)	{ fprintf(output, "\n  l%d:;\t", n); }static void jump(int n)		{ fprintf(output, "  goto l%d;", n); }static void save(int n)		{ fprintf(output, "  int yypos%d= yy->__pos, yythunkpos%d= yy->__thunkpos;", n, n); }static void restore(int n)	{ fprintf(output,     "  yy->__pos= yypos%d; yy->__thunkpos= yythunkpos%d;", n, n); } static void Node_compile_c_ko(Node *node, int ko){  assert(node);  switch (node->type)    {    case Rule:      sysfatal("internal error #1 (%s)", node->rule.name);    case Dot:      fprintf(output, "  if (!yymatchDot(yy)) goto l%d;", ko);      break;     case Name:      fprintf(output, "  if (!yy_%s(yy)) goto l%d;", node->name.rule->rule.name, ko);      if (node->name.variable)	fprintf(output, "  yyDo(yy, yySet, %d, 0);", node->name.variable->variable.offset);      break;     case Character:    case String:      {	int len= strlen(node->string.value);	if (1 == len)	  {	    if ('\'' == node->string.value[0])	      fprintf(output, "  if (!yymatchChar(yy, '\\'')) goto l%d;", ko);	    else	      fprintf(output, "  if (!yymatchChar(yy, '%s')) goto l%d;", node->string.value, ko);	  }	else	  if (2 == len && '\\' == node->string.value[0])	    fprintf(output, "  if (!yymatchChar(yy, '%s')) goto l%d;", node->string.value, ko);	  else	    fprintf(output, "  if (!yymatchString(yy, \"%s\")) goto l%d;", node->string.value, ko);      }      break;     case Class:      fprintf(output, "  if (!yymatchClass(yy, (unsigned char *)\"%s\")) goto l%d;", makeCharClass(node->cclass.value), ko);      break;     case Action:      fprintf(output, "  yyDo(yy, yy%s, yy->__begin, yy->__end);", node->action.name);      break;     case Predicate:      fprintf(output, "  yyText(yy, yy->__begin, yy->__end);  {\n");      fprintf(output, "#define yytext yy->__text\n");      fprintf(output, "#define yyleng yy->__textlen\n");      fprintf(output, "if (!(%s)) goto l%d;\n", node->action.text, ko);      fprintf(output, "#undef yytext\n");      fprintf(output, "#undef yyleng\n");      fprintf(output, "  }");      break;     case Error:      {	int eok= yyl(), eko= yyl();	Node_compile_c_ko(node->error.element, eko);	jump(eok);	label(eko);	fprintf(output, "  yyText(yy, yy->__begin, yy->__end);  {\n");	fprintf(output, "#define yytext yy->__text\n");	fprintf(output, "#define yyleng yy->__textlen\n");	fprintf(output, "  %s;\n", node->error.text);	fprintf(output, "#undef yytext\n");	fprintf(output, "#undef yyleng\n");	fprintf(output, "  }");	jump(ko);	label(eok);      }      break;     case Alternate:      {	int ok= yyl();	bbegin();	save(ok);	for (node= node->alternate.first;  node;  node= node->alternate.next)	  if (node->alternate.next)	    {	      int next= yyl();	      Node_compile_c_ko(node, next);	      jump(ok);	      label(next);	      restore(ok);	    }	  else	    Node_compile_c_ko(node, ko);	bend();	label(ok);      }      break;     case Sequence:      for (node= node->sequence.first;  node;  node= node->sequence.next)	Node_compile_c_ko(node, ko);      break;     case PeekFor:      {	int ok= yyl();	bbegin();	save(ok);	Node_compile_c_ko(node->peekFor.element, ko);	restore(ok);	bend();      }      break;     case PeekNot:      {	int ok= yyl();	bbegin();	save(ok);	Node_compile_c_ko(node->peekFor.element, ok);	jump(ko);	label(ok);	restore(ok);	bend();      }      break;     case Query:      {	int qko= yyl(), qok= yyl();	bbegin();	save(qko);	Node_compile_c_ko(node->query.element, qko);	jump(qok);	label(qko);	restore(qko);	bend();	label(qok);      }      break;     case Star:      {	int again= yyl(), out= yyl();	label(again);	bbegin();	save(out);	Node_compile_c_ko(node->star.element, out);	jump(again);	label(out);	restore(out);	bend();      }      break;     case Plus:      {	int again= yyl(), out= yyl();	Node_compile_c_ko(node->plus.element, ko);	label(again);	bbegin();	save(out);	Node_compile_c_ko(node->plus.element, out);	jump(again);	label(out);	restore(out);	bend();      }      break;     default:      sysfatal("Node_compile_c_ko: illegal node type %d", node->type);    }}  static int countVariables(Node *node){  int count= 0;  while (node)    {      ++count;      node= node->variable.next;    }  return count;} static void defineVariables(Node *node){  int count= 0;  while (node)    {      fprintf(output, "#define %s yy->__val[%d]\n", node->variable.name, --count);      node->variable.offset= count;      node= node->variable.next;    }  fprintf(output, "#define __ yy->__\n");  fprintf(output, "#define yypos yy->__pos\n");  fprintf(output, "#define yythunkpos yy->__thunkpos\n");} static void undefineVariables(Node *node){  fprintf(output, "#undef __\n");  fprintf(output, "#undef yythunkpos\n");  fprintf(output, "#undef yypos\n");  fprintf(output, "#undef yy\n");  while (node)    {      fprintf(output, "#undef %s\n", node->variable.name);      node= node->variable.next;    }}  static void Rule_compile_c2(Node *node){  assert(node);  assert(Rule == node->type);   if (!node->rule.expression)    fprintf(stderr, "rule '%s' used but not defined\n", node->rule.name);  else    {      int ko= yyl(), safe;       if ((!(RuleUsed & node->rule.flags)) && (node != start))	fprintf(stderr, "rule '%s' defined but not used\n", node->rule.name);       safe= ((Query == node->rule.expression->type) || (Star == node->rule.expression->type));       fprintf(output, "\nYY_RULE(int) yy_%s(yycontext *yy)\n{", node->rule.name);      if (!safe) save(0);      if (node->rule.variables)	fprintf(output, "  yyDo(yy, yyPush, %d, 0);", countVariables(node->rule.variables));      fprintf(output, "\n  yyprintf((stderr, \"%%s\\n\", \"%s\"));", node->rule.name);      Node_compile_c_ko(node->rule.expression, ko);      fprintf(output, "\n  yyprintf((stderr, \"  ok   %%s @ %%s\\n\", \"%s\", yy->__buf+yy->__pos));", node->rule.name);      if (node->rule.variables)	fprintf(output, "  yyDo(yy, yyPop, %d, 0);", countVariables(node->rule.variables));      fprintf(output, "\n  return 1;");      if (!safe)	{	  label(ko);	  restore(0);	  fprintf(output, "\n  yyprintf((stderr, \"  fail %%s @ %%s\\n\", \"%s\", yy->__buf+yy->__pos));", node->rule.name);	  fprintf(output, "\n  return 0;");	}      fprintf(output, "\n}");    }   if (node->rule.next)    Rule_compile_c2(node->rule.next);} static char *header= "\"; static char *preamble= "\#ifndef YY_MALLOC\n\#define YY_MALLOC(C, N)		malloc(N)\n\#endif\n\#ifndef YY_REALLOC\n\#define YY_REALLOC(C, P, N)	realloc(P, N)\n\#endif\n\#ifndef YY_FREE\n\#define YY_FREE(C, P)		free(P)\n\#endif\n\#ifndef YY_LOCAL\n\#define YY_LOCAL(T)	static T\n\#endif\n\#ifndef YY_ACTION\n\#define YY_ACTION(T)	static T\n\#endif\n\#ifndef YY_RULE\n\#define YY_RULE(T)	static T\n\#endif\n\#ifndef YY_PARSE\n\#define YY_PARSE(T)	T\n\#endif\n\#ifndef YYPARSE\n\#define YYPARSE		yyparse\n\#endif\n\#ifndef YYPARSEFROM\n\#define YYPARSEFROM	yyparsefrom\n\#endif\n\#ifndef YYRELEASE\n\#define YYRELEASE	yyrelease\n\#endif\n\#ifndef YY_BEGIN\n\#define YY_BEGIN	( yy->__begin= yy->__pos, 1)\n\#endif\n\#ifndef YY_END\n\#define YY_END		( yy->__end= yy->__pos, 1)\n\#endif\n\#ifdef YY_DEBUG\n\# define yyprintf(args)	fprintf args\n\#else\n\# define yyprintf(args)\n\#endif\n\#ifndef YYSTYPE\n\#define YYSTYPE	int\n\#endif\n\#ifndef YY_STACK_SIZE\n\#define YY_STACK_SIZE 128\n\#endif\n\\n\#ifndef YY_BUFFER_SIZE\n\#define YY_BUFFER_SIZE 1024\n\#endif\n\\n\#ifndef YY_PART\n\\n\typedef struct _yycontext yycontext;\n\typedef void (*yyaction)(yycontext *yy, char *yytext, int yyleng);\n\typedef struct _yythunk { int begin, end;  yyaction  action;  struct _yythunk *next; } yythunk;\n\\n\struct _yycontext {\n\  char     *__buf;\n\  int       __buflen;\n\  int       __pos;\n\  int       __limit;\n\  char     *__text;\n\  int       __textlen;\n\  int       __begin;\n\  int       __end;\n\  int       __textmax;\n\  yythunk  *__thunks;\n\  int       __thunkslen;\n\  int       __thunkpos;\n\  YYSTYPE   __;\n\  YYSTYPE  *__val;\n\  YYSTYPE  *__vals;\n\  int       __valslen;\n\#ifdef YY_CTX_MEMBERS\n\  YY_CTX_MEMBERS\n\#endif\n\};\n\\n\#ifdef YY_CTX_LOCAL\n\#define YY_CTX_PARAM_	yycontext *yyctx,\n\#define YY_CTX_PARAM	yycontext *yyctx\n\#define YY_CTX_ARG_	yyctx,\n\#define YY_CTX_ARG	yyctx\n\#ifndef YY_INPUT\n\#define YY_INPUT(yy, buf, result, max_size)		\\\n\  {							\\\n\    int yyc= getchar();					\\\n\    result= (EOF == yyc) ? 0 : (*(buf)= yyc, 1);	\\\n\    yyprintf((stderr, \"<%c>\", yyc));			\\\n\  }\n\#endif\n\#else\n\#define YY_CTX_PARAM_\n\#define YY_CTX_PARAM	void\n\#define YY_CTX_ARG_\n\#define YY_CTX_ARG\n\yycontext _yyctx= { 0, 0 };\n\yycontext *yyctx= &_yyctx;\n\#ifndef YY_INPUT\n\#define YY_INPUT(buf, result, max_size)			\\\n\  {							\\\n\    int yyc= getchar();					\\\n\    result= (EOF == yyc) ? 0 : (*(buf)= yyc, 1);	\\\n\    yyprintf((stderr, \"<%c>\", yyc));			\\\n\

Lines 1–500 of 809.