/* Parse one Texinfo file and create manpages according to the embedded instructions. */ static void parse_file (const char *fname, FILE *fp, char **section_name, int in_pause) { char *line; int lnr = 0; /* Fixme: The following state variables don't carry over to include files. */ int skip_to_end = 0; /* Used to skip over menu entries. */ int skip_sect_line = 0; /* Skip after @mansect. */ int item_indent = 0; /* How far is the current @item indented. */ /* Helper to define a macro. */ char *macroname = NULL; char *macrovalue = NULL; size_t macrovaluesize = 0; size_t macrovalueused = 0; line = xmalloc (LINESIZE); while (fgets (line, LINESIZE, fp)) { size_t n = strlen (line); int got_line = 0; char *p, *pend; lnr++; if (!n || line[n-1] != '\n') { err ("%s:%d: trailing linefeed missing, line too long or " "embedded Nul character", fname, lnr); break; } line[--n] = 0; /* Kludge to allow indentation of tables. */ for (p=line; *p == ' ' || *p == '\t'; p++) ; if (*p) { if (*p == '@' && !strncmp (p+1, "item", 4)) item_indent = p - line; /* Set a new indent level. */ else if (p - line < item_indent) item_indent = 0; /* Switch off indention. */ if (item_indent) { memmove (line, line+item_indent, n - item_indent + 1); n -= item_indent; } } if (*line == '@') { for (p=line+1, n=1; *p && *p != ' ' && *p != '\t'; p++) n++; while (*p == ' ' || *p == '\t') p++; } else p = line; /* Take action on macro. */ if (macroname) { if (n == 4 && !memcmp (line, "@end", 4) && (line[4]==' '||line[4]=='\t'||!line[4]) && !strncmp (p, "macro", 5) && (p[5]==' '||p[5]=='\t'||!p[5])) { if (macrovalueused) macrovalue[--macrovalueused] = 0; /* Kill the last LF. */ macrovalue[macrovalueused] = 0; /* Terminate macro. */ macrovalue = xrealloc (macrovalue, macrovalueused+1); set_macro (macroname, macrovalue); macrovalue = NULL; free (macroname); macroname = NULL; } else { if (macrovalueused + strlen (line) + 2 >= macrovaluesize) { macrovaluesize += strlen (line) + 256; macrovalue = xrealloc (macrovalue, macrovaluesize); } strcpy (macrovalue+macrovalueused, line); macrovalueused += strlen (line); macrovalue[macrovalueused++] = '\n'; } continue; } if (n >= 5 && !memcmp (line, "@node", 5) && (line[5]==' '||line[5]=='\t'||!line[5])) { /* Completey ignore @node lines. */ continue; } if (skip_sect_line) { skip_sect_line = 0; if (!strncmp (line, "@section", 8) || !strncmp (line, "@subsection", 11) || !strncmp (line, "@chapheading", 12)) continue; } /* We only parse lines we need and ignore the rest. There are a few macros used to control this as well as one @ifset command. Parts we know about are saved away into containers separate for each section. */ /* First process ifset/ifclear commands. */ if (*line == '@') { if (n == 6 && !memcmp (line, "@ifset", 6) && (line[6]==' '||line[6]=='\t')) { for (p=line+7; *p == ' ' || *p == '\t'; p++) ; if (!*p) { err ("%s:%d: name missing after \"@ifset\"", fname, lnr); continue; } for (pend=p; *pend && *pend != ' ' && *pend != '\t'; pend++) ; *pend = 0; /* Ignore rest of the line. */ push_condition (p, 1, fname, lnr); continue; } else if (n == 8 && !memcmp (line, "@ifclear", 8) && (line[8]==' '||line[8]=='\t')) { for (p=line+9; *p == ' ' || *p == '\t'; p++) ; if (!*p) { err ("%s:%d: name missing after \"@ifsclear\"", fname, lnr); continue; } for (pend=p; *pend && *pend != ' ' && *pend != '\t'; pend++) ; *pend = 0; /* Ignore rest of the line. */ push_condition (p, 0, fname, lnr); continue; } else if (n == 4 && !memcmp (line, "@end", 4) && (line[4]==' '||line[4]=='\t') && !strncmp (p, "ifset", 5) && (p[5]==' '||p[5]=='\t'||!p[5])) { pop_condition (1, fname, lnr); continue; } else if (n == 4 && !memcmp (line, "@end", 4) && (line[4]==' '||line[4]=='\t') && !strncmp (p, "ifclear", 7) && (p[7]==' '||p[7]=='\t'||!p[7])) { pop_condition (0, fname, lnr); continue; } } /* Take action on ifset/ifclear. */ if (!cond_is_active) continue; /* Process commands. */ if (*line == '@') { if (skip_to_end && n == 4 && !memcmp (line, "@end", 4) && (line[4]==' '||line[4]=='\t'||!line[4])) { skip_to_end = 0; } else if (cond_in_verbatim) { got_line = 1; } else if (n == 6 && !memcmp (line, "@macro", 6)) { macroname = xstrdup (p); macrovalue = xmalloc ((macrovaluesize = 1024)); macrovalueused = 0; } else if (n == 8 && !memcmp (line, "@manpage", 8)) { free (*section_name); *section_name = NULL; finish_page (); start_page (p); in_pause = 0; } else if (n == 8 && !memcmp (line, "@mansect", 8)) { if (!thepage.name) err ("%s:%d: section outside of a man page", fname, lnr); else { free (*section_name); *section_name = ascii_strupr (xstrdup (p)); in_pause = 0; skip_sect_line = 1; } } else if (n == 9 && !memcmp (line, "@manpause", 9)) { if (!*section_name) err ("%s:%d: pausing outside of a man section", fname, lnr); else if (in_pause) err ("%s:%d: already pausing", fname, lnr); else in_pause = 1; } else if (n == 8 && !memcmp (line, "@mancont", 8)) { if (!*section_name) err ("%s:%d: continue outside of a man section", fname, lnr); else if (!in_pause) err ("%s:%d: continue while not pausing", fname, lnr); else in_pause = 0; } else if (n == 5 && !memcmp (line, "@menu", 5) && (line[5]==' '||line[5]=='\t'||!line[5])) { skip_to_end = 1; } else if (n == 8 && !memcmp (line, "@include", 8) && (line[8]==' '||line[8]=='\t'||!line[8])) { char *incname = xstrdup (p); FILE *incfp = fopen (incname, "r"); if (!incfp && opt_include && *opt_include && *p != '/') { free (incname); incname = xmalloc (strlen (opt_include) + 1 + strlen (p) + 1); strcpy (incname, opt_include); if ( incname[strlen (incname)-1] != '/' ) strcat (incname, "/"); strcat (incname, p); incfp = fopen (incname, "r"); } if (!incfp) err ("can't open include file '%s':%s", incname, strerror (errno)); else { parse_file (incname, incfp, section_name, in_pause); fclose (incfp); } free (incname); } else if (n == 4 && !memcmp (line, "@bye", 4) && (line[4]==' '||line[4]=='\t'||!line[4])) { break; } else if (!skip_to_end) got_line = 1; } else if (!skip_to_end) got_line = 1; if (got_line && cond_in_verbatim) add_content (*section_name, line, 1); else if (got_line && thepage.name && *section_name && !in_pause) add_content (*section_name, line, 0); } if (ferror (fp)) err ("%s:%d: read error: %s", fname, lnr, strerror (errno)); free (macroname); free (macrovalue); free (line); }
bool config_file_parser(const char ** config_args, GlUniversEns* env) { bool succeeded = true; const char * c_type = config_args[1]; const char * c_operation = config_args[2]; const char * c_name = config_args[30]; float c_p_x, c_p_y, c_p_z; float c_g_mass, c_g_radius; //argument -p bool c_p = ! ( strcmp(config_args[10], "") == 0 && strcmp(config_args[12], "") == 0 && strcmp(config_args[14], "") == 0 ); if ( c_p ) { sscanf(config_args[10], "%f", &c_p_x); sscanf(config_args[12], "%f", &c_p_y); sscanf(config_args[14], "%f", &c_p_z); } //arguments -r et -m bool c_g = ! ( strcmp(config_args[4], "") == 0 && strcmp(config_args[8], "") == 0 ); if ( c_g ) { sscanf(config_args[4], "%f", &c_g_mass); sscanf(config_args[7], "%f", &c_g_radius); } //commanes sur univers if ( strcmp(c_type, "univers") == 0 ) { if ( strcmp(c_operation, "set") == 0 ) { //pour l'instant on ne fait rien cout << "warning : nothing done on : 'univers set " << c_name << "'" << endl; } else if ( strcmp(c_operation, "add") == 0 ) { //adpatation des arguments : //m : méthode de calcul //r : type de de rendu //p_x : dt //p_y : nmax pour iocsv //p_z : pas encore décidé GlUnivers new_u; if ( c_g ) { GlUnivers new_u = GlUnivers((Univers::methode) (int) c_g_mass, 5, (GlUnivers::glUniversMode) (int) c_g_radius); } else { cout << "adding : univers warning : methodes (rendu & calcul) not specified"; cout << endl; cout << "adding : univers default : U_2D & PFD:" << endl; GlUnivers new_u = GlUnivers(); } if ( c_p ) { new_u.Univers::init(c_p_x); time_t rawtime; //fichier log unique : date & heure + nom de l'univers struct tm * timeinfo; time ( &rawtime ); timeinfo = localtime ( &rawtime ); stringstream logfilename; logfilename << c_name << "::" << asctime(timeinfo); string filename_ = logfilename.str(); filename_.erase(filename_.end() - 2, filename_.end()); filename_ += ".csv"; new_u.Univers::start_CSVstream(filename_, c_p_y); } else { cout << "adding : univers warning : nmax & dt not specified" << endl; cout << "adding : univers default : dt=5, nmax=-1 (no output)" << endl; } env->add_univers((string) c_name, &new_u); cout << "adding : univers : '" << c_name << "'" << endl; } else if ( strcmp(c_operation, "delete") == 0 ) { //pour l'instant on ne fait rien cout << "warning : nothing done on : 'univers delete " << c_name << "'" << endl; } else { //message d'erreur succeeded = false; } } //commandes sur astres else if ( strcmp(c_type, "astre") == 0 ) { const char * c_parent_name = config_args[33]; float c_v_x, c_v_y, c_v_z; float c_a_x, c_a_y, c_a_z; //argument -v bool c_v = ! ( strcmp(config_args[17], "") == 0 && strcmp(config_args[19], "") == 0 && strcmp(config_args[21], "") == 0 ); if ( c_v ) { sscanf(config_args[17], "%f", &c_v_x); sscanf(config_args[19], "%f", &c_v_y); sscanf(config_args[21], "%f", &c_v_z); } //argument -a bool c_a = ! ( strcmp(config_args[24], "") == 0 && strcmp(config_args[26], "") == 0 && strcmp(config_args[28], "") == 0 ); if ( c_a ) { sscanf(config_args[24], "%f", &c_a_x); sscanf(config_args[26], "%f", &c_a_y); sscanf(config_args[28], "%f", &c_a_z); } //parent_name doit être spécfier pour les opérations sur les astres if ( strlen(c_parent_name) > 0 ) { if ( strcmp(c_operation, "set") == 0 ) { if ( (c_p || c_v || c_a) && !c_g ) { GlAstre * a = env->get_astre_by_name((string) c_name, (string) c_parent_name); set_macro(a, c_p, c_p_x, c_p_y, c_p_z, c_v, c_v_x, c_v_y, c_v_z, c_a, c_a_x, c_a_y, c_a_z); cout << "updated : astre : " << c_name << " in " << c_parent_name << endl; } else { //message d'erreur cerr << "error : astre : set : mass and radius cannot be set && one of position, vitesse and acceleration must be set" << endl; succeeded = false; } } else if ( strcmp(c_operation, "add") == 0 ) { if ( c_g && c_p ) { Astre new_a = Astre ( Vector(true, c_p_x, c_p_y, c_p_z), c_g_mass, c_g_radius ); GlAstre gl_new_a = GlAstre (new_a); env->add_astre((string) c_name, (string) c_parent_name, &gl_new_a); set_macro(&gl_new_a, false, 0, 0, 0, c_v, c_v_x, c_v_y, c_v_z, c_a, c_a_x, c_a_y, c_a_z); cout << "adding : astre : '" << c_name << "' in '" << c_parent_name << "'" << endl; } else { //message d'erreur cerr << "error : astre add : mass and radius && position must be set" << endl; succeeded = false; } } else if ( strcmp(c_operation, "delete") == 0 ) { env->delete_astre((string) c_name, (string) c_parent_name); cout << "deleting : astre : '" << c_name << "' in '" << c_parent_name << "'" << endl; } else { //message d'erreur succeeded = false; } } else { //message d'erreu cerr << "error : astre " << c_name << " : no univers have been specified" << endl; succeeded = false; } } else { // message d'erreur succeeded = false; } return succeeded; }