@@ -37,7 +37,6 @@ typedef enum {
3737typedef struct {
3838 char const * token ;
3939 BasicKind kind ;
40- int skip ;
4140} KeyWord ;
4241
4342static kindDefinition BasicKinds [] = {
@@ -49,76 +48,182 @@ static kindDefinition BasicKinds[] = {
4948 {true, 'g' , "enum" , "enumerations" }
5049};
5150
52- static KeyWord blitzbasic_keywords [] = {
53- {"const" , K_CONST , 0 },
54- {"global" , K_VARIABLE , 0 },
55- {"dim" , K_VARIABLE , 0 },
56- {"function" , K_FUNCTION , 0 },
57- {"type" , K_TYPE , 0 },
58- {NULL , 0 , 0 }
59- };
51+ static KeyWord basic_keywords [] = {
52+ /* freebasic */
53+ {"const" , K_CONST },
54+ {"dim" , K_VARIABLE },
55+ {"common" , K_VARIABLE },
56+ {"function" , K_FUNCTION },
57+ {"sub" , K_FUNCTION },
58+ {"private sub" , K_FUNCTION },
59+ {"public sub" , K_FUNCTION },
60+ {"private function" , K_FUNCTION },
61+ {"public function" , K_FUNCTION },
62+ {"property" , K_FUNCTION },
63+ {"constructor" , K_FUNCTION },
64+ {"destructor" , K_FUNCTION },
65+ {"type" , K_TYPE },
66+ {"enum" , K_ENUM },
6067
61- static KeyWord purebasic_keywords [] = {
62- {"newlist" , K_VARIABLE , 0 },
63- {"global" , K_VARIABLE , 0 },
64- {"dim" , K_VARIABLE , 0 },
65- {"procedure" , K_FUNCTION , 0 },
66- {"interface" , K_TYPE , 0 },
67- {"structure" , K_TYPE , 0 },
68- {NULL , 0 , 0 }
69- };
68+ /* blitzbasic, purebasic */
69+ {"global" , K_VARIABLE },
7070
71- static KeyWord freebasic_keywords [] = {
72- {"const" , K_CONST , 0 },
73- {"dim as" , K_VARIABLE , 1 },
74- {"dim" , K_VARIABLE , 0 },
75- {"common" , K_VARIABLE , 0 },
76- {"function" , K_FUNCTION , 0 },
77- {"sub" , K_FUNCTION , 0 },
78- {"private sub" , K_FUNCTION , 0 },
79- {"public sub" , K_FUNCTION , 0 },
80- {"private function" , K_FUNCTION , 0 },
81- {"public function" , K_FUNCTION , 0 },
82- {"type" , K_TYPE , 0 },
83- {"enum" , K_ENUM , 0 },
84- {NULL , 0 , 0 }
71+ /* purebasic */
72+ {"newlist" , K_VARIABLE },
73+ {"procedure" , K_FUNCTION },
74+ {"interface" , K_TYPE },
75+ {"structure" , K_TYPE },
76+
77+ {NULL , 0 }
8578};
8679
8780/*
8881 * FUNCTION DEFINITIONS
8982 */
9083
91- /* Match the name of a tag (function, variable, type, ...) starting at pos. */
92- static char const * extract_name (char const * pos , vString * name )
84+ static const char * skipToMatching (char begin , char end , const char * pos )
85+ {
86+ int counter = 1 ;
87+ pos ++ ;
88+ while (* pos && counter > 0 )
89+ {
90+ if (* pos == end )
91+ counter -- ;
92+ else if (* pos == begin )
93+ counter ++ ;
94+ else if (* pos == '"' )
95+ pos = skipToMatching ('"' , '"' , pos ) - 1 ;
96+ pos ++ ;
97+ }
98+ return pos ;
99+ }
100+
101+ static const char * nextPos (const char * pos )
93102{
103+ if (* pos == '\0' )
104+ return pos ;
105+
106+ pos ++ ;
107+ switch (* pos )
108+ {
109+ case '(' :
110+ pos = skipToMatching ('(' , ')' , pos );
111+ break ;
112+ case '"' :
113+ pos = skipToMatching ('"' , '"' , pos );
114+ break ;
115+ }
116+ return pos ;
117+ }
118+
119+ static bool isIdentChar (char c )
120+ {
121+ return c && !isspace (c ) && c != '(' && c != ',' && c != '=' ;
122+ }
123+
124+ /* Match the name of a dim or const starting at pos. */
125+ static void extract_dim (char const * pos , BasicKind kind )
126+ {
127+ vString * name = vStringNew ();
128+
129+ if (strncasecmp (pos , "shared" , 6 ) == 0 )
130+ pos += 6 ; /* skip keyword "shared" */
131+
94132 while (isspace (* pos ))
95133 pos ++ ;
96- vStringClear (name );
97- for (; * pos && !isspace (* pos ) && * pos != '(' && * pos != ',' ; pos ++ )
134+
135+ /* capture "dim as String str" */
136+ if (strncasecmp (pos , "as" , 2 ) == 0 )
137+ {
138+ pos += 2 ; /* skip keyword "as" */
139+
140+ while (isspace (* pos ))
141+ pos ++ ;
142+ while (!isspace (* pos ) && * pos ) /* skip next part which is a type */
143+ pos ++ ;
144+ while (isspace (* pos ))
145+ pos ++ ;
146+ /* now we are at the name */
147+ }
148+ /* capture "dim as foo ptr bar" */
149+ if (strncasecmp (pos , "ptr" , 3 ) == 0 && isspace (* (pos + 3 )))
150+ {
151+ pos += 3 ; /* skip keyword "ptr" */
152+ while (isspace (* pos ))
153+ pos ++ ;
154+ }
155+ /* capture "dim as string * 4096 chunk" */
156+ if (strncmp (pos , "*" , 1 ) == 0 )
157+ {
158+ pos += 1 ; /* skip "*" */
159+ while (isspace (* pos ) || isdigit (* pos ) || ispunct (* pos ))
160+ pos ++ ;
161+ }
162+
163+ for (; isIdentChar (* pos ); pos ++ )
98164 vStringPut (name , * pos );
99- return pos ;
165+ makeSimpleTag (name , kind );
166+
167+ /* if the line contains a ',', we have multiple declarations */
168+ while (* pos && strchr (pos , ',' ))
169+ {
170+ /* skip all we don't need(e.g. "..., new_array(5), " we skip "(5)") */
171+ while (* pos != ',' && * pos != '\'' && * pos )
172+ pos = nextPos (pos );
173+
174+ if (* pos == '\'' )
175+ break ; /* break if we are in a comment */
176+
177+ while (isspace (* pos ) || * pos == ',' )
178+ pos ++ ;
179+
180+ if (* pos == '\'' )
181+ break ; /* break if we are in a comment */
182+
183+ vStringClear (name );
184+ for (; isIdentChar (* pos ); pos ++ )
185+ vStringPut (name , * pos );
186+ makeSimpleTag (name , kind );
187+ }
188+
189+ vStringDelete (name );
190+ }
191+
192+ /* Match the name of a tag (function, variable, type, ...) starting at pos. */
193+ static void extract_name (char const * pos , BasicKind kind )
194+ {
195+ vString * name = vStringNew ();
196+ for (; isIdentChar (* pos ); pos ++ )
197+ vStringPut (name , * pos );
198+ makeSimpleTag (name , kind );
199+ vStringDelete (name );
100200}
101201
102202/* Match a keyword starting at p (case insensitive). */
103- static int match_keyword (const char * p , KeyWord const * kw )
203+ static bool match_keyword (const char * p , KeyWord const * kw )
104204{
105- vString * name ;
106205 size_t i ;
107- int j ;
206+ const char * old_p ;
108207 for (i = 0 ; i < strlen (kw -> token ); i ++ )
109208 {
110209 if (tolower (p [i ]) != kw -> token [i ])
111- return 0 ;
210+ return false ;
112211 }
113- name = vStringNew ();
114212 p += i ;
115- for (j = 0 ; j < 1 + kw -> skip ; j ++ )
116- {
117- p = extract_name (p , name );
118- }
119- makeSimpleTag (name , kw -> kind );
120- vStringDelete (name );
121- return 1 ;
213+
214+ old_p = p ;
215+ while (isspace (* p ))
216+ p ++ ;
217+
218+ /* create tags only if there is some space between the keyword and the identifier */
219+ if (old_p == p )
220+ return false;
221+
222+ if (kw -> kind == K_VARIABLE )
223+ extract_dim (p , kw -> kind ); /* extract_dim adds the found tag(s) */
224+ else
225+ extract_name (p , kw -> kind );
226+ return true;
122227}
123228
124229/* Match a "label:" style label. */
@@ -140,26 +245,12 @@ static void match_colon_label (char const *p)
140245static void match_dot_label (char const * p )
141246{
142247 if (* p == '.' )
143- {
144- vString * name = vStringNew ();
145- extract_name (p + 1 , name );
146- makeSimpleTag (name , K_LABEL );
147- vStringDelete (name );
148- }
248+ extract_name (p + 1 , K_LABEL );
149249}
150250
151251static void findBasicTags (void )
152252{
153253 const char * line ;
154- const char * extension = fileExtension (getInputFileName ());
155- KeyWord * keywords ;
156-
157- if (strcmp (extension , "bb" ) == 0 )
158- keywords = blitzbasic_keywords ;
159- else if (strcmp (extension , "pb" ) == 0 )
160- keywords = purebasic_keywords ;
161- else
162- keywords = freebasic_keywords ;
163254
164255 while ((line = (const char * ) readLineFromInputFile ()) != NULL )
165256 {
@@ -183,11 +274,11 @@ static void findBasicTags (void)
183274 continue ;
184275
185276 /* In Basic, keywords always are at the start of the line. */
186- for (kw = keywords ; kw -> token ; kw ++ )
277+ for (kw = basic_keywords ; kw -> token ; kw ++ )
187278 if (match_keyword (p , kw )) break ;
188279
189280 /* Is it a label? */
190- if (strcmp ( extension , "bb" ) == 0 )
281+ if (* p == '.' )
191282 match_dot_label (p );
192283 else
193284 match_colon_label (p );
0 commit comments