Compare commits

...

10 Commits

Author SHA1 Message Date
Nate Choe
4b23432cf4 Remove github workflow 2024-03-30 04:04:54 -05:00
Nate Choe
0db57614cd Better file checking 2024-02-18 00:27:34 -06:00
Nate Choe
561ad55a60 Fix a nesting bug
Before, strings such as @n@!_filename@@m wouldn't be parsed correctly
because of that '@@' in there.
2024-02-17 23:56:28 -06:00
Nate Choe
ba55ebd057 Remove optimizations, enable debugging symbols 2024-02-11 22:08:11 -06:00
Nate Choe
4f512c6503 Fix off-by-one errors 2024-02-11 19:07:10 -06:00
Nate Choe
817271a1bb Remove debug lines 2024-02-11 18:58:27 -06:00
Nate Choe
fd07dfd962 Got nesting to work 2024-02-11 18:57:54 -06:00
Nate Choe
254a644f41 Buggy skeleton 2024-02-11 18:47:38 -06:00
Nate Choe
bd8ae9c180 Nest detection and convert everything to ncdgfile 2024-02-11 18:14:02 -06:00
Nate Choe
72c117b388 Custom file struct 2024-02-11 18:02:22 -06:00
7 changed files with 249 additions and 56 deletions

View File

