summaryrefslogtreecommitdiff
path: root/support/relabel/relabelmac.pas
blob: f5b671181e8851db39a44dfdfe8bc970a91cc49d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
PROGRAM  relabelmac; {For Turbo Pascal for Macintosh.}
{Peter Ungar, 914 723 7187,  June 7, 1994; Mar. 5th, Mar. 31th 1995}
{Change of Mar. 5, 1995: In case of a reference to a nonexistent label,
RELABEL is supposed to print out the nonexistent label. Before this
correction this failed to work in most cases.
Change of Mar. 31: The messages to input the numbers of the first
chapter and the first section were changed. The old messages said -1 was
allowed, but RELABEL is programmed to regard the symbol - as
not part of a label.
 Also, the error message for nonexistent labels was made clearer.}

LABEL 1,3,8,9;

TYPE stringarray=array[1..6] of string[12];

       (* LaTeX calls the identifier "label" when it occurs next to
       the item, and "reference" elsewhere. I apologize for not having
       observed this distinction. I should have used "identifier" for
       an occurrence of a string which could be a label or a reference,
       but for the most part I called it a label. In text written
       for RELABEL, as in typeset books, labels and references
       are not marked as such by the author. RELABEL regards the first
       occurrence of an identifier as the label, unless it is marked as a
       forward reference.
         The program makes two passes over the text. The first
       involves reading only. The program takes down each label at its
       first nonforward occurrence and assigns to it the next
       available serial number. These pairs of old and new labels are
       stored in the labelentry file. Next, the text is read again and
       written out to a new file, with each label changed to its new
       value.
   
       Stringarrays will hold labels, including those parts of the label
       which are implicit, i.e. if we omit the chapter label or the
       chapter and section label or the chapter, section and subsection
       label when those are the current ones. 
          The entries of the stringarray are:
          a) If SectionReset=TRUE: chapterlabel, sectionlabel,
       subsection label and the identifier of the object of the label.
       If the item does not apply, e.g. if we are not in a subsection,
       the corresponding entry is the empty string '';
          b) If SectionReset=FALSE, i.e. sections are numbered
          consecutively, then chapter numbers are not needed in labels and
          the first entry of the string array is empty except in the
          label of a chapter. *)
     
       (* We use the following pointer construction to get around the fact
          that Turbo Pascal allots a space of only 32K to
          all regularly declared variables, but can utilize memory outside
          that limited space for  variables created by  NEW statements. *) 
     
     labelentry=RECORD oldlabel:stringarray;
                       newlabel:array[1..4] of integer;
                       secondpassoccurred:boolean;
                END;
     labelentryp=^labelentry;
     sublistp=array[-1..2000] of labelentryp;
     mainlistp=^sublistp;
        
        (* Oldlabel is a stringarray. The labels in the old text may
        contain lowercase letters as well as digits. 
           Newlabel is represented by an array of integers, the
        chapter number etc. This will be made into a string when there is
        a reference to the label.*)

 VAR  i,j,k,n,implicit,ImplAdj,SerialNo,
      FirstChapter,FirstSection,LabelKind:integer;
         (* ImplAdj (ImplicitAdjustment) is 0 if section numbers are reset 
        at the beginning of each chapter and 1 if they are not, and
        hence chapter numbers are not needed in labels other than chapter
        labels.
          SerialNo will hold the serial number of the first occurrence
        of a label in the array holding all labels of its kind.
          FirstChapter, FirstSection are the numbers to be assigned to the
        first chapter and the first section of the file. RELABEL asks an 
        input of this when the program starts, in case you want 0, 1 or
        larger numbers if the file is from the middle of a manuscript. *)
      totalcount, currentcount:array[0..9] of integer;
      (* countstarts gives where the numbering of chapters, sections
         subsections and other labeled items begins; the program sets
         the last two equal to 1. *)
      s,filename,outputfilename, filenameend:string;
      labelstring:string[51];
      sta,empty,current:stringarray;
      
        (* totalcount will say how many labels of the 10 kinds we have
        so far. currentcount gives the counts of the 10 kinds since they
        were last reset.
          current contains the current chapterlabel, section
        label and subsection label. *)
        
      mainlist:array[0..9] of mainlistp;
      SectionReset,ForwardRef, LabeltagsInOutput, omit,
      PeriodFollows, FirstChapterLabel, FirstSectionLabel: boolean;
