|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T n
Length: 8034 (0x1f62) Types: TextFile Names: »ncode.c«
└─⟦b20c6495f⟧ Bits:30007238 EUUGD18: Wien-båndet, efterår 1987 └─⟦this⟧ »EUUGD18/General/Ncode/ncode.c«
/* * ncode.c -- a random text constructor * pixar!good * based on a program by pixar!mark */ #include <stdio.h> #include <sys/file.h> #include <sys/time.h> #include <sys/types.h> #include <sys/stat.h> #define DATALUMP 8192 /* increment size of data[] by this as needed */ #define BIGBUF 4096 /* nice, roomy buffer for group name checks */ char **data; /* array of pointers to elements in bucket */ int dindex; /* number of elements in data */ int datasize; /* how many elements would fit in data[] is right now */ char *malloc(); char *realloc(); char *rindex(); char *fgets(); long random(); struct gstruct { char *name; /* points to name of a group in data[] */ int count; /* how many elements of data belong to this group */ int index; /* index of element of data where group starts */ }; struct gstruct *groups; /* where the group structs live, or is that obvious? */ int ngroups; /* number of elements in groups */ main (ac,av) int ac; char *av[]; { char *prog; /* name of this program */ char *fname = 0; int loopcnt = 1; /* times through main loop */ char *groupname = "CODE"; prog = rindex(*av,'/'); prog = ( prog == NULL ) ? *av : ++prog ; ac--;av++; while(ac && **av == '-'){ if (strcmp(*av,"-n") == 0){ ac--;av++; loopcnt = atoi(*av); if (loopcnt <= 0){ fprintf(stderr, "%s: -n: need positive integer\n",prog); exit(1); } ac--;av++; } else if (strcmp(*av,"-g") == 0){ ac--;av++; groupname = *av; /* use instead of "CODE" */ if (! groupname ){ fprintf(stderr, "%s: -g: need group name\n",prog); exit(1); } ac--;av++; } else { printf( "Usage %s [-n n ] [-g groupname] codefile\n",prog); exit(0); } } if (!ac){ fprintf(stderr, "Usage %s [-n n ] [-g groupname] codefile\n",prog); exit(1); } fname = *av; /* * Make some room to start, and increment by DATALUMP as needed */ datasize = DATALUMP; if ((data = (char **) malloc(datasize * sizeof(char *))) == NULL ){ perror("main: could not malloc for data[]"); exit(1); } dindex = 0; if( init(fname) != 0 ){ fprintf(stderr,"%s: init error\n",prog); exit(1); } /* * This should be more than enough room for worst-case */ groups = (struct gstruct *) malloc(dindex * sizeof(struct gstruct)); if (groups == NULL){ perror("main: could not malloc for groups[]"); exit(1); } if ( scan() != 0 ){ fprintf(stderr,"%s: scan error\n",prog); exit(1); } srandom(a_random_number()); /* seed the number generator */ while ( loopcnt ){ expand(groupname,strlen(groupname)); loopcnt--; } exit(0); } init(fname) char *fname; { char *bucket; /* big array where data lives */ char *bptr; /* points into bucket */ int fd; struct stat sbuf; char *s, *t; fd = open(fname,O_RDONLY,0); if ( fd < 0 ) { perror(fname); return 1; } if ( fstat(fd,&sbuf) != 0 ){ perror(fname); return 1; } if ((bucket = (char *) malloc( sbuf.st_size + 1)) == NULL ){ perror("init(): malloc() trouble"); return 1; } /* * Read entire file into bucket[] */ if ((read(fd,bucket,sbuf.st_size)) != sbuf.st_size){ perror("init: read error"); return 1; } close(fd); /* * Make first pass through memory, pointing data[] the right way * and recursing as needed on #include files. */ bptr = bucket; while ( *bptr && (bptr <= bucket + sbuf.st_size) ){ s = bptr; while ( *s != '\0' ){ if(*s == '\n' ) *s = '\0'; /* nuke newline */ else s++; } if( strncmp(bptr, "#include", 8) == 0 ){ for(t = bptr + 8; *t!='\0' && (*t==' '||*t=='\t');t++) ; /* skipping white space */ if (init(t) != 0){ /* RECURSES HERE */ return 1; } bptr = t +strlen(t) + 1; /* skip the #include line */ continue; /* back to the top of the while loop */ } /* * Make sure data[] is still big enough */ if ( dindex >= datasize){ datasize += DATALUMP; if((data=(char **) realloc(data, datasize*sizeof(char *)))==NULL){ perror("init: could not realloc for data[]"); return(1); } } data[dindex] = bptr; /* point it at the data */ bptr = s + 1; /* move bptr to the next location to fill */ dindex++; } return 0; } /* * Scan data[] marking and counting groups */ scan() { register i, gcnt, gindex; /* * special case: first line always a group name */ groups[0].name = data[0]; groups[0].index = 0; ngroups = 1; i = 1; gindex = 0; gcnt = 0; while ( i < dindex ){ if ( data[i][0] == '%' ){ groups[gindex].count = gcnt; gcnt = 0; /* close out prev group */ ngroups++; i++; /* start next group */ /* * If a #included file has any blank lines after * the last '%' then the group name would wind * up being '\0'. So the first group name after * the #include won't be marked as a group name * and will thus never be expanded. We could * cluck our tongues at the user and say he has * a bogus file and thus deserves what he gets. * But hopefully this check will just make the * program more robust. */ while ((i < dindex) && (data[i][0] == '\0')){ i++; } gindex++; groups[gindex].name = data[i]; groups[gindex].index = i; }else{ gcnt++; } i++; } ngroups--; /* The last % in the file doesn't start a new group */ return 0; } /* * This is where we finally do the deed. If a string is a group name * then expand() will randomly select a member of that group to * replace it. Through the miracle of recursion, a whole sentence * may be passed to expand() and each word (anything bounded by what * we call "white space" gets expanded. Anything that cannot be * expanded gets printed out. */ expand(s,lim) char s[]; int lim; { register i, j, k, done, n, r; i = j = 0; while ( s[i] != 0 && i < lim ){ done = 0; while ( ! done && j <= lim ){ if ( isawhite(s[j]) ){ /* chase down remaining white space */ for (k=j; k<=lim && s[k] && isawhite(s[k]);k++){ ; } n = isagroup(&s[i], j-i); if ( n >= 0 ){ r = (groups[n].index + 1 + rnd(groups[n].count)); expand( data[r], strlen(data[r])); outstring(&s[j], k-j); } else { outstring(&s[i], k-i); } done++; i = j = k; /* should be on next word, if any */ } j++; } } } /* * Return index into groups[] array if a group name, -1 if just a word. * We have to use gbuf, a seperate place, so that we can null-terminate * the string where we want. Otherwise it wouldn't know santa from * santana. */ isagroup(s,lim) char s[]; int lim; { register i; static char gbuf[BIGBUF]; strncpy(gbuf,s,lim); gbuf[lim] = '\0'; /* strncpy might not do this */ for(i=0; i<ngroups; i++ ){ if (groups[i].name && strcmp(gbuf,groups[i].name) == 0){ return i; /* hit */ } } return -1; /* fail */ } /* * Output string, handling splices */ outstring(s,lim) char s[]; int lim; { register i = 0; while ( s[i] != '\0' && i < lim ){ switch (s[i]){ case '|': break; /* splice: no output */ case '\\': putchar('\n'); break; default: putchar(s[i]); break; } i++; } } /* * Return random number 0 to limit */ rnd(limit) int limit; { if (limit > 0){ return (random() % limit); } return 0; /* better than a floating exception if lim == 0 */ } a_random_number() { struct timeval tp; struct timezone tzp; gettimeofday (&tp, &tzp); return((getpid() ^ tp.tv_usec) % 123456); } /* * Return 1 if one of our "white" characters. A white character is * any character which can bound a group name, so punctuation marks * are included. */ isawhite(c) char c; { if ( c == '\0' || /* traditional white space */ c == ' ' || c == '\t' || c == '|' || /* "splice" character */ c == '\\' || /* becomes a newline */ c == '.' || /* common punctuation */ c == '-' || c == ':' || c == ';' || c == ',' || c == '!' || c == '?' || c == '[' || c == ']' || c == '{' || c == '}' || c == '(' || c == ')' || c == '\'' || c == '\"' || c == '`' ) return 1; return 0; }