@@ -1,28 +0,0 @@
name: Docker Hub
on:
push:
branches: [ master ]
pull_request:
branches: [ master ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Set login
uses: azure/docker-login@v1
with:
username: ${{ secrets.REGISTRY_USERNAME }}
password: ${{ secrets.REGISTRY_PASSWORD }}
- name: Build image
working-directory: ${{github.workspace}}
run: ./build.sh
- name: Push image
run: docker push natechoe/ncdg

View File

@@ -1,7 +1,7 @@
SRC = $(wildcard src/*.c)
OBJ = $(subst .c,.o,$(subst src,work,$(SRC)))
LDFLAGS =
CFLAGS := -O2 -pipe -Wall -Wpedantic -Wshadow -ansi
CFLAGS := -pipe -Wall -Wpedantic -Wshadow -ansi -ggdb
CFLAGS += -Isrc/include/
INSTALLDIR := /usr/bin/
OUT = ncdg

View File

@@ -178,9 +178,8 @@ Turns into
!dlrow olleH
```
Things between an `@n` and `@m` tag get processed twice. A double escape char `@@`
gets escaped into a single escape char `@`. Defining variables in a nest is
illegal, so
Things between an `@n` and `@m` tag get processed twice. Defining variables in a
nest is illegal, so
```
@n @@= dynamic_variable @$./generate_variable_value.sh@ @@ @m

View File

@@ -6,6 +6,8 @@
#define NOMINIFY_CHAR '&'
#define SEPARATOR_CHAR ','
#define SHELL_CHAR '$'
#define NEST_START 'n'
#define NEST_END 'm'
#define ALLOW_SHELL

16
src/include/ncdgfile.h Normal file
View File

@@ -0,0 +1,16 @@
#ifndef HAVE_NCDGFILE
#define HAVE_NCDGFILE
#include <stdio.h>
struct ncdgfile {
int (*putc)(struct ncdgfile *file, int c);
int (*puts)(struct ncdgfile *file, char *s);
void (*free)(struct ncdgfile *file);
void *handle;
};
struct ncdgfile *file2ncdg(FILE *file);
struct ncdgfile *stringfile(void);
#endif

74
src/ncdgfile.c Normal file
View File

@@ -0,0 +1,74 @@
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <ncdgfile.h>
static int fileputc(struct ncdgfile *file, int c);
static int fileputs(struct ncdgfile *file, char *s);
static void filefree(struct ncdgfile *file);
static int stringputc(struct ncdgfile *file, int c);
static int stringputs(struct ncdgfile *file, char *s);
static void stringfree(struct ncdgfile *file);
struct ncdgfile *file2ncdg(FILE *file) {
struct ncdgfile *ret;
if ((ret = malloc(sizeof *ret)) == NULL) {
return NULL;
}
ret->putc = fileputc;
ret->puts = fileputs;
ret->free = filefree;
ret->handle = (void *) file;
return ret;
}
struct ncdgfile *stringfile(void) {
struct ncdgfile *ret;
if ((ret = malloc(sizeof *ret)) == NULL) {
goto error1;
}
if ((ret->handle = (void *) newstring()) == NULL) {
goto error2;
}
ret->putc = stringputc;
ret->puts = stringputs;
ret->free = stringfree;
return ret;
error2:
free(ret);
error1:
return NULL;
}
static int fileputc(struct ncdgfile *file, int c) {
return fputc(c, (FILE *) file->handle) == EOF ? -1 : 0;
}
static int fileputs(struct ncdgfile *file, char *s) {
return fputs(s, (FILE *) file->handle) == EOF ? -1 : 0;
}
static void filefree(struct ncdgfile *file) {
free(file);
}
static int stringputc(struct ncdgfile *file, int c) {
return appendchar((struct string *) file->handle, c) ? -1 : 0;
}
static int stringputs(struct ncdgfile *file, char *s) {
long i;
for (i = 0; s[i] != '\0'; ++i) {
if (appendchar((struct string *) file->handle, s[i])) {
return -1;
}
}
return 0;
}
static void stringfree(struct ncdgfile *file) {
freestring((struct string *) file->handle);
free(file);
}

View File

@@ -11,6 +11,7 @@
#include <parse.h>
#include <vector.h>
#include <strings.h>
#include <ncdgfile.h>
struct var {
struct string *var;
@@ -31,38 +32,44 @@ struct minstate {
};
static int expandfile(struct expandfile *ret, char *filename, int level);
static int writefile(struct expandfile *file, FILE *out);
static int writefile(struct expandfile *file, struct ncdgfile *out);
static struct string *getstring(FILE *file, char end);
static void initminstate(struct minstate *state);
static void mputs(struct minstate *state, char *s, FILE *file);
static void mputc(struct minstate *state, char c, FILE *file);
static long putvar(long i, struct minstate *s, FILE *out,
static void mputs(struct minstate *state, char *s, struct ncdgfile *file);
static void mputc(struct minstate *state, char c, struct ncdgfile *file);
static long putvar(long i, struct minstate *s, struct ncdgfile *out,
const struct string *file, const struct vector *vars);
static int defvars(struct expandfile *expanded, char *filename);
static long count_escapes(struct string *string);
int parsefile(char *template, FILE *out) {
struct expandfile expanded;
int ret;
struct ncdgfile *ncdgout;
if ((ncdgout = file2ncdg(out)) == NULL) {
ret = 1;
goto error1;
}
expanded.data = newstring();
if (expanded.data == NULL) {
ret = 1;
goto error1;
goto error2;
}
expanded.vars = newvector(struct var);
if (expanded.vars == NULL) {
ret = 1;
goto error2;
goto error3;
}
if (defvars(&expanded, template)) {
ret = 1;
goto error3;
goto error4;
}
if (expandfile(&expanded, template, 0)) {
ret = 1;
goto error3;
goto error4;
}
ret = writefile(&expanded, out);
error3:
ret = writefile(&expanded, ncdgout);
error4:
{
int i;
for (i = 0; i < expanded.vars->len; ++i) {
@@ -73,15 +80,21 @@ error3:
}
}
freevector(expanded.vars);
error2:
error3:
freestring(expanded.data);
error2:
ncdgout->free(ncdgout);
error1:
return ret;
}
static int writefile(struct expandfile *file, FILE *out) {
static int writefile(struct expandfile *file, struct ncdgfile *out) {
long i;
struct minstate s;
if (count_escapes(file->data) % 2 != 0) {
fputs("File or nest has an odd number of escape chars\n", stderr);
return 1;
}
initminstate(&s);
for (i = 0; i < file->data->len; ++i) {
if (file->data->data[i] == ESCAPE_CHAR) {
@@ -102,16 +115,16 @@ static int writefile(struct expandfile *file, FILE *out) {
for (++i; i < data->len; ++i) {
switch (data->data[i]) {
case '&':
fputs("&amp;", out);
out->puts(out, "&amp;");
break;
case ';':
fputs("&semi;", out);
out->puts(out, "&semi;");
break;
case '<':
fputs("&lt;", out);
out->puts(out, "&lt;");
break;
case '>':
fputs("&gt;", out);
out->puts(out, "&gt;");
break;
case ESCAPE_CHAR:
if (data->data[i + 1] != ESCAPE_CHAR)
@@ -119,7 +132,7 @@ static int writefile(struct expandfile *file, FILE *out) {
++i;
/* fallthrough */
default:
fputc(data->data[i], out);
out->putc(out, data->data[i]);
break;
}
}
@@ -134,7 +147,7 @@ autoescapeend:
break;
++i;
}
fputc(data->data[i], out);
out->putc(out, data->data[i]);
}
break;
#ifdef ALLOW_SHELL
@@ -157,8 +170,81 @@ autoescapeend:
break;
}
#endif
case NEST_START: {
struct ncdgfile *tmp;
struct string *buff;
struct expandfile nest;
int in_escape;
if ((buff = newstring()) == NULL) {
goto bufferror;
}
in_escape = 0;
++i;
/* read nest data into a string */
while (i < data->len) {
int c;
c = data->data[i++];
if (c != ESCAPE_CHAR) {
appendchar(buff, c);
continue;
}
if (in_escape) {
appendchar(buff, c);
in_escape = 0;
continue;
}
if (i >= data->len) {
break;
}
c = data->data[i++];
switch (c) {
case NEST_END:
goto got_nest;
default:
in_escape = 1;
case ESCAPE_CHAR:
appendchar(buff, ESCAPE_CHAR);
appendchar(buff, c);
break;
}
}
fputs("Unexpected EOF in nest\n", stderr);
return 1;
got_nest:
--i;
if ((tmp = stringfile()) == NULL) {
goto bufferror;
}
/* first pass */
nest.data = buff;
nest.vars = file->vars;
if (writefile(&nest, tmp)) {
return 1;
}
freestring(buff);
/* second pass */
nest.data = (struct string *) tmp->handle;
if (writefile(&nest, out)) {
return 1;
}
tmp->free(tmp);
break;
bufferror:
fputs("Failed to create temporary buffer while nesting\n", stderr);
return 1;
}
case NEST_END:
fputs("Error in expansion phase: Unmatched nest end char\n", stderr);
return 1;
default:
fprintf(stderr, "Error in expansion phase: Unknown escape %c%c\n", ESCAPE_CHAR, data->data[i]);
fprintf(stderr, "Error in expansion phase: Unknown escape '%c' (0x%x)\n",
data->data[i], data->data[i]);
return 1;
}
}
@@ -240,6 +326,39 @@ static int expandfile(struct expandfile *ret, char *filename, int level) {
freestring(inclname);
break;
}
case NEST_START: {
int origline = linenum;
appendchar(ret->data, ESCAPE_CHAR);
appendchar(ret->data, NEST_START);
for (;;) {
c = fgetc(file);
if (c == EOF) {
goto no_nest_end;
}
if (c != ESCAPE_CHAR) {
appendchar(ret->data, c);
continue;
}
appendchar(ret->data, c);
c = fgetc(file);
if (c == NEST_END) {
appendchar(ret->data, c);
break;
}
ungetc(c, file);
do {
c = fgetc(file);
appendchar(ret->data, c);
} while (c != ESCAPE_CHAR);
}
break;
no_nest_end:
fprintf(stderr, "Line %d: Unmatched nest start char\n", origline);
goto error;
}
case NEST_END:
fprintf(stderr, "Line %d: Unmatched nest end\n", linenum);
goto error;
default:
fprintf(stderr, "Line %d: Invalid escape %c\n",
linenum, c);
@@ -292,25 +411,25 @@ static void initminstate(struct minstate *state) {
memset(state, 0, sizeof *state);
}
static void mputs(struct minstate *state, char *s, FILE *file) {
static void mputs(struct minstate *state, char *s, struct ncdgfile *file) {
int i;
for (i = 0; s[i] != '\0'; ++i)
mputc(state, s[i], file);
}
static void mputc(struct minstate *state, char c, FILE *file) {
static void mputc(struct minstate *state, char c, struct ncdgfile *file) {
if (isspace(c))
state->isspace = 1;
else {
if (!state->ignore && state->isspace && c != '>')
fputc(' ', file);
fputc(c, file);
file->putc(file, ' ');
file->putc(file, c);
state->ignore = c == '<';
state->isspace = 0;
}
}
static long putvar(long i, struct minstate *s, FILE *out,
static long putvar(long i, struct minstate *s, struct ncdgfile *out,
const struct string *file, const struct vector *vars) {
long start;
for (;;) {
@@ -363,3 +482,14 @@ error2:
error1:
return 1;
}
static long count_escapes(struct string *string) {
long i, ret;
ret = 0;
for (i = 0; i < string->len; ++i) {
if (string->data[i] == ESCAPE_CHAR) {
++ret;
}
}
return ret;
}