1 /* START OF: _help_shared_data_.incl.pl1 * * * * * * * * * * * * * * * * * * * */ 2 3 4 /****^ HISTORY COMMENTS: 5 1) change(2020-10-25,GDixon), approve(2021-02-23,MCR10089), 6 audit(2021-03-31,Swenson), install(2021-03-31,MR12.6g-0053): 7 A) Initial version created as part of rewriting help_ subroutine. 8 B) Add hi.ALL_PARAGRAPHS_LABEL to support the new all_paragraphs 9 response. 10 C) Reorder items in help_info.info_ptrs substructure. 11 END HISTORY COMMENTS */ 12 13 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 14 /* */ 15 /* Data shared between: help_.pl1, help_requests_.pl1 and help_responses_.pl1; and */ 16 /* help_util_ and help_listen_util_. */ 17 /* */ 18 /* FUNCTION: Document hidden data stored before the help_args public data structure. */ 19 /* - Document location/content of help_info structure (declared below). */ 20 /* - Document location of info_seg_data structure in temp segment */ 21 /* (declared in info_seg_dcls_.incl.pl1) */ 22 /* Document location of help_args in temp segment (declared in help_args_.incl.pl1). */ 23 /* Document hidden data stored after the help_args public data structure. */ 24 /* - Document location of Dinfo structure (declared below.) */ 25 /* - Document location of PDinfo_seg structure (declared in help_cis_args_.incl.pl1). */ 26 /* */ 27 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 28 29 dcl 1 help_info aligned, /* .. Position 1 (base) of help_ temp segment. */ 30 31 2 init_ptrs, /* == Items set by help_$init call. == */ 32 3 (sciP, /* - help_ subsystem's ssu_ invocation info_ptr */ 33 areaP, /* - Points to help_ subsystem's standard allocation */ 34 /* area (supplied by ssu_). */ 35 36 isdP, /* - Points to info_seg_ subsystem's info_seg_data struct*/ 37 /* .. Position 2 within help_ temp segment. */ 38 39 help_argsP, /* - Points to help_args (help_ input arguments from */ 40 /* help command or caller) */ 41 /* .. Position 3 within help_ temp segment. */ 42 43 next_free_spaceP /* - Points to next available space in help_ temp seg. */ 44 ) ptr, 45 46 2 help_ptrs, /* == Items set by help_$help_ call. == */ 47 3 (Dinfo_arrayP, /* - Points to Dinfo structure containing an array of */ 48 /* Dinfo_seg structures, each describing one info */ 49 /* block matching a help_args.path(I) input argument. */ 50 /* .. Position 4 within help_ temp segment. */ 51 52 Dinfo_sort_ptrsP, /* - Points to PDinfo_seg structure containing a sorted */ 53 /* array of pointers to one of Dinfo_seg structures. */ 54 /* .. Position 5 within help_ temp segment. */ 55 56 DinfoP /* - Points to current Dinfo_seg structure. */ 57 ) ptr, 58 59 2 help_video_data, /* == Items set by help_$help_ & its display_block rtn == */ 60 3 video_iocbP ptr, /* - Points to IOCB of process's active video terminal. */ 61 62 /* == Items set by display_block & help_listen_util_ == */ 63 3 prompt_region, /* - Upper-left line/col index and lines/cols extent of */ 64 4 (lineI, colI, linesN, colsN) fixed bin, /* region containing most recent prompt & user response*/ 65 3 clear_prompt_regionS bit(1) aligned, /* - if T: clear prompt region before displaying pghs. */ 66 3 hvd_pad bit(36) aligned, 67 68 2 help_labels, /* == Labels set by help_$help_, used by display_block == */ 69 /* help_listen_util_ & help_responses_ */ 70 /* to handle asynchronous events. */ 71 /* Transfer to given label when response ... */ 72 3 NEXT_INFO_LABEL label variable, /* - requires skipping to next file. */ 73 3 PI_LABEL label variable, /* - interrupted via program_interrupt signal. */ 74 3 ALL_PARAGRAPHS_LABEL label variable, /* - wishes to print all paragraphs of current block, */ 75 /* or all blocks of a subroutine info seg. */ 76 3 ANOTHER_BLOCK_LABEL label variable, /* - requires changing to another block in same info seg.*/ 77 /* - iBlokP points to iBlok of that target block. */ 78 3 SUBSYSTEM_ABORT_LABEL label variable, /* - requires exiting help_ subsystem. */ 79 80 2 help_numbers, /* == Items set by help_$help_, used by header response== */ 81 3 (Dinfo_sort_ptrsI, /* - Index of current Dinfo_seg structure's pointer in */ 82 /* PDinfo_seg.P array of pointers to Dinfo_seg structs */ 83 Dinfo_last_cross_refI, /* - Index of last Dinfo_seg structure's pointer in the */ 84 /* PDinfo_seg.P array of pointers w/ Scross_ref = T. */ 85 86 /* == Items set by help_$help_ and display_block == */ 87 infos_printedN, /* - Count of Dinfo_seg info blocks displayed by help_. */ 88 89 /* == Items set by help_$help_, display_block, == */ 90 /* help_listen_util_, help_responses_, etc. */ 91 terminal_lineL, /* - Max length for lines on current terminal. */ 92 newline_Nblanks_output, /* - Count of blank lines emitted w/o additional output. */ 93 hn_pad /* - Pad field for alignment of pointers that follow. */ 94 ) fixed bin, 95 96 2 info_ptrs, /* == Data set/used by help_'s display_block and == */ 97 /* help_responses for each block. */ 98 3 storage, 99 4 (CACHE_caP, /* - Points to cache of default control_arg resp args. */ 100 CACHE_findP, /* - Points to cache of default find_info response args. */ 101 CACHE_scnP, /* - Points to cache of default section response args. */ 102 CACHE_srhP, /* - Points to cache of default search response args. */ 103 104 STRING_entrypointsP, /* - Points to STRING w/ list of subr entrypoints */ 105 LIST_entrypointsP, /* - Points to LIST of subr entrypoints in current info */ 106 LIST_non_subroutine_responsesP, /* - Points to LIST of help non-subroutine responses */ 107 LIST_subroutine_responsesP, /* - Points to LIST of help subroutine responses */ 108 LIST_helpRql_responsesP /* - Points to List of help request loop responses */ 109 ) ptr, /* (not currently used since help request does not */ 110 /* prompt user and accepts no responses) */ 111 112 /* == Data for the "current block" being displayed. == */ 113 3 (iFileP, /* - Points to block container's iFile structure. */ 114 iBlokP /* - Points to selected block's iBlok structure. */ 115 ) ptr, 116 117 3 selected, /* == Data for tracking "current paragraph" of block. == */ 118 4 (iSectP, /* - Points to selected section; null at "top" of block. */ 119 iPghP /* - Points to selected paragraph; null to select sect. */ 120 ) ptr, 121 122 3 iPgh_print_range, /* == Data given next chunk put onto terminal page. == */ 123 4 (startP, /* - Points to 1st paragraph to be displayed on cur page */ 124 endP /* - Points to last pgh to be displayed on current page */ 125 ) ptr, /* of display_block output. */ 126 127 2 info_numbers, /* == Data set by help_'s display_block procedure. == */ 128 3 (block_progress, /* - Progress selecting/searching/displaying info block. */ 129 /* (see BLOCK_PROGRESS_xxx constants below) */ 130 display_mode, /* - Current block is non-subroutine vs. subroutine. */ 131 /* (see DISPLAY_MODE_xxx constants below) */ 132 display_limit, /* - Limits on output paragraphs. */ 133 /* (see DISPLAY_LIMIT_xxx constants below) */ 134 header_Nlines_follow /* - Count of lines to be displayed immediately after */ 135 /* current help_responses_$header output. This value */ 136 /* is zeroed when header has been displayed. */ 137 ) fixed bin, 138 139 2 info_switches, /* == Switches controlling display/prompt content. == */ 140 3 (print_inhibitS, /* - If true, inhibit any printed output. */ 141 /* Set at PI_LABEL targets. */ 142 /* Cleared when ready to display next prompt. */ 143 prompt_repeatS, /* - If true, inhibits display of next info paragraphs, */ 144 /* and forces prior "More help?" prompt to be repeated.*/ 145 /* Set when response diagnoses user error, or */ 146 /* non-pgh request returns. */ 147 section_search_matchedS, /* - Result returned by most recent section/search/find */ 148 /* response. */ 149 another_blockS /* - If true, selects header format w/o path of info seg.*/ 150 /* Set when switching to another info block after */ 151 /* earlier printing of full header. It's same */ 152 /* info seg, just a different block. */ 153 ) bit(1) aligned, 154 3 Sctl aligned like help_args.Sctl; /* Copy of help_args.Sctl switches which can be changed */ 155 /* by display_block or responses as display ops occur. */ 156 157 dcl 1 hi aligned like help_info based (help_infoP), /* Short name for help_info structure. */ 158 help_infoP ptr; 159 160 dcl hi_area area based (hi.areaP); /* Temporary area used to call external subroutines which */ 161 /* expect an "area with standard characteristics" */ 162 163 dcl (BLOCK_PROGRESS_new_block init(1), /* Starting to process a new info block (Dinfo.seg item). */ 164 BLOCK_PROGRESS_section_search init(2), /* Searching within block for starting section/paragraph. */ 165 BLOCK_PROGRESS_needs_header init(3), /* First header response emits full header & increments */ 166 BLOCK_PROGRESS_display init(4) /* Entering request loop to display info block sections. */ 167 ) fixed bin int static options(constant); 168 169 dcl (DISPLAY_LIMIT_none init(0), /* - Set when displaying all paragraphs that fit on page.*/ 170 DISPLAY_LIMIT_section init(1), /* - Set when displaying only paragraphs of 1 section. */ 171 DISPLAY_LIMIT_unseen init(2), /* - Set when displaying only unseen paragraphs. */ 172 DISPLAY_LIMIT_rest_unseen init(3) /* - Set when displaying all remaining unseen paragraphs.*/ 173 ) fixed bin int static options(constant); 174 175 dcl (DISPLAY_MODE_unset init(0), 176 DISPLAY_MODE_non_subroutine init(1), /* - Set when displaying non-subroutine info block */ 177 DISPLAY_MODE_subroutine init(2), /* - Set when displaying subroutine w/ entrypoints block */ 178 DISPLAY_MODE_help_request_loop init(3) /* - Set when invoking help from help_'s request loop */ 179 ) fixed bin int static options(constant); 180 181 dcl HELP_LINE_SIZE_DEFAULT fixed bin int static options (constant) init (79); 182 dcl HELP_LINE_SIZE_MAX fixed bin int static options (constant) init (136); 183 184 dcl (HELP_PAGE_LENGTH_BIG init (35), /* Page size between 36 : 200 inclusive */ 185 HELP_PAGE_LENGTH_MID init (25), /* Page size between 26 : 35 inclusive */ 186 HELP_PAGE_LENGTH_SHORT init (15), /* Page size between 15 : 25 inclusive */ 187 HELP_PROMPT_LINES_MAX init ( 7), /* Prompt lines reserved on BIG length pages. */ 188 HELP_PROMPT_LINES_MID init ( 5), /* Prompt lines reserved on MID length pages. */ 189 HELP_PROMPT_LINES_MIN init ( 3), /* Prompt lines reserved on SHORT length pages. */ 190 HELP_PROMPT_RESPONSE_MIN_SPACE init (50) 191 ) fixed bin int static options(constant); 192 193 dcl HELP_VERSION_02 char (20) int static options(constant) init("help version: 2.00"); 194 195 /* * * * * * * * * * * * * * * * * ** * * * * * * * * * * * * * * * * * * */ 196 %page; 197 /* * * * * * * * * * * * * * * * * ** * * * * * * * * * * * * * * * * * * */ 198 199 dcl 1 Dinfo_item aligned like Dinfo_seg based (hi.DinfoP); 200 201 dcl 1 Dinfo aligned based (PDinfo), /* Also pointed to by help_info.Dinfo_arrayP */ 202 2 N fixed bin, /* Information about each log. info to be printed. */ 203 2 seg (0 refer (Dinfo.N)) like Dinfo_seg, /* Dinfo_seg is declared in: help_cis_args_.incl.pl1 */ 204 PDinfo ptr; 205 /* Each Dinfo.seg substructure is accessed by an */ 206 /* element of the PDinfo_seg.P array (same include file). */ 207 /* - Also pointed to by help_info.Dinfo_sort_ptrsP */ 208 /* - Pointers of this array have been sorted in */ 209 /* alphabetical order by the given info segment entry */ 210 /* name (or first entry name matching given starname).*/ 211 212 /* * * * * * * * * * * * * * * * * ** * * * * * * * * * * * * * * * * * * */ 213 %page; 214 /* * * * * * * * * * * * * * * * * ** * * * * * * * * * * * * * * * * * * */ 215 216 dcl 1 LIST aligned based, /* structure used by help_util_ to format list of things */ 217 2 header, /* to be output in columns. */ 218 3 (N, /* number of list elements. */ 219 Npghs, /* number of filled paragraphs of formatted out. */ 220 Nrows, /* number of rows in formatted output. */ 221 Ncols, /* number of columns in formatted output. */ 222 ML (6) /* length of longest element in each column. */ 223 ) fixed bin, 224 2 title char (84), /* title of output list (includes COLON ending title). */ 225 /* NOTE: This element is pointed to by iLine.P & .L, */ 226 /* and by the Line structure. It cannot be a */ 227 /* varying string. */ 228 2 group (0 refer (LIST.N)), 229 3 arg char (88) varying, /* the argument. */ 230 3 Snot_found fixed bin, /* = 1 if no match found for the argument. */ 231 2 print_array (0 refer (LIST.Npghs), 0 refer (LIST.Nrows)), 232 3 line_out char (HELP_LINE_SIZE_MAX); /* Array of lines to be output to the screen. */ 233 234 /* * * * * * * * * * * * * * * * * ** * * * * * * * * * * * * * * * * * * */ 235 %page; 236 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 237 238 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 239 /* */ 240 /* SUBROUTINE: error, response_error */ 241 /* */ 242 /* SYNTAX: */ 243 /* declare error entry options(variable); */ 244 /* call error (sci_ptr, status_code, ioa_string, optional_args); */ 245 /* */ 246 /* declare response_error entry options(variable); */ 247 /* call response_error (sci_ptr, status_code, ioa_string, optional_args); */ 248 /* */ 249 /* FUNCTION: */ 250 /* Provide a shared error routine used throughout help_ which has an ssu_$print_message */ 251 /* interface, and also provides the following side effects: */ 252 /* 1) Suppresses messages if help_ caller set help_args.Sctl.inhibit_errors. */ 253 /* 2) Ensures there is a blank line printed before every error message. */ 254 /* 3) Resets count of consecutive blank lines emitted to zero after error message is printed. */ 255 /* 4) For error entrypoint, calls ssu_$print_message to display the error. */ 256 /* For response_error, calls ssu_$abort_line to prevent any response following the one in */ 257 /* error from being executed. */ 258 /* 5) For response_error entrypoint: */ 259 /* - sets help_info.prompt_repeatS = T to suppress printing when ssu_$listen calls */ 260 /* help_listen_util_$iPgh_print_range. */ 261 /* - ssu_$listen then calls help_listen_util_$display_prompt to repeat prior prompt so */ 262 /* USER can correct the error diagnosed in the response. */ 263 /* NOTE: If neither status_code nor ioa_string are given, ssu_$abort_line only aborts remainder */ 264 /* of the current user response line. */ 265 /* */ 266 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 267 268 error: 269 procedure options (variable); 270 271 dcl cu_$arg_ptr entry (fixed bin, ptr, fixed bin(21), fixed bin(35)), 272 cu_$arg_list_ptr entry returns (ptr), 273 cu_$generate_call entry (entry, ptr), 274 ssu_$abort_line entry() options(variable), 275 ssu_$get_info_ptr entry (ptr) returns(ptr), 276 ssu_$print_message entry() options(variable); 277 278 dcl first_argP ptr, 279 hiP ptr, 280 ignore_code fixed bin(35), 281 ignore_argL fixed bin(21), 282 response_epS bit(1) aligned, 283 sciP ptr; 284 285 dcl first_arg ptr based(first_argP); 286 287 response_epS = F; 288 goto error_JOIN; 289 290 291 response_error: 292 entry options (variable); 293 294 response_epS = T; 295 296 error_JOIN: 297 call cu_$arg_ptr (1, first_argP, ignore_argL, ignore_code); 298 sciP = first_arg; /* First argument is sci_ptr for help_'s ssu_ invocation */ 299 300 hiP = ssu_$get_info_ptr (sciP); /* Get pointer to help_info structure. */ 301 /* - help_$init sets this pointer, so we're sure it is */ 302 /* non-null(). */ 303 if hiP->hi.help_argsP -> help_args.Sctl.inhibit_errors then 304 return; /* If errors are inhibited, do nothing further. */ 305 else if hiP->hi.newline_Nblanks_output = 0 then 306 call newline (1); /* Output blank line before error. */ 307 308 hiP->hi.newline_Nblanks_output = 0; /* Errors count as printed output. Zero blank line count. */ 309 310 if response_epS then do; /* Set hi.prompt_repeatS to inhibit display of info text. */ 311 hiP->hi.prompt_repeatS = T; /* Instead, latest prompt is redisplayed, so new user */ 312 /* response can correct the error. */ 313 call cu_$generate_call (ssu_$abort_line, cu_$arg_list_ptr() ); 314 end; /* Let ssu_$abort_line generate error message and abort */ 315 /* any responses after the failing response in the */ 316 /* response line. ssu_$abort_line does not return here. */ 317 else call cu_$generate_call (ssu_$print_message, cu_$arg_list_ptr() ); 318 /* Let ssu_$print_message generate the error message. */ 319 320 return; 321 322 warning_avoid: 323 entry options (variable); 324 325 dcl hi_AVOID_PL1_WARNING entry variable; /* PL/I issues warning if any internal procedure is not */ 326 /* called. These procedures are not called by */ 327 hi_AVOID_PL1_WARNING = error; /* all includers of this include file. */ 328 hi_AVOID_PL1_WARNING = ioa; 329 hi_AVOID_PL1_WARNING = newline; 330 hi_AVOID_PL1_WARNING = set_space_used; 331 332 end error; 333 %page; 334 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 335 /* */ 336 /* SUBROUTINE: ioa, ioa$nnl */ 337 /* */ 338 /* SYNTAX: */ 339 /* declare ioa entry options(variable); */ 340 /* call ioa (ioa_control_string, optional_args); */ 341 /* */ 342 /* declare ioa$nnl entry options(variable); */ 343 /* call ioa$nnl (ioa_control_string, optional_args); */ 344 /* */ 345 /* FUNCTION: */ 346 /* Provide a shared ioa_-like routine used throughout help_ which also provides the following */ 347 /* side effects: */ 348 /* 1) Suppresses output if hi.print_inhibitS is T (as results of program_interrupt signal). */ 349 /* 2) Resets count of consecutive blank lines emitted to zero. */ 350 /* ioa$nnl acts like ioa_$nnl (it suppresses NL at end of output string). */ 351 /* */ 352 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 353 354 ioa: 355 procedure options(variable); 356 357 dcl cu_$arg_list_ptr entry returns (ptr), 358 cu_$generate_call entry (entry, ptr), 359 (ioa_, ioa_$nnl) entry() options(variable); 360 361 if help_infoP = null() then; /* caller's environment must have a help_infoP pointer; */ 362 /* otherwise, do nothing! */ 363 else do; 364 hi.newline_Nblanks_output = 0; 365 if ^hi.print_inhibitS then 366 call cu_$generate_call (ioa_, cu_$arg_list_ptr() ); 367 end; 368 return; 369 370 ioa$nnl: 371 entry options(variable); 372 373 if help_infoP = null() then; /* caller's environment must have a help_infoP pointer; */ 374 /* otherwise, do nothing! */ 375 else do; 376 hi.newline_Nblanks_output = 0; 377 if ^hi.print_inhibitS then 378 call cu_$generate_call (ioa_$nnl, cu_$arg_list_ptr() ); 379 end; 380 end ioa; 381 382 383 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 384 /* */ 385 /* SUBROUTINE: newline */ 386 /* */ 387 /* SYNTAX: */ 388 /* declare newline entry (fixed bin); */ 389 /* call newline (count_of_consecutive_NLs_to_emit); */ 390 /* */ 391 /* FUNCTION: */ 392 /* Provide a shared routine used throughout help_ to consolidate requests to output NLs, thus */ 393 /* avoiding excess consecutive NLs requested by different parts of help_ code. */ 394 /* */ 395 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 396 397 newline: 398 procedure (Acount); 399 400 dcl Acount fixed bin; /* Count between 1 and 5 (inclusive). */ 401 402 dcl iox_$put_chars entry (ptr, ptr, fixed bin(21), fixed bin(35)); 403 dcl iox_$user_output ptr ext static; 404 dcl NLs char(5) int static options(constant) init((5)" 405 "); 406 dcl ignore_code fixed bin(35); 407 408 dcl count fixed bin(21); 409 410 if help_infoP = null() then; 411 else if hi.print_inhibitS then; 412 413 else if hi.newline_Nblanks_output < Acount then do; 414 count = max (min (length(NLs), Acount - hi.newline_Nblanks_output), 0); 415 if count > 0 then do; 416 hi.newline_Nblanks_output = hi.newline_Nblanks_output + count; 417 call iox_$put_chars (iox_$user_output, addr(NLs), count, ignore_code); 418 end; 419 end; 420 421 end newline; 422 423 /* * * * * * * * * * * * * * * * * ** * * * * * * * * * * * * * * * * * * */ 424 %page; 425 /* * * * * * * * * * * * * * * * * ** * * * * * * * * * * * * * * * * * * */ 426 427 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 428 /* */ 429 /* SUBROUTINE: set_space_used */ 430 /* */ 431 /* SYNTAX: */ 432 /* declare set_space_used (size_of_current_storage_allocation); */ 433 /* call set_space_used (currentsize(STRUCTURE_NAME)); */ 434 /* */ 435 /* FUNCTION: */ 436 /* Provide a shared routine used by many parts of the help_ code to record size of structures */ 437 /* and/or arrays "pushed" onto the help_ temporary segment. The temp segment returned by */ 438 /* help_$init is treated like a push-down stack. At any point in time, help_ code can "push" */ 439 /* new storage onto the stack, so long as size of that new storage can be determined before that */ 440 /* code returns to its caller. */ 441 /* */ 442 /* USAGE: */ 443 /* 1) Declare a based storage item which may include adjustable extents (refer extents) for */ 444 /* array size, area size, or character string lengths. For example, see the help_args */ 445 /* structure declared in help_args_.incl.pl1. */ 446 /* 2) Base that storage declaration on a pointer variable: P */ 447 /* 3) Set P to the value of hi.next_free_spaceP (a variable in the structure pointed to by */ 448 /* help_infoP. */ 449 /* 4) Initialize storage elements and refer extent variables. When fully setup... */ 450 /* 5) Call set_space_used supplying the current size of this storage. Use the PL/I builtin */ 451 /* function currentsize(STORAGE_VARIABLE) to obtain current size of adjustable-size storage */ 452 /* elements, based on current values of their refer-variable elements. */ 453 /* */ 454 /* Code below will adjust this currentsize upwards to the next even-word boundary, thus ensuring */ 455 /* all storage items are aligned on an even-word boundary. */ 456 /* */ 457 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 458 459 set_space_used: 460 procedure (Asize_current_space); /* This procedure sets pointer to next free word of */ 461 /* storage in help_args temp segment. */ 462 463 dcl Asize_current_space fixed bin (21); /* Amount of space used in structure last structure in */ 464 /* temp segment. */ 465 466 hi.next_free_spaceP = addrel (hi.next_free_spaceP, Asize_current_space + mod (Asize_current_space, 2)); 467 return; 468 469 end set_space_used; 470 471 /* * * * * * * * * * * * * * * * * ** * * * * * * * * * * * * * * * * * * */ 472 473 /* END OF: _help_shared_data_.incl.pl1 * * * * * * * * * * * * * * * * * * * */