1 /*  START OF:       mbuild_Tlist_.incl.pl1                    *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  * */
  2 
  3 
  4 /****^  HISTORY COMMENTS:
  5   1) change(2019-08-17,GDixon), approve(2019-10-23,MCR10069),
  6      audit(2020-01-20,Swenson), install(2020-01-20,MR12.6g-0035):
  7      mbuild subsystem threaded-list software and declarations.  See: MTB-1003
  8   2) change(2020-11-10,GDixon), approve(2021-02-22,MCR10086),
  9      audit(2021-03-17,Swenson), install(2021-03-17,MR12.6g-0051):
 10       A) Fix Syntax comment for Tlist_insert_before and Tlist_insert_after
 11          subroutines.
 12                                                    END HISTORY COMMENTS */
 13 
 14 /* ==========================================================================================
 15  * SUBROUTINE:  Tlist_
 16  *
 17  * Quick internal procedures that implement the mbuild threaded-list software.
 18  * For a description of these threaded lists, see:  MTB-1003  mbuild Subsystem.
 19  *
 20  * For continued efficiency of mbuild code, these entrypoints must adhere to the rules for
 21  * PL/I quick procedures, as described in AN82-00: Standards System Designer's Notebook,
 22  * page 8-9 and following.
 23  *
 24  *   Subroutine                                   Function Performed
 25  * ------------------------------------------   ------------------------------------------------------------
 26  * Tlist_initialize (list_baseP, holderP);      Initialize Tlist_base element of holderP structure.
 27 
 28  * Tlist_holder (list_dataP);                   Return pointer to structure holding threaded list anchor.
 29 
 30  * Tlist_member (list_dataP);                   Returns True if list_data is an active member of a threaded list.
 31 
 32  * Tlist_is_empty (list_baseP);                 Returns True if there are no members on list_baseP anchor.
 33 
 34  * Tlist_add_to_head (list_baseP, itemP, item_list_dataP);
 35  *                                              Adds itemP to head of list anchored by list_baseP.
 36 
 37  * Tlist_add_to_tail (list_baseP, itemP, item_list_dataP);
 38  *                                              Adds itemP to tail of list anchored by list_baseP.
 39 
 40  * Tlist_insert_before (list_baseP, new_itemP, new_item_list_dataP, cur_item_list_dataP );
 41  *                                              Adds new_itemP before cur_item_list_dataP.itemP in the threaded list.
 42 
 43  * Tlist_insert_after (list_baseP, new_itemP, new_item_list_dataP, cur_item_list_dataP );
 44  *                                              Adds new_itemP after cur_item_list_dataP.itemP in the threaded list.
 45 
 46  * Tlist_first_item (list_baseP);               Returns pointer to first item in list.
 47 
 48  * Tlist_last_item (list_baseP);                Returns pointer to last item in list.
 49 
 50  * Tlist_prev_item (item_list_dataP);           Returns pointer to previous item in list.
 51 
 52  * Tlist_next_item (item_list_dataP);           Returns pointer to next item in list.
 53 
 54  * Tlist_remove (item_list_dataP);              Removes item from list.
 55 
 56  * Tlist_count (list_baseP);                    Returns count of items in the list.
 57 
 58  *
 59  * ========================================================================================== */
 60 
 61 %include mbuild_Tlist_dcls_;
 62 %page;
 63 Tlist_:
 64      proc();
 65      return;
 66 
 67   dcl 1 b like Tlist_base aligned based(bP),
 68       bP ptr;
 69 
 70   dcl 1 a like Tlist_data aligned based(aP),
 71       aP ptr;
 72   dcl 1 n like Tlist_data aligned based(nP),
 73       nP ptr;
 74   dcl 1 p like Tlist_data aligned based(pP),
 75       pP ptr;
 76   dcl 1 r like Tlist_data aligned based(rP),
 77       rP ptr;
 78   dcl 1 t like Tlist_data aligned based(tP),
 79       tP ptr;
 80 
 81   dcl (null) builtin;
 82 
 83 
 84 Tlist_initialize:                                           /* Initialize a Tlist_base sub-structure contained in a   */
 85      entry (AbaseP, AholderP);                              /*  holder structure.                                     */
 86 
 87   dcl  AholderP ptr;
 88 
 89      bP = AbaseP;
 90      if bP = null() then return;
 91      b = Tlist_initial_base;
 92      b.holderP = AholderP;
 93      return;
 94 
 95 
 96 Tlist_holder:                                               /* Given pointer to an item's Tlist_data sub-structure,   */
 97      entry (Athis_item_thread_dataP) returns (ptr);         /*  return a pointer to structure holding Tlist_base of   */
 98                                                             /*  this threaded list.                                   */
 99 
