/* Output from p2c 1.21alpha-07.Dec.93, the Pascal-to-C translator */ /* From input file "bookshift.p" */ #include /* bookshift: shift the coordinates in a book according to an inst Dr. Thomas D. Schneider National Cancer Institute Laboratory of Experimental and Computational Biology Molecular Information Theory Group Frederick, Maryland 21702-1201 toms@ncifcrf.gov permanent email: toms@alum.mit.edu (use only if first address fails) http://www.lecb.ncifcrf.gov/~toms/ Uses module delmod. */ /* end of program */ /* begin module version */ #define version 1.12 /* of bookshift.p 2004 Sep 8 2004 Sep 8, 1.12: clean up for GPC 2004 Jan 18, 1.11: bug solved, cleanup 2004 Jan 17, 1.10: tracking bug in complementary cases 2004 Jan 14, 1.09: document cleanup 2004 Jan 14, 1.08: functional 2004 Jan 14, 1.07: read the inst directly by using trigger 2004 Jan 14, 1.06: use a simple read mechanism. the getocp routine is designed for reading, not output. 2004 Jan 14, 1.05: may need ocp for both in and out books??? 2004 Jan 13, 1.04: getocp fixed 2004 Jan 13, 1.03: getocp beginning to function 2004 Jan 13, 1.02: getocp beginning to function 2004 Jan 13, 1.01: getocp being imported from delmod.p 2004 Jan 13, 1.00: origin */ #define updateversion 1.00 /* defines lowest acceptable current parameter file */ /* end module version */ /* begin module describe.bookshift */ /* name bookshift: shift the coordinates in a book according to an inst synopsis bookshift(book, inst: in, bookshiftp: in, bookout: out, output: out) files book: A book from the delila system, aligned by the inst file inst: The delila instructions used to create the book. The delila instructions are of the form 'get from 56 -5 to 56 +10;' If this file is empty, then the sequences will be aligned either by their 5' ends or by their zero base, depending on the 4th parameter in bookshiftp. book: the book generated by delila using inst. bookshiftp: parameters to control the program. The file must contain the following parameters, one per line: parameterversion: The version number of the program. This allows the user to be warned if an old parameter file is used. The following parameter is required but only type 'i' has been implemented: The method of alignment, alignmenttype. See program alist for further details. If the first character is 'f' (for 'first') then the sequences are always aligned by their first base. 'i' then the sequences are aligned by the delila instructions. If the inst file is empty, alignment is forced to the 'b' mode. 'b' (for 'internal') then the alignment is on the internal zero of the book's sequence. This option is to be used when "default coordinate zero" is used in the Delila instructions. bookout: the book, realigned according to the inst. output: messages to the user description After constructing a model of a binding site one would like to know something about the density of that or other sites relative to the binding site. This can be done by scanning a Delila book which has an alignment so that the site zero base becomes the zero of each piece in the book. Then when the pieces are scanned, the coordinates are all common. The results of the scan can be plotted using the denplo program. Delila books can be assigned an alignment by an instruction file, but this preserves the original coordinate system in the book. The scan program (and biscan or multiscan) are not designed to use an inst file to align the results. Instead, the sequences in a book can be realigned by using the Delila instruction "set coordinate zero;" which then causes each output piece to have a zero according to the 'from' of the corresponding get instruction in the inst file. While changing the inst file and rerunning Delila is practical in most cases, some books built from whole genomes are extremely large, making it difficult to realign. The purpose of this bookshift program is to take an aligned set of sequences (the book/inst pair) and create a new book, bookout, in which each piece has a zero base set according to the inst. examples documentation see also {shifting Delila instructions instead of a book:} instshift.p {scanning programs: } scan.p multiscan.p {plotting program: } denplo.p {check book/inst alignment: } alist.p {program used to get the basis of this one: } range.p {source for better get scanning: } delmod.p author Thomas Dana Schneider bugs The mechanism to read the inst file is not robust and will fail if the word 'get' is inside comments or quotes. This can be fixed by taking code from procedure align in delmod.p technical notes */ /* end module describe.bookshift */ /* begin module book.const */ /* constants needed for book manipulations */ #define dnamax 1024 /* length of dna arrays */ #define namelength 100 /* maximum key name length */ #define linelength 80 /* maximum line readable in book */ /* end module book.const version = 7.62; {of delmod.p 2003 Jan 13} */ /* begin module interact.const */ /* begin module string.const */ #define maxstring 150 /* the maximum string */ /* end module string.const version = 4.39; (@ of prgmod.p 1999 November 28 */ /* end module interact.const version = 7.62; {of delmod.p 2003 Jan 13} */ /* begin module filler.const */ #define fillermax 50 /* the size of the filler array for a string */ /* end module filler.const version = 4.18; (@ of prgmod.p 1996 September 12 */ /* begin module interact.type */ /* begin module string.type */ /* pointer to a string */ typedef struct string { /* a string of characters */ Char letters[maxstring]; /* the letters in the string */ long length; /* the number of characters in the string */ long current; /* the letter we are working on */ Char *next; /* the next string in a series */ } string; /* end module string.type version = 4.39; (@ of prgmod.p 1999 November 28 */ /* end module interact.type version = 7.62; {of delmod.p 2003 Jan 13} */ /* begin module filler.type */ /* the following is an array used to fill a string. it is convenient to have it much shorter than the maxstring, so that it is easy to fill the string using procedure fillstring. the user must declare the value of constant fillermax. */ typedef Char filler[fillermax]; /* end module filler.type version = 4.18; (@ of prgmod.p 1996 September 12 */ /* begin module trigger.type */ typedef struct trigger { /* an object to be searched for */ string seek; /* the characters looked for */ long state; /* how close to triggering we are */ boolean skip; /* trigger not found- skip the line */ /* the trigger was found */ boolean found; } trigger; /* end module trigger.type version = 4.18; (@ of prgmod.p 1996 September 12 */ /* begin module book.type */ /* types needed for book manipulations */ typedef long chset[5]; /* types defined in book definition */ typedef Char alpha[namelength]; /* this is not alfa */ /* name is a left justified string with blanks following the characters */ typedef struct name { alpha letters; /* zero means an unspecified structure */ char length; } name; typedef struct line { /* a line of characters */ Char letters[linelength]; char length; struct line *next; } line; typedef enum { plus, minus, dircomplement, dirhomologous } direction; typedef enum { linear, circular } configuration; typedef enum { on, off } state; typedef struct header { /* header of key */ name keynam; /* key name of structure */ line *fulnam; /* full name of structure */ /* note key */ line *note; } header; /* begin module base.type */ /* define the four nucleotide bases */ typedef enum { a, c, g, t } base; /* end module base.type version = 7.62; {of delmod.p 2003 Jan 13} */ /* sequence types */ typedef short dnarange; /* p2c: bookshift.p, line 231: * Note: Field width for seq assumes enum base has 4 elements [105] */ typedef uchar seq[(dnamax + 3) / 4]; typedef struct dnastring { seq part; dnarange length; struct dnastring *next; } dnastring; typedef struct orgkey { /* organism key */ header hea; /* genetic map units */ line *mapunit; } orgkey; typedef struct chrkey { /* chromosome key */ header hea; double mapbeg; /* number of genetic map beginning */ /* number of genetic map ending */ double mapend; } chrkey; typedef struct piekey { /* piece key */ header hea; double mapbeg; /* genetic map beginning */ configuration coocon; /* configruation (circular/linear) */ direction coodir; /* direction (+/-) relative to genetic map */ long coobeg; /* beginning nucleotide */ long cooend; /* ending nucleotide */ configuration piecon; /* configruation (circular/linear) */ direction piedir; /* direction (+/-) relative to coordinates */ long piebeg; /* beginning nucleotide */ long pieend; /* ending nucleotide */ } piekey; typedef struct piece { piekey key; dnastring *dna; } piece; typedef struct reference { name pienam; /* name of piece referred to */ double mapbeg; /* genetic map beginning */ direction refdir; /* direction relative to coordinates */ long refbeg; /* beginning nucleotide */ long refend; /* ending nucleotide */ } reference; typedef struct genkey { /* gene key */ header hea; reference ref; } genkey; typedef struct trakey { /* transcript key */ header hea; reference ref; } trakey; typedef struct markey { /* marker key */ header hea; reference ref; state sta; line *phenotype; struct marker *next; } markey; typedef struct marker { markey key; dnastring *dna; } marker; /* end module book.type version = 7.62; {of delmod.p 2003 Jan 13} */ Static _TEXT book, inst; /* file used by this program */ Static _TEXT bookshiftp; /* file used by this program */ Static _TEXT bookout; /* file used by this program */ /* begin module book.var */ /* ************************************************************************ */ /* global variables needed for book manipulations */ /* free storage: */ Static line *freeline; /* unused lines */ Static dnastring *freedna; /* unused dnas */ Static boolean readnumber; /* whether to read a number from the notes, or to read in the notes */ Static long number; /* the number of the item just read */ Static boolean numbered; /* true when the item just read is numbered */ Static boolean skipunnum; Static jmp_buf _JL1; /* a control variable to allow skipping of un-numbered items in the book */ /* ************************************************************************ */ /* end module book.var version = 7.62; {of delmod.p 2003 Jan 13} */ /* begin module halt */ Static Void halt() { /* stop the program. the procedure performs a goto to the end of the program. you must have a label: label 1; declared, and also the end of the program must have this label: 1: end. examples are in the module libraries. this is the only goto in the delila system. */ printf(" program halt.\n"); longjmp(_JL1, 1); } /* end module halt version = 7.62; {of delmod.p 2003 Jan 13} */ /******************************************************************************/ /******************************************************************************/ /******************************************************************************/ /* begin module package.trigger */ /* ************************************************************************ */ /* begin module interact.clearstring */ Static Void clearstring(ribbon) string *ribbon; { /* empty the string */ long index; /* to the ribbon */ for (index = 0; index < maxstring; index++) ribbon->letters[index] = ' '; ribbon->length = 0; ribbon->current = 0; } /* clearstring */ /* end module interact.clearstring version = 4.18; (@ of prgmod.p 1996 September 12 */ /* begin module interact.writestring */ Static Void writestring(tofile, s) _TEXT *tofile; string *s; { /* write the string s to file tofile, no writeln */ long i; /* index to s */ long FORLIM; FORLIM = s->length; for (i = 0; i < FORLIM; i++) putc(s->letters[i], tofile->f); } /* writestring */ /* end module interact.writestring version = 4.18; (@ of prgmod.p 1996 September 12 */ /* begin module filler.fillstring */ Static Void fillstring(s, a_) string *s; Char *a_; { /* this procedure makes it reasonably easy to fill the string s with characters. one calls the procedure as: */ /* 1 2 3 4 5 */ /* 12345678901234567890123456789012345678901234567890 */ /* fillstring(s, 'this-is-the-string '); the two comments make it easy to line the characters up. also, for this example, it was assumed that the length of filler as defined by the constant fillermax was 50. */ long length = fillermax; /* of the string without trailing blanks */ long index; /* of s */ clearstring(s); while (length > 1 && a_[length-1] == ' ') length--; if (length == 1 && a_[length-1] == ' ') { printf("fillstring: the string is empty\n"); halt(); } for (index = 0; index < length; index++) s->letters[index] = a_[index]; s->length = length; s->current = 1; } /* fillstring */ /* end module filler.fillstring version = 4.18; (@ of prgmod.p 1996 September 12 */ /* begin module filler.filltrigger */ Static Void filltrigger(t_, a_) trigger *t_; Char *a_; { /* fill the trigger t */ fillstring(&t_->seek, a_); } /* fillstring */ /* end module filler.filltrigger version = 4.18; (@ of prgmod.p 1996 September 12 */ /* begin module trigger.proc */ /* this module allows one to scan a series of characters, as from an array or a file, and to "trigger" or detect a simple string in the series. the advantage of the trigger is that several triggers can "observe" a stream of characters at once, each looking for a different thing. some other modules required: interact.const, interact.type */ Static Void resettrigger(t_) trigger *t_; { /* reset the trigger to ground state */ t_->state = 0; t_->skip = false; t_->found = false; } /* resettrigger */ Static Void testfortrigger(ch, t_) Char ch; trigger *t_; { /* look at the character ch. if it is part of the trigger (at the current trigger state), then the trigger state goes higher. if it is not part of the trigger then the trigger state is reset, skip is true and one should skip onward to find the trigger. if the trigger is found, found is true. 1996 Sep 12: Bug found! In the case of a trigger "ab", the program used to miss it for situations like "aab". This was because at the first a it would step up. Then it would see the second a and recognize that was not part of ab. It would fail to realize that it could be the start of a new one. The code now accounts for that possibility. */ t_->state++; /* writestring(list,seek); writeln(list,'testfortrigger seek.letters[',state:1,']:', seek.letters[state],' ch:',ch); */ if (t_->seek.letters[t_->state - 1] == ch) { t_->skip = false; if (t_->state == t_->seek.length) t_->found = true; else t_->found = false; return; } /* it failed. But wait! It could be the beginning of a NEW trigger string! */ if (t_->seek.letters[0] == ch) { t_->state = 1; t_->skip = false; t_->found = false; return; } t_->state = 0; t_->skip = true; t_->found = false; /* reset trigger */ } /* testfortrigger */ /* end module trigger.proc version = 4.18; (@ of prgmod.p 1996 September 12 */ /* begin module skipblanks */ Static Void skipblanks(thefile) _TEXT *thefile; { /* skip over blanks until a non-blank, or end of line, is found */ while ((P_peek(thefile->f) == ' ') & (!P_eoln(thefile->f))) getc(thefile->f); } Static Void skipnonblanks(thefile) _TEXT *thefile; { /* skip over nonblanks until a blank, or end of line, is found */ while ((P_peek(thefile->f) != ' ') & (!P_eoln(thefile->f))) getc(thefile->f); } Static Void skipcolumn(thefile) _TEXT *thefile; { /* skip over a data column */ skipblanks(thefile); skipnonblanks(thefile); } /* end module skipblanks version = 4.18; (@ of prgmod.p 1996 September 12 */ /* ************************************************************************ */ /* end module package.trigger version = 4.18; (@ of prgmod.p 1996 September 12 */ /******************************************************************************/ /******************************************************************************/ /******************************************************************************/ /* begin module package.getpiece */ /* ************************************************************************ */ /* begin module package.brpiece */ /* ************************************************************************ */ /* begin module book.basis */ /* procedures needed for book manipulations */ /* get procedures should be used for all linked lists of records */ Static Void getline(l) line **l; { /* obtain a line from the free line list or by making a new one */ if (freeline != NULL) { *l = freeline; freeline = freeline->next; } else *l = (line *)Malloc(sizeof(line)); (*l)->length = 0; (*l)->next = NULL; } Static Void getdna(l) dnastring **l; { if (freedna != NULL) { *l = freedna; freedna = freedna->next; } else *l = (dnastring *)Malloc(sizeof(dnastring)); (*l)->length = 0; (*l)->next = NULL; } /* clear procedures should be called each time the records are no longer needed failure to do this may result in a stack overflow. */ Static Void clearline(l) line **l; { /* return a line to the free line list */ line *lptr; if (*l == NULL) return; lptr = *l; *l = (*l)->next; lptr->next = freeline; freeline = lptr; } Static Void writeline(afile, l, carriagereturn) _TEXT *afile; line *l; boolean carriagereturn; { /* write a line to a file, with carriage return if carriagereturn is true. */ long index; /* index to characters in l */ long FORLIM; FORLIM = l->length; for (index = 0; index < FORLIM; index++) putc(l->letters[index], afile->f); if (carriagereturn) putc('\n', afile->f); } Static Void showfreedna() { /* show the freedna list */ long counter = 0; /* count of freedna list */ dnastring *l; /* pointer into freedna list */ l = freedna; while (l != NULL) { counter++; printf("%ld", counter); printf(", length = %d\n", l->length); /* This is illegal according to gpc because one cannot write a pointer to a text file. It can be unearthed for debugging. write(output, ', pointer id: ',l:1); */ l = l->next; } } Static Void cleardna(l) dnastring **l; { dnastring *lptr; if (*l == NULL) return; lptr = *l; *l = (*l)->next; lptr->next = freedna; freedna = lptr; } Static Void clearheader(h) header *h; { /* clear the header h (remove lines to free storage) */ clearline(&h->fulnam); while (h->note != NULL) clearline(&h->note); } Static Void clearpiece(p) piece **p; { /* clear the dna of the piece */ while ((*p)->dna != NULL) cleardna(&(*p)->dna); clearheader(&(*p)->key.hea); } Static base chartobase(ch) Char ch; { /* convert a character into a base */ base Result; switch (ch) { case 'a': Result = a; break; case 'c': Result = c; break; case 'g': Result = g; break; case 't': Result = t; break; } return Result; } Static Char basetochar(ba) base ba; { /* convert a base into a character */ Char Result; switch (ba) { case a: Result = 'a'; break; case c: Result = 'c'; break; case g: Result = 'g'; break; case t: Result = 't'; break; } return Result; } Static base complement(ba) base ba; { /* take the complement of ba */ base Result; switch (ba) { case a: Result = t; break; case c: Result = g; break; case g: Result = c; break; case t: Result = a; break; } return Result; } Static Char chomplement(b) Char b; { /* create the character complement of base b. I must be getting hungry! */ return (basetochar(complement(chartobase(b)))); } Static long pietoint(p, pie) long p; piece *pie; { /* p is a coordinate on the piece. we want to transform p into a number from 1 to n: an internal coordinate system for easy manipulation of piece coordinates */ /* Note: the dirhomologous and dircomplement are treated as plus and minus directions, which MIGHT NOT BE RIGHT! */ long i; /* an intermediate value */ piekey *WITH; WITH = &pie->key; switch (WITH->piedir) { case dirhomologous: case plus: if (p >= WITH->piebeg) i = p - WITH->piebeg + 1; else i = p - WITH->coobeg + WITH->cooend - WITH->piebeg + 2; break; case dircomplement: case minus: if (p <= WITH->piebeg) i = WITH->piebeg - p + 1; else i = WITH->cooend - p + WITH->piebeg - WITH->coobeg + 2; break; } return i; } Static long inttopie(i, pie) long i; piece *pie; { /* i is in the range 1 to some maximum. it is an internal coordinate system for the program. we want to do a coordinate transformation to obtain a value in the range of the piece called pie: i=1 corresponds to piebeg and i=its maximum corresponds to pieend */ /* Note: the dirhomologous and dircomplement are treated as plus and minus directions, which MIGHT NOT BE RIGHT! */ long p; /* an intermediate value */ piekey *WITH; WITH = &pie->key; switch (WITH->piedir) { case dirhomologous: case plus: p = WITH->piebeg + i - 1; if (p > WITH->cooend) { if (WITH->coocon == circular) p += WITH->coobeg - WITH->cooend - 1; } break; case dircomplement: case minus: p = WITH->piebeg - i + 1; if (p < WITH->coobeg) { if (WITH->coocon == circular) p += WITH->cooend - WITH->coobeg + 1; } break; } return p; } Static long piecelength(pie) piece *pie; { /* return the length of the dna in pie */ return (pietoint(pie->key.pieend, pie)); } /* end module book.basis version = 7.62; {of delmod.p 2003 Jan 13} */ /* begin module book.getto */ Static Char getto(thefile, theline, ch) _TEXT *thefile; long *theline; long *ch; { /* search the file for a character in the first line which is a member of the set ch. Note: on 1999 March 10 the definition of this function was cleaned up. Instead of putting thefile on the line AFTER the charcter ch has been found, it puts thefile ON the line. Other routines like brdna and brpiece have to move to the next line themselves. This makes getto give the OBJECT. */ Char achar = ' '; /* a character in thefile */ boolean done = false; /* done finding achar */ while (!done) { if (BUFEOF(thefile->f)) { done = true; break; } achar = P_peek(thefile->f); if (P_inset(achar, ch)) { done = true; break; } fscanf(thefile->f, "%*[^\n]"); getc(thefile->f); (*theline)++; } if (P_inset(achar, ch)) return achar; else { return ' '; /* The old method - while (not(achar in ch)) and (not eof(thefile)) do begin readln(thefile,achar); theline := succ(theline) end; if (achar in ch) then getto:=achar else getto:=' ' */ } } /* end module book.getto version = 7.62; {of delmod.p 2003 Jan 13} */ /* begin module book.skipstar */ Static Void skipstar(thefile) _TEXT *thefile; { /* skip start of line (or star = '*'). */ if (BUFEOF(thefile->f)) { printf(" procedure skipstar: end of book found\n"); halt(); return; } if (P_peek(thefile->f) != '*') { printf(" procedure skipstar: bad book\n"); printf(" \"*\" expected as first character on the line, but \"%c\" was found\n", P_peek(thefile->f)); halt(); } getc(thefile->f); /* skip the star */ if (P_peek(thefile->f) != ' ') { /* skip the blank */ printf(" procedure skipstar: bad book\n"); printf(" \"* \" expected on a line but \"*%c\" was found\n", P_peek(thefile->f)); halt(); } getc(thefile->f); } /* skipstar */ /* end module book.skipstar version = 7.62; {of delmod.p 2003 Jan 13} */ /* begin module book.brreanum */ Static Void brreanum(thefile, theline, reanum) _TEXT *thefile; long *theline; double *reanum; { /* read a real number from the file */ skipstar(thefile); fscanf(thefile->f, "%lg%*[^\n]", reanum); getc(thefile->f); (*theline)++; } /* end module book.brreanum version = 7.62; {of delmod.p 2003 Jan 13} */ /* begin module book.brnumber */ Static Void brnumber(thefile, theline, num) _TEXT *thefile; long *theline, *num; { /* read a number from the file */ skipstar(thefile); fscanf(thefile->f, "%ld%*[^\n]", num); getc(thefile->f); (*theline)++; } /* end module book.brnumber version = 7.62; {of delmod.p 2003 Jan 13} */ /* begin module book.brname */ Static Void brname(thefile, theline, nam) _TEXT *thefile; long *theline; name *nam; { /* read a name from the file */ long i; /* an index to the name */ Char c_; /* a character read */ skipstar(thefile); nam->length = 0; do { nam->length++; c_ = getc(thefile->f); if (c_ == '\n') c_ = ' '; nam->letters[nam->length - 1] = c_; } while (!(P_eoln(thefile->f) || nam->length >= namelength || nam->letters[nam->length - 1] == ' ')); if (nam->letters[nam->length - 1] == ' ') nam->length--; if (nam->length < namelength) { for (i = nam->length; i < namelength; i++) nam->letters[i] = ' '; } fscanf(thefile->f, "%*[^\n]"); getc(thefile->f); (*theline)++; } /* brname */ /* end module book.brname version = 7.62; {of delmod.p 2003 Jan 13} */ /* begin module book.brline */ Static Void brline(thefile, theline, l) _TEXT *thefile; long *theline; line **l; { /* read a line from the file */ long i = 0; Char acharacter; skipstar(thefile); while (!P_eoln(thefile->f)) { i++; acharacter = getc(thefile->f); if (acharacter == '\n') acharacter = ' '; (*l)->letters[i-1] = acharacter; } (*l)->length = i; (*l)->next = NULL; fscanf(thefile->f, "%*[^\n]"); getc(thefile->f); (*theline)++; } /* end module book.brline version = 7.62; {of delmod.p 2003 Jan 13} */ /* begin module book.brdirect */ Static Void brdirect(thefile, theline, direct) _TEXT *thefile; long *theline; direction *direct; { /* read a direction */ Char ch; skipstar(thefile); fscanf(thefile->f, "%c%*[^\n]", &ch); getc(thefile->f); if (ch == '\n') ch = ' '; (*theline)++; if (ch == '+') *direct = plus; else *direct = minus; } /* end module book.brdirect version = 7.62; {of delmod.p 2003 Jan 13} */ /* begin module book.brconfig */ Static Void brconfig(thefile, theline, config) _TEXT *thefile; long *theline; configuration *config; { /* read a configuration */ Char ch; skipstar(thefile); fscanf(thefile->f, "%c%*[^\n]", &ch); getc(thefile->f); if (ch == '\n') ch = ' '; (*theline)++; if (ch == 'l') *config = linear; else *config = circular; } /* end module book.brconfig version = 7.62; {of delmod.p 2003 Jan 13} */ /* begin module book.brnotenumber */ Static Void brnotenumber(thefile, theline, note) _TEXT *thefile; long *theline; line **note; { /* book note reading to obtain the number of the object. the procedure returns the value of the number as a global. (this is not such a good practice, but we are stuck with it for now.) */ *note = NULL; numbered = false; number = 0; /* force number to zero if there is no number at all */ /* the next character is n or * depending on whether there are notes */ if (P_peek(thefile->f) != 'n') return; fscanf(thefile->f, "%*[^\n]"); getc(thefile->f); (*theline)++; if (P_peek(thefile->f) != 'n') { skipstar(thefile); if (!P_eoln(thefile->f)) { if (P_peek(thefile->f) == '#') { numbered = true; getc(thefile->f); /* move past the number symbol */ fscanf(thefile->f, "%ld", &number); } } do { fscanf(thefile->f, "%*[^\n]"); getc(thefile->f); (*theline)++; } while (P_peek(thefile->f) != 'n'); fscanf(thefile->f, "%*[^\n]"); getc(thefile->f); (*theline)++; return; } fscanf(thefile->f, "%*[^\n]"); getc(thefile->f); (*theline)++; } /* brnotenumber */ /* end module book.brnotenumber version = 7.62; {of delmod.p 2003 Jan 13} */ /* begin module book.brnote */ Static Void brnote(thefile, theline, note) _TEXT *thefile; long *theline; line **note; { /* read note key */ line *newnote; /* the new note */ line *previousnote; /* the last line of the notes */ *note = NULL; if (P_peek(thefile->f) != 'n') /* enter note */ return; fscanf(thefile->f, "%*[^\n]"); getc(thefile->f); (*theline)++; if (P_peek(thefile->f) != 'n') { /* abort null note (n/n) */ getline(note); newnote = *note; while (P_peek(thefile->f) != 'n') { /* wait until end of note */ brline(thefile, theline, &newnote); previousnote = newnote; /* get next note */ getline(&newnote->next); newnote = newnote->next; } /* last note was not used, so: */ clearline(&newnote); previousnote->next = NULL; fscanf(thefile->f, "%*[^\n]"); getc(thefile->f); (*theline)++; return; } fscanf(thefile->f, "%*[^\n]"); getc(thefile->f); (*theline)++; } /* brnote */ /* end module book.brnote version = 7.62; {of delmod.p 2003 Jan 13} */ /* begin module book.brheader */ Static Void brheader(thefile, theline, hea) _TEXT *thefile; long *theline; header *hea; { /* read the header of a key. */ fscanf(thefile->f, "%*[^\n]"); getc(thefile->f); /* move past the object name - new definition 1999 Mar 13 */ (*theline)++; /*bbb*/ /* read key name */ brname(thefile, theline, &hea->keynam); /* read full name */ getline(&hea->fulnam); brline(thefile, theline, &hea->fulnam); /* read note key */ if (readnumber) brnotenumber(thefile, theline, &hea->note); else brnote(thefile, theline, &hea->note); } /* end module book.brheader version = 7.62; {of delmod.p 2003 Jan 13} */ /* begin module book.copyheader */ Static Void copyheader(fromhea, tohea) header fromhea, *tohea; { /* copy the header fromhea into tohea. Note that the linked objects are NOT copied, but merely pointed to. */ memcpy(tohea->keynam.letters, fromhea.keynam.letters, sizeof(alpha)); tohea->keynam.length = fromhea.keynam.length; tohea->note = fromhea.note; tohea->fulnam = fromhea.fulnam; } /* end module book.copyheader version = 7.62; {of delmod.p 2003 Jan 13} */ /* begin module book.brpiekey */ Static Void brpiekey(thefile, theline, pie) _TEXT *thefile; long *theline; piekey *pie; { /* read piece key, track the line number */ brheader(thefile, theline, &pie->hea); brreanum(thefile, theline, &pie->mapbeg); brconfig(thefile, theline, &pie->coocon); brdirect(thefile, theline, &pie->coodir); brnumber(thefile, theline, &pie->coobeg); brnumber(thefile, theline, &pie->cooend); brconfig(thefile, theline, &pie->piecon); brdirect(thefile, theline, &pie->piedir); brnumber(thefile, theline, &pie->piebeg); brnumber(thefile, theline, &pie->pieend); } /* end module book.brpiekey version = 7.62; {of delmod.p 2003 Jan 13} */ /* begin module book.brdna */ Static Void brdna(thefile, theline, dna) _TEXT *thefile; long *theline; dnastring **dna; { /* read in dna from thefile, track the line */ /* note: if the dna were circularized, by linking the last dnastring to the first, then the cleardna routine could not clear properly, and would loop forever... there is no reason to do that, since a simple mod function will allow one to access the circle. */ Char ch; dnastring *workdna; long SET[5]; long TEMP; getdna(dna); workdna = *dna; ch = getto(thefile, theline, P_addset(P_expset(SET, 0L), 'd')); fscanf(thefile->f, "%*[^\n]"); getc(thefile->f); (*theline)++; ch = getc(thefile->f); /* skipstar */ if (ch == '\n') ch = ' '; while (ch == '*') { ch = getc(thefile->f); /* skip blank */ if (ch == '\n') ch = ' '; do { ch = getc(thefile->f); if (ch == '\n') ch = ' '; if (ch == 't' || ch == 'g' || ch == 'c' || ch == 'a') { if (workdna->length == dnamax) { getdna(&workdna->next); workdna = workdna->next; } workdna->length++; TEMP = workdna->length - 1; P_clrbits_B(workdna->part, TEMP, 1, 3); P_putbits_UB(workdna->part, TEMP, (int)chartobase(ch), 1, 3); } } while (!P_eoln(thefile->f)); fscanf(thefile->f, "%*[^\n]"); getc(thefile->f); /* go to next line */ (*theline)++; ch = getc(thefile->f); /* ch is either '*' or 'd' */ if (ch == '\n') ch = ' '; } fscanf(thefile->f, "%*[^\n]"); getc(thefile->f); /* read past the d */ (*theline)++; } /* end module book.brdna version = 7.62; {of delmod.p 2003 Jan 13} */ /* begin module book.brpiece */ Static Void brpiece(thefile, theline, pie) _TEXT *thefile; long *theline; piece **pie; { /* read in a piece, change theline to reflect the lines traversed */ /* readln(thefile); (* move past the word 'piece' - new definition 1999 Mar 13 *) theline := succ(theline); (* BUG: was below! *) bbb*/ brpiekey(thefile, theline, &(*pie)->key); if (numbered || !skipunnum) brdna(thefile, theline, &(*pie)->dna); fscanf(thefile->f, "%*[^\n]"); getc(thefile->f); /* move past the word 'piece' - new definition 1999 Mar 13 */ (*theline)++; } /* end module book.brpiece version = 7.62; {of delmod.p 2003 Jan 13} */ /* begin module book.brinit */ Static Void brinit(book, theline) _TEXT *book; long *theline; { /* check that the book is ok to read, and set up the global variables for br routines */ /* halt if the book is bad (first word is 'halt') or the first character is not * */ if (*book->name != '\0') { if (book->f != NULL) book->f = freopen(book->name, "r", book->f); else book->f = fopen(book->name, "r"); } else rewind(book->f); if (book->f == NULL) _EscIO2(FileNotFound, book->name); RESETBUF(book->f, Char); if (!BUFEOF(book->f)) { /* check for the date line */ if (P_peek(book->f) != '*') { if (P_peek(book->f) != 'h') printf(" this is not the first line of a book:\n"); else printf(" bad book:\n"); putchar(' '); while (!(P_eoln(book->f) | BUFEOF(book->f))) { putchar(P_peek(book->f)); getc(book->f); } putchar('\n'); halt(); } } else { printf(" book is empty\n"); halt(); } /* initialize free storage */ freeline = NULL; freedna = NULL; readnumber = true; /* usually we read in numbers for items */ number = 0; /* arbitrary value */ numbered = false; /* the piece has no number (none yet read in) */ skipunnum = false; *theline = 1; } /* brinit */ /* end module book.brinit version = 7.62; {of delmod.p 2003 Jan 13} */ /* ************************************************************************ */ /* end module package.brpiece version = 7.62; {of delmod.p 2003 Jan 13} */ /* begin module book.getpiece */ Static Void getpiece(thefile, theline, pie) _TEXT *thefile; long *theline; piece **pie; { /* move to and read in the next piece in the book */ Char ch; long SET[5]; ch = getto(thefile, theline, P_addset(P_expset(SET, 0L), 'p')); /* get to the next p(iece) in the book */ if (ch != ' ') { brpiece(thefile, theline, pie); /* 1999 june 2: removed this: ch:=getto(thefile,theline,['p']); (* read to end of p *) */ /* bbb - now done in brpiece readln(thefile); (* read past piece *) theline := succ(theline); */ } else clearpiece(pie); } /* end module book.getpiece version = 7.62; {of delmod.p 2003 Jan 13} */ /* ************************************************************************ */ /* end module package.getpiece version = 7.62; {of delmod.p 2003 Jan 13} */ /* begin module findblank */ Static Void findblank(afile) _TEXT *afile; { /* read a file to find the next blank character */ Char ch; do { ch = getc(afile->f); if (ch == '\n') ch = ' '; } while (ch != ' '); } /* end module findblank version = 7.62; {of delmod.p 2003 Jan 13} */ /* begin module findnonblank */ Static Void findnonblank(afile, ch) _TEXT *afile; Char *ch; { /* find the next non blank character in a file, return it in ch. */ *ch = ' '; while (!BUFEOF(afile->f) && *ch == ' ') { *ch = getc(afile->f); if (*ch == '\n') *ch = ' '; if (P_eoln(afile->f)) { fscanf(afile->f, "%*[^\n]"); getc(afile->f); } } } /* end module findnonblank version = 7.62; {of delmod.p 2003 Jan 13} */ /*qqq*/ /* begin module book.brorgkey */ Static Void brorgkey(thefile, theline, org) _TEXT *thefile; long *theline; orgkey *org; { /* read organism key */ /*bbb*/ brheader(thefile, theline, &org->hea); getline(&org->mapunit); brline(thefile, theline, &org->mapunit); } /* end module book.brorgkey version = 7.62; {of delmod.p 2003 Jan 13} */ /* begin module book.brchrkey */ Static Void brchrkey(thefile, theline, chr) _TEXT *thefile; long *theline; chrkey *chr; { /* read chromosome key */ /*bbb*/ brheader(thefile, theline, &chr->hea); brreanum(thefile, theline, &chr->mapbeg); brreanum(thefile, theline, &chr->mapend); } /* end module book.brchrkey version = 7.62; {of delmod.p 2003 Jan 13} */ /* begin module book.getocp */ Static Void getocp(thefile, theline, org, orgchange, orgopen, chr, chrchange, chropen, pie, piechange, pieopen) _TEXT *thefile; long *theline; orgkey *org; boolean *orgchange, *orgopen; chrkey *chr; boolean *chrchange, *chropen; piece **pie; boolean *piechange, *pieopen; { /* Get the next piece and its organism and chromosome keys. The three change variables indicate whether or not a new organism, chromosome or piece name was found. If a piece is not found, then pieopen will be false. orgopen, chropen and pieopen are used by getocp to tell when it has entered an organism, chromosome or piece. All booleans should be set to false initially. There should be one triplet for each book read. It is important to initialize ALL variables, including pie: orgchange := false; orgopen := false; chrchange := false; chropen := false; piechange := false; pieopen := false; pie := nil; theline := 0; 1999 June 2 The book reading routines now treat data objects more precisely. Rather than test for eof, the endo of book occurs when pieopen is returned as false. A book reading loop now looks like this: repeat getocp(book, theline, org, orgchange, orgopen, chr, chrchange, chropen, pie, piechange, pieopen); writeln(output,'pieopen: ',pieopen); if pieopen then begin writeln(output,'piece at line: ',theline:1); end; until not pieopen; */ Char ch = 'a'; chrkey newchr; orgkey neworg; piece *newpie; long SET[5]; while (ch != 'p' && ch != ' ') { P_addset(P_expset(SET, 0L), 'o'); P_addset(SET, 'c'); ch = getto(thefile, theline, P_addset(SET, 'p')); if (ch == ' ') { *pieopen = false; break; } switch (ch) { case 'o': if (*orgopen) { fscanf(thefile->f, "%*[^\n]"); getc(thefile->f); /* move past the word 'organism' - new definition 1999 Mar 13 */ *orgopen = false; /* close organism */ } else { brorgkey(thefile, theline, &neworg); if (strncmp(neworg.hea.keynam.letters, org->hea.keynam.letters, sizeof(alpha)) && neworg.hea.keynam.length != org->hea.keynam.length) { /* writeln(output,'--------orgchanged!'); write (output,'--------old org:"', org.hea.keynam.letters); writeln(output, '" ', org.hea.keynam.length:1); write (output,'--------new org:"',neworg.hea.keynam.letters); writeln(output, '" ',neworg.hea.keynam.length:1); */ /*ccc*/ *orgchange = true; copyheader(neworg.hea, &org->hea); /* move the mapunit over to the org! */ org->mapunit = neworg.mapunit; clearline(&neworg.mapunit); } else *orgchange = false; *orgopen = true; } break; case 'c': if (*chropen) { fscanf(thefile->f, "%*[^\n]"); getc(thefile->f); /* move past the word 'chromosome' - new definition 1999 Mar 13 */ *chropen = false; /* close chromosome */ } else { brchrkey(thefile, theline, &newchr); if (strncmp(newchr.hea.keynam.letters, chr->hea.keynam.letters, sizeof(alpha)) && newchr.hea.keynam.length != chr->hea.keynam.length) { /* writeln(output,'--------chrchanged!'); write (output,'--------old chr:"', chr.hea.keynam.letters); writeln(output, '" ', chr.hea.keynam.length:1); write (output,'--------new chr:"',newchr.hea.keynam.letters); writeln(output, '" ',newchr.hea.keynam.length:1); */ *chrchange = true; copyheader(newchr.hea, &chr->hea); /* move the map range over to the chr! */ chr->mapbeg = newchr.mapbeg; chr->mapend = newchr.mapend; } else *chrchange = false; *chropen = true; } break; case 'p': if (*pieopen) { *pieopen = false; /* close last piece */ ch = 'a'; /* prevent falling out of the loop */ } else { newpie = (piece *)Malloc(sizeof(piece)); brpiece(thefile, theline, &newpie); if (*pie == NULL) *piechange = true; else { if (strncmp(newpie->key.hea.keynam.letters, (*pie)->key.hea.keynam.letters, sizeof(alpha)) && newpie->key.hea.keynam.length != (*pie)->key.hea.keynam.length) *piechange = true; else *piechange = false; } *pieopen = true; /* we always have to switch over to the new piece, because although the name may be the same, the DNA sequence could be different. That is, the book may contain two pieces with the same name, and we want to be sure to search the new one, not the old one. */ if (*pie != NULL) { clearpiece(pie); /* save the links */ Free(*pie); /* close up shop */ } *pie = newpie; } break; } } } /* origin: search version = 6.39 */ /* end module book.getocp version = 7.62; {of delmod.p 2003 Jan 13} */ /* begin module package.bwrite */ /****************************************************************************/ /* this is a package of procedures for writing books, by gary stormo, aug 17, 1982 */ /* begin module book.bwbasics */ Static Void bwstartline(book) _TEXT *book; { /* start a line of output to the book */ fprintf(book->f, "* "); } Static Void bwline(book, l) _TEXT *book; line *l; { /* write a line to the book */ long i, FORLIM; if (l == NULL) return; bwstartline(book); if (l->length != 0) { FORLIM = l->length; for (i = 0; i < FORLIM; i++) putc(l->letters[i], book->f); } putc('\n', book->f); } Static Void bwtext(book, lines) _TEXT *book; line *lines; { /* write a set of lines to the book */ line *l = lines; while (l != NULL) { bwline(book, l); l = l->next; } } Static Void bwnote(book, note) _TEXT *book; line *note; { /* writes the notes pointed to by 'note' to 'book' */ if (note == NULL) return; fprintf(book->f, "note\n"); bwtext(book, note); fprintf(book->f, "note\n"); } Static Void bwnumber(book, num) _TEXT *book; long num; { /* write a number to the book */ bwstartline(book); fprintf(book->f, "%ld\n", num); /* pascal will expand the field as far as needed */ } Static Void bwreanum(book, reanum) _TEXT *book; double reanum; { /* write a real number to the book */ bwstartline(book); fprintf(book->f, "%1.2f\n", reanum); /* pascal will expand the field */ } Static Void bwstate(book, sta) _TEXT *book; state sta; { /* write a state to the book */ bwstartline(book); switch (sta) { case on: fprintf(book->f, "on\n"); break; case off: fprintf(book->f, "off\n"); break; } } Static Void bwname(book, nam) _TEXT *book; name nam; { /* write a name to the book */ long i; bwstartline(book); for (i = 0; i < nam.length; i++) putc(nam.letters[i], book->f); putc('\n', book->f); } Static Void bwdirect(book, direct) _TEXT *book; direction direct; { /* write a direction to the book */ bwstartline(book); switch (direct) { case plus: fprintf(book->f, "+\n"); break; case minus: fprintf(book->f, "-\n"); break; } } Static Void bwconfig(book, config) _TEXT *book; configuration config; { /* write a configuration to the book */ bwstartline(book); switch (config) { case linear: fprintf(book->f, "linear\n"); break; case circular: fprintf(book->f, "circular\n"); break; } } Static Void bwheader(book, hea) _TEXT *book; header hea; { /* write a key header to the book */ bwname(book, hea.keynam); bwline(book, hea.fulnam); bwnote(book, hea.note); } Static Void bworgkey(book, org) _TEXT *book; orgkey org; { /* write the organism key */ bwheader(book, org.hea); bwline(book, org.mapunit); } Static Void bwchrkey(book, chr) _TEXT *book; chrkey chr; { /* write the chromosome key */ bwheader(book, chr.hea); bwreanum(book, chr.mapbeg); bwreanum(book, chr.mapend); } /* end module book.bwbasics version = 7.62; {of delmod.p 2003 Jan 13} */ /* begin module book.bworg */ Static Void bworg(thefile, org, chropen, orgopen) _TEXT *thefile; orgkey org; boolean *chropen, *orgopen; { /* this writes the organism key 'org' to 'thefile', and returns 'orgopen' as true. if there is already a chromosome or organism open they are closed. */ if (*chropen) { fprintf(thefile->f, "chromosome\n"); *chropen = false; } if (*orgopen) fprintf(thefile->f, "organism\n"); fprintf(thefile->f, "organism\n"); bworgkey(thefile, org); *orgopen = true; } /* end module book.bworg version = 7.62; {of delmod.p 2003 Jan 13} */ /* begin module book.bwchr */ Static Void bwchr(thefile, chr, chropen) _TEXT *thefile; chrkey chr; boolean *chropen; { /* write the chromosome key 'chr' to 'thefile' and return chropen as true. if a chromosome is already open it is closed. */ if (*chropen) fprintf(thefile->f, "chromosome\n"); fprintf(thefile->f, "chromosome\n"); bwchrkey(thefile, chr); *chropen = true; } /* end module book.bwchr version = 7.62; {of delmod.p 2003 Jan 13} */ /* begin module book.bwdna */ Static Void bwdna(thefile, d) _TEXT *thefile; dnastring *d; { /* write the dna pointed to by 'd' to 'thefile' */ long i; /* index to the sequence */ long l; /* index to the number of bases on the line */ boolean newline = true; /* true when a new line should be started */ long FORLIM; fprintf(thefile->f, "dna\n"); while (d != NULL) { FORLIM = d->length; for (i = 1; i <= FORLIM; i++) { if (newline) { bwstartline(thefile); l = 0; newline = false; } fputc(basetochar((base)P_getbits_UB(d->part, i - 1, 1, 3)), thefile->f); l++; if (l % 60 == 0 || i == d->length && d->next == NULL) { /* end of line */ putc('\n', thefile->f); newline = true; } /* p2c: bookshift.p, line 1505: * Note: Using % for possibly-negative arguments [317] */ /* last base */ } d = d->next; } if (!newline) /* last base */ putc('\n', thefile->f); fprintf(thefile->f, "dna\n"); } /* end module book.bwdna version = 7.62; {of delmod.p 2003 Jan 13} */ /* begin module book.bwpie */ Static Void bwpie(thefile, pie) _TEXT *thefile; piece *pie; { /* writes the information pointed to by 'pie' to 'thefile' */ fprintf(thefile->f, "piece\n"); bwheader(thefile, pie->key.hea); bwstartline(thefile); fprintf(thefile->f, "%1.2f\n", pie->key.mapbeg); bwstartline(thefile); if (pie->key.coocon == circular) fprintf(thefile->f, "circular\n"); else fprintf(thefile->f, "linear\n"); bwstartline(thefile); if (pie->key.coodir == plus) fprintf(thefile->f, "+\n"); else fprintf(thefile->f, "-\n"); bwstartline(thefile); fprintf(thefile->f, "%ld\n", pie->key.coobeg); bwstartline(thefile); fprintf(thefile->f, "%ld\n", pie->key.cooend); bwstartline(thefile); if (pie->key.piecon == circular) fprintf(thefile->f, "circular\n"); else fprintf(thefile->f, "linear\n"); bwstartline(thefile); if (pie->key.piedir == plus) fprintf(thefile->f, "+\n"); else fprintf(thefile->f, "-\n"); bwstartline(thefile); fprintf(thefile->f, "%ld\n", pie->key.piebeg); bwstartline(thefile); fprintf(thefile->f, "%ld\n", pie->key.pieend); bwdna(thefile, pie->dna); fprintf(thefile->f, "piece\n"); } /* end module book.bwpie version = 7.62; {of delmod.p 2003 Jan 13} */ /* begin module book.bwref */ Static Void bwref(book, ref) _TEXT *book; reference ref; { /* write a key reference to the book */ bwname(book, ref.pienam); bwreanum(book, ref.mapbeg); bwdirect(book, ref.refdir); bwnumber(book, ref.refbeg); bwnumber(book, ref.refend); } /* end module book.bwref version = 7.62; {of delmod.p 2003 Jan 13} */ /* begin module book.bwgen */ Static Void bwgen(thefile, gene) _TEXT *thefile; genkey gene; { /* this proecdure writes to 'thefile' the information in 'gene', properly formatted; */ fprintf(thefile->f, "gene\n"); bwheader(thefile, gene.hea); bwref(thefile, gene.ref); fprintf(thefile->f, "gene\n"); } /* end module book.bwgen version = 7.62; {of delmod.p 2003 Jan 13} */ /* begin module book.bwtra */ Static Void bwtra(thefile, trans) _TEXT *thefile; trakey trans; { /* this proecdure writes to 'thefile' the information in 'trans', properly formatted; */ fprintf(thefile->f, "transcript\n"); bwheader(thefile, trans.hea); bwref(thefile, trans.ref); fprintf(thefile->f, "transcript\n"); } /* end module book.bwtra version = 7.62; {of delmod.p 2003 Jan 13} */ /* begin module book.bwmar */ Static Void bwmar(thefile, mark) _TEXT *thefile; marker mark; { /* this proecdure writes to 'thefile' the information in 'mark', properly formatted; */ long i, FORLIM; fprintf(thefile->f, "marker\n"); bwheader(thefile, mark.key.hea); bwref(thefile, mark.key.ref); bwstate(thefile, mark.key.sta); bwstartline(thefile); FORLIM = mark.key.phenotype->length; for (i = 0; i < FORLIM; i++) putc(mark.key.phenotype->letters[i], thefile->f); putc('\n', thefile->f); bwdna(thefile, mark.dna); fprintf(thefile->f, "marker\n"); } #define maximumrange 10000 /* if the alignment point is more than this distance from the piece ends, the program halts in an attempt to catch the alignment bug... 1991 Jan 11 It appears that the rewrite of the code has removed the bug, but the check will be kept. */ #define semicolon ';' /* end of delila instruction */ /* Local variables for alignwrite: */ struct LOC_alignwrite { _TEXT *inst; Char ch; /* a character in inst */ trigger endcomment; /* trigger to find '*-)' (ignore the dash!) */ trigger endcurly; /* trigger to find comments: '}' */ } ; /* procedure rd(var f: text; var ch: char); (* read ch from f allowing inspection of the result *) begin read(f,ch); write(output,ch); write(list,ch); write(output,'<',ch,'>'); end; procedure rdln(var f: text); (* readln f allowing inspection of the result *) begin readln(f); writeln(output); writeln(list); end; */ Local Void skipcomment(f, LINK) _TEXT *f; struct LOC_alignwrite *LINK; { /* skip an entire comment */ boolean comment = true; /* true means we are inside a comment */ /* skip to end of comment */ resettrigger(&LINK->endcomment); while (comment) { if (BUFEOF(f->f)) { printf("A comment does not end!\n"); halt(); } if (P_eoln(f->f)) { fscanf(f->f, "%*[^\n]"); getc(f->f); continue; } /* rdln(f) */ LINK->ch = getc(f->f); if (LINK->ch == '\n') LINK->ch = ' '; testfortrigger(LINK->ch, &LINK->endcomment); if (LINK->endcomment.found) { comment = false; /*write(output,'<'); rd(f,ch); write(output,'>');*/ } } } Local Void skipcurly(f, LINK) _TEXT *f; struct LOC_alignwrite *LINK; { /* skip an entire comment made by {}*/ boolean comment = true; /* true means we are inside a comment */ /* skip to end of comment */ resettrigger(&LINK->endcurly); while (comment) { if (BUFEOF(f->f)) { printf("A comment does not end!\n"); halt(); } if (P_eoln(f->f)) { fscanf(f->f, "%*[^\n]"); getc(f->f); continue; } /* rdln(f) */ LINK->ch = getc(f->f); if (LINK->ch == '\n') LINK->ch = ' '; testfortrigger(LINK->ch, &LINK->endcurly); if (LINK->endcurly.found) { comment = false; /*write(output,'<'); rd(f,ch); write(output,'>');*/ } } } Local Void skipquote(quote, LINK) trigger quote; struct LOC_alignwrite *LINK; { /* skip an entire quote of either the ' or " persuasion */ Char kind; /* the kind of quote, ' or " */ kind = quote.seek.letters[0]; /*writeln(output,'skipquote ',kind);*/ do { findnonblank(LINK->inst, &LINK->ch); /* get to the quote */ } while (!((LINK->ch == kind) | BUFEOF(LINK->inst->f))); if (LINK->ch != kind) { printf("end of quote starting with %c not found\n", kind); halt(); } } /* end module book.bwmar version = 7.62; {of delmod.p 2003 Jan 13} */ /****************************************************************************/ /* end module package.bwrite version = 7.62; {of delmod.p 2003 Jan 13} */ /*qqq*/ /* begin module align.write */ /*aaa*/ Static Void alignwrite(inst_, book, theline, length, alignedbase, org, orgchange, orgopen, chr, chrchange, chropen, pie, piechange, pieopen) _TEXT *inst_, *book; long *theline, *length, *alignedbase; orgkey *org; boolean *orgchange, *orgopen; chrkey *chr; boolean *chrchange, *chropen; piece **pie; boolean *piechange, *pieopen; { /* documentation on align is in module info.align and delman.use.aligned.books. 1996 Sep 12: The routine now uses the trigger functions found in prgmod. The bug in the oldalign routine (that it misses the end of comments that end in a series of astrisks) has been fixed. It now checks that the piece corresponds to the book. */ struct LOC_alignwrite V; long p; /* index to a piece name */ long p1; /* another index to a piece name */ boolean done = false; /* done finding an aligning get */ long thebase; /* the base read in */ boolean indefault = false; /* true when within a default statement. These can contain the word 'piece', which must be ignored. */ trigger gettrigger; /* trigger to find 'get' */ trigger defaulttrigger; /* trigger to find 'default' */ trigger nametrigger; /* trigger to find 'name' */ trigger piecetrigger; /* trigger to find 'piece' */ trigger settrigger; /* trigger to find 'set' */ trigger begincomment; /* trigger to find '(-*' (ignore the dash!) */ trigger begincurly; /* trigger to find comments: '{' */ trigger quote1trigger; /* trigger to find single quote ' */ trigger quote2trigger; /* trigger to find double quote " */ _TEXT TEMP; name *WITH; long FORLIM; V.inst = inst_; filltrigger(&defaulttrigger, "default "); filltrigger(&gettrigger, "get "); filltrigger(&nametrigger, "name "); filltrigger(&piecetrigger, "piece "); filltrigger(&settrigger, "set "); filltrigger(&begincomment, "(* "); filltrigger(&V.endcomment, "*) "); filltrigger(&begincurly, "{ "); filltrigger(&V.endcurly, "} "); filltrigger("e1trigger, "' "); filltrigger("e2trigger, "\" "); resettrigger(&defaulttrigger); resettrigger(&gettrigger); resettrigger(&nametrigger); resettrigger(&piecetrigger); resettrigger(&settrigger); resettrigger(&begincomment); resettrigger(&begincurly); resettrigger("e1trigger); resettrigger("e2trigger); if (BUFEOF(book->f)) /* if there is still more to the book ... */ return; printf("before getocp line %ld\n", *theline); getocp(book, theline, org, orgchange, orgopen, chr, chrchange, chropen, pie, piechange, pieopen); printf("after getocp line %ld\n", *theline); /* getpiece(book,theline,pie); (* read in the piece *) */ if (*orgopen) printf("orgopen at line %ld\n", *theline); else printf("NO orgopen at line %ld\n", *theline); if (*chropen) printf("chropen at line %ld\n", *theline); else printf("NO chropen at line %ld\n", *theline); if (*orgchange) printf("orgchange at line %ld\n", *theline); else printf("NO orgchange at line %ld\n", *theline); if (*chrchange) printf("chrchange at line %ld\n", *theline); else printf("NO chrchange at line %ld\n", *theline); if (*orgchange) { printf("WRITE ORG\n"); /*OUT*/ /*OUT*/ TEMP.f = stdout; *TEMP.name = '\0'; bworg(&TEMP, *org, chropen, orgopen); /*hhh*/ bworg(&bookout, *org, chropen, orgopen); printf("WRITE ORG DONE\n"); halt(); } if (*chrchange) { printf("WRITE CHR\n"); /* bwchr(output, chr, chropen); */ *chropen = false; /*OUT*/ bwchr(&bookout, *chr, chropen); printf("WRITE CHR DONE\n"); } if (BUFEOF(book->f)) /* if we found a piece ... */ return; *length = pietoint((*pie)->key.pieend, *pie); /* calculate piece length */ /* now find in inst the next occurance of 'get' */ while (!done) { if (BUFEOF(V.inst->f)) { /* no instructions? */ *alignedbase = 1; /* simply align by the first base */ done = true; break; } if (P_eoln(V.inst->f)) { fscanf(V.inst->f, "%*[^\n]"); getc(V.inst->f); continue; } /*then rdln(inst)*/ V.ch = getc(V.inst->f); if (V.ch == '\n') V.ch = ' '; testfortrigger(V.ch, &begincomment); testfortrigger(V.ch, &begincurly); if (begincomment.found || begincurly.found) { if (V.ch == '*') { skipcomment(V.inst, &V); resettrigger(&begincomment); } else { resettrigger(&begincurly); skipcurly(V.inst, &V); } continue; } testfortrigger(V.ch, &gettrigger); if (gettrigger.found) { findnonblank(V.inst, &V.ch); /* get to "from" */ findblank(V.inst); /* get past "from" */ fscanf(V.inst->f, "%ld", &thebase); /* read in the alignedbase */ /*writeln(output);writeln(output,'thebase = ',thebase:1);*/ *alignedbase = pietoint(thebase, *pie); /*writeln(output,'alignedbase=',alignedbase:1);*/ done = true; } testfortrigger(V.ch, "e1trigger); if (quote1trigger.found) skipquote(quote1trigger, &V); testfortrigger(V.ch, "e2trigger); if (quote2trigger.found) skipquote(quote2trigger, &V); testfortrigger(V.ch, &defaulttrigger); if (defaulttrigger.found) { indefault = true; resettrigger(&defaulttrigger); } if (V.ch == semicolon) indefault = false; testfortrigger(V.ch, &settrigger); if (settrigger.found) { indefault = true; resettrigger(&settrigger); } if (V.ch == semicolon) indefault = false; /* check that piece names are correct */ testfortrigger(V.ch, &piecetrigger); if (indefault) continue; if (!piecetrigger.found) continue; skipblanks(V.inst); /* get to name */ WITH = &(*pie)->key.hea.keynam; FORLIM = WITH->length; for (p = 1; p <= FORLIM; p++) { V.ch = getc(V.inst->f); if (V.ch == '\n') V.ch = ' '; if (WITH->letters[p-1] != V.ch) { printf("The piece name in the book: \n"); /* p2c: bookshift.p, line 1928: Note: * Format for packed-array-of-char will work only if width < length [321] */ printf("%.*s\n", WITH->length, WITH->letters); printf("does not match the inst file name:\n"); /* write the letters that matched: */ for (p1 = 1; p1 < p; p1++) putchar(WITH->letters[p-1]); /* write the offending letter: */ putchar(V.ch); /* get the rest of the name and show it: */ done = P_eoln(V.inst->f); while (!done) { done = P_eoln(V.inst->f); if (done) break; V.ch = getc(V.inst->f); if (V.ch == '\n') V.ch = ' '; if (V.ch == ' ' || V.ch == ';') done = true; if (!done) putchar(V.ch); } putchar('\n'); /* mark the first letter that does not match: */ for (p1 = 1; p1 < p; p1++) putchar(' '); printf("^\n"); halt(); /* we are not inside a comment */ } } } /*rd(inst,ch);*/ if (*alignedbase > -maximumrange && *alignedbase <= *length + maximumrange) return; printf(" In procedure align:\n"); printf(" read in base was %ld\n", thebase); printf(" in internal coordinates: %ld\n", *alignedbase); printf(" maximum range was %ld\n", (long)maximumrange); printf(" piece length was %ld\n", *length); WITH = &(*pie)->key.hea.keynam; /* p2c: bookshift.p, line 1969: Note: * Format for packed-array-of-char will work only if width < length [321] */ printf(" piece name: %.*s\n", WITH->length, WITH->letters); printf(" piece number: %ld\n", number); printf(" aligned base is too far away... see the code\n"); halt(); } #undef maximumrange #undef semicolon #define maximumrange 500 /* end module align.write */ /* begin module MODIFIEDalign.maxminalignment */ /* MODIFIED - delete later */ Static Void maxminalignment(inst, book, theline, fromparam, toparam, alignmenttype) _TEXT *inst, *book; long *theline, *fromparam, *toparam; Char alignmenttype; { /* prescan the book to find the range over which the pieces of the book are spread, relative to the aligned base. the procedure uses the same variables that align does (so it can call align itself), and it returns the range in fromparam and toparam. alignmenttype: 'f' means alignment by First internal coordinate base, 'b' means alignment by Book, 'i' means alignment by Instructions. */ /* the maximum size aligned piece; this will presumably catch the alignment bug */ long distance; /* a distance to the aligned base */ piece *pie; long length, alignedbase; pie = (piece *)Malloc(sizeof(piece)); /* set an initial range for the two bounds */ *fromparam = LONG_MAX; *toparam = -LONG_MAX; if (*book->name != '\0') { if (book->f != NULL) book->f = freopen(book->name, "r", book->f); else book->f = fopen(book->name, "r"); } else rewind(book->f); if (book->f == NULL) _EscIO2(FileNotFound, book->name); RESETBUF(book->f, Char); if (*inst->name != '\0') { if (inst->f != NULL) inst->f = freopen(inst->name, "r", inst->f); else inst->f = fopen(inst->name, "r"); } else rewind(inst->f); if (inst->f == NULL) _EscIO2(FileNotFound, inst->name); RESETBUF(inst->f, Char); while (!BUFEOF(book->f)) { switch (alignmenttype) { case 'i': /* blank case */ break; /* alignwrite(inst,book,theline,pie,length,alignedbase); */ case 'b': case 'f': getpiece(book, theline, &pie); /* read in the piece */ length = piecelength(pie); break; } if (BUFEOF(book->f)) break; switch (alignmenttype) { case 'f': /* force alignment on first base */ alignedbase = 0; *fromparam = 1; distance = length - alignedbase; if (*toparam < distance) *toparam = distance; break; case 'i': /* use the alignedbase from the book */ distance = 1 - alignedbase; if (*fromparam > distance) *fromparam = distance; distance = length - alignedbase; if (*toparam < distance) *toparam = distance; break; case 'b': /* use the internal book */ alignedbase = pietoint(0L, pie); distance = 1 - alignedbase; if (*fromparam > distance) *fromparam = distance; distance = length - alignedbase; if (*toparam < distance) *toparam = distance; break; } clearpiece(&pie); } if (*toparam - *fromparam > maximumrange) { printf(" in procedure maxminalignment:\n"); printf(" alignedbase = %ld\n", alignedbase); printf(" fromparameter = %ld\n", *fromparam); printf(" toparameter = %ld\n", *toparam); printf(" this exceeds the maximum range allowed (%ld)\n", (long)maximumrange); printf(" see notes in the procedure. \n"); /* notes: if you desired this range, increase 'maximumrange'. otherwise, this may indicate a bug - either: 1) locate the bug (and tell tom schneider, please...) 2) reduce the size of the fragments, from one or the other end until the bombing is stopped. */ halt(); } /* make the book readable again */ if (*book->name != '\0') { if (book->f != NULL) book->f = freopen(book->name, "r", book->f); else book->f = fopen(book->name, "r"); } else rewind(book->f); if (book->f == NULL) _EscIO2(FileNotFound, book->name); RESETBUF(book->f, Char); if (*inst->name != '\0') { if (inst->f != NULL) inst->f = freopen(inst->name, "r", inst->f); else inst->f = fopen(inst->name, "r"); } else rewind(inst->f); if (inst->f == NULL) _EscIO2(FileNotFound, inst->name); RESETBUF(inst->f, Char); Free(pie); } #undef maximumrange /* end module MODIFIEDalign.maxminalignment */ /* version = 7.60; {of delmod.p 2003 May 3} */ /* begin module copyaline */ Static Void copyaline(fin, fout) _TEXT *fin, *fout; { /* copy a line from file fin to file fout */ while (!P_eoln(fin->f)) { putc(P_peek(fin->f), fout->f); getc(fin->f); } fscanf(fin->f, "%*[^\n]"); getc(fin->f); putc('\n', fout->f); } /* copyaline */ #define maximumrange 500 /* end module copyaline version = 7.62; {of delmod.p 2003 Jan 13} */ /* uuu uuu */ /* begin module align.realignbook */ Static Void realignbook(inst, book, bookout, fromparam, toparam, alignmenttype) _TEXT *inst, *book, *bookout; long *fromparam, *toparam; Char alignmenttype; { /* realign the book according to the inst. alignmenttype: 'f' means alignment by First internal coordinate base, 'b' means alignment by Book, 'i' means alignment by Instructions. */ /* the maximum size aligned piece; this will presumably catch the alignment bug */ long distance; /* a distance to the aligned base */ /* pie: pieceptr; */ long length, alignedbase; long theline = 0; /* current line in the book */ orgkey org; boolean orgchange = false, orgopen = false; chrkey chr; boolean chrchange = false, chropen = false; piece *pie; boolean piechange = false, pieopen = false; _TEXT TEMP; pie = (piece *)Malloc(sizeof(piece)); /* set an initial range for the two bounds */ *fromparam = LONG_MAX; *toparam = -LONG_MAX; /* pie := nil; */ pie = (piece *)Malloc(sizeof(piece)); if (*book->name != '\0') { if (book->f != NULL) book->f = freopen(book->name, "r", book->f); else book->f = fopen(book->name, "r"); } else { rewind(book->f); } if (book->f == NULL) _EscIO2(FileNotFound, book->name); RESETBUF(book->f, Char); if (*inst->name != '\0') { if (inst->f != NULL) inst->f = freopen(inst->name, "r", inst->f); else inst->f = fopen(inst->name, "r"); } else rewind(inst->f); if (inst->f == NULL) _EscIO2(FileNotFound, inst->name); RESETBUF(inst->f, Char); if (*bookout->name != '\0') { if (bookout->f != NULL) bookout->f = freopen(bookout->name, "w", bookout->f); else bookout->f = fopen(bookout->name, "w"); } else { if (bookout->f != NULL) rewind(bookout->f); else bookout->f = tmpfile(); } if (bookout->f == NULL) _EscIO2(FileNotFound, bookout->name); SETUPBUF(bookout->f, Char); copyaline(book, bookout); /* copy the title over */ theline = 1; /* while not eof(book) do begin */ do { printf("HERE GOES!!!!!!!\n"); switch (alignmenttype) { case 'i': /*pie,*/ alignwrite(inst, book, &theline, &length, &alignedbase, &org, &orgchange, &orgopen, &chr, &chrchange, &chropen, &pie, &piechange, &pieopen); break; case 'b': case 'f': getpiece(book, &theline, &pie); /* read in the piece */ /*use getocp? */ length = piecelength(pie); break; } if (BUFEOF(book->f)) pieopen = false; printf("DONE ***************\n"); /* halt; if not eof(book) then begin */ if (pieopen) { switch (alignmenttype) { case 'f': /* force alignment on first base */ alignedbase = 1; *fromparam = 1; distance = length - alignedbase; if (*toparam < distance) *toparam = distance; break; case 'i': /* use the alignedbase from the book */ distance = 1 - alignedbase; if (*fromparam > distance) *fromparam = distance; distance = length - alignedbase; if (*toparam < distance) *toparam = distance; break; case 'b': /* use the internal book */ alignedbase = pietoint(0L, pie); distance = 1 - alignedbase; if (*fromparam > distance) *fromparam = distance; distance = length - alignedbase; if (*toparam < distance) *toparam = distance; break; } TEMP.f = stdout; *TEMP.name = '\0'; /*yyy*/ bwpie(&TEMP, pie); bwpie(bookout, pie); clearpiece(&pie); halt(); } } while (pieopen); /* getocp(book, theline, org, orgchange, orgopen, chr, chrchange, chropen, pie, piechange, pieopen); writeln(output,'pieopen: ',pieopen); if pieopen then begin writeln(output,'piece at line: ',theline:1); end; */ /* the problem is that the align routine is designed only to READ the book, not to copy the org chr and pie. So I really need to replace align ... and that requires reading through the inst file. */ /* end; */ if (*toparam - *fromparam > maximumrange) { printf(" in procedure realignbook:\n"); printf(" alignedbase = %ld\n", alignedbase); printf(" fromparameter = %ld\n", *fromparam); printf(" toparameter = %ld\n", *toparam); printf(" this exceeds the maximum range allowed (%ld)\n", (long)maximumrange); printf(" see notes in the procedure. \n"); /* notes: if you desired this range, increase 'maximumrange'. otherwise, this may indicate a bug - either: 1) locate the bug (and tell tom schneider, please...) 2) reduce the size of the fragments, from one or the other end until the bombing is stopped. */ halt(); } /* make the book readable again */ if (*book->name != '\0') { if (book->f != NULL) book->f = freopen(book->name, "r", book->f); else book->f = fopen(book->name, "r"); } else rewind(book->f); if (book->f == NULL) _EscIO2(FileNotFound, book->name); RESETBUF(book->f, Char); if (*inst->name != '\0') { if (inst->f != NULL) inst->f = freopen(inst->name, "r", inst->f); else inst->f = fopen(inst->name, "r"); } else rewind(inst->f); if (inst->f == NULL) _EscIO2(FileNotFound, inst->name); RESETBUF(inst->f, Char); Free(pie); } #undef maximumrange #define debug false /* give debug output */ /* Local variables for themain: */ struct LOC_themain { /* variables used by the align routines: */ piece *apiece; long zerobase; /* the zero base: 'get from [zerobase]' */ } ; Local Void notbetween(LINK) struct LOC_themain *LINK; { /* report a serious problem: the zero base is not where it should be, between the piece ends */ piekey *WITH; _TEXT TEMP; WITH = &LINK->apiece->key; printf(" zero base is not between piece ends!\n"); printf(" pieend: %ld\n", WITH->pieend); printf(" zerobase: %ld\n", LINK->zerobase); printf(" piebeg: %ld\n", WITH->piebeg); printf("piece: \n"); TEMP.f = stdout; *TEMP.name = '\0'; bwpie(&TEMP, LINK->apiece); halt(); } /* end module align.realignbook */ /* begin module bookshift.themain */ Static Void themain(book, inst, bookshiftp, bookout) _TEXT *book, *inst, *bookshiftp, *bookout; { /* the main procedure of the program */ struct LOC_themain V; double parameterversion; /* parameter version number */ /* length, alignedbase: integer; fromparam, toparam: integer; */ Char alignmenttype = 'i'; /* 'f' means alignment by First internal coordinate base, 'b' means alignment by Book, 'i' means alignment by Instructions */ trigger gettrigger; /* trigger to locate the word 'get' in a file */ Char ch; /* a character from the inst file */ long theline = 1; /* current line in the book */ boolean done; /* done looking for a 'get' in the inst file */ long ORIGINALpiebeg, ORIGINALpieend; /* original coordinates */ _TEXT TEMP; piekey *WITH; printf("bookshift %4.2f\n", version); if (*bookshiftp->name != '\0') { if (bookshiftp->f != NULL) bookshiftp->f = freopen(bookshiftp->name, "r", bookshiftp->f); else bookshiftp->f = fopen(bookshiftp->name, "r"); } else rewind(bookshiftp->f); if (bookshiftp->f == NULL) _EscIO2(FileNotFound, bookshiftp->name); RESETBUF(bookshiftp->f, Char); fscanf(bookshiftp->f, "%lg%*[^\n]", ¶meterversion); getc(bookshiftp->f); if ((long)floor(100 * parameterversion + 0.5) < (long)floor(100.0 + 0.5)) { printf("You have an old parameter file!\n"); halt(); } V.apiece = (piece *)Malloc(sizeof(piece)); if (!BUFEOF(bookshiftp->f)) { if (!BUFEOF(bookshiftp->f)) { fscanf(bookshiftp->f, "%c%*[^\n]", &alignmenttype); getc(bookshiftp->f); if (alignmenttype == '\n') alignmenttype = ' '; if (alignmenttype != 'b' && alignmenttype != 'i' && alignmenttype != 'f') { printf("alignment type must be f, b, or i\n"); printf("alignmenttype was \"%c\"\n", alignmenttype); halt(); } } } if (*inst->name != '\0') { if (inst->f != NULL) inst->f = freopen(inst->name, "r", inst->f); else inst->f = fopen(inst->name, "r"); } else rewind(inst->f); if (inst->f == NULL) _EscIO2(FileNotFound, inst->name); RESETBUF(inst->f, Char); if (BUFEOF(inst->f)) { if (alignmenttype == 'i') { printf("forcing alignment to be on book because there are no instructions\n"); alignmenttype = 'b'; } } /* original stuff from range.p maxminalignment(inst,book,fromparam,toparam,alignmenttype); writeln(output, 'alignmenttype = ',alignmenttype); writeln(output, fromparam:1, ' ',toparam:1); writeln(bookout, fromparam:1, ' ',toparam:1); writeln(bookout, fromparam:1); writeln(bookout, toparam:1); */ if (*bookout->name != '\0') { if (bookout->f != NULL) bookout->f = freopen(bookout->name, "w", bookout->f); else bookout->f = fopen(bookout->name, "w"); } else { if (bookout->f != NULL) rewind(bookout->f); else bookout->f = tmpfile(); } if (bookout->f == NULL) _EscIO2(FileNotFound, bookout->name); SETUPBUF(bookout->f, Char); /* this is based on alignbook, which is based on getocp. getocp is built to read, not to write. realignbook(inst,book,bookout,fromparam,toparam,alignmenttype); */ filltrigger(&gettrigger, "get from "); resettrigger(&gettrigger); if (*book->name != '\0') { if (book->f != NULL) book->f = freopen(book->name, "r", book->f); else book->f = fopen(book->name, "r"); } else { rewind(book->f); } if (book->f == NULL) _EscIO2(FileNotFound, book->name); RESETBUF(book->f, Char); if (*inst->name != '\0') { if (inst->f != NULL) inst->f = freopen(inst->name, "r", inst->f); else inst->f = fopen(inst->name, "r"); } else rewind(inst->f); if (inst->f == NULL) _EscIO2(FileNotFound, inst->name); RESETBUF(inst->f, Char); while (!BUFEOF(book->f)) { /* this write statement can be used to check the output: write(bookout, theline:3,' '); */ if (P_peek(book->f) != 'p') { copyaline(book, bookout); theline++; continue; } /* write(bookout, 'PIECE '); copyaline(book, bookout); */ if (debug) printf("Piece at line %ld\n", theline); brpiece(book, &theline, &V.apiece); /* Read through the inst file to locate the next get. The mechanism here is overly sinmple and should be replaced with the comment and quote skipping mechanism in the align routines. */ done = false; while (!done) { if (BUFEOF(inst->f)) { printf("ERROR: No get found for this piece "); printf(" at line %ld of the book:\n", theline); TEMP.f = stdout; *TEMP.name = '\0'; bwpie(&TEMP, V.apiece); halt(); } if (P_eoln(inst->f)) { fscanf(inst->f, "%*[^\n]"); getc(inst->f); /* writeln(output); */ continue; } ch = getc(inst->f); if (ch == '\n') ch = ' '; /* write(output, ch); */ testfortrigger(ch, &gettrigger); if (!gettrigger.found) continue; WITH = &V.apiece->key; fscanf(inst->f, "%ld", &V.zerobase); if (debug) { printf(" zero base: %ld\n", V.zerobase); printf(" from: %ld\n", WITH->piebeg); printf(" to: %ld\n", WITH->pieend); } ORIGINALpiebeg = WITH->piebeg; ORIGINALpieend = WITH->pieend; if (V.zerobase >= WITH->piebeg) { if (V.zerobase > WITH->pieend) notbetween(&V); WITH->piebeg = ORIGINALpiebeg - V.zerobase; WITH->pieend = ORIGINALpieend - V.zerobase; } else { if (V.zerobase < WITH->pieend) notbetween(&V); WITH->piebeg = ORIGINALpieend - V.zerobase; WITH->pieend = ORIGINALpiebeg - V.zerobase; } /*zerobase < piebeg*/ /* force a nice coordinate system: */ WITH->piedir = plus; WITH->coodir = plus; WITH->coobeg = WITH->piebeg; WITH->cooend = WITH->pieend; fscanf(inst->f, "%*[^\n]"); getc(inst->f); resettrigger(&gettrigger); done = true; } bwpie(bookout, V.apiece); } } #undef debug /* end module bookshift.themain */ main(argc, argv) int argc; Char *argv[]; { PASCAL_MAIN(argc, argv); if (setjmp(_JL1)) goto _L1; bookout.f = NULL; strcpy(bookout.name, "bookout"); bookshiftp.f = NULL; strcpy(bookshiftp.name, "bookshiftp"); inst.f = NULL; strcpy(inst.name, "inst"); book.f = NULL; strcpy(book.name, "book"); themain(&book, &inst, &bookshiftp, &bookout); _L1: if (book.f != NULL) fclose(book.f); if (inst.f != NULL) fclose(inst.f); if (bookshiftp.f != NULL) fclose(bookshiftp.f); if (bookout.f != NULL) fclose(bookout.f); exit(EXIT_SUCCESS); } /* End. */