gecko-dev/ef/Tools/Nad/NADGrammar/NADOutput.c
1999-11-02 06:38:29 +00:00

228 lines
5.3 KiB
C

/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
/*
NADOutput.c
Scott M. Silver
*/
#include <stdio.h>
#include <string.h>
#ifndef WIN32
#include <va_list.h>
#endif
#include <stdarg.h>
#include "NADOutput.h"
#include "NADGrammarTypes.h"
#include <time.h>
#include <assert.h>
extern FILE* yyout;
extern char* gEmitterName;
static void echoYYOut(const char* inFormat, ...);
static void fprintBurgRule(FILE* inFile, Rule* inRule, int inRuleNo);
static void fprintCase(FILE* infile, Rule* inRule, int inRuleNo);
static void fprintCaseBegin(FILE* inFile);
static void fprintCaseEnd(FILE* inFile);
static void fprintDeclaration(FILE* inFile, Rule* inRule, int inRuleNo);
static void fprintRuleHeader(FILE* inFile, Prototype* inPrototype, int inRuleNo, int inDefinition);
extern int gNextRuleNumber; /* next rule number */
void
echoEmitDefinitionHeader(Prototype* inPrototype)
{
fprintRuleHeader(yyout, inPrototype, gNextRuleNumber++, 1);
echoYYOut("\n{");
}
void
echoEmitDefinitionFooter()
{
echoYYOut("}\n");
}
/*
fprintBurgRule
Recreate the actual "BURG" style rule
*/
extern Rule** gRules;
extern Rule** gNextRule;
extern int gFirstRuleNumber;
void fprintRules(FILE* inBurgFile, FILE* inEmitterFile, FILE* inEmitterHeaderFile)
{
Rule** curRule;
int ruleNo;
ruleNo = gFirstRuleNumber;
fprintCaseBegin(inEmitterFile);
curRule = (Rule**)&gRules; /* maybe I just don't understand C */
for (; curRule < gNextRule; curRule++, ruleNo++)
{
fprintBurgRule(inBurgFile, *curRule, ruleNo);
fprintCase(inEmitterFile, *curRule, ruleNo);
fprintDeclaration(inEmitterHeaderFile, *curRule, ruleNo);
}
fprintCaseEnd(inEmitterFile);
}
void
fprintBurgRule(FILE* inFile, Rule* inRule, int inRuleNo)
{
Prototype* prototype = inRule->prototype;
fprintf(inFile, "%s: %s", prototype->returnVal, prototype->primitive);
if (prototype->paramList->param1)
{
fprintf(inFile, "(%s", prototype->paramList->param1->type->name);
if (prototype->paramList->param2)
fprintf(inFile, ", %s)", prototype->paramList->param2->type->name);
else
fprintf(inFile, ")");
}
else
assert(!prototype->paramList->param2); /* must have param1 */
fprintf(inFile, " = %d (%d);\n", inRuleNo, inRule->cost);
}
void
fprintCaseBegin(FILE* inFile)
{
fprintf(inFile, "void %s::\n"
"emitPrimitive(Primitive& inPrimitive, int inRule)\n"
"{\n"
"\tswitch (inRule)\n"
"\t{\n", gEmitterName);
}
void
fprintCaseEnd(FILE* inFile)
{
fprintf(inFile, "\t}\n\n"
"}\n");
}
void
fprintCase(FILE* inFile, Rule* inRule, int inRuleNo)
{
Prototype* prototype = inRule->prototype;
int curInput;
if (inRule->hasCode)
{
if (inRule->prototype->paramList->param1)
curInput = inRule->prototype->paramList->param1->type->start;
else
curInput = 0;
fprintf(inFile, "\t\tcase%4d: ", inRuleNo);
fprintf(inFile, "\t\t\temitRule%d(inPrimitive", inRuleNo);
if (prototype->paramList->param1)
fprintf(inFile, ", inPrimitive.nthInputVariable(%d)", curInput++);
if (prototype->paramList->param2)
fprintf(inFile, ", inPrimitive.nthInputVariable(%d)", curInput++);
fprintf(inFile, "); break;\n");
}
}
void
fprintDeclaration(FILE* inFile, Rule* inRule, int inRuleNo)
{
Prototype* prototype = inRule->prototype;
fprintf(inFile, "\t");
fprintRuleHeader(inFile, prototype, inRuleNo, 0);
fprintf(inFile, ";\n");
}
void
fprintRuleHeader(FILE* inFile, Prototype* inPrototype, int inRuleNo, int inDefinition)
{
int unused = 0;
if (inDefinition)
fprintf(inFile, "void %s::\n", gEmitterName);
else
fprintf(inFile, "void\t");
fprintf(inFile, "emitRule%d(Primitive& thisPrimitive", inRuleNo);
if (inPrototype->paramList->param1)
{
fprintf(inFile, ", ");
if (inPrototype->paramList->param1->name)
fprintf(inFile, "DataNode& %s", inPrototype->paramList->param1->name);
else
fprintf(inFile, "DataNode& /*inUnused%d*/", unused++);
}
if (inPrototype->paramList->param2)
{
fprintf(inFile, ", ");
if (inPrototype->paramList->param2->name)
fprintf(inFile, "DataNode& %s", inPrototype->paramList->param2->name);
else
fprintf(inFile, "DataNode& /*inUnused%d*/", unused++);
}
fprintf(inFile, ")");
}
void
fprintGeneratedHeader(FILE* inFile, const char* inFileName)
{
time_t currentTime;
time(&currentTime);
fprintf(inFile, "// %s\n"
"//\n"
"// Generated File. Do not edit.\n"
"//\n"
"// %s\n", inFileName, ctime(&currentTime));
}
/*
echoYYOut
Print stuff to stdout
*/
static void
echoYYOut(const char* inFormat, ...)
{
va_list ap;
va_start(ap, inFormat);
vfprintf(yyout, inFormat, ap);
}