00001
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 #include <stdio.h>
00036 #include <stdlib.h>
00037 #include <unistd.h>
00038 #include <string.h>
00039 #include <strings.h>
00040 #include <sys/time.h>
00041 #include <ctype.h>
00042 #include <wait.h>
00043 #include <limits.h>
00044
00045 #ifndef GCC
00046 #define GCC "/usr/bin/gcc"
00047 #endif
00048
00049 #define FILENAME_LEN 24
00050 #define MAX_OBJ_FILES 512
00051
00052 static const char *gcc_path = GCC;
00053 static const char *include_dirs[] = { "-I" PREFIX "/include", "-I.", NULL };
00054 static const char *library_dirs[] = { "-L" PREFIX "/lib", NULL };
00055 static const char *additional_libs[] = { "-lipc", "-lpthread", NULL };
00056 static const char *my_app;
00057 static char *additional_objects[MAX_OBJ_FILES + 1];
00058
00059
00060 inline static int usage(void)
00061 {
00062 fprintf(stderr, "Usage: %s [--with-gcc path to gcc (%s)] "
00063 "[--preserve-c-translation] [multiple gcc options]"
00064 " <input file>\n", my_app, gcc_path);
00065 return -1;
00066 }
00067
00068
00069 inline static int no_input(void)
00070 {
00071 fprintf(stderr, "%s: no input files\n", my_app);
00072 return -1;
00073 }
00074
00075
00076 inline static int no_file(char *name)
00077 {
00078 char msg[PATH_MAX];
00079 sprintf(msg, "%s: %s", my_app, name);
00080 perror(msg);
00081 return -1;
00082 }
00083
00084
00085 static int local_file_with_c(char *dot_h)
00086 {
00087 char path[PATH_MAX + 1];
00088 int filename_len;
00089 char *end, dot_c[PATH_MAX + 1];
00090 strncpy(dot_c, dot_h, PATH_MAX);
00091 if ((end = index(dot_c, '.')) == NULL)
00092 return 0;
00093 *(end+1) = 'c';
00094 *(end+2) = '\0';
00095 filename_len = strlen(dot_c);
00096
00097 if (getcwd(path, PATH_MAX - filename_len) == NULL)
00098 return 0;
00099 strcat(path, "/");
00100 strcat(path, dot_c);
00101
00102 if (access(path, R_OK) < 0)
00103 return 0;
00104 return 1;
00105 }
00106
00107
00108 static char *rtrim(char *string)
00109 {
00110 if (string != NULL) {
00111 char *end = string;
00112 while (*(end+1) != '\0')
00113 end++;
00114
00115 while (end >= string && isspace(*end)) {
00116 *end = '\0';
00117 end--;
00118 }
00119 }
00120 return string;
00121 }
00122
00123
00124 static char *ltrim(char *string)
00125 {
00126 if (string != NULL) {
00127 char *end = string;
00128 while (*(end+1) != '\0')
00129 end++;
00130
00131 while (string <= end && isspace(*string))
00132 string++;
00133 }
00134 return string;
00135 }
00136
00137
00138 static char *trim(char *string)
00139 {
00140 return rtrim(ltrim(string));
00141 }
00142
00143
00144 static char *next_ws(char *string)
00145 {
00146 char *end = string;
00147 while (!isspace(*end) && *end != ')'
00148 && *end != ';' && *end != ']')
00149 end++;
00150 return end;
00151 }
00152
00153
00154 static char *skip_ws(char *string)
00155 {
00156 char *end = string;
00157 while (isspace(*end))
00158 end++;
00159 return end;
00160 }
00161
00162
00163 static char *get_sensor_main(void)
00164 {
00165 return "}\n"
00166 "\n"
00167 "\n"
00168 "int main(int argc, char *argv[])\n"
00169 "{\n"
00170 " if (argc != 3)\n"
00171 " fprintf(stderr, \"Usage: %%s"
00172 " <data port> <cmd port>\", argv[0]);\n"
00173 " ipc_data_port = atoi(argv[1]);\n"
00174 " ipc_cmd_port = atoi(argv[2]);\n"
00175 "\n"
00176 " initialize_ipc(-1);\n"
00177 "\n"
00178 " while (!quitting()) {\n"
00179 " sensor_app();\n"
00180 " }\n"
00181 " pthread_join(data_thread, NULL);\n"
00182 " pthread_join(cmd_thread, NULL);\n"
00183 "\n"
00184 " return 0;\n"
00185 "}\n"
00186 "\n";
00187 }
00188
00189
00190 static char *my_mktemp(char *string)
00191 {
00192 if (string != NULL) {
00193 while (*string != '\0') {
00194 if (*string == 'X') {
00195 try_again:
00196 *string = '0' + (char)((double)'z' *
00197 ((double)random() /
00198 (RAND_MAX + (double)'0')));
00199 if (!isalnum(*string))
00200 goto try_again;
00201 }
00202 string++;
00203 }
00204 }
00205 return string;
00206 }
00207
00208
00209 static void transform(FILE *infile, FILE *outfile)
00210 {
00211 unsigned int app_def = 0;
00212 unsigned int incl_def = 0;
00213 unsigned int brace_count = 0;
00214 int obj = 0, line_len = 512;
00215 char line[line_len];
00216
00217 while (fgets(line, line_len, infile) != NULL) {
00218 char new_line[2048];
00219 char *cur_in = line;
00220 char *cur_out = new_line;
00221 char unused[256];
00222 int spaces = 0;
00223
00224 memset(new_line, '\0', 1024);
00225 while (*cur_in != '\0') {
00226 if (*cur_in == '\n') {
00227 cur_in++;
00228 spaces = 0;
00229 } else if (*cur_in == '{') {
00230 brace_count++;
00231 *cur_out++ = *cur_in++;
00232 spaces = 0;
00233 } else if (isspace(*cur_in)) {
00234 spaces++;
00235 *cur_out++ = *cur_in++;
00236 } else if (*cur_in == '}') {
00237 brace_count--;
00238 cur_in++;
00239 if (app_def > 0 && brace_count == 0) {
00240 sprintf(cur_out, get_sensor_main());
00241 cur_out += strlen(cur_out);
00242 } else
00243 *cur_out++ = '}';
00244 spaces = 0;
00245 } else if (*cur_in == ']') {
00246 cur_in++;
00247 *cur_out++ = ')';
00248 spaces = 0;
00249 } else if (strncmp(cur_in, "incl:", 5) == 0) {
00250 char dot_h[PATH_MAX];
00251 char *file = index(cur_in, ':');
00252 file++;
00253 sprintf(dot_h, "%s", trim(file));
00254 sprintf(cur_out, "#include <%s>", dot_h);
00255
00256 if (local_file_with_c(dot_h) &&
00257 obj < MAX_OBJ_FILES) {
00258 char *end, *dot_o =
00259 (char*) malloc(PATH_MAX + 1);
00260 snprintf(dot_o, PATH_MAX,
00261 "%s", trim(file));
00262 end = index(dot_o, '.');
00263 *(end+1) = 'o';
00264 *(end+2) = '\0';
00265 additional_objects[obj++] = dot_o;
00266 }
00267 break;
00268 } else if (strncmp(cur_in, "decl:", 5) == 0) {
00269 char *vars = index(cur_in, ':');
00270 vars++;
00271 sprintf(cur_out, "long %s", trim(vars));
00272 if (incl_def == 0 && app_def == 0) {
00273 sprintf(cur_out,
00274 "#include <stdio.h>\n"
00275 "#include <stdlib.h>\n"
00276 "#include <ipc.h>\n"
00277 "#include <sensor_app.h>\n\n"
00278 "int long_len ="
00279 " sizeof(long);\n\n");
00280 incl_def++;
00281 cur_out += strlen(cur_out);
00282 }
00283 break;
00284 } else if (strncmp(cur_in, "funct:", 6) == 0) {
00285 char *end, *a_end, *args;
00286 char *name = index(cur_in, ':');
00287 name++;
00288 name = skip_ws(name);
00289 args = next_ws(name);
00290 *args = '\0';
00291 args++;
00292 end = index(args, '{');
00293 *end = '\0';
00294
00295 if (incl_def == 0 && app_def == 0) {
00296 sprintf(cur_out,
00297 "#include <stdio.h>\n"
00298 "#include <stdlib.h>\n"
00299 "#include <ipc.h>\n"
00300 "#include <sensor_app.h>\n\n"
00301 "int long_len ="
00302 " sizeof(long);\n\n");
00303 incl_def++;
00304 cur_out += strlen(cur_out);
00305 }
00306
00307 sprintf(cur_out, "long %s(", trim(name));
00308
00309 do {
00310 a_end = index(args, ',');
00311 if (a_end != NULL)
00312 *a_end = '\0';
00313
00314 strcat(cur_out, "long ");
00315 strcat(cur_out, trim(args));
00316 if (a_end != NULL) {
00317 strcat(cur_out, ", ");
00318 args = a_end + 1;
00319 args = skip_ws(args);
00320 }
00321 } while (a_end != NULL);
00322 strcat(cur_out, ")\n{");
00323 brace_count++;
00324 break;
00325 } else if (strncmp(cur_in, "app:", 4) == 0) {
00326 char *name = NULL, *args = NULL;
00327 char *end = NULL;
00328
00329 name = index(cur_in, ':');
00330 name++;
00331 if (incl_def == 0 && app_def == 0) {
00332 sprintf(cur_out,
00333 "#include <stdio.h>\n"
00334 "#include <stdlib.h>\n"
00335 "#include <ipc.h>\n"
00336 "#include <sensor_app.h>\n\n"
00337 "int long_len ="
00338 " sizeof(long);\n\n");
00339 incl_def++;
00340 cur_out += strlen(cur_out);
00341 }
00342
00343 if ((args = index(name, '(')) != NULL) {
00344 end = index(args, ')');
00345 *args = '\0';
00346 args++;
00347 args = trim(args);
00348 *end = '\0';
00349 end++;
00350 sprintf(cur_out,
00351 "int ipc_data_port,"
00352 " ipc_cmd_port;\n"
00353 "const long %s;\n"
00354 "const char *my_app = \"%s\";"
00355 "\n\nvoid sensor_app()\n{",
00356 trim(args), trim(name));
00357 } else
00358 sprintf(cur_out,
00359 "int ipc_data_port,"
00360 " ipc_cmd_port;\n"
00361 "const char *my_app = \"%s\";"
00362 "\n\nvoid sensor_app()\n{",
00363 trim(name));
00364 app_def++;
00365 brace_count++;
00366 break;
00367 } else if (sscanf(cur_in, "when [ %s", unused) == 1) {
00368 char x, *end, *func, *compare;
00369 char spacing[128];
00370 char *assign = index(cur_in, '[');
00371 assign++;
00372 func = strstr(cur_in, "<-");
00373 *func = '\0';
00374 func += 2;
00375 func = skip_ws(func);
00376 end = next_ws(func);
00377 x = *end;
00378 *end = '\0';
00379 memset(spacing, '\0', 128);
00380 memset(spacing, ' ', spaces);
00381
00382 sprintf(cur_out, "consume(\"%s\","
00383 " (unsigned char*)&%s, &long_len);"
00384 "\n%sif (%s ",
00385 trim(func), trim(assign),
00386 spacing, trim(assign));
00387 *end = x;
00388 cur_in = end;
00389 cur_out += strlen(cur_out);
00390 spaces = 0;
00391 } else if (strncmp(cur_in, "produce:", 8) == 0) {
00392 char x, *end;
00393 char *assign = index(cur_in, ':');
00394 assign++;
00395 assign = skip_ws(assign);
00396 end = next_ws(assign);
00397 x = *end;
00398 *end = '\0';
00399
00400 sprintf(cur_out, "produce(Soap_Long,"
00401 " (unsigned char*)&%s, long_len)",
00402 trim(assign));
00403 *end = x;
00404 cur_in = end;
00405 cur_out += strlen(cur_out);
00406 spaces = 0;
00407 } else if (index(cur_in, ':') != NULL) {
00408 char x, *funct_name, *args, *end;
00409 char *begin, *delim = index(cur_in, ':');
00410
00411 begin = delim-1;
00412 while (isalnum(*begin) || *begin == '_')
00413 begin--;
00414
00415 if (begin == cur_in) {
00416 *cur_out++ = *cur_in++;
00417 continue;
00418 }
00419 funct_name = begin + 1;
00420 *delim = '\0';
00421
00422 end = args = delim + 1;
00423 while (*end != ';')
00424 end++;
00425 x = *end;
00426 *end = '\0';
00427 sprintf(cur_out, "%s(%s)",
00428 trim(funct_name), trim(args));
00429 *end = x;
00430 cur_in = end;
00431 cur_out += strlen(cur_out);
00432 spaces = 0;
00433 } else {
00434 *cur_out++ = *cur_in++;
00435 spaces = 0;
00436 }
00437 }
00438 fprintf(outfile, "%s\n", new_line);
00439 }
00440 }
00441
00442
00443 int main(int argc, char *argv[])
00444 {
00445 unsigned int keep_c = 0;
00446 int i, j = 0, k = 0;
00447 int error, status, verbose = 0;
00448 char *gcc_arg0;
00449 char *gcc_comp_args[ARG_MAX];
00450 char *gcc_link_args[ARG_MAX];
00451 char *in_filename = NULL;
00452 FILE *infile, *outfile;
00453 char *final_executable;
00454 char intermediate_c[FILENAME_LEN + 1] = "";
00455 char intermediate_o[FILENAME_LEN + 1] = "";
00456 struct timeval now;
00457
00458 gettimeofday(&now, NULL);
00459 srandom((unsigned int) now.tv_sec);
00460
00461 my_app = rindex(argv[0], '/');
00462 if (my_app == NULL)
00463 my_app = argv[0];
00464 else
00465 my_app++;
00466
00467 if (argc < 2)
00468 return no_input();
00469
00470 for (i = 0; i < ARG_MAX; i++) {
00471 gcc_comp_args[i] = (char *)0;
00472 gcc_link_args[i] = (char *)0;
00473 }
00474 gcc_comp_args[j++] = gcc_arg0;
00475 gcc_link_args[k++] = gcc_arg0;
00476
00477 for (i = 0; i <= MAX_OBJ_FILES; i++)
00478 additional_objects[i] = NULL;
00479
00480 for (i = 1; i < argc - 1; i++) {
00481 if (strncmp(argv[i], "--with-gcc", 10) == 0)
00482 gcc_path = argv[++i];
00483 else if (strncmp(argv[i], "--preserve-c-translation", 26) == 0)
00484 keep_c++;
00485 else if (strncmp(argv[i], "-o", 2) == 0)
00486 final_executable = argv[++i];
00487 else if (strncmp(argv[i], "-v", 2) == 0) {
00488 verbose++;
00489 gcc_comp_args[j++] = argv[i];
00490 gcc_link_args[k++] = argv[i];
00491 } else if (strncmp(argv[i], "-h", 2) == 0)
00492 return usage();
00493 else if (strncmp(argv[i], "--help", 6) == 0)
00494 return usage();
00495 else {
00496 gcc_comp_args[j++] = argv[i];
00497 gcc_link_args[k++] = argv[i];
00498 }
00499 }
00500 if ((in_filename = argv[argc - 1]) == NULL)
00501 return no_input();
00502
00503 if (keep_c) {
00504 snprintf(intermediate_c, FILENAME_LEN, "%s.c", final_executable);
00505 } else {
00506 strncpy(intermediate_c, "/tmp/sppXXXXXX.c", FILENAME_LEN);
00507 my_mktemp(intermediate_c);
00508 }
00509 strncpy(intermediate_o, "/tmp/sppXXXXXX.o", FILENAME_LEN);
00510 my_mktemp(intermediate_o);
00511
00512 gcc_arg0 = rindex(gcc_path, '/');
00513 if (my_app == NULL)
00514 gcc_arg0 = (char*) gcc_path;
00515 else
00516 gcc_arg0++;
00517
00518 if ((infile = fopen(in_filename, "r")) == NULL)
00519 return no_file(in_filename);
00520 if ((outfile = fopen(intermediate_c, "w")) == NULL)
00521 return no_file((char*)intermediate_c);
00522
00523 transform(infile, outfile);
00524
00525 fclose(infile);
00526 fclose(outfile);
00527
00528
00529 gcc_comp_args[0] = gcc_arg0;
00530 gcc_comp_args[j++] = "-c";
00531 gcc_comp_args[j++] = "-o";
00532 gcc_comp_args[j++] = (char*) intermediate_o;
00533 for (i = 0; include_dirs[i] != NULL; i++)
00534 gcc_comp_args[j++] = (char*) include_dirs[i];
00535 gcc_comp_args[j++] = (char*) intermediate_c;
00536
00537 gcc_link_args[0] = gcc_arg0;
00538 gcc_link_args[k++] = "-static";
00539 gcc_link_args[k++] = "-o";
00540 gcc_link_args[k++] = final_executable;
00541 gcc_link_args[k++] = (char*) intermediate_o;
00542 for (i = 0; additional_objects[i] != NULL; i++)
00543 gcc_link_args[k++] = (char*) additional_objects[i];
00544 for (i = 0; library_dirs[i] != NULL; i++)
00545 gcc_link_args[k++] = (char*) library_dirs[i];
00546 for (i = 0; additional_libs[i] != NULL; i++)
00547 gcc_link_args[k++] = (char*) additional_libs[i];
00548
00549
00550 if (verbose) {
00551 for (i = 0; i < j; i++) {
00552 fprintf(stderr, "%s ", gcc_comp_args[i]);
00553 fflush(stderr);
00554 }
00555 fprintf(stderr, "\n\n");
00556 }
00557
00558
00559 if (!fork()) {
00560 int error = 0;
00561 if ((error = execv(gcc_path, gcc_comp_args)) < 0)
00562 perror(my_app);
00563 exit(-1);
00564 } else
00565 wait(&status);
00566
00567 if (WIFEXITED(status)) {
00568 if ((error = WEXITSTATUS(status)) < 0)
00569 goto end;
00570 } else {
00571 error = -1;
00572 goto end;
00573 }
00574
00575 if (verbose) {
00576 fprintf(stderr, "\n");
00577 for (i = 0; i < k; i++) {
00578 fprintf(stderr, "%s ", gcc_link_args[i]);
00579 fflush(stderr);
00580 }
00581 fprintf(stderr, "\n\n");
00582 }
00583
00584
00585 if (!fork()) {
00586 int error = 0;
00587 if ((error = execv(gcc_path, gcc_link_args)) < 0)
00588 perror(my_app);
00589 exit(-1);
00590 } else
00591 wait(&status);
00592
00593 if (WIFEXITED(status))
00594 error = WEXITSTATUS(status);
00595
00596 end:
00597 for (i = 0; additional_objects[i] != NULL; i++)
00598 free(additional_objects[i]);
00599
00600 if (!keep_c)
00601 unlink(intermediate_c);
00602 unlink(intermediate_o);
00603
00604 return error;
00605 }