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 ((char *) "CC");
44 cxx
= __bice_get ((char *) "CXX");
45 cflags
= __bice_get ((char *) "CFLAGS");
46 cxxflags
= __bice_get ((char *) "CXXFLAGS");
47 opts
= __bice_get ((char *) "OPTS");
48 include
= __bice_get ((char *) "INCLUDE");
49 libs
= __bice_get ((char *) "LIBS");
50 ldflags
= __bice_get ((char *) "LDFLAGS");
57 cflags
= (char *) "-O3 -Wall -pipe";
63 include
= (char *) "";
67 ldflags
= (char *) "";
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 ((char *) "CC", strdup (cc
));
81 compile_env
->set ((char *) "CXX", strdup (cxx
));
82 compile_env
->set ((char *) "CFLAGS", strdup (cflags
));
83 compile_env
->set ((char *) "CXXFLAGS", strdup (cxxflags
));
84 compile_env
->set ((char *) "OPTS", strdup (opts
));
85 compile_env
->set ((char *) "INCLUDE", strdup (include
));
86 compile_env
->set ((char *) "LIBS", strdup (libs
));
87 compile_env
->set ((char *) "LDFLAGS", strdup (ldflags
));
92 int sb_prname (char *arg
)
96 d_ptr
= arg
+ strlen (arg
);
99 while (*d_ptr
!= '\\' &&
106 if (EQ (d_ptr
, "bob_perl"))
107 ENV
->language
= strdup ("Perl");
108 else if (EQ (d_ptr
, "bob_python"))
109 ENV
->language
= strdup ("Python");
110 else if (EQ (d_ptr
, "bob_ruby"))
111 ENV
->language
= strdup ("Ruby");
113 if (EQ (d_ptr
, "tags"))
115 else if (EQ (d_ptr
, "the_tt"))
117 else if (EQ (d_ptr
, "gc_indent"))
119 else if (EQ (d_ptr
, "structs"))
120 i_cmd
= cmd_give_structs
;
126 void tags (DArray
* d_names
, char * d_file_output
)
128 struct fdump_param_t d_param
;
130 struct d_tag_t
* d_tag
;
136 n_names
= d_names
->get_size ();
138 for (i
= 0; i
< n_names
; i
++) {
139 d_tags
= got_tag (d_names
->get (i
));
140 if (d_tags
== NULL
) {
141 if (d_tags
->get_size () == 0) {
142 fprintf (ENV
->d_stream_dbg
, "Tag not found : %s\n",
144 fflush (ENV
->d_stream_dbg
);
153 if(! d_tags
->get_size ()) {
161 for (a
= 0; a
< d_tags
->get_size (); a
++) {
162 d_tag
= (d_tag_t
*) d_tags
->get (a
);
167 printf ("// file %s line %i\n",
168 d_tag
->d_file
, d_tag
->d_line
);
170 memset (&d_param
, 0, sizeof (struct fdump_param_t
));
172 d_param
.d_file_name
= d_tag
->d_file
;
173 d_param
.d_line
= d_tag
->d_line
;
174 d_param
.linear
= true;
175 d_param
.d_file_output
= d_file_output
;
176 if (d_tag
->d_type
== OT::Function
)
177 d_param
.b_force_block
= true;
179 nogui_fdump (&d_param
);
181 fputc ('\n', stdout
);
195 void bug_longmacro ()
197 printf ("Too big macro."
198 "If your macro have more than 300 lines, please "
199 "contact <graycardinal@pisem.net>\n"
200 "Program stopped.\n");
205 void bug_nosuch_tag (char * f_name
)
207 printf ("Tag \"%s\" not found. Broken \"tags\" file ? "
208 "Try \"silent-bob --make-ctags\".\n", f_name
);
211 void bug_nocalltags ()
213 printf ("File \"call_tags\" not found. "
214 "Try \"silent-bob --call-tags [-L] <files>\"\n");
220 printf ("Can't make tags file. Maybe you do not have write permissions ?\n");
230 void bug_plugin (char *name
)
232 fprintf (stderr
, "Can't load plugin (%s)\n", name
);
235 void bug_notsupported ()
237 printf ("SilentBob (or language plugin)"
238 " don't support this feature !\n");
241 bool bob_tag (char *d_str
, char * d_name
, d_tag_t
* d_tag
)
247 strcpy (m_buf
, d_str
);
250 strncpy (d_tag
->d_name
, d_name
, 255);
251 d_tag
->d_name
[255] = 0;
252 S
= strchr (d_str
, '\t');
258 S
= strchr (d_file
, '\t');
263 strncpy (d_tag
->d_file
, d_file
, 255);
264 d_tag
->d_file
[255] = 0;
269 d_tag
->d_line
= atoi (S
);
276 char * cts (struct c_word
* d_word
)
284 if (!strncmp (S
, "else ", 5))
287 if (d_word
->ch
!= '(')
290 while (!strncmp (S
, "do ", 3))
293 if (!strncmp (S
, "return ", 7))
296 if (ENV
->d_cops
->sfind (S
) != -1)
299 if (words_count (S
) != 1)
305 bool def_test (char * d_op
)
309 while (*S
== ' ' || *S
== '\t')
312 if (! strncmp (S
, "define", 6))
319 find_one_ext ((char *) "*.h");
320 find_one_ext ("*.hpp");
321 find_one_ext ("*.cpp");
322 find_one_ext ("*.c");
323 find_one_ext ("*.cc");
324 find_one_ext ("*.cxx");
328 int sblib_find (const char * path
, const char * name
, const char * f_outname
)
337 devnull
= open ("/dev/null", O_WRONLY
, 0600);
338 fd
= open (f_outname
, O_WRONLY
, 0600);
340 fd
= open (f_outname
, O_WRONLY
| O_CREAT
, 0600);
346 lseek (fd
, 0, SEEK_END
);
349 execlp ("find", path
, "-name", name
, NULL
);
350 } else if (pid
> 0) {
351 waitpid (pid
, &status
, 0);
358 # define TMP_FILE_NAME (char *) "./silent_bob.tmp"
359 struct tt_state_t
* get_onett_tag (char * f_name
, char ** d_tt_buf
)
362 tt_state_t
* Ret
= NULL
;
368 d_array
.add (f_name
);
369 Ret
= CNEW (tt_state_t
, 1);
371 unlink (TMP_FILE_NAME
);
372 tags (&d_array
, TMP_FILE_NAME
);
375 if (access (TMP_FILE_NAME
, R_OK
) != 0)
378 Ret
->fileName
= strdup (TMP_FILE_NAME
);
379 S
= THE_TT::do_tt_file (Ret
);
385 munmap (Ret
->fileData
, Ret
->fileDataSize
);
393 unlink (TMP_FILE_NAME
);
398 unlink (TMP_FILE_NAME
);
402 void globalsPrint (tt_state_t
* tt
, char * d_out
, int d_found_type
)
407 if (SB_FLGET (SB_FLSIMULATE
))
410 if (d_found_type
& OT::Other
)
413 t_line
= tt
->attachment
[ENV
->t_op_no
].pair_line
+1;
414 t_line
+= ww_begin_line (tt
, d_out
,
415 tt
->attachment
[ENV
->t_op_no
].offset
);
417 if (SB_FLGET(SB_FLTAGSTYLE
))
418 mk_tag (d_out
, tt
->fileName
,
419 t_line
, d_found_type
);
421 if (d_found_type
& OT::Class
) {
422 S
= strchr (d_out
, ':');
429 printf ("%s\t\t//file %s //line %i\n", d_out
,
430 tt
->fileName
, t_line
);
438 EArray
* got_tag (char * d_tag
)
440 struct d_tag_t
*d_new_tag
;
449 if (ENV
->d_tags_file
== NULL
) {
450 ENV
->d_tags_file
= new EArray
;
451 ENV
->d_tags_file
->from_file ((char *) "./tags");
454 snprintf (d_buf
, 255, "%s\t", d_tag
);
455 d_len
= strlen (d_buf
);
457 if (ENV
->d_tags_file
->get_size () == 0)
460 i
= ENV
->d_tags_file
->snfind_fast (d_buf
, strlen (d_buf
));
463 fprintf (ENV
->d_stream_dbg
, "\tENV->d_tags_file->snfind_fast == -1"); LN
;
467 d_len
= strlen (d_buf
);
470 S
= ENV
->d_tags_file
->get (i
);
473 } while (! strncmp (S
, d_buf
, d_len
));
477 S
= ENV
->d_tags_file
->get (i
);
478 fprintf (ENV
->d_stream_dbg
, "\ttag : %s\n", S
); fflush (ENV
->d_stream_dbg
);
480 d_new_tag
= CNEW (d_tag_t
, 1);
481 memset (d_new_tag
, 0, sizeof (d_tag_t
));
482 if (strstr (S
, ";\tf"))
483 d_new_tag
->d_type
= OT::Function
;
485 if (bob_tag (S
, d_tag
, d_new_tag
) == false) {
487 fprintf (ENV
->d_stream_dbg
, "\tBAD tag : %s\n", S
);
491 d_ret
->add ((long) d_new_tag
);
497 S
= ENV
->d_tags_file
->get (i
);
498 if (strncmp (S
, d_tag
, strlen (d_tag
)))
505 char * macro_name (char * d_op
, char * d_macro_name
)
511 strncpy (m_buf
, d_op
, 255);
514 S
= strstr (m_buf
, "define");
527 S
= strchr (d_begin
, ' ');
531 S
= strchr (d_begin
, '(');
535 strcpy (d_macro_name
, d_begin
);
539 void mk_tag_macro (char * d_op
, char * d_file
, int t_line
)
543 if (! macro_name (d_op
, S
))
546 printf ("%s\t%s\t%i\n", S
, d_file
, t_line
);
549 void mk_tag (char * d_op
, char * d_file
, int line
, int d_found_type
)
551 char * d_format
= (char *) "%s\t%s\t%i\n";
554 if (d_found_type
& OT::Define
) {
555 mk_tag_macro (d_op
, d_file
, line
);
559 if (d_found_type
& OT::Class
) {
560 S
= strchr (d_op
, ':');
565 S
= ww_last_word (d_op
);
566 if (! S
|| !(*S
) || (*S
== ' '))
570 if (! strncmp (S
, "static", 6))
572 if (! strncmp (S
, "struct", 6))
576 if (*S
== 'u' && !strncmp (S
, "union", 5))
578 if (*S
== 'e' && !strncmp (S
, "enum", 4))
581 if (d_found_type
& OT::Function
)
582 d_format
= (char *) "%s\t%s\t%i\t;\tf\n";
583 else if (d_found_type
& OT::Class
)
584 d_format
= (char *) "%s\t%s\t%i\t;\tc\n";
585 else if (d_found_type
& OT::Struct
)
586 d_format
= (char *) "%s\t%s\t%i\t;\ts\n";
588 printf (d_format
, S
, d_file
, line
);
591 DArray
* mk_tag_structtail_split (char *S
)
593 bool b_macro
= false;
598 d_array
= new DArray (128);
605 if (*S
== '\"' || *S
== '\'') {
607 if (S
== NULL
|| *S
== '\0')
624 d_array
->add (d_old
);
639 if (*S
== ' ' || *S
== ',') {
643 while (*S
== ' ' || *S
== '*')
646 d_array
->add (d_old
);
657 void mk_tag_structtail (char * S
, char * d_file
, int t_line
)
663 d_array
= mk_tag_structtail_split (S
);
667 for (i
= 0; i
< d_array
->get_size (); i
++) {
668 w
= ww_last_word (d_array
->get (i
));
669 if (! w
|| !(*w
) || *w
== ' ')
671 printf ("%s\t%s\t%i\n", w
, d_file
, t_line
);
677 void mk_tags (char *f_name
, DArray
*d_in
)
680 DArray
* d_array
= NULL
;
687 d_array
= new DArray (1024);
688 d_array
->from_file (ENV
->tmp_tags
);
692 d_size
= d_array
->get_size ();
693 heap
= new DHeapSort (d_size
);
695 for (i
= 0; i
< d_size
; ++i
)
696 heap
->add (d_array
->get (i
));
698 my_file
= fopen (f_name
, "w");
699 if (my_file
== NULL
) {
700 fprintf (stderr
, "file %s:\n", f_name
);
705 fprintf (my_file
, "!_TAG_FILE_FORMAT\t2\n");
706 fprintf (my_file
, "!_TAG_FILE_SORTED\t1\n");
707 fprintf (my_file
, "!_TAG_PROGRAM_AUTHOR\tOleg Puchinin (graycardinalster@gmail.com)\n");
708 fprintf (my_file
, "!_TAG_PROGRAM_NAME\tSilent Bob\n");
709 fprintf (my_file
, "!_TAG_PROGRAM_URL\thttp://sf.net/projects/silentbob\n");
710 fprintf (my_file
, "!_TAG_PROGRAM_VERSION\t1.6\n");
712 while ((S
= heap
->extract_min ()) && S
)
713 fprintf (my_file
, "%s", S
);
716 d_array
->foreach (free
);
724 char * name2obj (char * name
)
730 strcpy (m_buf
, name
);
731 S
= rindex (m_buf
, '.');
735 return strdup (m_buf
);
739 bool brace_count (char * d_str
, int * d_count
, bool b_force_block
) // "nice"
743 if (! d_str
|| ! d_count
)
746 while (*d_str
!= 0) {
747 if (!strncmp (d_str
, "/*", 2)) {
754 if (strncmp (d_str
, "*/", 2)) {
759 b_in_comment
= false;
764 if (!strncmp (d_str
, "//", 2))
767 if (*d_str
== '\"' || *d_str
== '\'') {
768 d_str
= sstrend (d_str
);
769 if (d_str
== NULL
|| *d_str
== 0) {
770 assert (true, "HimTeh 4");
785 if (*d_str
== ';' && *d_count
== 0 && !b_force_block
) {
795 void nogui_fdump (struct fdump_param_t
* d_param
)
804 if (!d_array
.from_file (d_param
->d_file_name
))
807 if (d_param
->d_file_output
== NULL
)
810 d_file
= fopen (d_param
->d_file_output
, "w");
815 if (! d_param
->linear
) {
816 for (a
= 0; a
< d_param
->n_trip
; a
++)
817 fprintf (d_file
, "\t");
818 fprintf (d_file
, "//<***>\n");
821 i
= d_param
->d_line
-1;
822 d_size
= d_array
.get_size ();
823 b_in_comment
= false;
825 if (d_array
.get (i
)[0] != '#') {
827 if (!d_param
->linear
) {
828 for (a
= 0; a
< d_param
->n_trip
; a
++)
829 fprintf (d_file
, "\t");
831 fprintf (d_file
, "%s", d_array
.get(i
));
833 if (brace_count (d_array
.get(i
), &d_count
, d_param
->b_force_block
) && !d_count
)
836 if (!d_count
&& ((i
- d_param
->d_line
) > 2) && !d_param
->b_force_block
)
844 fprintf (d_file
, "%s", S
);
845 S
= &S
[strlen (S
)-2];
846 while ((*S
== ' ') || (*S
== '\t'))
852 } while (i
< d_size
);
855 if (!d_param
->linear
) {
856 for (a
= 0; a
< d_param
->n_trip
; a
++)
857 fprintf (d_file
, "\t");
858 fprintf (d_file
, "//</***>\n");
861 if (d_param
->d_file_output
!= NULL
)
864 d_array
.foreach (free
);
868 /* code for "linear" functionality, */
869 void nogui_tagsdump (char * f_name
, int n_trip
) {
872 struct fdump_param_t d_param
;
875 d_tags
= got_tag (f_name
);
877 assert (d_tags
->get_size () == 0, "HimTeh 1");
878 for (i
= 0; i
< d_tags
->get_size (); i
++) {
879 d_tag
= (d_tag_t
*) d_tags
->get (i
);
881 fputc ('\n', stdout
);
883 if (!SB_FLGET(SB_FLLINEAR
)) {
884 for (a
= 0; a
< n_trip
; a
++)
885 fputc ('\t', stdout
);
888 printf ("// file %s line %i\n", d_tag
->d_file
, d_tag
->d_line
);
890 memset (&d_param
, 0, sizeof (struct fdump_param_t
));
891 d_param
.n_trip
= n_trip
;
892 d_param
.d_file_name
= d_tag
->d_file
;
893 d_param
.d_line
= d_tag
->d_line
;
894 d_param
.linear
= SB_FLGET (SB_FLLINEAR
);
895 if (d_tag
->d_type
& OT::Function
)
896 d_param
.b_force_block
= true;
897 nogui_fdump (&d_param
);
900 d_tags
->foreach (free
);
905 void opMacro (char ** d_ptr
, char ** d_out
, char ch
)
912 macro_start
= *d_out
;
917 if ((ch
== '\n') && (d_my
[strlen (d_my
) - 1] != '\\'))
923 ch
= t_op (d_ptr
, d_out
);
931 int remove_tmp_files ()
936 for (i
= 0; i
< ENV
->max_proc
; ++i
) {
937 sprintf (m_buf
, "%s%i", ENV
->tmp_files
, i
);
941 unlink (ENV
->tmp_files
);
942 unlink (ENV
->tmp_tags
);
943 return ENV
->max_proc
;
946 void setParam (char *opt
)
954 S
= index (m_buf
, '=');
962 ENV
->settings
->set (m_buf
, strdup (S
));
965 int split_tmp_files ()
972 f_tmpfiles
= fopen (ENV
->tmp_files
, "r");
976 proc_files
= CNEW (FILE *, ENV
->max_proc
);
977 memset (proc_files
, 0, sizeof (FILE *) * ENV
->max_proc
);
979 for (i
= 0; i
< ENV
->max_proc
; ++i
) {
980 sprintf (m_buf
, "%s%i", ENV
->tmp_files
, i
);
982 proc_files
[i
] = fopen (m_buf
, "w");
983 if (! proc_files
[i
]) {
990 while (fgets (m_buf
, 512, f_tmpfiles
)) {
991 fprintf (proc_files
[i
], "%s", m_buf
);
992 if (++i
>= ENV
->max_proc
)
996 for (i
= 0; i
< ENV
->max_proc
; ++i
)
997 fclose (proc_files
[i
]);
999 return ENV
->max_proc
;
1002 DArray
* split_to_words (char * d_op
)
1004 DArray
* d_Ret
= new DArray (16);
1005 char * d_old
= strdup (d_op
);
1006 bool b_done
= false;
1011 if (d_Ret
== NULL
|| d_old
== NULL
)
1022 if (!(if_abc(d_end
) ||
1033 goto split_to_words_L1
;
1037 if (d_end
[-1] == ' ')
1042 while (*S
&& *S
== ' ')
1046 d_Ret
->add (LPCHAR(new_cword (S
, ch
)));
1051 if (ch
== '\"' || ch
== '\'') {
1053 d_end
= sstrend (d_end
);
1054 assert (d_end
== NULL
, "Lena 1");
1055 if (*d_end
== '\0' || *(++d_end
) == '\0')
1066 char * sstrend (char * d_ptr
)
1068 bool t_instring
= false;
1072 unsigned limit
= 1024;
1083 while (*d_ptr
&& (limit
> 0)) {
1084 if (*d_ptr
== '\'' || *d_ptr
== '\"') {
1085 if (t_instring
&& *d_ptr
!= ch_last
) {
1091 if (d_ptr
[-1] == '\\') {
1093 while (d_ptr
[-(d_slash_count
)] == '\\')
1096 if (d_slash_count
& 1)
1124 char * sstrkill (char *OP
)
1134 if (*S
== '\"' || *S
== '\'') {
1139 if (*tail
== '\0' ||*(tail
+1) == '\0') {
1153 int words_count (char *S
)
1155 bool b_begin
= true;
1180 if (!(if_abc (S
) || (*S
== '_')
1181 || (*S
== '*') || (if_digit (S
))))
1192 int ww_begin_line (struct tt_state_t
* d_tt_state
, char *d_out
, int d_offset
)
1194 char *S
= &d_tt_state
->fileData
[d_offset
] - 1;
1195 char * d_end
= &d_out
[strlen (d_out
)] - 1;
1198 while (d_end
> d_out
) {
1199 if (*d_end
== ' ' || *d_end
== '\t') {
1200 while ((S
>= d_tt_state
->fileData
) && (*S
== ' ' || *S
== '\t'))
1203 if (S
< d_tt_state
->fileData
)
1206 while ((d_end
>= d_out
) && (*d_end
== ' ' || *d_end
== '\t'))
1227 char * ww_begin_offset (struct tt_state_t
* d_tt_state
, char *d_out
, int d_offset
)
1229 char *S
= &d_tt_state
->fileData
[d_offset
] - 1;
1230 char * d_real
= &d_out
[strlen (d_out
)] - 1;
1232 while (d_real
!= d_out
) {
1233 if (*d_real
== ' ' || *d_real
== '\t') {
1234 while (*S
== ' ' || *S
== '\t')
1237 while ((*d_real
== ' ' || *d_real
== '\t')
1238 && (d_real
!= d_out
))
1253 char * ww_last_word (char *d_op
)
1259 if (*S
== '(' || *S
== '=' || *S
== '[')
1270 S
= strchr (d_word
, ' ');
1276 while (*d_word
== '*' ||
1284 bool validOption (char *Name
)
1290 S
= ENV
->listOptions
->first ();
1294 S
= ENV
->listOptions
->next ();
1299 int lastPluginID
= 0;
1302 return ++lastPluginID
;