Add GNU LGPL headers to all .c .C and .h files
[oweals/cde.git] / cde / osf / uil / UilSrcSrc.c
1 /*
2  * CDE - Common Desktop Environment
3  *
4  * Copyright (c) 1993-2012, The Open Group. All rights reserved.
5  *
6  * These libraries and programs are free software; you can
7  * redistribute them and/or modify them under the terms of the GNU
8  * Lesser General Public License as published by the Free Software
9  * Foundation; either version 2 of the License, or (at your option)
10  * any later version.
11  *
12  * These libraries and programs are distributed in the hope that
13  * they will be useful, but WITHOUT ANY WARRANTY; without even the
14  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15  * PURPOSE. See the GNU Lesser General Public License for more
16  * details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with these librararies and programs; if not, write
20  * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21  * Floor, Boston, MA 02110-1301 USA
22  */
23 /* 
24  *  @OSF_COPYRIGHT@
25  *  COPYRIGHT NOTICE
26  *  Copyright (c) 1990, 1991, 1992, 1993 Open Software Foundation, Inc.
27  *  ALL RIGHTS RESERVED (MOTIF). See the file named COPYRIGHT.MOTIF for
28  *  the full copyright text.
29 */ 
30 /* 
31  * HISTORY
32 */ 
33 #ifdef REV_INFO
34 #ifndef lint
35 static char rcsid[] = "$TOG: UilSrcSrc.c /main/13 1997/03/12 15:21:40 dbl $"
36 #endif
37 #endif
38
39 /*
40 *  (c) Copyright 1989, 1990, DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASS. */
41
42 /*
43 **++
44 **  FACILITY:
45 **
46 **      User Interface Language Compiler (UIL)
47 **
48 **  ABSTRACT:
49 **
50 **      This module contains the procedure for managing the UIL source
51 **      files.  
52 **
53 **--
54 **/
55
56
57 /*
58 **
59 **  INCLUDE FILES
60 **
61 **/
62
63 #include "UilDefI.h"
64
65 /* %COMPLETE */
66 #include <sys/stat.h>
67
68
69
70 /*
71 **
72 **  DEFINE and MACRO DEFINITIONS
73 **
74 **/
75
76
77
78 /*
79 **
80 **  EXTERNAL VARIABLE DECLARATIONS
81 **
82 **/
83
84
85 /*
86 **
87 **  GLOBAL VARIABLE DECLARATIONS
88 **
89 **/
90
91 /*
92 **  define the source buffer data structures
93 */
94
95 externaldef(uil_comp_glbl) src_source_buffer_type       *src_az_current_source_buffer;
96 externaldef(uil_comp_glbl) src_source_buffer_type       *src_az_avail_source_buffer;
97 externaldef(uil_comp_glbl) src_message_item_type        *src_az_orphan_messages;
98 /* %COMPLETE */
99 externaldef(uil_comp_glbl) long Uil_file_size;
100 struct stat stbuf;
101
102
103
104 /*
105 **  define the source record data structures
106 */
107
108 externaldef(uil_comp_glbl) src_source_record_type
109         *src_az_current_source_record;
110 externaldef(uil_comp_glbl) src_source_record_type
111         *src_az_first_source_record;
112
113 externaldef(uil_comp_glbl) uil_fcb_type
114         *src_az_source_file_table[src_k_max_source_files];
115 externaldef(uil_comp_glbl) int
116         src_l_last_source_file_number;
117
118 /*
119 **
120 **  OWN VARIABLE DECLARATIONS
121 **
122 **/
123     static uil_fcb_type     *main_fcb;
124     static char             *include_dir;
125     static unsigned short   main_dir_len;
126
127
128
129 \f
130 /*
131 **++
132 **  FUNCTIONAL DESCRIPTION:
133 **
134 **      This procedure initializes the reading of the UIL source program.
135 **
136 **  FORMAL PARAMETERS:
137 **
138 **      none
139 **
140 **  IMPLICIT INPUTS:
141 **
142 **      Uil_cmd_z_command
143 **
144 **  IMPLICIT OUTPUTS:
145 **
146 **      src_az_first_source_buffer
147 **      src_az_current_source_buffer
148 **      src_l_last_source_file_number
149 **      src_az_source_file_table
150 **      src_az_current_source_record
151 **      main_fcb
152 **      include_dir 
153 **      main_dir_len
154 **
155 **  FUNCTION VALUE:
156 **
157 **      void
158 **
159 **  SIDE EFFECTS:
160 **
161 **      source file is opened
162 **      source buffer structure is setup
163 **      source record structure is setup
164 **
165 **--
166 **/
167
168 void
169 src_initialize_source(void)
170 {
171     /* initialize source data structures */
172
173     src_az_current_source_buffer = NULL;
174     src_az_avail_source_buffer = NULL;
175     src_l_last_source_file_number = -1;
176     src_az_first_source_record = NULL;
177     src_az_current_source_record =
178         (src_source_record_type *) &src_az_first_source_record;
179
180     /*  Initialize Own storage    */
181
182     main_fcb = NULL;
183     include_dir = NULL;
184     main_dir_len = 0;
185
186
187     /* open the source file */
188     if ( Uil_cmd_z_command.ac_source_file == NULL )
189         diag_issue_diagnostic (d_src_open,
190                                diag_k_no_source, diag_k_no_column,
191                                "<null file name>");
192
193     src_open_file ( Uil_cmd_z_command.ac_source_file, NULL );
194
195     /* fixes initial filename is NULL bug in callable UIL */
196     Uil_current_file = Uil_cmd_z_command.ac_source_file;
197
198     return;
199 }
200 \f
201 /*
202 **++
203 **  FUNCTIONAL DESCRIPTION:
204 **
205 **      This procedure does the cleanup processing of the source files
206 **      structures.
207 **
208 **  FORMAL PARAMETERS:
209 **
210 **      none
211 **
212 **  IMPLICIT INPUTS:
213 **
214 **      Uil_cmd_z_command
215 **      src_az_first_source_buffer
216 **      src_az_current_source_buffer
217 **      src_l_last_source_file_number
218 **      src_az_source_file_table
219 **      src_az_current_source_record
220 **
221 **  IMPLICIT OUTPUTS:
222 **
223 **      none
224 **
225 **  FUNCTION VALUE:
226 **
227 **      void
228 **
229 **  SIDE EFFECTS:
230 **
231 **      structures are freed
232 **
233 **--
234 **/
235
236 void
237 Uil_src_cleanup_source(void)
238 {
239
240     int                         i;                  /* index over fcbs */
241     src_source_buffer_type      *buffer_to_free;   
242     src_source_record_type      *record_to_free;
243     src_machine_code_type       *first_code_item; 
244     src_machine_code_type       *code_item_to_free; 
245     status                      l_close_status;
246
247     /*
248     **  Loop through all open files freeing their fcbs
249     */
250     for (i = 0; i <= src_l_last_source_file_number; i++)
251         {
252         /* it is possible to get an error before the files are open,
253            so check and see if table is NULL before opening */
254         if (src_az_source_file_table[i] == NULL)
255                 continue;
256         l_close_status = close_source_file (src_az_source_file_table[i]);
257         if ( l_close_status == src_k_close_error )
258             {
259             diag_issue_diagnostic (d_src_close,
260                                    diag_k_no_source, diag_k_no_column,
261                                    src_az_source_file_table[i]->expanded_name);
262             }
263         _free_memory ((char*)src_az_source_file_table [i]);
264         src_az_source_file_table[i] = NULL;
265         }
266
267     /*
268     **  Loop through list of current source buffers, freeing them
269     */
270     while (src_az_current_source_buffer != NULL)
271         {
272         buffer_to_free = src_az_current_source_buffer;
273         src_az_current_source_buffer = 
274             src_az_current_source_buffer->az_prior_source_buffer;
275         _free_memory ((char*)buffer_to_free);
276         }
277
278     /*
279     **  Loop through list of source records, freeing them
280     */
281     while (src_az_first_source_record != NULL)
282         {
283         record_to_free = src_az_first_source_record;
284         first_code_item = record_to_free->az_machine_code_list;
285         
286         while (first_code_item != NULL)
287           {
288             code_item_to_free = first_code_item;
289             first_code_item = first_code_item->az_next_machine_code;
290             _free_memory((char *)code_item_to_free);
291           }
292         
293         src_az_first_source_record =
294             src_az_first_source_record->az_next_source_record;
295         _free_memory ((char*)record_to_free);
296         }
297
298     /*
299     **  Free Own storage
300     */
301 /* BEGIN OSF FIX pir 2240 */
302     /* Memory pointed to by main_fcb already freed. */
303 /* END OSF FIX pir 2240 */
304     _free_memory (include_dir);
305
306     return;
307 }
308 \f
309 /*
310 **++
311 **  FUNCTIONAL DESCRIPTION:
312 **
313 **      This procedure opens a file and sets up the static pointers to
314 **      read from this file.
315 **
316 **  FORMAL PARAMETERS:
317 **
318 **      c_file_name         file to open
319 **
320 **  IMPLICIT INPUTS:
321 **
322 **      src_az_first_source_buffer
323 **      src_az_current_source_buffer
324 **      src_l_last_source_file_number
325 **      src_az_source_file_table
326 **
327 **  IMPLICIT OUTPUTS:
328 **
329 **      src_az_first_source_buffer
330 **      src_az_current_source_buffer
331 **      src_l_last_source_file_number
332 **      src_az_source_file_table
333 **
334 **  FUNCTION VALUE:
335 **
336 **      void
337 **
338 **  SIDE EFFECTS:
339 **
340 **      input file is opened
341 **      input buffer structure is setup
342 **      input record structure is setup
343 **
344 **--
345 **/
346
347 void
348 src_open_file (XmConst char *c_file_name,
349                char         *full_file_name)
350 {
351     uil_fcb_type                *az_fcb;            /* file control block ptr */
352     status                      l_open_status;      /* status variable */
353     src_source_buffer_type      *az_source_buffer;  /* source buffer ptr */
354
355     /* allocate fcb and source buffer */
356
357     az_fcb = (uil_fcb_type *) _get_memory (sizeof (uil_fcb_type));
358
359     if (src_az_avail_source_buffer != NULL) {
360         az_source_buffer = src_az_avail_source_buffer;
361         src_az_avail_source_buffer = 
362                 src_az_avail_source_buffer->az_prior_source_buffer;
363     } else {
364         az_source_buffer =
365             (src_source_buffer_type *)
366                         _get_memory (sizeof (src_source_buffer_type));
367     }
368
369     /* Call the OS-specific open file procedure */
370
371     l_open_status = open_source_file (
372                         c_file_name,
373                         az_fcb,
374                         az_source_buffer );
375
376     /*  If the file is not found, a fatal error is generated.   */
377
378     if ( l_open_status == src_k_open_error ) {
379         diag_issue_diagnostic( d_src_open,
380                                diag_k_no_source, diag_k_no_column,
381                                c_file_name );
382     }
383
384     /* put fcb in the file table */
385
386     src_l_last_source_file_number++;
387
388     if (src_l_last_source_file_number >= src_k_max_source_files) {
389         diag_issue_diagnostic (
390                 d_src_limit,
391                 src_az_current_source_record,
392                 src_az_current_source_buffer -> w_current_position - 1,
393                 az_fcb->expanded_name );
394     }
395
396     src_az_source_file_table[ src_l_last_source_file_number ] = az_fcb;
397
398     /* Complete the OS-independent initialization. Get the size of the file
399     ** for %complete info then initialize a source
400     ** buffer placing a null in the buffer will cause the lexical analyzer
401     ** to start by reading the first line of the file
402     */
403
404     /* %COMPLETE */
405     if (stat(az_fcb->expanded_name, &stbuf) == -1) {
406         diag_issue_diagnostic( d_src_open,
407                                diag_k_no_source, diag_k_no_column,
408                                az_fcb->expanded_name );
409     }
410
411     Uil_file_size = stbuf.st_size;
412
413     if (full_file_name != NULL)
414         strcpy (full_file_name, az_fcb->expanded_name);
415
416     az_fcb->v_position_before_get = FALSE;
417
418     az_source_buffer->w_current_line_number = 0;
419     az_source_buffer->b_file_number = src_l_last_source_file_number;
420     az_source_buffer->w_current_position = 0;
421     az_source_buffer->c_text[ 0 ] = 0;
422
423     /* make the source buffer current */
424
425     az_source_buffer->az_prior_source_buffer =
426                                 src_az_current_source_buffer;
427     src_az_current_source_buffer = az_source_buffer;
428
429     return;
430 }
431 \f
432 /*
433 **++
434 **  FUNCTIONAL DESCRIPTION:
435 **
436 **      This procedure reads the next source line;
437 **
438 **  FORMAL PARAMETERS:
439 **
440 **      none
441 **
442 **  IMPLICIT INPUTS:
443 **
444 **      src_az_source_file_table
445 **
446 **  IMPLICIT OUTPUTS:
447 **
448 **      src_az_current_source_buffer
449 **      src_az_current_source_record
450 **
451 **  FUNCTION VALUE:
452 **
453 **      src_k_end_source        no more source lines
454 **      src_k_read_normal       new line in the source buffer
455 **
456 **  SIDE EFFECTS:
457 **
458 **      may issue diagnostics if error occurs reading record
459 **      may restore previous source upon reaching end of current source
460 **
461 **--
462 **/
463
464 status
465 src_get_source_line(void)
466 {
467     uil_fcb_type            *az_fcb;
468     src_source_record_type  *az_source_record;
469     status                  l_read_status;
470
471     /* Return if already at the end of file */
472
473     if (src_az_current_source_buffer == NULL)
474         return src_k_end_source;
475
476     /* Find the current fcb */
477
478     az_fcb = src_az_source_file_table
479                 [ src_az_current_source_buffer->b_file_number ];
480
481     /* Read the next record */
482
483     l_read_status = get_line( az_fcb );
484
485     /* Increment lines processed count, and update current file */
486     Uil_lines_processed++;
487     Uil_current_file = az_fcb->expanded_name;
488
489     if ( (l_read_status == src_k_read_normal) ||
490          (l_read_status == src_k_read_truncated) )
491     {
492         /* Read was successful
493          * Set position to the start of the record */
494
495         src_az_current_source_buffer->w_current_position = 0;
496
497         /* Allocate and initialize a source record */
498         
499         az_source_record = 
500             (src_source_record_type *)
501                 _get_memory( sizeof( src_source_record_type ) );
502
503         az_source_record->az_next_source_record = NULL;
504         az_source_record->w_line_number = 
505             ++src_az_current_source_buffer->w_current_line_number;
506         az_source_record->b_file_number = 
507             src_az_current_source_buffer->b_file_number;
508         az_source_record->az_message_list = NULL;
509         az_source_record->az_machine_code_list = NULL;
510         az_source_record->w_machine_code_cnt = 0;
511         az_source_record->z_access_key = az_fcb->last_key;
512
513         /* was uninitialized; fixes listing problem on HP  (RAP) */
514         az_source_record->b_flags = 0;
515
516         /* Link the source record to the end of source record list */
517
518         src_az_current_source_record->az_next_source_record =
519             az_source_record;
520         src_az_current_source_record = az_source_record;
521
522         if (l_read_status == src_k_read_truncated)
523             diag_issue_diagnostic( d_src_truncate,
524                                    src_az_current_source_record,
525                                    diag_k_no_column,
526                                    src_k_max_source_line_length );
527     
528         return src_k_read_normal;
529     }
530
531     /* Check for end of file */
532
533     if (l_read_status == src_k_end_source)
534     {
535         src_source_buffer_type  *az_prior_source_buffer;
536         
537         /* get prior source buffer */
538
539         az_prior_source_buffer = 
540             src_az_current_source_buffer->az_prior_source_buffer;
541
542         /* place current source buffer on the available list */
543
544         src_az_current_source_buffer->az_prior_source_buffer =
545             src_az_avail_source_buffer;
546         src_az_avail_source_buffer = src_az_current_source_buffer;
547
548         /* if there is no prior source buffer - return end of source */
549
550         if (az_prior_source_buffer == NULL)
551             return src_k_end_source;
552
553         /* restore the prior buffer as current */
554
555         src_az_current_source_buffer = az_prior_source_buffer;
556
557         return src_k_read_normal;
558     }
559
560     /* must have been an error */
561
562     diag_issue_diagnostic( d_src_read,
563                            src_az_current_source_record,
564                            diag_k_no_column,
565                            az_fcb->expanded_name );
566
567     _assert( FALSE, "read past source error" );
568         return(src_k_read_error);
569 }
570
571 \f
572
573
574 \f
575
576
577 /*
578 **++
579 **  FUNCTIONAL DESCRIPTION:
580 **
581 **      open the source file.
582 **
583 **  FORMAL PARAMETERS:
584 **
585 **      c_file_name         source file to open
586 **      az_fcb              file control block for the file
587 **      az_source_buffer    source buffer for the file
588 **
589 **  IMPLICIT INPUTS:
590 **
591 **      none
592 **
593 **  IMPLICIT OUTPUTS:
594 **
595 **      none
596 **
597 **  FUNCTION VALUE:
598 **
599 **      src_k_open_normal
600 **      src_k_open_error
601 **
602 **  SIDE EFFECTS:
603 **
604 **      file is opened and has a source buffer associated with it
605 **
606 **--
607 **/
608
609 status
610 open_source_file( XmConst char           *c_file_name, 
611                   uil_fcb_type           *az_fcb, 
612                   src_source_buffer_type *az_source_buffer )
613 {
614
615     static unsigned short       main_dir_len = 0;
616     boolean                     main_file;
617     int                         i;  /* loop index through include files */
618     char                        buffer[256];
619
620
621     /* place the file name in the expanded_name buffer */
622
623     strcpy(buffer, c_file_name);
624
625 /*    Determine if this is the main file or an include file.  */
626
627     main_file = (main_fcb == NULL);
628
629     if (main_file) {
630
631         char XmConst            * ptr;
632         unsigned short          len;
633
634 /*    Save the directory info for the main file.    */
635
636         for (len = strlen (c_file_name),
637              ptr = & c_file_name [len - 1];
638              len > 0; len--, ptr--) {
639             if ((* ptr) == '/') {
640                 break;
641             }
642         }
643
644         main_dir_len = len;
645         main_fcb = az_fcb;
646
647 /*    Open the main file.    */
648
649         az_fcb->az_file_ptr = fopen(c_file_name, "r");
650
651     } else {
652         static char XmConst     c_include_dir[]= "/usr/include/";
653         Boolean                 search_user_include=True;
654         Boolean                 specific_directory=False;
655
656 /*    See if the file name has a leading slash and set the flag. 
657       Look in the specified directory for the include file.  If the dir
658       is not specified (leading slash), look in the main file's directory  */
659
660         if (c_file_name[0] == '/') {
661             specific_directory = True;
662             }
663
664         if (!specific_directory) {
665             _move (buffer, main_fcb -> expanded_name, main_dir_len);
666             _move (& buffer [main_dir_len],
667                    c_file_name, strlen (c_file_name) + 1);  /* + NULL */
668         } else {
669             strcpy (buffer, c_file_name);
670         }
671
672 /*    Open the include file.    */
673
674         az_fcb->az_file_ptr = fopen (buffer, "r");
675
676 /*    If a specific directory was specified, or if the file was found,
677       then we are done. */
678
679         if ( (specific_directory) || (az_fcb -> az_file_ptr != NULL) ) {
680           goto open_label;
681         }
682
683 /*    Look in the command line specified include directories, if any.    */
684
685         for (i = 0; i < Uil_cmd_z_command.include_dir_count; i++) {          
686             int         inc_dir_len;
687
688             inc_dir_len = strlen (Uil_cmd_z_command.ac_include_dir[i]);
689             if (inc_dir_len == 0) {
690                 search_user_include = False;
691                 }
692             _move (buffer, Uil_cmd_z_command.ac_include_dir[i], inc_dir_len);
693
694         /*  Add '/' if not specified at end of directory  */
695
696             if (Uil_cmd_z_command.ac_include_dir[i][inc_dir_len - 1] != '/') {
697                 buffer [inc_dir_len] = '/';
698                 inc_dir_len++;
699             };
700
701             _move (& buffer [inc_dir_len],
702                    c_file_name, strlen (c_file_name) + 1);  /* + NULL */
703
704         /*    Open the include file.  If found, we are done.    */
705
706             az_fcb->az_file_ptr = fopen (buffer, "r");
707
708             if (az_fcb -> az_file_ptr != NULL) {
709                 goto open_label;
710             }
711         }
712
713 /*    Look in the default include directory.    */
714         if (search_user_include) {
715           _move(buffer, c_include_dir, sizeof c_include_dir - 1); /* no NULL */
716           _move(&buffer[sizeof c_include_dir - 1], 
717                 c_file_name, strlen (c_file_name) + 1);  /* + NULL */
718
719 /*    Open the include file.    */
720           az_fcb->az_file_ptr = fopen (buffer, "r");
721         }
722     }
723
724 open_label:
725
726     /* check the open status. */
727
728     if (az_fcb->az_file_ptr == NULL)
729         return src_k_open_error;
730
731     /* open succeeded - place buffer address in fcb */
732
733     az_fcb->c_buffer = az_source_buffer->c_text;
734     az_fcb->c_buffer[ src_k_max_source_line_length ] = 0;
735     strcpy(az_fcb->expanded_name, buffer);
736
737     return src_k_open_normal;
738 }
739
740 \f
741 /*
742 **++
743 **  FUNCTIONAL DESCRIPTION:
744 **
745 **      close the source file.
746 **
747 **  FORMAL PARAMETERS:
748 **
749 **      az_fcb              file control block for the file
750 **
751 **  IMPLICIT INPUTS:
752 **
753 **      none
754 **
755 **  IMPLICIT OUTPUTS:
756 **
757 **      none
758 **
759 **  FUNCTION VALUE:
760 **
761 **      src_k_close_normal
762 **      src_k_close_error
763 **
764 **  SIDE EFFECTS:
765 **
766 **      none
767 **
768 **--
769 **/
770
771 status
772 close_source_file( uil_fcb_type *az_fcb )
773 {
774     status      l_close_status;
775
776     /*
777     ** Close  the file
778     */
779
780     l_close_status = fclose (az_fcb->az_file_ptr);
781
782     if ( l_close_status != EOF )
783         return src_k_close_normal;
784     else
785         return src_k_close_error;
786 }
787 \f
788 /*
789 **++
790 **  FUNCTIONAL DESCRIPTION:
791 **
792 **      read line of the source file.
793 **
794 **  FORMAL PARAMETERS:
795 **
796 **      az_fcb              file control block for the file
797 **
798 **  IMPLICIT INPUTS:
799 **
800 **      none
801 **
802 **  IMPLICIT OUTPUTS:
803 **
804 **      none
805 **
806 **  FUNCTION VALUE:
807 **
808 **      src_k_read_normal
809 **      src_k_read_error
810 **      src_k_read_truncated
811 **      src_k_end_source
812 **
813 **  SIDE EFFECTS:
814 **
815 **      next record in file is read
816 **
817 **--
818 **/
819
820 status
821 get_line( uil_fcb_type *az_fcb )
822 {
823     status      l_read_status;
824     char        *c_new_line;
825
826     /*  
827     **  if v_position_before_get is true, we need to reposition
828     **  before the get because another retrieve has altered the
829     **  current record.
830     */
831
832     if (az_fcb->v_position_before_get)
833     {
834         fseek( az_fcb->az_file_ptr,
835                az_fcb->last_key.l_key,
836                0 );
837         l_read_status = (status) (fgets(az_fcb->c_buffer, 
838                                         src_k_max_source_line_length, 
839                                         az_fcb->az_file_ptr) != NULL);
840         az_fcb->v_position_before_get = FALSE;
841     }
842
843     /* get the current offset */
844
845     az_fcb->last_key.l_key = ftell(az_fcb->az_file_ptr);
846     
847     /* read the next line */
848
849     l_read_status = (status) (fgets(az_fcb->c_buffer, 
850                                     src_k_max_source_line_length, 
851                                     az_fcb->az_file_ptr) != NULL );
852
853     if ( l_read_status != 0 )
854     {
855         /* Read was successful
856          * Find \n character an replace with a null */
857
858         c_new_line = (char *) strchr( az_fcb->c_buffer, '\n' );
859
860         if (c_new_line == NULL) {
861
862 /* Fix for CR 3044 -- only return truncated if not at eof */
863
864             if (!feof(az_fcb->az_file_ptr))
865                 return src_k_read_truncated;
866         } else {
867             *c_new_line = 0;
868         } 
869
870         return src_k_read_normal;
871     }
872
873     /* Check for end of file */
874
875     if (feof(az_fcb->az_file_ptr))
876     {
877         if (sym_az_current_section_entry->prev_section != NULL)
878             {
879             sym_include_file_entry_type *include_entry;
880
881             /*
882             ** This is the end of an include file.  Set the pointers so that the sections
883             ** in the include file hang off the previous list correctly.
884             */
885             include_entry = (sym_include_file_entry_type *)
886                                 sym_az_current_section_entry->prev_section->entries;
887             include_entry->sections = sym_az_current_section_entry;
888             sym_az_current_section_entry = sym_az_current_section_entry->prev_section;
889             }
890         return src_k_end_source;
891     }
892
893     /* must have been an error */
894
895     return src_k_read_error;
896 }
897 \f
898 /*
899 **++
900 **  FUNCTIONAL DESCRIPTION:
901 **
902 **      re-read line of the source file.
903 **
904 **  FORMAL PARAMETERS:
905 **
906 **      az_fcb              file control block for the file
907 **      c_buffer            pointer to buffer to hold the source line
908 **      z_access_key        key to retrieve the source line
909 **  
910 **  IMPLICIT INPUTS:
911 **
912 **      none
913 **
914 **  IMPLICIT OUTPUTS:
915 **
916 **      v_position_before_read = TRUE
917 **
918 **  FUNCTION VALUE:
919 **
920 **      true            if the record can be retrieved
921 **      false           if the record cannot be retrieved
922 **
923 **  SIDE EFFECTS:
924 **
925 **      change next record for the file
926 **
927 **--
928 **/
929
930 boolean
931 reget_line( uil_fcb_type  *az_fcb, 
932             char          *c_buffer, 
933             XmConst z_key *z_access_key )
934 {
935     status      l_read_status;
936     char        *c_new_line;
937
938     fseek( az_fcb->az_file_ptr,
939            z_access_key->l_key,
940            0 );
941
942     l_read_status = (status) (fgets(c_buffer, 
943                                     src_k_max_source_line_length, 
944                                     az_fcb->az_file_ptr) != NULL );
945
946     az_fcb->v_position_before_get = TRUE;
947
948     if ( l_read_status != 0 )
949     {
950         /* Read was successful
951          * Find \n character an replace with a null */
952
953         c_new_line = (char *) strchr( c_buffer, '\n' );
954
955         if (c_new_line == NULL) {
956
957 /* Fix for CR 3044 -- only return truncated if not at eof */
958
959             if (!feof(az_fcb->az_file_ptr))
960                 return src_k_read_truncated;
961         } else {
962             *c_new_line = 0;
963         }        
964
965         return TRUE;
966     }
967
968     /* must have been an error */
969
970     return FALSE;
971 }
972
973 \f
974 /*
975 **++
976 **  FUNCTIONAL DESCRIPTION:
977 **
978 **      Given a source record, this function returns the file name of
979 **      the file containing that source record.
980 **
981 **  FORMAL PARAMETERS:
982 **
983 **      az_src_rec      pointer to a source record structure
984 **
985 **  IMPLICIT INPUTS:
986 **
987 **      src_az_source_file_table
988 **
989 **  IMPLICIT OUTPUTS:
990 **
991 **      none
992 **
993 **  FUNCTION VALUE:
994 **
995 **      pointer to the file name string
996 **
997 **  SIDE EFFECTS:
998 **
999 **      none
1000 **
1001 **--
1002 **/
1003
1004 char
1005 *src_get_file_name(XmConst src_source_record_type *az_src_rec)
1006 {
1007     uil_fcb_type    *fcb;
1008
1009     /* Find the correct fcb */
1010
1011     fcb = src_az_source_file_table[ az_src_rec->b_file_number ];
1012     
1013     /* Return a pointer to file name */
1014
1015     return fcb->expanded_name;
1016 }
1017 \f
1018 /*
1019 **++
1020 **  FUNCTIONAL DESCRIPTION:
1021 **
1022 **      Given a source record, this function retrieves the text of the
1023 **      line corresponding to that source line.
1024 **
1025 **  FORMAL PARAMETERS:
1026 **
1027 **      az_src_rec      pointer to a source record structure
1028 **      c_buffer        pointer to buffer to hold the text
1029 **
1030 **  IMPLICIT INPUTS:
1031 **
1032 **      src_az_source_file_table
1033 **
1034 **  IMPLICIT OUTPUTS:
1035 **
1036 **      none
1037 **
1038 **  FUNCTION VALUE:
1039 **
1040 **      true            if there is a source line
1041 **      false           if there is no source line
1042 **
1043 **  SIDE EFFECTS:
1044 **
1045 **      buffer is set to the contents of source line
1046 **
1047 **--
1048 **/
1049
1050 static char XmConst no_source[] = "[ source not available ]";
1051
1052
1053
1054 boolean src_retrieve_source
1055
1056         (XmConst src_source_record_type *az_src_rec,
1057         char *c_buffer)
1058
1059 {
1060     uil_fcb_type    *fcb;
1061
1062     /* check if there is any source */
1063
1064     if (az_src_rec == diag_k_no_source)
1065     {
1066         _move( c_buffer, no_source, sizeof no_source );
1067         return FALSE;
1068     }
1069
1070     /* 
1071     **  check if we are dealing with the current source record
1072     **  in which case we don't need to reread the source 
1073     */
1074
1075     if ((az_src_rec->b_file_number == 
1076          src_az_current_source_buffer->b_file_number)
1077          &&
1078         (az_src_rec->w_line_number ==
1079          src_az_current_source_buffer->w_current_line_number)
1080        )
1081     {
1082         strcpy( c_buffer, 
1083                src_az_current_source_buffer->c_text);
1084         return TRUE;
1085     }
1086
1087     /*
1088     **  Will have to reread the data from the file.
1089     */
1090
1091     /* Find the correct fcb */
1092
1093     fcb = src_az_source_file_table[ az_src_rec->b_file_number ];
1094     
1095     /* get the line */
1096
1097     if (reget_line( fcb, c_buffer, (z_key *) &(az_src_rec->z_access_key) ))
1098         return TRUE;
1099
1100     _move( c_buffer, no_source, sizeof no_source );
1101     return FALSE;
1102
1103 }
1104
1105 \f
1106 /*
1107 **++
1108 **  FUNCTIONAL DESCRIPTION:
1109 **
1110 **      This function adds diagnostic information to the source representation.
1111 **      This permit diagnostics to be placed in the listing.
1112 **
1113 **  FORMAL PARAMETERS:
1114 **
1115 **      az_src_rec          source line diagnostic issued against
1116 **      l_src_pos           offset of diagnostic in the source line
1117 **      c_msg_text          text of diagnostic
1118 **      l_msg_number        message number for diagnostic
1119 **
1120 **  IMPLICIT INPUTS:
1121 **
1122 **      none
1123 **
1124 **  IMPLICIT OUTPUTS:
1125 **
1126 **      none
1127 **
1128 **  FUNCTION VALUE:
1129 **
1130 **      void
1131 **
1132 **  SIDE EFFECTS:
1133 **
1134 **      diagnostic stuff away in the source structure
1135 **
1136 **--
1137 **/
1138
1139 void
1140 src_append_diag_info( XmConst src_source_record_type *az_src_rec, 
1141                       XmConst int                     l_src_pos, 
1142                       XmConst char                   *c_msg_text, 
1143                       XmConst int                     l_msg_number )
1144 {
1145     src_message_item_type           *az_msg_item;
1146     int                             l_msg_length;
1147     src_message_item_type           *current;
1148     src_message_item_type           **prior;
1149
1150     /*
1151     **  create the message item and fill it in.
1152     */
1153
1154     l_msg_length = strlen( c_msg_text ) + 1;    /* includes null */
1155
1156     az_msg_item = (src_message_item_type *)
1157         _get_memory( sizeof( src_message_item_type ) + l_msg_length );
1158
1159     az_msg_item->l_message_number = l_msg_number;
1160     az_msg_item->b_source_pos = l_src_pos;
1161
1162     _move( (az_msg_item->c_text), c_msg_text, l_msg_length );
1163
1164     /*
1165     **  Link the message from its source line
1166     **      Messages are in ascending column order for a line with
1167     **        messages without column info at the end
1168     **      Messages without source are appended to a list of orphans
1169     */
1170
1171     if (az_src_rec == diag_k_no_source)
1172         prior = &src_az_orphan_messages;
1173     else
1174         prior = (src_message_item_type **)&(az_src_rec->az_message_list);
1175
1176     current = *prior;
1177
1178     for (;  
1179          current != NULL;
1180          prior = &(current->az_next_message),  
1181          current = *prior )
1182     {
1183         if (l_src_pos < (int)current->b_source_pos)
1184             break;
1185     }
1186
1187     az_msg_item->az_next_message = current;
1188     *prior = az_msg_item;
1189     
1190     return;
1191 }
1192 \f
1193 /*
1194 **++
1195 **  FUNCTIONAL DESCRIPTION:
1196 **
1197 **      This function adds machine code information to the source
1198 **      representation.  This permits machine code to be placed in the listing.
1199 **
1200 **  FORMAL PARAMETERS:
1201 **
1202 **      az_src_rec          source line machine code is associated with.
1203 **      l_offset            offset in the record for this code element
1204 **      l_code_len          length of the binary machine code buffer
1205 **      c_code              buffer containing the machine code in binary form
1206 **      c_text_arg          text of machine code; optional
1207 **
1208 **  IMPLICIT INPUTS:
1209 **
1210 **      none
1211 **
1212 **  IMPLICIT OUTPUTS:
1213 **
1214 **      none
1215 **
1216 **  FUNCTION VALUE:
1217 **
1218 **      void
1219 **
1220 **  SIDE EFFECTS:
1221 **
1222 **      Machine code stuffed away in the source structure
1223 **
1224 **--
1225 **/
1226
1227 void
1228 src_append_machine_code ( src_source_record_type *az_src_rec, 
1229                           XmConst int             l_offset, 
1230                           XmConst int             l_code_len, 
1231                           XmConst char           *c_code, 
1232                           XmConst char           *c_text_arg )
1233 {
1234     src_machine_code_type   *az_code_item;
1235     int                     l_text_len;
1236     XmConst char            *c_text;
1237
1238     if (c_text_arg == NULL) {
1239         c_text = "";
1240     } else {
1241         c_text = c_text_arg;
1242     }
1243
1244     /*
1245     **  create the machine code item and fill it in.
1246     */
1247
1248     l_text_len = strlen( c_text ) + 1;  /* includes null */
1249
1250     az_code_item = (src_machine_code_type *) _get_memory(
1251                 sizeof( src_machine_code_type ) + l_text_len + l_code_len );
1252
1253     az_code_item -> w_offset = l_offset;
1254     az_code_item -> w_code_len = l_code_len;
1255     _move( (az_code_item->data.c_data), c_code, l_code_len );
1256     _move( &(az_code_item->data.c_data [l_code_len]), c_text, l_text_len );
1257
1258     /*
1259     **  Link the machine code to its source line, at the head of
1260     **  the machine code list.
1261     */
1262
1263     az_code_item->az_next_machine_code = az_src_rec->az_machine_code_list;
1264     az_src_rec->az_machine_code_list = az_code_item;
1265     az_src_rec->w_machine_code_cnt++;
1266     
1267     return;
1268 }