commit 6fff651
Emilia Smólska
·
2026-06-20 11:38:20 +0000 UTC
parent 6fff651
foo
5 files changed,
+273,
-0
+3,
-0
1@@ -0,0 +1,3 @@
2+dice
3+*.o
4+*.core
A
Makefile
+36,
-0
1@@ -0,0 +1,36 @@
2+.POSIX:
3+.SUFFIXES:
4+
5+CC=cc
6+CFLAGS=-g
7+LDFLAGS=-Wl,-w
8+LDLIBS=
9+STDCFLAGS=-std=c23
10+WCFLAGS=-Wall -Wextra -Wpedantic
11+
12+PREFIX=/usr/local
13+BINDIR=${DESTDIR}${PREFIX}/bin
14+MANDIR=${DESTDIR}${PREFIX}/man
15+MAN1=${MANDIR}/man1
16+
17+PROG=dice
18+MAN=dice.1
19+OBJS=dice.o
20+
21+all: ${PROG}
22+
23+${PROG}: ${OBJS}
24+ ${CC} ${LDFLAGS} -o ${PROG} ${OBJS} ${LDLIBS}
25+
26+.SUFFIXES: .c .o
27+.c.o:
28+ ${CC} ${CFLAGS} ${STDCFLAGS} ${WCFLAGS} -c -o $@ $<
29+
30+${OBJS}: mac.h
31+
32+clean:
33+ rm -f ${PROG} *.o *.core
34+
35+install: all
36+ cp ${PROG} ${BINDIR}/
37+ cp ${MAN} ${MAN1}/
A
dice.1
+40,
-0
1@@ -0,0 +1,40 @@
2+.Dd $Mdocdate$
3+.Dt DICE 1
4+.Os
5+.Sh NAME
6+.Nm dice
7+.Nd dice roller and coin flipper
8+.Sh SYNOPSIS
9+.Nm
10+.Op Fl csq
11+.Op Ar expr
12+.Sh DESCRIPTION
13+The
14+.Nm
15+utility displays pseudorandom results of specified dice roll or coinflip
16+expressions. It accepts the following flags:
17+.Bl -tag -width Ds
18+.It Fl c
19+Flip a coin, displaying
20+.Dq heads
21+or
22+.Dq tails .
23+.It Fl s
24+Parse a line read from standard input instead of
25+.Ar expr .
26+.It Fl q
27+Don't display
28+.Ar expr
29+followed by an equals sign before the result.
30+.El
31+If neither
32+.Fl c
33+or
34+.Fl s
35+are specified,
36+.Ar expr
37+is a required argument.
38+.Sh EXIT STATUS
39+.Ex -std
40+.Sh SEE ALSO
41+.Xr random 6
A
dice.c
+135,
-0
1@@ -0,0 +1,135 @@
2+/*
3+ * Public domain software
4+ * Dedicated to Stephen Bourne
5+ */
6+
7+#include <stdarg.h>
8+#include <stdio.h>
9+#include <stdlib.h>
10+#include <string.h>
11+#include <time.h>
12+#include <unistd.h>
13+
14+#include "mac.h"
15+
16+TYPE STRUCT DICE
17+{
18+ INT ndic;
19+ INT nsid;
20+ CONST STRUCT DICE *next;
21+} DICE;
22+
23+STATIC STRING argv0;
24+STATIC BOOL cflag,sflag,qflag;
25+
26+NORETURN STATIC VOID usage();
27+NORETURN STATIC VOID error(STRING, ...);
28+STATIC VOID initrand();
29+STATIC VOID initargv0(STRING);
30+STATIC CONST DICE *parsedice(STRING);
31+STATIC STRING getlin();
32+STATIC INT rolldice(CONST DICE *);
33+STATIC VOID coinflip();
34+STATIC VOID *xmalloc(SIZE);
35+
36+INT
37+main(INT argc, CHAR **argv)
38+{
39+ initargv0(argv[0]); initrand();
40+ INT ch; WHILE (ch=getopt(argc,argv,"csq"))!=-1
41+ DO SWITCH ch IN
42+ CASE 'c': cflag=TRUE; BREAK;
43+ CASE 's': sflag=TRUE; BREAK;
44+ CASE 'q': qflag=TRUE; BREAK;
45+ OUT: usage();
46+ ENDSW;
47+ OD; argc-=optind; argv+=optind;
48+ IF cflag THEN coinflip(); RETURN 0 FI;
49+ STRING e;
50+ IF sflag THEN e=getlin() ELIF argc<1 THEN usage() ELSE e=argv[0] FI;
51+ AUTO d=parsedice(e);
52+ IF NOT qflag THEN printf("%s=",e) FI; printf("%d\n",rolldice(d));
53+ RETURN 0;
54+}
55+
56+STATIC VOID
57+initrand()
58+{
59+ srandom(time(NIL)+getpid());
60+}
61+
62+NORETURN STATIC VOID
63+usage()
64+{
65+ fprintf(STDERR,"usage: %s [-csq] [expr]\n",argv0);
66+ exit(1);
67+}
68+
69+NORETURN STATIC VOID
70+error(STRING fmt, ...)
71+{
72+ fprintf(STDERR,"%s: ",argv0);
73+ VALIST ap;
74+ va_start(ap, fmt);
75+ vfprintf(STDERR,fmt,ap);
76+ fputc('\n',STDERR);
77+ va_end(ap);
78+ exit(1);
79+}
80+
81+STATIC VOID
82+initargv0(STRING s)
83+{
84+ argv0=strrchr(s,'/'); IF NOT argv0 THEN argv0=s ELSE argv0++ FI;
85+}
86+
87+STATIC CONST DICE *
88+parsedice(STRING e)
89+{
90+ CHAR *end;
91+ DICE *p=xmalloc(SIZEOF(DICE));
92+ IF NOT *e THEN error("expected number of dice") FI;
93+ p->ndic=strtol(e,&end,10); e=end;
94+ IF *e++!='d' THEN error("expected `d' in expression") FI;
95+ IF NOT *e THEN error("expected number of sides") FI;
96+ p->nsid=strtol(e,&end,10); e=end;
97+ IF p->nsid==0 THEN error("can't have zero-sided die") FI;
98+ IF NOT *e
99+ THEN RETURN p
100+ ELIF *e++!='+'
101+ THEN error("expected `+' in expression")
102+ FI;
103+ p->next=parsedice(e); RETURN p;
104+}
105+
106+STATIC STRING
107+getlin()
108+{
109+ CHAR *buf=xmalloc(80);
110+ IF NOT fgets(buf,80,STDIN) THEN buf[0]=0 FI;
111+ buf[strcspn(buf,"\n")]=0;
112+ RETURN buf;
113+}
114+
115+STATIC INT
116+rolldice(CONST DICE *dice)
117+{
118+ INT res=0;
119+ FOR AUTO d=dice; d; d=d->next
120+ DO FOR INT i=0; i<d->ndic; i++ DO res+=random()%d->nsid+1 OD;
121+ OD;
122+ RETURN res;
123+}
124+
125+STATIC VOID
126+coinflip()
127+{
128+ IF random()&1 THEN printf("heads\n") ELSE printf("tails\n") FI;
129+}
130+
131+STATIC VOID *
132+xmalloc(SIZE n)
133+{
134+ VOID *p=malloc(n); IF NOT p THEN abort() FI;
135+ RETURN memset(p,0,n);
136+}
A
mac.h
+59,
-0
1@@ -0,0 +1,59 @@
2+#define IF if(
3+#define THEN ){
4+#define ELIF ;}else if(
5+#define ELSE ;}else{
6+#define FI ;}
7+
8+#define FOR for(
9+#define WHILE while(
10+#define DO ){
11+#define OD ;}
12+#define BREAK break
13+#define CONTINUE continue
14+
15+#define SWITCH switch(
16+#define IN ){
17+#define CASE case
18+#define OUT default
19+#define ENDSW ;}
20+
21+#define CONST const
22+#define VOLATILE volatile
23+#define EXTERN extern
24+#define STATIC static
25+#define RETURN return
26+#define SIZEOF sizeof
27+
28+#define TYPE typedef
29+#define STRUCT struct
30+#define UNION union
31+#define ENUM enum
32+
33+#define AUTO auto
34+typedef int INT;
35+typedef long LONG;
36+typedef void VOID;
37+typedef char CHAR;
38+typedef bool BOOL;
39+typedef size_t SIZE;
40+typedef const char *STRING;
41+typedef va_list VALIST;
42+
43+#define TRUE true
44+#define FALSE false
45+
46+#define ANDF &&
47+#define ORF ||
48+
49+#define NOT !
50+#define OR |
51+#define AND &
52+#define XOR ^
53+
54+#define NIL ((VOID *)0)
55+
56+#define STDIN stdin
57+#define STDOUT stdout
58+#define STDERR stderr
59+
60+#define NORETURN [[noreturn]]