Line data Source code
1 : /* This file (just.cc) was created by Ron Rechenmacher <ron@fnal.gov> on
2 : // Feb 19, 2014. "TERMS AND CONDITIONS" governing this file are in the README
3 : // or COPYING file. If you do not have such a file, one can be obtained by
4 : // contacting Ron or Fermi Lab in Batavia IL, 60510, phone: 630-840-3000.
5 : // $RCSfile: just_user.cc,v $
6 : */
7 : char const *rev= "$Revision: 1784 $$Date: 2026-10-09 13:51:46 -0500 (Fri, 09 Oct 2026) $";
8 :
9 : #include <stdarg.h> // va_list
10 : #include <string>
11 : #include <getopt.h> // getopt_long, {no,required,optional}_argument, extern char *optarg; extern int opt{ind,err,opt}
12 : #include <sstream>
13 : #include <ios>
14 : #include <iostream> // std::cout
15 : #include <typeinfo> // typeid().name()
16 : #include <libgen.h> // basename
17 : #include <stdlib.h>
18 : #include <stdint.h> // uint16_t
19 :
20 : #if 1 // set to 0 to test trace.h TRACE_LOG_FUNCTION
21 : void my_log(uint16_t nargs, std::string msg, ...);
22 0 : void my_log2(timeval *, int, unsigned char, const char *, const char *, int, const char *, short unsigned int nargs,
23 : const char *msg, ...)
24 : {
25 0 : va_list ap;
26 0 : va_start(ap, msg);
27 0 : my_log(nargs, msg, ap);
28 0 : va_end(ap);
29 0 : }
30 0 : void my_log2(timeval *, int, unsigned char, const char *, const char *, int, const char *, short unsigned int nargs,
31 : std::string msg, ...)
32 : {
33 0 : va_list ap;
34 0 : va_start(ap, msg);
35 0 : my_log(nargs, msg, ap);
36 0 : va_end(ap);
37 0 : }
38 : # define TRACE_LOG_FUNCTION my_log2
39 : #endif
40 :
41 : #include "TRACE/trace.h" // TRACE
42 :
43 : #define USAGE \
44 : "\
45 : usage: %s [-t <test>]\n\
46 : \n\
47 : example: %s -t_\n\
48 : %s\n\
49 : \n\
50 : options:\n\
51 : --help\n\
52 : -t<test>\n\
53 : ", \
54 : basename(argv[0]), basename(argv[0]), basename(argv[0])
55 : #define VUSAGE "\n"
56 :
57 : // GLOBALS
58 : static int opt_v= 0;
59 : static char const *opt_test= "";
60 : static int opt_loops= 10000;
61 :
62 : // Note: "static" is good practice as compiler will warn when not used.
63 : // "_" at need to distinguish my functions from other library functions.
64 0 : static void parse_args_(int argc, char *argv[])
65 : {
66 : // parse opt, optargs, and args
67 0 : while (1) {
68 0 : int opt;
69 0 : static struct option long_options[]= {
70 : // name has_arg *flag val
71 : {"help", no_argument, 0, 'h'},
72 : {"verbose", optional_argument, 0, 'v'}, // --verbose can take optional arg (not so for just -v, so -vvv is allowed)
73 : {0, 0, 0, 0}};
74 0 : opt= getopt_long(argc, argv, "?hvVl:t:", // optional args use "::". NOTE: -v has no arg but --verbose can have optional
75 : long_options, NULL);
76 0 : if (opt == -1) break;
77 0 : switch (opt) {
78 0 : case '?':
79 0 : case 'h':
80 0 : printf(USAGE);
81 0 : if (opt_v) printf(VUSAGE);
82 0 : exit(0);
83 0 : break;
84 0 : case 'V':
85 0 : printf("%s\n", rev);
86 0 : exit(0);
87 0 : break;
88 0 : case 'v':
89 0 : if (optarg) opt_v= (int)strtoul(optarg, 0, 0);
90 : else
91 0 : ++opt_v;
92 : break; // optional is for when coming from long option
93 0 : case 'l': opt_loops= (int)strtoul(optarg, NULL, 0); break;
94 0 : case 't': opt_test= optarg; break;
95 0 : default: printf("?? getopt returned character code 0%o ??\n", opt); exit(1);
96 : }
97 : }
98 0 : }
99 :
100 : SUPPRESS_NOT_USED_WARN
101 0 : void my_log(uint16_t nargs, const char *msg, ...)
102 : {
103 0 : va_list ap;
104 0 : va_start(ap, msg);
105 0 : if (nargs) vprintf(msg, ap);
106 : else
107 0 : printf("%s", msg);
108 0 : printf("\n");
109 0 : va_end(ap);
110 0 : }
111 : SUPPRESS_NOT_USED_WARN
112 0 : void my_log(uint16_t nargs, std::string msg, ...)
113 : {
114 0 : va_list ap;
115 0 : va_start(ap, msg);
116 0 : if (nargs) vprintf(msg.c_str(), ap);
117 : else
118 0 : printf("%s", msg.c_str());
119 0 : printf("\n");
120 0 : va_end(ap);
121 0 : }
122 :
123 0 : void test(std::ostream &arg)
124 : {
125 0 : std::cout << "test start\n";
126 0 : std::ostringstream &os= dynamic_cast<std::ostringstream &>(arg);
127 0 : std::cout << os.str() << "\n";
128 0 : std::cout << "test done\n";
129 0 : }
130 :
131 : // this doesn't work with test( ostr << '\n' )
132 0 : void test(std::ostringstream &arg)
133 : {
134 0 : std::cout << "test start\n";
135 0 : std::cout << arg.str() << "\n";
136 0 : std::cout << "test done\n";
137 0 : }
138 :
139 0 : int main(int argc, char *argv[])
140 : {
141 0 : parse_args_(argc, argv);
142 0 : std::string stdstr("hello my name is");
143 0 : std::ostringstream ostr("inital characters123");
144 0 : char const *filename= "some/path";
145 0 : std::string fname("some/path2");
146 :
147 0 : if (strcmp(opt_test, "") == 0) {
148 0 : std::cout << "hello\n";
149 : //TRACE(1,std::cout << "hello"); // THIS prints hello to screen and an address -- not useful
150 :
151 0 : TRACE(0, "hello - hopefully no compile warnings %d %.1f %d", 1, 1.5, 2);
152 0 : TRACE(0, "hello - hopefully no compile warnings %d %.1f %d", 1, 1.5, 3);
153 :
154 0 : TLOG_DBG(1, "TRACE") << stdstr << " ron";
155 0 : TRACE(1, "ron is my name.");
156 :
157 : // now with args
158 : //TRACE_( 1, stdstr << " ron %d", 1 );
159 0 : TRACE(1, "ron is my name.");
160 0 : TLOG_DBG(1, "TRACE") << "hello - nice for strings: file=" << filename << " " << 1 << " " << 1.6 << " " << 2;
161 0 : TRACE(1, "hello - nice for strings: file=" + fname + " %d %.1f %d", 1, 1.6, 2);
162 0 : TLOG_DBG(1, "TRACE") << "hello - hopefully no compile warnings " << 1 << " " << 1.6 << " " << std::hex << 15;
163 :
164 0 : std::cout << "\n";
165 :
166 : //FILE *fp(popen("head -107 $HOME/.bashrc", "r")); // 107 lines is 4025 chars - works
167 : //FILE *fp(popen("head -108 $HOME/.bashrc", "r")); // 108 lines is 4192 chars - works
168 : //FILE *fp(popen("head -115 $HOME/.bashrc", "r")); // 115 lines is 4754 chars - works
169 0 : FILE *fp(popen("head -525 $HOME/.bashrc", "r")); // 525 lines is 22843 chars - crash
170 : //FILE *fp(popen("head -170 $HOME/.bashrc", "r")); // 170 lines is 8258 chars - works
171 : //FILE *fp(popen("head -300 $HOME/.bashrc", "r")); // works
172 : //FILE *fp(popen("head -400 $HOME/.bashrc", "r")); // crash
173 : //FILE *fp(popen("head -350 $HOME/.bashrc", "r")); // works
174 : //FILE *fp(popen("head -375 $HOME/.bashrc", "r")); // works
175 : //FILE *fp(popen("head -388 $HOME/.bashrc", "r")); // crash
176 : //FILE *fp(popen("head -382 $HOME/.bashrc", "r")); // crash
177 : //FILE *fp(popen("head -378 $HOME/.bashrc", "r")); // works 378 lines is 16664
178 : //FILE *fp(popen("head -380 $HOME/.bashrc", "r")); // crash
179 : //FILE *fp(popen("head -379 $HOME/.bashrc", "r")); // crash 379 lines in 16742 -- line 379 has HISTTIMEFORMAT="%a %m/%d %H:%M:%S "
180 : //FILE *fp(popen("cat $HOME/t.t", "r")); // 63125 KB of lines of 100 chars 123456... - works
181 0 : std::string result;
182 0 : if (fp) {
183 : char buffer[128];
184 0 : while (!feof(fp)) {
185 0 : if (fgets(buffer, 128, fp) != NULL) result+= buffer;
186 : }
187 0 : TLOG_DBG(1, "TRACE") << "bashrc: " << result;
188 0 : pclose(fp);
189 : }
190 :
191 0 : ostr << "<< stdstr (just to confuse) %d" << stdstr;
192 0 : std::cout << ostr.str() << "\n";
193 0 : test(ostr);
194 0 : test(ostr << "test function passed ostr<<\"string\"\n");
195 :
196 : #if defined(__cplusplus) && (__cplusplus > 201103L)
197 : # if 0
198 : test( (std::ostringstream)"cast (std::ostringstream)\"str\"<<\"str\"" << "jkl;\n" ); // gives address
199 : test( std::ostringstream("asdf") << "std::ostringstream(\"asdf\")<<\"string\"\n" ); // also gives address
200 : # endif
201 : #endif
202 :
203 : //std::cout << typeid( std::ostringstream("asdf") << "xyz\n" ).name() << '\n';
204 0 : test(std::ostringstream("asdf").flush() << "xyz\n"); // gives desired output
205 :
206 0 : std::cout << "\nXXXX\n";
207 :
208 : //TRACE_( 1, ostr, 1 ); // an address (also the 1 param is extra)
209 0 : TRACE(1, ostr.str(), 1);
210 :
211 0 : std::cout << "\n";
212 :
213 : //TRACE( 1, ostr <<"I would like to see what is it, not it's address", 1 ); // THIS prints to the screen and prints an address -- not useful
214 : //TRACE_( 1, (ostr<<"xx").str(), 2 ); these shenanigans don't compile
215 :
216 0 : TRACE(0, "hello - hopefully no compile warnings %d %.1f %d", 1, 1.7, 2);
217 0 : TRACE(0, "hello - hopefully no compile warnings %d %.1f %d", 1, 1.7, 3);
218 :
219 0 : TRACE(1,
220 : "%d %d %d %d %d %d %d %d %d %d "
221 : "%d %d %d %d %d %d %d %d %d %d "
222 : "%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d",
223 : 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32,
224 : 33, 34, 35);
225 0 : TRACE(1,
226 : "%d %d %d %d %d %d %d %d %d %d "
227 : "%d %d %d %d %d %d %d %d %d %d "
228 : "%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d",
229 : 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69,
230 : 70, 71, 72, 73, 74, 75);
231 0 : TLOG(1) << 0 << " " << 1 << " " << 2 << " " << 3 << " " << 4 << " " << 5 << " " << 6 << " " << 7 << " " << 8 << " " << 9
232 0 : << " " << 10 << " " << 11 << " " << 12 << " " << 13 << " " << 14 << " " << 15 << " " << 16 << " " << 17 << " " << 18
233 0 : << " " << 19 << " " << 20 << " " << 21 << " " << 22 << " " << 23 << " " << 24 << " " << 25 << " " << 26 << " " << 27
234 0 : << " " << 28 << " " << 29 << " " << 30 << " " << 31 << " " << 32 << " " << 33 << " " << 34;
235 0 : } else if (strcmp(opt_test, "<") == 0) {
236 0 : while (opt_loops--) { TLOG_DBG(0, "TRACE") << "this is an int: " << 55; }
237 0 : } else if (strcmp(opt_test, "C") == 0) {
238 0 : while (opt_loops--) { TRACE(0, "this is an int: %d", 55); }
239 : #if defined(__GXX_EXPERIMENTAL_CXX0X__) || __cplusplus >= 201103L
240 0 : } else if (strcmp(opt_test, "S") == 0) {
241 0 : while (opt_loops--) {
242 0 : TRACE(0,
243 : "this is an int: " +
244 : std::to_string(
245 : 55LL)); // this does same/similar thing as "<<" into stream (but without the stream constructor overhead
246 : }
247 : #endif
248 : } else {
249 0 : printf("invalid -t option %s (could be because of compiler version used)\n", opt_test);
250 : }
251 :
252 0 : return (0);
253 0 : } // main
|