preprocessor

simple preprocessor for any type of file
git clone https://noulin.net/git/preprocessor.git
Log | Files | Refs | LICENSE

commit d02fafe3b0ab746fb1772c7aec7ee900cc9bcb31
parent aa0ad7d221d7219585c069373bb2d47e430d87ab
Author: Remy Noulin <loader2x@gmail.com>
Date:   Sun, 20 May 2018 10:26:58 +0200

preprocessor library

package.yml         |  15 +++
pp.txt              |  21 ++++
ppCommentConfig.txt |  19 ++++
pp_inc.txt          |   3 +
preprocessor.c      | 289 ++++++++++++++++++++++++++++++++++++++++++++++++++++
preprocessor.h      |   4 +
preprocessorTest.c  |  18 ++++
7 files changed, 369 insertions(+)

Diffstat:
Apackage.yml | 15+++++++++++++++
App.txt | 21+++++++++++++++++++++
AppCommentConfig.txt | 19+++++++++++++++++++
App_inc.txt | 3+++
Apreprocessor.c | 289++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Apreprocessor.h | 4++++
ApreprocessorTest.c | 18++++++++++++++++++
7 files changed, 369 insertions(+), 0 deletions(-)

diff --git a/package.yml b/package.yml @@ -0,0 +1,15 @@ +--- + name: preprocessor + version: 0.0.2 + description: "simple preprocessor for any type of file" + bin: ./preprocessor.c + repository: + type: git + url: git+https://github.com/RemyNoulin/preprocessor.git + keywords: + - utility + author: Remy + license: MIT + bugs: + url: https://github.com/RemyNoulin/preprocessor/issues + homepage: https://github.com/RemyNoulin/preprocessor#readme diff --git a/pp.txt b/pp.txt @@ -0,0 +1,21 @@ +#:define a +asd +asd +#:end + +#:include 'pp_inc.txt' + +#:a + +#:b=1 +#:c=0 + +#:b +wewef +#:else +no output +#:end + +#:not c +c is 0 +#:end diff --git a/ppCommentConfig.txt b/ppCommentConfig.txt @@ -0,0 +1,19 @@ +/*: generator/pp comment config */ + +Define: +/*:define wefw*/ +wefwef +/*:end */ + +/*:include 'pp_inc.txt' */ + +/*:b=1*/ + +/*:not b */ +b=0 +/*:else*/ +b=1 +/*:end*/ + +Copy: +/*:wefw*/ diff --git a/pp_inc.txt b/pp_inc.txt @@ -0,0 +1,3 @@ +included txt + +line 3 diff --git a/preprocessor.c b/preprocessor.c @@ -0,0 +1,289 @@ + +#include "libsheepyObject.h" + +char *commentConfig = NULL; +char *commentEndConfig = NULL; + +/* ------------------------------------------------------------------------------------- + * set comment config + */ +internal void setCommentConfig(smallArrayt *input_lines) { + forEachSmallArray(input_lines, L) { + castS(l, L); + if (hasG(l, "generator/pp comment config")) { + smallStringt *lt = trimG(dupG(l)); + smallArrayt *la = splitG(lt, ": generator/pp comment config"); + commentConfig = getNDupG(la, rtChar, 0); + commentEndConfig = trimG(getNDupG(la, rtChar, 1)); + } + finishG(l); + } + if (not commentConfig) { + commentConfig = strdup("#"); + } +} + +internal smallArrayt *includePass(smallArrayt *input_lines, char *script_path) { + createAllocateSmallArray(lines); + + char *include = catS(commentConfig, ":include"); + + // Include files + forEachSmallArray(input_lines, L) { + castS(l, L); + smallStringt *l2 = dupG(l); + lowerG(l2); + if (hasG(l2, include) and hasG(l2, "'")) { + smallArrayt *a = splitG(l, "'"); + //putsG(l); + //logVarG(a); + char *file_to_include = catS(script_path, "/", getG(a, rtChar, 1)); + //logVarG(file_to_include); + createAllocateSmallArray(file); + readFileG(file, file_to_include); + appendNSmashG(lines, file); + terminateG(a); + } + else { + pushG(lines, l); + } + terminateG(l2); + finishG(l); + } + free(include); + smashG(input_lines); + return lines; +} + +// Search and replace defines +internal smallArrayt *definePass(smallArrayt *input_lines) { + createAllocateSmallArray(lines); + + char *define = catS(commentConfig, ":define "); + char *end = catS(commentConfig, ":end"); + char *ppMark = catS(commentConfig, ":"); + + // Assign values to defines + createAllocateSmallDict(defines); + char *status = NULL; + char *name = NULL; + forEachSmallArray(input_lines, L) { + castS(l, L); + //logVarG(l); + //logVarG(status); + if (eqG(status, "define code")) { + if (startsWithG(l, end)) { + status = "no define"; + } + else { + smallArrayt *def = getG(defines, rtSmallArrayt, name); + pushNFreeG(def, dupG(l)); + setPG(defines, name, def); + } + } + if (hasG(l, define)) { + smallArrayt *spl = splitG(l, define); + free(name); + name = getNDupG(spl, rtChar, 1); + replaceG(&name, commentEndConfig, "", 1); + terminateG(spl); + createAllocateSmallArray(defineCode); + setNFreeG(defines, name, defineCode); + status = "define code"; + } + finishG(l); + } + free(name); + //logVarG(defines); + + // cg: replace define with value. + char *statusDefine = "no define"; + forEachSmallArray(input_lines, L) { + castS(l, L); + //logVarG(l); + //logVarG(status); + //logVarG(statusDefine); + if (not startsWithG(l, ppMark)) { + pushG(lines, l); + } + else { + if (eqG(l, ppMark)) { + pushG(lines, l); + finishG(l); + continue; + } + status = "keep line"; + char *def = strdup(ssGet(l) + lenG(commentConfig) + 1); + replaceG(&def, commentEndConfig, "", 1); + trimG(&def); + if (hasG(defines, def)) { + status = "remove line"; + } + if (not hasG(l, define) and ((not startsWithG(l, end)) or (startsWithG(l, end) and (eqG(statusDefine, "no define")))) and eqG(status, "keep line")) { + pushG(lines, l); + } + if (hasG(defines, def)) { + status = "remove line"; + smallArrayt *defCode = getNDupG(defines, rtSmallArrayt, def); + //logVarG(def); + //logVarG(defCode); + appendNSmashG(lines, defCode); + } + if (startsWithG(l, end) and eqG(statusDefine, "define code")) { + statusDefine = "no define"; + } + if (startsWithG(l, define)) { + statusDefine = "define code"; + } + } + finishG(l); + } + smashG(input_lines); + terminateG(defines); + freeManyS(define, end, ppMark); + //logG(lines); + return lines; +} + +// Search tags +// Process tags +internal smallArrayt *tagPass(smallArrayt *input_lines) { + createAllocateSmallArray(lines); + + char *ppMark = catS(commentConfig, ":"); + + // Assign values to tags + createAllocateSmallDict(tags); + forEachSmallArray(input_lines, L) { + castS(l, L); + if (startsWithG(l, ppMark) and hasG(l, "=")) { + smallStringt *l2 = dupG(l); + replaceG(l2, commentEndConfig, "", 0); + delG(l2, 0, lenG(commentConfig)+1); + smallArrayt *spl = splitG(l2, "="); + terminateG(l2); + enumerateSmallArray(spl, T, i) { + castS(t, T); + setPG(spl, i, trimG(t)); + finishG(t); + } + char *s = getG(spl, rtChar, 1); + setG(tags, getG(spl, rtChar, 0), s); + terminateG(spl); + } + finishG(l); + } + //logVarG(tags); + + // cg: include or remove lines depending on tag value. + char *status = "no tag"; + char *yes, *no, *changeStatus; + // support for inner tags in else closes + createAllocateSmallArray(innerTags); + forEachSmallArray(input_lines, L) { + castS(l, L); + //logVarG(status); + //logVarG(innerTags); + //logVarG(l); + //put; + if (startsWithG(l, ppMark) and (not hasG(l, "="))) { + smallStringt *tag = dupG(l); + delG(tag, 0, lenG(commentConfig)+1); + replaceG(tag, commentEndConfig, "", 1); + trimG(tag); + if (eqG(tag, "end")) { + delG(innerTags, -1, 0); + status = "no tag"; + } + else if (not hasG(l, "generator/pp comment config")) { + if (eqG(tag, "else")) { + if (eqG(status, "keep lines")) { + status = "remove lines"; + } + else { + if (lenG(innerTags) > 1) { + if (eqG(getG(innerTags, rtChar, 0), "remove lines")) { + status = "keep lines"; + } + } + else { + status = "keep lines"; + } + } + } + else { + if (startsWithG(tag, "not ")) { + delG(tag, 0, 4); + yes = "remove lines"; + no = "keep lines"; + } + else { + yes = "keep lines"; + no = "remove lines"; + } + + if (lenG(innerTags) > 0) { + if (eqG(getG(innerTags, rtChar, 0), "remove lines") and eqG(status, "keep lines")) { + changeStatus = "yes"; + } + else { + changeStatus = "no"; + } + } + else { + changeStatus = "yes"; + } + if (eqG(changeStatus, "yes")) { + if (hasG(tags, ssGet(tag))) { + if (eqG(getG(tags, rtChar, ssGet(tag)), "0")) { + status = no; + } + else { + status = yes; + } + } + else { + // tag doesnt exit, same as tag = 0 + status = no; + } + } + pushG(innerTags, status); + } + } + } + if (not eqG(status, "remove lines") and not startsWithG(l, ppMark)) { + pushG(lines, l); + } + finishG(l); + } + //logVarG(lines); + terminateG(innerTags); + smashG(input_lines); + terminateG(tags); + free(ppMark); + return lines; +} + +smallArrayt *preprocess(char *filename) { + createAllocateSmallArray(lines); + + if (!fileExists(filename)) { + printf("File not found: %s", filename); + } + + char *dir = shDirnameG(filename); + //logVarG(dir); + + readFileG(lines, filename); + + setCommentConfig(lines); + //logVarG(commentConfig); + //logVarG(commentEndConfig); + + lines = includePass(lines, dir); + lines = definePass(lines); + lines = tagPass(lines); + + freeManyS(dir, commentConfig, commentEndConfig); + return lines; +} diff --git a/preprocessor.h b/preprocessor.h @@ -0,0 +1,4 @@ + +#include "libsheepyObject.h" + +smallArrayt *preprocess(char *filename); diff --git a/preprocessorTest.c b/preprocessorTest.c @@ -0,0 +1,18 @@ +#! /usr/bin/env sheepy + +#include "libsheepyObject.h" +#include "preprocessor.h" + +int main(int ARGC, char** ARGV) { + + smallArrayt *a; + puts(BLD WHT "pp.txt" RST); + a = preprocess("pp.txt"); + logG(a); + terminateG(a); + + puts(BLD WHT "ppCommentConfig.txt" RST); + a = preprocess("ppCommentConfig.txt"); + logG(a); + terminateG(a); +}