FreeBASIC  0.91.0
pp-pragma.bas
Go to the documentation of this file.
1 '' pre-processor #pragma parsing
2 ''
3 '' chng: oct/2005 written [v1ctor]
4 '' jan/2006 updated [jeffm] added 'once'
5 
6 #include once "fb.bi"
7 #include once "fbint.bi"
8 #include once "lex.bi"
9 #include once "parser.bi"
10 #include once "pp.bi"
11 
17 
19 end enum
20 
22  tk as zstring * 16
23  opt as integer
24  flags as integer
25 end type
26 
30 
32 end enum
33 
35  tos as integer
36  stk(0 to FB_MAXPRAGMARECLEVEL-1) as longint
37 end type
38 
39 '' globals
40  dim shared pragmaStk(0 to FB_COMPOPTIONS-1) as LEXPP_PRAGMASTK
41 
42  '' same order as LEXPP_PRAGMAOPT_ENUM
43  dim shared pragmaOpt(0 to LEXPP_PRAGMAS-1) as LEXPP_PRAGMAOPT => _
44  { _
45  ("msbitfields", FB_COMPOPT_MSBITFIELDS, LEXPP_PRAGMAFLAG_DEFAULT ), _
46  ("once" , 0 , LEXPP_PRAGMAFLAG_HAS_CALLBACK ) _
47  }
48 
50  '' reset stacks
51  for i as integer = 0 to FB_COMPOPTIONS-1
52  pragmaStk(i).tos = 0
53  next
54 end sub
55 
57 end sub
58 
59 sub pragmaPush( byval opt as integer, byval value as longint )
60  with pragmaStk(opt)
61  if( .tos >= FB_MAXPRAGMARECLEVEL ) then
62  errReport( FB_ERRMSG_RECLEVELTOODEEP )
63  '' error recovery: skip
64  exit sub
65  end if
66 
67  .stk(.tos) = value
68  .tos += 1
69  end with
70 end sub
71 
72 sub pragmaPop( byval opt as integer, byref value as longint )
73  with pragmaStk(opt)
74  if( .tos <= 0 ) then
75  errReport( FB_ERRMSG_STACKUNDERFLOW )
76  '' error recovery: skip
77  value = FALSE
78  exit sub
79  end if
80 
81  .tos -= 1
82  value = .stk(.tos)
83  end with
84 end sub
85 
86 '':::::
87 '' Pragma = PRAGMA
88 '' PUSH '(' symbol (',' expression{int})? ')'
89 '' | POP '(' symbol ')'
90 '' | symbol ('=' expression{int})?
91 ''
92 sub ppPragma( )
93  dim as string tk
94  dim as integer p = -1, ispop = FALSE, ispush = FALSE
95  dim as longint value = any
96 
97  tk = lcase( *lexGetText( ) )
98  if( tk = "push" ) then
99  ispush = TRUE
100  elseif( tk = "pop" ) then
101  ispop = TRUE
102  end if
103 
104  if( ispop or ispush ) then
105  lexSkipToken( )
106 
107  '' '('
108  if( lexGetToken() <> CHAR_LPRNT ) then
109  errReport( FB_ERRMSG_EXPECTEDLPRNT )
110  else
111  lexSkipToken( )
112  end if
113 
114  tk = lcase( *lexGetText( ) )
115  end if
116 
117  for i as integer = 0 to LEXPP_PRAGMAS-1
118  if( tk = pragmaOpt(i).tk ) then
119  p = i
120  exit for
121  end if
122  next
123 
124  if( p = -1 ) then
125  errReport( FB_ERRMSG_SYNTAXERROR )
126  '' error recovery: skip line
127  if( ispop or ispush ) then
128  hSkipUntil( CHAR_RPRNT, TRUE )
129  else
130  hSkipUntil( FB_TK_EOL )
131  end if
132  return
133  end if
134 
135  if( ispush or ispop ) then
136  if( (pragmaOpt(p).flags and LEXPP_PRAGMAFLAG_CAN_PUSHPOP) = 0 ) then
137  errReport( FB_ERRMSG_SYNTAXERROR )
138  '' error recovery: skip line
139  if( ispop or ispush ) then
140  hSkipUntil( CHAR_RPRNT, TRUE )
141  else
142  hSkipUntil( FB_TK_EOL )
143  end if
144  return
145  end if
146  end if
147 
148  lexSkipToken( )
149 
150  if( ispop ) then
151  pragmaPop( pragmaOpt(p).opt, value )
152 
153  '' Preserve msbitfields #pragmas under -pp
154  if( p = LEXPP_PRAGMAOPT_BITFIELD ) then
155  if( env.ppfile_num > 0 ) then
156  lexPPOnlyEmitText( "#pragma pop(msbitfields)" )
157  end if
158  end if
159  else
160  '' assume value is FALSE/TRUE unless the #pragma explicitly uses other values
161  value = FALSE
162 
163  if( ispush ) then
165 
166  '' ','?
167  if( lexGetToken() = CHAR_COMMA ) then
168  lexSkipToken( )
169  else
170  value = TRUE
171  end if
172  else
173  '' '='?
174  if( lexGetToken() = FB_TK_EQ ) then
175 
176  if( (pragmaOpt(p).flags and LEXPP_PRAGMAFLAG_CAN_ASSIGN) = 0 ) then
177  errReport( FB_ERRMSG_SYNTAXERROR )
178  '' error recovery: skip line
179  hSkipUntil( FB_TK_EOL )
180  return
181  end if
182 
183  lexSkipToken( )
184  else
185  value = TRUE
186  end if
187  end if
188 
189  if( value = FALSE ) then
190  '' expr
191  value = cConstIntExpr( cExpression( ) )
192  end if
193 
194  '' Preserve msbitfields #pragmas under -pp
195  if( p = LEXPP_PRAGMAOPT_BITFIELD ) then
196  if( env.ppfile_num > 0 ) then
197  if( ispush ) then
198  lexPPOnlyEmitText( "#pragma push(msbitfields, " + str( value ) + ")" )
199  else
200  lexPPOnlyEmitText( "#pragma msbitfields = " + str( value ) )
201  end if
202  end if
203  end if
204  end if
205 
206  ''
207  if( (pragmaOpt(p).flags and LEXPP_PRAGMAFLAG_HAS_CALLBACK) <> 0 ) then
208  select case p
210  fbPragmaOnce()
211  end select
212  else
214  fbChangeOption( pragmaOpt(p).opt, value )
215  end if
216  end if
217 
218  ''
219  if( ispop or ispush ) then
220  '' ')'
221  if( lexGetToken() <> CHAR_RPRNT ) then
222  errReport( FB_ERRMSG_EXPECTEDRPRNT )
223  '' error recovery: skip until next ')'
224  hSkipUntil( CHAR_RPRNT, TRUE )
225  else
226  lexSkipToken( )
227  end if
228  end if
229 end sub
230