4 * Copyright (C) 1989-2009 Alan R. Baldwin
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
25 * Extensions to produce NoICE debug files
27 * 31-Oct-1997 by John Hartman
28 * 30-Jan-98 JLH add page to DefineNoICE for 8051
29 * 2-Feb-98 JLH Allow optional .nest on local vars - C scoping rules...
30 * 27-May-01 ARB Updated for ASxxxx V4
40 * The module lknoice.c contains the functions
41 * required to create a NoICE debug file.
43 * lknoice.c contains the following functions:
50 * VOID DefineFunction()
51 * VOID DefineStaticFunction()
52 * VOID DefineEndFunction()
56 * lknoice.c contains these local variables:
57 * struct noicebn *noicebnp pointer to linked structure of
58 * ';!FILE' specifications
59 * char currentFile[] file being processed
60 * char currentFunction[] function being processed
64 struct noicefn
*n_np
; /* noicefn link */
65 char * n_id
; /* file name */
68 static struct noicefn
*noicefnp
= NULL
;
70 static char currentFile
[NCPS
];
71 static char currentFunction
[NCPS
];
74 /*)Function VOID NoICEfopen()
76 * The function NoICEfopen() opens the NoICE output file
77 * and sets the map flag, mflag, to create a map file.
78 * NoICE processing is performed during map generation.
84 * int jflag NoICE Debug flag
85 * FILE * jfp NoICE Debug File handle
86 * struct lfile *linkp Pointer to the Linker output file name
87 * int mflag Map output flag
90 * FILE * afile() lkmain.c
91 * VOID lkexit() lkmain.c
94 * The NoICE output file is opened.
95 * Failure to open the file will
96 * terminate the linker.
102 jfp
= afile(linkp
->f_idp
, "noi", 1);
111 /*)Function VOID NoICEmagic()
113 * The function NoICEmagic() passes any "magic Comments"
114 * to the NoICE output file. Magic comments are those
115 * beginning with ";!". Also a linked list of file names
116 * specified in ";!FILE" magic comments is created. These
117 * file names are used to verify that symbols in the
118 * ASxxxx .rel files of the form str1.str2 are NoICE symbols.
121 * char id[] id string
122 * struct noicefn * np pointer to new structure
123 * char * p1 temporary string pointer
124 * char * p2 temporary string pointer
125 * struct noicefn * tnp temporary pointer to noicefn structure
128 * char * ip position into the current
130 * FILE * jfp NoICE Debug File handle
133 * VOID getid() lklex.c
134 * VOID * new() lksym.c
135 * int fprintf() c_library
136 * char * strrchr() c_library
137 * char * strsto() lksym.c
138 * int symeq() lksym.c
141 * The NoICE "magic comments" are passed
142 * to the output file. A list of assembler
143 * file names is created.
146 VOID
NoICEmagic(void)
150 struct noicefn
*np
, *tnp
;
153 * Pass any "magic comments" to NoICE output
155 if ((ip
[0] == ';') && (ip
[1] == '!')) {
157 fprintf(jfp
, "%s\n", &ip
[2]);
161 if (symeq(id
, ";!FILE", 1)) {
164 * The name starts after the last
168 * and ends at the last
172 if ((p2
= strrchr(p1
, '\\')) != NULL
) p1
= ++p2
;
173 if ((p2
= strrchr(p1
, '/')) != NULL
) p1
= ++p2
;
174 if ((p2
= strrchr(p1
, ':')) != NULL
) p1
= ++p2
;
175 if ((p2
= strrchr(p1
, FSEPX
)) != NULL
) *p2
= 0;
177 np
= (struct noicefn
*) new (sizeof(struct noicefn
));
178 if (noicefnp
== NULL
) {
186 np
->n_id
= strsto(p1
);
193 /*)Function VOID DefineNoICE()
195 * char * name pointer to the symbol string
196 * a_uint value value of symbol
197 * struct bank * yp pointer to associated bank
199 * The function DefineNoICE() processes the symbols into
200 * NoICE commands for inclusion in the NoICE output file.
202 * The function is called from lstarea in lklist.c
206 * int j parsed argument count
207 * int k parsed argument count
208 * int level function level
209 * char token1[] parsed string
210 * char token2[] parsed string
211 * char token2[] parsed string
212 * char sep1 parsed character
213 * char sep2 parsed character
214 * struct noicefn * tnp temporary pointer to noicefn structure
217 * FILE * jfp NoICE Debug File handle
220 * VOID DefineFile() lknoice.c
221 * VOID DefineFunction() lknoice.c
222 * VOID DefineStaticFunction() lknoice.c
223 * VOID DefineEndFunction() lknoice.c
224 * VOID DefineScoped() lknoice.c
225 * VOID DefineLine() lknoice.c
226 * VOID DefineGlobal() lknoice.c
227 * VOID PagedAddress() lknoice.c
228 * int sprintf() c_library
229 * int sscanf() c_library
230 * int symeq() lksym.c
233 * NoICE debug commands are placed
234 * into the output file.
237 void DefineNoICE( char *name
, a_uint value
, struct bank
*yp
)
239 char token1
[NCPS
]; /* parse for file.function.symbol */
246 /* no output if file is not open */
247 if (jfp
== NULL
) return;
249 j
= sscanf( name
, "%[^.]%c%[^.]%c%s", token1
, &sep1
, token2
, &sep2
, token3
);
251 /* verify that first token is a file name */
255 if (symeq(token1
, np
->n_id
, 1)) {
266 /* file.function.symbol, or file.function..SPECIAL */
268 DefineFile( token1
, 0, NULL
);
269 if (token3
[0] == '.')
271 if (symeq( token3
, ".FN", 1 ) != 0)
273 /* Global function */
274 DefineFunction( token2
, value
, yp
);
276 else if (symeq( token3
, ".SFN", 1 ) != 0)
278 /* Static (file-scope) function */
279 DefineStaticFunction( token2
, value
, yp
);
281 else if (symeq( token3
, ".EFN", 1 ) != 0)
283 /* End of function */
284 DefineEndFunction( value
, yp
);
289 /* Function-scope var. */
290 DefineFunction( token2
, 0, NULL
);
292 /* Look for optional level integer */
293 j
= sscanf( token3
, "%[^.]%c%u", token1
, &sep1
, &level
);
294 if ((j
== 3) && (level
!= 0))
296 sprintf( &token1
[ strlen(token1
) ], "_%u", level
);
298 DefineScoped( token1
, value
, yp
);
302 /* either file.symbol or file.line# */
304 DefineFile( token1
, 0, NULL
);
305 if ((token2
[0] >= '0') && (token2
[0] <= '9'))
308 DefineLine( token2
, value
, yp
);
312 /* File-scope symbol. (Kill any function) */
313 DefineEndFunction( 0, NULL
);
314 DefineScoped( token2
, value
, yp
);
318 /* NoICE file.func. is illegal */
321 /* NoICE symbol. is illegal */
327 /* NoICE .symbol is illegal */
330 DefineGlobal( name
, value
, yp
);
336 /*)Function VOID DefineGlobal()
338 * char * name pointer to the symbol string
339 * a_uint value value of symbol
340 * struct bank * yp pointer to associated bank
342 * The function DefineGlobal() places a DEF statement
343 * in the .noi debug file for the global symbol.
349 * FILE * jfp NoICE Debug File handle
352 * int fprintf() c_library
353 * VOID PagedAddress() lknoice.c
356 * A global symbol definition is
357 * placed in the .noi debug file.
360 void DefineGlobal( char *name
, a_uint value
, struct bank
*yp
)
362 fprintf( jfp
, "DEF %s ", name
);
363 PagedAddress( value
, yp
);
367 /*)Function VOID DefineScoped()
369 * char * name pointer to the symbol string
370 * a_uint value value of symbol
371 * struct bank * yp pointer to associated bank
373 * The function DefineScoped() places a DEFS statement
374 * in the .noi debug file for the scoped symbol.
380 * FILE * jfp NoICE Debug File handle
383 * int fprintf() c_library
384 * VOID PagedAddress() lknoice.c
387 * A scoped symbol definition is
388 * placed in the .noi debug file.
391 void DefineScoped( char *name
, a_uint value
, struct bank
*yp
)
393 fprintf( jfp
, "DEFS %s ", name
);
394 PagedAddress( value
, yp
);
398 /*)Function VOID DefineFile()
400 * char * name pointer to the symbol string
401 * a_uint value value of symbol
402 * struct bank * yp pointer to associated bank
404 * The function DefineFile() places a FILE statement
405 * in the .noi debug file for the processed file.
411 * FILE * jfp NoICE Debug File handle
414 * int fprintf() c_library
415 * VOID PagedAddress() lknoice.c
416 * char * strcpy() c_library
417 * int symeq() lksym.c
420 * A file name definition is
421 * placed in the .noi debug file.
424 void DefineFile( char *name
, a_uint value
, struct bank
*yp
)
426 if (symeq( name
, currentFile
, 1 ) == 0)
428 strcpy( currentFile
, name
);
431 fprintf( jfp
, "FILE %s ", name
);
432 PagedAddress( value
, yp
);
436 fprintf( jfp
, "FILE %s\n", name
);
442 /*)Function VOID DefineFunction()
444 * char * name pointer to the symbol string
445 * a_uint value value of symbol
446 * struct bank * yp pointer to associated bank
448 * The function DefineFunction() places a FUNC statement
449 * in the .noi debug file for the processed symbol. If
450 * a vaulue is present then a preceeding DEF statement is
451 * also placed in the .noi debug file.
457 * FILE * jfp NoICE Debug File handle
460 * int fprintf() c_library
461 * VOID PagedAddress() lknoice.c
462 * char * strcpy() c_library
463 * int symeq() lksym.c
466 * A function definition is
467 * placed in the .noi debug file.
470 void DefineFunction( char *name
, a_uint value
, struct bank
*yp
)
472 if (symeq( name
, currentFunction
, 1 ) == 0)
474 strcpy( currentFunction
, name
);
477 fprintf( jfp
, "DEF %s ", name
);
478 PagedAddress( value
, yp
);
479 fprintf( jfp
, "FUNC %s ", name
);
480 PagedAddress( value
, yp
);
484 fprintf( jfp
, "FUNC %s\n", name
);
490 /*)Function VOID DefineStaticFunction()
492 * char * name pointer to the symbol string
493 * a_uint value value of symbol
494 * struct bank * yp pointer to associated bank
496 * The function DefineStaticFunction() places a SFUNC statement
497 * in the .noi debug file for the processed file. If
498 * a value is present then a preceeding DEFS statement is
499 * also placed in the .noi debug file.
505 * FILE * jfp NoICE Debug File handle
508 * int fprintf() c_library
509 * VOID PagedAddress() lknoice.c
510 * char * strcpy() c_library
511 * int symeq() lksym.c
514 * A static function definition is
515 * placed in the .noi debug file.
518 void DefineStaticFunction( char *name
, a_uint value
, struct bank
*yp
)
520 if (symeq( name
, currentFunction
, 1 ) == 0)
522 strcpy( currentFunction
, name
);
525 fprintf( jfp
, "DEFS %s ", name
);
526 PagedAddress( value
, yp
);
527 fprintf( jfp
, "SFUNC %s ", name
);
528 PagedAddress( value
, yp
);
532 fprintf( jfp
, "SFUNC %s\n", name
);
538 /*)Function VOID DefineEndFunction()
540 * char * name pointer to the symbol string
541 * a_uint value value of symbol
542 * struct bank * yp pointer to associated bank
544 * The function DefineEndFunction() places an ENDF statement
545 * in the .noi debug file for the processed file.
551 * FILE * jfp NoICE Debug File handle
554 * int fprintf() c_library
555 * VOID PagedAddress() lknoice.c
556 * char * strcpy() c_library
557 * int symeq() lksym.c
560 * An end function definition is
561 * placed in the .noi debug file.
564 void DefineEndFunction( a_uint value
, struct bank
*yp
)
566 if (currentFunction
[0] != 0)
570 fprintf( jfp
, "ENDF " );
571 PagedAddress( value
, yp
);
575 fprintf( jfp
, "ENDF\n" );
578 currentFunction
[0] = 0;
583 /*)Function VOID DefineLine()
585 * char * name pointer to the symbol string
586 * a_uint value value of symbol
587 * struct bank * yp pointer to associated bank
589 * The function DefineLine() places a LINE statement
590 * in the .noi debug file for the processed file.
593 * int indigit converted digit
594 * int lineNumber converted line number
597 * FILE * jfp NoICE Debug File handle
600 * int fprintf() c_library
601 * VOID PagedAddress() lknoice.c
602 * int digit() lkeval.c
605 * A Line definition is
606 * placed in the .noi debug file.
609 void DefineLine( char *lineString
, a_uint value
, struct bank
*yp
)
611 int indigit
, lineNumber
;
614 while( (indigit
=digit( *lineString
++, 10 )) >= 0)
616 lineNumber
= 10*lineNumber
+ indigit
;
618 fprintf( jfp
, "LINE %u ", lineNumber
);
619 PagedAddress( value
, yp
);
623 /*)Function VOID PagedAddress()
625 * a_uint value value of symbol
626 * struct bank * yp pointer to associated bank
628 * The function PagedAddress() places the value
629 * in the .noi debug file for the processed value.
630 * If the current bank is "mapped" then the page
631 * number preceeds the value as xx:.
637 * FILE * jfp NoICE Debug File handle
640 * int fprintf() c_library
643 * A value is appended to the current
644 * line placed in the .noi debug file.
647 void PagedAddress( a_uint value
, struct bank
*yp
)
649 if (yp
->b_flag
& B_MAP
) {
650 fprintf( jfp
, "%X:0x%X\n", yp
->b_map
, value
);
652 fprintf( jfp
, "0x%X\n", value
);