commit 8d7db8a2634f30dd81192877fe456ad5ec77ea65 Author: Thomas Jensen Date: Thu Mar 18 15:08:57 1999 +0000 Initial revision diff --git a/boxes-config b/boxes-config new file mode 100644 index 0000000..6bd5d60 --- /dev/null +++ b/boxes-config @@ -0,0 +1,312 @@ +# boxes-config +# Thomas Jensen +# Date created: March 17, 1999 (Wednesday, 17:02h) + + +BOX parchment + +author "Test Person " +created "March 12, 1999 (Friday, 17:05h)" +revision "1.0" +revdate "March 12, 1999 (Friday, 17:05h)" +escaped "aaa\"bbb\\\"ccc#" # der String aaa"bbb\"ccc# +#escaped2 "aaa\\"bbb" # unterminated + +sample { + ________________________ + /\\ \\ + \\_| | + | | + | | + | ____________________|_ + \\_/_____________________/ +} # double all backslashes in sample + +offsets { + nw-nnw 0 # 0 heißt immer "außen bündig" + nnw-n 0 # Verschiebung von n gegenüber nnw + n-nne 0 + nne-ne 0 + ne-ene 0 + ene-e 0 + e-ese 0 + ese-se -1 # um 1 weiter nach außen als ese + se-sse 0 + sse-s 0 + s-ssw 0 + ssw-sw 0 # Man sollte wohl 0 als Default erlauben + sw-wsw 0 + wsw-w 0 + w-wnw 0 + wnw-nw -2 +} + +shapes { + nw (" __", "/\\ ", "\\_|") + nnw () + n ("_") + nne () + ne (" ", "\\ ") + ene () + e ("|") + ese () + se ("|_","_/") + sse () + s ("_","_") + ssw () + sw (" \\_/") + wsw () + w ("|") + wnw () # Man sollte wohl () als Default erlauben +} + +elastic (n,e,s,w) # Da muß nur pro Seite mind. einer sein + +END parchment + + +# ============================================================================ + + +BOX columns + +revision "1.0" +revdate "March 17, 1999 (Wednesday, 15:27h)" +created "March 17, 1999 (Wednesday, 15:27h)" + +sample { + __^__ __^__ + ( ___ )---------------( ___ ) + | / | | \\ | + | / | | \\ | + | / | | \\ | + |___| |___| + (_____)---------------(_____) +} + +shapes { + nw (" __^__ ", "( ___ )") + nnw ("-") + ne (" __^__ ", "( ___ )") + e ("| / |") + w ("| \\ |") + wsw ("|___|") + ese ("|___|") + sw ("(_____)") + s ("-") + se ("(_____)") +} + +offsets { + nw-nnw 1 + nne-ne -1 + ne-ene 1 + ese-se -1 + sw-wsw 1 +} + +elastic (nnw, e, w, s) + +END columns + + +# ============================================================================ + + +BOX whirly + +created "March 17, 1999 (Wednesday, 15:40h)" +revdate "March 17, 1999 (Wednesday, 15:40h)" +revision "1.0" + +sample { + .+"+.+"+.+"+.+"+.+"+.+"+.+"+.+"+.+"+.+"+.+"+.+"+.+"+.+"+.+"+. + ( ) + ) ( + ( ) + "+.+"+.+"+.+"+.+"+.+"+.+"+.+"+.+"+.+"+.+"+.+"+.+"+.+"+.+"+.+" +} + +shapes { + nw (" .") + n ("+\"+.") + wnw ("(") + w (" )", "( ") + ene (")") + e ("( ", " )") + sw (" \"") + s ("+.+\"") +} + +offsets { + ne-ene -1 + ese-se 1 +} + +elastic (n, w, s, e) + +END whirly + + +# ============================================================================ + + +BOX scroll + +revision "1.0" +revdate "March 17, 1999 (Wednesday, 17:04h)" +created "March 17, 1999 (Wednesday, 17:04h)" + +sample { + / ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ \\ + | / ~ \\ / ~ \\ | + |\\ \\ | | / /| + | \\ /| |\\ / | + | ~~ | | ~~ | + | | | | + | | | | + | | | | + | | | | + | | | | + \\ |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| / + \\ / \\ / + ~~ ~~ +} + +shapes { + nw ("/ ~~~~~~~") + n ("~") + ne ("~~~~~~~ \\") + ene (" / ~ \\ |", "| / /|", "|\\ / |", "| ~~ |") + e ("| |") + se ("| /", " \\ / ", " ~~ ") + s ("~") + sw (" \\ |", " \\ / ", " ~~ ") +} + +offsets { + ne-ene -1 + ese-se 1 + sse-s 2 + ssw-sw -2 + wnw-nw 1 +} + +eLAStic (n, s, e, w) + +END scroll + + +# ============================================================================ + + +BOX simple + +author "Thomas Jensen " +revision "1.0" +revdate "March 18, 1999 (Thursday, 15:24h)" +created "March 18, 1999 (Thursday, 15:24h)" + +sample { + ************* + * * + * * + ************* +} + +shapes { + nw ("*") + se ("*") +} + +elastic (ne,sw) + +END simple + + +# ============================================================================ + + +BOX c + +author "Thomas Jensen " +revision "1.0" +revdate "March 18, 1999 (Thursday, 15:25h)" +created "March 18, 1999 (Thursday, 15:25h)" + +sample { + /*************/ + /* */ + /* */ + /*************/ +} + +shapes { + n ("*") # ambiguous corners! + e ("*/") + s ("*") + w ("/*") +} + +elastic (n,e,s,w) + +END c + + +# ============================================================================ + + +BOX html + +author "Thomas Jensen " +revision "1.0" +revdate "March 18, 1999 (Thursday, 15:26h)" +created "March 18, 1999 (Thursday, 15:26h)" + +sample { + + + + + +} + +shapes { + n ("-") + nw ("") + s ("-") +} + +elastic (nw,n,se,s) + +END html + + +# ============================================================================ + + +BOX shell + +author "Thomas Jensen " +revision "1.0" +revdate "March 18, 1999 (Thursday, 15:27h)" +created "March 18, 1999 (Thursday, 15:27h)" + +sample { + ############# + # # + # # + ############# +} + +shapes { + nw ("#") + se ("#") +} + +elastic (ne,sw) + +END shell + +#EOF vim: set ai sw=4: diff --git a/src/Makefile b/src/Makefile new file mode 100644 index 0000000..d9823b4 --- /dev/null +++ b/src/Makefile @@ -0,0 +1,34 @@ +# Makefile for boxes + +LEX = flex +YACC = yacc +CC = gcc +CFLAGS = -O + + +boxes: y.tab.o lex.yy.o boxes.o + $(CC) $(CFLAGS) -o boxes y.tab.o lex.yy.o boxes.o -ll + +lex.yy.o: lex.yy.c y.tab.h + +y.tab.o: y.tab.c y.tab.h + +boxes.o: boxes.c boxes.h + +y.tab.c y.tab.h: parser.y boxes.h + $(YACC) -d parser.y + +lex.yy.c: lexer.l boxes.h + $(LEX) -i lexer.l + +clean: + rm -f lex.yy.c y.tab.c y.tab.h + rm -f lex.yy.o y.tab.o + rm -f boxes + +love: + @echo "Not in front of the kids, honey!" + + + +#EOF diff --git a/src/boxes.c b/src/boxes.c new file mode 100644 index 0000000..5a8f202 --- /dev/null +++ b/src/boxes.c @@ -0,0 +1,229 @@ + +#include +#include +#include +#include +#include "boxes.h" + + +extern char *optarg; /* for getopt() */ +extern int optind, opterr, optopt; + +extern FILE *yyin; /* lex input file */ + +char *yyfilename = NULL; /* file name of config file used */ + +design_t *designs = NULL; /* available box designs */ + +int design_idx = 0; /* anz_designs-1 */ +int anz_designs = 0; /* no of designs after parsing */ + + +struct { /* command line options */ + int l; /* list available designs */ +} opt; + + + + +int yyerror (const char *fmt, ...) +{ + va_list ap; + char buf[1024]; + + va_start (ap, fmt); + snprintf (buf, 1024-1, "%s: %s: line %d: ", PROJECT, + yyfilename? yyfilename: "(null)", yylineno); + vsnprintf (buf+strlen(buf), 1024-strlen(buf)-1, fmt, ap); + strcat (buf, "\n"); + (void) fprintf (stderr, buf); + va_end (ap); + + return 0; +} + + + +void usage (FILE *st) +{ + fprintf (st, "Usage: %s [options] [infile [outfile]]\n", PROJECT); + fprintf (st, " -c box exchange current box for new box\n"); + fprintf (st, " -f file use only file as configuration file\n"); + fprintf (st, " -h usage information\n"); + fprintf (st, " -l generate listing of available box designs w/ samples\n"); + fprintf (st, " -r repair broken box\n"); + fprintf (st, " -s wxh resize box to width w and/or height h\n"); + fprintf (st, " -v print version information\n"); + fprintf (st, " -x remove box from text\n"); +} + + + +int process_commandline (int argc, char *argv[]) +{ + int oc; /* option character */ + FILE *f; /* potential input file */ + + memset (&opt, 0, sizeof(opt)); + yyin = stdin; + + do { + oc = getopt (argc, argv, "f:hlv"); + + switch (oc) { + + case 'f': + /* + * Input File + */ + f = fopen (optarg, "r"); + if (f == NULL) { + fprintf (stderr, "%s: Couldn\'t open config file \'%s\' " + "for input.\n", PROJECT, optarg); + return 1; + } + yyfilename = (char *) strdup (optarg); + yyin = f; + break; + + case 'h': + /* + * Display usage information and terminate + */ + printf ("%s - draws boxes around your text\n", PROJECT); + printf (" (c) Thomas Jensen \n"); + printf (" Web page: http://home.pages.de/~jensen/%s/\n", PROJECT); + usage (stdout); + return 42; + + case 'l': + /* + * List available box styles + */ + opt.l = 1; + break; + + case 'v': + /* + * Print version number + */ + printf ("%s version %s\n", PROJECT, VERSION); + return 42; + + case ':': case '?': + /* + * Missing argument or illegal option - do nothing else + */ + return 1; + + case EOF: + /* + * End of list, do nothing more + */ + break; + + default: /* This case must never be */ + fprintf (stderr, "%s: Uh-oh! This should have been " + "unreachable code. %%-)\n", PROJECT); + return 1; + } + } while (oc != EOF); + + if (yyin == stdin) { + fprintf (stderr, "%s: Could not find config file\n", PROJECT); + return 1; + } + + return 0; +} + + + +int style_sort (const void *p1, const void *p2) +{ + return strcasecmp ((const char *) ((*((design_t **) p1))->name), + (const char *) ((*((design_t **) p2))->name)); +} + +int list_styles() +{ + int i; + design_t **list; + + list = (design_t **) calloc (design_idx+1, sizeof(design_t *)); + if (list == NULL) return 1; + + for (i=0; i<=design_idx; ++i) + list[i] = &(designs[i]); + qsort (list, design_idx+1, sizeof(design_t *), style_sort); + + printf ("Available Styles:\n"); + printf ("-----------------\n\n"); + for (i=0; i<=design_idx; ++i) + printf ("%s (%s):\n\n%s\n\n", list[i]->name, + list[i]->author? list[i]->author: "unknown artist", + list[i]->sample); + + free (list); + list = NULL; + + return 0; +} + + + +int main (int argc, char *argv[]) +{ + extern int yyparse(); + int rc; /* general return code */ + design_t *tmp; + + rc = process_commandline (argc, argv); + if (rc == 42) exit (EXIT_SUCCESS); + if (rc) exit (EXIT_FAILURE); + + setlocale (LC_ALL, ""); /* muß des sein? TODO */ + + designs = (design_t *) calloc (1, sizeof(design_t)); + if (designs == NULL) { + perror (PROJECT); + exit (EXIT_FAILURE); + } + + /* + * If the following parser is one created by lex, the application must + * be careful to ensure that LC_CTYPE and LC_COLLATE are set to the + * POSIX locale. + */ + rc = yyparse(); + if (rc) exit (EXIT_FAILURE); + if (yyfilename) { + free (yyfilename); + yyfilename = NULL; + } + --design_idx; + tmp = (design_t *) realloc (designs, (design_idx+1)*sizeof(design_t)); + if (tmp) { + designs = tmp; /* yyparse() allocates space */ + } /* for one design too much */ + else { + perror (PROJECT); + exit (EXIT_FAILURE); + } + anz_designs = design_idx + 1; + + + if (opt.l) { + rc = list_styles(); + if (rc) { + perror (PROJECT); + exit (EXIT_FAILURE); + } + exit (EXIT_SUCCESS); + } + + + return EXIT_SUCCESS; +} + +/*EOF*/ /* vim: set sw=4: */ diff --git a/src/boxes.h.in b/src/boxes.h.in new file mode 100644 index 0000000..845afb0 --- /dev/null +++ b/src/boxes.h.in @@ -0,0 +1,73 @@ + + +#ifdef DEBUG +#ifndef DEBUG_STUFF +#define DEBUG_STUFF + +char *shape_name[] = { + "NW", "NNW", "N", "NNE", "NE", "ENE", "E", "ESE", + "SE", "SSE", "S", "SSW", "SW", "WSW", "W", "WNW" +}; + +char *ofs_name[] = { + "NW_NNW", "NNW_N", "N_NNE", "NNE_NE", "NE_ENE", "ENE_E", "E_ESE", "ESE_SE", + "SE_SSE", "SSE_S", "S_SSW", "SSW_SW", "SW_WSW", "WSW_W", "W_WNW", "WNW_NW" +}; + +#endif /* DEBUG_STUFF */ +#endif /* DEBUG */ + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ + +#ifndef BOXES_H +#define BOXES_H + +#define PROJECT "boxes" /* name of program */ +#define VERSION "1.0" /* current release of project */ + +#define ANZ_OFFSETS 16 + +typedef enum { + NW_NNW, NNW_N, N_NNE, NNE_NE, NE_ENE, ENE_E, E_ESE, ESE_SE, + SE_SSE, SSE_S, S_SSW, SSW_SW, SW_WSW, WSW_W, W_WNW, WNW_NW +} offset_t; + + +#define ANZ_SHAPES 16 + +typedef enum { + NW, NNW, N, NNE, NE, ENE, E, ESE, SE, SSE, S, SSW, SW, WSW, W, WNW +} shape_t; + + +typedef struct { + char **chars; + int height; + int width; +} sentry_t; + +typedef struct { + char *name; + char *author; + char *created; + char *revision; + char *revdate; + char *sample; + sentry_t shape[ANZ_SHAPES]; + int offset[ANZ_OFFSETS]; + shape_t elastic[ANZ_SHAPES]; + int anz_elastic; +} design_t; + +extern design_t *designs; +extern int design_idx; + +extern int yylineno; + +int yyerror (const char *fmt, ...); + + +#endif /* BOXES_H */ + + +/*EOF*/ /* vim: set cindent sw=4: */ diff --git a/src/lexer.l b/src/lexer.l new file mode 100644 index 0000000..b43b122 --- /dev/null +++ b/src/lexer.l @@ -0,0 +1,260 @@ +%{ +/* + * lexer.l + * + * flex lexical analyzer for boxes configuration files + * + * Thomas Jensen + * Date created: March 15, 1999 (Monday, 17:16h) + */ + +/* #define DEBUG */ + +#include +#include "boxes.h" +#include "y.tab.h" + +int yylineno = 1; + +%} + +%x SAMPLE1 +%x SAMPLE2 +%s SHAPES +%s OFFSETS +%s ELASTIC + +%% + +[\r\t ]+ /* ignore whitespace */ + +\n yylineno++; + +#[^#].*$ { + /* ignore comments */ + #ifdef DEBUG + fprintf (stderr, "\nCOMMENT: %s", yytext+1); + #endif +} + +\"[^"\n]*$ { + yyerror ("Unterminated String at %s", yytext); + exit (EXIT_FAILURE); +} + +\"[^"\n]*\" { + int bidx = yyleng-2; /* backslash index */ + + while (yytext[bidx] == '\\') bidx--; + + if ((yyleng-2-bidx) % 2) { + yyless (yyleng-1); /* give back last quote */ + yymore(); /* append next string */ + } + else { + for (bidx=0; bidx\{ { + #ifdef DEBUG + fprintf (stderr, "\n SYMBOL: \'%c\' -- STATE SAMPLE2", yytext[0]); + #endif + BEGIN SAMPLE2; + return yytext[0]; +} + +[^{]+ { + yyerror ("Syntax Error at %s", yytext); + exit (EXIT_FAILURE); +} + +\n { + ++yylineno; + if (yyleng > 1) + yymore(); +} + +\} { + int bidx = yyleng-2; /* backslash index */ + + if (bidx >= 0) { + while (bidx >= 0 && yytext[bidx] == '\\') bidx--; + + if ((yyleng-2-bidx) % 2) { /* odd number of backslashes */ + yymore(); /* append next string */ + } + else { + yyless (yyleng-1); /* have him recognize '}' symbol */ + + for (bidx=yyleng-1; yytext[bidx]=='\n'; --bidx) { + yytext[bidx] = '\0'; /* remove trailing newlines */ + --yyleng; + } + for (bidx=0; bidx. { + yymore(); +} + +Offsets { + #ifdef DEBUG + fprintf (stderr, "\nYOFFSET: %s -- STATE OFFSETS", yytext); + #endif + BEGIN OFFSETS; + return YOFFSETS; +} + +elastic { + #ifdef DEBUG + fprintf (stderr, "\nYELASTC: %s -- STATE ELASTIC", yytext); + #endif + BEGIN ELASTIC; + return YELASTIC; +} + +Shapes { + #ifdef DEBUG + fprintf (stderr, "\nYSHAPES: %s -- STATE SHAPES", yytext); + #endif + BEGIN SHAPES; + return YSHAPES; +} + +nw-nnw { yylval.offset = NW_NNW; return OFFSET; } +nnw-n { yylval.offset = NNW_N; return OFFSET; } +n-nne { yylval.offset = N_NNE; return OFFSET; } +nne-ne { yylval.offset = NNE_NE; return OFFSET; } +ne-ene { yylval.offset = NE_ENE; return OFFSET; } +ene-e { yylval.offset = ENE_E; return OFFSET; } +e-ese { yylval.offset = E_ESE; return OFFSET; } +ese-se { yylval.offset = ESE_SE; return OFFSET; } +se-sse { yylval.offset = SE_SSE; return OFFSET; } +sse-s { yylval.offset = SSE_S; return OFFSET; } +s-ssw { yylval.offset = S_SSW; return OFFSET; } +ssw-sw { yylval.offset = SSW_SW; return OFFSET; } +sw-wsw { yylval.offset = SW_WSW; return OFFSET; } +wsw-w { yylval.offset = WSW_W; return OFFSET; } +w-wnw { yylval.offset = W_WNW; return OFFSET; } +wnw-nw { yylval.offset = WNW_NW; return OFFSET; } + +nw { yylval.shape = NW; return SHAPE; } +nnw { yylval.shape = NNW; return SHAPE; } +n { yylval.shape = N; return SHAPE; } +nne { yylval.shape = NNE; return SHAPE; } +ne { yylval.shape = NE; return SHAPE; } +ene { yylval.shape = ENE; return SHAPE; } +e { yylval.shape = E; return SHAPE; } +ese { yylval.shape = ESE; return SHAPE; } +se { yylval.shape = SE; return SHAPE; } +sse { yylval.shape = SSE; return SHAPE; } +s { yylval.shape = S; return SHAPE; } +ssw { yylval.shape = SSW; return SHAPE; } +sw { yylval.shape = SW; return SHAPE; } +wsw { yylval.shape = WSW; return SHAPE; } +w { yylval.shape = W; return SHAPE; } +wnw { yylval.shape = WNW; return SHAPE; } + +\) { + #ifdef DEBUG + fprintf (stderr, "\n SYMBOL: \'%c\' -- STATE INITIAL", yytext[0]); + #endif + BEGIN INITIAL; + return yytext[0]; +} + +\} { + #ifdef DEBUG + fprintf (stderr, "\n SYMBOL: \'%c\' -- STATE INITIAL", yytext[0]); + #endif + BEGIN INITIAL; + return yytext[0]; +} + +BOX|revision|author|created|revdate|END { + /* + * general key words followed by a string + */ + #ifdef DEBUG + fprintf (stderr, "\nKEYWORD: %s", yytext); + #endif + yylval.s = (char *) strdup (yytext); + return KEYWORD; +} + +[a-zA-ZäöüÄÖÜ][a-zA-Z0-9\-_üäöÜÄÖß]* { + #ifdef DEBUG + fprintf (stderr, "\n WORD: %s", yytext); + #endif + yylval.s = (char *) strdup (yytext); + return WORD; +} + +[,(){}] { + #ifdef DEBUG + fprintf (stderr, "\n SYMBOL: \'%c\'", yytext[0]); + #endif + return yytext[0]; +} + +\-?[0-9]+ { + #ifdef DEBUG + fprintf (stderr, "\n NUMBER: %s", yytext); + #endif + yylval.num = atoi (yytext); + return NUMBER; +} + +. { + yyerror ("Unrecognized input at %s", yytext); + exit (EXIT_FAILURE); +} + + +%% + + +/*EOF*/ /* vim: set cindent sw=4: */ diff --git a/src/parser.y b/src/parser.y new file mode 100644 index 0000000..182a2c5 --- /dev/null +++ b/src/parser.y @@ -0,0 +1,361 @@ +%{ +/* + * parser.y + * + * yacc parser for boxes configuration files + * + * Thomas Jensen + * Date created: March 16, 1999 (Tuesday, 17:17h) + */ + +#define DEBUG + +#include +#include +#include +#include "boxes.h" + + +static int pflicht = 0; +static int time_for_corner_check = 0; + +int corner_ambiguity() +/* + * Checks for ambiguity in corner specification using elastic and shape + * data. It must be clear which shape to use for each corner of the box. + * +* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + */ +{ + /* TODO */ + + return 0; /* no ambiguity */ +} + +%} + +%union { + int num; + char *s; + shape_t shape; + offset_t offset; + sentry_t sentry; +} + +%token YSHAPES YOFFSETS YELASTIC YSAMPLE +%token KEYWORD +%token WORD +%token STRING +%token NUMBER +%token SHAPE +%token OFFSET + +%type slist +%type slist_entries + +%% + +config_file: config_file design | design ; + +design: KEYWORD WORD layout KEYWORD WORD + { + design_t *tmp; + + #ifdef DEBUG + fprintf (stderr, "--------- ADDING DESIGN \"%s\".\n", $2); + #endif + + if (strcasecmp ($2, $5)) { + yyerror ("Box design name differs at BOX and END"); + YYABORT; + } + if (strcasecmp ($1, "BOX")) { + yyerror ("Box design must start with \"BOX boxname\""); + YYABORT; + } + if (strcasecmp ($4, "END")) { + yyerror ("Box design must end with \"END boxname\""); + YYABORT; + } + if (pflicht < 3) { + yyerror ("Entries SAMPLE, SHAPES, and ELASTIC are mandatory"); + YYABORT; + } + + designs[design_idx].name = (char *) strdup ($2); + pflicht = 0; + + ++design_idx; + tmp = (design_t *) realloc (designs, (design_idx+1)*sizeof(design_t)); + if (tmp) { + designs = tmp; + memset (&(designs[design_idx]), 0, sizeof(design_t)); + } + else { + perror ("boxes"); + YYABORT; + } + } +; + +layout: layout entry | layout block | entry | block ; + +entry: KEYWORD STRING + { + #ifdef DEBUG + fprintf (stderr, "entry rule fulfilled [%s = %s]\n", $1, $2); + #endif + if (strcasecmp ($1, "author") == 0) { + designs[design_idx].author = (char *) strdup ($2); + } + else if (strcasecmp ($1, "revision") == 0) { + designs[design_idx].revision = (char *) strdup ($2); + } + else if (strcasecmp ($1, "created") == 0) { + designs[design_idx].created = (char *) strdup ($2); + } + else if (strcasecmp ($1, "revdate") == 0) { + designs[design_idx].revdate = (char *) strdup ($2); + } + else { + fprintf (stderr, "boxes: Internal parser error (unrecognized: %s)" + " in line %d of %s.\n", $1, __LINE__, __FILE__); + YYABORT; + } + } +| WORD STRING + { + fprintf (stderr, "boxes: Discarding entry [%s = %s].\n", $1, $2); + } +; + + +block: YSAMPLE '{' STRING '}' + { + #ifdef DEBUG + fprintf (stderr, "SAMPLE block rule fulfilled\n"); + #endif + + designs[design_idx].sample = (char *) strdup ($3); + ++pflicht; + } + +| YSHAPES '{' the_shapes '}' + { + /* + * Check that at least one shape per side is specified + */ + if (!((designs[design_idx].shape[NW].chars + || designs[design_idx].shape[NNW].chars + || designs[design_idx].shape[N].chars + || designs[design_idx].shape[NNE].chars + || designs[design_idx].shape[NE].chars) + && (designs[design_idx].shape[NE].chars + || designs[design_idx].shape[ENE].chars + || designs[design_idx].shape[E].chars + || designs[design_idx].shape[ESE].chars + || designs[design_idx].shape[SE].chars) + && (designs[design_idx].shape[SW].chars + || designs[design_idx].shape[SSW].chars + || designs[design_idx].shape[S].chars + || designs[design_idx].shape[SSE].chars + || designs[design_idx].shape[SE].chars) + && (designs[design_idx].shape[NW].chars + || designs[design_idx].shape[WNW].chars + || designs[design_idx].shape[W].chars + || designs[design_idx].shape[WSW].chars + || designs[design_idx].shape[SW].chars))) + { + yyerror ("Must specify at least one shape per side"); + YYABORT; + } + ++pflicht; + ++time_for_corner_check; + if (time_for_corner_check > 1 && corner_ambiguity()) { + yyerror ("Ambiguous Shape/Elastic specification for corners"); + YYABORT; + } + } + +| YELASTIC elist + { + int i; + int ok[4] = {0, 0, 0, 0}; + + /* + * Check that at least one shape per side is elastic + */ + for (i=0; i 1 && corner_ambiguity()) { + yyerror ("Ambiguous Shape/Elastic specification for corners"); + YYABORT; + } + } + +| YOFFSETS '{' the_offsets '}' +; + +the_shapes: the_shapes SHAPE slist + { + #ifdef DEBUG + fprintf (stderr, "Adding shape spec for \'%s\' (width %d " + "height %d)\n", shape_name[$2], $3.width, $3.height); + #endif + + designs[design_idx].shape[$2] = $3; + } +| SHAPE slist + { + #ifdef DEBUG + fprintf (stderr, "Adding shape spec for \'%s\' (width %d " + "height %d)\n", shape_name[$1], $2.width, $2.height); + #endif + + designs[design_idx].shape[$1] = $2; + } +; + +the_offsets: the_offsets OFFSET NUMBER + { + #ifdef DEBUG + fprintf (stderr, "Setting offset of \'%s\' to %d\n", + ofs_name[$2], $3); + #endif + + designs[design_idx].offset[$2] = $3; + } + +| OFFSET NUMBER + { + #ifdef DEBUG + fprintf (stderr, "Setting offset of \'%s\' to %d\n", + ofs_name[$1], $2); + #endif + + designs[design_idx].offset[$1] = $2; + } +; + +elist: '(' elist_entries ')' ; + +elist_entries: elist_entries ',' SHAPE + { + #ifdef DEBUG + fprintf (stderr, "Marked \'%s\' shape as elastic\n", + shape_name[(int)$3]); + #endif + designs[design_idx].elastic[designs[design_idx].anz_elastic] = $3; + ++(designs[design_idx].anz_elastic); + } +| SHAPE + { + #ifdef DEBUG + fprintf (stderr, "Marked \'%s\' shape as elastic\n", + shape_name[(int)$1]); + #endif + designs[design_idx].elastic[designs[design_idx].anz_elastic] = $1; + ++(designs[design_idx].anz_elastic); + } +; + +slist: '(' slist_entries ')' +{ + $$ = $2; +} +| '(' ')' +{ + $$ = (sentry_t) { NULL, 0, 0 }; +} +; + +slist_entries: slist_entries ',' STRING + { + sentry_t rval = $1; + size_t slen = strlen ($3); + char **tmp; + + #ifdef DEBUG + fprintf (stderr, "Extending a shape entry\n"); + #endif + + if (slen != rval.width) { + yyerror ("All elements of a shape spec must be of equal length"); + YYABORT; + } + + rval.height++; + tmp = (char **) realloc (rval.chars, rval.height*sizeof(char*)); + if (tmp == NULL) { + perror ("boxes: slist_entries11"); + YYABORT; + } + rval.chars = tmp; + rval.chars[rval.height-1] = (char *) strdup ($3); + if (rval.chars[rval.height-1] == NULL) { + perror ("boxes: slist_entries12"); + YYABORT; + } + $$ = rval; + } + +| STRING + { + sentry_t rval; + + #ifdef DEBUG + fprintf (stderr, "Initializing a shape entry with first line\n"); + #endif + + rval.width = strlen ($1); + rval.height = 1; + rval.chars = (char **) malloc (sizeof(char*)); + if (rval.chars == NULL) { + perror ("boxes: slist_entries21"); + YYABORT; + } + rval.chars[0] = (char *) strdup ($1); + if (rval.chars[0] == NULL) { + perror ("boxes: slist_entries22"); + YYABORT; + } + $$ = rval; + } +; + +%% + + +/*EOF*/ /* vim: set sw=4 cindent: */