100      tP = Athis_item_thread_dataP;
101      if tP = null() then return ( null() );
102      if t.baseP = null then
103           return ( null() );
104      bP = t.baseP;
105      return (b.holderP);
106 
107 
108 Tlist_member:                                               /* Return T ("1"b) if item's Tlist_data shows the item    */
109      entry (Athis_item_thread_dataP)                        /*  is actually threaded onto a list.                     */
110      returns (bit(1) aligned);
111 
112   dcl  Athis_item_thread_dataP ptr;
113 
114      tP = Athis_item_thread_dataP;
115      if tP = null() then return ( "0"b );
116      return ( t.prevP ^= null() | t.nextP ^= null() | t.baseP ^= null() );
117 
118 
119 Tlist_is_empty:                                             /* Return T ("1"b) if Tlist_base of threaded list shows   */
120      entry (AbaseP) returns (bit(1) aligned);               /*  the list contains no members.                         */
121 
122      bP = AbaseP;
123      if bP = null() then return ("1"b);
124      return ( b.headP = null() );
125 
126 
127 Tlist_add_to_head:                                          /* Add an item containing a Tlist_data sub-structure      */
128      entry (AbaseP, Aadd_itemP, Aadd_item_thread_dataP);    /*  to beginning of a threaded list identified by         */
129                                                             /*  a Tlist_base structure.                               */
130   dcl (AbaseP, Aadd_itemP, Aadd_item_thread_dataP) ptr;
131 
132      bP = AbaseP;                                           /* Address parameters.                                    */
133      aP = Aadd_item_thread_dataP;
134 
135      a.itemP = Aadd_itemP;                                  /* Initialize thread data within item being added.        */
136      a.baseP = bP;
137 
138      if b.headP = null() then do;                           /* List is empty?                                         */
139           b.headP = aP;                                     /*   <head>             <tail>                            */
140                                                             /* BECOMES:                                               */
141           a.nextP = null();                                 /*   <head> ---> a <--- <tail>                            */
142           a.prevP = null();
143 
144           b.tailP = aP;
145           end;
146      else do;                                               /* One or more items already in list?                     */
147           nP = b.headP;                                     /*   <head> ---> n                                        */
148                                                             /* BECOMES:                                               */
149           b.headP = aP;                                     /*   <head> ---> a <---> n                                */
150 
151           a.prevP = null();
152           a.nextP = nP;
153 
154           n.prevP = aP;
155           end;
156      return;
157 
158 
159 Tlist_add_to_tail:                                          /* Add an item containing a Tlist_data sub-structure      */
160      entry (AbaseP, Aadd_itemP, Aadd_item_thread_dataP);    /*  to end of a threaded list identified by               */
161                                                             /*  a Tlist_base structure.                               */
162 
163      bP = AbaseP;                                           /* Address parameters.                                    */
164      aP = Aadd_item_thread_dataP;
165 
166      a.itemP = Aadd_itemP;                                  /* Initialize thread data within item being added.        */
167      a.baseP = bP;
168 
169      if b.tailP = null() then do;                           /* List is empty?                                         */
170           b.headP = aP;                                     /*   <head>             <tail>                            */
171                                                             /* BECOMES:                                               */
172           a.nextP = null();                                 /*   <head> ---> a <--- <tail>                            */
173           a.prevP = null();
174 
175           b.tailP = aP;
176           end;
177      else do;                                               /* One or more items already in list?                     */
178           pP = b.tailP;                                     /*           p <--- <tail>                                */
179                                                             /* BECOMES:                                               */
180           p.nextP = aP;                                     /*   p <---> a <--- <tail>                                */
181 
182           a.prevP = pP;
183           a.nextP = null();
184 
185           b.tailP = aP;
186           end;
187      return;
188 
189 
190 Tlist_insert_before:                                        /* Add an item containing a Tlist_data sub-structure      */
191      entry (AbaseP, Aadd_itemP, Aadd_item_thread_dataP, Athis_item_thread_dataP);
192                                                             /*  before an item already on the threaded list defined   */
193                                                             /*  by a given Tlist_base sub-structure.                  */
194 
195      bP = AbaseP;                                           /* Address parameters.                                    */
196      aP = Aadd_item_thread_dataP;
197      tP = Athis_item_thread_dataP;
198 
199      a.itemP = Aadd_itemP;                                  /* Initialize thread data within item being added.        */
200      a.baseP = bP;
201 
202      if b.headP = tP then do;                               /* This item currently begins the list?                   */
203           b.headP = aP;                                     /*   <head> ---> t                                        */
204                                                             /* BECOMES:                                               */
205           a.prevP = null();                                 /*   <head> ---> a <---> t                                */
206           a.nextP = tP;
207 
208           t.prevP = aP;
209           end;
210      else do;                                               /* One or more items already in list?                     */
211           pP = t.prevP;                                     /*   p <---> t                                            */
212                                                             /* BECOMES:                                               */
213           p.nextP = aP;                                     /*   p <---> a <---> t                                    */
214 
215           a.prevP = pP;
216           a.nextP = tP;
217 
218           t.prevP = aP;
219           end;
220      return;
221 
222 
223 Tlist_insert_after:                                         /* Add an item containing a Tlist_data sub-structure      */
224      entry (AbaseP, Aadd_itemP, Aadd_item_thread_dataP, Athis_item_thread_dataP);
225                                                             /*  after an item already on the threaded list defined    */
226                                                             /*  by a given Tlist_base sub-structure.                  */
227 
228      bP = AbaseP;                                           /* Address parameters.                                    */
229      aP = Aadd_item_thread_dataP;
230      tP = Athis_item_thread_dataP;
231 
232      a.itemP = Aadd_itemP;                                  /* Initialize data within thread being added.             */
233      a.baseP = bP;
234 
235      if b.tailP = tP then do;                               /* This item currently ends the list?                     */
236           t.nextP = aP;                                     /*           t <--- <tail>                                */
237                                                             /* BECOMES:                                               */
238           a.prevP = tP;                                     /*   t <---> a <--- <tail>                                */
239           a.nextP = null();
240 
241           b.tailP = aP;
242           end;
243      else do;                                               /* One or more items already in list?                     */
244           nP = t.nextP;                                     /*   t <---> n                                            */
245                                                             /* BECOMES:                                               */
246           t.nextP = aP;                                     /*   t <---> a <---> n                                    */
247 
248           a.prevP = tP;
249           a.nextP = nP;
250 
251           n.prevP = aP;
252           end;
253      return;
254 
255 
256 Tlist_first_item:                                           /* Given a pointer to Tlist_base sub-structure of a       */
257      entry (AbaseP) returns(ptr);                           /*  threaded list, return pointer to first item in list.  */
258 
259      if AbaseP = null() then return ( null() );
260      bP = AbaseP;                                           /* Address parameter.                                     */
261      if b.headP ^= null then do;                            /*   <head> ---> t                                        */
262           tP = b.headP;
263           return (t.itemP);
264           end;
265      else return ( null() );                                /*   <head>                                               */
266 
267 
268 Tlist_last_item:                                            /* Given a pointer to Tlist_base sub-structure of a       */
269      entry (AbaseP) returns(ptr);                           /*  threaded list, return pointer to last item in list.   */
270 
271      if AbaseP = null() then return ( null() );
272      bP = AbaseP;                                           /* Address parameter.                                     */
273      if b.tailP ^= null() then do;                          /*   t <--- <tail>                                        */
274           tP = b.tailP;
275           return (t.itemP);
276           end;
277      else return ( null() );                                /*          <tail>                                        */
278 
279 
280 Tlist_next_item:                                            /* Given a pointer to Tlist_data sub-structure of an item */
281      entry (Athis_item_thread_dataP) returns(ptr);          /*  on a threaded list, return a pointer to next item     */
282                                                             /*  on the list.                                          */
283 
284      tP = Athis_item_thread_dataP;                          /* Address parameter.                                     */
285      if tP = null() then return ( null() );
286      if t.nextP = null then                                 /*   t <--- <tail>                                        */
287           return ( null() );
288      else do;                                               /*   t <---> n                                            */
289           nP = t.nextP;
290           return (n.itemP);
291           end;
292 
293 Tlist_prev_item:                                            /* Given a pointer to Tlist_data sub-structure of an item */
294      entry (Athis_item_thread_dataP) returns(ptr);          /*  on a threaded list, return a pointer to previous item */
295                                                             /*  on the list.                                          */
296 
297      tP = Athis_item_thread_dataP;                          /* Address parameter.                                     */
298      if tP = null() then return ( null() );
299      if t.prevP = null then                                 /*   <head> ---> t                                        */
300           return ( null() );
301      else do;                                               /*       p <---> t                                        */
302           pP = t.prevP;
303           return (p.itemP);
304           end;
305 
306 
307 Tlist_remove:                                               /* Given a pointer to Tlist_data sub-structure of an item */
308      entry (Aremove_item_thread_dataP);                     /*  on a list, remove that item from the threaded list.   */
309 
310   dcl  Aremove_item_thread_dataP ptr;                       /* Pointer to thread data in item to be removed from list */
311 
312      rP = Aremove_item_thread_dataP;                        /* Address parameter, and r.baseP                         */
313      if rP = null() then return;
314      bP = r.baseP;
315 
316      if bP = null() then return;                            /* item to remove is not in the list.                     */
317      else  if b.headP = rP & b.tailP = rP  then do;         /* item to remove is only item in the list.               */
318           b.headP = null();                                 /*   <head> ---> r <--- <tail>                            */
319                                                             /* BECOMES:                                               */
320           b.tailP = null();                                 /*   <head>             <tail>     r                      */
321           end;
322      else if b.headP = rP then do;                          /* item to remove is at head of multi-item list.          */
323           nP = r.nextP;                                     /*   <head> ---> r <----> n                               */
324                                                             /* BECOMES:                                               */
325           b.headP = nP;                                     /*   <head> ---> n                 r                      */
326 
327           n.prevP = null();
328           end;
329      else if b.tailP = rP then do;                          /* item to remove is at tail of multi-item list.          */
330           pP = r.prevP;                                     /*   p <---> r <--- <tail>                                */
331                                                             /* BECOMES:                                               */
332           p.nextP = null();                                 /*           p <--- <tail>         r                      */
333 
334           b.tailP = pP;
335           end;
336      else do;                                               /* item is in middle of multi-item list.                  */
337           pP = r.prevP;                                     /*   p <---> r <---> n                                    */
338           nP = r.nextP;                                     /* BECOMES:                                               */
339                                                             /*   p <---> n                     r                      */
340           p.nextP = nP;
341 
342           n.prevP = pP;
343           end;
344 
345      r.nextP = null();                                      /* In all cases, item being removed points to nothing     */
346      r.prevP = null();                                      /*  except itself.                                        */
347      r.baseP = null();
348      return;
349 
350 
351 Tlist_count:                                                /* Count items on a threaded list.                        */
352      entry (AbaseP) returns (fixed bin);
353 
354   dcl  Tcount fixed bin;
355 
356      bP = AbaseP;
357      if bP = null() then return ( 0 );
358      Tcount = 0;
359 
360      do tP = b.headP
361       repeat t.nextP while (tP ^= null());
362           Tcount = Tcount + 1;
363           if Tcount >= 99 then                              /* Avoid infinite loop...                                 */
364                return (999);
365           end;
366      return (Tcount);
367 
368      end Tlist_;
369 
370 /*  END OF:         mbuild_Tlist_.incl.pl1                    *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  * */