1 /* Pawn compiler - maintenance of various lists
3 * o Name list (aliases)
5 * o Macro definitions (text substitutions)
6 * o Documentation tags and automatic listings
9 * Copyright (c) ITB CompuPhase, 2001-2006
11 * This software is provided "as-is", without any express or implied warranty.
12 * In no event will the authors be held liable for any damages arising from
13 * the use of this software.
15 * Permission is granted to anyone to use this software for any purpose,
16 * including commercial applications, and to alter it and redistribute it
17 * freely, subject to the following restrictions:
19 * 1. The origin of this software must not be misrepresented; you must not
20 * claim that you wrote the original software. If you use this software in
21 * a product, an acknowledgment in the product documentation would be
22 * appreciated but is not required.
23 * 2. Altered source versions must be plainly marked as such, and must not be
24 * misrepresented as being the original software.
25 * 3. This notice may not be removed or altered from any source distribution.
37 #include <alloc/fortify.h>
40 /* a "private" implementation of strdup(), so that porting
41 * to other memory allocators becomes easier.
44 SC_FUNC char* duplicatestring(const char* sourcestring)
46 char* result=(char*)malloc(strlen(sourcestring)+1);
47 strcpy(result,sourcestring);
52 static stringpair *insert_stringpair(stringpair *root,char *first,char *second,int matchlength)
54 stringpair *cur,*pred;
59 /* create a new node, and check whether all is okay */
60 if ((cur=(stringpair*)malloc(sizeof(stringpair)))==NULL)
62 cur->first=duplicatestring(first);
63 cur->second=duplicatestring(second);
64 cur->matchlength=matchlength;
65 cur->documentation=NULL;
66 if (cur->first==NULL || cur->second==NULL) {
69 if (cur->second!=NULL)
74 /* link the node to the tree, find the position */
75 for (pred=root; pred->next!=NULL && strcmp(pred->next->first,first)<0; pred=pred->next)
82 static void delete_stringpairtable(stringpair *root)
84 stringpair *cur, *next;
90 assert(cur->first!=NULL);
91 assert(cur->second!=NULL);
97 memset(root,0,sizeof(stringpair));
100 static stringpair *find_stringpair(stringpair *cur,char *first,int matchlength)
104 assert(matchlength>0); /* the function cannot handle zero-length comparison */
106 while (cur!=NULL && result<=0) {
107 result=(int)*cur->first - (int)*first;
108 if (result==0 && matchlength==cur->matchlength) {
109 result=strncmp(cur->first,first,matchlength);
118 static int delete_stringpair(stringpair *root,stringpair *item)
124 while (cur->next!=NULL) {
125 if (cur->next==item) {
126 cur->next=item->next; /* unlink from list */
127 assert(item->first!=NULL);
128 assert(item->second!=NULL);
139 /* ----- string list functions ----------------------------------- */
140 static stringlist *insert_string(stringlist *root,char *string)
144 assert(string!=NULL);
145 if ((cur=(stringlist*)malloc(sizeof(stringlist)))==NULL)
146 error(103); /* insufficient memory (fatal error) */
147 if ((cur->line=duplicatestring(string))==NULL)
148 error(103); /* insufficient memory (fatal error) */
149 /* insert as "last" */
151 while (root->next!=NULL)
153 cur->next=root->next;
158 static char *get_string(stringlist *root,int index)
164 while (cur!=NULL && index-->0)
167 assert(cur->line!=NULL);
173 static int delete_string(stringlist *root,int index)
175 stringlist *cur,*item;
178 for (cur=root; cur->next!=NULL && index>0; cur=cur->next,index--)
180 if (cur->next!=NULL) {
182 cur->next=item->next; /* unlink from list */
183 assert(item->line!=NULL);
191 SC_FUNC void delete_stringtable(stringlist *root)
193 stringlist *cur,*next;
199 assert(cur->line!=NULL);
204 memset(root,0,sizeof(stringlist));
208 /* ----- alias table --------------------------------------------- */
209 static stringpair alias_tab = {NULL, NULL, NULL}; /* alias table */
211 SC_FUNC stringpair *insert_alias(char *name,char *alias)
216 assert(strlen(name)<=sNAMEMAX);
218 assert(strlen(alias)<=sNAMEMAX);
219 if ((cur=insert_stringpair(&alias_tab,name,alias,strlen(name)))==NULL)
220 error(103); /* insufficient memory (fatal error) */
224 SC_FUNC int lookup_alias(char *target,char *name)
226 stringpair *cur=find_stringpair(alias_tab.next,name,strlen(name));
228 assert(strlen(cur->second)<=sNAMEMAX);
229 strcpy(target,cur->second);
234 SC_FUNC void delete_aliastable(void)
236 delete_stringpairtable(&alias_tab);
239 /* ----- include paths list -------------------------------------- */
240 static stringlist includepaths = {NULL, NULL}; /* directory list for include files */
242 SC_FUNC stringlist *insert_path(char *path)
244 return insert_string(&includepaths,path);
247 SC_FUNC char *get_path(int index)
249 return get_string(&includepaths,index);
252 SC_FUNC void delete_pathtable(void)
254 delete_stringtable(&includepaths);
255 assert(includepaths.next==NULL);
259 /* ----- text substitution patterns ------------------------------ */
260 #if !defined NO_DEFINE
262 static stringpair substpair = { NULL, NULL, NULL}; /* list of substitution pairs */
264 static stringpair *substindex['z'-PUBLIC_CHAR+1]; /* quick index to first character */
265 static void adjustindex(char c)
268 assert(c>='A' && c<='Z' || c>='a' && c<='z' || c=='_' || c==PUBLIC_CHAR);
269 assert(PUBLIC_CHAR<'A' && 'A'<'_' && '_'<'z');
271 for (cur=substpair.next; cur!=NULL && cur->first[0]!=c; cur=cur->next)
273 substindex[(int)c-PUBLIC_CHAR]=cur;
276 SC_FUNC stringpair *insert_subst(char *pattern,char *substitution,int prefixlen)
280 assert(pattern!=NULL);
281 assert(substitution!=NULL);
282 if ((cur=insert_stringpair(&substpair,pattern,substitution,prefixlen))==NULL)
283 error(103); /* insufficient memory (fatal error) */
284 adjustindex(*pattern);
286 if (pc_deprecate!=NULL) {
288 cur->flags|=flgDEPRECATED;
289 if (sc_status==statWRITE) {
290 if (cur->documentation!=NULL) {
291 free(cur->documentation);
292 cur->documentation=NULL;
294 cur->documentation=pc_deprecate;
301 cur->documentation = NULL;
307 SC_FUNC stringpair *find_subst(char *name,int length)
312 assert(*name>='A' && *name<='Z' || *name>='a' && *name<='z' || *name=='_' || *name==PUBLIC_CHAR);
313 item=substindex[(int)*name-PUBLIC_CHAR];
315 item=find_stringpair(item,name,length);
317 if (item && (item->flags & flgDEPRECATED) != 0)
319 static char macro[128];
320 char *rem, *msg = (item->documentation != NULL) ? item->documentation : "";
321 strlcpy(macro, item->first, sizeof(macro));
323 /* If macro contains an opening parentheses and a percent sign, then assume that
324 * it takes arguments and remove them from the warning message.
326 if ((rem = strchr(macro, '(')) != NULL && strchr(macro, '%') > rem)
331 error(234, macro, msg); /* deprecated (macro/constant) */
336 SC_FUNC int delete_subst(char *name,int length)
341 assert(*name>='A' && *name<='Z' || *name>='a' && *name<='z' || *name=='_' || *name==PUBLIC_CHAR);
342 item=substindex[(int)*name-PUBLIC_CHAR];
344 item=find_stringpair(item,name,length);
347 if (item->documentation)
349 free(item->documentation);
350 item->documentation=NULL;
352 delete_stringpair(&substpair,item);
357 SC_FUNC void delete_substtable(void)
360 delete_stringpairtable(&substpair);
361 for (i=0; i<sizeof substindex/sizeof substindex[0]; i++)
365 #endif /* !defined NO_SUBST */
368 /* ----- input file list ----------------------------------------- */
369 static stringlist sourcefiles = {NULL, NULL};
371 SC_FUNC stringlist *insert_sourcefile(char *string)
373 return insert_string(&sourcefiles,string);
376 SC_FUNC char *get_sourcefile(int index)
378 return get_string(&sourcefiles,index);
381 SC_FUNC void delete_sourcefiletable(void)
383 delete_stringtable(&sourcefiles);
384 assert(sourcefiles.next==NULL);
388 /* ----- documentation tags -------------------------------------- */
389 #if !defined SC_LIGHT
390 static stringlist docstrings = {NULL, NULL};
392 SC_FUNC stringlist *insert_docstring(char *string)
394 return insert_string(&docstrings,string);
397 SC_FUNC char *get_docstring(int index)
399 return get_string(&docstrings,index);
402 SC_FUNC void delete_docstring(int index)
404 delete_string(&docstrings,index);
407 SC_FUNC void delete_docstringtable(void)
409 delete_stringtable(&docstrings);
410 assert(docstrings.next==NULL);
412 #endif /* !defined SC_LIGHT */
415 /* ----- autolisting --------------------------------------------- */
416 static stringlist autolist = {NULL, NULL};
418 SC_FUNC stringlist *insert_autolist(char *string)
420 return insert_string(&autolist,string);
423 SC_FUNC char *get_autolist(int index)
425 return get_string(&autolist,index);
428 SC_FUNC void delete_autolisttable(void)
430 delete_stringtable(&autolist);
431 assert(autolist.next==NULL);
435 /* ----- debug information --------------------------------------- */
437 /* These macros are adapted from LibDGG libdgg-int64.h, see
438 * http://www.dennougedougakkai-ndd.org/pub/libdgg/
440 #if defined(__STDC_VERSION__) && __STDC_VERSION__>=199901L
441 #define __STDC_FORMAT_MACROS
442 #define __STDC_CONSTANT_MACROS
443 #include <inttypes.h> /* automatically includes stdint.h */
444 #elif (defined _MSC_VER || defined __BORLANDC__) && (defined _I64_MAX || defined HAVE_I64)
445 #define PRId64 "I64d"
446 #define PRIx64 "I64x"
451 #if PAWN_CELL_SIZE==64
454 #elif PAWN_CELL_SIZE==32
462 static stringlist dbgstrings = {NULL, NULL};
464 SC_FUNC stringlist *insert_dbgfile(const char *filename)
467 if (sc_status==statWRITE && (sc_debug & sSYMBOLIC)!=0) {
468 char string[_MAX_PATH+40];
469 assert(filename!=NULL);
470 assert(strlen(filename)+40<sizeof string);
471 sprintf(string,"F:%" PRIxC " %s",code_idx,filename);
472 return insert_string(&dbgstrings,string);
477 SC_FUNC stringlist *insert_dbgline(int linenr)
479 if (sc_status==statWRITE && (sc_debug & sSYMBOLIC)!=0) {
482 linenr--; /* line numbers are zero-based in the debug information */
483 sprintf(string,"L:%" PRIxC " %x",code_idx,linenr);
484 return insert_string(&dbgstrings,string);
489 SC_FUNC stringlist *insert_dbgsymbol(symbol *sym)
491 if (sc_status==statWRITE && (sc_debug & sSYMBOLIC)!=0) {
492 char string[2*sNAMEMAX+128];
493 char symname[2*sNAMEMAX+16];
495 funcdisplayname(symname,sym->name);
496 /* address tag:name codestart codeend ident vclass [tag:dim ...] */
497 if (sym->ident==iFUNCTN) {
498 sprintf(string,"S:%" PRIxC " %x:%s %" PRIxC " %" PRIxC " %x %x",
499 sym->addr,sym->tag,symname,sym->addr,sym->codeaddr,sym->ident,sym->vclass);
501 sprintf(string,"S:%" PRIxC " %x:%s %" PRIxC " %" PRIxC " %x %x",
502 sym->addr,sym->tag,symname,sym->codeaddr,code_idx,sym->ident,sym->vclass);
504 if (sym->ident==iARRAY || sym->ident==iREFARRAY) {
506 int count=sym->dim.array.level;
509 strcat(string," [ ");
510 for (sub=sym; sub!=NULL; sub=finddepend(sub)) {
511 assert(sub->dim.array.level==count--);
512 sprintf(string+strlen(string),"%x:%x ",sub->x.tags.index,sub->dim.array.length);
517 return insert_string(&dbgstrings,string);
522 SC_FUNC char *get_dbgstring(int index)
524 return get_string(&dbgstrings,index);
527 SC_FUNC void delete_dbgstringtable(void)
529 delete_stringtable(&dbgstrings);
530 assert(dbgstrings.next==NULL);