2 * (c) Oleg Puchinin 2006,2007
3 * graycardinalster@gmail.com
7 #include <gclib/gclib.h>
20 char * __bice_get (char *optname
)
23 value
= ENV
->settings
->get (optname
);
25 value
= getenv (optname
);
29 EHash
* bob_init_compile_env ()
41 compile_env
= new EHash
;
43 cc
= __bice_get ("CC");
44 cxx
= __bice_get ("CXX");
45 cflags
= __bice_get ("CFLAGS");
46 cxxflags
= __bice_get ("CXXFLAGS");
47 opts
= __bice_get ("OPTS");
48 include
= __bice_get ("INCLUDE");
49 libs
= __bice_get ("LIBS");
50 ldflags
= __bice_get ("LDFLAGS");
57 cflags
= "-O3 -Wall -pipe";
69 if (SB_FLGET (SB_FLVERBOSE
)) {
70 printf ("C compiler: %s\n", cc
);
71 printf ("C++ compiler: %s\n", cxx
);
72 printf ("C flags: %s\n", cflags
);
73 printf ("C++ flags: %s\n", cxxflags
);
74 printf ("OPTS: %s\n", opts
);
75 printf ("INCLUDE: %s\n", include
);
76 printf ("LIBS: %s\n", libs
);
77 printf ("LDFLAGS: %s\n", ldflags
);
80 compile_env
->set ("CC", strdup (cc
));
81 compile_env
->set ("CXX", strdup (cxx
));
82 compile_env
->set ("CFLAGS", strdup (cflags
));
83 compile_env
->set ("CXXFLAGS", strdup (cxxflags
));
84 compile_env
->set ("OPTS", strdup (opts
));
85 compile_env
->set ("INCLUDE", strdup (include
));
86 compile_env
->set ("LIBS", strdup (libs
));
87 compile_env
->set ("LDFLAGS", strdup (ldflags
));
92 int sb_prname (char *arg
)
96 d_ptr
= arg
+ strlen (arg
);
99 while (*d_ptr
!= '\\' &&
106 if (EQ (d_ptr
, "tags"))
108 else if (EQ (d_ptr
, "the_tt"))
110 else if (EQ (d_ptr
, "gc_indent"))
112 else if (EQ (d_ptr
, "structs"))
113 i_cmd
= cmd_give_structs
;
119 void tags (DArray
* d_names
, char * d_file_output
)
121 struct fdump_param_t d_param
;
123 struct d_tag_t
* d_tag
;
129 n_names
= d_names
->get_size ();
131 for (i
= 0; i
< n_names
; i
++) {
132 d_tags
= got_tag (d_names
->get (i
));
133 if (d_tags
== NULL
) {
134 if (d_tags
->get_size () == 0) {
135 fprintf (ENV
->d_stream_dbg
, "Tag not found : %s\n",
137 fflush (ENV
->d_stream_dbg
);
146 if(! d_tags
->get_size ()) {
154 for (a
= 0; a
< d_tags
->get_size (); a
++) {
155 d_tag
= (d_tag_t
*) d_tags
->get (a
);
160 printf ("// file %s line %i\n",
161 d_tag
->d_file
, d_tag
->d_line
);
163 memset (&d_param
, 0, sizeof (struct fdump_param_t
));
165 d_param
.d_file_name
= d_tag
->d_file
;
166 d_param
.d_line
= d_tag
->d_line
;
167 d_param
.linear
= true;
168 d_param
.d_file_output
= d_file_output
;
169 if (d_tag
->d_type
== OT::Function
)
170 d_param
.b_force_block
= true;
172 nogui_fdump (&d_param
);
174 fputc ('\n', stdout
);
188 void bug_longmacro ()
190 printf ("Too big macro."
191 "If your macro have more than 300 lines, please "
192 "contact <graycardinal@pisem.net>\n"
193 "Program stopped.\n");
198 void bug_nosuch_tag (char * f_name
)
200 printf ("Tag \"%s\" not found. Broken \"tags\" file ? "
201 "Try \"silent-bob --make-ctags\".\n", f_name
);
204 void bug_nocalltags ()
206 printf ("File \"call_tags\" not found. "
207 "Try \"silent-bob --call-tags [-L] <files>\"\n");
213 printf ("Can't make tags file. Maybe you do not have write permissions ?\n");
223 void bug_plugin (char *name
)
225 fprintf (stderr
, "Can't load plugin (%s)\n", name
);
228 void bug_notsupported ()
230 printf ("SilentBob (or language plugin)"
231 " don't support this feature !\n");
234 bool bob_tag (char *d_str
, char * d_name
, d_tag_t
* d_tag
)
240 strcpy (m_buf
, d_str
);
243 strncpy (d_tag
->d_name
, d_name
, 255);
244 d_tag
->d_name
[255] = 0;
245 S
= strchr (d_str
, '\t');
251 S
= strchr (d_file
, '\t');
256 strncpy (d_tag
->d_file
, d_file
, 255);
257 d_tag
->d_file
[255] = 0;
262 d_tag
->d_line
= atoi (S
);
269 char * cts (struct c_word
* d_word
)
277 if (!strncmp (S
, "else ", 5))
280 if (d_word
->ch
!= '(')
283 while (!strncmp (S
, "do ", 3))
286 if (!strncmp (S
, "return ", 7))
289 if (ENV
->d_cops
->sfind (S
) != -1)
292 if (words_count (S
) != 1)
298 bool def_test (char * d_op
)
302 while (*S
== ' ' || *S
== '\t')
305 if (! strncmp (S
, "define", 6))
312 find_one_ext ("*.h");
313 find_one_ext ("*.hpp");
314 find_one_ext ("*.cpp");
315 find_one_ext ("*.c");
316 find_one_ext ("*.cc");
317 find_one_ext ("*.cxx");
321 int sblib_find (char * path
, char * name
, char * f_outname
)
330 devnull
= open ("/dev/null", O_WRONLY
, 0600);
331 fd
= open (f_outname
, O_WRONLY
, 0600);
333 fd
= open (f_outname
, O_WRONLY
| O_CREAT
, 0600);
339 lseek (fd
, 0, SEEK_END
);
342 execlp ("find", path
, "-name", name
, NULL
);
343 } else if (pid
> 0) {
344 waitpid (pid
, &status
, 0);
351 # define TMP_FILE_NAME "./silent_bob.tmp"
352 struct tt_state_t
* get_onett_tag (char * f_name
, char ** d_tt_buf
)
355 tt_state_t
* Ret
= NULL
;
361 d_array
.add (f_name
);
362 Ret
= CNEW (tt_state_t
, 1);
364 unlink (TMP_FILE_NAME
);
365 tags (&d_array
, TMP_FILE_NAME
);
368 if (access (TMP_FILE_NAME
, R_OK
) != 0)
371 Ret
->fileName
= strdup (TMP_FILE_NAME
);
372 S
= THE_TT::do_tt_file (Ret
);
378 munmap (Ret
->fileData
, Ret
->fileDataSize
);
386 unlink (TMP_FILE_NAME
);
391 unlink (TMP_FILE_NAME
);
395 void globalsPrint (tt_state_t
* tt
, char * d_out
, int d_found_type
)
399 if (SB_FLGET (SB_FLSIMULATE
))
402 if (d_found_type
& OT::Other
)
405 t_line
= tt
->attachment
[ENV
->t_op_no
].pair_line
+1;
406 t_line
+= ww_begin_line (tt
, d_out
,
407 tt
->attachment
[ENV
->t_op_no
].offset
);
409 if (SB_FLGET(SB_FLTAGSTYLE
))
410 mk_tag (d_out
, tt
->fileName
,
411 t_line
, d_found_type
);
413 printf ("%s\t\t//file %s //line %i\n", d_out
,
414 tt
->fileName
, t_line
);
421 EArray
* got_tag (char * d_tag
)
423 struct d_tag_t
*d_new_tag
;
432 if (ENV
->d_tags_file
== NULL
) {
433 ENV
->d_tags_file
= new EArray
;
434 ENV
->d_tags_file
->from_file ("./tags");
437 snprintf (d_buf
, 255, "%s\t", d_tag
);
438 d_len
= strlen (d_buf
);
440 if (ENV
->d_tags_file
->get_size () == 0)
443 i
= ENV
->d_tags_file
->snfind_fast (d_buf
, strlen (d_buf
));
446 fprintf (ENV
->d_stream_dbg
, "\tENV->d_tags_file->snfind_fast == -1"); LN
;
450 d_len
= strlen (d_buf
);
453 S
= ENV
->d_tags_file
->get (i
);
456 } while (! strncmp (S
, d_buf
, d_len
));
460 S
= ENV
->d_tags_file
->get (i
);
461 fprintf (ENV
->d_stream_dbg
, "\ttag : %s\n", S
); fflush (ENV
->d_stream_dbg
);
463 d_new_tag
= CNEW (d_tag_t
, 1);
464 memset (d_new_tag
, 0, sizeof (d_tag_t
));
465 if (strstr (S
, ";\tf"))
466 d_new_tag
->d_type
= OT::Function
;
468 if (bob_tag (S
, d_tag
, d_new_tag
) == false) {
470 fprintf (ENV
->d_stream_dbg
, "\tBAD tag : %s\n", S
);
474 d_ret
->add ((long) d_new_tag
);
480 S
= ENV
->d_tags_file
->get (i
);
481 if (strncmp (S
, d_tag
, strlen (d_tag
)))
488 char * macro_name (char * d_op
, char * d_macro_name
)
494 strncpy (m_buf
, d_op
, 255);
497 S
= strstr (m_buf
, "define");
510 S
= strchr (d_begin
, ' ');
514 S
= strchr (d_begin
, '(');
518 strcpy (d_macro_name
, d_begin
);
522 void mk_tag_macro (char * d_op
, char * d_file
, int t_line
)
526 if (! macro_name (d_op
, S
))
529 printf ("%s\t%s\t%i\n", S
, d_file
, t_line
);
532 void mk_tag (char * d_op
, char * d_file
, int line
, int d_found_type
)
534 char * d_format
= "%s\t%s\t%i\n";
537 if (d_found_type
& OT::Define
) {
538 mk_tag_macro (d_op
, d_file
, line
);
542 if (d_found_type
& OT::Class
) {
543 S
= strchr (d_op
, ':');
548 S
= ww_last_word (d_op
);
549 if (! S
|| !(*S
) || (*S
== ' '))
553 if (! strncmp (S
, "static", 6))
555 if (! strncmp (S
, "struct", 6))
559 if (*S
== 'u' && !strncmp (S
, "union", 5))
561 if (*S
== 'e' && !strncmp (S
, "enum", 4))
564 if (d_found_type
& OT::Function
)
565 d_format
= "%s\t%s\t%i\t;\tf\n";
567 printf (d_format
, S
, d_file
, line
);
570 DArray
* mk_tag_structtail_split (char *S
)
572 bool b_macro
= false;
577 d_array
= new DArray (128);
584 if (*S
== '\"' || *S
== '\'') {
586 if (S
== NULL
|| *S
== '\0')
603 d_array
->add (d_old
);
618 if (*S
== ' ' || *S
== ',') {
622 while (*S
== ' ' || *S
== '*')
625 d_array
->add (d_old
);
636 void mk_tag_structtail (char * S
, char * d_file
, int t_line
)
642 d_array
= mk_tag_structtail_split (S
);
646 for (i
= 0; i
< d_array
->get_size (); i
++) {
647 w
= ww_last_word (d_array
->get (i
));
648 if (! w
|| !(*w
) || *w
== ' ')
650 printf ("%s\t%s\t%i\n", w
, d_file
, t_line
);
656 void mk_tags (char *f_name
, DArray
*d_in
)
659 DArray
* d_array
= NULL
;
666 d_array
= new DArray (1024);
667 d_array
->from_file (ENV
->tmp_tags
);
671 d_size
= d_array
->get_size ();
672 heap
= new DHeapSort (d_size
);
674 for (i
= 0; i
< d_size
; ++i
)
675 heap
->add (d_array
->get (i
));
677 my_file
= fopen (f_name
, "w");
678 if (my_file
== NULL
) {
679 fprintf (stderr
, "file %s:\n", f_name
);
684 fprintf (my_file
, "!_TAG_FILE_FORMAT\t2\n");
685 fprintf (my_file
, "!_TAG_FILE_SORTED\t1\n");
686 fprintf (my_file
, "!_TAG_PROGRAM_AUTHOR\tOleg Puchinin (graycardinalster@gmail.com)\n");
687 fprintf (my_file
, "!_TAG_PROGRAM_NAME\tSilent Bob\n");
688 fprintf (my_file
, "!_TAG_PROGRAM_URL\thttp://sf.net/projects/silentbob\n");
689 fprintf (my_file
, "!_TAG_PROGRAM_VERSION\t1.6\n");
691 while ((S
= heap
->extract_min ()) && S
)
692 fprintf (my_file
, "%s", S
);
695 d_array
->foreach (free
);
703 char * name2obj (char * name
)
709 strcpy (m_buf
, name
);
710 S
= rindex (m_buf
, '.');
714 return strdup (m_buf
);
718 bool brace_count (char * d_str
, int * d_count
, bool b_force_block
) // "nice"
722 if (! d_str
|| ! d_count
)
725 while (*d_str
!= 0) {
726 if (!strncmp (d_str
, "/*", 2)) {
733 if (strncmp (d_str
, "*/", 2)) {
738 b_in_comment
= false;
743 if (!strncmp (d_str
, "//", 2))
746 if (*d_str
== '\"' || *d_str
== '\'') {
747 d_str
= sstrend (d_str
);
748 if (d_str
== NULL
|| *d_str
== 0) {
749 assert (true, "HimTeh 4");
764 if (*d_str
== ';' && *d_count
== 0 && !b_force_block
) {
774 void nogui_fdump (struct fdump_param_t
* d_param
)
783 if (!d_array
.from_file (d_param
->d_file_name
))
786 if (d_param
->d_file_output
== NULL
)
789 d_file
= fopen (d_param
->d_file_output
, "w");
794 if (! d_param
->linear
) {
795 for (a
= 0; a
< d_param
->n_trip
; a
++)
796 fprintf (d_file
, "\t");
797 fprintf (d_file
, "//<***>\n");
800 i
= d_param
->d_line
-1;
801 d_size
= d_array
.get_size ();
802 b_in_comment
= false;
804 if (d_array
.get (i
)[0] != '#') {
806 if (!d_param
->linear
) {
807 for (a
= 0; a
< d_param
->n_trip
; a
++)
808 fprintf (d_file
, "\t");
810 fprintf (d_file
, "%s", d_array
.get(i
));
812 if (brace_count (d_array
.get(i
), &d_count
, d_param
->b_force_block
) && !d_count
)
815 if (!d_count
&& ((i
- d_param
->d_line
) > 2) && !d_param
->b_force_block
)
823 fprintf (d_file
, "%s", S
);
824 S
= &S
[strlen (S
)-2];
825 while ((*S
== ' ') || (*S
== '\t'))
831 } while (i
< d_size
);
834 if (!d_param
->linear
) {
835 for (a
= 0; a
< d_param
->n_trip
; a
++)
836 fprintf (d_file
, "\t");
837 fprintf (d_file
, "//</***>\n");
840 if (d_param
->d_file_output
!= NULL
)
843 d_array
.foreach (free
);
847 /* code for "linear" functionality, */
848 void nogui_tagsdump (char * f_name
, int n_trip
) {
851 struct fdump_param_t d_param
;
854 d_tags
= got_tag (f_name
);
856 assert (d_tags
->get_size () == 0, "HimTeh 1");
857 for (i
= 0; i
< d_tags
->get_size (); i
++) {
858 d_tag
= (d_tag_t
*) d_tags
->get (i
);
860 fputc ('\n', stdout
);
862 if (!SB_FLGET(SB_FLLINEAR
)) {
863 for (a
= 0; a
< n_trip
; a
++)
864 fputc ('\t', stdout
);
867 printf ("// file %s line %i\n", d_tag
->d_file
, d_tag
->d_line
);
869 memset (&d_param
, 0, sizeof (struct fdump_param_t
));
870 d_param
.n_trip
= n_trip
;
871 d_param
.d_file_name
= d_tag
->d_file
;
872 d_param
.d_line
= d_tag
->d_line
;
873 d_param
.linear
= SB_FLGET (SB_FLLINEAR
);
874 if (d_tag
->d_type
& OT::Function
)
875 d_param
.b_force_block
= true;
876 nogui_fdump (&d_param
);
879 d_tags
->foreach (free
);
884 void opMacro (char ** d_ptr
, char ** d_out
, char ch
)
891 macro_start
= *d_out
;
896 if ((ch
== '\n') && (d_my
[strlen (d_my
) - 1] != '\\'))
902 ch
= t_op (d_ptr
, d_out
);
910 int remove_tmp_files ()
915 for (i
= 0; i
< ENV
->max_proc
; ++i
) {
916 sprintf (m_buf
, "%s%i", ENV
->tmp_files
, i
);
920 unlink (ENV
->tmp_files
);
921 unlink (ENV
->tmp_tags
);
922 return ENV
->max_proc
;
925 void setParam (char *opt
)
933 S
= index (m_buf
, '=');
941 ENV
->settings
->set (m_buf
, strdup (S
));
944 int split_tmp_files ()
951 f_tmpfiles
= fopen (ENV
->tmp_files
, "r");
955 proc_files
= CNEW (FILE *, ENV
->max_proc
);
956 memset (proc_files
, 0, sizeof (FILE *) * ENV
->max_proc
);
958 for (i
= 0; i
< ENV
->max_proc
; ++i
) {
959 sprintf (m_buf
, "%s%i", ENV
->tmp_files
, i
);
961 proc_files
[i
] = fopen (m_buf
, "w");
962 if (! proc_files
[i
]) {
969 while (fgets (m_buf
, 512, f_tmpfiles
)) {
970 fprintf (proc_files
[i
], "%s", m_buf
);
971 if (++i
>= ENV
->max_proc
)
975 for (i
= 0; i
< ENV
->max_proc
; ++i
)
976 fclose (proc_files
[i
]);
978 return ENV
->max_proc
;
981 DArray
* split_to_words (char * d_op
)
983 DArray
* d_Ret
= new DArray (16);
984 char * d_old
= strdup (d_op
);
990 if (d_Ret
== NULL
|| d_old
== NULL
)
1001 if (!(if_abc(d_end
) ||
1012 goto split_to_words_L1
;
1016 if (d_end
[-1] == ' ')
1021 while (*S
&& *S
== ' ')
1025 d_Ret
->add (LPCHAR(new_cword (S
, ch
)));
1030 if (ch
== '\"' || ch
== '\'') {
1032 d_end
= sstrend (d_end
);
1033 assert (d_end
== NULL
, "Lena 1");
1034 if (*d_end
== '\0' || *(++d_end
) == '\0')
1045 char * sstrend (char * d_ptr
)
1047 bool t_instring
= false;
1051 unsigned limit
= 1024;
1062 while (*d_ptr
&& (limit
> 0)) {
1063 if (*d_ptr
== '\'' || *d_ptr
== '\"') {
1064 if (t_instring
&& *d_ptr
!= ch_last
) {
1070 if (d_ptr
[-1] == '\\') {
1072 while (d_ptr
[-(d_slash_count
)] == '\\')
1075 if (d_slash_count
& 1)
1103 char * sstrkill (char *OP
)
1113 if (*S
== '\"' || *S
== '\'') {
1118 if (*tail
== '\0' ||*(tail
+1) == '\0') {
1132 int words_count (char *S
)
1134 bool b_begin
= true;
1159 if (!(if_abc (S
) || (*S
== '_')
1160 || (*S
== '*') || (if_digit (S
))))
1171 int ww_begin_line (struct tt_state_t
* d_tt_state
, char *d_out
, int d_offset
)
1173 char *S
= &d_tt_state
->fileData
[d_offset
] - 1;
1174 char * d_end
= &d_out
[strlen (d_out
)] - 1;
1177 while (d_end
> d_out
) {
1178 if (*d_end
== ' ' || *d_end
== '\t') {
1179 while ((S
>= d_tt_state
->fileData
) && (*S
== ' ' || *S
== '\t'))
1182 if (S
< d_tt_state
->fileData
)
1185 while ((d_end
>= d_out
) && (*d_end
== ' ' || *d_end
== '\t'))
1206 char * ww_begin_offset (struct tt_state_t
* d_tt_state
, char *d_out
, int d_offset
)
1208 char *S
= &d_tt_state
->fileData
[d_offset
] - 1;
1209 char * d_real
= &d_out
[strlen (d_out
)] - 1;
1211 while (d_real
!= d_out
) {
1212 if (*d_real
== ' ' || *d_real
== '\t') {
1213 while (*S
== ' ' || *S
== '\t')
1216 while ((*d_real
== ' ' || *d_real
== '\t')
1217 && (d_real
!= d_out
))
1232 char * ww_last_word (char *d_op
)
1238 if (*S
== '(' || *S
== '=' || *S
== '[')
1249 S
= strchr (d_word
, ' ');
1255 while (*d_word
== '*' ||
1263 bool validOption (char *Name
)
1269 S
= ENV
->listOptions
->first ();
1273 S
= ENV
->listOptions
->next ();