* Copyright (c) 2020-2021 Huawei Device Co., Ltd.
*
* HDF is dual licensed: you can use it either under the terms of
* the GPL, or the BSD license, at your option.
* See the LICENSE file in the root of this repository for complete details.
*/
#include <string.h>
#include <securec.h>
#include "hcs_file.h"
#include "hcs_compiler.h"
#include "hcs_gener.h"
#include "hcs_ast.h"
#include "hcs_option.h"
const char *g_nodeTypeStringMap[CONFIG_NODE_TYPE_COUNT] = {
[CONFIG_NODE_NOREF] = "NodeReference",
[CONFIG_NODE_COPY] = "NodeCopy",
[CONFIG_NODE_REF] = "NodeReference",
[CONFIG_NODE_DELETE] = "NodeDelete",
[CONFIG_NODE_INHERIT] = "NodeInherit",
[CONFIG_NODE_TEMPLATE] = "NodeTemplate",
};
uint32_t HcsAlign(uint32_t size)
{
if (HcsOptShouldAlign()) {
return (size + ALIGN_SIZE - 1) & (~(ALIGN_SIZE - 1));
} else {
return size;
}
}
const char *HcsParserNodeTypeToStr(uint32_t nodeType)
{
if (nodeType >= CONFIG_NODE_TYPE_COUNT) {
return "";
}
return g_nodeTypeStringMap[nodeType];
}
bool HcsIsNumberObject(const ParserObject *obj)
{
return obj->objectBase.type >= PARSEROP_UINT8 && obj->objectBase.type <= PARSEROP_UINT64;
}
bool HcsIsStringObject(const ParserObject *obj)
{
return obj->objectBase.type == PARSEROP_STRING;
}
bool HcsIsSameTypeObject(const ParserObject *cs, const ParserObject *ct)
{
if (HcsIsNumberObject(cs)) {
return HcsIsNumberObject(ct);
} else if (cs->objectBase.type == PARSEROP_CONFTERM || cs->objectBase.type == PARSEROP_ARRAY) {
return ct->objectBase.type == cs->objectBase.type && cs->objectBase.child->type == ct->objectBase.child->type;
} else {
return ct->objectBase.type == cs->objectBase.type;
}
}
void HcsSetCompilerIn(FILE *in);
static void InitParser(const struct HcsFile *sourceFile)
{
HcsSetCompilerIn(sourceFile->file);
HcsParserRestart(sourceFile->file);
HcsSetCurrentSourceLine(1);
}
void ParserCleanUp()
{
ParserObject *astRoot = HcsGetParserRoot();
HcsDeleteParserObjectTree(astRoot);
HcsSourceNameSetClean();
}
int32_t HcsProcessInclude(char *includePath, uint32_t lineNumber)
{
if (includePath[0] == '/' || !strstr(includePath, HCS_SOURCE_FILE_SUFFIX)) {
HCS_ERROR("File:%s Line:%u\n\tinclude file %s is invalid", HcsGetCurrentSourceName(), lineNumber, includePath);
return EFAIL;
}
struct HcsFile *currentSource = HcsSourceQueueTop();
uint32_t pathSize = strlen(currentSource->fullPath) + strlen(includePath) + 1;
char *path = HcsMemZalloc(pathSize);
if (path == NULL) {
HCS_ERROR("oom");
return EOOM;
}
if (HcsFileCopyDir(path, pathSize, currentSource->fullPath) != true) {
HcsMemFree(path);
return EFAIL;
}
int32_t res = strcat_s(path, pathSize, includePath);
if (res != EOK) {
HcsMemFree(path);
HCS_ERROR("%s:string cat fail", __func__);
return EFAIL;
}
HcsMemFree(includePath);
struct HcsFile *source = NULL;
uint32_t ret = HcsOpenSourceFile(path, &source, NULL);
if (ret == EREOPENF) {
HcsMemFree(path);
return NOERR;
}
if (ret) {
HCS_ERROR("File:%s Line:%u\n\tinclude file %s is invalid", HcsGetCurrentSourceName(), lineNumber, path);
HcsMemFree(path);
return EINVALF;
}
HcsSourceQueuePush(source);
HcsMemFree(path);
return NOERR;
}
int32_t HcsDoCompile(void)
{
struct HcsFile *source = NULL;
char *forestName = strdup("ForestRoot");
if (forestName == NULL) {
return EOOM;
}
ParserObject *astForest = HcsNewParserObject(forestName, PARSEROP_CONFNODE, 0);
if (astForest == NULL) {
HcsMemFree(forestName);
return EFAIL;
}
uint32_t ret = HcsOpenSourceFile(HcsGetInputFileName(), &source, NULL);
if (ret) {
HCS_ERROR("Invalid source file: %s", HcsGetInputFileName());
HcsAstFreeObject(astForest);
return ret;
}
HcsSourceQueuePush(source);
while (HcsSourceQueueSize()) {
source = HcsSourceQueueTop();
HCS_DEBUG("parsing file : %s%s", source->fullPath, source->name);
InitParser(source);
ret = HcsCompilerparse();
ParserObject *currentRoot = HcsGetParserRoot();
HcsSourceQueuePop();
HcsCloseFile(source);
if (ret) {
goto OUT;
}
HcsAstAddChild(astForest, currentRoot);
HcsSetParserRoot(NULL);
}
HcsSetParserRoot(astForest);
if (HcsVerbosePrint()) {
HcsDumpAst("Origin");
}
ret = HcsDoOptimize();
if (ret) {
goto OUT;
}
if (HcsOptShouldGenTextConfig()) {
ret = HcsTextCodeOutput();
} else if (HcsOptShouldGenByteCodeConfig()) {
ret = HcsBytecodeOutput();
}
OUT:
ParserCleanUp();
if (HcsGetParserRoot() != astForest) {
HcsDeleteParserObjectTree(astForest);
}
return ret;
}