/* * The Helium Toolkit * * Copyright (C) 1996-2000 Edouard Thiel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License; see http://www.lif-sud.univ-mrs.fr/~thiel/helium/LICENSE */ /* * gui/args.c - 04/11/1997 * * Traitement des arguments de la ligne de commande. */ #include /* PROJETS : 1) autoriser plusieurs fois le meme "-truc" --> par defaut on met dans le struct un flag "multiple is forbidden" puis on met une fct "allow_multiple". Dans ce cas, l'analyse de ligne ne renvoie pas d'erreur, mais donne la position de la premiere occurence. Une fct "next_occurence" fournit la suivante, ou "termine'" */ /* * Variables globales et exportees */ int he_argc; char **he_argv; /* * Variables statiques */ static He_argl *he_argl = NULL; static int he_argtot = 0, he_argmax = 0; /*------------------- I N T E R F A C E - P U B L I Q U E --------------------*/ /* * Declare une "option" ou une "ressource" dans la ligne de commande. * * Exemple : * HeDeclArg ("-help", NULL, NULL, 0, "print options"); * HeDeclArg ("-color", "winColor", "", 1, * "set window color"); * HeDeclArg ("-remote", NULL, " ", 2, * "call remote server"); * * Si option est NULL, c'est uniquement la ressource qui est specifiee. * Si resource est NULL, elle n'est pas recherchee dans la X database. * Si nb_param est 0, il n'y a pas de parametre. * Si help est NULL, il n'y a pas d'aide affichee pour l'option -help. * * RQ : aucun string n'est recopie'. */ void HeDeclArg (char *option, char *resource, char *param, int nb_param, char *help) { if (he_init_stat > 0) { HeError ("HeDeclArg ignored: should not be called after HeInit\n"); return; } if (option == NULL && resource == NULL) { HeError ("HeDeclArg ignored: option AND resource are NULL\n"); return; } /* Gestion liste */ if (he_argtot >= he_argmax) { he_argmax += 32; /* Certains compilos ne supportent pas de realloc (NULL, ..); */ if (he_argl == NULL) he_argl = malloc (sizeof(He_argl) * he_argmax); else he_argl = realloc (he_argl, sizeof(He_argl) * he_argmax); } if (he_argl == NULL) { HeError ("HeDeclArg: malloc error\n"); return; } he_argl[he_argtot].option = option; he_argl[he_argtot].resource = resource; he_argl[he_argtot].param = param; he_argl[he_argtot].help = help; he_argl[he_argtot].nb = nb_param; he_argl[he_argtot].pos = 0; he_argtot++; } /* * Teste la presence de l'option, sinon de la ressource. * Renvoie le parametre numero 1 de l'option (ou l'option si 0 parametre), * sinon la ressource, sinon le string par defaut (qui peut etre NULL). */ char *HeGetOption (const char *option, char *default_val) { return HeRetrieveArg (option, 1, NULL, default_val); } /* * Teste la presence de l'option, sinon de la ressource. * Renvoie le parametre numero num de l'option (ou l'option si 0 parametre), * sinon la ressource, sinon default_val si non-NULL, * sinon le string par defaut (qui peut etre NULL). */ char *HeGetOptionN (const char *option, int num, char *default_val) { return HeRetrieveArg (option, num, NULL, default_val); } /* * Teste la presence de la ressource. * Renvoie le parametre de la ressource, * sinon du string par defaut (qui peut etre NULL). * A employer lorqu'une ressource n'a pas d'option correspondante. */ char *HeGetResource (const char *resource, char *default_val) { return HeRetrieveArg (NULL, 0, resource, default_val); } /* * Affiche la liste des options */ void HePrintHelp () { int i; printf ("\n O P T I O N S\n\n"); for (i = 0; i < he_argtot; i++) { if (he_argl[i].option == NULL) continue; printf (" %s", he_argl[i].option); if (he_argl[i].param) printf (" %s", he_argl[i].param); if (he_argl[i].help) printf (" : %s", he_argl[i].help); printf ("\n"); } printf (" -- : all following args are non-options\n"); printf ("\n"); } /* * Affiche la liste des ressources X */ void HePrintRes () { int i; printf ("\n R E S O U R C E S\n\n"); for (i = 0; i < he_argtot; i++) { if (he_argl[i].resource == NULL) continue; printf (" .%s:", he_argl[i].resource); if (he_argl[i].param) printf (" %s", he_argl[i].param); if (he_argl[i].help) printf (" : %s", he_argl[i].help); printf ("\n"); } printf ("\n"); printf (" Example of resource to put in .Xdefaults\n"); printf (" ! for every program\n"); printf (" *winColor: #cccccc\n"); printf (" ! for %s class programs\n", he_res_class); printf (" %s.winColor: #e0b4b0\n", he_res_class); printf (" ! only for %s\n", he_res_name); printf (" %s.winColor: grey\n", he_res_name); printf ("\n"); } /*-------------------- F O N C T I O N S - P R I V E E S ---------------------*/ /* * Decomptage des arguments dans la ligne de commande. * Renvoie -1 erreur, sinon le nombre d'arguments reconnus, * parmi les he_argtot decrits dans la liste he_argl. */ int HeAnalyseArgs (int *argc, char ***argv) { int c, i, trouve, n = 0; /* Sauve arguments originaux dans var globales */ he_argc = *argc; he_argv = *argv; /* Cree nouveau *argv */ *argv = malloc (he_argc * sizeof(char*)); if (*argv == NULL) { HeError ("HeAnalyseArgs: malloc error\n"); return -1; } /* Copie le nom de l'executable dans (*argv)[0] */ (*argv)[0] = he_argv[0]; *argc = 1; /* Recherche des params */ for (c = 1; c < he_argc; c++) { trouve = FALSE; /* Si he_argv[c] = "--", on stop l'analyse * et on recopie tous les args restants dans *argv */ if (!strcmp("--", he_argv[c])) { for (c++; c < he_argc; c++) (*argv)[(*argc)++] = he_argv[c]; break; } /* Recherche de he_argv[c] dans la table des options */ for (i = 0; i < he_argtot; i++) if (he_argl[i].option && !strcmp(he_argl[i].option, he_argv[c])) { if (he_argl[i].pos) { HeError ("HeAnalyseArgs: arg `%s' already set\n", he_argl[i].option); return -1; } he_argl[i].pos = c; c += (he_argl[i].nb > 0) ? he_argl[i].nb : 0; if (c >= he_argc && he_argl[i].nb > 0) { HeError ("HeAnalyseArgs: arg `%s' needs %d param\n" " %s %s\n" " %s\n", he_argl[i].option, he_argl[i].nb, he_argl[i].option, (he_argl[i].param) ? he_argl[i].param : "", (he_argl[i].help) ? he_argl[i].help : "" ); return -1; } trouve = TRUE; n++; /* Si cette option a un nombre de parametres infini, alors on stop l'analyse, sans rien recopier dans *argv */ if (he_argl[i].nb == -1) return n; /* On a fini avec he_argv[c] */ break; } /* arg non reconnu, copie dans (*argv)[] */ if (!trouve) (*argv)[(*argc)++] = he_argv[c]; } return n; } /* * Teste la presence de l'option, sinon de la ressource. * Renvoie le parametre numero num de l'option (ou l'option si 0 parametre), * sinon la ressource, sinon default_val (qui peut etre NULL). */ char *HeRetrieveArg (const char *option, int num, const char *resource, char *default_val) { char *s; int i = -1; if (he_init_stat < 2) { HeError ("HeRetrieveArg: should not retrieve options" " or resource before HeInit\n"); return NULL; } if (option) { i = HeGetArgPos (option); /* Fin si option n'est pas reconnue */ if (i < 0) return NULL; /* Option est dans argv */ if (he_argl[i].pos > 0) { if (he_argl[i].nb == 0) return he_argv[he_argl[i].pos]; else return he_argv[he_argl[i].pos+num]; } if (resource == NULL) resource = he_argl[i].resource; } /* On ne cherche pas la ressource si le display X est fermé. */ if (resource && he_display) { if (i < 0) i = HeGetResPos (resource); /* Fin si resource n'est pas reconnue */ if (i < 0) return NULL; /* On renvoie la resource */ s = XGetDefault (he_display, he_res_name, resource); if (s != NULL) return s; s = XGetDefault (he_display, he_res_class, resource); if (s != NULL) return s; } /* Ni l'option ni la ressource ne sont connus */ if (i < 0) return NULL; /* Valeur par defaut */ return default_val; } /* * Retrouve une option dans he_argl. * Renvoie son indice > 0, ou -1 (erreur, option indefinie). */ int HeGetArgPos (const char *option) { int i; if (option == NULL) return -1; for (i = 0; i < he_argtot; i++) if (he_argl[i].option && !strcmp(he_argl[i].option, option)) return i; return -1; } /* * Retrouve une ressource dans he_argl. * Renvoie son indice > 0, ou -1 (erreur, ressource indefinie). */ int HeGetResPos (const char *resource) { int i; if (resource == NULL) return -1; for (i = 0; i < he_argtot; i++) if (he_argl[i].resource && !strcmp(he_argl[i].resource, resource)) return i; return -1; }