Initial revision

This commit is contained in:
Thomas Jensen 1999-03-18 15:08:57 +00:00
commit 8d7db8a263
6 changed files with 1269 additions and 0 deletions

312
boxes-config Normal file
View File

@ -0,0 +1,312 @@
# boxes-config
# Thomas Jensen <tsjensen@stud.informatik.uni-erlangen.de>
# Date created: March 17, 1999 (Wednesday, 17:02h)
BOX parchment
author "Test Person <foo@bar.com>"
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 <tsjensen@stud.informatik.uni-erlangen.de>"
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 <tsjensen@stud.informatik.uni-erlangen.de>"
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 <tsjensen@stud.informatik.uni-erlangen.de>"
revision "1.0"
revdate "March 18, 1999 (Thursday, 15:26h)"
created "March 18, 1999 (Thursday, 15:26h)"
sample {
<!-- ------------------- -->
<!-- -->
<!-- -->
<!-- -->
<!-- ------------------- -->
}
shapes {
n ("-")
nw ("<!-- ")
se (" -->")
s ("-")
}
elastic (nw,n,se,s)
END html
# ============================================================================
BOX shell
author "Thomas Jensen <tsjensen@stud.informatik.uni-erlangen.de>"
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:

34
src/Makefile Normal file
View File

@ -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

229
src/boxes.c Normal file
View File

@ -0,0 +1,229 @@
#include <locale.h>
#include <stdarg.h>
#include <stdlib.h>
#include <stdio.h>
#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 <tsjensen@stud.informatik.uni-erlangen.de>\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: */

73
src/boxes.h.in Normal file
View File

@ -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: */

260
src/lexer.l Normal file
View File

