summaryrefslogtreecommitdiffstats
path: root/makedev-1.4.1/makedev.syn
diff options
context:
space:
mode:
Diffstat (limited to 'makedev-1.4.1/makedev.syn')
-rw-r--r--makedev-1.4.1/makedev.syn994
1 files changed, 0 insertions, 994 deletions
diff --git a/makedev-1.4.1/makedev.syn b/makedev-1.4.1/makedev.syn
deleted file mode 100644
index 26ccef311..000000000
--- a/makedev-1.4.1/makedev.syn
+++ /dev/null
@@ -1,994 +0,0 @@
-{
-/*
- * makedev.c: Generate /dev entries
- *
- * Based on the MAKEDEV shell script, version 2.0, distributed with
- * util-linux 1.10 and written by Nick Holloway.
- *
- * A number of bugs were fixed, and some additional features added.
- * Written 10-Dec-94 by David A. Holland, dholland@husc.harvard.edu
- *
- * Copyright 1994, 1995. All rights reserved.
- * See the file LEGAL.NOTICE for conditions of redistribution.
- *
- * Bugs:
- * None known right now.
- *
- * History:
- *
- * Version 1.4: 15-Jan-95 Wrote man pages. Now reads DEVINFO.local.
- * Version 1.3: 31-Dec-94 Bug fixes. Added batches. Added omits.
- * Version 1.2: 11-Dec-94 Add configuration file parsing.
- * Version 1.1: 11-Dec-94 Distinguish block and character devices in the
- * table of major device numbers. Changed the name and format of the
- * update cache file to include the type. It appears that the old script
- * was broken in this regard.
- * Version 1.0: 10-Dec-94 Initial version.
- */
-
-static const char *version = "MAKEDEV-C version 1.4";
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdarg.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <pwd.h>
-#include <grp.h>
-#include <sys/stat.h>
-
-#define YES 1
-#define NO 0
-
-static int isverbose=NO; /* flag: print out what we do? */
-static int deletion=NO; /* flag: delete instead of create */
-static int donothing=NO; /* flag: don't actually do anything */
-
-/*
- * Proto for main operative function.
- */
-typedef enum { M_CREATE, M_OMIT } makeopts;
-static void make(const char *batch_or_grp_or_devname, makeopts);
-
-/*
- * Roll over and die.
- */
-static void crash(const char *msg) {
- fprintf(stderr, "MAKEDEV: %s\n", msg);
- exit(1);
-}
-
-/*
- * Print a warning.
- */
-static void warn(const char *format, ...) {
- va_list ap;
- va_start(ap, format);
- fprintf(stderr, "MAKEDEV: ");
- vfprintf(stderr, format, ap);
- fprintf(stderr, "\n");
- va_end(ap);
-}
-
-/*
- * Translate string name to uid.
- */
-static uid_t name2uid(const char *name) {
- struct passwd *p = getpwnam(name);
- if (!p) warn("undefined user: %s, using uid 0", name);
- return p ? p->pw_uid : 0; /* make things owned by root by default */
-}
-
-/*
- * Translate string name to gid.
- */
-static gid_t name2gid(const char *name) {
- struct group *g = getgrnam(name);
- if (!g) warn("undefined group: %s, using gid 0", name);
- return g ? g->gr_gid : 0; /* group 0 is a good default too */
-}
-
-/*
- * Proto for parser.
- */
-static void doparse(FILE *f, int filetype, const char *filename);
-
-/************************* device classes *************************/
-
-/*
- * A device class is a string attached to the device which tells us
- * what set of permissions and ownership should be used. This is the
- * table of classes.
- */
-
-typedef struct {
- const char *classname;
- const char *owner;
- const char *group;
- int mode;
-} devclass;
-
-#define MAXCLASSES 32
-static devclass classes[MAXCLASSES];
-static int nclasses=0;
-
-static void addclass(const char *name, const char *o, const char *g, int m) {
- if (nclasses>=MAXCLASSES) crash("out of space for device classes");
- classes[nclasses].classname = name;
- classes[nclasses].owner = o;
- classes[nclasses].group = g;
- classes[nclasses].mode = m;
- nclasses++;
- name2uid(o); /* check for undefined users/groups */
- name2gid(g);
-}
-
-static void loadclasses(void) {
- FILE *f = fopen("MAKEDEV.cfg", "r");
- if (!f) f = fopen("../MAKEDEV.cfg", "r");
- if (!f) f = fopen("/etc/makedev.cfg", "r");
- if (!f) crash("can't find MAKEDEV.cfg");
- doparse(f, 4, "MAKEDEV.cfg");
- fclose(f);
-}
-
-/*
- * Return the index into the above table for a particular class name.
- */
-static int which_class(const char *name) {
- int i;
- for (i=0; i<nclasses; i++)
- if (!strcmp(classes[i].classname, name)) return i;
- return 0;
-}
-
-/*
- * Produce an "ls -l"-ish mode string.
- */
-static const char *modestring(int mode) {
- static char rv[12];
- int i,z;
- strcpy(rv, "rwxrwxrwx");
- for (i=8,z=1; i>=0; i--, z<<=1) if (!(mode&z)) rv[i]='-';
- return rv;
-}
-
-/*
- * Create (or delete, or update) a block or character device.
- */
-static void class_makedev(const char *name, const char *class,
- int major, int minor, char type) {
- int x = which_class(class), mode = classes[x].mode;
- const char *owner = classes[x].owner, *group = classes[x].group;
- if (isverbose) {
- if (deletion) printf("rm -f %s\n", name);
- else printf("%c%s 1 %-8s %-8s %3d, %3d for %s\n", type,
- modestring(mode), owner, group, major, minor, name);
- }
- if (donothing) return;
- if (unlink(name) && deletion) warn("Couldn't remove %s\n", name);
- if (!deletion) {
- dev_t q = (major<<8) | minor;
- if (mknod(name, type=='c' ? S_IFCHR : S_IFBLK, q) ||
- chown(name, name2uid(owner), name2gid(group)) ||
- chmod(name, mode)) {
- warn("couldn't create %s: %s", name, strerror(errno));
- }
- }
-}
-
-/************************* major number list *************************/
-
-/*
- * In Linux device major numbers can be allocated dynamically, so we go
- * look in /proc/devices to see what they are. This keeps track of things.
- */
-
-typedef struct {
- const char *procname;
- int flag;
-} majorentry;
-
-#define MAXMAJORS 256
-static majorentry cmajors[MAXMAJORS]; /* initialized to 0 */
-static majorentry bmajors[MAXMAJORS]; /* initialized to 0 */
-static int no_proc=0; /* true if we didn't find /proc/devices */
-
-/*
- * Store the name associated with a particular major device number.
- */
-static void set_major(const char *procname, int ischar, int num) {
- if (num<0 || num>255) {
- warn("warning: got bogus major number %d for %s", num, procname);
- return;
- }
- if (ischar) cmajors[num].procname=procname;
- else bmajors[num].procname=procname;
-}
-
-/*
- * Look up a major device number by name; return the default value
- * if provided. A default value of -1 implies the device is only
- * dynamic, and so if there's no entry we shouldn't even note its
- * existence.
- */
-static int get_major(const char *procname, int ischar, int defaalt) {
- int i;
- if (!procname) return defaalt;
- if (ischar) {
- for (i=0; i<MAXMAJORS; i++)
- if (cmajors[i].procname && !strcmp(cmajors[i].procname, procname))
- return i;
- }
- else {
- for (i=0; i<MAXMAJORS; i++)
- if (bmajors[i].procname && !strcmp(bmajors[i].procname, procname))
- return i;
- }
- return defaalt;
-}
-
-/*
- * Read /proc/devices.
- */
-static void setup_majors(void) {
- FILE *f = fopen("/proc/devices", "r");
- if (!f) {
- fprintf(stderr, "MAKEDEV: warning: can't read /proc/devices\n");
- no_proc = 1;
- return;
- }
- doparse(f, 1, "/proc/devices");
- fclose(f);
-}
-
-/************************** procname list *************************/
-
-/*
- * The names found in /proc/devices aren't usually quite the same
- * as the names we use. This is a mapping between the two namespaces.
- */
-typedef struct {
- const char *procname;
- const char *groupname;
-} namealias;
-
-#define MAXALIASES 100
-static namealias aliases[MAXALIASES];
-static int naliases=0;
-
-static void addalias(const char *procname, const char *groupname) {
- if (naliases>=MAXALIASES) crash("out of space for aliases");
- aliases[naliases].procname = procname;
- aliases[naliases].groupname = groupname;
- naliases++;
-}
-
-static void ignore_procname(const char *procname) {
- addalias(procname, NULL);
-}
-
-static const char *procnameof(const char *groupname) {
- int i;
- for (i=0; i<naliases; i++) if (!strcmp(groupname, aliases[i].groupname))
- return aliases[i].procname;
- return NULL;
-}
-
-static const char *groupnameof(const char *procname) {
- int i;
- for (i=0; i<naliases; i++) if (!strcmp(procname, aliases[i].procname))
- return aliases[i].groupname;
- return NULL;
-}
-
-/************************* batch list *************************/
-/*
- * Create a device "batch" - a bunch of devices or groups.
- * This is used for "generic" and automatically for disk entries.
- * (Disk entries for "hd" come up with groups hda, hdb, etc., but
- * "hd" itself needs to run these too.)
- */
-#define MAXTARGETS 32
-#define MAXBATCHES 16
-
-typedef struct {
- const char *name; /* name of batch */
- const char *targets[MAXTARGETS];
- int ntargets;
- int busy;
-} batch;
-
-static batch batches[MAXBATCHES];
-static int nbatches=0;
-
-/*
- * Start a new batch.
- */
-static batch *addbatch(const char *name) {
- batch *b;
- if (nbatches>=MAXBATCHES) crash("Out of space for batches");
- b = &batches[nbatches++];
- b->name = name;
- b->busy = NO;
- return b;
-}
-
-/*
- * Add something to a batch.
- */
-static batch *add2batch(batch *b, const char *target) {
- if (b->ntargets>=MAXTARGETS) {
- warn("Too many targets for batch %s (max %d)", b->name, MAXTARGETS);
- return b;
- }
- b->targets[b->ntargets++] = target;
- return b;
-}
-
-/*
- * Run a batch.
- */
-static void run_batch(const batch *b, makeopts m) {
- int i;
- for (i=0; i<b->ntargets; i++) make(b->targets[i], m);
-}
-
-/*
- * Try to run a batch; returns YES if it found one.
- */
-static int try_run_batch(const char *name, makeopts m) {
- int i;
- for (i=0; i<nbatches; i++) {
- if (!strcmp(name, batches[i].name)) {
- if (batches[i].busy) {
- warn("Found recursive batch definition for %s", batches[i].name);
- continue;
- }
- batches[i].busy=YES;
- run_batch(&batches[i], m);
- batches[i].busy=NO;
- return YES;
- }
- }
- return NO;
-}
-
-/************************* device list *************************/
-
-/*
- * Structure to remember the properties of an individual device.
- * NOTE: if the device is actually a symbolic link, the "class"
- * member is used to store the thing it should be linked to.
- */
-typedef struct {
- const char *name; /* file name to create */
- const char *grp; /* device "group" name (e.g. "busmice") */
- const char *class; /* device class ( -> owner and permissions) */
- int major, minor; /* device number */
- char type; /* 'c', 'b', or 'l' for symbolic link */
- int omit; /* don't make me if this is nonzero */
-} device;
-
-/*
- * Create a device (link or actual "special file") - special files are
- * passed on to class_makedev().
- */
-void makedev(device *d, makeopts m) {
- if (m==M_OMIT) {
- d->omit=1;
- }
- if (d->omit==1) return;
- if (d->type=='l') {
- if (isverbose) {
- if (deletion) printf("rm -f %s\n", d->name);
- else printf("lrwxrwxrwx %s -> %s\n", d->name, d->class);
- }
- if (donothing) return;
- if (unlink(d->name) && deletion) warn("Couldn't remove %s\n", d->name);
- if (!deletion) {
- if (symlink(d->class, d->name)) /* class holds thing pointed to */
- warn("couldn't link %s -> %s: %s", d->name, d->class, strerror(errno));
- }
- }
- else class_makedev(d->name, d->class, d->major, d->minor, d->type);
-}
-
-/*
- * Array of devices. We allocate it once from main(); it doesn't grow.
- * Should maybe make it growable sometime. This keeps track of all possible
- * devices. We build this thing first, and then create devices from it as
- * requested.
- */
-static device *devices = NULL;
-static int maxdevices, ndevices;
-
-/*
- * Allocate space for the device array.
- */
-static void allocate_devs(int nd) {
- devices = malloc(nd * sizeof(device));
- if (!devices) crash("Out of memory");
- ndevices = 0;
- maxdevices = nd;
-}
-
-/*
- * Check all the devices for having valid device classes.
- */
-static void check_classes(void) {
- int i;
- const char *q=NULL;
- for (i=0; i<ndevices; i++)
- if (devices[i].type!='l' && !devices[i].omit &&
- which_class(devices[i].class)<0) {
- if (!q || strcmp(q, devices[i].class)) {
- warn("Invalid device class %s for %s",
- devices[i].class, devices[i].name);
- q = devices[i].class;
- }
- devices[i].class = "default";
- }
-}
-
-/*
- * Create an entry in the device table for a single device.
- */
-static void init(const char *name, const char *grp, const char *class,
- int major, int minor, int type) {
- if (major < 0) return;
- if (!strchr("bcl", type)) {
- warn("invalid device type %c for %s (skipping)", type, name);
- return;
- }
- if (ndevices>=maxdevices) crash("out of space for devices");
- devices[ndevices].name = name;
- devices[ndevices].grp = grp;
- devices[ndevices].class = class;
- devices[ndevices].major = major;
- devices[ndevices].minor = minor;
- devices[ndevices].type = type;
- devices[ndevices].omit = 0;
- ndevices++;
-}
-
-/*
- * Create an entry for a symbolic link "device", such as /dev/fd
- * (which is a symbolic link to /proc/self/fd)
- */
-static void initlink(const char *name, const char *grp, const char *target) {
- init(name, grp, target, 0, 0, 'l');
-}
-
-/*
- * Init lots of devices. This creates a number of devices, numbered between
- * lo and hi. The idea is that "base" contains a %d or %x (or something like
- * that) in it which pulls in the number. The device group can also do this,
- * though this will in most cases not be useful. "baseminor" is the minor
- * number of the first device created.
- */
-static void initlots(const char *base, int lo, int hi, const char *grp,
- const char *class,
- int maj, int baseminor, int type) {
- char buf[32], gbuf[32];
- int i;
- if (maj<0) return;
- for (i=lo; i<hi; i++) {
- sprintf(buf, base, i);
- if (grp) sprintf(gbuf, grp, i); /* grp is permitted to contain a %d */
- init(strdup(buf), grp ? strdup(gbuf) : NULL, class,
- maj, baseminor+i-lo, type);
- }
-}
-
-/*
- * Init a whole (hard) disk's worth of devices - given `hd', it makes
- * hda1...hda8 through hdd1...hdd8 in one fell swoop. "low" and "high"
- * are the letters to use ('a' and 'd' for the previous example).
- * "nparts" is the number of partitions to create, ordinarily 8.
- * "maj" is the major device number; minmult is the multiplier for the
- * minor number. That is, if hda starts at 0, and hdb starts at 64, minmult
- * is 64.
- *
- * Note that it creates "hda", "hdb", etc. too, and puts things in the
- * groups "hda", "hdb", etc. as appropriate. The class is set to "disk".
- */
-static void initdisk(const char *base, int low, int high, int nparts,
- int maj, int minmult) {
- char buf[16], buf2[16];
- int i;
- batch *b;
- if (maj<0) return;
- if (low>=high) return;
- b = addbatch(base);
- for (i=low; i<=high; i++) {
- char *q;
- sprintf(buf, "%s%c", base, i);
- q = strdup(buf);
- init(q, q, "disk", maj, (i-low)*minmult, 'b');
- strcpy(buf2, buf);
- strcat(buf2, "%d");
- initlots(buf2, 1, nparts, buf, "disk", maj, (i-low)*minmult+1, 'b');
- add2batch(b, q);
- }
-}
-
-static void initdevs(void) {
- FILE *f = fopen("DEVINFO", "r");
- if (!f) f = fopen("../DEVINFO", "r");
- if (!f) f = fopen("/etc/devinfo", "r");
- if (!f) crash("Can't find DEVINFO");
- doparse(f,3, "DEVINFO");
- fclose(f);
- f = fopen("DEVINFO.local", "r");
- if (!f) f = fopen("../DEVINFO.local", "r");
- if (!f) f = fopen("/etc/devinfo.local", "r");
- if (!f) f = fopen("/usr/local/etc/devinfo.local", "r");
- if (f) {
- doparse(f,3, "DEVINFO.local");
- fclose(f);
- }
-}
-
-/************************** update *************************/
-
-/*
- * Call make() with our names for something that appeared in /proc/devices.
- */
-
-static void transmake(const char *procname, makeopts m) {
- const char *gname = groupnameof(procname);
- if (gname) make(gname, m);
-}
-
-/*
- * Update a device that appeared in MAKEDEV.cache. Whenever we update,
- * we save what we did into MAKEDEV.cache; this lets us avoid doing
- * them over the next time. We only do something if the device has
- * disappeared or the major number has changed.
- *
- * Note that this caching made the shell version go much faster (it took
- * around 15 seconds with the cache, vs. over a minute if the cache was
- * blown away.) For us, it still does, but it hardly matters: it shaves
- * one second off a two-second execution.
- *
- * Also note the old script used DEVICES instead of MAKEDEV.cache. We
- * changed because the old file didn't record whether something was
- * a block or character device; since the sets of numbers are independent,
- * this was bound to break.
- */
-static void update2(const char *name, int ischar, int major) {
- int now = get_major(name, ischar, -1);
- if (now<0) {
- deletion = 1; /* must have been zero if we're doing an update */
- transmake(name, M_CREATE);
- deletion = 0;
- }
- else if (now!=major) { /* oops, it moved; remake it */
- transmake(name, M_CREATE);
- if (ischar) cmajors[now].flag=1;
- else bmajors[now].flag=1;
- }
- else {
- if (ischar) cmajors[now].flag=1; /* unchanged; inhibit remaking it */
- else bmajors[now].flag=1; /* unchanged; inhibit remaking it */
- }
-}
-
-static void updatefromcache(const char *name, int major, int type) {
- update2(name, type=='c', major);
-}
-
-
-/*
- * Update. Read the information stored in MAKEDEV.cache from the last
- * update; fix anything that changed; then create any new devices that
- * weren't listed the last time. (We use the "flag" field in the
- * majors array to check this.) At that point, write out a new
- * cache file.
- */
-#define CACHEFILE "MAKEDEV.cache"
-
-static void update(void) {
- FILE *f;
- int i;
- if (no_proc) { warn("Couldn't read anything from /proc/devices"); return; }
- if (deletion) { warn("update and -d are incompatible"); return; }
- f = fopen(CACHEFILE, "r");
- if (f) {
- doparse(f, 2, CACHEFILE);
- fclose(f);
- }
- for (i=0; i<MAXMAJORS; i++) {
- if (cmajors[i].procname && !cmajors[i].flag) {
- transmake(cmajors[i].procname, M_CREATE);
- cmajors[i].flag=1;
- }
- if (bmajors[i].procname && !bmajors[i].flag) {
- transmake(bmajors[i].procname, M_CREATE);
- bmajors[i].flag=1;
- }
- }
- if (donothing) return;
- f = fopen(CACHEFILE, "w");
- if (f) {
- for (i=0; i<MAXMAJORS; i++) {
- if (cmajors[i].procname) fprintf(f, "%s %d char\n", cmajors[i].procname, i);
- if (bmajors[i].procname) fprintf(f, "%s %d block\n", bmajors[i].procname, i);
- }
- fclose(f);
- }
- else warn("warning: can't write MAKEDEV.cache");
-}
-
-/************************* work *************************/
-
-/*
- * Create (or delete, etc. according to flags) a device or device group.
- * The "generic" group is handled specially by recursing once.
- * "update" is handled specially; see update() below.
- * "local" issues a warning; people should use DEVINFO.local instead.
- */
-static void make(const char *what, makeopts m) {
- int i;
- if (!strcmp(what, "update")) {
- if (m!=M_CREATE) warn("update not compatible with those options");
- else update();
- }
- else if (!strcmp(what, "local")) {
- warn("The local target is obsolete.");
- }
- else if (!try_run_batch(what, m)) {
- int found=0;
- for (i=0; i<ndevices; i++) {
- if ((devices[i].grp && !strcmp(what, devices[i].grp)) ||
- !strcmp(what, devices[i].name)) {
- makedev(&devices[i], m);
- found = 1;
- }
- }
- if (!found) warn("unknown device or device group %s", what);
- }
-}
-
-/*
- * A major improvement over the shell version...
- */
-static void usage(void) {
- printf("MAKEDEV usage:\n");
- printf(" MAKEDEV [-vdcn] device [device...]\n");
- printf(" -v Verbose output\n");
- printf(" -d Remove specified devices\n");
- printf(" -c Create devices (default)\n");
- printf(" -n Don't actually do anything (implies -v)\n");
- printf(" -V Print version information\n");
- printf("\n");
-}
-
-/*
- * We should use getopt one of these days.
- */
-int main(int argc, char **argv) {
- int i,j, done=0;
- for (i=1; i<argc && argv[i][0]=='-' && !done; i++)
- for (j=1; argv[i][j] && !done; j++) switch(argv[i][j]) {
- case '-': done=1; break;
- case 'v': isverbose = 1; break;
- case 'd': deletion = 1; break;
- case 'c': deletion = 0; break;
- case 'n': donothing = 1; isverbose = 1; break;
- case 'h': usage(); exit(0);
- case 'V': printf("MAKEDEV: %s\n", version); exit(0);
- default: fprintf(stderr, "MAKEDEV: unknown flag %c\n", argv[i][j]);
- exit(1);
- }
- setup_majors(); /* read major device numbers from /proc */
- allocate_devs(1500); /* make space to hold devices */
- initdevs(); /* set up device structures */
- loadclasses(); /* load device classes from config file */
- check_classes(); /* make sure no devices have bogus classes */
- if (i==argc) warn("didn't do anything; try -h for help.");
- else for (; i<argc; i++) make(argv[i], M_CREATE);
- return 0;
-}
-
-}
-{
-/************************* parsing support *************************/
-
-/*
- * Don't use the built-in error printing.
- */
-#define SYNTAX_ERROR
-#define PARSER_STACK_OVERFLOW
-#define REDUCTION_TOKEN_ERROR
-
-static void doparse(FILE *f, int filetype, const char *filename) {
- char *x;
- int i=0, len;
- if (filetype<1 || filetype>4) crash("tried to parse a bad file type");
- if (filetype!=1) { /* /proc/devices won't stat intelligently */
- struct stat buf;
- if (fstat(fileno(f), &buf)) crash("fstat failed?!?");
- len = buf.st_size;
- }
- else len=1023;
- x = malloc(len+1);
- if (!x) crash("Out of memory");
-
- len = fread(x, 1, len, f); /* it shouldn't return a short count... */
- if (len<0) crash("fread failed?!?");
- x[len]=0;
-
- init_parse();
- PCB.input_code = filetype+'0';
- parse();
- PCB.column--; /* correct for the filetype token */
- while (!PCB.exit_flag) {
- PCB.input_code = x[i++];
- parse();
- }
- if (PCB.exit_flag == AG_SYNTAX_ERROR_CODE) {
- warn("syntax error: %s, line %d, column %d in file %s",
- PCB.error_message, PCB.line, PCB.column, filename);
- crash("Sorry, can't continue.");
- }
- else if (PCB.exit_flag != AG_SUCCESS_CODE) {
- crash("parser stack overflow!");
- }
-}
-
-#define STRINGSIZE 8192
-static char string_space[STRINGSIZE];
-static int stringptr=0;
-
-static const char *string_start(int c) {
- if (stringptr>=STRINGSIZE) crash("out of string space");
- return string_space[stringptr]=c, string_space+stringptr++;
-}
-
-static void string_push(int c) {
- if (stringptr>=STRINGSIZE) crash("out of string space");
- string_space[stringptr++] = c;
-}
-
-static void string_finish(void) {
- string_push(0);
-}
-
-}
-/************************* syntax begins here *************************/
-
-/*
- * We read four different file formats here:
- * /proc/devices 1
- * MAKEDEV.cache 2
- * DEVINFO 3
- * MAKEDEV.config 4
- */
-
-
-[
- sticky {identifier}
- disregard white space
- lexeme {identifier, simple eol, quoted string}
- distinguish keywords {'a-z' + 'A-Z'}
- event driven
- parser name = parse
- line numbers
-]
-
-(void) file format $
- -> '1', devices
- -> '2', cache
- -> '3', devinfo
- -> '4', config
-
-
-/************************* /proc/devices *************************/
-
-(void) devices
- -> eol?, device list..., eof
-
-(void) device list
- -> "Character devices:", eol, character device...
- -> "Block devices:", eol, block device...
-
-(void) character device
- -> number:n, name:s, eol = set_major(s,YES,n);
-
-(void) block device
- -> number:n, name:s, eol = set_major(s,NO,n);
-
-/************************* cache *************************/
-
-(void) cache
- -> eol?, cachedevice..., eof
-
-(void) cachedevice
- -> name:n, number:maj, devicetype:t, eol = updatefromcache(n,maj,t);
-
-(char) devicetype
- -> 'b' = 'b';
- -> 'c' = 'c';
- -> "block" = 'b';
- -> "char" = 'c';
-
-/************************* devinfo *************************/
-
-(void) devinfo
- -> eol?, device block..., eof
-
-(void) device block
- -> device header spec, '{', eol?, device decl?..., '}', eol?
- -> device header spec, eol?, device decl
- -> "ignore", '{', eol?, ignoramus..., '}', eol?
- -> "batch", batch list, '}', eol?
-
-(batch *) batch list
- -> name:n, '{', eol?, batch item:i, eol? = add2batch(addbatch(n), i);
- -> batch list:b, [',', eol?], batch item:i, eol? = add2batch(b,i);
-
-(const char *) batch item
- -> name:n = n;
-
-(void) ignoramus
- -> name:n, eol?, [',', eol?] = ignore_procname(n);
-
-{
- static const char *cur_group=NULL, *cur_class=NULL;
- static int cur_type;
- static int cur_maj=0, cur_min=0, cur_bot=0, cur_top=0, ishex=0;
-
- static void dhsproc(const char *g, const char *p, int t, int m) {
- cur_group = g;
- cur_type = t;
- cur_maj = get_major(p, (t=='c'), m);
- cur_min = 0;
- cur_bot = cur_top = ishex = 0;
- if (p) addalias(p,g);
- }
-
- static void newdev(const char *n) {
- if (cur_maj<0) return;
- init(n, cur_group, cur_class, cur_maj, cur_min, cur_type);
- }
- static void devrange(const char *n, const char *n1) {
- char temp[32];
- if (cur_maj<0) return;
- sprintf(temp, "%s%%d%s", n, n1 ? n1 : "");
- initlots(temp, cur_bot, cur_top, cur_group, cur_class,
- cur_maj, cur_min, cur_type);
- }
- static void doinitlink(const char *src, const char *tg) {
- if (cur_maj>=0) initlink(src, cur_group, tg);
- }
-}
-
-(void) device header spec
- -> devicetype:t, '(', groupname:g, '=', procname:p, ')' = dhsproc(g,p,t,-1);
- -> devicetype:t, '(', groupname:g, '=', procname:p,
- ',', number:m, ')' = dhsproc(g,p,t,m);
- -> devicetype:t, '(', groupname:g, ',', number:m, ')' = dhsproc(g,NULL,t,m);
-
-(const char *) class
- -> '(', name:classname, ')' = classname;
-
-(void) device tail
- -> class:c, ':', expr:min, eol = (cur_class=c, cur_min=min);
-
-(void) device range
- -> '[', number:a, '-', number:b, ']' = cur_bot=a, cur_top=b, ishex=0;
- -> '[', hex number:a, '-', auto hex:b, ']' = cur_bot=a, cur_top=b, ishex=1;
-
-(void) device decl
- -> devname:n, device tail = newdev(n);
- -> devname:n, device range, devname:n1, device tail = devrange(n,n1);
- -> devname:n, device range, device tail = devrange(n,NULL);
- -> devname:n, '[', letter:a, '-', letter:b,']', number:p,'/',number:m, eol =
- initdisk(n, a, b, p, cur_maj, m);
- -> devname:n, "->", name:tg, eol = doinitlink(n, tg);
-
-(const char *) devname -> name:n = n;
-(const char *) groupname -> name:n = n;
-(const char *) procname -> name:n = n;
-
-
-/************************* config *************************/
-
-(void) config
- -> eol?, config decl..., eof
-
-(void) config decl
- -> class decl
- -> omit decl
-
-(void) class decl
- -> "class", name:n, ':', name:o, name:g, mode:m, eol = addclass(n,o,g,m);
-
-(void) omit decl
- -> "omit", name:n, eol = make(n, M_OMIT);
- -> "omit", '{', eol?, single omit..., '}', eol?
-
-(void) single omit
- -> name:n, eol?, [',', eol?] = make(n, M_OMIT);
-
-(int) mode
- -> octal number:n = n;
-
-/************************* support *************************/
-
-eof = -1 + 0
-digit = '0-9'
-letter = 'a-z' + 'A-Z' + '-' + '_'
-octal digit = '0-7'
-qchar = 32..126 - '\\' - '"'
-
-(void) white space
- -> ' ' + '\t' + '\r'
- -> "/*", ~eof?..., "*/"
-
-
-(void) eol
- -> simple eol...
-
-(void) simple eol
- -> [{"//" | '#'}, ~'\n'?...], '\n'
-
-(const char *) name
- -> identifier:s = string_finish(), s;
- -> quoted string:s = s;
-
-(const char *) identifier
- -> letter:c = string_start(c);
- -> identifier:s, letter+digit:c = string_push(c), s;
-
-(const char *) quoted string
- -> '"', qstring:s, '"' = string_finish(), s;
-
-(const char *) qstring
- -> qstring char:c = string_start(c);
- -> qstring:s, qstring char:c = string_push(c), s;
-
-(char) qstring char
- -> qchar:c = c;
- -> '\\', '\\' = '\\';
- -> '\\', '"' = '"';
-
-(int) number
- -> digit:d = d-'0';
- -> number:n, digit:d = n*10 + d-'0';
-
-(int) hex number
- -> {"0x" | "0X"}, hex digit:d =d;
- -> hex number:n, hex digit:d =16*n+d;
-
-(int) auto hex
- -> hex digit:d =d;
- -> auto hex:n, hex digit:d =16*n+d;
-
-
-(int) hex digit
- -> digit:d =d-'0';
- -> 'a-f' + 'A-F' :d =10 + (d&7);
-
-(int) octal number
- -> octal digit:d = d-'0';
- -> octal number:n, octal digit:d = n*8+d-'0';
-
-(int) expr
- -> term
- -> expr:x, '+', term:t =x+t;
- -> expr:x, '-', term:t =x-t;
-
-(int) term
- -> factor
- -> term:t, '*', factor:f =t*f;
-// -> term:t, '/', factor:f =t/f;
-
-(int) factor
- -> number
- -> hex number
- -> '-', factor:f =-f;
- -> '(', expr:x, ')' =x;