diff options
| author | Xavier Del Campo Romero <xavi92@disroot.org> | 2026-09-26 23:30:40 +0200 |
|---|---|---|
| committer | Xavier Del Campo Romero <xavi92@disroot.org> | 2026-09-27 23:57:29 +0200 |
| commit | 204f6f332318056a9b950e71e4a958da0c10ea72 (patch) | |
| tree | 5d7938d9ed44dbe9455d2a88b2ef93a4beef4397 | |
| parent | 88d1bca43a8412b285ea2dd54dfa98d08ecc7849 (diff) | |
| download | prc-204f6f332318056a9b950e71e4a958da0c10ea72.tar.gz | |
prc1: Rework arg handling + dbg
| -rw-r--r-- | src/prc1/CMakeLists.txt | 2 | ||||
| -rw-r--r-- | src/prc1/arg.c | 123 | ||||
| -rw-r--r-- | src/prc1/arg.h | 23 | ||||
| -rw-r--r-- | src/prc1/call.c | 13 | ||||
| -rw-r--r-- | src/prc1/dbg.c | 19 | ||||
| -rw-r--r-- | src/prc1/dbg.h | 8 | ||||
| -rw-r--r-- | src/prc1/display.c | 5 | ||||
| -rw-r--r-- | src/prc1/end.c | 3 | ||||
| -rw-r--r-- | src/prc1/fn.c | 4 | ||||
| -rw-r--r-- | src/prc1/from.c | 10 | ||||
| -rw-r--r-- | src/prc1/lex.h | 2 | ||||
| -rw-r--r-- | src/prc1/lit.c | 3 | ||||
| -rw-r--r-- | src/prc1/parse.h | 2 | ||||
| -rw-r--r-- | src/prc1/pr.c | 6 | ||||
| -rw-r--r-- | src/prc1/prc1.c | 34 | ||||
| -rw-r--r-- | src/prc1/set.c | 27 | ||||
| -rw-r--r-- | src/prc1/storage.c | 5 | ||||
| -rw-r--r-- | src/prc1/td.c | 39 | ||||
| -rw-r--r-- | src/prc1/tmp.c | 3 | ||||
| -rw-r--r-- | src/prc1/warn.c | 5 |
20 files changed, 263 insertions, 73 deletions
diff --git a/src/prc1/CMakeLists.txt b/src/prc1/CMakeLists.txt index e2b9ad4..f5dfa86 100644 --- a/src/prc1/CMakeLists.txt +++ b/src/prc1/CMakeLists.txt @@ -1,6 +1,8 @@ add_executable(prc1 + arg.c call.c cgen.c + dbg.c display.c div.c end.c diff --git a/src/prc1/arg.c b/src/prc1/arg.c new file mode 100644 index 0000000..f61bca7 --- /dev/null +++ b/src/prc1/arg.c @@ -0,0 +1,123 @@ +#include "arg.h" +#include "dbg.h" +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +struct arg +{ + const char *s; + int (*f)(struct args *, const char *); + + enum + { + NOVAL, + SPACEVAL = 1, + EQVAL = 1 << 1, + JOINVAL = 1 << 2 + } v; +}; + +static int debug(struct args *a, const char *arg) +{ + dbgen = 1; + return 0; +} + +static int inc(struct args *a, const char *arg) +{ + struct arg_input *i = &a->incs; + size_t n = i->n + 1; + const char **v = realloc(i->v, n * sizeof *v); + + if (!v) + { + perror("realloc(3)"); + return -1; + } + + v[i->n++] = arg; + i->v = v; + return 0; +} + +static int opt(struct args *args, const struct arg *a, const char *arg) +{ + const struct arg *prev = args->arg; + const char *v = arg + strlen(a->s); + + if (prev && prev->v) + { + fprintf(stderr, "%s: option '%s' requires a value\n", args->name, + prev->s); + return -1; + } + else if (*v) + { + if (!(a->v & JOINVAL)) + { + fprintf(stderr, "%s: unrecognized command-line option '%s'\n", + args->name, arg); + return -1; + } + } + else if (a->v & SPACEVAL) + { + args->arg = a; + return 0; + } + else + v = NULL; + + return a->f(args, v); +} + +int arg(struct args *a, const char *value) +{ + static const struct arg args[] = + { + {"-d", debug}, + {"-I", inc, SPACEVAL | JOINVAL} + }; + + const struct arg *prev = a->arg; + + for (size_t i = 0; i < sizeof args / sizeof *args; i++) + { + const struct arg *arg = &args[i]; + + if (!strncmp(value, arg->s, strlen(arg->s))) + return opt(a, arg, value); + } + + if (prev) + { + if (*value != '-' && prev->f(a, value)) + return -1; + + a->arg = NULL; + } + else if (a->src) + { + fprintf(stderr, "%s: only one source file allowed\n", a->name); + return -1; + } + else + a->src = value; + + return 0; +} + +void arg_defaults(struct args *a) +{ +} + +static void free_input(struct arg_input *i) +{ + free(i->v); +} + +void arg_free(struct args *a) +{ + free_input(&a->incs); +} diff --git a/src/prc1/arg.h b/src/prc1/arg.h new file mode 100644 index 0000000..efa623f --- /dev/null +++ b/src/prc1/arg.h @@ -0,0 +1,23 @@ +#ifndef ARG_H +#define ARG_H + +#include <stddef.h> + +struct arg_input +{ + const char **v; + size_t n; +}; + +struct args +{ + const char *name, *src; + const struct arg *arg; + struct arg_input incs; +}; + +int arg(struct args *a, const char *arg); +void arg_defaults(struct args *a); +void arg_free(struct args *a); + +#endif diff --git a/src/prc1/call.c b/src/prc1/call.c index 8140eba..21ef4de 100644 --- a/src/prc1/call.c +++ b/src/prc1/call.c @@ -1,4 +1,5 @@ #include "call.h" +#include "dbg.h" #include "errloc.h" #include "fn.h" #include "lex.h" @@ -148,8 +149,8 @@ static int callpr(const struct lex *l, struct prv *p) else if (pop(l, p)) return -1; - fprintf(stderr, "\t\tadding call to %s using %zu params " - "and %s as return variable\n", c->tk->s, n, tk->s); + dbg("\t\tadding call to %s using %zu params and %s as return variable\n", + c->tk->s, n, tk->s); c->ret = e; c->nparams = n; p->stk = ++tk; @@ -184,8 +185,7 @@ static int callr(const struct lex *l, struct prv *p) else if (pop(l, p)) return -1; - fprintf(stderr, "\t\tadding call to %s with %s as return variable\n", - c->tk->s, tk->s); + dbg("\t\tadding call to %s with %s as return variable\n", c->tk->s, tk->s); c->ret = e; p->stk = ++tk; return 1; @@ -229,7 +229,7 @@ static int callp(const struct lex *l, struct prv *p) if (pop(l, p)) return -1; - fprintf(stderr, "\t\tadding call to %s with 1 param\n", c->tk->s); + dbg("\t\tadding call to %s with 1 param\n", c->tk->s); p->stk = tk; return 1; } @@ -249,8 +249,7 @@ static int callv(const struct lex *l, struct prv *p) else if (pop(l, p)) return -1; - fprintf(stderr, "\t\tadding call to %s with %s as return variable\n", - c->tk->s, tk->s); + dbg("\t\tadding call to %s with %s as return variable\n", c->tk->s, tk->s); p->stk = ++tk; return 1; } diff --git a/src/prc1/dbg.c b/src/prc1/dbg.c new file mode 100644 index 0000000..cf2d18c --- /dev/null +++ b/src/prc1/dbg.c @@ -0,0 +1,19 @@ +#include "dbg.h" +#include <stdarg.h> +#include <stdio.h> + +int dbgen; + +int dbg(const char *fmt, ...) +{ + int n; + va_list ap; + + if (!dbgen) + return 0; + + va_start(ap, fmt); + n = vfprintf(stderr, fmt, ap); + va_end(ap); + return n; +} diff --git a/src/prc1/dbg.h b/src/prc1/dbg.h new file mode 100644 index 0000000..956187e --- /dev/null +++ b/src/prc1/dbg.h @@ -0,0 +1,8 @@ +#ifndef DBG_H +#define DBG_H + +int dbg(const char *fmt, ...); + +extern int dbgen; + +#endif diff --git a/src/prc1/display.c b/src/prc1/display.c index 885fbe7..2fbf331 100644 --- a/src/prc1/display.c +++ b/src/prc1/display.c @@ -1,5 +1,6 @@ #include "display.h" #include "cgen.h" +#include "dbg.h" #include "parse.h" #include "prv.h" #include "stmt.h" @@ -29,8 +30,8 @@ static int finalize(const struct lex *l, const struct prv *p, .u.display.p = *pr }; - fprintf(stderr, "\t\tadding display statement with %zu entries%s\n", - pr->nentries, pr->println ? "" : ", no lf"); + dbg("\t\tadding display statement with %zu entries%s\n", pr->nentries, + pr->println ? "" : ", no lf"); return 0; } diff --git a/src/prc1/end.c b/src/prc1/end.c index b9ad790..561c981 100644 --- a/src/prc1/end.c +++ b/src/prc1/end.c @@ -1,4 +1,5 @@ #include "end.h" +#include "dbg.h" #include "errloc.h" #include "fn.h" #include "stmt.h" @@ -75,6 +76,6 @@ int end(const struct lex *l, struct prv *p) pos->seq = pos->stseq = stmts; pos->step = stmts->steps; p->stk = p->tk; - fprintf(stderr, "\t\tadding end statement, block index %zu\n", bl_i); + dbg("\t\tadding end statement, block index %zu\n", bl_i); return 1; } diff --git a/src/prc1/fn.c b/src/prc1/fn.c index c2d3b4f..03aa11e 100644 --- a/src/prc1/fn.c +++ b/src/prc1/fn.c @@ -1,4 +1,5 @@ #include "fn.h" +#include "dbg.h" #include "div.h" #include "errloc.h" #include "gl.h" @@ -91,8 +92,7 @@ static int pushfn(const struct tk *tk, const struct lex *lex, struct prv *p, if (div_fn(lex, p)) return -1; - fprintf(stderr, "adding %s function %s\n", - l == STATIC ? "private" : "public", tk->s); + dbg("adding %s function %s\n", l == STATIC ? "private" : "public", tk->s); return 1; } diff --git a/src/prc1/from.c b/src/prc1/from.c index b9cb99e..838d1de 100644 --- a/src/prc1/from.c +++ b/src/prc1/from.c @@ -1,5 +1,6 @@ #include "from.h" #include "cgen.h" +#include "dbg.h" #include "fn.h" #include "errloc.h" #include "stmt.h" @@ -236,8 +237,7 @@ static int finalize(struct prv *p, struct fn *fn, struct from *fr) fn->stmts = s; pos->seq = pos->stseq = stmts; pos->step = stmts->steps; - fprintf(stderr, ", iterator %s, block index %zu\n", fr->var->tk->s, - bl[fn->nblocks - 1]); + dbg(", iterator %s, block index %zu\n", fr->var->tk->s, bl[fn->nblocks - 1]); return 0; } @@ -297,7 +297,7 @@ int from(const struct lex *l, struct prv *p) || !(fr.var = tmp_create(fn, t))) return -1; - fprintf(stderr, "\t\tadding from statement [%s, %s]", start->s, end->s); + dbg("\t\tadding from statement [%s, %s]", start->s, end->s); if (finalize(p, fn, &fr)) return -1; @@ -341,8 +341,8 @@ int from_id(const struct lex *l, struct prv *p) || checkvar(fn, var, &fr)) return -1; - fprintf(stderr, "\t\tadding from statement [%s, %s] using %s", - start->s, end->s, var->s); + dbg("\t\tadding from statement [%s, %s] using %s", start->s, end->s, + var->s); if (finalize(p, fn, &fr)) return -1; diff --git a/src/prc1/lex.h b/src/prc1/lex.h index 6e836ac..4ab3e70 100644 --- a/src/prc1/lex.h +++ b/src/prc1/lex.h @@ -1,6 +1,7 @@ #ifndef LEX_H #define LEX_H +#include "arg.h" #include <stddef.h> #include <stdio.h> @@ -21,6 +22,7 @@ struct tk struct lex { + const struct args *args; struct loc loc; struct tk *tokens, tk; size_t ntok, len; diff --git a/src/prc1/lit.c b/src/prc1/lit.c index 09528a2..1faf247 100644 --- a/src/prc1/lit.c +++ b/src/prc1/lit.c @@ -1,3 +1,4 @@ +#include "dbg.h" #include "lit.h" #include "fn.h" #include "lex.h" @@ -92,8 +93,8 @@ const struct lit *lit_push(const struct tk *tk, struct prv *p) else if (ast->lastlit) ast->lastlit->next = l; + dbg("adding literal \"%s\"\n", name); ast->lastlit = l; - fprintf(stderr, "adding literal \"%s\"\n", name); return l; failure: diff --git a/src/prc1/parse.h b/src/prc1/parse.h index b85d618..5d3d25a 100644 --- a/src/prc1/parse.h +++ b/src/prc1/parse.h @@ -1,6 +1,7 @@ #ifndef PARSE_H #define PARSE_H +#include "arg.h" #include "lex.h" #include "storage.h" @@ -119,6 +120,7 @@ struct lit struct ast { + const struct args *args; struct fn *fns; struct lit *lits, *lastlit; struct type *types; diff --git a/src/prc1/pr.c b/src/prc1/pr.c index a171554..3a4221a 100644 --- a/src/prc1/pr.c +++ b/src/prc1/pr.c @@ -1,4 +1,5 @@ #include "pr.h" +#include "dbg.h" #include "errloc.h" #include "fn.h" #include "prv.h" @@ -147,9 +148,8 @@ static int finalize(const struct lex *l, struct prv *p) else if (push(&init, p)) return -1; - fprintf(stderr, "\tadding procedure using %zu%s parameters " - "and%s return value\n", pr->nparams, pr->variadic ? " variadic" : "", - pr->ret ? "" : " no"); + dbg("\tadding procedure using %zu%s parameters and%s return value\n", + pr->nparams, pr->variadic ? " variadic" : "", pr->ret ? "" : " no"); p->stk = p->tk; return 1; } diff --git a/src/prc1/prc1.c b/src/prc1/prc1.c index 6378907..2822cc5 100644 --- a/src/prc1/prc1.c +++ b/src/prc1/prc1.c @@ -1,3 +1,4 @@ +#include "arg.h" #include "cgen.h" #include "lex.h" #include "parse.h" @@ -8,34 +9,40 @@ int main(int argc, char *argv[]) { + const char *fname = "<standard input>"; + struct args args = {.name = *argv}; struct lex l = {0}; struct ast a = {0}; struct cgen c = {0}; FILE *f = stdin; - int opened = 0, ret = EXIT_FAILURE; + int ret = EXIT_FAILURE; - for (int i = 1; i < argc; i++) - fprintf(stderr, "[%d]=%s\n", i, argv[i]); - - if (argc < 2) + if (argc == 1) { fprintf(stderr, "%s [options ...] file\n", *argv); goto end; } - else if (strcmp(argv[1], "-")) + + arg_defaults(&args); + + for (int i = 1; i < argc; i++) + if (arg(&args, argv[i])) + goto end; + + if (args.src) { - if (!(f = fopen(argv[1], "rb"))) + if (!(f = fopen(args.src, "rb"))) { - fprintf(stderr, "%s: failed to open %s: %s\n", *argv, argv[1], + fprintf(stderr, "%s: fopen(3) %s: %s\n", *argv, args.src, strerror(errno)); goto end; } - opened = 1; - l.loc.f = argv[1]; + fname = args.src; } - else - l.loc.f = "stdin"; + + l.loc.f = fname; + l.args = a.args = &args; if (lex(&l, f) || parse(&l, &a) || cgen(&a, &c)) goto end; @@ -43,7 +50,7 @@ int main(int argc, char *argv[]) ret = EXIT_SUCCESS; end: - if (opened && fclose(f)) + if (f && f != stdin && fclose(f)) { perror("fclose(3)"); ret = EXIT_FAILURE; @@ -52,5 +59,6 @@ end: cgen_free(&c); ast_free(&a); lex_free(&l); + arg_free(&args); return ret; } diff --git a/src/prc1/set.c b/src/prc1/set.c index 3058040..3b83fc9 100644 --- a/src/prc1/set.c +++ b/src/prc1/set.c @@ -1,5 +1,6 @@ #include "set.h" #include "cgen.h" +#include "dbg.h" #include "errloc.h" #include "fn.h" #include "lex.h" @@ -259,12 +260,12 @@ static int mv(const struct lex *l, struct prv *p) } } - fputs("\t\tadding set ", stderr); + dbg("\t\tadding set "); for (size_t i = 0; i < s->ndsts; i++) - fprintf(stderr, "%s ", s->dsts[i].entry->tk->s); + dbg("%s ", s->dsts[i].entry->tk->s); - fprintf(stderr, "to %s\n", tk->s); + dbg("to %s\n", tk->s); if (pop(l, p)) return -1; @@ -307,12 +308,12 @@ static int maddr(const struct lex *l, struct prv *p) s->type = SET_ADDR; s->src = e; p->stk = ++tk; - fputs("\t\tadding set ", stderr); + dbg("\t\tadding set "); for (size_t i = 0; i < s->ndsts; i++) - fprintf(stderr, "%s ", s->dsts[i].entry->tk->s); + dbg("%s ", s->dsts[i].entry->tk->s); - fprintf(stderr, "to address of %s\n", s->src->tk->s); + dbg("to address of %s\n", s->src->tk->s); return 1; } @@ -368,12 +369,12 @@ static int msz(const struct lex *l, struct prv *p) s->type = SET_VAL; p->stk = ++tk; - fputs("\t\tadding set ", stderr); + dbg("\t\tadding set "); for (size_t i = 0; i < s->ndsts; i++) - fprintf(stderr, "%s ", s->dsts[i].entry->tk->s); + dbg("%s ", s->dsts[i].entry->tk->s); - fprintf(stderr, "size=%llu\n", s->srcv); + dbg("size=%llu\n", s->srcv); return 1; } @@ -391,10 +392,10 @@ static int mimb(const struct lex *l, struct prv *p) /* skip "to" */ tk++; - fputs("\t\tadding set ", stderr); + dbg("\t\tadding set "); for (size_t i = 0; i < s->ndsts; i++) - fprintf(stderr, "%s ", s->dsts[i].entry->tk->s); + dbg("%s ", s->dsts[i].entry->tk->s); if (tk->type == LIT) { @@ -409,7 +410,7 @@ static int mimb(const struct lex *l, struct prv *p) else if (tk->type == NUM) s->srcv = tonum(tk->s); - fprintf(stderr, "to [%s] ", tk->s); + dbg("to [%s] ", tk->s); /* skip index and "of" */ tk += 2; @@ -422,7 +423,7 @@ static int mimb(const struct lex *l, struct prv *p) else if (pop(l, p)) return -1; - fprintf(stderr, " of %s\n", tk->s); + dbg(" of %s\n", tk->s); s->type = SET_IMB; p->stk = ++tk; return 1; diff --git a/src/prc1/storage.c b/src/prc1/storage.c index 62f3c1f..828ca1b 100644 --- a/src/prc1/storage.c +++ b/src/prc1/storage.c @@ -1,4 +1,5 @@ #include "storage.h" +#include "dbg.h" #include "errloc.h" #include "fn.h" #include "lex.h" @@ -140,8 +141,8 @@ static int stpush(const struct lex *l, struct prv *p, const struct tk *name, if (p->proto) fputc('\t', stderr); - fprintf(stderr, "\tadding %s (%d:%d) to %s, type %s, offset %zu, " - "size %zu\n", name->s, loc->line, loc->col, st->name, tname, + dbg("\tadding %s (%d:%d) to %s, type %s, offset %zu, size %zu\n", + name->s, loc->line, loc->col, st->name, tname, entries[st->nentries - 1].offset, t->sz); ret = 1; end: diff --git a/src/prc1/td.c b/src/prc1/td.c index 72c379f..06572e7 100644 --- a/src/prc1/td.c +++ b/src/prc1/td.c @@ -1,4 +1,5 @@ #include "td.h" +#include "dbg.h" #include "div.h" #include "errloc.h" #include "fn.h" @@ -76,17 +77,16 @@ static int bump(const struct tk *tk, const struct type *t, struct prv *p) tdc->neg = neg; for (size_t i = 0; i < p->block; i++) - fputc('\t', stderr); + dbg("\t"); - fprintf(stderr, "\t\tnext %s constant value set to ", - neg ? "negative" : "positive"); + dbg("\t\tnext %s constant value set to ", neg ? "negative" : "positive"); if (neg) - fprintf(stderr, "%lld", tdc->u.v); + dbg("%lld", tdc->u.v); else - fprintf(stderr, "%llu", tdc->u.uv); + dbg("%llu", tdc->u.uv); - fputc('\n', stderr); + dbg("\n"); return 0; } @@ -160,10 +160,9 @@ static int cid(const struct lex *l, struct prv *p) return -1; for (size_t i = 0; i < p->block; i++) - fputc('\t', stderr); + dbg("\t"); - fprintf(stderr, "\tadding constant %s to %s (%lld)\n", id->s, v->s, - t->u.c.v); + dbg("\tadding constant %s to %s (%lld)\n", id->s, v->s, t->u.c.v); reset(p); return 1; } @@ -232,9 +231,9 @@ static int cnum(const struct lex *l, struct prv *p) tdc->neg = sign; for (size_t i = 0; i < p->block; i++) - fputc('\t', stderr); + dbg("\t"); - fprintf(stderr, "\tadding constant %s to %s\n", id->s, num->s); + dbg("\tadding constant %s to %s\n", id->s, num->s); if (bump(id, nt, p)) return -1; @@ -291,16 +290,16 @@ static int c(const struct lex *l, struct prv *p) nt->u.c.uv = tdc->u.uv; for (size_t i = 0; i < p->block; i++) - fputc('\t', stderr); + dbg("\t"); - fprintf(stderr, "\tadding constant %s to ", id->s); + dbg("\tadding constant %s to ", id->s); if (tdc->neg) - fprintf(stderr, "%lld", tdc->u.v); + dbg("%lld", tdc->u.v); else - fprintf(stderr, "%llu", tdc->u.uv); + dbg("%llu", tdc->u.uv); - fputc('\n', stderr); + dbg("\n", stderr); if (bump(id, &td->types[td->ntypes++], p)) return -1; @@ -341,7 +340,7 @@ static int p(const struct lex *l, struct prv *p) td->types = types; p->proto = pt; - fprintf(stderr, "\tadding prototype %s\n", p->stk->s); + dbg("\tadding prototype %s\n", p->stk->s); return div_p(l, p); failure: @@ -365,8 +364,7 @@ static int ends(struct type *t) t->align = st->entries->t->align; t->sz = e->offset + e->t->sz; t->sz += t->align - (t->sz % t->align); - fprintf(stderr, "\tadding struct %s, size %zu, align %zu\n", t->tk->s, - t->sz, t->align); + dbg("\tadding struct %s, size %zu, align %zu\n", t->tk->s, t->sz, t->align); return 0; } @@ -514,8 +512,7 @@ static int tt(const struct lex *l, struct prv *p, const struct type *t) .u.t.alias = t }; - fprintf(stderr, "\tadding %s (%d:%d) alias %s\n", id->s, loc->line, - loc->col, s); + dbg("\tadding %s (%d:%d) alias %s\n", id->s, loc->line, loc->col, s); reset(p); p->id = NULL; ret = 1; diff --git a/src/prc1/tmp.c b/src/prc1/tmp.c index c93443f..a08716b 100644 --- a/src/prc1/tmp.c +++ b/src/prc1/tmp.c @@ -1,4 +1,5 @@ #include "tmp.h" +#include "dbg.h" #include "type.h" #include <stddef.h> #include <stdio.h> @@ -58,7 +59,7 @@ const struct stentry *tmp_create(struct fn *fn, const struct type *t) break; } - fprintf(stderr, "\tcreating temporary variable %s, type %s\n", s, tname); + dbg("\tcreating temporary variable %s, type %s\n", s, tname); free(tname); return &tmp->e; diff --git a/src/prc1/warn.c b/src/prc1/warn.c index 456ce79..93635db 100644 --- a/src/prc1/warn.c +++ b/src/prc1/warn.c @@ -1,5 +1,6 @@ #include "warn.h" #include "cgen.h" +#include "dbg.h" #include "parse.h" #include "prv.h" #include "stmt.h" @@ -29,8 +30,8 @@ static int finalize(const struct lex *l, const struct prv *p, .u.warn.p = *pr }; - fprintf(stderr, "\t\tadding warn statement with %zu entries%s\n", - pr->nentries, pr->println ? "" : ", no lf"); + dbg("\t\tadding warn statement with %zu entries%s\n", pr->nentries, + pr->println ? "" : ", no lf"); return 0; } |