@ -0,0 +1,260 @@
%{
/*
* lexer.l
*
* flex lexical analyzer for boxes configuration files
*
* Thomas Jensen <tsjensen@stud.informatik.uni-erlangen.de>
* Date created: March 15, 1999 (Monday, 17:16h)
*/
/* #define DEBUG */
#include <string.h>
#include "boxes.h"
#include "y.tab.h"
int yylineno = 1;
%}
%x SAMPLE1
%x SAMPLE2
%s SHAPES
%s OFFSETS
%s ELASTIC
%%
<SAMPLE1,SHAPES,OFFSETS,ELASTIC,INITIAL>[\r\t ]+ /* ignore whitespace */
<SAMPLE1,SHAPES,OFFSETS,ELASTIC,INITIAL>\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<yyleng-1; ++bidx) {
if (yytext[bidx] == '\\') {
memmove (yytext+bidx, yytext+bidx+1, yyleng-bidx-1);
yytext[yyleng-1] = '\0';
--yyleng; /* inefficient */
}
}
memmove (yytext, yytext+1, yyleng-1); /* cut quotes */
--yyleng;
yytext[yyleng-1] = '\0';
--yyleng;
#ifdef DEBUG
fprintf (stderr, "\n STRING: \"%s\"", yytext);
#endif
yylval.s = (char *) strdup (yytext);
return STRING;
}
}
Sample {
#ifdef DEBUG
fprintf (stderr, "\n WORD: %s -- STATE SAMPLE1", yytext);
#endif
BEGIN SAMPLE1;
return YSAMPLE;
}
<SAMPLE1>\{ {
#ifdef DEBUG
fprintf (stderr, "\n SYMBOL: \'%c\' -- STATE SAMPLE2", yytext[0]);
#endif
BEGIN SAMPLE2;
return yytext[0];
}
<SAMPLE1>[^{]+ {
yyerror ("Syntax Error at %s", yytext);
exit (EXIT_FAILURE);
}
<SAMPLE2>\n {
++yylineno;
if (yyleng > 1)
yymore();
}
<SAMPLE2>\} {
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<yyleng-1; ++bidx) {
if (yytext[bidx] == '\\') {
memmove (yytext+bidx, yytext+bidx+1, yyleng-bidx-1);
yytext[yyleng-1] = '\0';
--yyleng; /* inefficient */
}
}
BEGIN INITIAL;
#ifdef DEBUG
fprintf (stderr, "\n SAMPLE: %s -- STATE INITIAL", yytext);
#endif
yylval.s = (char *) strdup (yytext);
return STRING;
}
}
else {
yymore();
}
}
<SAMPLE2>. {
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;
}
<OFFSETS>nw-nnw { yylval.offset = NW_NNW; return OFFSET; }
<OFFSETS>nnw-n { yylval.offset = NNW_N; return OFFSET; }
<OFFSETS>n-nne { yylval.offset = N_NNE; return OFFSET; }
<OFFSETS>nne-ne { yylval.offset = NNE_NE; return OFFSET; }
<OFFSETS>ne-ene { yylval.offset = NE_ENE; return OFFSET; }
<OFFSETS>ene-e { yylval.offset = ENE_E; return OFFSET; }
<OFFSETS>e-ese { yylval.offset = E_ESE; return OFFSET; }
<OFFSETS>ese-se { yylval.offset = ESE_SE; return OFFSET; }
<OFFSETS>se-sse { yylval.offset = SE_SSE; return OFFSET; }
<OFFSETS>sse-s { yylval.offset = SSE_S; return OFFSET; }
<OFFSETS>s-ssw { yylval.offset = S_SSW; return OFFSET; }
<OFFSETS>ssw-sw { yylval.offset = SSW_SW; return OFFSET; }
<OFFSETS>sw-wsw { yylval.offset = SW_WSW; return OFFSET; }
<OFFSETS>wsw-w { yylval.offset = WSW_W; return OFFSET; }
<OFFSETS>w-wnw { yylval.offset = W_WNW; return OFFSET; }
<OFFSETS>wnw-nw { yylval.offset = WNW_NW; return OFFSET; }
<SHAPES,ELASTIC>nw { yylval.shape = NW; return SHAPE; }
<SHAPES,ELASTIC>nnw { yylval.shape = NNW; return SHAPE; }
<SHAPES,ELASTIC>n { yylval.shape = N; return SHAPE; }
<SHAPES,ELASTIC>nne { yylval.shape = NNE; return SHAPE; }
<SHAPES,ELASTIC>ne { yylval.shape = NE; return SHAPE; }
<SHAPES,ELASTIC>ene { yylval.shape = ENE; return SHAPE; }
<SHAPES,ELASTIC>e { yylval.shape = E; return SHAPE; }
<SHAPES,ELASTIC>ese { yylval.shape = ESE; return SHAPE; }
<SHAPES,ELASTIC>se { yylval.shape = SE; return SHAPE; }
<SHAPES,ELASTIC>sse { yylval.shape = SSE; return SHAPE; }
<SHAPES,ELASTIC>s { yylval.shape = S; return SHAPE; }
<SHAPES,ELASTIC>ssw { yylval.shape = SSW; return SHAPE; }
<SHAPES,ELASTIC>sw { yylval.shape = SW; return SHAPE; }
<SHAPES,ELASTIC>wsw { yylval.shape = WSW; return SHAPE; }
<SHAPES,ELASTIC>w { yylval.shape = W; return SHAPE; }
<SHAPES,ELASTIC>wnw { yylval.shape = WNW; return SHAPE; }
<ELASTIC>\) {
#ifdef DEBUG
fprintf (stderr, "\n SYMBOL: \'%c\' -- STATE INITIAL", yytext[0]);
#endif
BEGIN INITIAL;
return yytext[0];
}
<SHAPES,OFFSETS>\} {
#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: */

361
src/parser.y Normal file
View File

@ -0,0 +1,361 @@
%{
/*
* parser.y
*
* yacc parser for boxes configuration files
*
* Thomas Jensen <tsjensen@stud.informatik.uni-erlangen.de>
* Date created: March 16, 1999 (Tuesday, 17:17h)
*/
#define DEBUG
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#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 <s> KEYWORD
%token <s> WORD
%token <s> STRING
%token <num> NUMBER
%token <shape> SHAPE
%token <offset> OFFSET
%type <sentry> slist
%type <sentry> 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<designs[design_idx].anz_elastic; ++i) {
if (designs[design_idx].elastic[i] == NW
|| designs[design_idx].elastic[i] == NNW
|| designs[design_idx].elastic[i] == N
|| designs[design_idx].elastic[i] == NNE
|| designs[design_idx].elastic[i] == NE)
++ok[0];
if (designs[design_idx].elastic[i] == NE
|| designs[design_idx].elastic[i] == ENE
|| designs[design_idx].elastic[i] == E
|| designs[design_idx].elastic[i] == ESE
|| designs[design_idx].elastic[i] == SE)
++ok[1];
if (designs[design_idx].elastic[i] == SW
|| designs[design_idx].elastic[i] == SSW
|| designs[design_idx].elastic[i] == S
|| designs[design_idx].elastic[i] == SSE
|| designs[design_idx].elastic[i] == SE)
++ok[2];
if (designs[design_idx].elastic[i] == NW
|| designs[design_idx].elastic[i] == WNW
|| designs[design_idx].elastic[i] == W
|| designs[design_idx].elastic[i] == WSW
|| designs[design_idx].elastic[i] == SW)
++ok[3];
}
for (i=0; i<4; ++i) {
if (!ok[i]) {
yyerror ("At least one shape per side must be elastic");
YYABORT;
}
}
++pflicht;
++time_for_corner_check;
if (time_for_corner_check > 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: */