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 * * * * * * * * * * * * * * * * * * * */