Index: trunk/scconfig/Rev.h =================================================================== --- trunk/scconfig/Rev.h (revision 8077) +++ trunk/scconfig/Rev.h (revision 8078) @@ -1 +1 @@ -static const int myrev = 8049; +static const int myrev = 8078; Index: trunk/scconfig/Rev.tab =================================================================== --- trunk/scconfig/Rev.tab (revision 8077) +++ trunk/scconfig/Rev.tab (revision 8078) @@ -1,3 +1,4 @@ +8078 configure std_forge: conditional scripts 8049 configure new plugins for high level sim support 7737 configure new plugins: export_spice, target_spice 7469 configure new plugin for non-graphical fawk sheets Index: trunk/src/plugins/Common_enabled.tmpasm =================================================================== --- trunk/src/plugins/Common_enabled.tmpasm (revision 8077) +++ trunk/src/plugins/Common_enabled.tmpasm (revision 8078) @@ -58,6 +58,63 @@ end end +# explicit rules: .y -> .c (byaccic) +switch /local/rnd/mod/BYACCIC + case {^$} end + default + foreach /local/n in /local/rnd/mod/BYACCIC + put /local/bn /local/n + sub {/local/bn} {^.*/} {} + put /local/dn /local/n + sub {/local/dn} {/[^/]*$} {} + + if /local/csch/want_parsgen_byaccic + then + append /local/rnd/RULES [@ +# byaccic for @/local/rnd/mod@ +@/local/n@.c @/local/n@.h: @/local/n@.y + byaccic -o ../plugins/@/local/rnd/mod@/@/local/bn@.c -H ../plugins/@/local/rnd/mod@/@/local/bn@.h -v ../plugins/@/local/rnd/mod@/@/local/bn@.desc ../plugins/@/local/rnd/mod@/@/local/bn@.y +@] + else + append /local/rnd/RULES [@ +# dummy byaccic for @/local/rnd/mod@ +@/local/n@.c @/local/n@.h: + echo "skipping byaccic..." +@] + end + end + end +end + +# explicit rules: .l -> .c (ureglex) +switch /local/rnd/mod/UREGLEX + case {^$} end + default + foreach /local/n in /local/rnd/mod/UREGLEX + if /local/csch/want_parsgen_byaccic + then + put /local/bn /local/n + sub {/local/bn} {^.*/} {} + put /local/dn /local/n + sub {/local/dn} {/[^/]*$} {} + + append /local/rnd/RULES [@ +# lex for @/local/rnd/mod@ +@/local/n@.c @/local/n@.h: @/local/n@.ul + cd @/local/dn@ && ureglex -C -c @/local/bn@.c -h @/local/bn@.h -l @/local/bn@.ul +@] + else + append /local/rnd/RULES [@ +# dummy ureglex for @/local/rnd/mod@ +@/local/n@.c: + echo "skipping ureglex..." +@] + end + end + end +end + + put /local/rnd/mod/enabled {1} include /local/csch/tmpasm/plugin_conf @@ -74,6 +131,8 @@ put /local/rnd/mod/CFLAGS {} put /local/rnd/mod/YACC {} put /local/rnd/mod/LEX {} +put /local/rnd/mod/BYACCIC {} +put /local/rnd/mod/UREGLEX {} put /local/rnd/mod/SPHASH {} put /local/rnd/mod/SPHASH_ARGS {} put /local/rnd/mod/CLEANFILES {} Index: trunk/src/plugins/std_forge/cond/std_forge_cond.c =================================================================== --- trunk/src/plugins/std_forge/cond/std_forge_cond.c (revision 8077) +++ trunk/src/plugins/std_forge/cond/std_forge_cond.c (nonexistent) @@ -1,38 +0,0 @@ -#include -#include "cond.h" - -const char *forgecond_var_resolve_cb(forgecond_ctx_t *ctx, const char *name1, const char *name2) -{ - if (strcmp(name2, "a") == 0) return "one"; - if (strcmp(name2, "b") == 0) return "two"; - if (strcmp(name2, "c") == 0) return "three"; - if (strcmp(name2, "d") == 0) return "one"; - return NULL; -} - -void forgecond_error_cb(forgecond_ctx_t *ctx, const char *s) -{ - fprintf(stderr, "%s\n", s); -} - - -int main(void) -{ - long res; - forgecond_ctx_t ctx = {0}; - vtl0_t stack = {0}; - char line[256], *s; - - - s = fgets(line, sizeof(line), stdin); - if (forgecond_parse_str(&ctx, s) != 0) - return 1; - - forgecond_dump(stderr, &ctx); - - res = forgecond_exec(&ctx, &stack); - printf("res=%ld\n", res); - - return 0; -} - Index: trunk/src/plugins/std_forge/cond/cond.h =================================================================== --- trunk/src/plugins/std_forge/cond/cond.h (revision 8077) +++ trunk/src/plugins/std_forge/cond/cond.h (nonexistent) @@ -1,20 +0,0 @@ -#include -#include - -typedef struct { - gds_t strs; - vtl0_t prg; - unsigned in_quote:1; - const char *var_val[2]; -} forgecond_ctx_t; - -int forgecond_parse_str(forgecond_ctx_t *ctx, const char *str); -void forgecond_dump(FILE *f, forgecond_ctx_t *ctx); -long forgecond_exec(forgecond_ctx_t *ctx, vtl0_t *stack); - - -/* Provided by the caller: */ -extern const char *forgecond_var_resolve_cb(forgecond_ctx_t *ctx, const char *name1, const char *name2); -extern void forgecond_error_cb(forgecond_ctx_t *ctx, const char *s); - - Index: trunk/src/plugins/std_forge/cond/cond.y =================================================================== --- trunk/src/plugins/std_forge/cond/cond.y (revision 8077) +++ trunk/src/plugins/std_forge/cond/cond.y (nonexistent) @@ -1,342 +0,0 @@ -%prefix forgecond_% - -%{ -#include -#include -#include "cond.h" - -#define STR_VAL_NULL -1000 -#define STR_VAL_BASE -100 - -#define INST(a, b, c) ((((long)a) << 16) | (((long)b) << 8) | ((long)c)) - -typedef enum { - FGC_ABORT = 0, - FGC_ADD = INST('A', 'D', 'D'), - FGC_SUB = INST('S', 'U', 'B'), - FGC_MUL = INST('M', 'U', 'L'), - FGC_DIV = INST('D', 'I', 'V'), - FGC_MOD = INST('M', 'O', 'D'), - FGC_STR_EQ = INST('S', 'E', 'Q'), - FGC_STR_NEQ = INST('S', 'N', 'Q'), - FGC_EQ = INST('E', 'Q', 0), - FGC_NEQ = INST('N', 'E', 'Q'), - FGC_GT = INST('G', 'T', 0), - FGC_LT = INST('L', 'T', 0), - FGC_GTEQ = INST('G', 'T', 'E'), - FGC_LTEQ = INST('L', 'T', 'E'), - FGC_BIN_AND = INST('&', 0, 0), - FGC_BIN_OR = INST('|', 0, 0), - FGC_LOG_AND = INST('&', '&', 0), - FGC_LOG_OR = INST('|', '|', 0), - FGC_NEG = INST('N', 'E', 'G'), - FGC_NOT = INST('N', 'O', 'T'), - FGC_VAR1 = INST('V', 'R', '1'), - FGC_VAR2 = INST('V', 'R', '2'), - FGC_NUM = INST('N', 'U', 'M'), - FGC_STR = INST('S', 'T', 'R') /* string literal */ -} forgecond_inst_t; - -static long append(forgecond_ctx_t *ctx, long cod) { vtl0_append(&ctx->prg, cod); } - -%} - -%start cond - -%token DIGIT LETTER - -%left '|' -%left '&' -%left '+' '-' -%left '*' '/' '%' -%left '=' '!' '<' '>' -%left UMINUS /* supplies precedence for unary minus */ -%left UNOT /* supplies precedence for unary not */ - -%union -{ - long l; -} - -%type LETTER -%type DIGIT -%type expr -%type number -%type id -%type var -%type str - -%% /* beginning of rules section */ - -cond: - expr - ; - -expr: - '(' expr ')' { /* nothing to generate */ } - | str '=' '=' str { append(ctx, FGC_STR_EQ); } - | str '!' '=' str { append(ctx, FGC_STR_NEQ); } - | expr '=' '=' expr { append(ctx, FGC_EQ); } - | expr '>' '=' expr { append(ctx, FGC_GTEQ); } - | expr '<' '=' expr { append(ctx, FGC_LTEQ); } - | expr '>' expr { append(ctx, FGC_GT); } - | expr '<' expr { append(ctx, FGC_LT); } - | expr '!' '=' expr { append(ctx, FGC_NEQ); } - | expr '+' expr { append(ctx, FGC_ADD); } - | expr '-' expr { append(ctx, FGC_SUB); } - | expr '*' expr { append(ctx, FGC_MUL); } - | expr '/' expr { append(ctx, FGC_DIV); } - | expr '%' expr { append(ctx, FGC_MOD); } - | expr '&' expr { append(ctx, FGC_BIN_AND); } - | expr '|' expr { append(ctx, FGC_BIN_OR); } - | expr '&' '&' expr { append(ctx, FGC_LOG_AND); } - | expr '|' '|' expr { append(ctx, FGC_LOG_OR); } - | '-' expr %prec UMINUS { append(ctx, FGC_NEG); } - | '!' expr %prec UNOT { append(ctx, FGC_NOT); } - | number { append(ctx, FGC_NUM); append(ctx, $1); } - ; - -number: - DIGIT { $$ = $1; } - | number DIGIT { $$ = 10 * $1 + $2; } - ; - -id: - LETTER { if (ctx->strs.used != 0) gds_append(&ctx->strs, '\0'); $$ = ctx->strs.used; gds_append(&ctx->strs, $1); } - | id LETTER { $$ = $1; gds_append(&ctx->strs, $2); } - | id DIGIT { $$ = $1; gds_append(&ctx->strs, $2 + '0'); } - ; - -var: - id { append(ctx, FGC_VAR1); append(ctx, $1); } - | id '.' id { append(ctx, FGC_VAR2); append(ctx, $1); append(ctx, $3); } - ; - -str: - var { $$ = $1; } - | '"' { ctx->in_quote = 1; } - id '"' { ctx->in_quote = 0; append(ctx, FGC_STR); append(ctx, $3); } - ; - -%% /* start of programs */ - -static int lex(forgecond_ctx_t *ctx, forgecond_STYPE *yylval, const char **inp) -{ - int c; - - if (ctx->in_quote) { - c = **inp; - (*inp)++; - if (c == '\\') { - c = **inp; - (*inp)++; - } - else if (c == '\"') - return c; - yylval->l = c; - return LETTER; - } - - do { - c = **inp; - (*inp)++; - } while(isspace(c)); /* skip space */ - - if (c == '\0') - return forgecond_EOF; - - /* c is now nonblank */ - if (islower(c) || (c == '_')) { - yylval->l = c; - return LETTER; - } - if (isdigit(c)) { - yylval->l = c - '0'; - return DIGIT; - } - return c; -} - -void forgecond_dump(FILE *f, forgecond_ctx_t *ctx) -{ - long n, len; - - fprintf(f, "prg:\n"); - for(n = 0; n < ctx->prg.used; n++) { - char s[4]; - long l; - - switch(ctx->prg.array[n]) { - case FGC_NUM: fprintf(f, " NUM: %ld\n", ctx->prg.array[++n]); break; - case FGC_STR: fprintf(f, " STR: [%ld]\n", ctx->prg.array[++n]); break; - case FGC_VAR1: fprintf(f, " VAR1: [%ld]\n", ctx->prg.array[++n]); break; - case FGC_VAR2: fprintf(f, " VAR2: [%ld] [%ld]\n", ctx->prg.array[++n], ctx->prg.array[++n]); break; - default: - l = ctx->prg.array[n]; - s[0] = (l >> 16) & 0x0ff; - s[1] = (l >> 8) & 0x0ff; - s[2] = l & 0x0ff; - s[3] = '\0'; - fprintf(f, " %s\n", s); - break; - } - } - - fprintf(f, "strings:\n"); - for(n = 0; n < ctx->strs.used; n += len) { - len = strlen(ctx->strs.array+n)+1; - fprintf(f, " [%ld] '%s'\n", n, ctx->strs.array+n); - } -} - -static long pop_(forgecond_ctx_t *ctx, vtl0_t *stack) -{ - if (stack->used > 0) - return (long)stack->array[--stack->used]; - forgecond_error_cb(ctx, "forgecond: stack underflow (internal error)\n"); - return 0; -} - -static const char *get_str(forgecond_ctx_t *ctx, long idx, int allow_strval) -{ - if ((allow_strval) && (idx < 0)) { - if (idx == STR_VAL_NULL) - return NULL; - idx = idx - STR_VAL_BASE; - if ((idx >= 0) && (idx < sizeof(ctx->var_val)/sizeof(ctx->var_val[0]))) { - const char *res = ctx->var_val[idx]; - ctx->var_val[idx] = NULL; - return res; - } - forgecond_error_cb(ctx, "forgecond: invalid str val address (internal error)\n"); - return NULL; - } - - if ((idx < 0) || (idx >= ctx->strs.used)) { - forgecond_error_cb(ctx, "forgecond: invalid string literal address (internal error)\n"); - return NULL; - } - return ctx->strs.array + idx; - -} - -static const char *pop_str_(forgecond_ctx_t *ctx, vtl0_t *stack) -{ - return get_str(ctx, pop_(ctx, stack), 1); -} - -#define push(val) vtl0_append(stack, val) -#define pop() pop_(ctx, stack) -#define pop_str() pop_str_(ctx, stack) - -static void push_var_val(forgecond_ctx_t *ctx, vtl0_t *stack, long name_idx2, long name_idx1) -{ - int n; - const char *name1 = (name_idx1 >= 0) ? get_str(ctx, name_idx1, 0) : NULL; - const char *name2 = (name_idx2 >= 0) ? get_str(ctx, name_idx2, 0) : NULL; - const char *res = forgecond_var_resolve_cb(ctx, name1, name2); - - if (res == NULL) { - push(STR_VAL_NULL); - return; - } - - for(n = 0; n < sizeof(ctx->var_val)/sizeof(ctx->var_val[0]); n++) { - if (ctx->var_val[n] == NULL) { - ctx->var_val[n] = res; - push(STR_VAL_BASE+n); - return; - } - } - - forgecond_error_cb(ctx, "forgecond: no slot for str val (internal error)\n"); - push(STR_VAL_NULL); - return; -} - - - -static int safe_strcmp(const char *a, const char *b) -{ - if ((a == NULL) || (b == NULL)) return -1; /* an invalid string never equals to anyting */ - return strcmp(a, b); -} - -long forgecond_exec(forgecond_ctx_t *ctx, vtl0_t *stack) -{ - long n, a, b; - const char *sa, *sb; - - for(n = 0; n < ctx->prg.used; n++) { - switch(ctx->prg.array[n]) { - - /* push immediate */ - case FGC_VAR2: - push_var_val(ctx, stack, ctx->prg.array[++n], ctx->prg.array[++n]); - break; - /* fall-thru to push two string indices */ - case FGC_VAR1: - push_var_val(ctx, stack, ctx->prg.array[++n], -1); - break; - - case FGC_NUM: - case FGC_STR: - push(ctx->prg.array[++n]); - break; - - case FGC_ADD: push(pop() + pop()); break; - case FGC_SUB: a = pop(); b = pop(); push(b - a); break; - case FGC_MUL: push(pop() * pop()); break; - case FGC_DIV: a = pop(); b = pop(); push(b / a); break; - case FGC_MOD: a = pop(); b = pop(); push(b % a); break; - case FGC_EQ: push(pop() == pop()); break; - case FGC_NEQ: push(pop() != pop()); break; - case FGC_GT: a = pop(); b = pop(); push(b > a); break; - case FGC_LT: a = pop(); b = pop(); push(b < a); break; - case FGC_GTEQ: a = pop(); b = pop(); push(b >= a); break; - case FGC_LTEQ: a = pop(); b = pop(); push(b <= a); break; - case FGC_BIN_AND: push(pop() & pop()); break; - case FGC_BIN_OR: push(pop() | pop()); break; - case FGC_LOG_AND: push(pop() && pop()); break; - case FGC_LOG_OR: push(pop() || pop()); break; - case FGC_NEG: push(-pop()); break; - case FGC_NOT: push(!pop()); break; - - case FGC_STR_EQ: sa = pop_str(); sb = pop_str(); push(safe_strcmp(sa, sb) == 0); break; - case FGC_STR_NEQ: sa = pop_str(); sb = pop_str(); push(safe_strcmp(sa, sb) != 0); break; - } - } - - return pop(); -} - -int forgecond_parse_str(forgecond_ctx_t *ctx, const char *str) -{ - forgecond_res_t res; - forgecond_yyctx_t yyctx; - - ctx->strs.used = 0; - ctx->prg.used = 0; - ctx->in_quote = 0; - memset(&ctx->var_val, 0, sizeof(ctx->var_val)); - - if (str == NULL) - return -1; - - if (forgecond_parse_init(&yyctx) != 0) - return -1; - - do { - forgecond_STYPE lval; - int tok = lex(ctx, &lval, &str); - res = forgecond_parse(&yyctx, ctx, tok, &lval); - } while(res == forgecond_RES_NEXT); - - return (res == forgecond_RES_DONE) ? 0 : -1; -} - -void forgecond_error(forgecond_ctx_t *ctx, forgecond_STYPE tok, const char *s) -{ - forgecond_error_cb(ctx, s); -} - Index: trunk/src/plugins/std_forge/cond/Makefile =================================================================== --- trunk/src/plugins/std_forge/cond/Makefile (revision 8077) +++ trunk/src/plugins/std_forge/cond/Makefile (nonexistent) @@ -1,24 +0,0 @@ -BYACCIC=byaccic - -include ../../../../Makefile.conf -include $(LIBRND_MAK) - -CFLAGS = $(CFLAGS_LIBRND) -g -std=c89 -pedantic -LDLIBS = -lrnd-3rd - -all: std_forge_cond - -std_forge_cond: std_forge_cond.o cond.o - $(CC) -o std_forge_cond std_forge_cond.o cond.o $(LDLIBS) - -cond.o: cond.c cond.h - $(CC) -c $(CFLAGS) -o cond.o cond.c - -std_forge_cond.o: cond.c cond.h - $(CC) -c $(CFLAGS) -o std_forge_cond.o std_forge_cond.c - -cond.c: cond.y - $(BYACCIC) -o cond.c cond.y - -clean: - -rm cond cond.c Index: trunk/src/plugins/std_forge/Plug.tmpasm =================================================================== --- trunk/src/plugins/std_forge/Plug.tmpasm (revision 8077) +++ trunk/src/plugins/std_forge/Plug.tmpasm (revision 8078) @@ -1,8 +1,11 @@ put /local/rnd/mod {std_forge} put /local/rnd/mod/OBJS [@ $(PLUGDIR)/std_forge/std_forge.o + $(PLUGDIR)/std_forge/cond_gram.o @] +put /local/rnd/mod/BYACCIC {$(PLUGDIR)/std_forge/cond_gram} + switch /local/module/std_forge/controls case {buildin} include /local/csch/tmpasm/buildin; end; case {plugin} include /local/csch/tmpasm/plugin; end; Index: trunk/src/plugins/std_forge/cond.h =================================================================== --- trunk/src/plugins/std_forge/cond.h (nonexistent) +++ trunk/src/plugins/std_forge/cond.h (revision 8078) @@ -0,0 +1,20 @@ +#include +#include + +typedef struct { + gds_t strs; + vtl0_t prg; + unsigned in_quote:1; + const char *var_val[2]; +} forgecond_ctx_t; + +int forgecond_parse_str(forgecond_ctx_t *ctx, const char *str); +void forgecond_dump(FILE *f, forgecond_ctx_t *ctx); +long forgecond_exec(forgecond_ctx_t *ctx, vtl0_t *stack); + + +/* Provided by the caller: */ +extern const char *forgecond_var_resolve_cb(forgecond_ctx_t *ctx, const char *name1, const char *name2); +extern void forgecond_error_cb(forgecond_ctx_t *ctx, const char *s); + + Index: trunk/src/plugins/std_forge/cond_gram.y =================================================================== --- trunk/src/plugins/std_forge/cond_gram.y (nonexistent) +++ trunk/src/plugins/std_forge/cond_gram.y (revision 8078) @@ -0,0 +1,342 @@ +%prefix forgecond_% + +%{ +#include +#include +#include "cond.h" + +#define STR_VAL_NULL -1000 +#define STR_VAL_BASE -100 + +#define INST(a, b, c) ((((long)a) << 16) | (((long)b) << 8) | ((long)c)) + +typedef enum { + FGC_ABORT = 0, + FGC_ADD = INST('A', 'D', 'D'), + FGC_SUB = INST('S', 'U', 'B'), + FGC_MUL = INST('M', 'U', 'L'), + FGC_DIV = INST('D', 'I', 'V'), + FGC_MOD = INST('M', 'O', 'D'), + FGC_STR_EQ = INST('S', 'E', 'Q'), + FGC_STR_NEQ = INST('S', 'N', 'Q'), + FGC_EQ = INST('E', 'Q', 0), + FGC_NEQ = INST('N', 'E', 'Q'), + FGC_GT = INST('G', 'T', 0), + FGC_LT = INST('L', 'T', 0), + FGC_GTEQ = INST('G', 'T', 'E'), + FGC_LTEQ = INST('L', 'T', 'E'), + FGC_BIN_AND = INST('&', 0, 0), + FGC_BIN_OR = INST('|', 0, 0), + FGC_LOG_AND = INST('&', '&', 0), + FGC_LOG_OR = INST('|', '|', 0), + FGC_NEG = INST('N', 'E', 'G'), + FGC_NOT = INST('N', 'O', 'T'), + FGC_VAR1 = INST('V', 'R', '1'), + FGC_VAR2 = INST('V', 'R', '2'), + FGC_NUM = INST('N', 'U', 'M'), + FGC_STR = INST('S', 'T', 'R') /* string literal */ +} forgecond_inst_t; + +static long append(forgecond_ctx_t *ctx, long cod) { vtl0_append(&ctx->prg, cod); } + +%} + +%start cond + +%token DIGIT LETTER + +%left '|' +%left '&' +%left '+' '-' +%left '*' '/' '%' +%left '=' '!' '<' '>' +%left UMINUS /* supplies precedence for unary minus */ +%left UNOT /* supplies precedence for unary not */ + +%union +{ + long l; +} + +%type LETTER +%type DIGIT +%type expr +%type number +%type id +%type var +%type str + +%% /* beginning of rules section */ + +cond: + expr + ; + +expr: + '(' expr ')' { /* nothing to generate */ } + | str '=' '=' str { append(ctx, FGC_STR_EQ); } + | str '!' '=' str { append(ctx, FGC_STR_NEQ); } + | expr '=' '=' expr { append(ctx, FGC_EQ); } + | expr '>' '=' expr { append(ctx, FGC_GTEQ); } + | expr '<' '=' expr { append(ctx, FGC_LTEQ); } + | expr '>' expr { append(ctx, FGC_GT); } + | expr '<' expr { append(ctx, FGC_LT); } + | expr '!' '=' expr { append(ctx, FGC_NEQ); } + | expr '+' expr { append(ctx, FGC_ADD); } + | expr '-' expr { append(ctx, FGC_SUB); } + | expr '*' expr { append(ctx, FGC_MUL); } + | expr '/' expr { append(ctx, FGC_DIV); } + | expr '%' expr { append(ctx, FGC_MOD); } + | expr '&' expr { append(ctx, FGC_BIN_AND); } + | expr '|' expr { append(ctx, FGC_BIN_OR); } + | expr '&' '&' expr { append(ctx, FGC_LOG_AND); } + | expr '|' '|' expr { append(ctx, FGC_LOG_OR); } + | '-' expr %prec UMINUS { append(ctx, FGC_NEG); } + | '!' expr %prec UNOT { append(ctx, FGC_NOT); } + | number { append(ctx, FGC_NUM); append(ctx, $1); } + ; + +number: + DIGIT { $$ = $1; } + | number DIGIT { $$ = 10 * $1 + $2; } + ; + +id: + LETTER { if (ctx->strs.used != 0) gds_append(&ctx->strs, '\0'); $$ = ctx->strs.used; gds_append(&ctx->strs, $1); } + | id LETTER { $$ = $1; gds_append(&ctx->strs, $2); } + | id DIGIT { $$ = $1; gds_append(&ctx->strs, $2 + '0'); } + ; + +var: + id { append(ctx, FGC_VAR1); append(ctx, $1); } + | id '.' id { append(ctx, FGC_VAR2); append(ctx, $1); append(ctx, $3); } + ; + +str: + var { $$ = $1; } + | '"' { ctx->in_quote = 1; } + id '"' { ctx->in_quote = 0; append(ctx, FGC_STR); append(ctx, $3); } + ; + +%% /* start of programs */ + +static int lex(forgecond_ctx_t *ctx, forgecond_STYPE *yylval, const char **inp) +{ + int c; + + if (ctx->in_quote) { + c = **inp; + (*inp)++; + if (c == '\\') { + c = **inp; + (*inp)++; + } + else if (c == '\"') + return c; + yylval->l = c; + return LETTER; + } + + do { + c = **inp; + (*inp)++; + } while(isspace(c)); /* skip space */ + + if (c == '\0') + return forgecond_EOF; + + /* c is now nonblank */ + if (islower(c) || (c == '_')) { + yylval->l = c; + return LETTER; + } + if (isdigit(c)) { + yylval->l = c - '0'; + return DIGIT; + } + return c; +} + +void forgecond_dump(FILE *f, forgecond_ctx_t *ctx) +{ + long n, len; + + fprintf(f, "prg:\n"); + for(n = 0; n < ctx->prg.used; n++) { + char s[4]; + long l; + + switch(ctx->prg.array[n]) { + case FGC_NUM: fprintf(f, " NUM: %ld\n", ctx->prg.array[++n]); break; + case FGC_STR: fprintf(f, " STR: [%ld]\n", ctx->prg.array[++n]); break; + case FGC_VAR1: fprintf(f, " VAR1: [%ld]\n", ctx->prg.array[++n]); break; + case FGC_VAR2: fprintf(f, " VAR2: [%ld] [%ld]\n", ctx->prg.array[++n], ctx->prg.array[++n]); break; + default: + l = ctx->prg.array[n]; + s[0] = (l >> 16) & 0x0ff; + s[1] = (l >> 8) & 0x0ff; + s[2] = l & 0x0ff; + s[3] = '\0'; + fprintf(f, " %s\n", s); + break; + } + } + + fprintf(f, "strings:\n"); + for(n = 0; n < ctx->strs.used; n += len) { + len = strlen(ctx->strs.array+n)+1; + fprintf(f, " [%ld] '%s'\n", n, ctx->strs.array+n); + } +} + +static long pop_(forgecond_ctx_t *ctx, vtl0_t *stack) +{ + if (stack->used > 0) + return (long)stack->array[--stack->used]; + forgecond_error_cb(ctx, "forgecond: stack underflow (internal error)\n"); + return 0; +} + +static const char *get_str(forgecond_ctx_t *ctx, long idx, int allow_strval) +{ + if ((allow_strval) && (idx < 0)) { + if (idx == STR_VAL_NULL) + return NULL; + idx = idx - STR_VAL_BASE; + if ((idx >= 0) && (idx < sizeof(ctx->var_val)/sizeof(ctx->var_val[0]))) { + const char *res = ctx->var_val[idx]; + ctx->var_val[idx] = NULL; + return res; + } + forgecond_error_cb(ctx, "forgecond: invalid str val address (internal error)\n"); + return NULL; + } + + if ((idx < 0) || (idx >= ctx->strs.used)) { + forgecond_error_cb(ctx, "forgecond: invalid string literal address (internal error)\n"); + return NULL; + } + return ctx->strs.array + idx; + +} + +static const char *pop_str_(forgecond_ctx_t *ctx, vtl0_t *stack) +{ + return get_str(ctx, pop_(ctx, stack), 1); +} + +#define push(val) vtl0_append(stack, val) +#define pop() pop_(ctx, stack) +#define pop_str() pop_str_(ctx, stack) + +static void push_var_val(forgecond_ctx_t *ctx, vtl0_t *stack, long name_idx2, long name_idx1) +{ + int n; + const char *name1 = (name_idx1 >= 0) ? get_str(ctx, name_idx1, 0) : NULL; + const char *name2 = (name_idx2 >= 0) ? get_str(ctx, name_idx2, 0) : NULL; + const char *res = forgecond_var_resolve_cb(ctx, name1, name2); + + if (res == NULL) { + push(STR_VAL_NULL); + return; + } + + for(n = 0; n < sizeof(ctx->var_val)/sizeof(ctx->var_val[0]); n++) { + if (ctx->var_val[n] == NULL) { + ctx->var_val[n] = res; + push(STR_VAL_BASE+n); + return; + } + } + + forgecond_error_cb(ctx, "forgecond: no slot for str val (internal error)\n"); + push(STR_VAL_NULL); + return; +} + + + +static int safe_strcmp(const char *a, const char *b) +{ + if ((a == NULL) || (b == NULL)) return -1; /* an invalid string never equals to anyting */ + return strcmp(a, b); +} + +long forgecond_exec(forgecond_ctx_t *ctx, vtl0_t *stack) +{ + long n, a, b; + const char *sa, *sb; + + for(n = 0; n < ctx->prg.used; n++) { + switch(ctx->prg.array[n]) { + + /* push immediate */ + case FGC_VAR2: + push_var_val(ctx, stack, ctx->prg.array[++n], ctx->prg.array[++n]); + break; + /* fall-thru to push two string indices */ + case FGC_VAR1: + push_var_val(ctx, stack, ctx->prg.array[++n], -1); + break; + + case FGC_NUM: + case FGC_STR: + push(ctx->prg.array[++n]); + break; + + case FGC_ADD: push(pop() + pop()); break; + case FGC_SUB: a = pop(); b = pop(); push(b - a); break; + case FGC_MUL: push(pop() * pop()); break; + case FGC_DIV: a = pop(); b = pop(); push(b / a); break; + case FGC_MOD: a = pop(); b = pop(); push(b % a); break; + case FGC_EQ: push(pop() == pop()); break; + case FGC_NEQ: push(pop() != pop()); break; + case FGC_GT: a = pop(); b = pop(); push(b > a); break; + case FGC_LT: a = pop(); b = pop(); push(b < a); break; + case FGC_GTEQ: a = pop(); b = pop(); push(b >= a); break; + case FGC_LTEQ: a = pop(); b = pop(); push(b <= a); break; + case FGC_BIN_AND: push(pop() & pop()); break; + case FGC_BIN_OR: push(pop() | pop()); break; + case FGC_LOG_AND: push(pop() && pop()); break; + case FGC_LOG_OR: push(pop() || pop()); break; + case FGC_NEG: push(-pop()); break; + case FGC_NOT: push(!pop()); break; + + case FGC_STR_EQ: sa = pop_str(); sb = pop_str(); push(safe_strcmp(sa, sb) == 0); break; + case FGC_STR_NEQ: sa = pop_str(); sb = pop_str(); push(safe_strcmp(sa, sb) != 0); break; + } + } + + return pop(); +} + +int forgecond_parse_str(forgecond_ctx_t *ctx, const char *str) +{ + forgecond_res_t res; + forgecond_yyctx_t yyctx; + + ctx->strs.used = 0; + ctx->prg.used = 0; + ctx->in_quote = 0; + memset(&ctx->var_val, 0, sizeof(ctx->var_val)); + + if (str == NULL) + return -1; + + if (forgecond_parse_init(&yyctx) != 0) + return -1; + + do { + forgecond_STYPE lval; + int tok = lex(ctx, &lval, &str); + res = forgecond_parse(&yyctx, ctx, tok, &lval); + } while(res == forgecond_RES_NEXT); + + return (res == forgecond_RES_DONE) ? 0 : -1; +} + +void forgecond_error(forgecond_ctx_t *ctx, forgecond_STYPE tok, const char *s) +{ + forgecond_error_cb(ctx, s); +} + Index: trunk/src/plugins/std_forge/std_forge.c =================================================================== --- trunk/src/plugins/std_forge/std_forge.c (revision 8077) +++ trunk/src/plugins/std_forge/std_forge.c (revision 8078) @@ -2,7 +2,7 @@ * COPYRIGHT * * cschem - modular/flexible schematics editor - standard cschem attributes - * Copyright (C) 2022 Tibor 'Igor2' Palinkas + * Copyright (C) 2022, 2023 Tibor 'Igor2' Palinkas * * (Supported by NLnet NGI0 PET Fund in 2022) * @@ -47,6 +47,8 @@ #include #include +#include "cond.h" + #if 0 typedef struct { } std_forge_ctx_t; /* per view data */ @@ -325,6 +327,17 @@ return -1; } +const char *forgecond_var_resolve_cb(forgecond_ctx_t *ctx, const char *name1, const char *name2) +{ + return NULL; +} + +void forgecond_error_cb(forgecond_ctx_t *ctx, const char *s) +{ + rnd_message(RND_MSG_ERROR, "std_forge condition: %s\n", s); +} + + static int forge_condition(csch_ahdr_t *aobj, const char *inst) { rnd_trace("forge condition!\n"); Index: trunk/src/sch-rnd/Makefile.in =================================================================== --- trunk/src/sch-rnd/Makefile.in (revision 8077) +++ trunk/src/sch-rnd/Makefile.in (revision 8078) @@ -97,7 +97,7 @@ RNDLIB_LDLIBS = -lrnd-hid -lrnd-font -lrnd-poly -lrnd-core -lrnd-3rd ROOT=@/local/csch/root@ CC=@cc/cc@ -CFLAGS=@/local/csch/CFLAGS@ @/local/csch/c89flags@ @?/local/rnd/CFLAGS@ $(CFLAGS_LIBRND) @?/local/csch/librnd_extra_inc@ +CFLAGS=-I. @/local/csch/CFLAGS@ @/local/csch/c89flags@ @?/local/rnd/CFLAGS@ $(CFLAGS_LIBRND) @?/local/csch/librnd_extra_inc@ C89FLAGS=$(CFLAGS) CP=cp MKDIR=mkdir -p Index: trunk/tests/std_forge_cond/Makefile =================================================================== --- trunk/tests/std_forge_cond/Makefile (nonexistent) +++ trunk/tests/std_forge_cond/Makefile (revision 8078) @@ -0,0 +1,23 @@ +TRUNK=../.. +STDFRG=$(TRUNK)/src/plugins/std_forge + +include $(TRUNK)/Makefile.conf +include $(LIBRND_MAK) + +CFLAGS = $(CFLAGS_LIBRND) -I$(STDFRG) -g -std=c89 -pedantic +LDLIBS = -lrnd-3rd + + +all: std_forge_cond + +std_forge_cond: $(STDFRG)/cond_gram.o std_forge_cond.o + $(CC) -o std_forge_cond std_forge_cond.o $(STDFRG)/cond_gram.o $(LDLIBS) + +$(STDFRG)/cond_gram.o: $(STDFRG)/cond_gram.c $(STDFRG)/cond.h + $(CC) -c $(CFLAGS) -o $(STDFRG)/cond_gram.o $(STDFRG)/cond_gram.c + +std_forge_cond.o: std_forge_cond.c $(STDFRG)/cond.h + $(CC) -c $(CFLAGS) -o std_forge_cond.o std_forge_cond.c + +clean: + -rm cond cond.c Index: trunk/tests/std_forge_cond/std_forge_cond.c =================================================================== --- trunk/tests/std_forge_cond/std_forge_cond.c (nonexistent) +++ trunk/tests/std_forge_cond/std_forge_cond.c (revision 8078) @@ -0,0 +1,38 @@ +#include +#include "cond.h" + +const char *forgecond_var_resolve_cb(forgecond_ctx_t *ctx, const char *name1, const char *name2) +{ + if (strcmp(name2, "a") == 0) return "one"; + if (strcmp(name2, "b") == 0) return "two"; + if (strcmp(name2, "c") == 0) return "three"; + if (strcmp(name2, "d") == 0) return "one"; + return NULL; +} + +void forgecond_error_cb(forgecond_ctx_t *ctx, const char *s) +{ + fprintf(stderr, "%s\n", s); +} + + +int main(void) +{ + long res; + forgecond_ctx_t ctx = {0}; + vtl0_t stack = {0}; + char line[256], *s; + + + s = fgets(line, sizeof(line), stdin); + if (forgecond_parse_str(&ctx, s) != 0) + return 1; + + forgecond_dump(stderr, &ctx); + + res = forgecond_exec(&ctx, &stack); + printf("res=%ld\n", res); + + return 0; +} +