FreeBASIC  0.91.0
symb-define.bas
Go to the documentation of this file.
1 '' symbol table module for defines and macros
2 ''
3 '' chng: sep/2004 written [v1ctor]
4 '' jan/2005 updated to use real linked-lists [v1ctor]
5 
6 
7 #include once "fb.bi"
8 #include once "fbint.bi"
9 #include once "parser.bi"
10 #include once "hash.bi"
11 #include once "list.bi"
12 #include once "lex.bi"
13 #include once "hlp.bi"
14 
15 #include once "datetime.bi"
16 #include once "string.bi"
17 
18 type DEFCALLBACK as function() as string
19 
20 type SYMBDEF
21  name as const zstring ptr
22  value as zstring ptr
23  flags as integer
25 end type
26 
27 declare function hDefFile_cb ( ) as string
28 declare function hDefFpmode_cb ( ) as string
29 declare function hDefFpu_cb ( ) as string
30 declare function hDefFunction_cb ( ) as string
31 declare function hDefLine_cb ( ) as string
32 declare function hDefDate_cb ( ) as string
33 declare function hDefDateISO_cb ( ) as string
34 declare function hDefTime_cb ( ) as string
35 declare function hDefMultithread_cb ( ) as string
36 declare function hDefOptByval_cb ( ) as string
37 declare function hDefOptDynamic_cb ( ) as string
38 declare function hDefOptEscape_cb ( ) as string
39 declare function hDefOptExplicit_cb ( ) as string
40 declare function hDefOptPrivate_cb ( ) as string
41 declare function hDefOptGosub_cb ( ) as string
42 declare function hDefOutExe_cb ( ) as string
43 declare function hDefOutLib_cb ( ) as string
44 declare function hDefOutDll_cb ( ) as string
45 declare function hDefOutObj_cb ( ) as string
46 declare function hDefDebug_cb ( ) as string
47 declare function hDefErr_cb ( ) as string
48 declare function hDefExErr_cb ( ) as string
49 declare function hDefExxErr_cb ( ) as string
50 declare function hDefLang_cb ( ) as string
51 declare function hDefBackend_cb ( ) as string
52 declare function hDefPath_cb ( ) as string
53 declare function hDefGcc_cb ( ) as string
54 
55 '' predefined #defines: name, value, flags, proc (for description flags, see FBS_DEFINE)
56 const SYMB_MAXDEFINES = 34
57 
58  dim shared defTb( 0 to SYMB_MAXDEFINES-1 ) as SYMBDEF => _
59  { _
60  (@"__FB_VERSION__" , @FB_VERSION , 0, NULL ), _
61  (@"__FB_BUILD_DATE__" , @FB_BUILD_DATE , 0, NULL ), _
62  (@"__FB_VER_MAJOR__" , @FB_VER_STR_MAJOR , 1, NULL ), _
63  (@"__FB_VER_MINOR__" , @FB_VER_STR_MINOR , 1, NULL ), _
64  (@"__FB_VER_PATCH__" , @FB_VER_STR_PATCH , 1, NULL ), _
65  (@"__FB_SIGNATURE__" , @FB_SIGN , 0, NULL ), _
66  (@"__FB_MT__" , NULL , 1, @hDefMultithread_cb ), _
67  (@"__FILE__" , NULL , 0, @hDefFile_cb ), _
68  (@"__FILE_NQ__" , NULL , 1, @hDefFile_cb ), _
69  (@"__FUNCTION__" , NULL , 0, @hDefFunction_cb ), _
70  (@"__FUNCTION_NQ__" , NULL , 1, @hDefFunction_cb ), _
71  (@"__LINE__" , NULL , 1, @hDefLine_cb ), _
72  (@"__DATE__" , NULL , 0, @hDefDate_cb ), _
73  (@"__DATE_ISO__" , NULL , 0, @hDefDateISO_cb ), _
74  (@"__TIME__" , NULL , 0, @hDefTime_cb ), _
75  (@"__PATH__" , NULL , 0, @hDefPath_cb ), _
76  (@"__FB_OPTION_BYVAL__" , NULL , 1, @hDefOptByval_cb ), _
77  (@"__FB_OPTION_DYNAMIC__" , NULL , 1, @hDefOptDynamic_cb ), _
78  (@"__FB_OPTION_ESCAPE__" , NULL , 1, @hDefOptEscape_cb ), _
79  (@"__FB_OPTION_EXPLICIT__" , NULL , 1, @hDefOptExplicit_cb ), _
80  (@"__FB_OPTION_PRIVATE__" , NULL , 1, @hDefOptPrivate_cb ), _
81  (@"__FB_OPTION_GOSUB__" , NULL , 1, @hDefOptGosub_cb ), _
82  (@"__FB_OUT_EXE__" , NULL , 1, @hDefOutExe_cb ), _
83  (@"__FB_OUT_LIB__" , NULL , 1, @hDefOutLib_cb ), _
84  (@"__FB_OUT_DLL__" , NULL , 1, @hDefOutDll_cb ), _
85  (@"__FB_OUT_OBJ__" , NULL , 1, @hDefOutObj_cb ), _
86  (@"__FB_DEBUG__" , NULL , 1, @hDefDebug_cb ), _
87  (@"__FB_ERR__" , NULL , 1, @hDefErr_cb ), _
88  (@"__FB_LANG__" , NULL , 0, @hDefLang_cb ), _
89  (@"__FB_BACKEND__" , NULL , 0, @hDefBackend_cb ), _
90  (@"__FB_FPU__" , NULL , 0, @hDefFpu_cb ), _
91  (@"__FB_FPMODE__" , NULL , 0, @hDefFpmode_cb ), _
92  (@"__FB_GCC__" , NULL , 1, @hDefGcc_cb ), _
93  (NULL) _
94  }
95 
96 '':::::
97 function hDefFile_cb( ) as string static
98 
99  function = env.inf.name
100 
101 end function
102 
103  '':::::
104 function hDefPath_cb( ) as string static
105 
106  function = fbGetInputFileParentDir( )
107 
108 end function
109 
110 '':::::
111 function hDefFunction_cb( ) as string
112 
113  if( symbGetIsMainProc( parser.currproc ) ) then
114  function = FB_MAINPROCNAME
115  elseif( symbGetIsModLevelProc( parser.currproc ) ) then
116  function = FB_MODLEVELNAME
117  else
118  function = *symbGetFullProcName( parser.currproc )
119  end if
120 
121 end function
122 
123 '':::::
124 function hDefLine_cb( ) as string static
125 
126  function = str( lexLineNum( ) )
127 
128 end function
129 
130 '':::::
131 function hDefDate_cb( ) as string static
132 
133  function = date
134 
135 end function
136 
137 '':::::
138 function hDefDateISO_cb( ) as string static
139 
140  function = format( now( ), "yyyy-mm-dd" )
141 
142 end function
143 
144 '':::::
145 function hDefTime_cb( ) as string static
146 
147  function = time
148 
149 end function
150 
151 '':::::
152 function hDefMultithread_cb( ) as string static
153 
154  function = str( env.clopt.multithreaded )
155 
156 end function
157 
158 '':::::
159 function hDefOptByval_cb ( ) as string
160 
161  function = str( env.opt.parammode = FB_PARAMMODE_BYVAL )
162 
163 end function
164 
165 '':::::
166 function hDefOptDynamic_cb ( ) as string
167 
168  function = str( env.opt.dynamic = TRUE )
169 
170 end function
171 
172 '':::::
173 function hDefOptEscape_cb ( ) as string
174 
175  function = str( env.opt.escapestr = TRUE )
176 
177 end function
178 
179 '':::::
180 function hDefOptExplicit_cb ( ) as string
181 
182  function = str( env.opt.explicit = TRUE )
183 
184 end function
185 
186 '':::::
187 function hDefOptPrivate_cb ( ) as string
188 
189  function = str( env.opt.procpublic = FALSE )
190 
191 end function
192 
193 '':::::
194 function hDefOptGosub_cb ( ) as string
195 
196  function = str( env.opt.gosub = TRUE )
197 
198 end function
199 
200 '':::::
201 function hDefOutExe_cb ( ) as string
202 
203  function = str( env.clopt.outtype = FB_OUTTYPE_EXECUTABLE )
204 
205 end function
206 
207 '':::::
208 function hDefOutLib_cb ( ) as string
209 
210  function = str( env.clopt.outtype = FB_OUTTYPE_STATICLIB )
211 
212 end function
213 
214 '':::::
215 function hDefOutDll_cb ( ) as string
216 
217  function = str( env.clopt.outtype = FB_OUTTYPE_DYNAMICLIB )
218 
219 end function
220 
221 '':::::
222 function hDefOutObj_cb ( ) as string
223 
224  function = str( env.clopt.outtype = FB_OUTTYPE_OBJECT )
225 
226 end function
227 
228 '':::::
229 function hDefDebug_cb ( ) as string
230 
231  function = str( env.clopt.debug )
232 
233 end function
234 
235 ''::::
236 function hDefErr_cb ( ) as string
237  dim as integer res = &h0000
238 
239  if( env.clopt.errorcheck ) then
240  res = &h0001
241  end if
242 
243  if( env.clopt.resumeerr ) then
244  res or= &h0002
245  end if
246 
247  if( env.clopt.extraerrchk ) then
248  res or= &h0004
249  end if
250 
251  function = str( res )
252 
253 end function
254 
255 '':::::
256 function hDefLang_cb ( ) as string
257 
258  function = fbGetLangName( env.clopt.lang )
259 
260 end function
261 
262 '':::::
263 function hDefBackend_cb ( ) as string
264  select case env.clopt.backend
265  case FB_BACKEND_GAS
266  function = "gas"
267  case FB_BACKEND_GCC
268  function = "gcc"
269  case FB_BACKEND_LLVM
270  function = "llvm"
271  end select
272 end function
273 
274 '':::::
275 function hDefFpu_cb ( ) as string
276 
277  select case fbGetOption( FB_COMPOPT_FPUTYPE )
278  case FB_FPUTYPE_FPU
279  return "x87"
280  case FB_FPUTYPE_SSE
281  return "sse"
282  case else
283  assert( 0 )
284  end select
285 
286 end function
287 
288 '':::::
289 function hDefFpmode_cb ( ) as string
290 
291  select case fbGetOption( FB_COMPOPT_FPMODE )
292  case FB_FPMODE_PRECISE
293  return "precise"
294  case FB_FPMODE_FAST
295  return "fast"
296  case else
297  assert( 0 )
298  end select
299 
300 end function
301 
302 function hDefGcc_cb( ) as string static
303  function = str( (env.clopt.backend = FB_BACKEND_GCC) )
304 end function
305 
306 '':::::
307 sub symbDefineInit _
308  ( _
309  byval ismain as integer _
310  )
311 
312  dim as string value
313  dim as const zstring ptr def = any
314 
315  listInit( @symb.def.paramlist, FB_INITDEFARGNODES, len( FB_DEFPARAM ), LIST_FLAGS_NOCLEAR )
316  listInit( @symb.def.toklist, FB_INITDEFTOKNODES, len( FB_DEFTOK ), LIST_FLAGS_NOCLEAR )
317 
318  '' add the pre-defines
319  for i as integer = 0 to SYMB_MAXDEFINES-1
320  if( defTb(i).name = NULL ) then
321  exit for
322  end if
323 
324  value = *defTb(i).value
325  if( defTb(i).value <> NULL ) then
326  if( bit( defTb(i).flags, 0 ) = 0 ) then
327  value = QUOTE + value + QUOTE
328  end if
329  end if
330 
331  symbAddDefine( defTb(i).name, value, len( value ), _
332  FALSE, defTb(i).proc, defTb(i).flags )
333  next
334 
335  '' Add __FB_<target>__ define
336  symbAddDefine( "__FB_" + ucase( *env.target.id ) + "__", NULL, 0 )
337 
338  '' add __FB_UNIX__ / __FB_PCOS__ defines, as necessary
339  if( env.target.options and FB_TARGETOPT_UNIX ) then
340  symbAddDefine( @"__FB_UNIX__", NULL, 0 )
341  else
342  symbAddDefine( @"__FB_PCOS__", NULL, 0 )
343  end if
344 
345  '' 64bit?
346  if( fbCpuTypeIs64bit( ) ) then
347  symbAddDefine( @"__FB_64BIT__", NULL, 0 )
348  end if
349 
350  '' add "main" define
351  if( ismain ) then
352  symbAddDefine( "__FB_MAIN__", NULL, 0 )
353  end if
354 
355  '' add SSE define
356  if( env.clopt.fputype >= FB_FPUTYPE_SSE ) then
357  symbAddDefine( "__FB_SSE__", NULL, 0 )
358  end if
359 
360  '' add vectorization define
361  value = str( env.clopt.vectorize )
362  symbAddDefine( "__FB_VECTORIZE__", value, len( value ) )
363 
364  '' macro params
365  symb.def.param = 0
366 
367  hashInit( @symb.def.paramhash, FB_MAXDEFINEARGS )
368 
369 end sub
370 
371 '':::::
373 
374  '' macro params
375  hashEnd( @symb.def.paramhash )
376 
377  symb.def.param = 0
378 
379  listEnd( @symb.def.paramlist )
380  listEnd( @symb.def.toklist )
381 
382 end sub
383 
384 '':::::
385 function symbAddDefine _
386  ( _
387  byval symbol as const zstring ptr, _
388  byval text as zstring ptr, _
389  byval lgt as integer, _
390  byval isargless as integer, _
391  byval proc as FBS_DEFINE_PROC, _
392  byval flags as FB_DEFINE_FLAGS _
393  ) as FBSYMBOL ptr
394 
395  dim as FBSYMBOL ptr sym = any
396 
397  function = NULL
398 
399  '' allocate new node (always on global hash, ns' won't work in lexer)
400  sym = symbNewSymbol( FB_SYMBOPT_DOHASH, _
401  NULL, _
402  NULL, @symbGetGlobalHashTb( ), _
403  FB_SYMBCLASS_DEFINE, _
404  symbol, NULL, _
405  FB_DATATYPE_CHAR, NULL )
406  if( sym = NULL ) then
407  exit function
408  end if
409 
410  sym->def.text = ZstrAllocate( lgt )
411  *sym->def.text = *text
412  sym->lgt = lgt
413  sym->def.params = 0
414  sym->def.paramhead = NULL
415  sym->def.isargless = isargless
416  sym->def.proc = proc
417  sym->def.flags = flags
418 
419  function = sym
420 
421 end function
422 
423 '':::::
424 function symbAddDefineW _
425  ( _
426  byval symbol as zstring ptr, _
427  byval text as wstring ptr, _
428  byval lgt as integer, _
429  byval isargless as integer, _
430  byval proc as FBS_DEFINE_PROC, _
431  byval flags as FB_DEFINE_FLAGS _
432  ) as FBSYMBOL ptr
433 
434  dim as FBSYMBOL ptr sym = any
435 
436  function = NULL
437 
438  '' allocate new node (always on global hash, ns' won't work in lexer)
439  sym = symbNewSymbol( FB_SYMBOPT_DOHASH, _
440  NULL, _
441  NULL, @symbGetGlobalHashTb( ), _
442  FB_SYMBCLASS_DEFINE, _
443  symbol, NULL, _
444  FB_DATATYPE_WCHAR, NULL )
445  if( sym = NULL ) then
446  exit function
447  end if
448 
449  sym->def.textw = WstrAllocate( lgt )
450  *sym->def.textw = *text
451  sym->lgt = lgt
452  sym->def.params = 0
453  sym->def.paramhead = NULL
454  sym->def.isargless = isargless
455  sym->def.proc = proc
456  sym->def.flags = flags
457 
458  function = sym
459 
460 end function
461 
462 '':::::
463 function symbAddDefineMacro _
464  ( _
465  byval symbol as const zstring ptr, _
466  byval tokhead as FB_DEFTOK ptr, _
467  byval params as integer, _
468  byval paramhead as FB_DEFPARAM ptr, _
469  byval flags as FB_DEFINE_FLAGS _
470  ) as FBSYMBOL ptr
471 
472  dim as FBSYMBOL ptr sym = any
473 
474  function = NULL
475 
476  '' allocate new node (always on global hash, ns' won't work in lexer)
477  sym = symbNewSymbol( FB_SYMBOPT_DOHASH, _
478  NULL, _
479  NULL, @symbGetGlobalHashTb( ), _
480  FB_SYMBCLASS_DEFINE, _
481  symbol, NULL, _
482  FB_DATATYPE_INVALID, NULL )
483  if( sym = NULL ) then
484  exit function
485  end if
486 
487  sym->def.tokhead = tokhead
488  sym->def.params = params
489  sym->def.paramhead = paramhead
490  sym->def.isargless = FALSE
491  sym->def.proc = NULL
492  sym->def.flags = flags
493 
494  function = sym
495 
496 end function
497 
498 '':::::
500  dim as integer i
501 
502  for i = 0 to symb.def.param-1
503  hashDel( @symb.def.paramhash, symb.def.hash(i).item, symb.def.hash(i).index )
504  next
505 
506  symb.def.param = 0
507 
508 end sub
509 
510 '':::::
511 function symbAddDefineParam _
512  ( _
513  byval lastparam as FB_DEFPARAM ptr, _
514  byval id as const zstring ptr _
515  ) as FB_DEFPARAM ptr static
516 
517  dim as FB_DEFPARAM ptr param
518  dim as uinteger index
519 
520  function = NULL
521 
522  param = listNewNode( @symb.def.paramlist )
523 
524  if( lastparam <> NULL ) then
525  lastparam->next = param
526 
527  '' new param list..
528  else
529  '' reset the old list, if any
530  if( symb.def.param > 0 ) then
531  hResetDefHash( )
532  end if
533  end if
534 
535  ''
536  param->name = ZstrAllocate( len( *id ) )
537  hUcase( *id, *param->name )
538 
539  '' add to hash, for fast lookup
540  index = hashHash( param->name )
541 
542  '' dup definition? !!!FIXME!!! don't do this check for system headers !!!FIXME!!!
543  if( hashLookupEx( @symb.def.paramhash, param->name, index ) <> NULL ) then
544  ZstrFree( param->name )
545  listDelNode( @symb.def.paramlist, param )
546  return NULL
547  end if
548 
549  symb.def.hash(symb.def.param).item = hashAdd( @symb.def.paramhash, _
550  param->name, _
551  param, _
552  index )
553 
554  symb.def.hash(symb.def.param).index = index
555 
556  ''
557  param->num = symb.def.param
558  param->next = NULL
559 
560  symb.def.param += 1
561 
562  function = param
563 
564 end function
565 
566 '':::::
567 function symbAddDefineTok _
568  ( _
569  byval lasttok as FB_DEFTOK ptr, _
570  byval dtype as FB_DEFTOK_TYPE _
571  ) as FB_DEFTOK ptr static
572 
573  dim t as FB_DEFTOK ptr
574 
575  function = NULL
576 
577  t = listNewNode( @symb.def.toklist )
578 
579  if( lasttok <> NULL ) then
580  lasttok->next = t
581  end if
582 
583  t->prev = lasttok
584  t->next = NULL
585 
586  ''
587  t->type = dtype
588  select case as const dtype
589  case FB_DEFTOK_TYPE_TEX
590  t->text = NULL
591  case FB_DEFTOK_TYPE_TEXW
592  t->textw = NULL
593  end select
594 
595  function = t
596 
597 end function
598 
599 '':::::
600 function symbDelDefineTok _
601  ( _
602  byval tok as FB_DEFTOK ptr _
603  ) as FB_DEFTOK ptr static
604 
605  '' warning: this should only be used to remove the tail tokens
606  if( tok->prev <> NULL ) then
607  tok->prev->next = NULL
608  function = tok->prev
609  else
610  function = NULL
611  end if
612 
613  select case tok->type
614  case FB_DEFTOK_TYPE_TEX
615  ZstrFree( tok->text )
616  case FB_DEFTOK_TYPE_TEXW
617  WstrFree( tok->textw )
618  end select
619 
620  listDelNode( @symb.def.toklist, tok )
621 
622 end function
623 
624 '':::::
625 sub hDelDefineParams( byval s as FBSYMBOL ptr )
626  dim as FB_DEFPARAM ptr param, nxt
627 
628  param = s->def.paramhead
629  do while( param <> NULL )
630  nxt = param->next
631  ZstrFree( param->name )
632 
633  listDelNode( @symb.def.paramlist, param )
634 
635  param = nxt
636  loop
637 
638 end sub
639 
640 '':::::
641 sub hDelDefineTokens( byval s as FBSYMBOL ptr )
642  dim as FB_DEFTOK ptr tok, nxt
643 
644  tok = s->def.tokhead
645  do while( tok <> NULL )
646  nxt = tok->next
647 
648  symbDelDefineTok( tok )
649 
650  tok = nxt
651  loop
652 
653 end sub
654 
655 '':::::
656 function symbDelDefine _
657  ( _
658  byval s as FBSYMBOL ptr _
659  ) as integer
660 
661  function = FALSE
662 
663  if( s = NULL ) then
664  exit function
665  end if
666 
667  ''
668  if( symbGetDefineParams( s ) = 0 ) then
669  if( symbGetType( s ) <> FB_DATATYPE_WCHAR ) then
670  ZstrFree( s->def.text )
671  else
672  WstrFree( s->def.textw )
673  end if
674  else
675  hDelDefineTokens( s )
676  end if
677 
678  ''
679  hDelDefineParams( s )
680 
681  '' del the define node
682  symbFreeSymbol( s )
683 
684  ''
685  function = TRUE
686 
687 end function
688 
689 
690