mirror of
https://github.com/ascii-boxes/boxes.git
synced 2025-06-19 08:16:45 +02:00
Initial revision
This commit is contained in:
commit
8d7db8a263
312
boxes-config
Normal file
312
boxes-config
Normal 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
34
src/Makefile
Normal 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
229
src/boxes.c
Normal 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
73
src/boxes.h.in
Normal 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
260
src/lexer.l
Normal 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
361
src/parser.y
Normal 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: */
|
Loading…
x
Reference in New Issue
Block a user