--- /dev/null
+/*
+ *
+ * Commands ...
+ *
+ * INIT(...) : Set configs. (rowstep, totwidth, stdheight, stdwidth)
+ * SPOS(V,H) : Set current position.
+ *
+ * SCOL : Standard column, for a single column, increment position
+ * NEXT(V,H) : increment postion by standard + (V,H)
+ * COL(K,N) : X,Y position for col K of N (default 1of [same as last])
+ * SS : Standard size of last COL (using number of cols).
+ * ADJ(V,H) : Adjust next COL or SCOL by (V,H)
+ *
+ * CURX(H) : Current Xpos+H
+ * CURY(V) : Current Ypos+V
+ *
+ */
+
+#include <stdio.h>
+
+FILE * ifd;
+FILE * ofd;
+
+char wordbuf[256];
+
+#define T_INIT 100 /* Init the style of the values */
+#define T_SPOS 101 /* Set the current position */
+#define T_SCOL 102 /* Standard column COL(1,1), SS NEXT */
+#define T_NEXT 103 /* Next line */
+#define T_COL 104 /* Multi-column */
+#define T_SS 105 /* Standard Size */
+#define T_ADJ 106 /* Adjust next COL/SCOL */
+#define T_GRID 107 /* */
+#define T_GAP 108 /* */
+
+#define T_CURX 120 /* Current X + offset */
+#define T_CURY 121 /* Current Y + offset */
+
+#define T_SAVEPOSN 122 /* Save current status */
+#define T_RESTOREPOSN 123 /* Restore current status */
+
+
+struct keys {
+ char * name;
+ int token;
+} keywords[] = {
+ {"INIT", T_INIT, },
+ {"SPOS", T_SPOS, },
+ {"SCOL", T_SCOL, },
+ {"NEXT", T_NEXT, },
+ {"COL", T_COL, },
+ {"SS", T_SS, },
+ {"ADJ", T_ADJ, },
+ {"GRID", T_GRID, },
+ {"GAP", T_GAP, },
+ {"CURX", T_CURX, },
+ {"CURY", T_CURY, },
+ {"SAVEPOSN", T_SAVEPOSN, },
+ {"RESTOREPOSN", T_RESTOREPOSN, },
+ {0,0}
+};
+
+struct statbuf {
+ int token;
+
+ int curx;
+ int cury;
+ int cols;
+
+ int con_width;
+ int con_height;
+ int row_step;
+ int tot_width;
+
+ int gutter;
+
+ int vadjust;
+ int hadjust;
+}
+ status, saved_status;
+
+int ar_count, ar_val[10];
+
+main(argc, argv)
+int argc;
+char ** argv;
+{
+ int ch;
+
+ ifd = stdin; ofd = stdout;
+
+ while(!feof(ifd))
+ {
+ if (ferror(ifd))
+ {
+ fprintf(stderr, "Error reading input file\n");
+ exit(1);
+ }
+
+ if (readword() < 0) break;
+
+ if (check_keys() < 0)
+ {
+ fprintf(ofd, "%s", wordbuf);
+ continue;
+ }
+
+ /* To get here we have found one of our keywords, some words will
+ * be followed by an argument.
+ */
+
+ ar_count = 0;
+
+ while((ch = getc(ifd)) != EOF && isspace(ch) && ch != '\n')
+ putc(ch, ofd);
+
+ if (ch == '(' )
+ {
+ for(;;)
+ {
+ ar_val[ar_count++] = get_number();
+
+ while((ch=getc(ifd)) != EOF && isspace(ch)) ;
+ if (ch != ',') break;
+ }
+ if (ch == EOF) break;
+ }
+ else
+ ungetc(ch, ifd);
+
+ /* Ok got args, now doit */
+ execute_command();
+ }
+ exit(0);
+}
+
+/* This is the lexer - not using lex(1) because this will have to
+ * compile under windows.
+ */
+int readword()
+{
+ int ch;
+ char *wp;
+
+try_again:; /* This is for "too big" words and strings. */
+
+ wp=wordbuf;
+
+ /* Find a word ... */
+ while((ch=getc(ifd)) != EOF && !isalpha(ch) && ch != '"')
+ putc(ch, ofd);
+
+ if (ch == '"')
+ {
+ putc(ch, ofd);
+
+ while((ch=getc(ifd)) != EOF && ch != '"')
+ putc(ch, ofd);
+ if (ch != EOF)
+ putc(ch, ofd);
+
+ goto try_again;
+ }
+
+ if (ch == EOF) return -1;
+
+ do
+ {
+ if (wp>=wordbuf+sizeof(wordbuf)-2)
+ {
+ *wp = 0;
+ fprintf(ofd, "%s", wordbuf);
+
+ while(ch!=EOF && isalpha(ch))
+ {
+ putc(ch, ofd);
+ ch=getc(ifd);
+ }
+ ungetc(ch, ifd);
+
+ goto try_again;
+ }
+ *wp++ = ch;
+ ch = getc(ifd);
+ }
+ while(ch != EOF && (isalnum(ch) || ch == '_'));
+ *wp = 0;
+
+ ungetc(ch, ifd);
+ return wp-wordbuf;
+}
+
+int
+get_number()
+{
+ int ch;
+ int sign = 0;
+ int value = 0;
+
+ while((ch=getc(ifd)) != EOF && isspace(ch)) ;
+
+ if( ch == '+' ) { sign=1; ch=getc(ifd); }
+ else if( ch == '-' ) { sign=-1; ch=getc(ifd); }
+
+ while(ch>='0' && ch<='9')
+ {
+ value = value * 10 + ch - '0';
+ ch = getc(ifd);
+ }
+
+ ungetc(ch, ifd);
+ if (sign < 0) value = -value;
+
+ return value;
+}
+
+check_keys()
+{
+ struct keys *p;
+
+ for(p=keywords; p->name; p++)
+ {
+ if (strcmp(wordbuf, p->name) == 0 )
+ {
+ status.token = p->token;
+ return p->token;
+ }
+ }
+ return -1;
+}
+
+execute_command()
+{
+ if (status.cols < 1) status.cols = 1;
+
+ switch(status.token)
+ {
+ case T_INIT:
+ if (ar_count > 0) status.row_step = ar_val[0];
+ if (ar_count > 1) status.tot_width = ar_val[1];
+ if (ar_count > 2) status.con_height = ar_val[2];
+ else status.con_height = status.row_step;
+ if (ar_count > 3) status.con_width = ar_val[3];
+ else status.con_width = status.tot_width;
+
+ status.gutter = ( status.tot_width - status.con_width ) /2;
+ break;
+
+ case T_SPOS:
+ status.cury = status.curx = 0;
+ if (ar_count > 0) status.cury = ar_val[0];
+ if (ar_count > 1) status.curx = ar_val[1];
+ break;
+
+ case T_SCOL:
+ fprintf(ofd, "%d, %d", status.curx + status.hadjust,
+ status.cury + status.vadjust);
+ status.hadjust = status.vadjust = 0;
+
+ fprintf(ofd, ", %d, %d", status.con_width, status.con_height);
+
+ status.cury += status.row_step;
+
+ if (ar_count > 0) status.cury += ar_val[0];
+ if (ar_count > 1) status.curx += ar_val[1];
+ break;
+
+ case T_NEXT:
+ status.cury += status.row_step;
+ if (ar_count > 0) status.cury += ar_val[0];
+ if (ar_count > 1) status.curx += ar_val[1];
+ break;
+
+ case T_COL:
+ {
+ int curcol;
+ int col_pos;
+
+ if (ar_count > 0) curcol = ar_val[0]; else curcol = 1;
+ if (ar_count > 1) status.cols = ar_val[1];
+
+ col_pos = (status.con_width+status.gutter) *(curcol-1) /status.cols;
+
+ fprintf(ofd, "%d, %d",
+ status.curx + status.hadjust + col_pos,
+ status.cury + status.vadjust);
+ status.hadjust = status.vadjust = 0;
+ }
+ break;
+
+ case T_SS:
+ {
+ int wm = 1, hm=1;
+ int width;
+ if (ar_count > 0) wm = ar_val[0];
+ if (ar_count > 1) hm = ar_val[1];
+
+ width = (status.con_width+status.gutter) / status.cols;
+ width *= wm;
+ width -= status.gutter;
+
+ fprintf(ofd, "%d, %d", width, hm*status.con_height);
+ }
+ break;
+
+ case T_ADJ:
+ if (ar_count > 0) status.vadjust = ar_val[0];
+ if (ar_count > 1) status.hadjust = ar_val[0];
+ break;
+
+ case T_GRID:
+ if (ar_count > 0) status.cols = ar_val[0];
+ else status.cols = 1;
+ if (ar_count > 1) status.con_height = ar_val[1];
+ if (ar_count > 2) status.row_step = ar_val[2];
+ break;
+
+ case T_GAP:
+ if (ar_count > 0) status.cury += ar_val[0];
+ else status.cury += 2;
+ break;
+
+ case T_CURX:
+ if (ar_count>0)
+ fprintf(ofd, "%d", status.curx+ar_val[0]);
+ else
+ fprintf(ofd, "%d", status.curx);
+ break;
+ case T_CURY:
+ if (ar_count>0)
+ fprintf(ofd, "%d", status.cury+ar_val[0]);
+ else
+ fprintf(ofd, "%d", status.cury);
+ break;
+
+ case T_SAVEPOSN:
+ saved_status = status;
+ break;
+ case T_RESTOREPOSN:
+ status = saved_status;
+ break;
+ }
+}