(* Sectionreset: Each chapter starts with section 1.*)      
      
      incoming, outgoing:text;
      c,ans:char; 
      
FUNCTION min(i,j:integer):integer;
BEGIN
  IF i<j THEN min:=i ELSE min:=j
END;

FUNCTION max(i,j:integer):integer;
BEGIN
  IF i<j THEN max:=j ELSE max:=i
END;

PROCEDURE IntToStr(a:integer; VAR s:string);
     (*Writes  a  as a string s*)
  LABEL 9;
  VAR d:integer;
  BEGIN
    s:='';
    IF a<0 THEN BEGIN s:='-'; a:=-a END;
    IF a=0 THEN BEGIN s:='0'; GOTO 9 END;
    d:=10000;
    WHILE (a DIV d)=0 DO d:=d DIV 10;
    WHILE d>0 DO BEGIN s:=s+chr(48+(a DIV d)); a:= a MOD d; d:=d DIV 10 END;
  9:END;
  
  FUNCTION labelsymbol(c:char):boolean;
(* TRUE if  c  is a symbol allowed in a label, i.e. a digit or
   a lowercase letter. *)
  VAR x:integer;
  BEGIN x:=ord(c);
    labelsymbol:=(((48<=x) AND (x<=57)) OR ((97<=x) AND (x<=122))
                  OR ((65<=x) AND (x<=90)))
  END;

  PROCEDURE ReadLabel(VAR star:stringarray; VAR c:char);
     (* Reads the components of a label from the incoming stream and
     puts its components into the stringarray star, including
     the implicit items. If section numbers are not reset in each
     chapter (2 levels of test units) then the empty string is put in
     the chapter designator location star[1] except in the case of
     chapter labels. *)
  LABEL 2,5,9;
  VAR i,implicit:integer; str:string[12];
  BEGIN    
    k:=0; star:=empty; PeriodFollows:=FALSE;
      (* k will count the number of parts separated by .'s in the label. *)
 2: str:='';
    WHILE labelsymbol(c)  DO BEGIN
      str:=str+c;
      read(incoming,c);
    END;
    k:=k+1; star[k+ImplAdj]:=str;
    IF c='.' THEN BEGIN
        (* Another part of the label is coming, or there is a . after
        the label. *)
      read(incoming,c);
      IF labelsymbol(c) THEN GOTO 2
      ELSE PeriodFollows:=TRUE;
    END;
      (* Now we have all  k  items of the label in the stringarray star.
       We want the program to work so that, if desired, the chapter, section
       and subsection labels may be omitted and then they are understood to 
       refer to the current chapter, section or subsection. 
       We reconstruct the omitted parts of the label. We assemble it
       in  star  and then if it is a new label we put it into the mainlist.
         If the number of levels is 3, then the
       components of  star  are: Chapter label, Section label, Subsection
       label and item label. If any of these are missing or not applicable,
       the corresponding label is ''. A subsection label is missing
       if the section is not divided into subsections. A subsection
       label is inapplicable if the label is a chapter or section label.
         If the number of levels is 2, (ImplAdj=1) then a label of
       anything except a chapter is complete without the chapter label,
       and star[1]:='' for all such items. *)
    IF (LabelKind > 1) AND ((k+ImplAdj) > min(LabelKind, 4)) THEN BEGIN
      writeln('Found a label with too many parts. If you have 2 levels,');
      writeln('only a chapter label should contain a chapter identifier.');
      GOTO 5;
    END;
    IF ((LabelKind=0) AND (k>1)) THEN BEGIN
      writeln(' An at-large item label with more than one part: ');
5:    write('LabelKind: ',Labelkind,'  Label: ');
      FOR i:=1+ImplAdj TO k+ImplAdj-1 DO write(sta[i],'.');
      writeln(sta[k+ImplAdj]);
      writeln('Continue? y or n '); readln(ans);
      IF ans='n' THEN BEGIN close(incoming); halt END;
    END; (* Of error handling. *)
    IF LabelKind=0 THEN BEGIN
      star[4]:=star[1+ImplAdj]; star[1+ImplAdj]:='';
    END;
    IF LabelKind=1 THEN BEGIN
      star[1]:=star[1+ImplAdj]; star[2]:='';GOTO 9 END;
    IF (2<=LabelKind) AND (LabelKind<=3) THEN BEGIN
      implicit:=LabelKind-k-ImplAdj;
      IF implicit>0 THEN BEGIN
        FOR i:=LabelKind DOWNTO implicit+1 DO star[i]:=star[i-implicit];
        FOR i:=1+ImplAdj TO implicit+ImplAdj DO star[i]:=current[i];
      END;
    END;
    IF (labelkind >= 4) THEN BEGIN
      IF k+ImplAdj<4 THEN BEGIN
        star[4]:=star[k+ImplAdj]; star[k+ImplAdj]:='' END;
      IF k=1 THEN FOR i:=1+ImplAdj to 3 DO star[i]:=current[i];
        (*This must be a label of an item in the current text unit.*)
    END;  
9:END;  (* of procedure readlabel. Note that  c  is the first symbol after
           the label at this stage, or the first symbol after the period 
           if there was a period immediately after the label. *) 
 
  FUNCTION InList(st:StringArray;VAR SerialNo:integer):boolean;
  (* TRUE if the label st is already in the mainlist.
     This function is also used to compute the index SerialNo of
     the label in the array of that LabelKind*)
  LABEL 9;
  VAR i:integer;  bool:boolean; 
  BEGIN 
    IF totalcount[LabelKind]=0 THEN InList:=FALSE
    ELSE FOR i:=totalcount[LabelKind] DOWNTO 1 DO
    BEGIN
      bool:=TRUE;
      WITH  mainlist[LabelKind]^[i]^ DO
        FOR j:=1 TO 4 DO bool:=bool AND (oldlabel[j]=st[j]);
      IF bool THEN BEGIN
        InList:=TRUE;
        SerialNo:=i;
           (*  mainlist[LabelKind]^[SerialNo] is the record where this
          label and the new label which is to replace it can be found.*)
      GOTO 9 END;
    END;
    InList:=FALSE; (* The label is not in mainlist. *)
9:END;


  PROCEDURE AddToList(sta:stringarray);
(* We have a new label which is not a forward reference. Add it to mainlist*)
  VAR i:integer;
  BEGIN 
    totalcount[LabelKind]:=totalcount[LabelKind]+1;
    currentcount[LabelKind]:=currentcount[LabelKind]+1;
      (* If the new label is a chapter, section or subsection label then
         the counts of subordinate items have to be reset.*)

    IF (0<LabelKind) AND (LabelKind<=3) THEN BEGIN
      current[labelkind]:=sta[labelkind];
      FOR i:=max(labelkind+1,ImplAdj+2) TO 9 DO BEGIN
        currentcount[i]:=0; current[i]:='';
      END;
      IF (FirstChapterLabel AND (labelkind=1)) THEN BEGIN
        CurrentCount[1]:=FirstChapter; FirstChapterLabel:=False
      END;
      IF (FirstSectionLabel AND (labelkind=2)) THEN BEGIN
        CurrentCount[2]:=FirstSection; FirstSectionLabel:=False
      END;
    END; (* of adjusting the label counts and the array of current chapter,
    section and subsection to account for the new label.
    Next add a new blank record where we will put the label we just found,
    and the label which will replace it. *)
  
    new(mainlist[LabelKind]^[totalcount[LabelKind]]);
    WITH mainlist[LabelKind]^[totalcount[LabelKind]]^ DO BEGIN
      oldlabel:=sta;
      FOR i:=1 to 4 DO newlabel[i]:=0;
      IF LabelKind=0 THEN  newlabel[4]:= currentcount[0];
      IF LabelKind=1 THEN newlabel[1]:=currentcount[1];
      IF LabelKind>=2 THEN
        FOR i:=1+ImplAdj TO min(3,LabelKind) DO newlabel[i]:=currentcount[i];
      IF LabelKind>=4 THEN newlabel[4]:=currentcount[labelkind];
        (* Newlabel[1] is 0 if sections are numbered
           consecutively and chapter numbers occur only in chapter labels.*)
      SecondPassOccurred:=FALSE;
    END; (* of preparing new mainlist entry *) 
  END; (* of processing the new label *)

  PROCEDURE MakeNewLabelstring(VAR newlabelstring:string;
                               labelkind,SerialNo:integer);
  LABEL 9;
  VAR j:integer;s:string;
      InUnitRef:boolean;
  BEGIN
    WITH mainlist[LabelKind]^[SerialNo]^ DO
    BEGIN
      newlabelstring:='';
      IF LabelKind=0 THEN
        BEGIN IntToStr(newlabel[4],newlabelstring);
        GOTO 9 END; (* Of LabelKind=0 (at large label) case *)
      IF LabelKind=1 THEN
        BEGIN IntToStr(newlabel[1],newlabelstring);
        GOTO 9 END; (* Of LabelKind=1 (i.e. chapterlabel) case *)
      
      IF omit AND (LabelKind>3) THEN BEGIN
        (* Find whether the reference is to the current unit of the text.*)
        InUnitRef:=TRUE;
        FOR j:=1+ImplAdj TO 3 DO
          InUnitRef:=InUnitRef AND (newlabel[j]=currentcount[j]);
        IF InUnitRef THEN BEGIN
          IntToStr(newlabel[4],newlabelstring); GOTO 9 END;
      END; (* Of making label without chapter,section and subsection
        number. Note we exit to 9 only if such a label has been made. *)
      FOR j:=1+ImplAdj TO min(LabelKind,4) DO
        IF OldLabel[j] <> '' THEN BEGIN
          IntToStr(newlabel[j],s);  
          IF newlabelstring='' THEN newlabelstring:=s
          ELSE newlabelstring:=newlabelstring+'.'+s;
        END;
    END; (* of WITH statement *)
9:END;   

  FUNCTION LabelTag(LabelKind:integer):char; (* For error message.*)
  BEGIN
    CASE LabelKind OF
       0: LabelTag:= ''; {Option a,  At large item  ASCII 140}
       1: LabelTag:= ''; {Option c,  Chapter        ASCII 141}
       2: LabelTag:= ''; {Option s,  Section        ASCII 167}
       3: LabelTag:= ''; {Option b,   suBsection    ASCII 186}
       4: LabelTag:= ''; {Option g,  fiGure        ASCII 169}
       5: LabelTag:= ''; {Option f,  Formula       ASCII 196}
       6: LabelTag:= ''; {Option p,  Problem       ASCII 185}
       7: LabelTag:= ''; {Option d,  Definition    ASCII 182} 
       8: LabelTag:= ''; {Option t,  Theorem       ASCII 160}
       9: LabelTag:= ''; {Option l,  Lemma         ASCII 194}
 (* In the IBM-compatible version of RELABEL different label tags are used.
    Their ASCII numbers are 227, 228, 229, 221, 222,..., 226 *)
    END;
  END; (* Main program begins here.*)
BEGIN 
1:  FOR i:=1 TO 4 DO empty[i]:=''; current:=empty;
  writeln('File to be renumbered. If it is not in the same folder as RENUMBER');
  writeln('then give path name, e.g.  HardDisk:Calculus Book Folder:Ch3 ');
  readln(filename);
  writeln('Do you have a 2 level (Section, possibly subsection) or');
  writeln('3 level (Chapter, section, subsection) hierarchy of text units?');
  write('Input  2  or  3  '); 
  readln(i); SectionReset:= i=3; ImplAdj:=3-i;
    (*ImplAdj (Implicit Adjustment) = 1 if chapter numbers are superfluous
      in labels, 0 otherwise.*)
  writeln('Do you want the chapter, section and subsection numbers');
  writeln('in the new file if they are all the current ones (y or n) ');
  writeln('(Chapter numbers are included only if you have 3 levels)');
  readln(ans); omit:=ans='n';
  writeln('Do you want the label tags to remain in the output? y or n: ');
  readln(ans); LabeltagsInOutput:=ans='y';
  IF labeltagsinoutput THEN filenameend:='R' ELSE filenameend:='T'; 
  FOR i:=0 TO 9 DO currentcount[i]:=0;
  TotalCount:=CurrentCount;
  writeln('Input the number  >= 0 you want for the first chapter');
  readln(FirstChapter);
  currentcount[1]:=FirstChapter-1; FirstChapterLabel:=TRUE;
  writeln('Input the number  >= 0 you want for the first section');
  readln(FirstSection);
  currentcount[2]:=FirstSection-1; FirstSectionLabel:=TRUE;
  writeln('I will beep when ready');
  (* Next create the arrays for storing the various types of labels. *)
  
  FOR i:=0 TO 9 DO new(mainlist[i]);

  Reset(incoming,filename{,50000}); (* Use large buffer to spare disk drive *)
  read(incoming, c);
  WHILE eof(incoming)=FALSE DO
  BEGIN
    IF ord(c) > 128 THEN BEGIN
      CASE c OF
        '': LabelKind:=0;
        '': LabelKind:=1;
        '': LabelKind:=2;
        '': LabelKind:=3;
        '': LabelKind:=4;
        '': LabelKind:=5;
        '': LabelKind:=6;
        '': LabelKind:=7;
        '': LabelKind:=8;
        '': LabelKind:=9;
        OTHERWISE (* In case the file comes from MS-DOS user of RELABEL *)
          IF ((227 <= ord(c)) AND (ord(c)<= 229))
            THEN LabelKind:= ord(c)-226
          ELSE IF ((221 <= ord(c)) AND (ord(c)<= 226))
                 THEN LabelKind:= ord(c)-217
                 ELSE IF ord(c)=220 THEN LabelKind:=0
                      ELSE GOTO 8;
      END;
      read(incoming, c);
      IF (c<>'') THEN readlabel(sta,c) ELSE GOTO 8;

       (* Do readlabel and the work below only if this is not
          labeled to be a reference.
            Next, we check if this is a repeat occurrence of a label.
          If not, enter in the list of labels and increase the count
          of labels of the kind we found.*)  
         
      IF NOT InList(sta,SerialNo) THEN AddToList(sta);
    END; (* of processing a label *)  
  8:read(incoming,c)
  END;  (* of loop which reads characters of the file *)

  writeln('First pass completed. I am starting to write the new file.');
    
  Reset(incoming);
  
 outputfilename:=filename+filenameend;
         (*If we choose to retain the tags of the labels in the renumbered
           file then its name is original file name with R appended,
           if the tags are stripped from the labels, S is appended.*)
  TextCreator:='*TEX';
  Rewrite(outgoing,outputfilename{,50000});
     (* Use large buffers to avoid frequent disk operation *)
    
  current:=empty;
  FOR i:=0 TO 9 DO currentcount[i]:=0;
  currentcount[1]:=FirstChapter-1;
  currentcount[2]:=FirstSection-1;
   
    (* We need to redo  current  to be able to restore the implicit
       parts of the labels as we encounter them on the second pass. *)
 
3:read(incoming,c);
  WHILE eof(incoming)=FALSE DO
  BEGIN 
    IF ord(c) >=128 THEN BEGIN (* A label may begin here. *)
            (* Check for and convert MS-DOS label tags *)
      IF ord(c)=220 THEN BEGIN LabelKind:=0; c:=labeltag(0) END;
      IF ((227 <= ord(c)) AND (ord(c)<= 229)) THEN BEGIN
        LabelKind:= ord(c)-226; c:=labeltag(labelkind) END;
      IF ((221 <= ord(c)) AND (ord(c)<= 226)) THEN BEGIN
        LabelKind:= ord(c)-217; c:=labeltag(labelkind) END; {Of DOS conv.}
      ForwardRef:=FALSE;
      CASE c OF
        '': LabelKind:=0;
        '': LabelKind:=1; 
        '': LabelKind:=2;
        '': LabelKind:=3;
        '': LabelKind:=4;
        '': LabelKind:=5;
        '': LabelKind:=6;
        '': LabelKind:=7;
        '': LabelKind:=8;
        '': LabelKind:=9
        OTHERWISE BEGIN (*The symbol is not a labelkind indicator*)
          write(outgoing,c); GOTO 3;
        END;
      END; (* of CASEs. We did not GOTO 3,  c  is a labeltag. *)
      IF LabeltagsInOutput THEN write(outgoing,c);
      read(incoming,c);
      IF c=chr(222) THEN c:='';
      IF c='' THEN BEGIN
        ForwardRef:=TRUE;
        IF LabeltagsInOutput THEN write(outgoing,c);
        read(incoming,c) 
      END;
      readlabel(sta,c);
      IF NOT(InList(sta,SerialNo)) THEN BEGIN
        writeln('LABEL NOT FOUND IN LIST ON SECOND PASS. ERROR');
        writeln('YOU MAY HAVE  REFERRED TO A NONEXISTENT LABEL');
        writeln('OR YOU MAY HAVE ENTERED THE WRONG LEVEL NUMBER.');
        write('LabelKind: ',Labelkind,'  Label in full form: ');
        FOR i:=1+ImplAdj TO min(LabelKind-1, 3) DO
         IF sta[i] <> '' THEN write(sta[i],'.');
        IF ((LabelKind = 0) OR (LabelKind > 3)) THEN writeln(sta[4])
          ELSE writeln(sta[LabelKind]);
        writeln('Continue (with ??? in this reference)?  y or n ');
        readln(ans);
        IF ans='n' THEN BEGIN close(incoming); close(outgoing); halt END;
        write(outgoing,'???'); GOTO 9;
      END; (* Of message and output, we had a reference to unknown label.*)
      IF NOT ForwardRef THEN BEGIN
        WITH mainlist[labelkind]^[SerialNo]^ DO BEGIN
          IF (NOT secondpassoccurred)THEN BEGIN
           IF (0<LabelKind) AND (labelkind<4) THEN BEGIN
              currentcount[labelkind]:=currentcount[labelkind]+1;
               (* This is not a reference but the label of a new *)
                     (* subdivision. Adjust current subdiv.*)
              current[labelkind]:=oldlabel[labelkind];
              IF (currentcount[1]>FirstChapter)
                       OR (currentcount[2]>FirstSection) THEN BEGIN
                FOR i:=max(labelkind+1,ImplAdj+2) TO 3 DO BEGIN
                  current[i]:=''; currentcount[i]:=0;
                END;
              END;   
            END; (* Of dealing with the label of a new heading. *)
            secondpassoccurred:=TRUE; 
          END
          ELSE IF LabeltagsInOutput THEN write(outgoing,'');
               (* We have a reference.*)
        END; (* Of WITH mainlist...*) 
      END; (* Of NOT ForwardRef *)
       (* Now we are ready to get the new label and convert it to a
          string. This can not be done once for all since the string
          may be shorter in a reference to the item from within
          the same subunit. Doing the job from scratch each time just
          because we may need one or the other of two expressions
          is admittedly inelegant but seldom are there many references
          to one item. *)
      MakeNewLabelstring(s,LabelKind, SerialNo);
      write(outgoing,s);
9:    IF PeriodFollows THEN write(outgoing,'.');
    END (* of assembling and writing the new label. *)
    ELSE BEGIN (* ord(c)<128, certainly not a labelkind symbol*)
      write(outgoing,c);
      read(incoming,c);
    END;  (* of IF ord(c)>=128..ELSE statement. *)
  END; (* Return to the beginning of the WHILE eof(incoming)=FALSE cycle *)
  write(outgoing,c); (* write the last symbol of the file *)
  close(outgoing);close(incoming);
  writeln(chr(7),'"',outputfilename,'"', 'written on disk.');
  FOR i:=0 TO 9 DO dispose(mainlist[i]);
  write('Relabel another file? (y or n)');
  readln(c); IF c='y' THEN GOTO 1;
  END.